Python遊戲開發之魔塔小遊戲的實現
前言
這一期我們繼續完善我們的魔塔小遊戲。
廢話不多說,讓我們愉快地開始吧~
開發工具
Python版本: 3.7.4
相關模塊:
cpgames模塊;
以及一些python自帶的模塊。
環境搭建
安裝Python並添加到環境變量,pip安裝需要的相關模塊即可。
原理簡介
本期我們實現一些之前還沒實現的功能,以及做一些功能優化(部分內容為瞭測試方便,我會把人物設置成無敵狀態)。首先,是拾取物品等遊戲事件的提示效果,核心代碼如下:
'''遊戲事件提示''' def showinfo(self, screen): if self.obtain_tips is None: return self.show_obtain_tips_count += 1 if self.show_obtain_tips_count > self.max_obtain_tips_count: self.show_obtain_tips_count = 0 self.obtain_tips = None # 畫框 left, top = self.cfg.BLOCKSIZE // 2, 100 width, height = self.cfg.SCREENSIZE[0] // self.cfg.BLOCKSIZE - 1, 2 pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7) for col in range(width): for row in range(height): image = self.resource_loader.images['mapelements']['0'][0] image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE)) screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE)) # 文字 if isinstance(self.obtain_tips, list): assert len(self.obtain_tips) == 2 font = pygame.font.Font(self.fontpath, 30) font_render1 = font.render(self.obtain_tips[0], True, (255, 255, 255)) font_render2 = font.render(self.obtain_tips[1], True, (255, 255, 255)) rect1 = font_render1.get_rect() rect2 = font_render2.get_rect() rect1.midtop = left + width * self.cfg.BLOCKSIZE // 2, top + 10 rect2.midtop = left + width * self.cfg.BLOCKSIZE // 2, top + 10 + self.blocksize screen.blit(font_render1, rect1) screen.blit(font_render2, rect2) else: font = pygame.font.Font(self.fontpath, 40) font_render = font.render(self.obtain_tips, True, (255, 255, 255)) rect = font_render.get_rect() rect.midtop = left + width * self.cfg.BLOCKSIZE // 2, top + height * self.cfg.BLOCKSIZE // 2 - 20 screen.blit(font_render, rect)
效果:
'''顯示商店''' def showbuyinterface(self, screen, scenes, shop_type): # 購買函數 def buy(hero, coins_cost=0, experience_cost=0, add_life_value=0, add_attack_power=0, add_defense_power=0, add_level=0, add_yellow_keys=0, add_purple_keys=0, add_red_keys=0): if hero.num_coins < coins_cost: return if hero.experience < experience_cost: return if add_yellow_keys < 0 and hero.num_yellow_keys < 1: return if add_purple_keys < 0 and hero.num_purple_keys < 1: return if add_red_keys < 0 and hero.num_red_keys < 1: return hero.num_coins -= coins_cost hero.experience -= experience_cost hero.life_value += add_life_value + 1000 * add_level hero.attack_power += add_attack_power + 7 * add_level hero.defense_power += add_defense_power + 7 * add_level hero.level += add_level hero.num_yellow_keys += add_yellow_keys hero.num_purple_keys += add_purple_keys hero.num_red_keys += add_red_keys # 選項定義 # --第三層商店 if self.map_level_pointer == 3 and shop_type == 'buy_from_shop': choices_dict = { '增加 800 點生命(25 金幣)': lambda: buy(self.hero, coins_cost=25, add_life_value=800), '增加 4 點攻擊(25 金幣)': lambda: buy(self.hero, coins_cost=25, add_attack_power=4), '增加 4 點防禦(25 金幣)': lambda: buy(self.hero, coins_cost=25, add_defense_power=4), '離開商店': lambda: buy(self.hero), } id_image = self.resource_loader.images['mapelements']['22'][0] # --第十一層商店 elif self.map_level_pointer == 11 and shop_type == 'buy_from_shop': choices_dict = { '增加 4000 點生命(100 金幣)': lambda: buy(self.hero, coins_cost=100, add_life_value=4000), '增加 20 點攻擊(100 金幣)': lambda: buy(self.hero, coins_cost=100, add_attack_power=20), '增加 20 點防禦(100 金幣)': lambda: buy(self.hero, coins_cost=100, add_defense_power=20), '離開商店': lambda: buy(self.hero), } id_image = self.resource_loader.images['mapelements']['22'][0] # --第五層神秘老人 elif self.map_level_pointer == 5 and shop_type == 'buy_from_oldman': choices_dict = { '提升一級(100 經驗)': lambda: buy(self.hero, experience_cost=100, add_level=1), '增加 5 點攻擊(30 經驗)': lambda: buy(self.hero, experience_cost=30, add_attack_power=5), '增加 5 點防禦(30 經驗)': lambda: buy(self.hero, experience_cost=30, add_defense_power=5), '離開商店': lambda: buy(self.hero), } id_image = self.resource_loader.images['mapelements']['26'][0] # --第十三層神秘老人 elif self.map_level_pointer == 13 and shop_type == 'buy_from_oldman': choices_dict = { '提升三級(270 經驗)': lambda: buy(self.hero, experience_cost=270, add_level=1), '增加 17 點攻擊(95 經驗)': lambda: buy(self.hero, experience_cost=95, add_attack_power=17), '增加 17 點防禦(95 經驗)': lambda: buy(self.hero, experience_cost=95, add_defense_power=17), '離開商店': lambda: buy(self.hero), } id_image = self.resource_loader.images['mapelements']['26'][0] # --第五層商人 elif self.map_level_pointer == 5 and shop_type == 'buy_from_businessman': choices_dict = { '購買 1 把黃鑰匙(10 金幣)': lambda: buy(self.hero, coins_cost=10, add_yellow_keys=1), '購買 1 把藍鑰匙(50 金幣)': lambda: buy(self.hero, coins_cost=50, add_purple_keys=1), '購買 1 把紅鑰匙(100 金幣)': lambda: buy(self.hero, coins_cost=100, add_red_keys=1), '離開商店': lambda: buy(self.hero), } id_image = self.resource_loader.images['mapelements']['27'][0] # --第十二層商人 elif self.map_level_pointer == 12 and shop_type == 'buy_from_businessman': choices_dict = { '賣出 1 把黃鑰匙(7 金幣)': lambda: buy(self.hero, coins_cost=-7, add_yellow_keys=-1), '賣出 1 把藍鑰匙(35 金幣)': lambda: buy(self.hero, coins_cost=-35, add_purple_keys=-1), '賣出 1 把紅鑰匙(70 金幣)': lambda: buy(self.hero, coins_cost=-70, add_red_keys=-1), '離開商店': lambda: buy(self.hero), } id_image = self.resource_loader.images['mapelements']['27'][0] id_image = pygame.transform.scale(id_image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE)) # 主循環 clock, selected_idx = pygame.time.Clock(), 1 font = pygame.font.Font(self.cfg.FONT_PATHS_NOPRELOAD_DICT['font_cn'], 20) while True: screen.fill((0, 0, 0)) screen.blit(self.background_images['gamebg'], (0, 0)) self.map_parser.draw(screen) for scene in scenes: screen.blit(scene[0], scene[1]) self.hero.draw(screen) # --按鍵檢測 for event in pygame.event.get(): if event.type == pygame.QUIT: QuitGame() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: list(choices_dict.values())[selected_idx-1]() if selected_idx == 4: return elif event.key == pygame.K_w or event.key == pygame.K_UP: selected_idx = max(selected_idx - 1, 1) elif event.key == pygame.K_s or event.key == pygame.K_DOWN: selected_idx = min(selected_idx + 1, 4) # --對話框 # ----底色 width, height = 8, 3 left, bottom = self.hero.rect.left + self.hero.rect.width // 2 - width // 2 * self.cfg.BLOCKSIZE, self.hero.rect.bottom for col in range(width): for row in range(height): image = self.resource_loader.images['mapelements']['0'][0] image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE)) screen.blit(image, (left + col * self.cfg.BLOCKSIZE, bottom + row * self.cfg.BLOCKSIZE)) # ----邊框 pygame.draw.rect(screen, (199, 97, 20), (left - 4, bottom - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7) # ----展示選項 for idx, choice in enumerate(['請選擇:'] + list(choices_dict.keys())): if selected_idx == idx and idx > 0: choice = '➤' + choice font_render = font.render(choice, True, (255, 0, 0)) elif idx > 0: choice = ' ' + choice font_render = font.render(choice, True, (255, 255, 255)) else: font_render = font.render(choice, True, (255, 255, 255)) rect = font_render.get_rect() rect.left, rect.top = left + self.cfg.BLOCKSIZE + 20, bottom + 10 + idx * 30 screen.blit(font_render, rect) # ----展示頭像 screen.blit(id_image, (left + 10, bottom + 10)) # --刷新 pygame.display.flip() clock.tick(self.cfg.FPS)
即,商店主要包括三種類型:一種的明面上的商店,用金幣進行交易,可以獲得生命值、攻擊力和防禦力的提升;一種是商人,用金幣進行交易,可以獲得/出售不同顏色的鑰匙;還有一種是神秘老人,用經驗值進行交易,可以獲得等級、攻擊力和防禦力的提示。效果如下
接著,我們來實現一下地圖中可以撿到的一些寶物的特效,主要包括風之羅盤、聖光徽、星光神榔和幸運十字架。
其中,風之羅盤用於在已經走過的樓層間進行跳躍,代碼實現如下:
'''顯示關卡跳轉''' def showjumplevel(self, screen, scenes): # 主循環 clock, selected_level = pygame.time.Clock(), 1 font = pygame.font.Font(self.cfg.FONT_PATHS_NOPRELOAD_DICT['font_cn'], 20) while True: screen.fill((0, 0, 0)) screen.blit(self.background_images['gamebg'], (0, 0)) self.map_parser.draw(screen) for scene in scenes: screen.blit(scene[0], scene[1]) self.hero.draw(screen) # --按鍵檢測 for event in pygame.event.get(): if event.type == pygame.QUIT: QuitGame() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: return selected_level elif event.key == pygame.K_w or event.key == pygame.K_UP: selected_level = max(selected_level - 1, 0) elif event.key == pygame.K_s or event.key == pygame.K_DOWN: selected_level = min(selected_level + 1, self.max_map_level_pointer) # --對話框 # ----底色 width, height = 11, 4 left, top = self.cfg.SCREENSIZE[0] // 2 - width // 2 * self.cfg.BLOCKSIZE, self.cfg.SCREENSIZE[1] // 2 - height * self.cfg.BLOCKSIZE for col in range(width): for row in range(height): image = self.resource_loader.images['mapelements']['0'][0] image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE)) screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE)) # ----邊框 pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7) # ----展示選項 for idx in list(range(self.max_map_level_pointer+1)): if selected_level == idx: text = f'➤第 {idx} 層' font_render = font.render(text, True, (255, 0, 0)) else: text = f' 第 {idx} 層' font_render = font.render(text, True, (255, 255, 255)) rect = font_render.get_rect() rect.left, rect.top = left + 20 + idx // 6 * self.cfg.BLOCKSIZE * 2, top + 20 + (idx % 6) * 30 screen.blit(font_render, rect) # --刷新 pygame.display.flip() clock.tick(self.cfg.FPS)
效果:
然後是聖光徽,用於查看怪物的基本情況,代碼實現如下:
'''顯示關卡怪物信息''' def showforecastlevel(self, screen, scenes): # 主循環 clock = pygame.time.Clock() font = pygame.font.Font(self.cfg.FONT_PATHS_NOPRELOAD_DICT['font_cn'], 20) monsters = self.map_parser.getallmonsters() if len(monsters) < 1: return monsters_show_pointer, max_monsters_show_pointer = 1, round(len(monsters) / 4) show_tip_text, show_tip_text_count, max_show_tip_text_count = True, 1, 15 return_flag = False while True: screen.fill((0, 0, 0)) screen.blit(self.background_images['gamebg'], (0, 0)) self.map_parser.draw(screen) for scene in scenes: screen.blit(scene[0], scene[1]) self.hero.draw(screen) # --按鍵檢測 for event in pygame.event.get(): if event.type == pygame.QUIT: QuitGame() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_l: return_flag = True elif event.key == pygame.K_SPACE: monsters_show_pointer = monsters_show_pointer + 1 if monsters_show_pointer > max_monsters_show_pointer: monsters_show_pointer = 1 elif event.type == pygame.KEYUP: if event.key == pygame.K_l and return_flag: return # --對話框 # ----底色 width, height = 14, 5 left, top = self.cfg.SCREENSIZE[0] // 2 - width // 2 * self.cfg.BLOCKSIZE, self.cfg.SCREENSIZE[1] // 2 - height * self.cfg.BLOCKSIZE for col in range(width): for row in range(height): image = self.resource_loader.images['mapelements']['0'][0] image = pygame.transform.scale(image, (self.cfg.BLOCKSIZE, self.cfg.BLOCKSIZE)) screen.blit(image, (left + col * self.cfg.BLOCKSIZE, top + row * self.cfg.BLOCKSIZE)) # ----邊框 pygame.draw.rect(screen, (199, 97, 20), (left - 4, top - 4, self.cfg.BLOCKSIZE * width + 8, self.cfg.BLOCKSIZE * height + 8), 7) # ----展示選項 for idx, monster in enumerate(monsters[(monsters_show_pointer-1)*4: monsters_show_pointer*4]): id_image = self.resource_loader.images['mapelements'][monster[6]][0] id_image = pygame.transform.scale(id_image, (self.cfg.BLOCKSIZE - 10, self.cfg.BLOCKSIZE - 10)) screen.blit(id_image, (left + 10, top + 20 + idx * self.cfg.BLOCKSIZE)) text = f'名稱: {monster[0]} 生命: {monster[1]} 攻擊: {monster[2]} 防禦: {monster[3]} 金幣: {monster[4]} 經驗: {monster[5]} 損失: {self.hero.winmonster(monster)[1]}' font_render = font.render(text, True, (255, 255, 255)) rect = font_render.get_rect() rect.left, rect.top = left + 15 + self.cfg.BLOCKSIZE, top + 30 + idx * self.cfg.BLOCKSIZE screen.blit(font_render, rect) # ----操作提示 show_tip_text_count += 1 if show_tip_text_count == max_show_tip_text_count: show_tip_text_count = 1 show_tip_text = not show_tip_text if show_tip_text: tip_text = '空格鍵' font_render = font.render(tip_text, True, (255, 255, 255)) rect.left, rect.bottom = self.cfg.BLOCKSIZE * width + 30, self.cfg.BLOCKSIZE * (height + 1) + 10 screen.blit(font_render, rect) # --刷新 pygame.display.flip() clock.tick(self.cfg.FPS)
效果:
然後我們來實現一下幸運十字架,把它交給序章中的仙子,可以將自身的所有能力提升一些(攻擊防禦和生命值)。
# 定義所有對話 if self.hero.has_cross: conversations = [ ['仙子, 我已經將那個十字架找到瞭.'], ['你做得很好. 那麼現在我就開始', '授予你更強的力量! 咪啦哆咪嗶...', '好瞭, 我已經將你現在的能力提升瞭!', '記住: 如果你沒有足夠的實力的話,', '不要去第二十一層. 在那一層裡,', '你所有寶物的法力都會失去作用.'] ] self.hero.has_cross = False self.hero.life_value = int(self.hero.life_value * 4 / 3) self.hero.attack_power = int(self.hero.attack_power * 4 / 3) self.hero.defense_power = int(self.hero.defense_power * 4 / 3)
以上就是Python遊戲開發之魔塔小遊戲的實現的詳細內容,更多關於Python魔塔遊戲的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Python實現敲擊木魚積累功德小項目
- Python pygame項目實戰英雄動畫特效實現
- python實現跨年表白神器–你值得擁有
- Python實現打乒乓小遊戲
- pygame實現井字棋之第二步邏輯實現