gpt4 book ai didi

Pygame 级别/菜单状态

转载 作者:太空宇宙 更新时间:2023-11-03 20:16:04 26 4
gpt4 key购买 nike

通过下面的代码,实现游戏状态来控制关卡的最简单、最容易的方法是什么?如果我想从标题屏幕开始,然后加载一个关卡,并在完成后进入下一个关卡?如果有人可以解释处理这个问题的最简单方法,那就太好了!

import pygame
from pygame import *

WIN_WIDTH = 1120 - 320
WIN_HEIGHT = 960 - 320
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 0
FLAGS = 0
CAMERA_SLACK = 30

def main():
global level
pygame.init()
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
timer = pygame.time.Clock()
level = 0

bg = Surface((32,32))
bg.convert()
bg.fill(Color("#0094FF"))

up = left = right = False
entities = pygame.sprite.Group()
player = Player(32, 32)
enemy = Enemy(32,32)
platforms = []

x = 0
y = 0

if level == 0:
level = [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" E ",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPP PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPP P",
" PPPP P",
" PPPP PPPPPPP",
" PPPPPPPPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
"PPPPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPPP PPPP PPPPPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",]

#background = pygame.image.load("Untitled.png")


total_level_width = len(level[0]) * 32
total_level_height = len(level) * 32

# build the level
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)
platforms.append(p)
entities.add(p)
if col == "E":
e = ExitBlock(x, y)
platforms.append(e)
entities.add(e)
x += 32
y += 32
x = 0

camera = Camera(complex_camera, total_level_width, total_level_height)
entities.add(player)
entities.add(enemy)

while 1:
timer.tick(60)

for e in pygame.event.get():
if e.type == QUIT: raise SystemExit, "QUIT"
if e.type == KEYDOWN and e.key == K_ESCAPE:
raise SystemExit, "ESCAPE"

if e.type == KEYDOWN and e.key == K_UP:
up = True
if e.type == KEYDOWN and e.key == K_LEFT:
left = True
if e.type == KEYDOWN and e.key == K_RIGHT:
right = True

if e.type == KEYUP and e.key == K_UP:
up = False
if e.type == KEYUP and e.key == K_LEFT:
left = False
if e.type == KEYUP and e.key == K_RIGHT:
right = False

# draw background
for y in range(20):
for x in range(25):
screen.blit(bg, (x * 32, y * 32))

# draw background
#screen.blit(background, camera.apply((0,0)))
#draw entities
for e in entities:
screen.blit(e.image, camera.apply(e))
# update player, update camera, and refresh
player.update(up, left, right, platforms)
enemy.update(platforms)
camera.update(player)
pygame.display.flip()

class Camera(object):
def __init__(self, camera_func, width, height):
self.camera_func = camera_func
self.state = Rect(0, 0, width, height)

def apply(self, target):
try:
return target.rect.move(self.state.topleft)
except AttributeError:
return map(sum, zip(target, self.state.topleft))

def update(self, target):
self.state = self.camera_func(self.state, target.rect)

def complex_camera(camera, target_rect):
l, t, _, _ = target_rect
_, _, w, h = camera
l, t, _, _ = -l + HALF_WIDTH, -t +HALF_HEIGHT, w, h

l = min(0, l) # stop scrolling left
l = max(-(camera.width - WIN_WIDTH), l) # stop scrolling right
t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling bottom

return Rect(l, t, w, h)

class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)

class Player(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.xvel = 0
self.yvel = 0
self.onGround = False
self.image = Surface((32,32))
self.image.fill(Color("#0000FF"))
self.image.convert()
self.rect = Rect(200, 1200, 32, 32)


def update(self, up, left, right, platforms):
if self.rect.top > 1440 or self.rect.top < 0:
main()
if self.rect.left > 1408 or self.rect.right < 0:
main()
if up:
if self.onGround:
self.yvel = 0
self.yvel -= 10 # only jump if on the ground
if left:
self.xvel = -10
if right:
self.xvel = 10
if not self.onGround:
self.yvel += 0.3 # only accelerate with gravity if in the air
if self.yvel > 80: self.yvel = 80 # max falling speed
if not(left or right):
self.xvel = 0

self.rect.left += self.xvel # increment in x direction
self.collide(self.xvel, 0, platforms) # do x-axis collisions
self.rect.top += self.yvel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yvel, platforms) # do y-axis collisions

def collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, ExitBlock):
pygame.event.post(pygame.event.Event(QUIT))
if xvel > 0: self.rect.right = p.rect.left
if xvel < 0: self.rect.left = p.rect.right
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yvel < 0:
self.rect.top = p.rect.bottom


