1 項目簡介
?? Hi,各位同學好呀,這里是L學長!
??今天向大家分享一個今年(2022)最新完成的畢業(yè)設(shè)計項目作品
**python小游戲畢設(shè) 炸彈人小游戲設(shè)計與實現(xiàn) **
?? 學長根據(jù)實現(xiàn)的難度和等級對項目進行評分(最低0分,滿分5分)
-
難度系數(shù):3分
-
工作量:3分
-
創(chuàng)新點:4分
-
項目獲取:https://gitee.com/sinonfin/system-sharing
1 游戲介紹
大家小時候一定在紅白機上玩過炸彈人這款小游戲吧,《炸彈人》是HUDSON出品的一款A(yù)CT類型游戲,經(jīng)典的第一作登陸在FC版本,游戲于1983年發(fā)行。游戲具體操作是一個機器人放置炸彈來炸死敵人,但也可以炸死自己,還有些增強威力與技能道具增加了游戲的可玩性。
今天我們用pygame做一個炸彈人小游戲,游戲規(guī)則如下:
玩家通過↑↓←→鍵控制角色zelda(綠色)行動,當玩家按下空格鍵時,則可以在當前位置放置炸彈。其他角色(dk和batman)則由電腦控制進行隨機行動。所有角色被炸彈產(chǎn)生的火焰灼燒時(包括自己放置的炸彈),都將損失一定生命值;所有角色吃到水果時,均可恢復(fù)一定數(shù)值的生命值。另外,墻可以阻止炸彈產(chǎn)生的火焰進一步擴散。
當我方角色生命值為0時,游戲失?。划旊娔X方所有角色生命值為0時,游戲勝利,進入下一關(guān)。
2 實現(xiàn)效果
3 Pygame介紹
簡介
Pygame是一系列專門為編寫電子游戲而設(shè)計的Python模塊(modules)。Pygame在已經(jīng)非常優(yōu)秀的SDL庫的基礎(chǔ)上增加了許多功能。這讓你能夠用Python語言編寫出豐富多彩的游戲程序。
Pygame可移植性高,幾乎能在任何平臺和操作系統(tǒng)上運行。
Pygame已經(jīng)被下載過數(shù)百萬次。
Pygame免費開源。它在LGPL許可證(Lesser General Public License,GNU寬通用公共許可證)下發(fā)行。使用Pygame,你可以創(chuàng)造出免費開源,可共享,或者商業(yè)化的游戲。詳情請見LGPL許可證。
優(yōu)點
-
能夠輕松使用多核CPU(multi core CPUs) :如今雙核CPU很常用,8核CPU在桌面系統(tǒng)中也很便宜,而利用好多核系統(tǒng),能讓你在你的游戲中實現(xiàn)更多東西。特定的pygame函數(shù)能夠釋放令人生畏的python GIL(全局解釋器鎖),這幾乎是你用C語言才能做的事。
-
核心函數(shù)用最優(yōu)化的C語言或匯編語言編寫:C語言代碼通常比Python代碼運行速度快10-20倍。而匯編語言編寫的代碼(assembly code)比Python甚至快到100多倍。
-
安裝便捷:一般僅需包管理程序或二進制系統(tǒng)程序便能安裝。
-
真正地可移植:支持Linux (主要發(fā)行版), Windows (95, 98, ME, 2000, XP, Vista, 64-bit Windows,), Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX等操作系統(tǒng).也能支持AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS and OS/2,但是還沒有受到官方認可。你也可以在手持設(shè)備,游戲控制臺, One Laptop Per Child (OLPC) computer項目的電腦等設(shè)備中使用pygame.
-
用法簡單:無論是小孩子還是大人都能學會用pygame來制作射擊類游戲。
-
很多Pygame游戲已發(fā)行:其中包括很多游戲大賽入圍作品、非常受歡迎的開源可分享的游戲。
-
由你來控制主循環(huán):由你來調(diào)用pygame的函數(shù),pygame的函數(shù)并不需要調(diào)用你的函數(shù)。當你同時還在使用其他庫來編寫各種各種的程序時,這能夠為你提供極大的掌控權(quán)。
-
不需要GUI就能使用所有函數(shù):僅在命令行中,你就可以使用pygame的某些函數(shù)來處理圖片,獲取游戲桿輸入,播放音樂……
-
對bug反應(yīng)迅速:很多bug在被上報的1小時內(nèi)就能被我們修復(fù)。雖然有時候我們確實會卡在某一個bug上很久,但大多數(shù)時候我們都是很不錯的bug修復(fù)者。如今bug的上報已經(jīng)很少了,因為許多bug早已被我們修復(fù)。
-
代碼量少:pygame并沒有數(shù)以萬計的也許你永遠用不到的冗雜代碼。pygame的核心代碼一直保持著簡潔特點,其他附加物諸如GUI庫等,都是在核心代碼之外單獨設(shè)計研發(fā)的。
-
模塊化:你可以單獨使用pygame的某個模塊。想要換著使用一個別的聲音處理庫?沒問題。pygame的很多核心模塊支持獨立初始化與使用。
最小開發(fā)框架
import pygame,sys #sys是python的標準庫,提供Python運行時環(huán)境變量的操控
pygame.init() #內(nèi)部各功能模塊進行初始化創(chuàng)建及變量設(shè)置,默認調(diào)用
size = width,height = 800,600 #設(shè)置游戲窗口大小,分別是寬度和高度
screen = pygame.display.set_mode(size) #初始化顯示窗口
pygame.display.set_caption("小游戲程序") #設(shè)置顯示窗口的標題內(nèi)容,是一個字符串類型
while True: #無限循環(huán),直到Python運行時退出結(jié)束
for event in pygame.event.get(): #從Pygame的事件隊列中取出事件,并從隊列中刪除該事件
if event.type == pygame.QUIT: #獲得事件類型,并逐類響應(yīng)
sys.exit() #用于退出結(jié)束游戲并退出
pygame.display.update() #對顯示窗口進行更新,默認窗口全部重繪
代碼執(zhí)行流程
4 具體實現(xiàn)
4.1 環(huán)境配置
- Python版本:3.6.4
- 相關(guān)模塊:
- pygame模塊;
- 以及一些Python自帶的模塊。
4.2 創(chuàng)建游戲類
首先,我們來明確一下該游戲包含哪些游戲精靈類:
- 炸彈類
- 角色類
- 墻類
- 背景類
- 水果類
4.3 墻和背景類
墻類和背景類很好定義,只需要可以導入圖片,然后把圖片綁定到指定位置就行了:
'''墻類'''
class Wall(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
'''畫到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
return True
'''背景類'''
class Background(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
'''畫到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
return True
4.4 水果類
水果類定義其實也差不多,但是不同的水果可以幫助角色恢復(fù)不同數(shù)值的生命值:
'''水果類'''
class Fruit(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.kind = imagepath.split('/')[-1].split('.')[0]
if self.kind == 'banana':
self.value = 5
elif self.kind == 'cherry':
self.value = 10
else:
raise ValueError('Unknow fruit <%s>...' % self.kind)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
'''畫到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
return True
4.3 角色類
炸彈類和角色類的定義就稍稍復(fù)雜一些了。角色類需要根據(jù)玩家或者電腦的指示上下左右移動,同時可以在自己的位置上產(chǎn)生炸彈以及吃水果之后恢復(fù)一定數(shù)值的生命值:
角色類定義
'''角色類'''
class Hero(pygame.sprite.Sprite):
def __init__(self, imagepaths, coordinate, blocksize, map_parser, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.imagepaths = imagepaths
self.image = pygame.image.load(imagepaths[-1])
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
self.map_parser = map_parser
self.hero_name = kwargs.get('hero_name')
# 生命值
self.health_value = 50
# 炸彈冷卻時間
self.bomb_cooling_time = 5000
self.bomb_cooling_count = 0
# 隨機移動冷卻時間(僅AI電腦用)
self.randommove_cooling_time = 100
self.randommove_cooling_count = 0
角色類移動
'''角色移動'''
def move(self, direction):
self.__updateImage(direction)
if direction == 'left':
if self.coordinate[0]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0]-1, self.coordinate[1]]) in ['w', 'x', 'z']:
return False
self.coordinate[0] = self.coordinate[0] - 1
elif direction == 'right':
if self.coordinate[0]+1 >= self.map_parser.width or self.map_parser.getElemByCoordinate([self.coordinate[0]+1, self.coordinate[1]]) in ['w', 'x', 'z']:
return False
self.coordinate[0] = self.coordinate[0] + 1
elif direction == 'up':
if self.coordinate[1]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]-1]) in ['w', 'x', 'z']:
return False
self.coordinate[1] = self.coordinate[1] - 1
elif direction == 'down':
if self.coordinate[1]+1 >= self.map_parser.height or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]+1]) in ['w', 'x', 'z']:
return False
self.coordinate[1] = self.coordinate[1] + 1
else:
raise ValueError('Unknow direction <%s>...' % direction)
self.rect.left, self.rect.top = self.coordinate[0] * self.blocksize, self.coordinate[1] * self.blocksize
return True
AI電腦隨機移動
'''隨機行動(AI電腦用)'''
def randomAction(self, dt):
# 冷卻倒計時
if self.randommove_cooling_count > 0:
self.randommove_cooling_count -= dt
action = random.choice(['left', 'left', 'right', 'right', 'up', 'up', 'down', 'down', 'dropbomb'])
flag = False
if action in ['left', 'right', 'up', 'down']:
if self.randommove_cooling_count <= 0:
flag = True
self.move(action)
self.randommove_cooling_count = self.randommove_cooling_time
elif action in ['dropbomb']:
if self.bomb_cooling_count <= 0:
flag = True
self.bomb_cooling_count = self.bomb_cooling_time
return action, flag
生成炸彈、吃水果、角色朝向
'''生成炸彈'''
def generateBomb(self, imagepath, digitalcolor, explode_imagepath):
return Bomb(imagepath=imagepath, coordinate=copy.deepcopy(self.coordinate), blocksize=self.blocksize, digitalcolor=digitalcolor, explode_imagepath=explode_imagepath)
'''畫到屏幕上'''
def draw(self, screen, dt):
# 冷卻倒計時
if self.bomb_cooling_count > 0:
self.bomb_cooling_count -= dt
screen.blit(self.image, self.rect)
return True
'''吃水果'''
def eatFruit(self, fruit_sprite_group):
eaten_fruit = pygame.sprite.spritecollide(self, fruit_sprite_group, True, None)
for fruit in eaten_fruit:
self.health_value += fruit.value
'''更新角色朝向'''
def __updateImage(self, direction):
directions = ['left', 'right', 'up', 'down']
idx = directions.index(direction)
self.image = pygame.image.load(self.imagepaths[idx])
self.image = pygame.transform.scale(self.image, (self.blocksize, self.blocksize))
4.4 炸彈類
定義
'''炸彈類'''
class Bomb(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, digitalcolor, explode_imagepath, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.explode_imagepath = explode_imagepath
self.rect = self.image.get_rect()
# 像素位置
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
# 坐標(元素塊為單位長度)
self.coordinate = coordinate
self.blocksize = blocksize
# 爆炸倒計時
self.explode_millisecond = 6000 * 1 - 1
self.explode_second = int(self.explode_millisecond / 1000)
self.start_explode = False
# 爆炸持續(xù)時間
self.exploding_count = 1000 * 1
# 炸彈傷害能力
self.harm_value = 1
# 該炸彈是否還存在
self.is_being = True
self.font = pygame.font.SysFont('Consolas', 20)
self.digitalcolor = digitalcolor
'''畫到屏幕上'''
def draw(self, screen, dt, map_parser):
if not self.start_explode:
# 爆炸倒計時
self.explode_millisecond -= dt
self.explode_second = int(self.explode_millisecond / 1000)
if self.explode_millisecond < 0:
self.start_explode = True
screen.blit(self.image, self.rect)
text = self.font.render(str(self.explode_second), True, self.digitalcolor)
rect = text.get_rect(center=(self.rect.centerx-5, self.rect.centery+5))
screen.blit(text, rect)
return False
else:
# 爆炸持續(xù)倒計時
self.exploding_count -= dt
if self.exploding_count > 0:
return self.__explode(screen, map_parser)
else:
self.is_being = False
return False
爆炸效果
'''爆炸效果'''
def __explode(self, screen, map_parser):
explode_area = self.__calcExplodeArea(map_parser.instances_list)
for each in explode_area:
image = pygame.image.load(self.explode_imagepath)
image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
rect = image.get_rect()
rect.left, rect.top = each[0] * self.blocksize, each[1] * self.blocksize
screen.blit(image, rect)
return explode_area
爆炸區(qū)域
'''計算爆炸區(qū)域'''
def __calcExplodeArea(self, instances_list):
explode_area = []
# 區(qū)域計算規(guī)則為墻可以阻止爆炸擴散, 且爆炸范圍僅在游戲地圖范圍內(nèi)
for ymin in range(self.coordinate[1], self.coordinate[1]-5, -1):
if ymin < 0 or instances_list[ymin][self.coordinate[0]] in ['w', 'x', 'z']:
break
explode_area.append([self.coordinate[0], ymin])
for ymax in range(self.coordinate[1]+1, self.coordinate[1]+5):
if ymax >= len(instances_list) or instances_list[ymax][self.coordinate[0]] in ['w', 'x', 'z']:
break
explode_area.append([self.coordinate[0], ymax])
for xmin in range(self.coordinate[0], self.coordinate[0]-5, -1):
if xmin < 0 or instances_list[self.coordinate[1]][xmin] in ['w', 'x', 'z']:
break
explode_area.append([xmin, self.coordinate[1]])
for xmax in range(self.coordinate[0]+1, self.coordinate[0]+5):
if xmax >= len(instances_list[0]) or instances_list[self.coordinate[1]][xmax] in ['w', 'x', 'z']:
break
explode_area.append([xmax, self.coordinate[1]])
return explode_area
4.5 地圖設(shè)計
通過一個地圖解析類來解析.map文件,這樣每次切換關(guān)卡時只需要重新導入一個新的.map文件就行了,同時這樣也方便游戲后續(xù)進行擴展:
'''.map文件解析器'''
class mapParser():
def __init__(self, mapfilepath, bg_paths, wall_paths, blocksize, **kwargs):
self.instances_list = self.__parse(mapfilepath)
self.bg_paths = bg_paths
self.wall_paths = wall_paths
self.blocksize = blocksize
self.height = len(self.instances_list)
self.width = len(self.instances_list[0])
self.screen_size = (blocksize * self.width, blocksize * self.height)
'''地圖畫到屏幕上'''
def draw(self, screen):
for j in range(self.height):
for i in range(self.width):
instance = self.instances_list[j][i]
if instance == 'w':
elem = Wall(self.wall_paths[0], [i, j], self.blocksize)
elif instance == 'x':
elem = Wall(self.wall_paths[1], [i, j], self.blocksize)
elif instance == 'z':
elem = Wall(self.wall_paths[2], [i, j], self.blocksize)
elif instance == '0':
elem = Background(self.bg_paths[0], [i, j], self.blocksize)
elif instance == '1':
elem = Background(self.bg_paths[1], [i, j], self.blocksize)
elif instance == '2':
elem = Background(self.bg_paths[2], [i, j], self.blocksize)
else:
raise ValueError('instance parse error in mapParser.draw...')
elem.draw(screen)
'''隨機獲取一個空地'''
def randomGetSpace(self, used_spaces=None):
while True:
i = random.randint(0, self.width-1)
j = random.randint(0, self.height-1)
coordinate = [i, j]
if used_spaces and coordinate in used_spaces:
continue
instance = self.instances_list[j][i]
if instance in ['0', '1', '2']:
break
return coordinate
'''根據(jù)坐標獲取元素類型'''
def getElemByCoordinate(self, coordinate):
return self.instances_list[coordinate[1]][coordinate[0]]
'''解析.map文件'''
def __parse(self, mapfilepath):
instances_list = []
with open(mapfilepath) as f:
for line in f.readlines():
instances_line_list = []
for c in line:
if c in ['w', 'x', 'z', '0', '1', '2']:
instances_line_list.append(c)
instances_list.append(instances_line_list)
return instances_list
4.6 游戲主循環(huán)
最后,做完準備工作,只差游戲主循環(huán)了。
邏輯很簡單,就是初始化之后導入關(guān)卡地圖開始游戲,結(jié)束一關(guān)之后,判斷是游戲勝利還是游戲失敗,游戲勝利的話就進入下一關(guān),否則就退出主循環(huán),讓玩家選擇是否重新開始游戲。文章來源:http://www.zghlxwxcb.cn/news/detail-828286.html
'''游戲主程序'''
def main(cfg):
# 初始化
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(cfg.BGMPATH)
pygame.mixer.music.play(-1, 0.0)
screen = pygame.display.set_mode(cfg.SCREENSIZE)
pygame.display.set_caption('Bomber Man - 微信公眾號: Charles的皮卡丘')
# 開始界面
Interface(screen, cfg, mode='game_start')
# 游戲主循環(huán)
font = pygame.font.SysFont('Consolas', 15)
for gamemap_path in cfg.GAMEMAPPATHS:
# -地圖
map_parser = mapParser(gamemap_path, bg_paths=cfg.BACKGROUNDPATHS, wall_paths=cfg.WALLPATHS, blocksize=cfg.BLOCKSIZE)
# -水果
fruit_sprite_group = pygame.sprite.Group()
used_spaces = []
for i in range(5):
coordinate = map_parser.randomGetSpace(used_spaces)
used_spaces.append(coordinate)
fruit_sprite_group.add(Fruit(random.choice(cfg.FRUITPATHS), coordinate=coordinate, blocksize=cfg.BLOCKSIZE))
# -我方Hero
coordinate = map_parser.randomGetSpace(used_spaces)
used_spaces.append(coordinate)
ourhero = Hero(imagepaths=cfg.HEROZELDAPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='ZELDA')
# -電腦Hero
aihero_sprite_group = pygame.sprite.Group()
coordinate = map_parser.randomGetSpace(used_spaces)
aihero_sprite_group.add(Hero(imagepaths=cfg.HEROBATMANPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='BATMAN'))
used_spaces.append(coordinate)
coordinate = map_parser.randomGetSpace(used_spaces)
aihero_sprite_group.add(Hero(imagepaths=cfg.HERODKPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='DK'))
used_spaces.append(coordinate)
# -炸彈bomb
bomb_sprite_group = pygame.sprite.Group()
# -用于判斷游戲勝利或者失敗的flag
is_win_flag = False
# -主循環(huán)
screen = pygame.display.set_mode(map_parser.screen_size)
clock = pygame.time.Clock()
while True:
dt = clock.tick(cfg.FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(-1)
# --↑↓←→鍵控制上下左右, 空格鍵丟炸彈
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
ourhero.move('up')
elif event.key == pygame.K_DOWN:
ourhero.move('down')
elif event.key == pygame.K_LEFT:
ourhero.move('left')
elif event.key == pygame.K_RIGHT:
ourhero.move('right')
elif event.key == pygame.K_SPACE:
if ourhero.bomb_cooling_count <= 0:
bomb_sprite_group.add(ourhero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))
screen.fill(cfg.WHITE)
# --電腦Hero隨機行動
for hero in aihero_sprite_group:
action, flag = hero.randomAction(dt)
if flag and action == 'dropbomb':
bomb_sprite_group.add(hero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))
# --吃到水果加生命值(只要是Hero, 都能加)
ourhero.eatFruit(fruit_sprite_group)
for hero in aihero_sprite_group:
hero.eatFruit(fruit_sprite_group)
# --游戲元素都綁定到屏幕上
map_parser.draw(screen)
for bomb in bomb_sprite_group:
if not bomb.is_being:
bomb_sprite_group.remove(bomb)
explode_area = bomb.draw(screen, dt, map_parser)
if explode_area:
# --爆炸火焰范圍內(nèi)的Hero生命值將持續(xù)下降
if ourhero.coordinate in explode_area:
ourhero.health_value -= bomb.harm_value
for hero in aihero_sprite_group:
if hero.coordinate in explode_area:
hero.health_value -= bomb.harm_value
fruit_sprite_group.draw(screen)
for hero in aihero_sprite_group:
hero.draw(screen, dt)
ourhero.draw(screen, dt)
# --左上角顯示生命值
pos_x = showText(screen, font, text=ourhero.hero_name+'(our):'+str(ourhero.health_value), color=cfg.YELLOW, position=[5, 5])
for hero in aihero_sprite_group:
pos_x, pos_y = pos_x+15, 5
pos_x = showText(screen, font, text=hero.hero_name+'(ai):'+str(hero.health_value), color=cfg.YELLOW, position=[pos_x, pos_y])
# --我方玩家生命值小于等于0/電腦方玩家生命值均小于等于0則判斷游戲結(jié)束
if ourhero.health_value <= 0:
is_win_flag = False
break
for hero in aihero_sprite_group:
if hero.health_value <= 0:
aihero_sprite_group.remove(hero)
if len(aihero_sprite_group) == 0:
is_win_flag = True
break
pygame.display.update()
clock.tick(cfg.FPS)
if is_win_flag:
Interface(screen, cfg, mode='game_switch')
else:
break
Interface(screen, cfg, mode='game_end')
5 最后
項目獲取:https://gitee.com/sinonfin/system-sharing文章來源地址http://www.zghlxwxcb.cn/news/detail-828286.html
到了這里,關(guān)于python項目分享 - 炸彈人小游戲設(shè)計與實現(xiàn) (源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!