溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么在Python做的游戲中添加投擲機制

發(fā)布時間:2021-07-20 11:54:14 來源:億速云 閱讀:146 作者:chen 欄目:編程語言

本篇內(nèi)容主要講解“怎么在Python做的游戲中添加投擲機制”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“怎么在Python做的游戲中添加投擲機制”吧!

怎么在Python做的游戲中添加投擲機制

四處奔跑躲避敵人是一回事,反擊敵人是另一回事。學(xué)習(xí)如何在這系列的第十二篇文章中在 Pygame 中創(chuàng)建平臺游戲。

這是仍在進行中的關(guān)于使用 Pygame 模塊在 Python 3 中創(chuàng)建電腦游戲的第十二部分。先前的文章是:

  1. 通過構(gòu)建一個簡單的擲骰子游戲去學(xué)習(xí)怎么用 Python 編程

  2. 使用 Python 和 Pygame 模塊構(gòu)建一個游戲框架

  3. 如何在你的 Python 游戲中添加一個玩家

  4. 用 Pygame 使你的游戲角色移動起來

  5. 如何向你的 Python 游戲中添加一個敵人

  6. 在 Pygame 游戲中放置平臺

  7. 在你的 Python 游戲中模擬引力

  8. 為你的 Python 平臺類游戲添加跳躍功能

  9. 使你的 Python 游戲玩家能夠向前和向后跑

  10. 在你的 Python 平臺類游戲中放一些獎勵

  11. 添加計分到你的 Python 游戲

我的上一篇文章本來是這一系列文章的最后一篇,它鼓勵你為這個游戲編寫自己的附加程序。你們很多人都這么做了!我收到了一些電子郵件,要求幫助我還沒有涵蓋的常用機制:戰(zhàn)斗。畢竟,跳起來躲避壞人是一回事,但是有時候讓他們走開是一件非常令人滿意的事。在電腦游戲中向你的敵人投擲一些物品是很常見的,不管是一個火球、一支箭、一道閃電,還是其它適合游戲的東西。

與迄今為止你在這個系列中為你的平臺游戲編程的任何東西不同,可投擲物品有一個生存時間。在你投擲一個物品后,它會如期在移動一段距離后消失。如果它是一支箭或其它類似的東西,它可能會在通過屏幕的邊緣時而消失。如果它是一個火球或一道閃電,它可能會在一段時間后熄滅。

這意味著每次生成一個可投擲的物品時,也必須生成一個獨特的衡量其生存時間的標(biāo)準(zhǔn)。為了介紹這個概念,這篇文章演示如何一次只投擲一個物品。(換句話說,每次僅存在一個投擲物品)。  一方面,這是一個游戲的限制條件,但另一方面,它卻是游戲本身的運行機制。你的玩家不能每次同時投擲 50  個火球,因為每次僅允許一個投擲物品,所以當(dāng)你的玩家釋放一個火球來嘗試擊中一名敵人就成為了一項挑戰(zhàn)。而在幕后,這也使你的代碼保持簡單。

如果你想啟用每次投擲多個項目,在完成這篇教程后,通過學(xué)習(xí)這篇教程所獲取的知識來挑戰(zhàn)你自己。

創(chuàng)建 Throwable 類

如果你跟隨學(xué)習(xí)這系列的其它文章,那么你應(yīng)該熟悉在屏幕上生成一個新的對象基礎(chǔ)的 __init__ 函數(shù)。這和你用來生成你的 玩家 和 敵人 的函數(shù)是一樣的。這里是生成一個 throwable 對象的 __init__ 函數(shù)來:

class Throwable(pygame.sprite.Sprite):    """    生成一個 throwable 對象    """    def __init__(self, x, y, img, throw):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load(os.path.join('images',img))        self.image.convert_alpha()        self.image.set_colorkey(ALPHA)        self.rect   = self.image.get_rect()        self.rect.x = x        self.rect.y = y        self.firing = throw

同你的 Player 類或 Enemy 類的 __init__ 函數(shù)相比,這個函數(shù)的主要區(qū)別是,它有一個 self.firing 變量。這個變量保持跟蹤一個投擲的物品是否在當(dāng)前屏幕上活動,因此當(dāng)一個 throwable 對象創(chuàng)建時,將變量設(shè)置為 1 的合乎情理的。

判斷存活時間

