首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用PyGame创建用于蛇和梯子的10x10电路板?

如何使用PyGame创建用于蛇和梯子的10x10电路板?
EN

Stack Overflow用户
提问于 2019-11-22 22:15:38
回答 1查看 1.8K关注 0票数 0

我以前从未使用过Pygame,但我决定为我的项目创建游戏‘Snake& Ladders’,这是一款棋盘游戏,通常有大约100个方格,并有供用户使用的计数器/棋子。它有一个掷骰子来控制你移动的空间,如果你落在梯子上,它会把你带到你已经在的地方前面的某个位置,如果你落在一条蛇上,它会把你带到你现在所在的地方后面的位置。它通常是由2-4个玩家玩的。

我想知道,我怎么才能用Pygame创建一个编号为10*10的网格,因为我没有使用它的经验,我做了一些研究,但仍然不完全理解。

EN

回答 1

Stack Overflow用户

发布于 2019-11-23 00:17:21

在考虑如何绘制10*10网格之前,您应该考虑的第一件事是如何将游戏逻辑从绘制逻辑中分离出来,以及如何表示游戏状态。

这实际上是最重要的事情之一,所以让我重复一遍:首先考虑如何表示游戏状态,然后再考虑如何绘制它。

假设我们有一个由10个瓦片组成的棋盘(为了保持这个例子简单),那么让我们从创建一个连接瓦片的地图开始:

代码语言:javascript
复制
CONNECTIONS = {
    2: 4,
    1: 7,
    5: 3,
    8: 0,
}

这意味着如果玩家落在牌2上,他们就会移动到牌4。如果他们落在牌8上,他们就会回到0,以此类推。所以CONNECTIONS已经是我们游戏的重要组成部分了。

因为我们想要一个很好的棋盘来玩,让我们定义每个磁贴在屏幕上的位置。为此,我们可以使用一个简单的列表:

代码语言:javascript
复制
POSITIONS = [
    (93, 394),
    (244, 338),
    (368, 391),
    (457, 317),
    (579, 348),
    (572, 181),
    (458, 108),
    (379, 203),
    (231, 115),
    (89, 197)
]

这意味着tile 0位于屏幕位置(93, 394)等位置,并且已经允许我们使用pygame的draw模块绘制一个漂亮的游戏棋盘

代码语言:javascript
复制
screen = pygame.display.set_mode((width, height))
...
# Let's create a board
board = screen.copy()
board.fill((40, 40, 40))

# We connect all dots with lines
prev = None
for pos in POSITIONS:
    if prev:
        pygame.draw.line(board, (0,0,0), prev, pos, 4)
    prev = pos

# Then we draw the good and bad connections
for pos in CONNECTIONS:
    target = CONNECTIONS[pos]
    pygame.draw.line(board, (0,200,0) if pos < target else (200,0,0), POSITIONS[pos], POSITIONS[target], 4)

# Last we create all fields
for pos in POSITIONS:
    pygame.draw.circle(board, (0,0,0), pos, 40)
    pygame.draw.circle(board, (200,200,200), pos, 36)

并在以后重用CONNECTIONSPOSITIONS (绿色是好的,红色是坏的)。

当然,如果你想要一个简单的网格而不是一个非对称板,你可以使用一个嵌套的循环或一些简单的数学来动态创建每个瓦片的位置。

但是正如你所看到的,我们已经有了游戏坐标( 1D:棋盘是线性的)和屏幕坐标( 2D: x和y)之间的某种关系,这些东西是不同的。

这意味着,如果我们使用某种数据结构来表示玩家,那么该数据结构(我们将使用一个继承pygame的Sprite的类)也应该有两个位置:一个表示玩家在棋盘上的位置,另一个表示精灵在场地上的位置。

当玩家移动时,我们改变它的棋盘位置,如果它们落在一个有连接的字段上(我们将他们的棋盘位置与CONNECTIONS中的值进行比较),我们知道玩家必须继续前进。

这里有一个我拼凑出来的例子(按任何键来滚动骰子并移动):

代码语言:javascript
复制
import pygame
import random

CONNECTIONS = {
    2: 4,
    1: 7,
    5: 3,
    8: 0,
}

POSITIONS = [
    (93, 394),
    (244, 338),
    (368, 391),
    (457, 317),
    (579, 348),
    (572, 181),
    (458, 108),
    (379, 203),
    (231, 115),
    (89, 197)
]

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((30, 50))
        self.image.fill((200,100,0))
        self.rect = self.image.get_rect()

        # The player has a state.
        # Either it is WAITING, so it reacts to the move() command
        # Or it is already MOVING, and pressing a key does nothing
        self.state = 'WAITING'

        # It's important to have a distinction between the logical position
        # on the board, and the actual position of the sprite on the screen
        # We start on board position 0
        self.board_pos = 0

        # We set the current position of the sprite to the position
        # of the tile we're standing on
        self.rect.center = POSITIONS[self.board_pos]

        # We use an additional vector to store the position of the
        # sprite so we can let pygame handle all the vector math
        self.pos = pygame.Vector2(self.rect.center)

    def move(self):
        if self.state == 'WAITING':
            # If we are waiting and a key is pressed, we start moving
            eyes = random.randint(1, 6)
            print(f"rolled a {eyes}")
            # Keep track of how many tiles we move forward
            self.eyes = eyes
            self.state = 'MOVING'
            # Since we move forward, increase our board position
            self.board_pos += 1
            # We want a smooth movement, so we store the position
            # of the next tile in a vector, too
            self.target = pygame.Vector2(POSITIONS[self.board_pos])

    def update(self, dt, events):
        if self.state == 'MOVING':
            # When we're moving, create a movement vector 
            # so we know in which direction we have to move
            movement = self.target - self.pos
            length = movement.length()

            if length < 5:
                # We arrived at out target tile

                # If we still have some tiles to go, decrease the number
                # since we arrived at one
                if self.eyes > 0:
                    self.eyes -= 1

                self.pos = self.target
                if self.eyes == 0:
                    # We moved all tiles, so let's see if there's a 
                    # connection to another tile
                    con = CONNECTIONS.get(self.board_pos, None)
                    if con:
                        # If there is, we have a new target to move to 
                        self.board_pos = con
                        self.target = pygame.Vector2(POSITIONS[self.board_pos])
                    else:
                        # If not, our turn is over
                        self.state = 'WAITING'
                else:
                    # We have still some tiles to go
                    self.board_pos += 1
                    self.target = pygame.Vector2(POSITIONS[self.board_pos])
            else:
                # Just keep moving
                movement.normalize_ip()
                # Some math to keep the movement smooth and nice
                self.pos += movement * dt/10 * max(length/40., 0.7)

        # Pygame uses the rect attribute to position the sprite
        # so let's update it with the position of our vector
        self.rect.center = int(self.pos.x), int(self.pos.y)

def main():
    width, height = 640, 480
    pygame.init()
    screen = pygame.display.set_mode((width, height))
    clock = pygame.time.Clock()
    player = Player()
    sprites = pygame.sprite.Group(player)

    # Let's create a board
    board = screen.copy()
    board.fill((40, 40, 40))

    # We connect all dots with lines
    prev = None
    for pos in POSITIONS:
        if prev:
            pygame.draw.line(board, (0,0,0), prev, pos, 4)
        prev = pos

    # Then we draw the good and bad connections
    for pos in CONNECTIONS:
        target = CONNECTIONS[pos]
        pygame.draw.line(board, (0,200,0) if pos < target else (200,0,0), POSITIONS[pos], POSITIONS[target], 4)

    # Last we create all fields
    for pos in POSITIONS:
        pygame.draw.circle(board, (0,0,0), pos, 40)
        pygame.draw.circle(board, (200,200,200), pos, 36)

    dt = 0
    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
            if e.type == pygame.KEYDOWN:
                player.move()

        screen.blit(board, (0,0))
        sprites.update(dt, events)
        sprites.draw(screen)
        pygame.display.flip()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58996059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档