游戏规则简介:
玩家通过建造箭塔抵御敌人的进攻。
每隔一段时间,将会有一波敌人从左上角的洞穴中诞生,并冲向右下角的城堡。玩家需要做的,则是通过建造箭塔射杀敌人,避免城堡受到敌人攻击,同时,每当你射杀一个敌人,将获得一定的金钱奖励。
游戏失败:
每有一个敌人冲进城堡,城堡的生命值下降一定的数值,当城堡的生命值为0时,则游戏失败。
游戏胜利:
随着时间的推移,敌人的实力会越来越强,数量也会越来越多,所以你是不可能胜利的,哈哈。
游戏进行中的界面说明:
T1-T3代表不同的箭塔类型,不同的箭塔类型具有不同的价格以及能力;
XXX代表出售箭塔(半价);
Pause代表暂停游戏;
Quit代表退出游戏。
玩家通过左键选中箭塔/出售箭塔标识,右键放弃当前选中的内容。鼠标中间箭用于控制箭塔射击的方向,否则箭塔将自由射击。
选中箭塔后,将其移动到你认为合适的位置,点击鼠标左键即可在该位置建造一个箭塔(当然前提是你账户余额买得起箭塔,不然只能打怪攒钱了);选中出售箭塔后,将出售箭塔标识放在已建造的箭塔上,点击鼠标左键,即可出售选中的箭塔。
# 游戏进行中界面
# 作者: Charles
import sys
import json
import math
import random
import pygame
sys.path.append('..')
from sprites import Enemy
from sprites import Turret
from interface import PAUSE
from pygame.locals import *
from collections import namedtuple
# 按钮类: 位置、文本、点击触发的事件
Button = namedtuple('Button', ['rect', 'text', 'onClick'])
# 定义一些颜色
info_color = (120, 20, 50)
red = (255, 0, 0)
green = (0, 255, 0)
black = (0, 0, 0)
white = (255, 255, 255)
grey = (127, 127, 127)
button_color1 = (0, 200, 0)
button_color2 = (0, 100, 0)
# 游戏进行中界面
class GAMING():
def __init__(self, WIDTH=800, HEIGHT=600):
self.WIDTH = WIDTH
self.HEIGHT = HEIGHT
# 游戏地图大小
map_w = WIDTH
map_h = 500
# 按钮大小和位置
button_w = 60
button_h = 60
button_y = 520
# 间隙
gap = 20
# 按钮放在工具栏, 工具栏两端各有一个信息显示框
toolbar_w = gap * 7 + button_w * 6
info_w = (WIDTH - toolbar_w) // 2
info_h = HEIGHT - map_h
toolbar_h = HEIGHT - map_h
# 界面布置
self.map_rect = pygame.Rect(0, 0, map_w, map_h)
self.map_surface = pygame.Surface((map_w, map_h))
self.leftinfo_rect = pygame.Rect(0, map_h, info_w, info_h)
self.rightinfo_rect = pygame.Rect(WIDTH-info_w, map_h, info_w, info_h)
self.toolbar_rect = pygame.Rect(info_w, map_h, toolbar_w, toolbar_h)
# 草
self.grass = pygame.image.load("./resource/imgs/game/grass.png")
# 岩石(铺路用的)
self.rock = pygame.image.load("./resource/imgs/game/rock.png")
# 污垢
self.dirt = pygame.image.load("./resource/imgs/game/dirt.png")
# 水
self.water = pygame.image.load("./resource/imgs/game/water.png")
# 灌木
self.bush = pygame.image.load("./resource/imgs/game/bush.png")
# 纽带
self.nexus = pygame.image.load("./resource/imgs/game/nexus.png")
# 洞穴
self.cave = pygame.image.load("./resource/imgs/game/cave.png")
# 获取地图元素的大小,请保证素材库里组成地图的元素图大小一致
# 一些字体
self.info_font = pygame.font.Font('./resource/fonts/Calibri.ttf', 14)
self.button_font = pygame.font.Font('./resource/fonts/Calibri.ttf', 20)
# 可以放炮塔的地方
self.placeable =
# 地图元素字典(数字对应.map文件中的数字)
self.map_elements = {
0: self.grass,
1: self.rock,
2: self.dirt,
3: self.water,
4: self.bush,
5: self.nexus,
6: self.cave
}
# 用于记录地图中的道路
self.path_list = []
# 当前的地图,将地图导入到这里面
self.currentMap = dict()
# 当前鼠标携带的图标(即选中道具) -> [道具名, 道具]
self.mouseCarried = []
# 在地图上建造好了的炮塔
self.builtTurretGroup = pygame.sprite.Group()
# 所有的敌人
self.EnemiesGroup = pygame.sprite.Group()
# 所有射出的箭
self.arrowsGroup = pygame.sprite.Group()
# 玩家操作用的按钮
self.buttons = [
Button(pygame.Rect((info_w+gap), button_y, button_w, button_h), 'T1', self.takeT1),
Button(pygame.Rect((info_w+gap*2+button_w), button_y, button_w, button_h), 'T2', self.takeT2),
Button(pygame.Rect((info_w+gap*3+button_w*2), button_y, button_w, button_h), 'T3', self.takeT3),
Button(pygame.Rect((info_w+gap*4+button_w*3), button_y, button_w, button_h), 'XXX', self.takeXXX),
Button(pygame.Rect((info_w+gap*5+button_w*4), button_y, button_w, button_h), 'Pause', self.pauseGame),
Button(pygame.Rect((info_w+gap*6+button_w*5), button_y, button_w, button_h), 'Quit', self.quitGame)
]
# 开始游戏
def start(self, screen, map_path=None, difficulty_path=None):
# 读取游戏难度对应的参数
with open(difficulty_path, 'r') as f:
difficulty_dict = json.load(f)
self.money = difficulty_dict.get('money')
self.health = difficulty_dict.get('health')
self.max_health = difficulty_dict.get('health')
difficulty_dict = difficulty_dict.get('enemy')
# 每60s生成一波敌人
GenEnemiesEvent = pygame.constants.USEREVENT + 0
# 生成敌人的flag和当前已生成敌人的总次数
genEnemiesFlag = False
genEnemiesNum = 0
# 每0.5秒出一个敌人
GenEnemyEvent = pygame.constants.USEREVENT + 1
genEnemyFlag = False
# 防止变量未定义
enemyRange = None
numEnemy = None
# 是否手动操作箭塔射击
Manualshot = False
has_control = False
while True:
if self.health
return
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
# 左键选物品
if event.button == 1:
# 鼠标点击在地图上
if self.map_rect.collidepoint(event.pos):
if self.mouseCarried:
if self.mouseCarried[0] == 'turret':
self.buildTurret(event.pos)
elif self.mouseCarried[0] == 'XXX':
self.sellTurret(event.pos)
# 鼠标点击在工具栏
elif self.toolbar_rect.collidepoint(event.pos):
for button in self.buttons:
if button.text == 'T1':
button.onClick()
elif button.text == 'T2':
button.onClick()
elif button.text == 'T3':
button.onClick()
elif button.text == 'XXX':
button.onClick()
elif button.text == 'Pause':
button.onClick(screen)
elif button.text == 'Quit':
button.onClick()
# 显然只能有一个按钮被点击
break
# 右键释放物品
if event.button == 3:
self.mouseCarried = []
# 按中间键手动控制炮塔射箭方向一次,否则自由射箭
if event.button == 2:
Manualshot = True
if event.type == GenEnemiesEvent:
genEnemiesFlag = True
if event.type == GenEnemyEvent:
genEnemyFlag = True
# 生成敌人
# 生成的敌人随当前已生成敌人的总次数的增加而变强变多
if genEnemiesFlag:
genEnemiesFlag = False
genEnemiesNum += 1
idx = 0
for key, value in difficulty_dict.items():
idx += 1
if idx == len(difficulty_dict.keys()):
enemyRange = value['enemyRange']
numEnemy = value['numEnemy']
break
if genEnemiesNum
enemyRange = value['enemyRange']
numEnemy = value['numEnemy']
break
if genEnemyFlag and numEnemy:
genEnemyFlag = False
numEnemy -= 1
enemy = Enemy.Enemy(random.choice(range(enemyRange)))
self.EnemiesGroup.add(enemy)
# 射箭
for turret in self.builtTurretGroup:
if not Manualshot:
position = turret.position[0] + self.elementSize // 2, turret.position[1]
arrow = turret.shot(position)
else:
position = turret.position[0] + self.elementSize // 2, turret.position[1]
angle = math.atan((mouse_pos[1]-position[1])/(mouse_pos[0]-position[0]+1e-6))
arrow = turret.shot(position, angle)
has_control = True
if arrow:
self.arrowsGroup.add(arrow)
else:
has_control = False
if has_control:
has_control = False
Manualshot = False
# 移动箭和碰撞检测
for arrow in self.arrowsGroup:
arrow.move()
if (not self.map_rect.collidepoint(points[0])) and (not self.map_rect.collidepoint(points[1])) and \
(not self.map_rect.collidepoint(points[2])) and (not self.map_rect.collidepoint(points[3])):
self.arrowsGroup.remove(arrow)
del arrow
continue
for enemy in self.EnemiesGroup:
enemy.life_value -= arrow.attack_power
self.arrowsGroup.remove(arrow)
del arrow
break
self.draw(screen, map_path)
# 将场景画到游戏界面上
def draw(self, screen, map_path):
self.drawToolbar(screen)
self.loadMap(screen, map_path)
self.drawMouseCarried(screen)
self.drawBuiltTurret(screen)
self.drawEnemies(screen)
self.drawArrows(screen)
# 画出所有射出的箭
def drawArrows(self, screen):
for arrow in self.arrowsGroup:
screen.blit(arrow.image, arrow.rect)
# 画敌人
def drawEnemies(self, screen):
for enemy in self.EnemiesGroup:
if enemy.life_value
self.money += enemy.reward
self.EnemiesGroup.remove(enemy)
del enemy
continue
res = enemy.move(self.elementSize)
if res:
coord = self.find_next_path(enemy)
if coord:
enemy.reached_path.append(enemy.coord)
enemy.coord = coord
enemy.position = self.coord2pos(coord)
else:
self.health -= enemy.damage
self.EnemiesGroup.remove(enemy)
del enemy
continue
# 画血条
greenLen = max(0, enemy.life_value / enemy.max_life_value) * self.elementSize
if greenLen > 0:
if greenLen
screen.blit(enemy.image, enemy.rect)
# 画已经建造好的炮塔
def drawBuiltTurret(self, screen):
for turret in self.builtTurretGroup:
screen.blit(turret.image, turret.rect)
# 画鼠标携带物
def drawMouseCarried(self, screen):
if self.mouseCarried:
coord = self.pos2coord(position)
position = self.coord2pos(coord)
代码来源于小甲鱼论坛,如有不便请留言删除