class Enemy(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.yVel = 0
self.xVel = 0
self.image = Surface((32,32))
self.image.fill(Color("#00FF00"))
self.image.convert()
self.rect = Rect(300, 1200, 32, 32)
self.onGround = False
self.right_dis = False

def update(self, platforms):
if not self.onGround:
self.yVel += 0.3

if self.rect.left == 96:
self.right_dis = False
if self.rect.right == 480:
self.right_dis = True
if not self.right_dis:
self.xVel = 2
if self.right_dis:
self.xVel = -2

self.rect.left += self.xVel # increment in x direction
self.collide(self.xVel, 0, platforms) # do x-axis collisions
self.rect.top += self.yVel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yVel, platforms) # do y-axis collisions

def collide(self, xVel, yVel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if xVel > 0: self.rect.right = p.rect.left
if xVel < 0: self.rect.left = p.rect.right
if yVel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yVel < 0:
self.rect.top = p.rect.bottom

class Platform(Entity):
def __init__(self, x, y):
Entity.__init__(self)
#self.image = Surface([32, 32], pygame.SRCALPHA, 32) #makes blocks invisible for much better artwork
self.image = Surface((32,32)) #makes blocks visible for building levels
self.image.convert()
self.rect = Rect(x, y, 32, 32)

def update(self):
pass

class ExitBlock(Platform):
def __init__(self, x, y):
Platform.__init__(self, x, y)
self.image = pygame.image.load("end.png")




if __name__ == "__main__":
main()

最佳答案

首先,让我们摆脱这些丑陋的 if block :

for e in pygame.event.get():
if e.type == QUIT: raise SystemExit, "QUIT"
if e.type == KEYDOWN and e.key == K_ESCAPE:
raise SystemExit, "ESCAPE"

if e.type == KEYDOWN and e.key == K_UP:
up = True
if e.type == KEYDOWN and e.key == K_LEFT:
left = True
if e.type == KEYDOWN and e.key == K_RIGHT:
right = True

if e.type == KEYUP and e.key == K_UP:
up = False
if e.type == KEYUP and e.key == K_LEFT:
left = False
if e.type == KEYUP and e.key == K_RIGHT:
right = False

我们可以将它们重写为:

for e in pygame.event.get():
if e.type == QUIT: raise SystemExit, "QUIT"
if e.type == KEYDOWN and e.key == K_ESCAPE:
raise SystemExit, "ESCAPE"

pressed = pygame.key.get_pressed()
up, left, right = [pressed[key] for key in (K_UP, K_LEFT, K_RIGHT)]

这稍后会派上用场。

<小时/>

回到主题:我们想要的是一堆不同的场景。每个场景都必须负责自己的屏幕渲染和事件处理。

让我们尝试将现有代码提取到游戏场景中,以便以后可以添加其他场景。我们首先创建一个空的 Scene 类,它将作为场景的基类:

class Scene(object):
def __init__(self):
pass

def render(self, screen):
raise NotImplementedError

def update(self):
raise NotImplementedError

def handle_events(self, events):
raise NotImplementedError

我们的计划是覆盖每个子类中的每个方法,因此我们在基类中引发 NotImplementedErrors,以便我们很容易发现是否忘记这样做(我们也可以使用 ABC,但是让我们保持简单)。

现在让我们将与运行游戏状态相关的所有内容(基本上是所有内容)放入新的 GameScene 类中。

class GameScene(Scene):
def __init__(self):
super(GameScene, self).__init__()
level = 0
self.bg = Surface((32,32))
self.bg.convert()
self.bg.fill(Color("#0094FF"))
up = left = right = False
self.entities = pygame.sprite.Group()
self.player = Player(32, 32)
self.enemy = Enemy(32,32)
self.platforms = []

x = 0
y = 0

if level == 0:
level = [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" E ",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPP PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPP P",
" PPPP P",
" PPPP PPPPPPP",
" PPPPPPPPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
"PPPPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPPP PPPP PPPPPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",]

#background = pygame.image.load("Untitled.png")


total_level_width = len(level[0]) * 32
total_level_height = len(level) * 32

# build the level
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)
self.platforms.append(p)
self.entities.add(p)
if col == "E":
e = ExitBlock(x, y)
self.platforms.append(e)
self.entities.add(e)
x += 32
y += 32
x = 0

self.camera = Camera(complex_camera, total_level_width, total_level_height)
self.entities.add(self.player)
self.entities.add(self.enemy)

