1
import pygame, sys
from pygame.locals import *

pygame.init()

windowwidth = 600
windowheight = 800
WALLWIDTH = 30
WALLHEIGHT = 30
PLAYERWIDTH = 20
PLAYERHEIGHT = 20


BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
LIMEGREEN = (50, 205, 50)

running = True
while running == True:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        if event.type == KEYDOWN:
            if (event.key == K_UP or event.key == K_w):
            elif (event.key == K_DOWN or event.key == K_s):
            elif (event.key == K_LEFT or event.key == K_a):
            elif (event.key == K_RIGHT or event.key == K_d):

thescreen = pygame.display.set_mode((windowwidth, windowheight))
pygame.display.set_caption('Maze Game')
mainclock = pygame.time.Clock()

player1 = pygame.draw.rect(thescreen, LIMEGREEN, (50, 50, PLAYERWIDTH, PLAYERHEIGHT))

我正在尝试使用 Python/Pygame 为学校的一个项目创建一个迷宫游戏(不是生成器)。我一直在寻找一种方法来创建墙壁并使玩家(只是一个绿色矩形)与这些墙壁发生碰撞,以及如何为此制作多个关卡。我将如何制作关卡,如何创建墙壁,以及如何检测玩家和墙壁之间的碰撞?

4

1 回答 1

10

这是我知道的两种最简单的砌墙方法。这两种方式都适用于图结构和图搜索算法,因此如果您愿意,您可以在未来实现“路径查找”。这一切都在我的脑海中,所以如果有任何不清楚的地方,我深表歉意,但我还提供了相关文档的链接,如果您感到困惑,您可以查看这些链接。

方法 1:基于瓷砖的迷宫

这可能是生成地图的最简单方法,因为它可以通过简单地通过创建一个 ASCII 字符数组并在 Python 中处理它们来制作方形“墙”对象来完成。

以这个网格为例:

###########
#         #
#  ###### #
#S #F     #
###########

“S”表示起点,“F”表示终点。是的,这可能是世界上最容易解决的“迷宫”,但这只是一个例子。想象一下,我可怕的 ASCII 数组中的每个字符都代表一个大小为 N x N 的正方形瓷砖。空格代表瓷砖可以在上面行走的字符,而哈希字符代表墙壁“#”。

在这种类型的游戏中,墙本身就是游戏实体。特别是在 Pygame 的上下文中,它们继承自Sprite 类。Sprite 类是表示实体的特殊类,或者基本上是游戏中现有的对象。它们非常特别,因为它们可以代表障碍物、墙壁、地板、天花板、玩家、敌人,应有尽有。基本上游戏中的每个对象都可以从 Sprite 类继承。

那么是什么让 Sprite 类如此特别呢?首先,你提到你在理解墙壁碰撞时遇到了概念上的困难。Pygame 中的每个精灵都有自己的Rect 属性。rect 属性基本上只是一个不可见的矩形,用于确定诸如碰撞检测和绘制精灵之类的事情。根据定义,在纯平铺地图中,实体之间的“碰撞”定义如下:如果两个实体的矩形相互重叠,则它们发生碰撞。然后是 Sprite 类的一个方法,叫做pygame.sprite.groupcollide(). 上面 ASCII 地图中的每面墙都有一个宽度、高度和位置,由它们在数组中的位置决定。因此,每个主题标签字符直接代表一个矩形,该矩形也是一个正方形,并具有一个正方形的“表面”图像。

让你的玩家继承 sprite 类并将他放在一个 sprite 组中,即“玩家组”。让你的墙实体从精灵类继承并将它们放在另一个精灵组中,称之为“障碍组”或类似的东西。然后,您所要做的就是pygame.sprite.groupcollide()在游戏循环的每一帧中调用并使用它返回的字典来判断玩家是否与任何精灵发生碰撞。如果其中有任何不清楚,我已经提供了文档的链接。阅读 Pygame 文档可能比我的回答更能帮助您理解这一点。

所以无论如何你最终得到的是一本字典。我将从文档中直接引用来解释我的观点:

groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
This will find collisions between all the Sprites in two groups. Collision is
determined by comparing the Sprite.rect attribute of each Sprite or by using the 
collided function if it is not None.

Every Sprite inside group1 is added to the return dictionary. The value 
for each item is the list of Sprites in group2 that intersect.

在更新玩家的运动之后,在绘制所有实体之前,您将在游戏循环的每次迭代中直接调用此函数,使用玩家的组作为group1参数,障碍组作为group2参数。然后你会得到一个如下形式的字典:

{player_in_group1: [<list of obstacles from group2 that collide with player>] }

那么,您如何处理该列表?好吧,它建议您定义自己的本地函数(如果您愿意,也可以将其设为播放器类的方法)来处理此问题。这是我非常高级的伪代码实现,它根本不接近实际代码:

def handle_collisions(sprite_dict):
    '''given sprite dict, moves all entities in group1 out of group2's
       rectangle area'''
    for p in sprite_dict:
        for o in sprite_dict[p]:
            # move p in such a way that its rectangle is no longer overlapping
            # with the rectangle of o with the additional constraint that p must
            # be moved **as minimally as possible.**

我不会为你实现这个功能,因为我觉得把挑战留给你会更好。:) 但是,我会警告您,逻辑并不是那么简单。

顺便说一句,这种类型的迷宫/地图结构用于许多流行的游戏,包括《塞尔达传说》、《吃豆人》、《炸弹人》、《俄罗斯方块》等。我不可能全部说出它们的名字,但你明白了。这是一种行之有效的方法,因为它将自身与游戏设计无缝集成。但不要相信我的话,有一个完整的网站可以解释为什么基于图块的游戏如此强大。

方法2:基于顶点边缘的迷宫

请注意,这种方法实施起来要困难得多。它纯粹是基于图形的。图中的每个空间都是玩家可以遍历的节点。决定一个实体是否被允许在两个节点之间移动(换句话说......基于限制原则的碰撞)是在底层无向(或有向,如果你愿意)中这两个节点之间是否存在图形。

我真的不打算详细解释这一点,因为它很难在一个答案中涵盖。如果您想使用这种方法,您只需要自己进行研究,但请记住,这要困难得多,因为 Pygame 实际上并不支持您使用这种策略。如果您真的对此感兴趣,最好的起点可能是Google


就是这样!尝试使用我提供给您的信息,如果您对此有任何疑问,可以在此处或在GameDev StackExchange上提出另一个问题。将来,当您提出关于 SO 的问题时,请尝试确保这是一个特定的编程问题,否则您很可能会得到很多反对意见。

于 2013-09-25T21:55:52.963 回答