Merge branch 'main' of git.gangary.cn:gary/maze_python

This commit is contained in:
Gary Gan 2025-06-30 19:30:35 +08:00
commit 133cfeea63
8 changed files with 303 additions and 10 deletions

View File

@ -19,15 +19,21 @@ class SourceCollector:
self.end_pos = None
self.path = []
self.node_path = []
self.boss_pos = None
self.lock_pos = None
if self.filename:
self.maze = []
with open(f"{self.filename}",'r') as f:
reader = csv.reader(f)
for row in reader:
for idx,row in enumerate(reader):
t = []
for i in row:
if i.startswith('b') or i.startswith('l'):
for idy,i in enumerate(row):
if i.startswith('b'):
t.append('0')
self.boss_pos = (idx,idy)
elif i.startswith('l'):
t.append('0')
self.lock_pos = (idx,idy)
else:
t.append(i)
self.maze.append(t)
@ -142,8 +148,8 @@ class SourceCollector:
children = sn.children[:]
for child in children:
self.dfs(child)
children.sort(key=lambda c: len(c.path))
if self.colNums < 11:
children.sort(key=lambda c: len(c.path))
cur = None
for idx, child in enumerate(children):
if child.dp > 0:
@ -204,10 +210,7 @@ class SourceCollector:
if item == self.path[idx-1]:
del self.path[idx]
if self.path and self.end_pos and self.path[-1] != self.end_pos:
bfs_tail = self.bfs_path(self.path[-1], self.end_pos)
if bfs_tail:
self.path.extend(bfs_tail[1:])

BIN
boss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

BIN
cast.wav Normal file

Binary file not shown.

BIN
groan.wav Normal file

Binary file not shown.

BIN
hit.wav Normal file

Binary file not shown.

BIN
skill.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

290
wan.py Normal file
View File

