2013-10-03 3 views
2

Я пытаюсь создать игру, где вам нужно избегать препятствий, пока карта прокручивается автоматически. До сих пор я взял какой-то код от кого-то другого, пытаясь перепрофилировать его, но у меня проблемы. Я новичок в pygame, поэтому любая помощь будет очень признательна.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() 

Благодаря Доминик 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) 

enter image description here

+0

Удивительный! Большое вам спасибо за вашу помощь! У меня есть еще один вопрос: что было бы хорошим способом включения текстур для движущихся «стен»? Я посмотрел на плитки в PyxelEdit и Tiled. Было бы легко заменить изображение на один из этих «#» блоков? – braintree

+0

Конечно. Вместо 'pygame.draw.rect (экран, (200, 200, 0), блок)' просто blit изображение, например. 'screen.blit (block_image, block)' где 'block_image' - это изображение, загруженное в начале вашей игры, например. 'block_image = pygame.image.load ('your/file/name.jpg'). convert()' – sloth

+0

Или используйте block_image = pygame.image.load ('red.png'). convert_alpha(), это не беспорядок качество изображения. –

Смежные вопросы