Python開發(fā)之城堡保衛(wèi)戰(zhàn)游戲的實現(xiàn)
實現(xiàn)功能
1:敵人的綿綿不斷的前進,拿著各種各樣的武器(叉子,斧頭,寶劍),揮動武器攻擊我方城堡,對我方城堡造成傷害!
2:我方城堡發(fā)現(xiàn)敵人可手動點擊鼠標(biāo)左鍵來發(fā)起子彈攻擊,對日人造成致命傷害,讓其死亡!
3:完備的數(shù)據(jù)顯示,攻擊敵人獲取金幣,累計得分,當(dāng)前管卡的級別,我方城堡生命值的顯示等等,擊殺敵人獲取的金幣可以兌換額外屬性來裝備回復(fù)加強我方堡壘!
4:項目的布局界面優(yōu)美干凈,結(jié)合添加的純音樂游戲背景和攻擊音效以及實時的動畫顯示(如我方城堡的外觀會隨著我方城堡生命值的降低而發(fā)生改變,也就是變得會破敗一些等等)以此讓項目更加具有可玩性!
5:拿該項目練手或者作為一個python簡單的課程設(shè)計也是一個可以的選擇!
6:項目總代碼700行左右
用到的編程知識
python基礎(chǔ),os文件讀寫,pygame模塊以及面向?qū)ο笏枷耄?/p>
代碼如下
enemy.py類文件(100行代碼左右)
import pygame class Enemy(pygame.sprite.Sprite): def __init__(self, health, animation_list, x, y, speed): pygame.sprite.Sprite.__init__(self) self.alive = True self.speed = speed self.health = health self.last_attack = pygame.time.get_ticks() self.attack_cooldown = 1000 self.animation_list = animation_list self.frame_index = 0 self.action = 0#0: walk, 1: attack, 2: death self.update_time = pygame.time.get_ticks() #select starting image self.image = self.animation_list[self.action][self.frame_index] self.rect = pygame.Rect(0, 0, 25, 40) self.rect.center = (x, y) def update(self, surface, target, bullet_group): if self.alive: #check for collision with bullets if pygame.sprite.spritecollide(self, bullet_group, True): #lower enemy health self.health -= 25 #check if enemy has reached the castle if self.rect.right > target.rect.left: self.update_action(1) #move enemy if self.action == 0: #update rectangle position self.rect.x += self.speed #attack if self.action == 1: #check if enough time has passed since last attack if pygame.time.get_ticks() - self.last_attack > self.attack_cooldown: target.health -= 25 if target.health < 0: target.health = 0 self.last_attack = pygame.time.get_ticks() #check if health has dropped to zero if self.health <= 0: target.money += 100 target.score += 100 self.update_action(2)#death self.alive = False self.update_animation() #draw image on screen surface.blit(self.image, (self.rect.x - 10, self.rect.y - 15)) def update_animation(self): #define animation cooldown ANIMATION_COOLDOWN = 50 #update image depending on current action self.image = self.animation_list[self.action][self.frame_index] #check if enough time has passed since the last update if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: self.update_time = pygame.time.get_ticks() self.frame_index += 1 #if the animation has run out then reset back to the start if self.frame_index >= len(self.animation_list[self.action]): if self.action == 2: self.frame_index = len(self.animation_list[self.action]) - 1 else: self.frame_index = 0 def update_action(self, new_action): #check if the new action is different to the previous one if new_action != self.action: self.action = new_action #update the animation settings self.frame_index = 0 self.update_date = pygame.time.get_ticks()
castle.py類文件(500行代碼左右)
# 導(dǎo)入庫 import pygame import math import os import sys import random import button from pygame import mixer # 初始化pygame pygame.init() # 定義游戲窗口高度和寬度 SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 # 加載背景音樂 pygame.mixer.music.load("sound/bjmusic.WAV") pygame.mixer.music.set_volume(0.3) jump_fx = pygame.mixer.Sound("sound/bullet.wav") jump_fx.set_volume(0.5) # 創(chuàng)建游戲窗口 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("城堡防衛(wèi)戰(zhàn)") clock = pygame.time.Clock() FPS = 60 # 定義游戲變量 level = 1 high_score = 0 level_difficulty = 0 target_difficulty = 1000 DIFFICULTY_MULTIPLIER = 1.1 game_over = False next_level = False ENEMY_TIMER = 1000 last_enemy = pygame.time.get_ticks() enemies_alive = 0 max_towers = 4 TOWER_COST = 5000 # 定義炮塔位置的列表 tower_positions = [ [SCREEN_WIDTH - 250, SCREEN_HEIGHT - 200], [SCREEN_WIDTH - 200, SCREEN_HEIGHT - 150], [SCREEN_WIDTH - 150, SCREEN_HEIGHT - 150], [SCREEN_WIDTH - 100, SCREEN_HEIGHT - 150] ] # 加載最高分 if os.path.exists('socre.txt'): with open('socre.txt', 'r') as file: high_score = int(file.read()) # 定義顏色 WHITE = (255, 255, 255) GREY = (100, 100, 100) # 定義字體 font = pygame.font.SysFont('華文彩云', 30) font_60 = pygame.font.SysFont('華文行楷', 60) # 加載圖片 bg = pygame.image.load('img/bg.png').convert_alpha() # 城堡 castle_img_100 = pygame.image.load('img/castle/castle_100.png').convert_alpha() castle_img_50 = pygame.image.load('img/castle/castle_50.png').convert_alpha() castle_img_25 = pygame.image.load('img/castle/castle_25.png').convert_alpha() # 炮塔 tower_img_100 = pygame.image.load('img/tower/tower_100.png').convert_alpha() tower_img_50 = pygame.image.load('img/tower/tower_50.png').convert_alpha() tower_img_25 = pygame.image.load('img/tower/tower_25.png').convert_alpha() # 子彈圖像 bullet_img = pygame.image.load('img/bullet.png').convert_alpha() b_w = bullet_img.get_width() b_h = bullet_img.get_height() bullet_img = pygame.transform.scale(bullet_img, (int(b_w * 0.075), int(b_h * 0.075))) # 創(chuàng)建敵人類 class Enemy(pygame.sprite.Sprite): def __init__(self, health, animation_list, x, y, speed): super().__init__() self.alive = True self.speed = speed self.health = health self.last_attack = pygame.time.get_ticks() self.attack_cooldown = 1000 self.animation_list = animation_list self.frame_index = 0 self.action = 0 self.update_time = pygame.time.get_ticks() # 選擇動畫開始的圖片 self.image = self.animation_list[self.action][self.frame_index] self.rect = pygame.Rect(0, 0, 25, 40) self.rect.center = (x, y) def update(self, surface, target, bullet_group): if self.alive: # 檢查敵人與子彈的碰撞 if pygame.sprite.spritecollide(self, bullet_group, True): # 減少健康 self.health -= 25 # 檢查敵人是否已經(jīng)到達城堡 if self.rect.right > target.rect.left: self.update_action(1) # 移動敵人 if self.action == 0: self.rect.x += 1 # 攻擊城堡 if self.action == 1: # 檢測冷卻時間 if pygame.time.get_ticks() - self.last_attack > self.attack_cooldown: target.health -= 25 if target.health < 0: target.health = 0 self.last_attack = pygame.time.get_ticks() # 檢查敵人血條是否為0 if self.health <= 0: target.money += 100 target.score += 100 self.update_action(2) self.alive = False # 調(diào)用更新動畫 self.update_animation() # 繪制敵人 # pygame.draw.rect(surface, (255, 255, 255), self.rect, 1) surface.blit(self.image, (self.rect.x - 10, self.rect.y - 15)) def update_animation(self): # 定義動畫冷卻時間 ANIMATION_COOLDOWN = 50 # 根據(jù)選擇的冬瓜更新幀 self.image = self.animation_list[self.action][self.frame_index] # 判斷多久更新一次幀 if pygame.time.get_ticks() - self.update_time > ANIMATION_COOLDOWN: self.update_time = pygame.time.get_ticks() self.frame_index += 1 # 檢查幀數(shù)不能超過最大幀數(shù) if self.frame_index >= len(self.animation_list[self.action]): if self.action == 2: self.frame_index = len(self.animation_list[self.action]) - 1 else: self.frame_index = 0 def update_action(self, new_action): # 檢查新動作與上一個動作是否相同 if new_action != self.action: self.action = new_action # 更新動畫重置 self.frame_index = 0 self.update_time = pygame.time.get_ticks() # 加載敵人列表 enemy_animations = [] enemy_tpyes = ['knight', 'goblin', 'purple_goblin', 'red_goblin'] enemy_health = [75, 100, 125, 150] animation_types = ['walk', 'attack', 'death'] for enemy in enemy_tpyes: # 加載動畫列表 animation_list = [] for animation in animation_types: # 創(chuàng)建臨時列表 temp_list = [] # 定義幀數(shù) num_of_frames = 20 for i in range(num_of_frames): img = pygame.image.load(f'img/enemies/{enemy}/{animation}/{i}.png').convert_alpha() e_w = img.get_width() e_h = img.get_height() img = pygame.transform.scale(img, (int(e_w * 0.2), int(e_h * 0.2))) temp_list.append(img) animation_list.append(temp_list) enemy_animations.append(animation_list) # 加載按鈕圖片 repair_img = pygame.image.load('img/repair.png').convert_alpha() armour_img = pygame.image.load('img/armour.png').convert_alpha() # 在屏幕上輸出文本信息 def draw_text(text, font, text_color, x, y): img = font.render(text, True, text_color) screen.blit(img, (x, y)) # 定義一個顯示狀態(tài)的函數(shù) def show_info(): draw_text('錢數(shù):' + str(castle.money), font, GREY, 10, 10) draw_text('分?jǐn)?shù):' + str(castle.score), font, GREY, 180, 10) draw_text('最分?jǐn)?shù):' + str(high_score), font, GREY, 180, 50) draw_text('級別:' + str(level), font, GREY, SCREEN_WIDTH // 2, 10) draw_text('健康:' + str(castle.health) + "/" + str(castle.max_health), font, GREY, SCREEN_WIDTH - 230, SCREEN_HEIGHT - 50) draw_text('1000', font, GREY, SCREEN_WIDTH - 250, 70) draw_text(str(TOWER_COST), font, GREY, SCREEN_WIDTH - 150, 70) draw_text('500', font, GREY, SCREEN_WIDTH - 70, 70) # 城堡類 class Castle(): def __init__(self, image100, image50, image25, x, y, scale): self.health = 1000 self.max_health = self.health self.fired = False self.money = 0 self.score = 0 width = image100.get_width() height = image100.get_height() self.image100 = pygame.transform.scale(image100, (int(width * scale), int(height * scale))) self.image50 = pygame.transform.scale(image50, (int(width * scale), int(height * scale))) self.image25 = pygame.transform.scale(image25, (int(width * scale), int(height * scale))) self.rect = self.image100.get_rect() self.rect.x = x self.rect.y = y def shoot(self): pos = pygame.mouse.get_pos() x_dist = pos[0] - self.rect.midleft[0] y_dist = -(pos[1] - self.rect.midleft[1]) self.angle = math.degrees(math.atan2(y_dist, x_dist)) # 在該位置點擊鼠標(biāo) if pygame.mouse.get_pressed()[0] and self.fired == False and pos[1] > 70: self.fired = True bullet = Bullet(bullet_img, self.rect.midleft[0], self.rect.midleft[1], self.angle) bullet_group.add(bullet) jump_fx.play() # 重置鼠標(biāo)點擊 if pygame.mouse.get_pressed()[0] == False: self.fired = False def draw(self): # 根據(jù)血量判斷加載那張圖片 if self.health <= 250: self.image = self.image25 elif self.health <= 500: self.image = self.image50 else: self.image = self.image100 screen.blit(self.image, self.rect) def repair(self): if self.money >= 1000 and self.health < self.max_health: self.health += 500 self.money -= 1000 if castle.health > castle.max_health: castle.health = castle.max_health def armour(self): if self.money >= 500: self.max_health += 250 self.money -= 500 # 炮塔類 class Tower(pygame.sprite.Sprite): def __init__(self, image100, image50, image25, x, y, scale): super().__init__() self.got_target = False self.angle = 0 self.last_shot = pygame.time.get_ticks() width = image100.get_width() height = image100.get_height() self.image100 = pygame.transform.scale(image100, (int(width * scale), int(height * scale))) self.image50 = pygame.transform.scale(image50, (int(width * scale), int(height * scale))) self.image25 = pygame.transform.scale(image25, (int(width * scale), int(height * scale))) self.image = self.image100 self.rect = self.image100.get_rect() self.rect.x = x self.rect.y = y def update(self, enemy_group): self.got_target = False for e in enemy_group: if e.alive: target_x, target_y = e.rect.midbottom self.got_target = True break if self.got_target: x_dist = target_x - self.rect.midleft[0] y_dist = -(target_y - self.rect.midleft[1]) self.angle = math.degrees(math.atan2(y_dist, x_dist)) # pygame.draw.line(screen, WHITE, (self.rect.midleft[0], self.rect.midleft[1]), (target_x, target_y)) shot_cooldown = 1000 # 開火 if pygame.time.get_ticks() - self.last_shot > shot_cooldown: self.last_shot = pygame.time.get_ticks() bullet = Bullet(bullet_img, self.rect.midleft[0], self.rect.midleft[1], self.angle) bullet_group.add(bullet) # 根據(jù)城堡血量判斷加載那張圖片 if castle.health <= 250: self.image = self.image25 elif castle.health <= 500: self.image = self.image50 else: self.image = self.image100 # 創(chuàng)建子彈類 class Bullet(pygame.sprite.Sprite): def __init__(self, image, x, y, angle): super().__init__() self.image = image self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.angle = math.radians(angle) # 角度轉(zhuǎn)換為弧度 self.speed = 10 # 根據(jù)角度計算水平和垂直的速度 self.dx = math.cos(self.angle) * self.speed self.dy = -(math.sin(self.angle) * self.speed) def update(self): # 檢測子彈是否已經(jīng)超出窗口 if self.rect.right < 0 or self.rect.left > SCREEN_WIDTH or self.rect.bottom < 0 or self.rect.top > SCREEN_HEIGHT: self.kill() # 移動子彈 self.rect.x += self.dx self.rect.y += self.dy # 創(chuàng)建十字準(zhǔn)心 class Crosshair(): def __init__(self, scale): image = pygame.image.load("img/crosshair.png").convert_alpha() width = image.get_width() height = image.get_height() self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale))) self.rect = self.image.get_rect() # 隱藏鼠標(biāo)指針 pygame.mouse.set_visible(False) def draw(self): mx, my = pygame.mouse.get_pos() self.rect.center = (mx, my) screen.blit(self.image, self.rect) # 創(chuàng)建城堡 castle = Castle(castle_img_100, castle_img_50, castle_img_25, SCREEN_WIDTH - 250, SCREEN_HEIGHT - 300, 0.2) # 實例化十字準(zhǔn)心 crosshair = Crosshair(0.025) # 創(chuàng)建按鈕 repair_button = button.Button(SCREEN_WIDTH - 240, 10, repair_img, 0.5) tower_button = button.Button(SCREEN_WIDTH - 130, 10, tower_img_100, 0.1) armour_button = button.Button(SCREEN_WIDTH - 75, 10, armour_img, 1.5) # 創(chuàng)建組 bullet_group = pygame.sprite.Group() enemy_group = pygame.sprite.Group() tower_group = pygame.sprite.Group() # 穿件臨時塔 # tower = Tower(tower_img_100, tower_img_50, tower_img_25, SCREEN_WIDTH - 350, SCREEN_HEIGHT - 200, 0.2) # tower_group.add(tower) # 游戲循環(huán)顯示窗口 pygame.mixer.music.unpause() pygame.mixer.music.play(-1) run = True while run: clock.tick(FPS) if game_over == False: screen.blit(bg, (0, 0)) # 顯示城堡 castle.draw() castle.shoot() # 顯示炮塔 tower_group.draw(screen) tower_group.update(enemy_group) # 顯示十字準(zhǔn)心 crosshair.draw() # 繪制子彈到屏幕 bullet_group.update() bullet_group.draw(screen) # 繪制敵人 enemy_group.update(screen, castle, bullet_group) # 顯示詳細(xì)信息 show_info() # 顯示按鈕 修理和鎧甲按鈕 if repair_button.draw(screen): castle.repair() if tower_button.draw(screen): # 檢查是否有足夠的金錢來建造炮塔 if castle.money >= TOWER_COST and len(tower_group) < max_towers: tower = Tower(tower_img_100, tower_img_50, tower_img_25, tower_positions[len(tower_group)][0], tower_positions[len(tower_group)][1], 0.2) tower_group.add(tower) # 減去消耗的金錢數(shù) castle.money -= TOWER_COST if armour_button.draw(screen): castle.armour() # 創(chuàng)建不同的敵人 if level_difficulty < target_difficulty: if pygame.time.get_ticks() - last_enemy > ENEMY_TIMER: # 創(chuàng)建敵人實例 e = random.randint(0, len(enemy_tpyes) - 1) enemy = Enemy(enemy_health[e], enemy_animations[e], -100, SCREEN_HEIGHT - 100, 1) enemy_group.add(enemy) last_enemy = pygame.time.get_ticks() level_difficulty += enemy_health[e] # 檢測是所有的的敵人都產(chǎn)生了 if level_difficulty >= target_difficulty: # 檢查有多少敵人仍然是活著的 enemies_alive = 0 for e in enemy_group: if e.alive == True: enemies_alive += 1 # 檢測如果活著的敵人都被消滅了則當(dāng)前級別就完成了 if enemies_alive == 0 and next_level == False: next_level = True level_reset_time = pygame.time.get_ticks() # 判斷是否進入下一關(guān) if next_level == True: draw_text('關(guān)卡已完成', font_60, WHITE, 200, 300) # 更新最高分 if castle.score > high_score: high_score = castle.score with open('socre.txt', 'w') as file: file.write(str(high_score)) if pygame.time.get_ticks() - level_reset_time > 1500: next_level = False level += 1 last_enemy = pygame.time.get_ticks() target_difficulty *= DIFFICULTY_MULTIPLIER level_difficulty = 0 enemy_group.empty() # 檢查游戲是否結(jié)束 if castle.health <= 0: game_over = True else: draw_text('游戲結(jié)束!', font, GREY, 300, 300) draw_text('按下"A"重新進入游戲', font, GREY, 250, 350) pygame.mouse.set_visible(True) key = pygame.key.get_pressed() if key[pygame.K_a]: # 重置游戲 game_over = False level = 1 target_difficulty = 1000 level_difficulty = 0 last_enemy = pygame.time.get_ticks() enemy_group.empty() tower_group.empty() castle.score = 0 castle.health = 1000 castle.max_health = castle.health castle.money = 0 pygame.mouse.set_visible(False) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() sys.exit() pygame.display.update()
button.py類文件(50行代碼左右)
import pygame # 按鈕類 class Button(): def __init__(self, x, y, image, scale): width = image.get_width() height = image.get_height() self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale))) self.rect = self.image.get_rect() self.rect.topleft = (x, y) self.clicked = False def draw(self, surface): action = False # 得到鼠標(biāo)的位置 pos = pygame.mouse.get_pos() # 檢測鼠標(biāo)指針的碰撞 if self.rect.collidepoint(pos): if pygame.mouse.get_pressed()[0] == 1 and self.clicked == False: self.clicked = True action = True if pygame.mouse.get_pressed()[0] == 0: self.clicked = False # 畫按鈕到屏幕上 surface.blit(self.image, (self.rect.x, self.rect.y)) return action
部分運行截圖
到此這篇關(guān)于Python開發(fā)之城堡保衛(wèi)戰(zhàn)游戲的實現(xiàn)的文章就介紹到這了,更多相關(guān)Python城堡保衛(wèi)戰(zhàn)游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python Pygame實戰(zhàn)之實現(xiàn)經(jīng)營類游戲夢想小鎮(zhèn)代碼版
作為一名模擬經(jīng)營類游戲的發(fā)燒友,各種農(nóng)場類、醫(yī)院類、鐵路類的游戲玩兒了很多年。今天用代碼給大家打造一款夢想小鎮(zhèn)游戲,希望大家喜歡啦2022-12-12python實現(xiàn)對指定輸入的字符串逆序輸出的6種方法
這篇文章主要介紹了python實現(xiàn)對指定輸入的字符串逆序輸出的6種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04Pandas如何將表格的前幾行生成html實戰(zhàn)案例
這篇文章主要介紹了Pandas如何將表格的前幾行生成html實戰(zhàn)案例,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08Python使用PEfile模塊實現(xiàn)分析PE文件
PeFile模塊是Python中一個強大的便攜式第三方PE格式分析工具,用于解析和處理Windows可執(zhí)行文件,本文主要就來講講如何使用PEfile模塊實現(xiàn)分析PE文件,需要的可以參考下2023-08-08基于Python實現(xiàn)簡易文檔格式轉(zhuǎn)換器
這篇文章主要介紹了基于Python和PyQT5實現(xiàn)簡易的文檔格式轉(zhuǎn)換器,支持.txt/.xlsx/.csv格式的轉(zhuǎn)換。感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2021-12-12