示例#1
0
    def initComponents(self):
        textFont = Fonts.getFont(Fonts.Courier, 30)
        window = self.window
        height, width = self.app.height, self.app.width
        title = Label(window, width/2, 0.5*height/3,
                            font=textFont, text="Load World")

        self.worldButtons = []
        y = [1.8, 2.5, 3.2]
        for i in range(3):
            button = Button(window, width/2, y[i]*height/4,
                            font=textFont, text="New World",
                            padding=10, fillColor=Colors.WHITE)
            button.setOnClickListener(self.loadWorld, i)
            self.worldButtons.append(button)

        self.deleteButtons = []
        for i in range(3):
            button = self.worldButtons[i]
            imgButton = ImageButton(window, width/2 + button.width, y[i]*height/4,
                                 Assets.assets["delete"], padding=10, borderWidth=0)
            imgButton.setOnClickListener(self.deleteWorld, i)
            self.deleteButtons.append(imgButton)

        self.addComponents(self.worldButtons)
        self.addComponents(self.deleteButtons)
        self.addComponent(title)
示例#2
0
    def initComponents(self):
        textFont = Fonts.getFont(Fonts.Courier, 30)
        window = self.window
        height, width = self.app.height, self.app.width
        title = Label(window,
                      width / 2,
                      1 * height / 3,
                      font=textFont,
                      text="Craft112")

        startGame = Button(window,
                           width / 2,
                           1.5 * height / 3,
                           font=textFont,
                           text="Start Game",
                           padding=10)
        startGame.setOnClickListener(lambda: self.app.changeScene("load_game"))

        quitGame = Button(window,
                          width / 2,
                          2 * height / 3,
                          font=textFont,
                          text="Quit Game",
                          padding=10)
        quitGame.setOnClickListener(self.app.quit)

        self.addComponents([title, startGame, quitGame])
