import glob import os import random import math from PIL import Image # Vibrant colors closer to the original 8-bit sprites, but rich and organic C_DARK = (15, 110, 35, 255) C_MED = (30, 155, 45, 255) C_LIGHT = (45, 195, 60, 255) C_BRIGHT = (70, 230, 80, 255) C_SHADOW = (20, 50, 30, 100) # Softer, greener shadow instead of black/purple C_SHADOW_SOFT = (20, 50, 30, 50) C_DIRT = (128, 128, 128, 255) def draw_wrapped_circle(pixels, w, h, cx, cy, r, color): for y in range(int(cy - r - 1), int(cy + r + 2)): for x in range(int(cx - r - 1), int(cx + r + 2)): d = math.hypot(x - cx, y - cy) if d <= r: pixels[x % w, y % h] = color def generate_seamless_hedge(w, h): img = Image.new('RGBA', (w, h), C_MED) pixels = img.load() # Large clusters of base grass color for _ in range((w * h) // 16): cx, cy = random.uniform(0, w), random.uniform(0, h) draw_wrapped_circle(pixels, w, h, cx, cy, random.uniform(2.0, 3.5), C_LIGHT) # Highlights for _ in range((w * h) // 32): cx, cy = random.uniform(0, w), random.uniform(0, h) draw_wrapped_circle(pixels, w, h, cx, cy, random.uniform(1.0, 2.0), C_BRIGHT) # Tiny dark gaps for _ in range((w * h) // 80): cx, cy = random.uniform(0, w), random.uniform(0, h) draw_wrapped_circle(pixels, w, h, cx, cy, random.uniform(0.5, 1.2), C_DARK) return img def get_class(rgb): if rgb in [(0, 128, 0), (0, 255, 0)]: return 'GRASS' return 'DIRT' def alpha_blend(c1, c2): a = c1[3] / 255.0 r = int(c1[0] * a + c2[0] * (1 - a)) g = int(c1[1] * a + c2[1] * (1 - a)) b = int(c1[2] * a + c2[2] * (1 - a)) return (r, g, b, 255) input_files = glob.glob('/home/enne2/dev/mice/assets/Rat/*BMP_1*.png') out_dir = '/home/enne2/dev/mice/assets/Rat_LPC_Style/' os.makedirs(out_dir, exist_ok=True) base_hedge_64 = generate_seamless_hedge(64, 64) for f in input_files: basename = os.path.basename(f) img = Image.open(f).convert('RGBA') width, height = img.size pixels = img.load() out_img = Image.new('RGBA', (width, height)) out_pixels = out_img.load() is_fx = 'EXPLOSION' in basename or 'GAS' in basename is_flower = 'FLOWER' in basename mask = {} for y in range(height): for x in range(width): px = pixels[x, y][:3] cls = get_class(px) if is_flower: mask[(x, y)] = 'GRASS' elif is_fx: if cls == 'GRASS': mask[(x, y)] = 'GRASS' else: mask[(x, y)] = 'DIRT' else: mask[(x, y)] = cls tile_hedge = base_hedge_64.copy() tile_pixels = tile_hedge.load() if basename == 'BMP_1_GRASS_2.png': for _ in range(8): cx, cy = random.randint(16, 48), random.randint(16, 48) tile_pixels[cx, cy] = (220, 50, 50, 255) elif basename == 'BMP_1_GRASS_3.png': for _ in range(12): cx, cy = random.randint(16, 48), random.randint(16, 48) tile_pixels[cx, cy] = (255, 255, 255, 255) elif basename == 'BMP_1_GRASS_4.png': for _ in range(20): cx, cy = random.randint(20, 44), random.randint(20, 44) draw_wrapped_circle(tile_pixels, 64, 64, cx, cy, random.uniform(1.0, 2.5), C_MED) for y in range(height): for x in range(width): if mask[(x, y)] == 'GRASS': dist_to_dirt = 999 for dy in range(-3, 4): for dx in range(-3, 4): nx, ny = x + dx, y + dy if 0 <= nx < width and 0 <= ny < height: if mask[(nx, ny)] == 'DIRT': d = math.hypot(dx, dy) if d < dist_to_dirt: dist_to_dirt = d if dist_to_dirt <= 1.5: dirt_below = (y+1 < height and mask[(x, y+1)] == 'DIRT') or (y+2 < height and mask[(x, y+2)] == 'DIRT') if dirt_below: # Solid dark green outline on the bottom (no more dashes!) out_pixels[x, y] = C_DARK else: out_pixels[x, y] = C_MED elif dist_to_dirt <= 2.5: out_pixels[x, y] = C_MED else: out_pixels[x, y] = tile_pixels[x % 64, y % 64] else: orig_color = pixels[x, y][:3] if orig_color == (0, 0, 0) and not is_fx: # Replace debug dashed lines with dirt orig_color = C_DIRT[:3] if orig_color == (0, 0, 0): out_pixels[x, y] = (0, 0, 0, 255) elif orig_color in [(128,128,128), (192,192,192)]: dist_to_grass = 999 for dy in range(-2, 3): for dx in range(-2, 3): nx, ny = x + dx, y + dy if 0 <= nx < width and 0 <= ny < height: if mask[(nx, ny)] == 'GRASS': d = math.hypot(dx, dy) if d < dist_to_grass: dist_to_grass = d base_c = orig_color if dist_to_grass <= 1.5: out_pixels[x, y] = alpha_blend(C_SHADOW, base_c) elif dist_to_grass <= 2.5: out_pixels[x, y] = alpha_blend(C_SHADOW_SOFT, base_c) else: out_pixels[x, y] = base_c + (255,) else: out_pixels[x, y] = orig_color + (255,) # Flowers logic if is_flower: def draw_circle(cx, cy, r, color, outline=None): for fy in range(cy - r - 1, cy + r + 2): for fx in range(cx - r - 1, cx + r + 2): if 0 <= fx < width and 0 <= fy < height: d = math.hypot(fx - cx, fy - cy) if d <= r: out_pixels[fx, fy] = color elif outline and r < d <= r + 1.2: if out_pixels[fx, fy] != color: out_pixels[fx, fy] = outline def draw_petal(cx, cy, angle, length, pw, color, outline): cos_a, sin_a = math.cos(angle), math.sin(angle) size = int(length + pw) for fy in range(cy - size, cy + size + 1): for fx in range(cx - size, cx + size + 1): if 0 <= fx < width and 0 <= fy < height: dx, dy = fx - cx, fy - cy rx = dx * cos_a + dy * sin_a ry = -dx * sin_a + dy * cos_a if length > 0 and pw > 0: val = (rx / length)**2 + (ry / pw)**2 if val <= 1.0: out_pixels[fx, fy] = color elif val <= 1.5: if out_pixels[fx, fy] != color: out_pixels[fx, fy] = outline def draw_large_flower(cx, cy, petal_color, outline_color, center_color, num_petals, petal_length, petal_width): draw_circle(cx, cy + 3, petal_length + 1, (20, 50, 20, 200)) for i in range(num_petals): angle = i * (2 * math.pi / num_petals) pcolor = (int(petal_color[0]*0.8), int(petal_color[1]*0.8), int(petal_color[2]*0.8), 255) if math.sin(angle) > 0 else petal_color draw_petal(cx, cy, angle, petal_length, petal_width, pcolor, outline_color) draw_circle(cx, cy, petal_width + 1, center_color, (int(center_color[0]*0.6), int(center_color[1]*0.6), int(center_color[2]*0.6), 255)) if 'FLOWER_1' in basename: draw_large_flower(32, 32, (240, 240, 240, 255), (100, 100, 110, 255), (240, 200, 50, 255), 10, 14, 5) elif 'FLOWER_2' in basename: draw_large_flower(16, 16, (200, 40, 40, 255), (80, 20, 20, 255), (240, 200, 50, 255), 5, 7, 4) draw_large_flower(48, 20, (200, 40, 40, 255), (80, 20, 20, 255), (240, 200, 50, 255), 5, 7, 4) draw_large_flower(32, 48, (200, 40, 40, 255), (80, 20, 20, 255), (240, 200, 50, 255), 5, 7, 4) elif 'FLOWER_3' in basename: draw_large_flower(32, 32, (220, 80, 180, 255), (100, 30, 80, 255), (240, 200, 50, 255), 8, 12, 6) elif 'FLOWER_4' in basename: draw_large_flower(32, 32, (80, 150, 230, 255), (30, 70, 120, 255), (240, 200, 50, 255), 8, 12, 6) if is_fx: for y in range(height): for x in range(width): px = pixels[x, y][:3] if get_class(px) != 'GRASS' and px not in [(128,128,128), (192,192,192), (0,0,0)]: out_pixels[x, y] = px + (255,) out_img.save(os.path.join(out_dir, basename)) print("V11 - Vibrant 8-bit-like colors and NO dashed lines!")