2013-10-03 52 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(screen,(200,200,0),block)'' '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()提高圖像質量。 –