Initial
This commit is contained in:
commit
91a723e40d
8 changed files with 283 additions and 0 deletions
82
ember.py
Normal file
82
ember.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import pygame
|
||||
from typing import Tuple
|
||||
import numpy as np
|
||||
import pygame.gfxdraw
|
||||
from math import ceil
|
||||
from config import HEIGHT, WIDTH
|
||||
from utils import clamp, mix
|
||||
|
||||
BLUR_RADIUS = 3
|
||||
TTL_LOSS_NEAR_BORDER_IN_PIXELS = 200
|
||||
UP_DRAFT = 300
|
||||
|
||||
|
||||
class Ember:
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.position = (np.random.randint(0, WIDTH), HEIGHT)
|
||||
self.up_draft = np.random.uniform(0.3, 1) * UP_DRAFT
|
||||
self.time_to_live = np.random.uniform(1, 6)
|
||||
self.color_offset = np.random.uniform(0, 1)
|
||||
self.size = np.random.uniform(2.5, 6.5)
|
||||
|
||||
def update(self, velocity: Tuple[float, float], delta_time: float):
|
||||
self.position = (
|
||||
self.position[0] + velocity[0] * delta_time,
|
||||
self.position[1] + (velocity[1] - self.up_draft) * delta_time,
|
||||
)
|
||||
self.time_to_live -= delta_time
|
||||
if self.distance_from_screen_border() < TTL_LOSS_NEAR_BORDER_IN_PIXELS:
|
||||
self.time_to_live = min(
|
||||
self.distance_from_screen_border() / TTL_LOSS_NEAR_BORDER_IN_PIXELS,
|
||||
self.time_to_live,
|
||||
)
|
||||
|
||||
if self.time_to_live < 0:
|
||||
self.reset()
|
||||
|
||||
def draw(self, screen: pygame.Surface):
|
||||
color = (
|
||||
int(mix(255, 189, self.color_offset)),
|
||||
int(mix(165, 40, self.color_offset)),
|
||||
int(mix(0, 40, self.color_offset)),
|
||||
255 * (1 - clamp((0.5 - self.time_to_live) * 2, 0, 1) ** 2),
|
||||
)
|
||||
draw_antialiased_circle(
|
||||
screen, self.position[0], self.position[1], int(self.size), color
|
||||
)
|
||||
|
||||
def distance_from_screen_border(self):
|
||||
return min(
|
||||
self.position[0],
|
||||
WIDTH - self.position[0],
|
||||
self.position[1],
|
||||
# HEIGHT - self.position[1],
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Ember(position={self.position}, velocity={self.velocity}, time_to_live={self.time_to_live})"
|
||||
|
||||
|
||||
def draw_antialiased_circle(surface: pygame.Surface, x, y, radius, color):
|
||||
for dx in range(-ceil(radius), ceil(radius) + 1):
|
||||
for dy in range(-ceil(radius), ceil(radius) + 1):
|
||||
distance = ((dx - x % 1) ** 2 + (dy - y % 1) ** 2) ** 0.5 - radius
|
||||
if (
|
||||
distance < 0
|
||||
and 0 <= x + dx < surface.get_width()
|
||||
and 0 <= y + dy < surface.get_height()
|
||||
):
|
||||
alpha = min(color[3] / 255, -distance / BLUR_RADIUS)
|
||||
value = surface.get_at((int(x + dx), int(y + dy)))
|
||||
surface.set_at(
|
||||
(int(x + dx), int(y + dy)),
|
||||
(
|
||||
mix(value[0], color[0], alpha),
|
||||
mix(value[1], color[1], alpha),
|
||||
mix(value[2], color[2], alpha),
|
||||
mix(value[3], color[3], alpha),
|
||||
),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue