gpt4 book ai didi

python - 将碰撞检测添加到 pygame 中的平台

转载 作者:行者123 更新时间:2023-11-28 20:23:46 25 4
gpt4 key购买 nike

我正在开发一款小型平台游戏,您可以在其中放置方 block 来打造关卡,然后进行游戏。

我有重力、跳跃和左右移动..但我不确定如何让玩家在左右移动时与墙壁发生碰撞。

我希望它的工作方式是这样的-

如果键[K_LEFT]:

如果左边没有挡住:

向左移动

我将如何去做(相对于这个来源):

import pygame,random
from pygame.locals import *
import itertools
pygame.init()
screen=pygame.display.set_mode((640,480))
class Block(object):
sprite = pygame.image.load("texture\\dirt.png").convert_alpha()
def __init__(self, x, y):
self.rect = self.sprite.get_rect(centery=y, centerx=x)

class Player(object):
sprite = pygame.image.load("texture\\playr.png").convert()
sprite.set_colorkey((0,255,0))
def __init__(self, x, y):
self.rect = self.sprite.get_rect(centery=y, centerx=x)

blocklist = []
player = []
colliding = False

while True:
screen.fill((25,30,90))
mse = pygame.mouse.get_pos()
key=pygame.key.get_pressed()

if key[K_LEFT]:
p.rect.left-=1
if key[K_RIGHT]:
p.rect.left+=1
if key[K_UP]:
p.rect.top-=10

for event in pygame.event.get():
if event.type == QUIT: exit()

if key[K_LSHIFT]:
if event.type==MOUSEMOTION:
if not any(block.rect.collidepoint(mse) for block in blocklist):
x=(int(mse[0]) / 32)*32
y=(int(mse[1]) / 32)*32
blocklist.append(Block(x+16,y+16))
else:
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
to_remove = [b for b in blocklist if b.rect.collidepoint(mse)]
for b in to_remove:
blocklist.remove(b)

if not to_remove:
x=(int(mse[0]) / 32)*32
y=(int(mse[1]) / 32)*32
blocklist.append(Block(x+16,y+16))

elif event.button == 3:
x=(int(mse[0]) / 32)*32
y=(int(mse[1]) / 32)*32
player=[]
player.append(Player(x+16,y+16))

for b in blocklist:
screen.blit(b.sprite, b.rect)
for p in player:
if any(p.rect.colliderect(block) for block in blocklist):
#collide
pass
else:
p.rect.top += 1
screen.blit(p.sprite, p.rect)
pygame.display.flip()

最佳答案

一个常见的方法是将水平和垂直碰撞处理分成两个独立的步骤。

如果您这样做并跟踪玩家的速度,就很容易知道碰撞发生在哪一侧。

首先,让我们给玩家一些属性来跟踪他的速度:

class Player(object):
...
def __init__(self, x, y):
self.rect = self.sprite.get_rect(centery=y, centerx=x)
# indicates that we are standing on the ground
# and thus are "allowed" to jump
self.on_ground = True
self.xvel = 0
self.yvel = 0
self.jump_speed = 10
self.move_speed = 8

现在我们需要一种方法来实际检查碰撞。如前所述,为了让事情变得简单,我们使用我们的 xvelyvel 来知道我们是否与左侧或右侧等发生碰撞。这进入了 Player 类:

def collide(self, xvel, yvel, blocks):
# all blocks that we collide with
for block in [blocks[i] for i in self.rect.collidelistall(blocks)]:

# if xvel is > 0, we know our right side bumped
# into the left side of a block etc.
if xvel > 0: self.rect.right = block.rect.left
if xvel < 0: self.rect.left = block.rect.right

# if yvel > 0, we are falling, so if a collision happpens
# we know we hit the ground (remember, we seperated checking for
# horizontal and vertical collision, so if yvel != 0, xvel is 0)
if yvel > 0:
self.rect.bottom = block.rect.top
self.on_ground = True
self.yvel = 0
# if yvel < 0 and a collision occurs, we bumped our head
# on a block above us
if yvel < 0: self.rect.top = block.rect.bottom

接下来,我们将移动处理移至 Player 类。因此,让我们创建一个跟踪输入的对象。在这里,我使用 namedtuple ,因为为什么不呢。

from collections import namedtuple
...
max_gravity = 100
Move = namedtuple('Move', ['up', 'left', 'right'])
while True:
screen.fill((25,30,90))
mse = pygame.mouse.get_pos()
key = pygame.key.get_pressed()

for event in pygame.event.get():
...

move = Move(key[K_UP], key[K_LEFT], key[K_RIGHT])
for p in player:
p.update(move, blocklist)
screen.blit(p.sprite, p.rect)

我们将blocklist 传递给Playerupdate 方法,这样我们就可以检查碰撞。使用 move 对象,我们现在知道玩家应该移动到哪里,所以让我们实现 Player.update:

def update(self, move, blocks):

# check if we can jump
if move.up and self.on_ground:
self.yvel -= self.jump_speed

# simple left/right movement
if move.left: self.xvel = -self.move_speed
if move.right: self.xvel = self.move_speed

# if in the air, fall down
if not self.on_ground:
self.yvel += 0.3
# but not too fast
if self.yvel > max_gravity: self.yvel = max_gravity

# if no left/right movement, x speed is 0, of course
if not (move.left or move.right):
self.xvel = 0

# move horizontal, and check for horizontal collisions
self.rect.left += self.xvel
self.collide(self.xvel, 0, blocks)

# move vertically, and check for vertical collisions
self.rect.top += self.yvel
self.on_ground = False;
self.collide(0, self.yvel, blocks)

唯一剩下的就是使用 Clock限制帧率让游戏以恒定速度运行。就是这样。

完整代码如下:

import pygame,random
from pygame.locals import *
from collections import namedtuple

pygame.init()
clock=pygame.time.Clock()
screen=pygame.display.set_mode((640,480))

max_gravity = 100

class Block(object):
sprite = pygame.image.load("dirt.png").convert_alpha()
def __init__(self, x, y):
self.rect = self.sprite.get_rect(centery=y, centerx=x)

class Player(object):
sprite = pygame.image.load("dirt.png").convert()
sprite.set_colorkey((0,255,0))
def __init__(self, x, y):
self.rect = self.sprite.get_rect(centery=y, centerx=x)
# indicates that we are standing on the ground
# and thus are "allowed" to jump
self.on_ground = True
self.xvel = 0
self.yvel = 0
self.jump_speed = 10
self.move_speed = 8

def update(self, move, blocks):

# check if we can jump
if move.up and self.on_ground:
self.yvel -= self.jump_speed

# simple left/right movement
if move.left: self.xvel = -self.move_speed
if move.right: self.xvel = self.move_speed

# if in the air, fall down
if not self.on_ground:
self.yvel += 0.3
# but not too fast
if self.yvel > max_gravity: self.yvel = max_gravity

# if no left/right movement, x speed is 0, of course
if not (move.left or move.right):
self.xvel = 0

# move horizontal, and check for horizontal collisions
self.rect.left += self.xvel
self.collide(self.xvel, 0, blocks)

# move vertically, and check for vertical collisions
self.rect.top += self.yvel
self.on_ground = False;
self.collide(0, self.yvel, blocks)

def collide(self, xvel, yvel, blocks):
# all blocks that we collide with
for block in [blocks[i] for i in self.rect.collidelistall(blocks)]:

# if xvel is > 0, we know our right side bumped
# into the left side of a block etc.
if xvel > 0: self.rect.right = block.rect.left
if xvel < 0: self.rect.left = block.rect.right

# if yvel > 0, we are falling, so if a collision happpens
# we know we hit the ground (remember, we seperated checking for
# horizontal and vertical collision, so if yvel != 0, xvel is 0)
if yvel > 0:
self.rect.bottom = block.rect.top
self.on_ground = True
self.yvel = 0
# if yvel < 0 and a collision occurs, we bumped our head
# on a block above us
if yvel < 0: self.rect.top = block.rect.bottom

blocklist = []
player = []
colliding = False
Move = namedtuple('Move', ['up', 'left', 'right'])
while True:
screen.fill((25,30,90))
mse = pygame.mouse.get_pos()
key = pygame.key.get_pressed()

for event in pygame.event.get():
if event.type == QUIT: exit()

if key[K_LSHIFT]:
if event.type==MOUSEMOTION:
if not any(block.rect.collidepoint(mse) for block in blocklist):
x=(int(mse[0]) / 32)*32
y=(int(mse[1]) / 32)*32
blocklist.append(Block(x+16,y+16))
else:
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
to_remove = [b for b in blocklist if b.rect.collidepoint(mse)]
for b in to_remove:
blocklist.remove(b)

if not to_remove:
x=(int(mse[0]) / 32)*32
y=(int(mse[1]) / 32)*32
blocklist.append(Block(x+16,y+16))

elif event.button == 3:
x=(int(mse[0]) / 32)*32
y=(int(mse[1]) / 32)*32
player=[]
player.append(Player(x+16,y+16))

move = Move(key[K_UP], key[K_LEFT], key[K_RIGHT])

for b in blocklist:
screen.blit(b.sprite, b.rect)
for p in player:
p.update(move, blocklist)
screen.blit(p.sprite, p.rect)
clock.tick(60)
pygame.display.flip()

请注意,我更改了图像名称,因此我只需要一个图像文件来测试它。另外,我不知道为什么要将玩家保留在列表中,但这是我们游戏的精彩动画:

enter image description here

关于python - 将碰撞检测添加到 pygame 中的平台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18966882/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com