Python開發(fā)之城堡保衛(wèi)戰(zhàn)游戲的實現(xiàn)
實現(xiàn)功能
1:敵人的綿綿不斷的前進,拿著各種各樣的武器(叉子,斧頭,寶劍),揮動武器攻擊我方城堡,對我方城堡造成傷害!
2:我方城堡發(fā)現(xiàn)敵人可手動點擊鼠標左鍵來發(fā)起子彈攻擊,對日人造成致命傷害,讓其死亡!
3:完備的數(shù)據(jù)顯示,攻擊敵人獲取金幣,累計得分,當前管卡的級別,我方城堡生命值的顯示等等,擊殺敵人獲取的金幣可以兌換額外屬性來裝備回復(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('分數(shù):' + str(castle.score), font, GREY, 180, 10)
draw_text('最分數(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))
# 在該位置點擊鼠標
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()
# 重置鼠標點擊
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)建十字準心
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()
# 隱藏鼠標指針
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)
# 實例化十字準心
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)
# 顯示十字準心
crosshair.draw()
# 繪制子彈到屏幕
bullet_group.update()
bullet_group.draw(screen)
# 繪制敵人
enemy_group.update(screen, castle, bullet_group)
# 顯示詳細信息
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
# 檢測如果活著的敵人都被消滅了則當前級別就完成了
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
# 得到鼠標的位置
pos = pygame.mouse.get_pos()
# 檢測鼠標指針的碰撞
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-12
python實現(xiàn)對指定輸入的字符串逆序輸出的6種方法
這篇文章主要介紹了python實現(xiàn)對指定輸入的字符串逆序輸出的6種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04
Pandas如何將表格的前幾行生成html實戰(zhàn)案例
這篇文章主要介紹了Pandas如何將表格的前幾行生成html實戰(zhàn)案例,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08
Python使用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)換。感興趣的小伙伴可以跟隨小編一起學習一下2021-12-12