def render(self, screen):
for y in range(20):
for x in range(25):
screen.blit(self.bg, (x * 32, y * 32))

for e in self.entities:
screen.blit(e.image, self.camera.apply(e))

def update(self):
pressed = pygame.key.get_pressed()
up, left, right = [pressed[key] for key in (K_UP, K_LEFT, K_RIGHT)]
self.player.update(up, left, right, self.platforms)
self.enemy.update(self.platforms)
self.camera.update(self.player)

def handle_events(self, events):
for e in events:
if e.type == KEYDOWN and e.key == K_ESCAPE:
pass #somehow go back to menu

虽然还不完美,但是一个好的开始。与实际游戏玩法相关的所有内容都被提取到其自己的类中。有些变量必须是实例变量,因此必须通过 self 访问它们。

现在我们需要更改 main 函数以实际使用此类:

def main():
pygame.init()
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
timer = pygame.time.Clock()
running = True

scene = GameScene()

while running:
timer.tick(60)

if pygame.event.get(QUIT):
running = False
return
scene.handle_events(pygame.event.get())
scene.update()
scene.render(screen)
pygame.display.flip()

请注意,我更改了两件小事:我使用 pygame.event.get(QUIT) 来仅首先获取可能的 QUIT 事件,因为这是唯一的我们在主循环中感兴趣的事件。所有其他事件都直接传递到当前场景: scene.handle_events(pygame.event.get())

此时,我们可以考虑将一些类提取到自己的文件中,但我们还是继续吧。

让我们创建一个标题菜单:

class TitleScene(object):

def __init__(self):
super(TitleScene, self).__init__()
self.font = pygame.font.SysFont('Arial', 56)
self.sfont = pygame.font.SysFont('Arial', 32)

def render(self, screen):
# beware: ugly!
screen.fill((0, 200, 0))
text1 = self.font.render('Crazy Game', True, (255, 255, 255))
text2 = self.sfont.render('> press space to start <', True, (255, 255, 255))
screen.blit(text1, (200, 50))
screen.blit(text2, (200, 350))

def update(self):
pass

def handle_events(self, events):
for e in events:
if e.type == KEYDOWN and e.key == K_SPACE:
self.manager.go_to(GameScene(0))

这仅显示绿色背景和一些文本。如果玩家按下空格,我们要开始第一个关卡。请注意这一行:

self.manager.go_to(GameScene(0))

这里我将参数 0 传递给 GameScene 类,所以让我们对其进行更改,使其接受此参数:

class GameScene(Scene):
def __init__(self, level):
...

正如您已经猜到的那样,可以删除 level = 0 行。

那么self.manager是什么?它只是一个为我们管理场景的小助手类。

class SceneMananger(object):
def __init__(self):
self.go_to(TitleScene())

def go_to(self, scene):
self.scene = scene
self.scene.manager = self

它从标题场景开始,并将每个场景manager字段设置为自身以允许更改当前场景。如何实现这样的场景管理器有很多可能性,这是最简单的方法。缺点是每个场景都必须知道它后面是哪个场景,但这现在不应该困扰我们。

让我们使用新的 SceneMananger:

def main():
pygame.init()
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
timer = pygame.time.Clock()
running = True

manager = SceneMananger()

while running:
timer.tick(60)

if pygame.event.get(QUIT):
running = False
return
manager.scene.handle_events(pygame.event.get())
manager.scene.update()
manager.scene.render(screen)
pygame.display.flip()

简单明了。让我们快速添加第二个关卡和获胜/失败屏幕,然后就完成了。

class CustomScene(object):

def __init__(self, text):
self.text = text
super(CustomScene, self).__init__()
self.font = pygame.font.SysFont('Arial', 56)

def render(self, screen):
# ugly!
screen.fill((0, 200, 0))
text1 = self.font.render(self.text, True, (255, 255, 255))
screen.blit(text1, (200, 50))

def update(self):
pass

def handle_events(self, events):
for e in events:
if e.type == KEYDOWN:
self.manager.go_to(TitleScene())

下面是完整的代码。请注意 Player 类的更改:它不再调用 main 函数,而是调用场景上的方法来指示玩家到达导出或死亡。

此外,我还更改了玩家和敌人的位置。现在,您指定实体将出现在关卡中的位置。例如。 Player(5, 40) 将在关卡第 5 列、第 40 行创建玩家。作为奖励,敌人可以进行适当的碰撞检测。

我将级别的描述提取到名为 levels 的字典中,因此可以根据需要轻松更改和添加级别(稍后,您可能需要每个级别一个文件,所以这是一个好的开始)。它可以扩展以保持玩家的起始位置,但您也可以创建一个特殊的图 block ,例如用于起始位置的 * 和用于关卡描述中的敌人的 E 。 p>

import pygame
from pygame import *

WIN_WIDTH = 1120 - 320
WIN_HEIGHT = 960 - 320
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 0
FLAGS = 0
CAMERA_SLACK = 30

levels = {0: {'level': [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" E ",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPP PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPP P",
" PPPP P",
" PPPP PPPPPPP",
" PPPPPPPPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
"PPPPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPPP PPPP PPPPPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",],
'enemies': [(9, 38)]},
1: {'level': [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" E ",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPPP PPPPPPPPPPPPPPPP",
" PPPPPPPPPPPPPPPP",
" PPPP P",
" PPPP P",
" PPPP PPPPPPP",
" PPPPPPPPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
" PPPP PPPPPPP",
"PPPPP PPPP PPPPPPP",
"PPP PPPPPPPPPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPP PPPPPPP",
"PPP PPPPPPPP PPPP PPPPPPP",
"PPP PPPP",
"PPP PPPP",
"PPP PPPPP PPPP",
"PPP P PPPPPPPPPPPPPPPPPP",
"PPP P PPPPPPPPPPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",
"PPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPP",],
'enemies': [(9, 38), (18, 38), (15, 15)]}}

class Scene(object):
def __init__(self):
pass

def render(self, screen):
raise NotImplementedError

def update(self):
raise NotImplementedError

def handle_events(self, events):
raise NotImplementedError

class GameScene(Scene):
def __init__(self, levelno):
super(GameScene, self).__init__()
self.bg = Surface((32,32))
self.bg.convert()
self.bg.fill(Color("#0094FF"))
up = left = right = False
self.entities = pygame.sprite.Group()
self.player = Player(5, 40)
self.player.scene = self
self.platforms = []

self.levelno = levelno

levelinfo = levels[levelno]
self.enemies = [Enemy(*pos) for pos in levelinfo['enemies']]

level = levelinfo['level']
total_level_width = len(level[0]) * 32
total_level_height = len(level) * 32

# build the level
x = 0
y = 0
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)
self.platforms.append(p)
self.entities.add(p)
if col == "E":
e = ExitBlock(x, y)
self.platforms.append(e)
self.entities.add(e)
x += 32
y += 32
x = 0

self.camera = Camera(complex_camera, total_level_width, total_level_height)
self.entities.add(self.player)
for e in self.enemies:
self.entities.add(e)

def render(self, screen):
for y in range(20):
for x in range(25):
screen.blit(self.bg, (x * 32, y * 32))

for e in self.entities:
screen.blit(e.image, self.camera.apply(e))

def update(self):
pressed = pygame.key.get_pressed()
up, left, right = [pressed[key] for key in (K_UP, K_LEFT, K_RIGHT)]
self.player.update(up, left, right, self.platforms)

for e in self.enemies:
e.update(self.platforms)

self.camera.update(self.player)

def exit(self):
if self.levelno+1 in levels:
self.manager.go_to(GameScene(self.levelno+1))
else:
self.manager.go_to(CustomScene("You win!"))

def die(self):
self.manager.go_to(CustomScene("You lose!"))

def handle_events(self, events):
for e in events:
if e.type == KEYDOWN and e.key == K_ESCAPE:
self.manager.go_to(TitleScene())

class CustomScene(object):

def __init__(self, text):
self.text = text
super(CustomScene, self).__init__()
self.font = pygame.font.SysFont('Arial', 56)

def render(self, screen):
# ugly!
screen.fill((0, 200, 0))
text1 = self.font.render(self.text, True, (255, 255, 255))
screen.blit(text1, (200, 50))

def update(self):
pass

def handle_events(self, events):
for e in events:
if e.type == KEYDOWN:
self.manager.go_to(TitleScene())

class TitleScene(object):

def __init__(self):
super(TitleScene, self).__init__()
self.font = pygame.font.SysFont('Arial', 56)
self.sfont = pygame.font.SysFont('Arial', 32)

def render(self, screen):
# ugly!
screen.fill((0, 200, 0))
text1 = self.font.render('Crazy Game', True, (255, 255, 255))
text2 = self.sfont.render('> press space to start <', True, (255, 255, 255))
screen.blit(text1, (200, 50))
screen.blit(text2, (200, 350))

def update(self):
pass

def handle_events(self, events):
for e in events:
if e.type == KEYDOWN and e.key == K_SPACE:
self.manager.go_to(GameScene(0))

class SceneMananger(object):
def __init__(self):
self.go_to(TitleScene())