示例#3
0
class GameScene(Scene):
    def __init__(self, app):
        super().__init__(app)
        self.initNew()
        self.initGame()
        self.initComponents()
        self.initOverlay()

        self.isPaused = False

    def initNew(self):
        self.initWorld()
        self.initPlayer()

    def initWorld(self):
        self.world = World()
        self.world.generateWorld()

    def initGame(self):
        self.player = None
        self.previewWidth = 10
        Constants.blockSize = self.app.width / (self.previewWidth * 2 + 1)
        self.previewHeight = math.ceil(self.app.height / Constants.blockSize)

        self.offset = 5  # load outside canvas to hide buffering
        self.renderOffset = 7.6
        self.holdPos = False
        self.holdPosTickThresh = 30
        self.holdPosTick = 0

        self.difficulty = 2
        self.difficultyLabels = ["Peaceful", "Easy", "Normal", "Hard"]

    def initPlayer(self):
        self.player = Player(self.world)
        sword = ItemStack(Material.SWORD, 1)
        fire_sword = ItemStack(Material.FIRE_SWORD, 1)
        ice_sword = ItemStack(Material.ICE_SWORD, 1)

        pickaxe = ItemStack(Material.PICKAXE, 1)
        explosive_pickaxe = ItemStack(Material.EXPLOSIVE_PICKAXE, 1)

        inventory = self.player.getInventory()

        inventory.addItem(sword)
        inventory.addItem(fire_sword)
        inventory.addItem(ice_sword)

        inventory.addItem(pickaxe)
        inventory.addItem(explosive_pickaxe)

        y = self.world.getHighestBlock(0)
        self.player.position = Vector2D(0, y)
        self.world.addEntity(self.player)

    def initComponents(self):
        textFont = Fonts.getFont(Fonts.Roboto_Mono, 30)
        self.label = Label(self.window,
                           self.app.width / 2,
                           5 * self.app.height / 6,
                           text="",
                           font=textFont)
        self.label.x = self.app.width / 2
        self.label.y = 6 * self.app.height / 7

        self.addComponent(self.label)

    def initOverlay(self):
        textFont = Fonts.getFont(Fonts.Courier, 30)
        window = self.window
        width, height = self.app.width, self.app.height

        unit = height / 4

        self.volumeButton = ImageButton(window,
                                        2 * width / 3,
                                        1.6 * unit,
                                        Assets.assets["volume_on"],
                                        fillColor=Colors.WHITE)
        self.volumeButton.setOnClickListener(self.toggleVolume)

        self.respawnButton = Button(window,
                                    width / 2,
                                    2 * unit,
                                    font=textFont,
                                    text="Respawn",
                                    fillColor=Colors.WHITE,
                                    padding=10)
        self.respawnButton.setOnClickListener(self.respawnPlayer)

        self.resumeButton = Button(window,
                                   width / 2,
                                   2 * unit,
                                   font=textFont,
                                   text="Resume Game",
                                   fillColor=Colors.WHITE,
                                   padding=10)
        self.resumeButton.setOnClickListener(self.togglePause)

        self.difficultyButton = Button(window,
                                       width / 2,
                                       2.5 * unit,
                                       font=textFont,
                                       text="Difficulty: Normal",
                                       fillColor=Colors.WHITE,
                                       padding=10)
        self.difficultyButton.setOnClickListener(self.cycleDifficulty)

        self.quitButton = Button(window,
                                 width / 2,
                                 3 * unit,
                                 font=textFont,
                                 text="Main Menu",
                                 fillColor=Colors.WHITE,
                                 padding=10)
        self.quitButton.setOnClickListener(self.quit)

        self.overlayComponents = [
            self.resumeButton, self.quitButton, self.respawnButton,
            self.volumeButton, self.difficultyButton
        ]

        for component in self.overlayComponents:
            component.setEnabled(False)

        self.addComponents(self.overlayComponents)

    def drawComponents(self):
        self.drawBackground()
        self.drawTerrain()
        self.drawEntities()
        self.drawInventory()
        self.drawOverlay()

        super().drawComponents()

    def drawBackground(self):
        window = self.window
        player = self.player
        bg = Assets.assets["game_background"]
        bgSize = bg.get_size()
        windowSize = window.get_size()
        x = windowSize[0] - bgSize[0] / 2 - player.position[0]
        y = windowSize[1] - bgSize[1] / 2 + player.position[1]
        window.blit(bg, (x, y))

    def drawTerrain(self):
        world = self.world
        height, width = self.previewHeight, self.previewWidth
        player = self.player
        px, py = player.position
        offset = self.offset
        renderOffset = self.renderOffset

        size = Constants.blockSize
        for y in range(-height - offset, height + offset):
            for x in range(-width - offset, width + offset):
                bx = px + x
                by = py - y
                block = world.getBlock((bx, by))

                renderX = (x + width) * size
                renderY = (y + height - renderOffset) * size
                self.drawBlock(block, (renderX, renderY))

    def drawBlock(self, block, position):
        window = self.window
        texture = Assets.assets["textures"][block.getType().getId()][0]

        x, y = position
        size = Constants.blockSize
        blockRect = pygame.Rect(0, 0, size, size)
        blockRect.center = (x + size / 2, y + size / 2)

        window.blit(texture, blockRect)

    def drawEntities(self):
        window = self.window
        world = self.world
        px, py = self.player.position
        cx, cy = self.app.width / 2, self.app.height / 2

        for entity in world.entities:
            x, y = entity.position
            rx = cx + (x - px) * Constants.blockSize
            ry = cy + (-y + py) * Constants.blockSize
            if not isinstance(entity, Player):
                ry += self.renderOffset
            entity.draw(window, rx, ry)

    def drawInventory(self):
        window = self.window
        inventory = self.player.getInventory()
        width = inventory.getDimensions()[0]

        cellSize = 40
        offset = 10
        for i in range(width):
            rect = pygame.Rect(i * cellSize + offset, offset, cellSize,
                               cellSize)
            borderWidth = 1
            if i == self.player.equipIndex:
                borderWidth = 3
            pygame.draw.rect(self.window, Colors.BLACK, rect, borderWidth)

            item = inventory[0][i]
            if item.getType() != Material.AIR:
                id = item.getType().getId()
                texture = Assets.assets["textures"][id]
                if item.getType() in Tools.tools:
                    texture = texture[0]
                else:
                    texture = texture[1]
                tWidth, tHeight = texture.get_size()
                tRect = pygame.Rect(0, 0, tWidth, tHeight)
                tRect.center = rect.center
                window.blit(texture, tRect)

                amount = item.getAmount()
                self.drawItemCount(amount, tRect)

    def drawItemCount(self, amount, rect):
        font = Fonts.getFont(Fonts.Courier, 20)
        if amount > 1:
            window = self.window
            x, y = rect.bottomright
            countLabel = Label(window,
                               x,
                               y,
                               str(amount),
                               font,
                               color=Colors.BLACK)
            countLabel.draw()

    def drawOverlay(self):
        if Constants.FILTER is None:
            Constants.FILTER = pygame.Surface(
                (self.app.width, self.app.height))
            Constants.FILTER.set_alpha(100)
            Constants.FILTER.fill((255, 255, 255))

        for component in self.overlayComponents:
            enabled = not self.player.isAlive or self.isPaused
            component.setEnabled(enabled)

        if not self.player.isAlive:
            self.window.blit(Constants.FILTER, (0, 0))
            self.resumeButton.setEnabled(False)
        elif self.isPaused:
            self.window.blit(Constants.FILTER, (0, 0))
            self.respawnButton.setEnabled(False)

    def onKeyPress(self, keys, mods):
        super().onKeyPress(keys, mods)
        if self.isPaused: return
        player = self.player

        if keys[pygame.K_a]:
            player.move(-1, 0, walk=True)
        elif keys[pygame.K_d]:
            player.move(1, 0, walk=True)
        else:
            if not self.holdPos:
                player.faceDirection(0, False)
        player.update()

    def onKeyDown(self, key):
        if key == pygame.K_ESCAPE and self.player.isAlive:
            self.togglePause()

        if self.isPaused: return
        player = self.player
        if key == pygame.K_c:
            self.world.rngSpawnEntity(self.player, spawn=True)
        else:
            for i in range(9):
                if key == pygame.K_1 + i:
                    player.equipIndex = i
                    break
        if not player.isJumping and key == pygame.K_SPACE:
            player.jump()
        player.update()

    def onMouseClick(self, mousePos):
        super().onMouseClick(mousePos)
        if self.isPaused: return
        item = self.player.getEquippedItem()

        if item.getType() in Tools.tools:
            self.breakBlock(mousePos)
        elif item.getType() in Weapons.weapons:
            self.attack(mousePos, item)

    def onMouseRightClick(self, mousePos):
        if self.isPaused: return
        player = self.player
        type = player.getEquippedItem().getType()
        if (type not in Tools.tools and type not in Weapons.weapons
                and type != Material.AIR):
            _, bx, by = self.getBlockFromMousePos(mousePos)
            world = self.world
            item = player.getEquippedItem()
            world.setBlock(item.getType(), (bx, by))
            item.setAmount(item.getAmount() - 1)
            if item.getAmount() == 0:
                item.material = Material.AIR
                item.amount = 1

    def onMouseScroll(self, scroll):
        player = self.player
        inventory = player.getInventory()
        player.equipIndex = (player.equipIndex - scroll) % (inventory.width)

        self.label.setText(player.getEquippedItem().getType().getName())

    def onTick(self):
        if self.isPaused: return
        self.world.tick()
        if self.holdPos:
            self.holdPosTick += 1
            if self.holdPosTick == self.holdPosTickThresh:
                self.holdPosTick = 0
                self.holdPos = False
        if not self.player.isAlive:
            self.isPaused = True

    def onLoad(self):
        if self.isPaused:
            self.togglePause()
        self.onMouseScroll(0)
        self.difficulty = self.world.difficulty

    def getBlockFromMousePos(self, mousePos):
        rx, ry = mousePos
        px, py = self.player.position
        size = Constants.blockSize
        height, width = self.previewHeight, self.previewWidth
        offset = 0.5

        x = rx / size - width - offset
        y = ry / size - height + self.renderOffset - offset

        bx = px + x
        by = py - y
        block = self.world.getBlock((bx, by))
        return block, bx, by

    def breakBlock(self, mousePos):
        block, bx, by = self.getBlockFromMousePos(mousePos)
        if block.getType() != Material.AIR:
            item = self.player.getEquippedItem()
            radius = Tools.tools[item.getType()]
            self.destroyBlock((bx, by))
            for dx in range(radius):
                for dy in range(radius):
                    self.destroyBlock((bx + dx, by + dy))

    def destroyBlock(self, coordinate):
        block = self.world.getBlock(coordinate)
        if block.getType() != Material.AIR:
            self.player.getInventory().addItem(ItemStack(block.getType(), 1))
            self.world.setBlock(Material.AIR, coordinate)

    def attack(self, mousePos, item):
        mx = mousePos[0]
        cx = self.app.width / 2
        player = self.player
        direction = 1 if mx > cx else -1

        dead = []
        self.player.faceDirection(direction, False)
        self.holdPos = True

        weapon = Weapons.weapons[item.getType()]
        damage = weapon.damage
        reach = weapon.reach

        targets = []

        for entity in self.world.entities:
            if isinstance(entity, Enemy):
                pPos = player.position
                ePos = entity.position

                px, ex = pPos[0], ePos[0]

                relativeDelta = 1 if ex > px else -1
                distance = pPos.distance(ePos)
                if relativeDelta == direction and distance <= reach:
                    knockback = True
                    status = 0
                    if weapon.getType() == Material.ICE_SWORD:
                        knockback = False
                        status = 1
                    elif weapon.getType() == Material.FIRE_SWORD:
                        status = 2
                    targets.append(
                        (entity, damage, relativeDelta, knockback, status))

        for entity, damage, relativeDelta, knockback, status in targets:
            entity.damage(damage, relativeDelta, knockback)
            if status == 1:
                entity.freeze()
            elif status == 2:
                entity.burn()

    def togglePause(self):
        self.isPaused = not self.isPaused
        self.difficulty = self.world.difficulty

    def toggleVolume(self):
        self.app.volumeOn = not self.app.volumeOn
        if self.app.volumeOn:
            self.volumeButton.setImage(Assets.assets["volume_on"])
            self.app.musicChannel.set_volume(1)
        else:
            self.volumeButton.setImage(Assets.assets["volume_off"])
            self.app.musicChannel.set_volume(0)

    def cycleDifficulty(self):
        self.difficulty = (self.difficulty + 1) % 4
        self.world.setDifficulty(self.difficulty)
        self.difficultyButton.setText(
            f"Difficulty: {self.difficultyLabels[self.difficulty]}")

    def respawnPlayer(self):
        self.player.respawn()
        self.isPaused = False

    def quit(self):
        Utility.save(self.world)
        pygame.event.wait()
        self.app.changeScene("main")