@ -0,0 +1,290 @@
import pygame
import sys
import time
import random
import math
# 配置
SCREEN_WIDTH, SCREEN_HEIGHT = 900, 600
BOSS_IMG = 'boss.png' # 替换为你的boss图片路径
SKILL_IMG = 'skill.png' # 替换为你的技能图片路径
FPS = 60
HIT_SOUND = 'hit.wav' # 技能击中boss
CAST_SOUND = 'cast.wav' # 技能释放
WIN_SOUND = 'win.wav' # 胜利
GROAN_SOUND = 'groan.wav' # 怪物呻吟
# 技能颜色和名称
SKILL_COLORS = [(255, 80, 80), (80, 180, 255), (120, 255, 120), (255, 220, 80), (180, 80, 255)]
SKILL_NAMES = ["火球", "冰锥", "风刃", "雷击", "暗影"]
class Particle:
def __init__(self, x, y, color, shadow=False, glow=False):
self.x = x + random.randint(-10, 10)
self.y = y + random.randint(-10, 10)
self.radius = random.randint(2, 5)
self.color = color
self.life = random.randint(15, 30)
self.vx = random.uniform(-1.2, 1.2)
self.vy = random.uniform(-1.2, 1.2)
self.shadow = shadow
self.glow = glow
def update(self):
self.x += self.vx
self.y += self.vy
self.life -= 1
self.radius = max(0, self.radius - 0.08)
def draw(self, screen):
if self.life > 0 and self.radius > 0:
if self.shadow:
s = pygame.Surface((int(self.radius*4), int(self.radius*2)), pygame.SRCALPHA)
pygame.draw.ellipse(s, (30,30,30,80), (0,0,int(self.radius*4),int(self.radius*2)))
screen.blit(s, (int(self.x-self.radius*2), int(self.y+self.radius)))
if self.glow:
s = pygame.Surface((int(self.radius*4), int(self.radius*4)), pygame.SRCALPHA)
pygame.draw.circle(s, (*self.color, 60), (int(self.radius*2), int(self.radius*2)), int(self.radius*2))
screen.blit(s, (int(self.x-self.radius), int(self.y-self.radius)))
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), int(self.radius))
def draw_gradient_bg(screen):
for i in range(SCREEN_HEIGHT):
color = (
220 - i // 8,
220 - i // 16,
255 - i // 12
)
pygame.draw.line(screen, color, (0, i), (SCREEN_WIDTH, i))
def shake_pos(x, y, frame):
if frame % 2 == 0:
return x + 8, y + random.randint(-3, 3)
else:
return x - 8, y + random.randint(-3, 3)
def draw_health_bar(screen, x, y, w, h, hp, max_hp):
pygame.draw.rect(screen, (180, 0, 0), (x, y, w, h), border_radius=8)
pygame.draw.rect(screen, (0, 220, 0), (x, y, int(w * hp / max_hp), h), border_radius=8)
pygame.draw.rect(screen, (0, 0, 0), (x, y, w, h), 2, border_radius=8)
def draw_skill_cooldown(screen, x, y, w, h, cooldown, max_cd):
pygame.draw.rect(screen, (80, 80, 80), (x, y, w, h), border_radius=6)
if cooldown > 0:
pygame.draw.rect(screen, (120, 120, 255), (x, y, int(w * cooldown / max_cd), h), border_radius=6)
class Skill:
def __init__(self, idx, dmg, img):
self.idx = idx
self.dmg = dmg
self.img = img
self.x = 60
self.y = SCREEN_HEIGHT // 2 + random.randint(-60, 60)
self.active = True
self.color = SKILL_COLORS[idx % len(SKILL_COLORS)]
self.angle = random.uniform(-0.2, 0.2)
self.trail = []
self.shadow = True
self.glow = True
self.speed = 7 + self.idx * 0.7 # 更慢
self.cast_sound_played = False
def update(self):
self.trail.append((self.x, self.y))
if len(self.trail) > 12:
self.trail.pop(0)
self.x += self.speed
self.y += math.sin(self.x / 40) * 3 + self.angle * 8
if self.x > SCREEN_WIDTH:
self.active = False
def draw(self, screen):
# 阴影
s = pygame.Surface((self.img.get_width(), self.img.get_height()), pygame.SRCALPHA)
pygame.draw.ellipse(s, (30,30,30,80), (0, self.img.get_height()//2, self.img.get_width(), self.img.get_height()//2))
screen.blit(s, (self.x, self.y+self.img.get_height()//2))
# 光晕
s2 = pygame.Surface((self.img.get_width()*2, self.img.get_height()*2), pygame.SRCALPHA)
pygame.draw.circle(s2, (*self.color, 60), (self.img.get_width(), self.img.get_height()), self.img.get_width())
screen.blit(s2, (self.x-self.img.get_width()//2, self.y-self.img.get_height()//2))
# 轨迹
for i, (tx, ty) in enumerate(self.trail):
alpha = int(255 * (i + 1) / len(self.trail))
s = pygame.Surface((self.img.get_width(), self.img.get_height()), pygame.SRCALPHA)
s.fill((*self.color, alpha // 2))
screen.blit(s, (tx, ty))
screen.blit(self.img, (self.x, self.y))
class Boss:
def __init__(self, img, hp, groan_sound=None):
self.img = img
self.hp = hp
self.max_hp = hp
self.x = SCREEN_WIDTH - img.get_width() - 80
self.y = SCREEN_HEIGHT // 2 - img.get_height() // 2
self.shake_frame = 0
self.shake = False
self.dead = False
self.death_anim = 0
self.particles = []
self.groan_sound = groan_sound
self.groan_cooldown = 0
def hit(self, dmg):
if self.hp > 0:
self.hp = max(0, self.hp - dmg)
self.shake = True
self.shake_frame = 12
# 受击粒子
for _ in range(16):
self.particles.append(Particle(self.x + self.img.get_width() // 2, self.y + self.img.get_height() // 2, (255, 80, 80), shadow=True, glow=True))
if self.groan_sound and self.groan_cooldown == 0:
self.groan_sound.play()
self.groan_cooldown = 30
if self.hp == 0:
self.dead = True
self.death_anim = 60
def update(self):
if self.shake:
self.shake_frame -= 1
if self.shake_frame <= 0:
self.shake = False
if self.groan_cooldown > 0:
self.groan_cooldown -= 1
# 死亡动画
if self.dead and self.death_anim > 0:
self.death_anim -= 1
for _ in range(8):
self.particles.append(Particle(self.x + self.img.get_width() // 2, self.y + self.img.get_height() // 2, (80, 80, 80), shadow=True, glow=True))
# 更新粒子
for p in self.particles:
p.update()
self.particles = [p for p in self.particles if p.life > 0]
def draw(self, screen):
# 投影
s = pygame.Surface((self.img.get_width()*2, self.img.get_height()), pygame.SRCALPHA)
pygame.draw.ellipse(s, (30,30,30,90), (0, self.img.get_height()//2, self.img.get_width()*2, self.img.get_height()//2))
screen.blit(s, (self.x-self.img.get_width()//2, self.y+self.img.get_height()-10))
# 光晕
s2 = pygame.Surface((self.img.get_width()*2, self.img.get_height()*2), pygame.SRCALPHA)
pygame.draw.circle(s2, (200,200,255,60), (self.img.get_width(), self.img.get_height()), self.img.get_width())
screen.blit(s2, (self.x-self.img.get_width()//2, self.y-self.img.get_height()//2))
if self.shake:
x, y = shake_pos(self.x, self.y, self.shake_frame)
else:
x, y = self.x, self.y
if not self.dead or self.death_anim > 0:
screen.blit(self.img, (x, y))
draw_health_bar(screen, x, y - 40, 240, 24, self.hp, self.max_hp)
for p in self.particles:
p.draw(screen)
def main(boss_hp, skill_seq):
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('自动打Boss - 3D炫酷升级版')
clock = pygame.time.Clock()
boss_img = pygame.image.load(BOSS_IMG).convert_alpha()
skill_img = pygame.image.load(SKILL_IMG).convert_alpha()
# 音效
try:
hit_sound = pygame.mixer.Sound(HIT_SOUND)
cast_sound = pygame.mixer.Sound(CAST_SOUND)
win_sound = pygame.mixer.Sound(WIN_SOUND)
groan_sound = pygame.mixer.Sound(GROAN_SOUND)
except Exception:
hit_sound = cast_sound = win_sound = groan_sound = None
boss = Boss(boss_img, boss_hp, groan_sound=groan_sound)
skills = []
skill_idx = 0
running = True
skill_cooldown = 0
max_cd = 40 # 冷却更长
font = pygame.font.SysFont('SimHei', 36)
big_font = pygame.font.SysFont('SimHei', 60)
particles = []
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
draw_gradient_bg(screen)
# 随机背景粒子
if random.random() < 0.18:
particles.append(Particle(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT), (200, 200, 255), shadow=True, glow=True))
for p in particles:
p.update()
p.draw(screen)
particles = [p for p in particles if p.life > 0]
boss.update()
boss.draw(screen)
# 技能释放
if skill_idx < len(skill_seq) and skill_cooldown == 0 and not boss.dead:
s = skill_seq[skill_idx]
skills.append(Skill(s['first'], s['second'], skill_img))
if cast_sound:
cast_sound.play()
skill_cooldown = max_cd
skill_idx += 1
if skill_cooldown > 0:
skill_cooldown -= 1
# 技能动画
for skill in skills:
if skill.active:
skill.update()
skill.draw(screen)
# 判断是否击中boss
if skill.x + skill.img.get_width() > boss.x and boss.hp > 0 and not boss.dead:
boss.hit(skill.dmg)
# 爆炸粒子
for _ in range(24):
particles.append(Particle(boss.x+boss.img.get_width()//2, boss.y+boss.img.get_height()//2, random.choice(SKILL_COLORS), shadow=True, glow=True))
if hit_sound:
hit_sound.play()
skill.active = False
# 移除无效技能
skills = [s for s in skills if s.active]
# 技能冷却条和技能名
if skill_idx < len(skill_seq):
s = skill_seq[skill_idx]
skill_name = SKILL_NAMES[s['first'] % len(SKILL_NAMES)]
name_text = font.render(f"下一个技能:{skill_name}", True, SKILL_COLORS[s['first'] % len(SKILL_COLORS)])
screen.blit(name_text, (60, SCREEN_HEIGHT - 80))
draw_skill_cooldown(screen, 60, SCREEN_HEIGHT - 40, 200, 18, skill_cooldown, max_cd)
# 显示血量数字
hp_text = font.render(f'Boss HP: {boss.hp}/{boss.max_hp}', True, (0,0,0))
screen.blit(hp_text, (60, 30))
# Boss死亡动画
if boss.dead and boss.death_anim == 0:
win_text = big_font.render("胜利!", True, (255, 120, 80))
screen.blit(win_text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2 - 60))
if win_sound:
win_sound.play()
pygame.display.flip()
clock.tick(FPS)
if boss.hp <= 0 and not skills and boss.death_anim == 0:
time.sleep(1.5)
running = False
pygame.quit()
if __name__ == "__main__":
# 示例参数boss血量1000技能序列
boss_hp = 1000
skill_seq = [
{'first': 0, 'second': 120},
{'first': 1, 'second': 200},
{'first': 2, 'second': 150},
{'first': 3, 'second': 300},
{'first': 4, 'second': 250},
]
main(boss_hp, skill_seq)

BIN
win.wav Normal file

Binary file not shown.