def go_to(self, scene):
self.scene = scene
self.scene.manager = self

def main():
pygame.init()
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
timer = pygame.time.Clock()
running = True

manager = SceneMananger()

while running:
timer.tick(60)

if pygame.event.get(QUIT):
running = False
return
manager.scene.handle_events(pygame.event.get())
manager.scene.update()
manager.scene.render(screen)
pygame.display.flip()

class Camera(object):
def __init__(self, camera_func, width, height):
self.camera_func = camera_func
self.state = Rect(0, 0, width, height)

def apply(self, target):
try:
return target.rect.move(self.state.topleft)
except AttributeError:
return map(sum, zip(target, self.state.topleft))

def update(self, target):
self.state = self.camera_func(self.state, target.rect)

def complex_camera(camera, target_rect):
l, t, _, _ = target_rect
_, _, w, h = camera
l, t, _, _ = -l + HALF_WIDTH, -t +HALF_HEIGHT, w, h

l = min(0, l) # stop scrolling left
l = max(-(camera.width - WIN_WIDTH), l) # stop scrolling right
t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling bottom

return Rect(l, t, w, h)

class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)

class Player(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.xvel = 0
self.yvel = 0
self.onGround = False
self.image = Surface((32,32))
self.image.fill(Color("#0000FF"))
self.image.convert()
self.rect = Rect(x*32, y*32, 32, 32)

def update(self, up, left, right, platforms):
if self.rect.top > 1440 or self.rect.top < 0:
self.scene.die()
if self.rect.left > 1408 or self.rect.right < 0:
self.scene.die()
if up:
if self.onGround:
self.yvel = 0
self.yvel -= 10 # only jump if on the ground
if left:
self.xvel = -10
if right:
self.xvel = 10
if not self.onGround:
self.yvel += 0.3 # only accelerate with gravity if in the air
if self.yvel > 80: self.yvel = 80 # max falling speed
if not(left or right):
self.xvel = 0

self.rect.left += self.xvel # increment in x direction
if self.collide(self.xvel, 0, platforms): # do x-axis collisions
self.rect.top += self.yvel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yvel, platforms) # do y-axis collisions

def collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, ExitBlock):
self.scene.exit()
return False
if xvel > 0: self.rect.right = p.rect.left
if xvel < 0: self.rect.left = p.rect.right
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yvel < 0:
self.rect.top = p.rect.bottom
return True

class Enemy(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.yVel = 0
self.xVel = 2 # start moving immediately
self.image = Surface((32,32))
self.image.fill(Color("#00FF00"))
self.image.convert()
self.rect = Rect(x*32, y*32, 32, 32)
self.onGround = False

def update(self, platforms):
if not self.onGround:
self.yVel += 0.3

# no need for right_dis to be a member of the class,
# since we know we are moving right if self.xVel > 0
right_dis = self.xVel > 0

# create a point at our left (or right) feet
# to check if we reached the end of the platform
m = (1, 1) if right_dis else (-1, 1)
p = self.rect.bottomright if right_dis else self.rect.bottomleft
fp = map(sum, zip(m, p))

# if there's no platform in front of us, change the direction
collide = any(p for p in platforms if p.rect.collidepoint(fp))
if not collide:
self.xVel *= -1

self.rect.left += self.xVel # increment in x direction
self.collide(self.xVel, 0, platforms) # do x-axis collisions
self.rect.top += self.yVel # increment in y direction
self.onGround = False; # assuming we're in the air
self.collide(0, self.yVel, platforms) # do y-axis collisions

def collide(self, xVel, yVel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if xVel > 0:
self.rect.right = p.rect.left
self.xVel *= -1 # hit wall, so change direction
if xVel < 0:
self.rect.left = p.rect.right
self.xVel *= -1 # hit wall, so change direction
if yVel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
if yVel < 0:
self.rect.top = p.rect.bottom

class Platform(Entity):
def __init__(self, x, y):
Entity.__init__(self)
#self.image = Surface([32, 32], pygame.SRCALPHA, 32) #makes blocks invisible for much better artwork
self.image = Surface((32,32)) #makes blocks visible for building levels
self.image.convert()
self.rect = Rect(x, y, 32, 32)

def update(self):
pass

class ExitBlock(Platform):
def __init__(self, x, y):
Platform.__init__(self, x, y)
self.image = Surface((32,32)) #makes blocks visible for building levels
self.image.convert()
self.rect = Rect(x, y, 32, 32)




if __name__ == "__main__":
main()

关于Pygame 级别/菜单状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58441049/

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