117 lines
3.8 KiB
Python
117 lines
3.8 KiB
Python
"""Visual effects: floating damage numbers, attack lines, ink splash."""
|
|
|
|
import math
|
|
import random
|
|
|
|
import pygame
|
|
|
|
from card_game.config import INK_BLACK, ZHU_HONG, TENG_HUANG
|
|
|
|
|
|
class FloatingText:
|
|
def __init__(self, x, y, text, color=ZHU_HONG, duration=60):
|
|
self.x = x
|
|
self.y = y
|
|
self.text = text
|
|
self.color = color
|
|
self.timer = duration
|
|
self.max_timer = duration
|
|
|
|
def update(self):
|
|
self.y -= 0.5
|
|
self.timer -= 1
|
|
return self.timer > 0
|
|
|
|
def draw(self, surface, font):
|
|
alpha = min(255, int(255 * self.timer / self.max_timer))
|
|
text_surf = font.render(self.text, True, self.color)
|
|
alpha_surf = pygame.Surface(text_surf.get_size(), pygame.SRCALPHA)
|
|
alpha_surf.fill((255, 255, 255, alpha))
|
|
text_surf.blit(alpha_surf, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
|
|
surface.blit(text_surf, (self.x - text_surf.get_width() // 2, int(self.y)))
|
|
|
|
|
|
class AttackLine:
|
|
def __init__(self, x1, y1, x2, y2, duration=20):
|
|
self.x1, self.y1 = x1, y1
|
|
self.x2, self.y2 = x2, y2
|
|
self.timer = duration
|
|
self.max_timer = duration
|
|
|
|
def update(self):
|
|
self.timer -= 1
|
|
return self.timer > 0
|
|
|
|
def draw(self, surface):
|
|
progress = 1 - self.timer / self.max_timer
|
|
cx = self.x1 + (self.x2 - self.x1) * min(progress * 2, 1)
|
|
cy = self.y1 + (self.y2 - self.y1) * min(progress * 2, 1)
|
|
from card_game.ink_style import draw_brush_stroke
|
|
draw_brush_stroke(surface, (int(self.x1), int(self.y1)),
|
|
(int(cx), int(cy)), 3, TENG_HUANG, alpha=200)
|
|
|
|
|
|
class InkSplash:
|
|
def __init__(self, x, y, duration=30):
|
|
self.x = x
|
|
self.y = y
|
|
self.timer = duration
|
|
self.max_timer = duration
|
|
rng = random.Random(int(x * 100 + y))
|
|
self.particles = []
|
|
for _ in range(8):
|
|
angle = rng.uniform(0, 2 * math.pi)
|
|
speed = rng.uniform(1, 4)
|
|
size = rng.randint(3, 8)
|
|
self.particles.append((angle, speed, size))
|
|
|
|
def update(self):
|
|
self.timer -= 1
|
|
return self.timer > 0
|
|
|
|
def draw(self, surface):
|
|
progress = 1 - self.timer / self.max_timer
|
|
alpha = max(0, int(200 * (1 - progress)))
|
|
|
|
for angle, speed, size in self.particles:
|
|
dist = speed * progress * 30
|
|
px = int(self.x + dist * math.cos(angle))
|
|
py = int(self.y + dist * math.sin(angle))
|
|
current_size = max(1, int(size * (1 - progress * 0.5)))
|
|
s = pygame.Surface((current_size * 2, current_size * 2), pygame.SRCALPHA)
|
|
pygame.draw.circle(s, (*INK_BLACK[:3], alpha),
|
|
(current_size, current_size), current_size)
|
|
surface.blit(s, (px - current_size, py - current_size))
|
|
|
|
|
|
class EffectManager:
|
|
def __init__(self):
|
|
self.texts = []
|
|
self.lines = []
|
|
self.splashes = []
|
|
|
|
def add_damage(self, x, y, amount):
|
|
self.texts.append(FloatingText(x, y, f"-{amount}", ZHU_HONG))
|
|
|
|
def add_heal(self, x, y, amount):
|
|
self.texts.append(FloatingText(x, y, f"+{amount}", (70, 140, 80)))
|
|
|
|
def add_attack_line(self, x1, y1, x2, y2):
|
|
self.lines.append(AttackLine(x1, y1, x2, y2))
|
|
|
|
def add_ink_splash(self, x, y):
|
|
self.splashes.append(InkSplash(x, y))
|
|
|
|
def update(self):
|
|
self.texts = [t for t in self.texts if t.update()]
|
|
self.lines = [l for l in self.lines if l.update()]
|
|
self.splashes = [s for s in self.splashes if s.update()]
|
|
|
|
def draw(self, surface, font):
|
|
for line in self.lines:
|
|
line.draw(surface)
|
|
for splash in self.splashes:
|
|
splash.draw(surface)
|
|
for text in self.texts:
|
|
text.draw(surface, font)
|