我正在尝试制作一个游戏,您需要在地图自动滚动时避开障碍物。到目前为止,我已经从其他人那里获取了一些代码以试图重新利用它,但我遇到了一些麻烦。我是pygame的新手,所以任何帮助都会非常感激。
我想简化这段代码,但每当我更改一行时,就会出现问题。我不需要任何重力,我想随意上下移动(有点像R-Type或其他一些旧的太空射击者)。最重要的部分是使地图自己从右向左滚动,如果玩家触摸墙壁,则玩家将死亡。
我知道我需要告诉它移动播放器周围的所有内容,但我不知道如何在此代码中表达它。
以下是代码:
import pygame
from pygame import *
WIN_WIDTH = 800
WIN_HEIGHT = 640
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)
DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30
def main():
global cameraX, cameraY
pygame.init()
screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
pygame.display.set_caption("Use arrows to move!")
timer = pygame.time.Clock()
up = down = left = right = running = False
bg = Surface((32,32))
bg.convert()
bg.fill(Color("#000000"))
entities = pygame.sprite.Group()
player = Player(32, 32)
platforms = []
x = y = 0
level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P P P E",
"P P P PPP PPPPPPPPPPPPP E",
"P P P PPP PPPPPPPPPPPPP E",
"P P P PPPPPPPPP P",
"P PPPP P P PPPPPPPPP P",
"P P P PPPP PPP PPPPPPPPPPPP P",
"P P P PPP PPP PPPPPPPPPPPP P",
"P P P PPP PPP P",
"P P P PPP PPPPPPP P",
"P P P PPPPPPP P",
"P P P P",
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"]
# 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
total_level_width = len(level[0])*32
total_level_height = len(level)*32
camera = Camera(complex_camera, total_level_width, total_level_height)
entities.add(player)
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_DOWN:
down = 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 == KEYDOWN and e.key == K_SPACE:
running = True
if e.type == KEYUP and e.key == K_UP:
up = False
if e.type == KEYUP and e.key == K_DOWN:
down = False
if e.type == KEYUP and e.key == K_RIGHT:
right = 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(32):
for x in range(32):
screen.blit(bg, (x * 32, y * 32))
camera.update(player)
# update player, draw everything else
player.update(up, down, left, right, running, platforms)
for e in entities:
screen.blit(e.image, camera.apply(e))
pygame.display.update()
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):
return target.rect.move(self.state.topleft)
def update(self, target):
self.state = self.camera_func(self.state, target.rect)
def simple_camera(camera, target_rect):
l, t, _, _ = target_rect
_, _, w, h = camera
return Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)
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 at the left edge
l = max(-(camera.width-WIN_WIDTH), l) # stop scrolling at the right edge
t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling at the bottom
t = min(0, t) # stop scrolling at the top
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, y, 32, 32)
def update(self, up, down, left, right, running, platforms):
if up:
# only jump if on the ground
if self.onGround: self.yvel -= 10
pass
if down:
pass
if running:
self.xvel = 12
if left:
self.xvel = -8
if right:
self.xvel = 8
if not self.onGround:
# only accelerate with gravity if in the air
self.yvel += 0.3
# max falling speed
if self.yvel > 100: self.yvel = 100
if not(left or right):
self.xvel = 0
# increment in x direction
self.rect.left += self.xvel
# do x-axis collisions
self.collide(self.xvel, 0, platforms)
# increment in y direction
self.rect.top += self.yvel
# assuming we're in the air
self.onGround = False;
# do y-axis collisions
self.collide(0, self.yvel, platforms)
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
print "collide right"
if xvel < 0:
self.rect.left = p.rect.right
print "collide left"
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
self.yvel = 0
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))
self.image.convert()
self.image.fill(Color("#DDDDDD"))
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.fill(Color("#0033FF"))
if __name__ == "__main__":
main()
感谢Dominic Kexel提供了大部分代码。
答案 0 :(得分:1)
我认为在这里使用相机是错误的做法;我宁愿自己移动块。
看看这个简单的例子(它应该让你开始):
import pygame
lvl = """
##################################################################
# #
# # # #
# # # #
# # # #
# # # #
# # # # # #
# # #
#### # # #
# # # #
##################################################################"""
# initialisation
pygame.init()
clock = pygame.time.Clock()
lvl = lvl.split('\n')[1:]
TOTAL_H, TOTAL_W = len(lvl)*32, len(lvl[0])*32
screen = pygame.display.set_mode((800, TOTAL_H))
LEVEL_SPEED = 5
player, PLAYER_SPEED = pygame.Rect(100, 100, 32, 32), 4
font = pygame.font.SysFont('Arial', 52)
text = font.render('FAILED !', True, (255, 0, 0))
timeout = 0
# create Rects that represent the level
x, y = 0, 0
blocks = []
for line in lvl:
for char in line:
if char == '#':
blocks.append(pygame.Rect(x*32, y*32, 32, 32))
x += 1
x, y = 0, y + 1
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.QUIT:
run = False
break
if timeout:
timeout -= 1
else:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: player.move_ip(0, -PLAYER_SPEED)
if pressed[pygame.K_DOWN]: player.move_ip(0, PLAYER_SPEED)
if pressed[pygame.K_LEFT]: player.move_ip(-PLAYER_SPEED, 0)
if pressed[pygame.K_RIGHT]: player.move_ip(PLAYER_SPEED, 0)
for block in blocks:
# move each block
block.move_ip(-LEVEL_SPEED, 0)
# collision detection
if not timeout and block.colliderect(player):
timeout = 100
# if blocks move out of view,
# let'm reappear on the right to
# create an endless loop
if block.right < 0:
block.move_ip(TOTAL_W, 0)
screen.fill((0, 0, 0))
for block in blocks:
pygame.draw.rect(screen, (200, 200, 0), block)
if not timeout:
pygame.draw.rect(screen, (100, 200, 200), player)
else:
screen.blit(text, (200, 150))
pygame.display.flip()
clock.tick(40)