Spaces:
Sleeping
Sleeping
| """ | |
| Classic Sprite Generator - Original smooth/rounded style | |
| """ | |
| import numpy as np | |
| from PIL import Image, ImageDraw | |
| from typing import Tuple | |
| import math | |
| from .sprite_generator_base import SpriteGeneratorBase | |
| from .sprite_generator import Sprite | |
| class ClassicSpriteGenerator(SpriteGeneratorBase): | |
| """Classic sprite generator with smooth, rounded style""" | |
| def generate_smurf_sprites(self, color_tint: Tuple[int, int, int] = (0, 120, 255), | |
| size_scale: float = 1.0) -> dict: | |
| """Generate complete smurf sprite set""" | |
| from entities.enums import AnimationType | |
| return { | |
| AnimationType.IDLE.value: self._gen_smurf_idle(color_tint, size_scale), | |
| AnimationType.WALK.value: self._gen_smurf_walk(color_tint, size_scale), | |
| AnimationType.GATHER.value: self._gen_smurf_gather(color_tint, size_scale), | |
| AnimationType.HAPPY.value: self._gen_smurf_happy(color_tint, size_scale), | |
| AnimationType.ANGRY.value: self._gen_smurf_angry(color_tint, size_scale), | |
| AnimationType.CHAT.value: self._gen_smurf_chat(color_tint, size_scale), | |
| AnimationType.PLAY.value: self._gen_smurf_play(color_tint, size_scale) | |
| } | |
| def _draw_smurf_base(draw, color: Tuple[int, int, int], scale: float, y_offset: int = 0): | |
| """Draw base smurf body (reusable)""" | |
| s = scale | |
| # Body | |
| draw.ellipse([8*s, (12+y_offset)*s, 24*s, (26+y_offset)*s], fill=color) | |
| # Head | |
| draw.ellipse([10*s, (6+y_offset)*s, 22*s, (16+y_offset)*s], fill=(255, 220, 180)) | |
| # Hat | |
| draw.polygon([(10*s, (6+y_offset)*s), (22*s, (6+y_offset)*s), (16*s, (0+y_offset)*s)], | |
| fill=(255, 255, 255)) | |
| def _draw_face_neutral(draw, scale: float, y_offset: int = 0): | |
| """Draw neutral face""" | |
| s = scale | |
| # Eyes | |
| draw.ellipse([13*s, (10+y_offset)*s, 15*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| draw.ellipse([17*s, (10+y_offset)*s, 19*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| # Small mouth | |
| draw.line([(14*s, (13+y_offset)*s), (18*s, (13+y_offset)*s)], fill=(0, 0, 0), width=1) | |
| def _draw_face_happy(draw, scale: float, y_offset: int = 0): | |
| """Draw happy face with big smile""" | |
| s = scale | |
| # Eyes (wider/sparkly) | |
| draw.ellipse([12*s, (9+y_offset)*s, 15*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| draw.ellipse([17*s, (9+y_offset)*s, 20*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| # Big smile (arc) | |
| draw.arc([12*s, (10+y_offset)*s, 20*s, (15+y_offset)*s], 0, 180, fill=(0, 0, 0), width=int(2*scale)) | |
| # Rosy cheeks | |
| draw.ellipse([9*s, (12+y_offset)*s, 11*s, (13+y_offset)*s], fill=(255, 150, 150)) | |
| draw.ellipse([21*s, (12+y_offset)*s, 23*s, (13+y_offset)*s], fill=(255, 150, 150)) | |
| def _draw_face_angry(draw, scale: float, y_offset: int = 0): | |
| """Draw angry face with frown""" | |
| s = scale | |
| # Angry eyes (narrow) | |
| draw.ellipse([13*s, (11+y_offset)*s, 15*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| draw.ellipse([17*s, (11+y_offset)*s, 19*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| # Angry eyebrows | |
| draw.line([(12*s, (9+y_offset)*s), (15*s, (10+y_offset)*s)], fill=(0, 0, 0), width=int(2*scale)) | |
| draw.line([(17*s, (10+y_offset)*s), (20*s, (9+y_offset)*s)], fill=(0, 0, 0), width=int(2*scale)) | |
| # Frown | |
| draw.arc([13*s, (14+y_offset)*s, 19*s, (16+y_offset)*s], 180, 360, fill=(0, 0, 0), width=int(2*scale)) | |
| def _draw_face_chatting(draw, scale: float, y_offset: int = 0, frame: int = 0): | |
| """Draw chatting face (mouth open/closed)""" | |
| s = scale | |
| # Eyes | |
| draw.ellipse([13*s, (10+y_offset)*s, 15*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| draw.ellipse([17*s, (10+y_offset)*s, 19*s, (12+y_offset)*s], fill=(0, 0, 0)) | |
| # Mouth (talking - open/closed) | |
| if frame % 2 == 0: | |
| draw.ellipse([14*s, (13+y_offset)*s, 18*s, (15+y_offset)*s], fill=(0, 0, 0)) # Open | |
| else: | |
| draw.line([(14*s, (13+y_offset)*s), (18*s, (13+y_offset)*s)], fill=(0, 0, 0), width=1) # Closed | |
| def _gen_smurf_idle(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(2): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| y_offset = int(1 * scale) if i == 0 else 0 | |
| self._draw_smurf_base(draw, color, scale, y_offset) | |
| self._draw_face_neutral(draw, scale, y_offset) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=15) | |
| def _gen_smurf_walk(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(4): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| bob = int(2 * scale) if i % 2 == 0 else 0 | |
| s = scale | |
| self._draw_smurf_base(draw, color, scale, bob) | |
| self._draw_face_neutral(draw, scale, bob) | |
| # Walking legs | |
| left_leg = int(2 * scale) if i < 2 else int(-2 * scale) | |
| right_leg = int(-2 * scale) if i < 2 else int(2 * scale) | |
| draw.rectangle([11*s, (26+bob)*s, 13*s, (30+bob+left_leg)*s], fill=color) | |
| draw.rectangle([19*s, (26+bob)*s, 21*s, (30+bob+right_leg)*s], fill=color) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=8) | |
| def _gen_smurf_gather(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(4): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| bend = int(i * 2 * scale) | |
| self._draw_smurf_base(draw, color, scale, bend) | |
| self._draw_face_neutral(draw, scale, bend) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=10) | |
| def _gen_smurf_happy(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| """Happy jumping with big smile""" | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(6): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| jump = int(abs(math.sin(i * math.pi / 3) * 8) * scale) | |
| self._draw_smurf_base(draw, color, scale, -jump) | |
| self._draw_face_happy(draw, scale, -jump) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=5) | |
| def _gen_smurf_angry(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| """Angry shaking with frown""" | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(4): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| shake_x = int((i % 2) * 2 - 1) * int(2 * scale) | |
| # Slightly red-tinted when angry | |
| angry_color = (min(255, color[0] + 50), max(0, color[1] - 20), max(0, color[2] - 20)) | |
| # Draw body with offset for shake | |
| s = scale | |
| draw.ellipse([(8+shake_x)*s, 12*s, (24+shake_x)*s, 26*s], fill=angry_color) | |
| draw.ellipse([(10+shake_x)*s, 6*s, (22+shake_x)*s, 16*s], fill=(255, 200, 180)) | |
| draw.polygon([((10+shake_x)*s, 6*s), ((22+shake_x)*s, 6*s), ((16+shake_x)*s, 0)], | |
| fill=(255, 255, 255)) | |
| # Angry face with correct offset | |
| draw.ellipse([(13+shake_x)*s, 11*s, (15+shake_x)*s, 12*s], fill=(0, 0, 0)) | |
| draw.ellipse([(17+shake_x)*s, 11*s, (19+shake_x)*s, 12*s], fill=(0, 0, 0)) | |
| draw.line([((12+shake_x)*s, 9*s), ((15+shake_x)*s, 10*s)], fill=(0, 0, 0), width=int(2*scale)) | |
| draw.line([((17+shake_x)*s, 10*s), ((20+shake_x)*s, 9*s)], fill=(0, 0, 0), width=int(2*scale)) | |
| draw.arc([((13+shake_x)*s, 14*s), ((19+shake_x)*s, 16*s)], 180, 360, fill=(0, 0, 0), width=int(2*scale)) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=8) | |
| def _gen_smurf_chat(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| """Chatting with mouth movement""" | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(4): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| nod = int((i % 2) * scale) | |
| self._draw_smurf_base(draw, color, scale, nod) | |
| self._draw_face_chatting(draw, scale, nod, i) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=12) | |
| def _gen_smurf_play(self, color: Tuple[int, int, int], scale: float) -> Sprite: | |
| """Playing - bouncing with happy face""" | |
| frames = [] | |
| base_size = int(32 * scale) | |
| for i in range(6): | |
| img = Image.new('RGBA', (base_size, base_size), (0, 0, 0, 0)) | |
| draw = ImageDraw.Draw(img) | |
| bounce = int(abs(math.sin(i * math.pi / 3) * 4) * scale) | |
| self._draw_smurf_base(draw, color, scale, bounce) | |
| self._draw_face_happy(draw, scale, bounce) | |
| frames.append(np.array(img)) | |
| return Sprite(frames=frames, frame_speed=10) | |