接下來,就像使用 Player 和 Enemy 一樣,你需要一個 update 函數(shù),以便投擲的物品在瞄準(zhǔn)敵人拋向空中時,它會自己移動。

測定一個投擲的物品存活時間的最簡單方法是偵測它何時離開屏幕。你需要監(jiān)視的屏幕邊緣取決于你投擲的物品的物理特性。

  • 如果你的玩家正在投擲的物品是沿著水平軸快速移動的,像一只弩箭或箭或一股非常快的魔法力量,而你想監(jiān)視你游戲屏幕的水平軸極限。這可以通過 worldx 定義。

  • 如果你的玩家正在投擲的物品是沿著垂直方向或同時沿著水平方向和垂直方向移動的,那么你必須監(jiān)視你游戲屏幕的垂直軸極限。這可以通過 worldy 定義。

這個示例假設(shè)你投擲的物品向前移動一點并最終落到地面上。不過,投擲的物品不會從地面上反彈起來,而是繼續(xù)掉落出屏幕。你可以嘗試不同的設(shè)置來看看什么最適合你的游戲:

    def update(self,worldy):        '''        投擲物理學(xué)        '''        if self.rect.y < worldy:   #垂直軸             self.rect.x  += 15     #它向前移動的速度有多快            self.rect.y  += 5      #它掉落的速度有多快        else:            self.kill()            #移除投擲對象            self.firing = 0        #解除火力發(fā)射

為使你的投擲物品移動地更快,增加 self.rect 的動量值。

如果投擲物品不在屏幕上,那么該物品將被銷毀,以及釋放其所占用的寄存器。另外,self.firing 將被設(shè)置回 0 以允許你的玩家來進行另一次射擊。

設(shè)置你的投擲對象

就像使用你的玩家和敵人一樣,你必須在你的設(shè)置部分中創(chuàng)建一個精靈組來保持投擲對象。

此外,你必須創(chuàng)建一個非活動的投擲對象來供開始的游戲使用。如果在游戲開始時卻沒有一個投擲對象,那么玩家在第一次嘗試投擲一柄武器時,投擲將失敗。

這個示例假設(shè)你的玩家使用一個火球作為開始的武器,因此,每一個投擲實例都是由 fire 變量指派的。在后面的關(guān)卡中,當(dāng)玩家獲取新的技能時,你可以使用相同的 Throwable 類來引入一個新的變量以使用一張不同的圖像。

在這代碼塊中,前兩行已經(jīng)在你的代碼中,因此不要重新鍵入它們:

player_list = pygame.sprite.Group() #上下文player_list.add(player)             #上下文fire = Throwable(player.rect.x,player.rect.y,'fire.png',0)firepower = pygame.sprite.Group()

注意,每一個投擲對象的起始位置都是和玩家所在的位置相同。這使得它看起來像是投擲對象來自玩家。在第一個火球生成時,使用 0 來顯示 self.firing 是可用的。

在主循環(huán)中獲取投擲行為

沒有在主循環(huán)中出現(xiàn)的代碼不會在游戲中使用,因此你需要在你的主循環(huán)中添加一些東西,以便能在你的游戲世界中獲取投擲對象。

首先,添加玩家控制。當(dāng)前,你沒有火力觸發(fā)器。在鍵盤上的按鍵是有兩種狀態(tài)的:釋放的按鍵,按下的按鍵。為了移動,你要使用這兩種狀態(tài):按下按鍵來啟動玩家移動,釋放按鍵來停止玩家移動。開火僅需要一個信號。你使用哪個按鍵事件(按鍵按下或按鍵釋放)來觸發(fā)你的投擲對象取決于你的品味。

在這個代碼語句塊中,前兩行是用于上下文的:

            if event.key == pygame.K_UP or event.key == ord('w'):                player.jump(platform_list)            if event.key == pygame.K_SPACE:                if not fire.firing:                    fire = Throwable(player.rect.x,player.rect.y,'fire.png',1)                    firepower.add(fire)

與你在設(shè)置部分創(chuàng)建的火球不同,你使用一個 1 來設(shè)置 self.firing 為不可用。

最后,你必須更新和繪制你的投擲物品。這個順序很重要,因此把這段代碼放置到你現(xiàn)有的 enemy.move 和 player_list.draw 的代碼行之間:

    enemy.move()  # 上下文     if fire.firing:        fire.update(worldy)        firepower.draw(world)    player_list.draw(screen)  # 上下文    enemy_list.draw(screen)   # 上下文

