使你的 Python 遊戲玩家能夠向前和向後跑

2020-01-25 22:07:00

使用 Pygame 模組來使你的 Python 平台開啟側滾效果,來讓你的玩家自由奔跑。

這是仍在進行中的關於使用 Pygame 模組來在 Python 3 中在建立電腦遊戲的第九部分。先前的文章是:

在這一系列關於使用 Pygame 模組來在 Python 3 中建立電腦遊戲的先前文章中,你已經設計了你的關卡設計布局,但是你的關卡的一些部分可能已近超出你的螢幕的可視區域。在平台類遊戲中,這個問題的普遍解決方案是,像術語“側滾side-scroller”表明的一樣,捲動。

捲動的關鍵是當玩家精靈接近屏的幕邊緣時,使在玩家精靈周圍的平台移動。這樣給予一種錯覺,螢幕是一個在遊戲世界中穿梭追拍的攝像機

這個捲動技巧需要兩個在螢幕邊緣的絕對區域,在絕對區域內的點處,在世界捲動期間,你的化身靜止不動。

在側捲軸中放置捲軸

如果你希望你的玩家能夠後退,你需要一個觸發點來向前和向後。這兩個點僅僅是兩個變數。設定它們各個距各個螢幕邊緣大約 100 或 200 畫素。在你的設定部分中建立變數。在下面的程式碼中,前兩行用於上下文說明,所以僅需要新增這行後的程式碼:

player_list.add(player)steps = 10forwardX  = 600backwardX = 230

在主迴圈中,檢視你的玩家精靈是否在 forwardxbackwardx 捲動點處。如果是這樣,向左或向右移動使用的平台,取決於世界是向前或向後移動。在下面的程式碼中,程式碼的最後三行僅供你參考:

        # scroll the world forward        if player.rect.x >= forwardx:                scroll = player.rect.x - forwardx                player.rect.x = forwardx                for p in plat_list:                        p.rect.x -= scroll        # scroll the world backward        if player.rect.x <= backwardx:                scroll = backwardx - player.rect.x                player.rect.x = backwardx                for p in plat_list:                        p.rect.x += scroll        ## scrolling code above    world.blit(backdrop, backdropbox)    player.gravity() # check gravity    player.update()

啟動你的遊戲,並嘗試它。

Scrolling the world in Pygame

捲動像預期的一樣工作,但是你可能注意到一個發生的小問題,當你捲動你的玩家和非玩家精靈周圍的世界時:敵人精靈不隨同世界捲動。除非你要你的敵人精靈要無休止地追逐你的玩家,你需要修改敵人程式碼,以便當你的玩家快速撤退時,敵人被留在後面。

敵人捲軸

在你的主迴圈中,你必須對捲軸平台為你的敵人的位置的應用相同的規則。因為你的遊戲世界將(很可能)有不止一個敵人在其中,該規則應該被應用於你的敵人列表,而不是一個單獨的敵人精靈。這是分組類似元素到列表中的優點之一。

前兩行用於上下文注釋,所以只需新增這兩行後面的程式碼到你的主迴圈中:

    # scroll the world forward    if player.rect.x >= forwardx:        scroll = player.rect.x - forwardx        player.rect.x = forwardx        for p in plat_list:            p.rect.x -= scroll        for e in enemy_list:            e.rect.x -= scroll

來滾向另一個方向:

    # scroll the world backward    if player.rect.x <= backwardx:        scroll = backwardx - player.rect.x        player.rect.x = backwardx        for p in plat_list:            p.rect.x += scroll        for e in enemy_list:            e.rect.x += scroll

再次啟動遊戲,看看發生什麼。

這裡是到目前為止你已經為這個 Python 平台所寫所有的程式碼:

#!/usr/bin/env python3# draw a world# add a player and player control# add player movement# add enemy and basic collision# add platform# add gravity# add jumping# add scrolling# GNU All-Permissive License# Copying and distribution of this file, with or without modification,# are permitted in any medium without royalty provided the copyright# notice and this notice are preserved.  This file is offered as-is,# without any warranty.import pygameimport sysimport os'''Objects'''class Platform(pygame.sprite.Sprite):    # x location, y location, img width, img height, img file        def __init__(self,xloc,yloc,imgw,imgh,img):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load(os.path.join('images',img)).convert()        self.image.convert_alpha()        self.rect = self.image.get_rect()        self.rect.y = yloc        self.rect.x = xlocclass Player(pygame.sprite.Sprite):    '''    Spawn a player    '''    def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.movex = 0        self.movey = 0        self.frame = 0        self.health = 10        self.collide_delta = 0        self.jump_delta = 6        self.score = 1        self.images = []        for i in range(1,9):            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()            img.convert_alpha()            img.set_colorkey(ALPHA)            self.images.append(img)            self.image = self.images[0]            self.rect  = self.image.get_rect()    def jump(self,platform_list):        self.jump_delta = 0    def gravity(self):        self.movey += 3.2 # how fast player falls               if self.rect.y > worldy and self.movey >= 0:            self.movey = 0            self.rect.y = worldy-ty           def control(self,x,y):        '''        control player movement        '''        self.movex += x        self.movey += y           def update(self):        '''        Update sprite position        '''               self.rect.x = self.rect.x + self.movex        self.rect.y = self.rect.y + self.movey        # moving left        if self.movex < 0:            self.frame += 1            if self.frame > ani*3:                self.frame = 0            self.image = self.images[self.frame//ani]        # moving right        if self.movex > 0:            self.frame += 1            if self.frame > ani*3:                self.frame = 0            self.image = self.images[(self.frame//ani)+4]        # collisions        enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)        for enemy in enemy_hit_list:            self.health -= 1            #print(self.health)        plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)        for p in plat_hit_list:            self.collide_delta = 0 # stop jumping            self.movey = 0            if self.rect.y > p.rect.y:                self.rect.y = p.rect.y+ty            else:                self.rect.y = p.rect.y-ty                   ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)        for g in ground_hit_list:            self.movey = 0            self.rect.y = worldy-ty-ty            self.collide_delta = 0 # stop jumping            if self.rect.y > g.rect.y:                self.health -=1                print(self.health)                       if self.collide_delta < 6 and self.jump_delta < 6:            self.jump_delta = 6*2            self.movey -= 33  # how high to jump            self.collide_delta += 6            self.jump_delta    += 6           class Enemy(pygame.sprite.Sprite):    '''    Spawn an enemy    '''    def __init__(self,x,y,img):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load(os.path.join('images',img))        self.movey = 0        #self.image.convert_alpha()        #self.image.set_colorkey(ALPHA)        self.rect = self.image.get_rect()        self.rect.x = x        self.rect.y = y        self.counter = 0                   def move(self):        '''        enemy movement        '''        distance = 80        speed = 8        self.movey += 3.2               if self.counter >= 0 and self.counter <= distance:            self.rect.x += speed        elif self.counter >= distance and self.counter <= distance*2:            self.rect.x -= speed        else:            self.counter = 0               self.counter += 1        if not self.rect.y >= worldy-ty-ty:            self.rect.y += self.movey        plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)        for p in plat_hit_list:            self.movey = 0            if self.rect.y > p.rect.y:                self.rect.y = p.rect.y+ty            else:                self.rect.y = p.rect.y-ty        ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)        for g in ground_hit_list:            self.rect.y = worldy-ty-ty       class Level():    def bad(lvl,eloc):        if lvl == 1:            enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy            enemy_list = pygame.sprite.Group() # create enemy group            enemy_list.add(enemy)              # add enemy to group                   if lvl == 2:            print("Level " + str(lvl) )        return enemy_list    def loot(lvl,lloc):        print(lvl)    def ground(lvl,gloc,tx,ty):        ground_list = pygame.sprite.Group()        i=0        if lvl == 1:            while i < len(gloc):                ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')                ground_list.add(ground)                i=i+1        if lvl == 2:            print("Level " + str(lvl) )        return ground_list    def platform(lvl,tx,ty):        plat_list = pygame.sprite.Group()        ploc = []        i=0        if lvl == 1:            ploc.append((0,worldy-ty-128,3))            ploc.append((300,worldy-ty-256,3))            ploc.append((500,worldy-ty-128,4))            while i < len(ploc):                j=0                while j <= ploc[i][2]:                    plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')                    plat_list.add(plat)                    j=j+1                print('run' + str(i) + str(ploc[i]))                i=i+1        if lvl == 2:            print("Level " + str(lvl) )        return plat_list'''Setup'''worldx = 960worldy = 720fps = 40 # frame rateani = 4  # animation cyclesclock = pygame.time.Clock()pygame.init()main = TrueBLUE  = (25,25,200)BLACK = (23,23,23 )WHITE = (254,254,254)ALPHA = (0,255,0)world = pygame.display.set_mode([worldx,worldy])backdrop = pygame.image.load(os.path.join('images','stage.png')).convert()backdropbox = world.get_rect()player = Player() # spawn playerplayer.rect.x = 0player.rect.y = 0player_list = pygame.sprite.Group()player_list.add(player)steps = 10forwardx = 600backwardx = 230eloc = []eloc = [200,20]gloc = []#gloc = [0,630,64,630,128,630,192,630,256,630,320,630,384,630]tx = 64 #tile sizety = 64 #tile sizei=0while i <= (worldx/tx)+tx:    gloc.append(i*tx)    i=i+1enemy_list = Level.bad( 1, eloc )ground_list = Level.ground( 1,gloc,tx,ty )plat_list = Level.platform( 1,tx,ty )'''Main loop'''while main == True:    for event in pygame.event.get():        if event.type == pygame.QUIT:            pygame.quit(); sys.exit()            main = False        if event.type == pygame.KEYDOWN:            if event.key == pygame.K_LEFT or event.key == ord('a'):                print("LEFT")                player.control(-steps,0)            if event.key == pygame.K_RIGHT or event.key == ord('d'):                print("RIGHT")                player.control(steps,0)            if event.key == pygame.K_UP or event.key == ord('w'):                print('jump')        if event.type == pygame.KEYUP:            if event.key == pygame.K_LEFT or event.key == ord('a'):                player.control(steps,0)            if event.key == pygame.K_RIGHT or event.key == ord('d'):                player.control(-steps,0)            if event.key == pygame.K_UP or event.key == ord('w'):                player.jump(plat_list)            if event.key == ord('q'):                pygame.quit()                sys.exit()                main = False    # scroll the world forward    if player.rect.x >= forwardx:        scroll = player.rect.x - forwardx        player.rect.x = forwardx        for p in plat_list:            p.rect.x -= scroll        for e in enemy_list:            e.rect.x -= scroll                   # scroll the world backward    if player.rect.x <= backwardx:        scroll = backwardx - player.rect.x        player.rect.x = backwardx        for p in plat_list:            p.rect.x += scroll        for e in enemy_list:            e.rect.x += scroll    world.blit(backdrop, backdropbox)    player.gravity() # check gravity    player.update()    player_list.draw(world) #refresh player position    enemy_list.draw(world)  # refresh enemies    ground_list.draw(world)  # refresh enemies    plat_list.draw(world)   # refresh platforms    for e in enemy_list:        e.move()    pygame.display.flip()    clock.tick(fps)