20251216 20260323《Python程序设计》实验4报告
课程:《Python程序设计》
班级:2512
姓名:杜立
学号:20251216
实验教师:王志强
实验日期:2026年6月10日
必修/选修:公选课
一.实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
二.项目概述
本程序旨在完成游戏《ddl生存计划:GPA保卫战》。游戏中玩家扮演一名大学生,在“期末月”的战场中,通过移动走位躲避或击破不断涌来的任务(DDL、作业、点名、社交邀约),用有限的时间资源存活到最后。
该游戏将“吸血鬼幸存者”式的割草玩法与大学生的真实生活相结合,非常具有可玩性
三.游戏机制
- 资源系统(贴合真实学习生活)
玩家只有两个核心资源:
时间(Time):相当于血量,每秒自然流逝,被敌人碰到额外扣除。
精力(Energy):释放技能消耗,随时间缓慢恢复,相当于蓝量。 - 敌人设计(各种“大学危机”)
所有敌人从屏幕边缘生成,向玩家缓慢移动:
作业:基础小怪,数量多,移动慢,碰撞扣 3 秒。
DDL:精英怪,速度较快,到达玩家附近会自爆,造成范围伤害。
点名:稀有怪,移速极快,扣时间多(15 秒)。
社交邀约:靠近后会诱惑玩家(短时输入反转/减速),但不直接扣血。
大作业/考试:Boss,血量高,周期性释放“焦虑光环”(全屏减速)。
3.技能系统(Roguelike 成长)
每次升级可从随机抽选的 3 个技能中选择一个:
咖啡狂热 攻击速度翻倍(攻击间隔减半)
学霸附体 攻击力 +5
运动健将 移动速度 +2
时间管理 时间上限 +20,并立即回复 20 点时间
精力充沛 精力恢复速度提升 50%
(此外主动技能(空格)可瞬间清怪,并对周围敌人造成 30 点伤害)
4.波次与成长
每 30 秒 为一波,波次结束时:
时间短暂回复 10 点
游戏暂停,弹出 3 选 1 技能升级 界面
敌人生成速度与种类难度提升
第 4 波最后 30 秒必定刷新 期末考试 Boss
四.实验过程
1.在初步学习了游戏编写并回顾了本学期所学知识后,在AI的辅助下,我进行的初代游戏的编写,编写完成后,遇到了以下情况
![屏幕截图 2026-06-22 171604]()
经过检查,发现是电脑缺少pygame导致的,在安装pygame的过程中也不顺利:

因为我电脑上的python版本过新,因此即使最新版本的pygame也无法与我的pycharm相互适配,因而我转向使用pygame-ce以完成后续代码调试
2.第一次运行时代码并没有按照预期顺利运行下去,仅游戏开始界面就是一团乱麻,根本无法正常使用。在我排除问题重新进入游戏后,我无法通过预设的“WASD”控制键与鼠标控制人物。