注意,這些更新僅在 self.firing 變量被設(shè)置為 1 時執(zhí)行。如果它被設(shè)置為 0 ,那么 fire.firing 就不為 true,接下來就跳過更新。如果你嘗試做上述這些更新,不管怎樣,你的游戲都會崩潰,因為在游戲中將不會更新或繪制一個 fire 對象。

啟動你的游戲,嘗試挑戰(zhàn)你的武器。

檢測碰撞

如果你玩使用了新投擲技巧的游戲,你可能會注意到,你可以投擲對象,但是它卻不會對你的敵人有任何影響。

原因是你的敵人沒有被查到碰撞事故。一名敵人可能會被你的投擲物品所擊中,但是敵人卻從來不知道被擊中了。

你已經(jīng)在你的 Player 類中完成了碰撞檢測,這非常類似。在你的 Enemy 類中,添加一個新的 update 函數(shù):

    def update(self,firepower, enemy_list):        """        檢測火力碰撞        """        fire_hit_list = pygame.sprite.spritecollide(self,firepower,False)        for fire in fire_hit_list:            enemy_list.remove(self)

代碼很簡單。每個敵人對象都檢查并看看它自己是否被 firepower 精靈組的成員所擊中。如果它被擊中,那么敵人就會從敵人組中移除和消失。

為集成這些功能到你的游戲之中,在主循環(huán)中調(diào)用位于新觸發(fā)語句塊中的函數(shù):

    if fire.firing:                             # 上下文        fire.update(worldy)                     # 上下文        firepower.draw(screen)                  # 上下文        enemy_list.update(firepower,enemy_list) # 更新敵人

你現(xiàn)在可以嘗試一下你的游戲了,大多數(shù)的事情都如預(yù)期般的那樣工作。不過,這里仍然有一個問題,那就是投擲的方向。

更改投擲機制的方向

當(dāng)前,你英雄的火球只會向右移動。這是因為 Throwable 類的 update 函數(shù)將像素添加到火球的位置,在 Pygame 中,在 X 軸上一個較大的數(shù)字意味著向屏幕的右側(cè)移動。當(dāng)你的英雄轉(zhuǎn)向另一個方向時,你可能希望它投擲的火球也拋向左側(cè)。

到目前為止,你已經(jīng)知道如何實現(xiàn)這一點,至少在技術(shù)上是這樣的。然而,最簡單的解決方案卻是使用一個變量,在一定程度上對你來說可能是一種新的方法。一般來說,你可以“設(shè)置一個標(biāo)記”(有時也被稱為“翻轉(zhuǎn)一個位”)來標(biāo)明你的英雄所面向的方向。在你做完后,你就可以檢查這個變量來得知火球是向左移動還是向右移動。

首先,在你的 Player 類中創(chuàng)建一個新的變量來代表你的游戲所面向的方向。因為我的游戲天然地面向右側(cè),由此我把面向右側(cè)作為默認(rèn)值:

        self.score = 0        self.facing_right = True  # 添加這行        self.is_jumping = True

當(dāng)這個變量是 True 時,你的英雄精靈是面向右側(cè)的。當(dāng)玩家每次更改英雄的方向時,變量也必須重新設(shè)置,因此,在你的主循環(huán)中相關(guān)的 keyup 事件中這樣做:

        if event.type == pygame.KEYUP:            if event.key == pygame.K_LEFT or event.key == ord('a'):                player.control(steps, 0)                player.facing_right = False  # 添加這行            if event.key == pygame.K_RIGHT or event.key == ord('d'):                player.control(-steps, 0)                player.facing_right = True   # 添加這行

最后,更改你的 Throwable 類的 update 函數(shù),以檢測英雄是否面向右側(cè),并恰當(dāng)?shù)靥砑踊驕p去來自火球位置的像素:

        if self.rect.y < worldy:            if player.facing_right:                self.rect.x += 15            else:                self.rect.x -= 15            self.rect.y += 5

再次嘗試你的游戲,清除掉你游戲世界中的一些壞人。

怎么在Python做的游戲中添加投擲機制

Python 平臺類使用投擲能力

作為一項額外的挑戰(zhàn),當(dāng)徹底打敗敵人時,嘗試增加你玩家的得分。

