我以前从未使用过Pygame,但我决定为我的项目创建游戏‘Snake& Ladders’,这是一款棋盘游戏,通常有大约100个方格,并有供用户使用的计数器/棋子。它有一个掷骰子来控制你移动的空间,如果你落在梯子上,它会把你带到你已经在的地方前面的某个位置,如果你落在一条蛇上,它会把你带到你现在所在的地方后面的位置。它通常是由2-4个玩家玩的。
我想知道,我怎么才能用Pygame创建一个编号为10*10的网格,因为我没有使用它的经验,我做了一些研究,但仍然不完全理解。
发布于 2019-11-23 00:17:21
在考虑如何绘制10*10网格之前,您应该考虑的第一件事是如何将游戏逻辑从绘制逻辑中分离出来,以及如何表示游戏状态。
这实际上是最重要的事情之一,所以让我重复一遍:首先考虑如何表示游戏状态,然后再考虑如何绘制它。
假设我们有一个由10个瓦片组成的棋盘(为了保持这个例子简单),那么让我们从创建一个连接瓦片的地图开始:
CONNECTIONS = {
2: 4,
1: 7,
5: 3,
8: 0,
}这意味着如果玩家落在牌2上,他们就会移动到牌4。如果他们落在牌8上,他们就会回到0,以此类推。所以CONNECTIONS已经是我们游戏的重要组成部分了。
因为我们想要一个很好的棋盘来玩,让我们定义每个磁贴在屏幕上的位置。为此,我们可以使用一个简单的列表:
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模块绘制一个漂亮的游戏棋盘
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)

并在以后重用CONNECTIONS和POSITIONS (绿色是好的,红色是坏的)。
当然,如果你想要一个简单的网格而不是一个非对称板,你可以使用一个嵌套的循环或一些简单的数学来动态创建每个瓦片的位置。
但是正如你所看到的,我们已经有了游戏坐标( 1D:棋盘是线性的)和屏幕坐标( 2D: x和y)之间的某种关系,这些东西是不同的。
这意味着,如果我们使用某种数据结构来表示玩家,那么该数据结构(我们将使用一个继承pygame的Sprite的类)也应该有两个位置:一个表示玩家在棋盘上的位置,另一个表示精灵在场地上的位置。
当玩家移动时,我们改变它的棋盘位置,如果它们落在一个有连接的字段上(我们将他们的棋盘位置与CONNECTIONS中的值进行比较),我们知道玩家必须继续前进。
这里有一个我拼凑出来的例子(按任何键来滚动骰子并移动):
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()

https://stackoverflow.com/questions/58996059
复制相似问题