这是一个简短的平台游戏示例。特别重要的是移动。您首先必须沿着x轴移动,检查玩家是否与墙碰撞,如果发生碰撞,则将其移回。然后在y轴上执行相同操作。如果您不将移动分成这两个部分,则玩家会在同时按下多个移动键时跳到墙的侧面、顶部或底部。
import pygame as pg
pg.init()
WINDOW_WIDTH, WINDOW_HEIGHT = 800, 600
screen = pg.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
GRAY = pg.Color('gray24')
GRAVITY = 800
class Player(pg.sprite.Sprite):
def __init__(self, pos, blocks):
super().__init__()
self.image = pg.Surface((30, 50))
self.image.fill(pg.Color(0, 110, 170))
self.rect = self.image.get_rect(topleft=pos)
self.vel = pg.math.Vector2(0, 0)
self.pos = pg.math.Vector2(pos)
self.blocks = blocks
self.on_ground = False
def update(self, dt):
self.pos.x += self.vel.x * dt
self.rect.x = self.pos.x
collisions = pg.sprite.spritecollide(self, self.blocks, False)
for block in collisions:
if self.vel.x > 0:
self.rect.right = block.rect.left
elif self.vel.x < 0:
self.rect.left = block.rect.right
self.pos.x = self.rect.x
self.pos.y += self.vel.y * dt
self.rect.y = self.pos.y + 1
if self.vel.y > 0:
self.on_ground = False
collisions = pg.sprite.spritecollide(self, self.blocks, False)
for block in collisions:
if self.vel.y > 0:
self.rect.bottom = block.rect.top
self.vel.y = 0
self.on_ground = True
elif self.vel.y < 0:
self.rect.top = block.rect.bottom
self.vel.y = 0
self.pos.y = self.rect.y
if self.rect.bottom >= WINDOW_HEIGHT:
self.vel.y = 0
self.rect.bottom = WINDOW_HEIGHT
self.pos.y = self.rect.y
self.on_ground = True
else:
self.vel.y += GRAVITY * dt
class Block(pg.sprite.Sprite):
def __init__(self, rect):
super().__init__()
self.image = pg.Surface(rect.size)
self.image.fill(pg.Color('paleturquoise2'))
self.rect = rect
def main():
clock = pg.time.Clock()
done = False
dt = 0
all_sprites = pg.sprite.Group()
blocks = pg.sprite.Group()
player = Player((300, 100), blocks)
all_sprites.add(player)
rects = ((300, 200, 30, 70), (100, 350, 270, 30),
(500, 450, 30, 170), (400, 570, 270, 30),
(500, 150, 70, 170), (535, 310, 270, 70))
for rect in rects:
block = Block(pg.Rect(rect))
all_sprites.add(block)
blocks.add(block)
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_a:
player.vel.x = -220
elif event.key == pg.K_d:
player.vel.x = 220
elif event.key == pg.K_w:
if player.on_ground:
player.vel.y = -470
player.pos.y -= 20
player.on_ground = False
elif event.type == pg.KEYUP:
if event.key == pg.K_a and player.vel.x < 0:
player.vel.x = 0
elif event.key == pg.K_d and player.vel.x > 0:
player.vel.x = 0
all_sprites.update(dt)
screen.fill(GRAY)
all_sprites.draw(screen)
pg.display.flip()
dt = clock.tick(60) / 1000
if __name__ == '__main__':
main()
pg.quit()
这是您在评论中发布的代码的工作版本(仅包含垂直碰撞,您还需要添加水平碰撞)。因此,当玩家跳跃并与平台碰撞时,您必须将
player.rect.top
设置为
platform.rect.bottom
并更改
vel.y
。
import pygame as pg
from pygame.math import Vector2 as vec
pg.init()
WIDTH, HEIGHT = 800, 600
YELLOW = pg.Color('yellow')
GREEN = pg.Color('green')
BLACK = pg.Color('gray11')
screen = pg.display.set_mode((WIDTH,HEIGHT))
clock = pg.time.Clock()
FPS = 60
PLAYER_FRICTION = .95
PLAYER_ACC = .2
class Player(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((30, 40))
self.image.fill(YELLOW)
self.rect = self.image.get_rect(center=(WIDTH/2, HEIGHT-30))
self.pos = vec(WIDTH/2, HEIGHT/2)
self.vel = vec(0,0)
self.acc = vec(0,0)
def jump(self):
self.rect.y += 1
hits = pg.sprite.spritecollide(self, platforms, False)
self.rect.y -= 1
if hits:
self.vel.y = -13
def update(self):
self.acc = vec(0, 0.5)
keys = pg.key.get_pressed()
if keys[pg.K_a]:
self.acc.x = -PLAYER_ACC
if keys[pg.K_d]:
self.acc.x = PLAYER_ACC
self.vel.x *= PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
self.rect.midbottom = self.pos
class Platform(pg.sprite.Sprite):
def __init__(self, x, y, w, h):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((w, h))
self.image.fill(GREEN)
self.rect = self.image.get_rect(topleft=(x, y))
all_sprites = pg.sprite.Group()
platforms = pg.sprite.Group()
player = Player()
all_sprites.add(player)
p1 = Platform(0, HEIGHT - 40, WIDTH, 40)
p2 = Platform(WIDTH / 2 - 50, HEIGHT - 300, 100, 20)
p3 = Platform(WIDTH / 2 - 100, HEIGHT - 150, 200, 20)
all_sprites.add(p1, p2, p3)
platforms.add(p1, p2, p3)
running = True
while running:
clock.tick(FPS)
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
if event.type == pg.KEYDOWN:
if event.key == pg.K_SPACE:
player.jump()
all_sprites.update()
hits = pg.sprite.spritecollide(player, platforms, False)
for platform in hits:
if player.vel.y > 0:
player.rect.bottom = platform.rect.top
player.vel.y = 0
elif player.vel.y < 0:
player.rect.top = platform.rect.bottom
player.vel.y = 3
player.pos.y = player.rect.bottom
screen.fill(BLACK)
all_sprites.draw(screen)
pg.display.flip()
pg.quit()
顺便提一下,在jump方法中,你需要更改self.rect.y
而不是self.rect.x
。