完整的代碼

#!/usr/bin/env python3# 作者: Seth Kenlon # GPLv3# This program is free software: you can redistribute it and/or# modify it under the terms of the GNU General Public License as# published by the Free Software Foundation, either version 3 of the# License, or (at your option) any later version.## This program is distributed in the hope that it will be useful, but# WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU# General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program.  If not, see <[http://www.gnu.org/licenses/>][17]. import pygameimport pygame.freetypeimport sysimport os '''變量''' worldx = 960worldy = 720fps = 40ani = 4world = pygame.display.set_mode([worldx, worldy])forwardx  = 600backwardx = 120 BLUE = (80, 80, 155)BLACK = (23, 23, 23)WHITE = (254, 254, 254)ALPHA = (0, 255, 0) tx = 64ty = 64 font_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "fonts", "amazdoom.ttf")font_size = txpygame.freetype.init()myfont = pygame.freetype.Font(font_path, font_size) '''對象''' def stats(score, health):    myfont.render_to(world, (4, 4), "Score:"+str(score), BLUE, None, size=64)    myfont.render_to(world, (4, 72), "Health:"+str(health), BLUE, None, size=64) class Throwable(pygame.sprite.Sprite):    """    生成一個投擲的對象    """    def __init__(self, x, y, img, throw):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load(os.path.join('images', img))        self.image.convert_alpha()        self.image.set_colorkey(ALPHA)        self.rect = self.image.get_rect()        self.rect.x = x        self.rect.y = y        self.firing = throw     def update(self, worldy):        '''        投擲物理學(xué)        '''        if self.rect.y < worldy:            if player.facing_right:                self.rect.x += 15            else:                self.rect.x -= 15            self.rect.y += 5        else:            self.kill()            self.firing = 0 # x 位置, y 位置, img 寬度, img 高度, img 文件class Platform(pygame.sprite.Sprite):    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.image.set_colorkey(ALPHA)        self.rect = self.image.get_rect()        self.rect.y = yloc        self.rect.x = xloc class Player(pygame.sprite.Sprite):    """    生成一名玩家    """     def __init__(self):        pygame.sprite.Sprite.__init__(self)        self.movex = 0        self.movey = 0        self.frame = 0        self.health = 10        self.damage = 0        self.score = 0        self.facing_right = True        self.is_jumping = True        self.is_falling = True        self.images = []        for i in range(1, 5):            img = pygame.image.load(os.path.join('images', 'walk' + 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 gravity(self):        if self.is_jumping:            self.movey += 3.2     def control(self, x, y):        """        控制玩家移動        """        self.movex += x     def jump(self):        if self.is_jumping is False:            self.is_falling = False            self.is_jumping = True     def update(self):        """        更新精靈位置        """         # 向左移動        if self.movex < 0:            self.is_jumping = True            self.frame += 1            if self.frame > 3 * ani:                self.frame = 0            self.image = pygame.transform.flip(self.images[self.frame // ani], True, False)         # 向右移動        if self.movex > 0:            self.is_jumping = True            self.frame += 1            if self.frame > 3 * ani:                self.frame = 0            self.image = self.images[self.frame // ani]         # 碰撞        enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)        if self.damage == 0:            for enemy in enemy_hit_list:                if not self.rect.contains(enemy):                    self.damage = self.rect.colliderect(enemy)        if self.damage == 1:            idx = self.rect.collidelist(enemy_hit_list)            if idx == -1:                self.damage = 0   # 設(shè)置傷害回 0                self.health -= 1  # 減去 1 單位健康度         ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)        for g in ground_hit_list:            self.movey = 0            self.rect.bottom = g.rect.top            self.is_jumping = False  # 停止跳躍         # 掉落世界        if self.rect.y > worldy:            self.health -=1            print(self.health)            self.rect.x = tx            self.rect.y = ty         plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)        for p in plat_hit_list:            self.is_jumping = False  # 停止跳躍            self.movey = 0            if self.rect.bottom <= p.rect.bottom:               self.rect.bottom = p.rect.top            else:               self.movey += 3.2         if self.is_jumping and self.is_falling is False:            self.is_falling = True            self.movey -= 33  # 跳躍多高         loot_hit_list = pygame.sprite.spritecollide(self, loot_list, False)        for loot in loot_hit_list:            loot_list.remove(loot)            self.score += 1            print(self.score)         plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)         self.rect.x += self.movex        self.rect.y += self.movey class Enemy(pygame.sprite.Sprite):    """    生成一名敵人    """     def __init__(self, x, y, img):        pygame.sprite.Sprite.__init__(self)        self.image = pygame.image.load(os.path.join('images', img))        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):        """        敵人移動        """        distance = 80        speed = 8         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     def update(self, firepower, enemy_list):        """        檢測火力碰撞        """        fire_hit_list = pygame.sprite.spritecollide(self, firepower, False)        for fire in fire_hit_list:            enemy_list.remove(self) class Level:    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, 'tile-ground.png')                ground_list.add(ground)                i = i + 1         if lvl == 2:            print("Level " + str(lvl))         return ground_list     def bad(lvl, eloc):        if lvl == 1:            enemy = Enemy(eloc[0], eloc[1], 'enemy.png')            enemy_list = pygame.sprite.Group()            enemy_list.add(enemy)        if lvl == 2:            print("Level " + str(lvl))         return enemy_list     # x 位置, y 位置, img 寬度, img 高度, img 文件    def platform(lvl, tx, ty):        plat_list = pygame.sprite.Group()        ploc = []        i = 0        if lvl == 1:            ploc.append((200, worldy - ty - 128, 3))            ploc.append((300, worldy - ty - 256, 3))            ploc.append((550, worldy - ty - 128, 4))            while i &lt; len(ploc):                j = 0                while j <= ploc[i][2]:                    plat = Platform((ploc[i][0] + (j * tx)), ploc[i][1], tx, ty, 'tile.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     def loot(lvl):        if lvl == 1:            loot_list = pygame.sprite.Group()            loot = Platform(tx*5, ty*5, tx, ty, 'loot_1.png')            loot_list.add(loot)         if lvl == 2:            print(lvl)         return loot_list '''Setup 部分''' backdrop = pygame.image.load(os.path.join('images', 'stage.png'))clock = pygame.time.Clock()pygame.init()backdropbox = world.get_rect()main = True player = Player()         # 生成玩家player.rect.x = 0         # 轉(zhuǎn)到 xplayer.rect.y = 30        # 轉(zhuǎn)到 yplayer_list = pygame.sprite.Group()player_list.add(player)steps = 10fire = Throwable(player.rect.x, player.rect.y, 'fire.png', 0)firepower = pygame.sprite.Group() eloc = []eloc = [300, worldy-ty-80]enemy_list = Level.bad(1, eloc)gloc = [] i = 0while i &lt;= (worldx / tx) + tx:    gloc.append(i * tx)    i = i + 1 ground_list = Level.ground(1, gloc, tx, ty)plat_list = Level.platform(1, tx, ty)enemy_list = Level.bad( 1, eloc )loot_list = Level.loot(1) '''主循環(huán)''' while main:    for event in pygame.event.get():        if event.type == pygame.QUIT:            pygame.quit()            try:                sys.exit()            finally:                main = False         if event.type == pygame.KEYDOWN:            if event.key == ord('q'):                pygame.quit()                try:                    sys.exit()                finally:                    main = False            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()         if event.type == pygame.KEYUP:            if event.key == pygame.K_LEFT or event.key == ord('a'):                player.control(steps, 0)                player.facing_right = False            if event.key == pygame.K_RIGHT or event.key == ord('d'):                player.control(-steps, 0)                player.facing_right = True            if event.key == pygame.K_SPACE:                if not fire.firing:                    fire = Throwable(player.rect.x, player.rect.y, 'fire.png', 1)                    firepower.add(fire)     # 向向滾動世界    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        for l in loot_list:            l.rect.x -= scroll     # 向后滾動世界    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        for l in loot_list:            l.rect.x += scroll     world.blit(backdrop, backdropbox)    player.update()    player.gravity()    player_list.draw(world)    if fire.firing:        fire.update(worldy)        firepower.draw(world)    enemy_list.draw(world)    enemy_list.update(firepower, enemy_list)    loot_list.draw(world)    ground_list.draw(world)    plat_list.draw(world)    for e in enemy_list:        e.move()    stats(player.score, player.health)    pygame.display.flip()    clock.tick(fps)

到此,相信大家對“怎么在Python做的游戲中添加投擲機制”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI