当前位置: 首页 > news >正文

20251216杜立实验四实验报告

20251216 20260323《Python程序设计》实验4报告
课程:《Python程序设计》
班级:2512
姓名:杜立
学号:20251216
实验教师:王志强
实验日期:2026年6月10日
必修/选修:公选课
一.实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
二.项目概述
本程序旨在完成游戏《ddl生存计划:GPA保卫战》。游戏中玩家扮演一名大学生,在“期末月”的战场中,通过移动走位躲避或击破不断涌来的任务(DDL、作业、点名、社交邀约),用有限的时间资源存活到最后。
该游戏将“吸血鬼幸存者”式的割草玩法与大学生的真实生活相结合,非常具有可玩性
三.游戏机制

  1. 资源系统(贴合真实学习生活)
    玩家只有两个核心资源:
    时间(Time):相当于血量,每秒自然流逝,被敌人碰到额外扣除。
    精力(Energy):释放技能消耗,随时间缓慢恢复,相当于蓝量。
  2. 敌人设计(各种“大学危机”)
    所有敌人从屏幕边缘生成,向玩家缓慢移动:
    作业:基础小怪,数量多,移动慢,碰撞扣 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的过程中也不顺利:

屏幕截图 2026-06-22 172242
因为我电脑上的python版本过新,因此即使最新版本的pygame也无法与我的pycharm相互适配,因而我转向使用pygame-ce以完成后续代码调试
2.第一次运行时代码并没有按照预期顺利运行下去,仅游戏开始界面就是一团乱麻,根本无法正常使用。在我排除问题重新进入游戏后,我无法通过预设的“WASD”控制键与鼠标控制人物。
image
image
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以上,比如游戏结算界面,我几次修改优化,也没有办法将乱码问题解决(这也是这次作业提交一拖再拖的缘由之一),由此可见,我的编程水平还有很高的提交空间,希望以后还能通过与王老师和同学们多加交流,促进提高!

http://www.jsqmd.com/news/1063652/

相关文章:

  • 覆盖扫码 / 断连 / 消息异常,OpenClaw 2.7.9 微信机器人故障速查表
  • 最新深圳法律业务律师推荐指南2026:深圳离婚律师离婚财产分割股权分割抚养权纠纷起诉离婚流程 - 逻辑孤岛
  • 2026过炉托盘行业:三大核心发展趋势解读 - 资讯快报
  • Chat LangChain生产环境架构设计:多模型容错与监控系统解决方案
  • 人体姿势智能检索系统:用动作语言重新定义图像搜索
  • WeChatMsg终极指南:数字记忆重构与对话资产化完整方案
  • 如何免费解锁WeMod专业功能:Wand-Enhancer完整实战指南
  • Let‘s Encrypt介绍(免费、自动化、开放的SSL/TLS证书颁发机构CA,Certificate Authority)cert-manager
  • 2026/4/2课程博客 软件测试复习:选择题考点(测试工具+等价类划分)
  • 零基础学AI人工智能:9.4 聚类算法
  • PvZ Toolkit终极指南:植物大战僵尸PC版最全修改器使用教程
  • 2026清远营业性演出许可证有没有正规代办推荐 - 资讯速览
  • 人类学习的本质:从DeepSeek V4看动态反馈与多专家协同
  • Video2X深度解析:如何通过C++架构重构实现高性能视频AI处理
  • 上海高端酒水回收市场调研及靠谱服务商名录汇总 - 海棠依旧大
  • 基于视觉语言模型的交通事故自动分析与报告生成技术实践
  • 无痛季度规划:用实时信号替代传统OKR流程
  • 视频字幕文字提取全攻略:2026保姆级教程,手把手教你免费搞定
  • Vue 3 自定义插件开发实战:从原理到生产级权限指令
  • 苏州卫生间免砸砖防水补漏哪家专业?服务商挑选标准与适用场景 - 徽顺虹
  • 2026年口碑好的 最新 烟台家常菜特色美食餐厅、烟台家常菜老字号饭馆排行:5家地道门店一览 - 起跑123
  • 2026年6月澳洲旅游签证机构优先考虑哪家?5家主流机构资质与服务对比 - 资讯快报
  • keytool-importkeypair深度解析:企业级Java密钥管理架构设计
  • AI工程化三支柱:Agent可视化、模型安全护栏与推理引擎优化
  • 瑞士本地电力社区技术经济评估:从P2P交易到能源民主化
  • 2026年过炉托盘源头厂家选购指南:代表性企业解析 - 资讯快报
  • 3步解决老款Mac系统升级难题:OpenCore Legacy Patcher完整指南
  • 2026济南财税公司靠谱推荐榜|企业财税托管避坑实测榜单 - 资讯快报
  • 企业 AI 转型避坑指南:从头部翻车案例看工程落地核心逻辑
  • 立体视觉与语言引导分割:模块化设计与消融实验深度解析