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为学校的项目创建一个迷宫游戏(不是生成器)。我一直在寻找一种方法来创建墙壁并让玩家(只是一个绿色的矩形)与这些墙壁碰撞,以及如何为此制作几个级别。我将如何制作关卡,如何创建墙壁,以及如何检测玩家与墙壁之间的碰撞?
答案 0 :(得分:9)
这是我知道制作墙壁的两种最简单的方法。两种方式都可以使用图形结构和图形搜索算法,因此您可以实现"路径查找"将来如果你愿意的话。这一切都是我的头脑,所以我道歉,如果有任何不清楚,但我也提供了相关文件的链接,如果你感到困惑,你可以检查。
这可能是生成地图的最简单的方法,因为它可以简单地通过制作一个ASCII字符数组并在Python中处理它们来制作正方形" wall"对象。
以此网格为例:
###########
# #
# ###### #
#S #F #
###########
' S'表示起点和' F'表示结束点。是的,这可能是最容易的"迷宫"在世界上解决但它只是一个例子。想象一下,我可怕的ASCII数组中的每个字符代表一个大小为N x N的方形图块。这些空格代表图块可以行走的字符,而哈希字符代表墙壁#'。
在这种类型的游戏中,墙壁本身就是游戏实体。特别是在Pygame的上下文中,它们继承自Sprite class。 Sprite类是特殊类,它们代表游戏中的实体或基本上现有的对象。它们非常特别,因为它们可以代表障碍物,墙壁,地板,天花板,玩家,敌人等等。基本上,游戏中的每个对象都可以从Sprite类继承。
那么是什么让Sprite类如此特别?好吧,你提到你在理解墙碰撞时遇到了概念上的困难。 Pygame中的每个精灵都有自己的Rect attribute。 rect属性基本上只是一个不可见的矩形,用于确定碰撞检测和绘制精灵等内容。根据定义,在纯粹的基于图块的地图中,"碰撞"实体之间定义如下:如果两个实体的矩形相互重叠,则它们会发生碰撞。然后有一个名为pygame.sprite.groupcollide()
的Sprite类的方法。上面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.
您可以在游戏循环的每次迭代中直接调用此函数在更新玩家的移动后 之前您使用播放器绘制所有实体& #39; s组作为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.**
我不打算为你实现这个功能,因为我觉得把挑战留给你更好。 :)但是我会警告你,逻辑并不那么简单。
顺便提一下,这种类型的迷宫/地图结构被用于许多流行的游戏,包括塞尔达传说,吃豆子,炸弹人,俄罗斯方块等等。我不可能将它们全部命名,但你明白了。这是一种经过验证的方法,因为它可以与游戏设计无缝集成。但是不要接受我的话,有an entire website which explains why tile-based games are so powerful.
请注意,此方法实施起来要困难得多。纯粹Graph based.图中的每个空间都是玩家可以遍历的节点。决定是否允许实体在两个节点之间移动(换句话说......基于 restriction 原则的冲突)的原因是这些节点之间是否存在 edge 底层无向(或定向,如果您愿意)图中的两个节点。
我并没有真正详细解释这一点,因为在一个答案中难以涵盖。如果你想使用这种方法,你只需要做自己的研究,但要记住,由于Pygame实际上并没有为这个策略提供太多支持,所以要困难得多。如果您真的对此感兴趣,最好的起点可能是Google。
那就是它!尝试使用我提供的信息,如果您遇到任何问题,可以在此处或The GameDev StackExchange提出其他问题。将来当您在SO上提出问题时,请尝试确保它是特定的编程问题,否则您很可能会收到大量的投票。