3.在排除万难,解决乱码,控制异常等问题后,游戏终于可以正常运行了以下是运行视频
五.专业知识
在一边查资料学习,一边完成大作业的过程中,我从“干中学”中学习到很多专业知识,下面介绍一下这个游戏中蕴含的PYTHON的相关知识:
1.整体架构与状态机
游戏状态通过一个简单的 有限状态机(FSM) 管理,在 Game 类中用 self.state 字符串表示,共有 5 种状态:
menu–主菜单
playing–正常游戏
paused–暂停
levelup–升级选择
gameover–游戏结束
状态的切换由事件(按键、点击)驱动。
例如:
def draw(self):
if self.state == 'menu':
self.draw_menu()
elif self.state == 'playing':
# ... 绘制游戏画面
elif self.state == 'levelup':
self.draw_levelup_menu()
这种编写架构使得代码逻辑清晰,易于扩展。
2.主游戏循环
游戏的核心是经典的 “事件 → 更新 → 渲染” 循环:
pygame.event.get() 获取所有事件(键盘、鼠标、退出等),并分发给状态对应的处理逻辑。
update() 中只处理 playing 状态的逻辑,保证暂停/菜单时游戏世界“冻结”。
draw() 根据状态绘制不同界面。
clock.tick(60) 保证每秒最多 60 帧,使游戏在不同性能机器上速度一致。
代码实例:
while running:
for event in pygame.event.get(): # 1. 处理输入
# ...
self.update() # 2. 更新游戏世界
self.draw() # 3. 绘制画面
pygame.display.flip() # 4. 刷新屏幕
self.clock.tick(FPS) # 5. 限制帧率
3.游戏对象设计
(1)Player(玩家)
属性:位置、半径、速度、时间(血量)、精力(蓝量)、攻击属性、状态计时器等。
方法:
update(keys, mouse_pos):处理移动(WASD)、状态效果衰减、时间自然流逝、精力恢复。
attack(target_x, target_y):若攻击冷却结束,生成多个投射物,朝目标方向发射。
take_damage(amount):扣除时间,并给予短暂无敌帧。
use_skill():消耗精力释放爆炸技能,返回一个技能效果字典。
add_skill(skill_name):永久应用被动技能效果(如修改射速、移速等)。
(2)Enemy(敌人)
属性:类型、半径、速度、血量、伤害、特殊效果(如自爆、混乱时间)等。
方法:
update(player_x, player_y):每帧向玩家位置移动(简单追踪)。
take_damage(damage):减少血量,若 ≤0 则标记 alive=False。
draw(screen):根据类型绘制不同形状(方块、三角形、圆、泡泡等),并显示血条(Boss 和精英)。
敌人生成位置在屏幕四边随机,类型随机,但难度越高精英概率越大。
(3)Particle(粒子)
一个简单的粒子类,用于击中和死亡特效:
初始化时设置随机方向和速度。
life 逐渐减少,大小和透明度随之衰减。
draw() 根据生命值计算颜色透明度(Alpha)和大小。
4.碰撞伤害体系
游戏中有两类碰撞,均使用圆形/矩形近似的简单方法:
(1)玩家与敌人
用 pygame.Rect 创建玩家和敌人的包围矩形:
python
player_rect = pygame.Rect(self.player.x - self.player.radius, ...)
enemy_rect = pygame.Rect(enemy.x - enemy.radius, ...)
if player_rect.colliderect(enemy_rect):
# 处理伤害和特殊效果
这种方式计算快,适合大量敌人。半径越小的敌人,矩形近似误差可接受。
(2)投射物与敌人
同样用 colliderect 检测,命中后:
敌人扣血,若死亡则记录击杀、生成粒子、移除敌人。
投射物自身移除(单次命中即消失,非穿透)。
无敌帧 防止连续碰撞:玩家受伤后 invincible_timer 启动 0.5 秒,期间 take_damage() 直接返回。
5.波次与难度系统
游戏时长 120 秒,分为 4 个 30 秒波次,由 wave_timer 计时:
每次 wave_timer >= 30 时重置计时,调用 start_wave():
current_wave += 1
difficulty += 0.2
弹出升级选择(state = 'levelup')
奖励 10 点时间
难度影响:
敌人生成速率:spawn_enemy() 中 random.random() < 0.02 * self.difficulty,每秒约 2% 概率(受难度倍增)。
敌人类型权重:difficulty > 1.5 时 DDL 概率增加;> 2.0 时点名概率增加。
最后 30 秒(game_time >= 90)自动召唤 Boss,且只召唤一次。
6.技能系统
技能分为主动技能(空格释放)和被动升级(波次结束时选择)。
主动技能
player.use_skill() 检查精力和冷却,返回一个爆炸效果字典:
python
{'type': 'explosion', 'x': x, 'y': y, 'radius': 100, 'damage': 30}
在 Game 的事件处理中,获取该效果后遍历所有敌人,对距离小于半径的造成伤害并可能击杀。
被动技能
波次结束时从 skill_pool 随机抽 3 个,玩家点击选择。
apply_skill() 调用 player.add_skill(),其中直接用 if-elif 修改玩家属性:
咖啡狂热:attack_speed *= 0.5(攻击间隔减半)
学霸附体:attack_damage += 5
运动健将:speed += 2
时间管理:max_time += 20; time += 20
精力充沛:energy_regen *= 1.5
(这些效果永久叠加,构成 Roguelike 式的成长。)
(升级界面使用简单的矩形碰撞检测判断鼠标点击了哪个选项。)
7.总结:
本程序使用的关键知识
Pygame 坐标系:左上角 (0,0),x 右增,y 下增。所有绘制位置需转换。
Surface 和 Alpha:pygame.Surface((w,h), pygame.SRCALPHA) 创建支持透明度的图层,可用于画半透明遮罩或粒子。
事件队列:pygame.event.get() 一次性取走所有事件,必须在每帧处理,否则会堆积。
键盘状态:pygame.key.get_pressed() 返回所有键的当前按下状态,适合连续移动;而 KEYDOWN 事件适合单次触发(如技能)。
鼠标位置:pygame.mouse.get_pos() 实时获取,用于瞄准和点击检测。
碰撞检测:pygame.Rect.colliderect() 快速判断矩形重叠。
三角函数:math.atan2(dy, dx) 计算两点间角度,用于自动瞄准和投射物方向。
帧率控制:pygame.time.Clock.tick(fps) 返回本帧耗时,可用于实现与帧率无关的物理(本游戏简单地把 dt=1/FPS 当作固定步长)。
数据驱动设计:虽然本简化版没有外部 JSON,但技能库 skill_pool、敌人属性等都使用字典/列表集中管理,方便修改和扩展。
六.最终代码版本
`"""
Deadline 生存计划:GPA 保卫战 - 简化版
一个俯视角生存割草游戏,玩家扮演大学生在期末月中生存
"""
import pygame
import random
import math
import json
from collections import defaultdict
import os
os.environ['SDL_VIDEO_CENTERED'] = '1' # 窗口居中(可选)
初始化 Pygame
pygame.init()
游戏常量
SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
FPS = 60
颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 50, 255)
YELLOW = (255, 255, 50)
PURPLE = (200, 100, 255)
GRAY = (128, 128, 128)
DARK_GRAY = (64, 64, 64)
LIGHT_BLUE = (100, 150, 255)
ORANGE = (255, 165, 0)
class Player:
"""玩家类 - 大学生"""
def init(self, x, y):
pygame.font.init()
self.x = x
self.y = y
self.radius = 15
self.speed = 5
核心资源
self.time = 100 # 相当于血量
self.max_time = 100
self.energy = 100 # 相当于蓝量
self.max_energy = 100
self.energy_regen = 0.3
战斗属性
self.attack_damage = 10
self.attack_speed = 0.5 # 攻击间隔(秒)
self.attack_timer = 0
self.attack_range = 250
self.projectile_speed = 8
self.projectile_count = 1
状态效果
self.confusion_timer = 0
self.slow_timer = 0
self.slow_amount = 1.0
self.invincible_timer = 0
self.invincible_duration = 0.5
技能系统
self.skills = []
self.skill_timers = {}
统计
self.kills = 0
self.damage_taken = 0
self.skills_used = 0
def update(self, keys, mouse_pos):
# 自然时间流逝(每秒减少0.1)
self.time -= 0.1
能量恢复
self.energy = min(self.max_energy, self.energy + self.energy_regen)
更新状态效果
if self.confusion_timer > 0:
self.confusion_timer -= 1 / FPS
if self.slow_timer > 0:
self.slow_timer -= 1 / FPS
else:
self.slow_amount = 1.0
if self.invincible_timer > 0:
self.invincible_timer -= 1 / FPS
移动控制
move_x = 0
move_y = 0
current_speed = self.speed * self.slow_amount
if self.confusion_timer > 0:
# 混乱状态:方向反转
if keys[pygame.K_w]: move_y += current_speed
if keys[pygame.K_s]: move_y -= current_speed
if keys[pygame.K_a]: move_x += current_speed
if keys[pygame.K_d]: move_x -= current_speed
else:
if keys[pygame.K_w]: move_y -= current_speed
if keys[pygame.K_s]: move_y += current_speed
if keys[pygame.K_a]: move_x -= current_speed
if keys[pygame.K_d]: move_x += current_speed
更新位置
self.x += move_x
self.y += move_y
边界限制
self.x = max(50 + self.radius, min(SCREEN_WIDTH - 50 - self.radius, self.x))
self.y = max(50 + self.radius, min(SCREEN_HEIGHT - 50 - self.radius, self.y))
更新攻击计时器
self.attack_timer -= 1 / FPS
更新技能计时器
for skill in list(self.skill_timers.keys()):
self.skill_timers[skill] -= 1 / FPS
if self.skill_timers[skill] <= 0:
del self.skill_timers[skill]
def can_attack(self):
return self.attack_timer <= 0
def attack(self, target_x, target_y):
"""自动攻击最近的敌人"""
if not self.can_attack():
return []
self.attack_timer = self.attack_speed
projectiles = []
计算方向
angle = math.atan2(target_y - self.y, target_x - self.x)
发射多个投射物
for i in range(self.projectile_count):
spread = (i - self.projectile_count // 2) * 0.2 if self.projectile_count > 1 else 0
proj_angle = angle + spread
projectiles.append({
'x': self.x,
'y': self.y,
'vx': math.cos(proj_angle) * self.projectile_speed,
'vy': math.sin(proj_angle) * self.projectile_speed,
'damage': self.attack_damage,
'life': 2.0
})
return projectiles
def take_damage(self, amount):
"""受到伤害"""
if self.invincible_timer <= 0:
self.time -= amount
self.damage_taken += amount
self.invincible_timer = self.invincible_duration
def use_skill(self):
"""使用主动技能"""
if self.energy >= 30 and 'skill_cooldown' not in self.skill_timers:
self.energy -= 30
self.skills_used += 1
self.skill_timers['skill_cooldown'] = 5.0
return {
'type': 'explosion',
'x': self.x,
'y': self.y,
'radius': 100,
'damage': 30
}
return None
def add_skill(self, skill_name):
"""添加被动技能"""
self.skills.append(skill_name)
应用技能效果
if skill_name == '咖啡狂热':
self.attack_speed *= 0.5
elif skill_name == '学霸附体':
self.attack_damage += 5
elif skill_name == '运动健将':
self.speed += 2
elif skill_name == '时间管理':
self.max_time += 20
self.time += 20
elif skill_name == '精力充沛':
self.energy_regen *= 1.5
def draw(self, screen):
"""绘制玩家"""
# 无敌闪烁效果
if self.invincible_timer > 0 and int(self.invincible_timer * 10) % 2 == 0:
return
绘制身体
color = BLUE
if self.confusion_timer > 0:
color = RED
elif self.slow_timer > 0:
color = PURPLE
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius, 2)
绘制方向指示器
mouse_pos = pygame.mouse.get_pos()
angle = math.atan2(mouse_pos[1] - self.y, mouse_pos[0] - self.x)
end_x = self.x + math.cos(angle) * (self.radius + 8)
end_y = self.y + math.sin(angle) * (self.radius + 8)
pygame.draw.line(screen, WHITE, (self.x, self.y), (end_x, end_y), 2)
class Enemy:
"""敌人类 - 各种大学危机"""
def init(self, x, y, enemy_type):
self.x = x
self.y = y
self.type = enemy_type
self.alive = True
根据类型设置属性
if enemy_type == 'homework':
self.radius = 12
self.speed = 1.5
self.health = 20
self.damage = 3
self.color = WHITE
self.time_penalty = 0
elif enemy_type == 'ddl':
self.radius = 16
self.speed = 2.5
self.health = 40
self.damage = 5
self.color = RED
self.time_penalty = 5
self.can_explode = True
elif enemy_type == 'attendance':
self.radius = 10
self.speed = 4.0
self.health = 15
self.damage = 8
self.color = ORANGE
self.time_penalty = 10
elif enemy_type == 'social':
self.radius = 14
self.speed = 1.8
self.health = 30
self.damage = 2
self.color = GREEN
self.time_penalty = 0
self.confusion_duration = 2.0
elif enemy_type == 'boss':
self.radius = 25
self.speed = 1.0
self.health = 200
self.damage = 15
self.color = PURPLE
self.time_penalty = 20
self.max_health = self.health
self.animation_timer = 0
def update(self, player_x, player_y):
"""更新敌人位置"""
self.animation_timer += 0.05
移向玩家
dx = player_x - self.x
dy = player_y - self.y
distance = max(1, math.sqrt(dx ** 2 + dy ** 2))
self.x += (dx / distance) * self.speed
self.y += (dy / distance) * self.speed
def take_damage(self, damage):
"""受到伤害"""
self.health -= damage
if self.health <= 0:
self.alive = False
def draw(self, screen):
"""绘制敌人"""
if not self.alive:
return
if self.type == 'homework':
# 作业:白色方块
rect = pygame.Rect(self.x - self.radius, self.y - self.radius,
self.radius * 2, self.radius * 2)
pygame.draw.rect(screen, self.color, rect)
pygame.draw.rect(screen, GRAY, rect, 2)
elif self.type == 'ddl':
# DDL:红色三角形警告
points = [
(self.x, self.y - self.radius),
(self.x + self.radius, self.y + self.radius * 0.7),
(self.x - self.radius, self.y + self.radius * 0.7)
]
pygame.draw.polygon(screen, self.color, points)
# 绘制感叹号
font = pygame.font.Font(None, 20)
text = font.render("!", True, WHITE)
text_rect = text.get_rect(center=(self.x, self.y))
screen.blit(text, text_rect)
elif self.type == 'attendance':
# 点名:快速红色圆点
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), self.radius + 2, 2)
elif self.type == 'social':
# 社交邀约:彩色泡泡
hue = (math.sin(self.animation_timer) + 1) / 2
color = (
int(200 + 55 * hue),
int(200 + 55 * (1 - hue)),
int(200)
)
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)
elif self.type == 'boss':
# Boss:大型紫色实体
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius, 3)
# 闪烁光环
aura_radius = self.radius + 5 * (1 + math.sin(self.animation_timer * 2))
pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), int(aura_radius), 1)
绘制血条(仅精英怪和Boss)
if self.max_health >= 40:
bar_width = self.radius * 2
bar_height = 3
health_percent = self.health / self.max_health
bar_x = self.x - bar_width // 2
bar_y = self.y - self.radius - 8
pygame.draw.rect(screen, DARK_GRAY, (bar_x, bar_y, bar_width, bar_height))
pygame.draw.rect(screen, RED, (bar_x, bar_y, bar_width * health_percent, bar_height))
class Particle:
"""粒子效果类"""
def init(self, x, y, color, speed=2):
self.x = x
self.y = y
angle = random.uniform(0, 2 * math.pi)
self.vx = math.cos(angle) * random.uniform(0.5, 1) * speed
self.vy = math.sin(angle) * random.uniform(0.5, 1) * speed
self.life = 1.0
self.max_life = 1.0
self.color = color
self.size = random.randint(2, 5)
def update(self):
self.x += self.vx
self.y += self.vy
self.life -= 0.02
def draw(self, screen):
if self.life > 0:
alpha = int(255 * self.life)
color = (*self.color, alpha)
size = int(self.size * self.life)
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), size)
pygame.init()
游戏常量
SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 768
FPS = 60
颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 50, 50)
GREEN = (50, 255, 50)
BLUE = (50, 50, 255)
YELLOW = (255, 255, 50)
PURPLE = (200, 100, 255)
GRAY = (128, 128, 128)
DARK_GRAY = (64, 64, 64)
LIGHT_BLUE = (100, 150, 255)
ORANGE = (255, 165, 0)
class Player:
"""玩家类 - 大学生"""
def init(self, x, y):
pygame.font.init()
self.x = x
self.y = y
self.radius = 15
self.speed = 5
核心资源
self.time = 100 # 相当于血量
self.max_time = 100
self.energy = 100 # 相当于蓝量
self.max_energy = 100
self.energy_regen = 0.3
战斗属性
self.attack_damage = 10
self.attack_speed = 0.5 # 攻击间隔(秒)
self.attack_timer = 0
self.attack_range = 250
self.projectile_speed = 8
self.projectile_count = 1
状态效果
self.confusion_timer = 0
self.slow_timer = 0
self.slow_amount = 1.0
self.invincible_timer = 0
self.invincible_duration = 0.5
技能系统
self.skills = []
self.skill_timers = {}
统计
self.kills = 0
self.damage_taken = 0
self.skills_used = 0
def update(self, keys, mouse_pos):
# 自然时间流逝(每秒减少0.1)
self.time -= 0.1
能量恢复
self.energy = min(self.max_energy, self.energy + self.energy_regen)
更新状态效果
if self.confusion_timer > 0:
self.confusion_timer -= 1 / FPS
if self.slow_timer > 0:
self.slow_timer -= 1 / FPS
else:
self.slow_amount = 1.0
if self.invincible_timer > 0:
self.invincible_timer -= 1 / FPS
移动控制
move_x = 0
move_y = 0
current_speed = self.speed * self.slow_amount
if self.confusion_timer > 0:
# 混乱状态:方向反转
if keys[pygame.K_w]: move_y += current_speed
if keys[pygame.K_s]: move_y -= current_speed
if keys[pygame.K_a]: move_x += current_speed
if keys[pygame.K_d]: move_x -= current_speed
else:
if keys[pygame.K_w]: move_y -= current_speed
if keys[pygame.K_s]: move_y += current_speed
if keys[pygame.K_a]: move_x -= current_speed
if keys[pygame.K_d]: move_x += current_speed
更新位置
self.x += move_x
self.y += move_y
边界限制
self.x = max(50 + self.radius, min(SCREEN_WIDTH - 50 - self.radius, self.x))
self.y = max(50 + self.radius, min(SCREEN_HEIGHT - 50 - self.radius, self.y))
更新攻击计时器
self.attack_timer -= 1 / FPS
更新技能计时器
for skill in list(self.skill_timers.keys()):
self.skill_timers[skill] -= 1 / FPS
if self.skill_timers[skill] <= 0:
del self.skill_timers[skill]
def can_attack(self):
return self.attack_timer <= 0
def attack(self, target_x, target_y):
"""自动攻击最近的敌人"""
if not self.can_attack():
return []
self.attack_timer = self.attack_speed
projectiles = []
计算方向
angle = math.atan2(target_y - self.y, target_x - self.x)
发射多个投射物
for i in range(self.projectile_count):
spread = (i - self.projectile_count // 2) * 0.2 if self.projectile_count > 1 else 0
proj_angle = angle + spread
projectiles.append({
'x': self.x,
'y': self.y,
'vx': math.cos(proj_angle) * self.projectile_speed,
'vy': math.sin(proj_angle) * self.projectile_speed,
'damage': self.attack_damage,
'life': 2.0
})
return projectiles
def take_damage(self, amount):
"""受到伤害"""
if self.invincible_timer <= 0:
self.time -= amount
self.damage_taken += amount
self.invincible_timer = self.invincible_duration
def use_skill(self):
"""使用主动技能"""
if self.energy >= 30 and 'skill_cooldown' not in self.skill_timers:
self.energy -= 30
self.skills_used += 1
self.skill_timers['skill_cooldown'] = 5.0
return {
'type': 'explosion',
'x': self.x,
'y': self.y,
'radius': 100,
'damage': 30
}
return None
def add_skill(self, skill_name):
"""添加被动技能"""
self.skills.append(skill_name)
应用技能效果
if skill_name == '咖啡狂热':
self.attack_speed *= 0.5
elif skill_name == '学霸附体':
self.attack_damage += 5
elif skill_name == '运动健将':
self.speed += 2
elif skill_name == '时间管理':
self.max_time += 20
self.time += 20
elif skill_name == '精力充沛':
self.energy_regen *= 1.5
def draw(self, screen):
"""绘制玩家"""
# 无敌闪烁效果
if self.invincible_timer > 0 and int(self.invincible_timer * 10) % 2 == 0:
return
绘制身体
color = BLUE
if self.confusion_timer > 0:
color = RED
elif self.slow_timer > 0:
color = PURPLE
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius, 2)
绘制方向指示器
mouse_pos = pygame.mouse.get_pos()
angle = math.atan2(mouse_pos[1] - self.y, mouse_pos[0] - self.x)
end_x = self.x + math.cos(angle) * (self.radius + 8)
end_y = self.y + math.sin(angle) * (self.radius + 8)
pygame.draw.line(screen, WHITE, (self.x, self.y), (end_x, end_y), 2)
class Enemy:
"""敌人类 - 各种大学危机"""
def init(self, x, y, enemy_type):
self.x = x
self.y = y
self.type = enemy_type
self.alive = True
根据类型设置属性
if enemy_type == 'homework':
self.radius = 12
self.speed = 1.5
self.health = 20
self.damage = 3
self.color = WHITE
self.time_penalty = 0
elif enemy_type == 'ddl':
self.radius = 16
self.speed = 2.5
self.health = 40
self.damage = 5
self.color = RED
self.time_penalty = 5
self.can_explode = True
elif enemy_type == 'attendance':
self.radius = 10
self.speed = 4.0
self.health = 15
self.damage = 8
self.color = ORANGE
self.time_penalty = 10
elif enemy_type == 'social':
self.radius = 14
self.speed = 1.8
self.health = 30
self.damage = 2
self.color = GREEN
self.time_penalty = 0
self.confusion_duration = 2.0
elif enemy_type == 'boss':
self.radius = 25
self.speed = 1.0
self.health = 200
self.damage = 15
self.color = PURPLE
self.time_penalty = 20
self.max_health = self.health
self.animation_timer = 0
def update(self, player_x, player_y):
"""更新敌人位置"""
self.animation_timer += 0.05
移向玩家
dx = player_x - self.x
dy = player_y - self.y
distance = max(1, math.sqrt(dx ** 2 + dy ** 2))
self.x += (dx / distance) * self.speed
self.y += (dy / distance) * self.speed
def take_damage(self, damage):
"""受到伤害"""
self.health -= damage
if self.health <= 0:
self.alive = False
def draw(self, screen):
"""绘制敌人"""
if not self.alive:
return
if self.type == 'homework':
# 作业:白色方块
rect = pygame.Rect(self.x - self.radius, self.y - self.radius,
self.radius * 2, self.radius * 2)
pygame.draw.rect(screen, self.color, rect)
pygame.draw.rect(screen, GRAY, rect, 2)
elif self.type == 'ddl':
# DDL:红色三角形警告
points = [
(self.x, self.y - self.radius),
(self.x + self.radius, self.y + self.radius * 0.7),
(self.x - self.radius, self.y + self.radius * 0.7)
]
pygame.draw.polygon(screen, self.color, points)
# 绘制感叹号
font = pygame.font.Font(None, 20)
text = font.render("!", True, WHITE)
text_rect = text.get_rect(center=(self.x, self.y))
screen.blit(text, text_rect)
elif self.type == 'attendance':
# 点名:快速红色圆点
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), self.radius + 2, 2)
elif self.type == 'social':
# 社交邀约:彩色泡泡
hue = (math.sin(self.animation_timer) + 1) / 2
color = (
int(200 + 55 * hue),
int(200 + 55 * (1 - hue)),
int(200)
)
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)
elif self.type == 'boss':
# Boss:大型紫色实体
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius, 3)
# 闪烁光环
aura_radius = self.radius + 5 * (1 + math.sin(self.animation_timer * 2))
pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), int(aura_radius), 1)
绘制血条(仅精英怪和Boss)
if self.max_health >= 40:
bar_width = self.radius * 2
bar_height = 3
health_percent = self.health / self.max_health
bar_x = self.x - bar_width // 2
bar_y = self.y - self.radius - 8
pygame.draw.rect(screen, DARK_GRAY, (bar_x, bar_y, bar_width, bar_height))
pygame.draw.rect(screen, RED, (bar_x, bar_y, bar_width * health_percent, bar_height))
class Particle:
"""粒子效果类"""
def init(self, x, y, color, speed=2):
self.x = x
self.y = y
angle = random.uniform(0, 2 * math.pi)
self.vx = math.cos(angle) * random.uniform(0.5, 1) * speed
self.vy = math.sin(angle) * random.uniform(0.5, 1) * speed
self.life = 1.0
self.max_life = 1.0
self.color = color
self.size = random.randint(2, 5)
def update(self):
self.x += self.vx
self.y += self.vy
self.life -= 0.02
def draw(self, screen):
if self.life > 0:
alpha = int(255 * self.life)
color = (*self.color, alpha)
size = int(self.size * self.life)
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), size)
class Game:
def init(self):
pygame.font.init()
# 字体加载(带容错)
try:
font_path = "C:/Windows/Fonts/msyh.ttf"
self.font_large = pygame.font.Font(font_path, 48)
self.font_medium = pygame.font.Font(font_path, 36)
self.font_small = pygame.font.Font(font_path, 24)
except:
self.font_large = pygame.font.Font(None, 48)
self.font_medium = pygame.font.Font(None, 36)
self.font_small = pygame.font.Font(None, 24)
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Deadline 生存计划:GPA 保卫战")
self.clock = pygame.time.Clock()
游戏状态
self.state = 'menu'
self.player = None
self.enemies = []
self.projectiles = []
self.particles = []
self.skill_effects = []
游戏数据
self.game_time = 0
self.total_time = 120 # 2分钟游戏时长
self.wave_timer = 0
self.wave_duration = 30 # 每30秒一波
self.current_wave = 0
self.difficulty = 1.0
升级选择
self.level_up_options = []
self.selected_option = -1
统计
self.enemy_kills = defaultdict(int)
self.total_kills = 0
字体
self.font_large = pygame.font.Font(None, 48)
self.font_medium = pygame.font.Font(None, 36)
self.font_small = pygame.font.Font(None, 24)
技能库
self.skill_pool = [
{'name': '咖啡狂热', 'desc': '攻击速度翻倍'},
{'name': '学霸附体', 'desc': '攻击力+5'},
{'name': '运动健将', 'desc': '移动速度+2'},
{'name': '时间管理', 'desc': '时间上限+20'},
{'name': '精力充沛', 'desc': '精力恢复速度+50%'}
]
def reset_game(self):
"""重置游戏"""
self.player = Player(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)
self.enemies = []
self.projectiles = []
self.particles = []
self.skill_effects = []
self.game_time = 0
self.wave_timer = 0
self.current_wave = 0
self.total_kills = 0
self.enemy_kills.clear()
self.level_up_options = []
self.selected_option = -1
def spawn_enemy(self):
"""生成敌人"""
# 在屏幕边缘生成
side = random.randint(0, 3)
if side == 0: # 上方
x = random.randint(50, SCREEN_WIDTH - 50)
y = 30
elif side == 1: # 下方
x = random.randint(50, SCREEN_WIDTH - 50)
y = SCREEN_HEIGHT - 30
elif side == 2: # 左侧
x = 30
y = random.randint(50, SCREEN_HEIGHT - 50)
else: # 右侧
x = SCREEN_WIDTH - 30
y = random.randint(50, SCREEN_HEIGHT - 50)
根据难度选择敌人类型
roll = random.random()
if self.difficulty > 1.5 and roll < 0.1:
enemy_type = 'ddl'
elif self.difficulty > 2.0 and roll < 0.15:
enemy_type = 'attendance'
elif roll < 0.2:
enemy_type = 'social'
else:
enemy_type = 'homework'
enemy = Enemy(x, y, enemy_type)
self.enemies.append(enemy)
def spawn_boss(self):
"""生成Boss"""
boss = Enemy(SCREEN_WIDTH // 2, 100, 'boss')
self.enemies.append(boss)
def start_wave(self):
"""开始新一波"""
self.current_wave += 1
self.difficulty += 0.2
生成升级选择
self.level_up_options = random.sample(self.skill_pool, 3)
self.state = 'levelup'
奖励时间
self.player.time = min(self.player.max_time, self.player.time + 10)
def apply_skill(self, skill_name):
"""应用技能"""
self.player.add_skill(skill_name)
if skill_name == '咖啡狂热':
self.skill_effects.append({
'text': '攻击速度翻倍!',
'timer': 2.0,
'color': YELLOW
})
elif skill_name == '学霸附体':
self.skill_effects.append({
'text': '攻击力提升!',
'timer': 2.0,
'color': BLUE
})
elif skill_name == '运动健将':
self.skill_effects.append({
'text': '移动速度提升!',
'timer': 2.0,
'color': GREEN
})
elif skill_name == '时间管理':
self.skill_effects.append({
'text': '时间上限增加!',
'timer': 2.0,
'color': WHITE
})
elif skill_name == '精力充沛':
self.skill_effects.append({
'text': '精力恢复提升!',
'timer': 2.0,
'color': ORANGE
})
def handle_collisions(self):
"""处理碰撞"""
player_rect = pygame.Rect(self.player.x - self.player.radius,
self.player.y - self.player.radius,
self.player.radius * 2,
self.player.radius * 2)
玩家与敌人的碰撞
for enemy in self.enemies[:]:
if not enemy.alive:
continue
enemy_rect = pygame.Rect(enemy.x - enemy.radius,
enemy.y - enemy.radius,
enemy.radius * 2,
enemy.radius * 2)
if player_rect.colliderect(enemy_rect):
self.player.take_damage(enemy.damage)
特殊效果
if enemy.type == 'social' and self.player.confusion_timer <= 0:
self.player.confusion_timer = enemy.confusion_duration
敌人死亡
if enemy.type != 'boss':
enemy.alive = False
# 生成粒子
for _ in range(5):
self.particles.append(
Particle(enemy.x, enemy.y, enemy.color)
)
投射物与敌人的碰撞
for proj in self.projectiles[:]:
proj_rect = pygame.Rect(proj['x'] - 5, proj['y'] - 5, 10, 10)
for enemy in self.enemies[:]:
if not enemy.alive:
continue
enemy_rect = pygame.Rect(enemy.x - enemy.radius,
enemy.y - enemy.radius,
enemy.radius * 2,
enemy.radius * 2)
if proj_rect.colliderect(enemy_rect):
enemy.take_damage(proj['damage'])
if not enemy.alive:
self.total_kills += 1
self.enemy_kills[enemy.type] += 1
self.player.kills += 1
击杀粒子
for _ in range(10):
self.particles.append(
Particle(enemy.x, enemy.y, enemy.color, 3)
)
移除敌人
if enemy in self.enemies:
self.enemies.remove(enemy)
移除投射物
if proj in self.projectiles:
self.projectiles.remove(proj)
break
清理死亡敌人
self.enemies = [e for e in self.enemies if e.alive]
def handle_skill_effects(self):
"""处理技能效果"""
# 更新技能效果文字
for effect in self.skill_effects[:]:
effect['timer'] -= 1 / FPS
if effect['timer'] <= 0:
self.skill_effects.remove(effect)
def get_nearest_enemy(self):
"""获取最近的敌人"""
nearest = None
min_dist = float('inf')
for enemy in self.enemies:
if not enemy.alive:
continue
dx = enemy.x - self.player.x
dy = enemy.y - self.player.y
dist = math.sqrt(dx ** 2 + dy ** 2)
if dist < min_dist:
min_dist = dist
nearest = enemy
return nearest
def update(self):
"""更新游戏逻辑"""
if self.state != 'playing':
return
更新时间
dt = 1 / FPS
self.game_time += dt
self.wave_timer += dt
检查游戏结束条件
if self.player.time <= 0:
self.state = 'gameover'
return
if self.game_time >= self.total_time:
self.state = 'gameover'
return
波次管理
if self.wave_timer >= self.wave_duration:
self.wave_timer = 0
self.start_wave()
更新玩家
keys = pygame.key.get_pressed()
mouse_pos = pygame.mouse.get_pos()
self.player.update(keys, mouse_pos)
自动攻击
nearest_enemy = self.get_nearest_enemy()
if nearest_enemy:
new_projectiles = self.player.attack(nearest_enemy.x, nearest_enemy.y)
self.projectiles.extend(new_projectiles)
更新投射物
for proj in self.projectiles[:]:
proj['x'] += proj['vx'] * dt * 60
proj['y'] += proj['vy'] * dt * 60
proj['life'] -= dt
移除超出屏幕或生命结束的投射物
if (proj['life'] <= 0 or
proj['x'] < 0 or proj['x'] > SCREEN_WIDTH or
proj['y'] < 0 or proj['y'] > SCREEN_HEIGHT):
self.projectiles.remove(proj)
更新敌人
for enemy in self.enemies:
enemy.update(self.player.x, self.player.y)
生成敌人
if random.random() < 0.02 * self.difficulty: # 每秒2%概率,难度影响
self.spawn_enemy()
Boss战(最后30秒)
if self.game_time >= self.total_time - 30 and not any(
e.type == 'boss' for e in self.enemies):
self.spawn_boss()
碰撞检测
self.handle_collisions()
更新粒子
for particle in self.particles[:]:
particle.update()
if particle.life <= 0:
self.particles.remove(particle)
更新技能效果
self.handle_skill_effects()
清理已死亡敌人
self.enemies = [e for e in self.enemies if e.alive]
def handle_levelup_click(self, mouse_pos):
"""处理升级选择点击"""
option_height = 50
start_y = SCREEN_HEIGHT // 2 - 80
for i in range(len(self.level_up_options)):
option_rect = pygame.Rect(
SCREEN_WIDTH // 2 - 150,
start_y + i * (option_height + 10),
300,
option_height
)
if option_rect.collidepoint(mouse_pos):
skill_name = self.level_up_options[i]['name']
self.apply_skill(skill_name)
self.state = 'playing'
break
def draw_ui(self):
"""绘制UI"""
# 时间条
time_percent = self.player.time / self.player.max_time
bar_width = 200
bar_height = 15
bar_x = 20
bar_y = 20
背景
pygame.draw.rect(self.screen, DARK_GRAY, (bar_x, bar_y, bar_width, bar_height))
# 当前时间
time_color = GREEN if time_percent > 0.5 else YELLOW if time_percent > 0.25 else RED
pygame.draw.rect(self.screen, time_color,
(bar_x, bar_y, bar_width * time_percent, bar_height))
pygame.draw.rect(self.screen, WHITE, (bar_x, bar_y, bar_width, bar_height), 2)
时间文字
time_text = self.font_small.render(f"时间: {int(self.player.time)}", True, WHITE)
self.screen.blit(time_text, (bar_x + bar_width + 10, bar_y - 2))
精力条
energy_percent = self.player.energy / self.player.max_energy
energy_y = bar_y + bar_height + 10
pygame.draw.rect(self.screen, DARK_GRAY, (bar_x, energy_y, bar_width, bar_height))
pygame.draw.rect(self.screen, BLUE,
(bar_x, energy_y, bar_width * energy_percent, bar_height))
pygame.draw.rect(self.screen, WHITE, (bar_x, energy_y, bar_width, bar_height), 2)
精力文字
energy_text = self.font_small.render(f"精力: {int(self.player.energy)}", True, WHITE)
self.screen.blit(energy_text, (bar_x + bar_width + 10, energy_y - 2))
游戏时间
time_left = max(0, self.total_time - self.game_time)
time_text = self.font_medium.render(f"剩余: {time_left:.1f}秒", True, WHITE)
self.screen.blit(time_text, (SCREEN_WIDTH - 200, 20))
波次信息
wave_text = self.font_small.render(f"第 {self.current_wave + 1} 波", True, WHITE)
self.screen.blit(wave_text, (SCREEN_WIDTH - 200, 50))
击杀计数
kills_text = self.font_small.render(f"击杀: {self.total_kills}", True, WHITE)
self.screen.blit(kills_text, (SCREEN_WIDTH - 200, 75))
技能列表
y_offset = 110
for skill in self.player.skills:
skill_text = self.font_small.render(f"✓ {skill}", True, GREEN)
self.screen.blit(skill_text, (20, y_offset))
y_offset += 20
技能效果文字
for effect in self.skill_effects:
alpha = min(255, int(255 * effect['timer'] / 2.0))
text_surface = self.font_medium.render(effect['text'], True, effect['color'])
text_surface.set_alpha(alpha)
text_rect = text_surface.get_rect(center=(SCREEN_WIDTH // 2, 100))
self.screen.blit(text_surface, text_rect)
def draw_levelup_menu(self):
"""绘制升级选择菜单"""
# 半透明背景
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
overlay.set_alpha(200)
overlay.fill(BLACK)
self.screen.blit(overlay, (0, 0))
标题
title = self.font_large.render("升级!选择技能", True, YELLOW)
title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 120))
self.screen.blit(title, title_rect)
选项
option_height = 50
start_y = SCREEN_HEIGHT // 2 - 80
for i, option in enumerate(self.level_up_options):
option_rect = pygame.Rect(
SCREEN_WIDTH // 2 - 150,
start_y + i * (option_height + 10),
300,
option_height
)
选项背景
color = DARK_GRAY if i != self.selected_option else LIGHT_BLUE
pygame.draw.rect(self.screen, color, option_rect)
pygame.draw.rect(self.screen, WHITE, option_rect, 2)
选项文字
name_text = self.font_medium.render(option['name'], True, WHITE)
name_rect = name_text.get_rect(
center=(option_rect.centerx, option_rect.centery - 8)
)
self.screen.blit(name_text, name_rect)
desc_text = self.font_small.render(option['desc'], True, GRAY)
desc_rect = desc_text.get_rect(
center=(option_rect.centerx, option_rect.centery + 15)
)
self.screen.blit(desc_text, desc_rect)
def draw_gameover(self):
"""绘制游戏结束界面"""
# 半透明背景
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
overlay.set_alpha(200)
overlay.fill(BLACK)
self.screen.blit(overlay, (0, 0))
计算GPA
survival_ratio = self.game_time / self.total_time
if survival_ratio >= 0.95:
gpa_grade = 'S'
grade_color = YELLOW
elif survival_ratio >= 0.85:
gpa_grade = 'A'
grade_color = GREEN
elif survival_ratio >= 0.70:
gpa_grade = 'B'
grade_color = BLUE
elif survival_ratio >= 0.55:
gpa_grade = 'C'
grade_color = WHITE
elif survival_ratio >= 0.40:
gpa_grade = 'D'
grade_color = ORANGE
else:
gpa_grade = 'F'
grade_color = RED
标题
title = self.font_large.render("考试结束!", True, WHITE)
title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 150))
self.screen.blit(title, title_rect)
GPA
gpa_text = self.font_large.render(f"GPA: {gpa_grade}", True, grade_color)
gpa_rect = gpa_text.get_rect(center=(SCREEN_WIDTH // 2, 220))
self.screen.blit(gpa_text, gpa_rect)
统计信息
stats = [
f"存活时间: {self.game_time:.1f}秒 / {self.total_time}秒",
f"击败敌人: {self.total_kills}",
f"受到伤害: {self.player.damage_taken:.0f}",
f"使用技能: {self.player.skills_used}次",
f"获得技能: {len(self.player.skills)}个"
]
y_offset = 300
for stat in stats:
text = self.font_medium.render(stat, True, WHITE)
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, y_offset))
self.screen.blit(text, text_rect)
y_offset += 35
击败敌人统计
if self.enemy_kills:
y_offset += 20
enemy_text = self.font_medium.render("击败敌人分布:", True, WHITE)
self.screen.blit(enemy_text, (SCREEN_WIDTH // 2 - 100, y_offset))
y_offset += 30
for enemy_type, count in self.enemy_kills.items():
type_names = {
'homework': '作业',
'ddl': 'DDL',
'attendance': '点名',
'social': '社交邀约',
'boss': '期末考试'
}
name = type_names.get(enemy_type, enemy_type)
text = self.font_small.render(f"{name}: {count}", True, GRAY)
self.screen.blit(text, (SCREEN_WIDTH // 2 - 80, y_offset))
y_offset += 20
操作提示
y_offset += 30
restart_text = self.font_medium.render("按 R 重新开始 按 ESC 返回菜单", True, YELLOW)
restart_rect = restart_text.get_rect(center=(SCREEN_WIDTH // 2, y_offset))
self.screen.blit(restart_text, restart_rect)
def draw_menu(self):
"""绘制主菜单"""
self.screen.fill(DARK_GRAY)
标题
title = self.font_large.render("Deadline 生存计划", True, WHITE)
title_rect = title.get_rect(center=(SCREEN_WIDTH // 2, 200))
self.screen.blit(title, title_rect)
subtitle = self.font_medium.render("GPA 保卫战", True, YELLOW)
subtitle_rect = subtitle.get_rect(center=(SCREEN_WIDTH // 2, 250))
self.screen.blit(subtitle, subtitle_rect)
游戏说明
instructions = [
"WASD - 移动",
"鼠标 - 瞄准方向",
"空格 - 使用技能(消耗30精力)",
"ESC - 暂停游戏",
"",
"目标:在期末月中存活120秒!",
"注意管理你的时间和精力"
]
y_offset = 320
for line in instructions:
text = self.font_small.render(line, True, GRAY)
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, y_offset))
self.screen.blit(text, text_rect)
y_offset += 25
开始按钮
start_text = self.font_large.render("按 ENTER 开始游戏", True, GREEN)
start_rect = start_text.get_rect(center=(SCREEN_WIDTH // 2, 550))
self.screen.blit(start_text, start_rect)
闪烁效果
if int(pygame.time.get_ticks() / 500) % 2:
pygame.draw.rect(self.screen, GREEN,
(start_rect.x - 10, start_rect.y - 5,
start_rect.width + 20, start_rect.height + 10), 2)
def draw_pause_menu(self):
"""绘制暂停菜单"""
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
overlay.set_alpha(128)
overlay.fill(BLACK)
self.screen.blit(overlay, (0, 0))
pause_text = self.font_large.render("游戏暂停", True, WHITE)
pause_rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
self.screen.blit(pause_text, pause_rect)
continue_text = self.font_small.render("按 ESC 继续", True, WHITE)
continue_rect = continue_text.get_rect(
center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 40)
)
self.screen.blit(continue_text, continue_rect)
def draw(self):
"""主绘制函数"""
if self.state == 'menu':
self.draw_menu()
elif self.state == 'playing':
# 绘制游戏区域
self.screen.fill((30, 30, 40))
绘制网格
for x in range(50, SCREEN_WIDTH - 50, 50):
pygame.draw.line(self.screen, (50, 50, 60),
(x, 50), (x, SCREEN_HEIGHT - 50), 1)
for y in range(50, SCREEN_HEIGHT - 50, 50):
pygame.draw.line(self.screen, (50, 50, 60),
(50, y), (SCREEN_WIDTH - 50, y), 1)
绘制游戏区域边界
game_rect = pygame.Rect(50, 50, SCREEN_WIDTH - 100, SCREEN_HEIGHT - 100)
pygame.draw.rect(self.screen, (100, 100, 120), game_rect, 2)
绘制投射物
for proj in self.projectiles:
pygame.draw.circle(self.screen, YELLOW,
(int(proj['x']), int(proj['y'])), 3)
绘制敌人
for enemy in self.enemies:
enemy.draw(self.screen)
绘制玩家
self.player.draw(self.screen)
绘制粒子
for particle in self.particles:
particle.draw(self.screen)
绘制UI
self.draw_ui()
elif self.state == 'levelup':
self.draw_levelup_menu()
elif self.state == 'gameover':
self.draw_gameover()
elif self.state == 'paused':
self.draw_pause_menu()
def run(self):
"""主游戏循环"""
running = True
while running:
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if self.state == 'menu':
if event.key == pygame.K_RETURN:
self.reset_game()
self.state = 'playing'
elif self.state == 'playing':
if event.key == pygame.K_ESCAPE:
self.state = 'paused'
elif event.key == pygame.K_SPACE:
# 使用技能
effect = self.player.use_skill()
if effect:
self.skill_effects.append({
'text': '技能释放!',
'timer': 1.0,
'color': YELLOW
})
# 对周围敌人造成伤害
for enemy in self.enemies[:]:
dx = enemy.x - effect['x']
dy = enemy.y - effect['y']
if math.sqrt(dx ** 2 + dy ** 2) < effect['radius']:
enemy.take_damage(effect['damage'])
if not enemy.alive:
self.total_kills += 1
self.enemy_kills[enemy.type] += 1
self.enemies.remove(enemy)
elif self.state == 'paused':
if event.key == pygame.K_ESCAPE:
self.state = 'playing'
elif event.key == pygame.K_q:
self.state = 'menu'
elif self.state == 'gameover':
if event.key == pygame.K_r:
self.reset_game()
self.state = 'playing'
elif event.key == pygame.K_ESCAPE:
self.state = 'menu'
elif self.state == 'levelup':
if event.key == pygame.K_ESCAPE:
self.state = 'playing'
elif event.type == pygame.MOUSEBUTTONDOWN:
if self.state == 'levelup':
self.handle_levelup_click(event.pos)
更新游戏
self.update()
绘制游戏
self.draw()
更新显示
pygame.display.flip(
self.clock.tick(FPS)
pygame.quit()
if name == "main":
game = Game()
game.run()`
七.课程总结
1.经过一个学期的学习,我逐渐掌握了python这门语言,在我看来,python无疑是编程语言体系里的一个重要且伟大的发明
python语言在我看来干净得不像是编程语言而是像是一门人类语言,没有之前学习C语言时括号套括号的眼花缭乱别的语言觉得代码是写给机器看的,Python 却像在写伪代码,思路直接转成代码,调试时读起来也很舒服。
2.个人感悟
我选择这门课程很大程度上是受了前几届学长学姐的影响,听得大家都说王老师讲课十分的高水准,亲自体会后自觉不虚此说,在王老师诸如“蛋炒饭和盖浇饭”这样生动形象的授课与引导后,我逐渐迷上了python这门简洁的语言。Python语言不愧于常年在各编程语言使用频次榜中常居前位的语言。
3.对最后一次作业想说的
最后一次作业在快马加鞭后完成了,但是还是有各种遗憾,比如因为游戏机制过难,我至今没有把GPA完成到E以上,比如游戏结算界面,我几次修改优化,也没有办法将乱码问题解决(这也是这次作业提交一拖再拖的缘由之一),由此可见,我的编程水平还有很高的提交空间,希望以后还能通过与王老师和同学们多加交流,促进提高!

