diff --git a/assets/images/bosses/boss_dragon_fire.png b/assets/images/bosses/boss_dragon_fire.png new file mode 100644 index 000000000..b10757627 Binary files /dev/null and b/assets/images/bosses/boss_dragon_fire.png differ diff --git a/assets/images/bosses/boss_golem.png b/assets/images/bosses/boss_golem.png new file mode 100644 index 000000000..f65f14c8f Binary files /dev/null and b/assets/images/bosses/boss_golem.png differ diff --git a/assets/images/bosses/boss_kraken.png b/assets/images/bosses/boss_kraken.png new file mode 100644 index 000000000..e3d96954e Binary files /dev/null and b/assets/images/bosses/boss_kraken.png differ diff --git a/assets/images/bosses/boss_slime_emperor.png b/assets/images/bosses/boss_slime_emperor.png new file mode 100644 index 000000000..37b402347 Binary files /dev/null and b/assets/images/bosses/boss_slime_emperor.png differ diff --git a/assets/images/bosses/boss_spider_queen.png b/assets/images/bosses/boss_spider_queen.png new file mode 100644 index 000000000..b0e8a1129 Binary files /dev/null and b/assets/images/bosses/boss_spider_queen.png differ diff --git a/assets/images/bosses/boss_trex.png b/assets/images/bosses/boss_trex.png new file mode 100644 index 000000000..4341bcaaa Binary files /dev/null and b/assets/images/bosses/boss_trex.png differ diff --git a/assets/images/bosses/boss_werewolf.png b/assets/images/bosses/boss_werewolf.png new file mode 100644 index 000000000..58ce8c1ac Binary files /dev/null and b/assets/images/bosses/boss_werewolf.png differ diff --git a/assets/images/bosses/boss_zombie_king.png b/assets/images/bosses/boss_zombie_king.png new file mode 100644 index 000000000..fb555f1dc Binary files /dev/null and b/assets/images/bosses/boss_zombie_king.png differ diff --git a/assets/images/environment/bush_green.png b/assets/images/environment/bush_green.png new file mode 100644 index 000000000..2376e5118 Binary files /dev/null and b/assets/images/environment/bush_green.png differ diff --git a/assets/images/environment/campfire.png b/assets/images/environment/campfire.png new file mode 100644 index 000000000..8e0746b8f Binary files /dev/null and b/assets/images/environment/campfire.png differ diff --git a/assets/images/environment/chest_wooden.png b/assets/images/environment/chest_wooden.png new file mode 100644 index 000000000..3a0e052b3 Binary files /dev/null and b/assets/images/environment/chest_wooden.png differ diff --git a/assets/images/environment/rock_large.png b/assets/images/environment/rock_large.png new file mode 100644 index 000000000..67a2b1e7b Binary files /dev/null and b/assets/images/environment/rock_large.png differ diff --git a/assets/images/environment/tree_oak.png b/assets/images/environment/tree_oak.png new file mode 100644 index 000000000..d8449b14e Binary files /dev/null and b/assets/images/environment/tree_oak.png differ diff --git a/assets/images/items/ana_bracelet.png b/assets/images/items/ana_bracelet.png new file mode 100644 index 000000000..b4bd26cb2 Binary files /dev/null and b/assets/images/items/ana_bracelet.png differ diff --git a/assets/images/items/gronk_vape.png b/assets/images/items/gronk_vape.png new file mode 100644 index 000000000..f2c4e2d45 Binary files /dev/null and b/assets/images/items/gronk_vape.png differ diff --git a/assets/images/items/potion_health.png b/assets/images/items/potion_health.png new file mode 100644 index 000000000..f98d4a016 Binary files /dev/null and b/assets/images/items/potion_health.png differ diff --git a/assets/images/items/tool_axe_iron.png b/assets/images/items/tool_axe_iron.png new file mode 100644 index 000000000..c21d95a63 Binary files /dev/null and b/assets/images/items/tool_axe_iron.png differ diff --git a/assets/images/items/wand_fire.png b/assets/images/items/wand_fire.png new file mode 100644 index 000000000..9214b5783 Binary files /dev/null and b/assets/images/items/wand_fire.png differ diff --git a/assets/images/items/wand_ice.png b/assets/images/items/wand_ice.png new file mode 100644 index 000000000..295e92818 Binary files /dev/null and b/assets/images/items/wand_ice.png differ diff --git a/assets/images/items/weapon_sword_iron.png b/assets/images/items/weapon_sword_iron.png new file mode 100644 index 000000000..c667d3569 Binary files /dev/null and b/assets/images/items/weapon_sword_iron.png differ diff --git a/assets/images/mutanti/slime_blue.png b/assets/images/mutanti/slime_blue.png new file mode 100644 index 000000000..2b2b4a639 Binary files /dev/null and b/assets/images/mutanti/slime_blue.png differ diff --git a/assets/images/mutanti/slime_green.png b/assets/images/mutanti/slime_green.png new file mode 100644 index 000000000..bbf5033be Binary files /dev/null and b/assets/images/mutanti/slime_green.png differ diff --git a/assets/images/mutanti/zombie_basic.png b/assets/images/mutanti/zombie_basic.png new file mode 100644 index 000000000..06bbf6dd8 Binary files /dev/null and b/assets/images/mutanti/zombie_basic.png differ diff --git a/assets/images/mutanti/zombie_dreadlocks.png b/assets/images/mutanti/zombie_dreadlocks.png new file mode 100644 index 000000000..74f10f490 Binary files /dev/null and b/assets/images/mutanti/zombie_dreadlocks.png differ diff --git a/assets/images/mutanti/zombie_runner.png b/assets/images/mutanti/zombie_runner.png new file mode 100644 index 000000000..c6c9d0447 Binary files /dev/null and b/assets/images/mutanti/zombie_runner.png differ diff --git a/assets/images/npcs/ana_explorer.png b/assets/images/npcs/ana_explorer.png new file mode 100644 index 000000000..e4c0bc94b Binary files /dev/null and b/assets/images/npcs/ana_explorer.png differ diff --git a/assets/images/npcs/gronk_front_walk1.png b/assets/images/npcs/gronk_front_walk1.png new file mode 100644 index 000000000..54813e5a1 Binary files /dev/null and b/assets/images/npcs/gronk_front_walk1.png differ diff --git a/assets/images/npcs/gronk_front_walk2.png b/assets/images/npcs/gronk_front_walk2.png new file mode 100644 index 000000000..894b9be43 Binary files /dev/null and b/assets/images/npcs/gronk_front_walk2.png differ diff --git a/assets/images/npcs/gronk_troll.png b/assets/images/npcs/gronk_troll.png new file mode 100644 index 000000000..a49ff3569 Binary files /dev/null and b/assets/images/npcs/gronk_troll.png differ diff --git a/assets/images/npcs/kai_survivor.png b/assets/images/npcs/kai_survivor.png new file mode 100644 index 000000000..37551a51e Binary files /dev/null and b/assets/images/npcs/kai_survivor.png differ diff --git a/assets/images/npcs/npc_blacksmith.png b/assets/images/npcs/npc_blacksmith.png new file mode 100644 index 000000000..c498e9e23 Binary files /dev/null and b/assets/images/npcs/npc_blacksmith.png differ diff --git a/assets/images/npcs/npc_child.png b/assets/images/npcs/npc_child.png new file mode 100644 index 000000000..cee7ae4d8 Binary files /dev/null and b/assets/images/npcs/npc_child.png differ diff --git a/assets/images/npcs/npc_cook.png b/assets/images/npcs/npc_cook.png new file mode 100644 index 000000000..7549bfdcc Binary files /dev/null and b/assets/images/npcs/npc_cook.png differ diff --git a/assets/images/npcs/npc_elder.png b/assets/images/npcs/npc_elder.png new file mode 100644 index 000000000..7fef8e49b Binary files /dev/null and b/assets/images/npcs/npc_elder.png differ diff --git a/assets/images/npcs/npc_farmer.png b/assets/images/npcs/npc_farmer.png new file mode 100644 index 000000000..26a841729 Binary files /dev/null and b/assets/images/npcs/npc_farmer.png differ diff --git a/assets/images/npcs/npc_healer.png b/assets/images/npcs/npc_healer.png new file mode 100644 index 000000000..de89cc143 Binary files /dev/null and b/assets/images/npcs/npc_healer.png differ diff --git a/assets/images/npcs/npc_hunter.png b/assets/images/npcs/npc_hunter.png new file mode 100644 index 000000000..64bebd045 Binary files /dev/null and b/assets/images/npcs/npc_hunter.png differ diff --git a/assets/images/npcs/npc_mechanic.png b/assets/images/npcs/npc_mechanic.png new file mode 100644 index 000000000..af9d0113a Binary files /dev/null and b/assets/images/npcs/npc_mechanic.png differ diff --git a/assets/images/npcs/npc_medic.png b/assets/images/npcs/npc_medic.png new file mode 100644 index 000000000..eb1c11624 Binary files /dev/null and b/assets/images/npcs/npc_medic.png differ diff --git a/assets/images/npcs/npc_scout.png b/assets/images/npcs/npc_scout.png new file mode 100644 index 000000000..c42eab6ee Binary files /dev/null and b/assets/images/npcs/npc_scout.png differ diff --git a/assets/images/npcs/npc_soldier.png b/assets/images/npcs/npc_soldier.png new file mode 100644 index 000000000..b302acd78 Binary files /dev/null and b/assets/images/npcs/npc_soldier.png differ diff --git a/assets/images/npcs/npc_trader.png b/assets/images/npcs/npc_trader.png new file mode 100644 index 000000000..953835303 Binary files /dev/null and b/assets/images/npcs/npc_trader.png differ diff --git a/assets/images/zivali/bear_brown.png b/assets/images/zivali/bear_brown.png new file mode 100644 index 000000000..0d10389ff Binary files /dev/null and b/assets/images/zivali/bear_brown.png differ diff --git a/assets/images/zivali/cat_tabby.png b/assets/images/zivali/cat_tabby.png new file mode 100644 index 000000000..dee9c4895 Binary files /dev/null and b/assets/images/zivali/cat_tabby.png differ diff --git a/assets/images/zivali/chicken_white.png b/assets/images/zivali/chicken_white.png new file mode 100644 index 000000000..0f613e1a1 Binary files /dev/null and b/assets/images/zivali/chicken_white.png differ diff --git a/assets/images/zivali/cow_spotted.png b/assets/images/zivali/cow_spotted.png new file mode 100644 index 000000000..dcbafcd47 Binary files /dev/null and b/assets/images/zivali/cow_spotted.png differ diff --git a/assets/images/zivali/dog_husky.png b/assets/images/zivali/dog_husky.png new file mode 100644 index 000000000..f72e647b3 Binary files /dev/null and b/assets/images/zivali/dog_husky.png differ diff --git a/assets/images/zivali/horse_brown.png b/assets/images/zivali/horse_brown.png new file mode 100644 index 000000000..b837bf73a Binary files /dev/null and b/assets/images/zivali/horse_brown.png differ diff --git a/assets/images/zivali/phoenix_chicken.png b/assets/images/zivali/phoenix_chicken.png new file mode 100644 index 000000000..452c32b41 Binary files /dev/null and b/assets/images/zivali/phoenix_chicken.png differ diff --git a/assets/images/zivali/pig_pink.png b/assets/images/zivali/pig_pink.png new file mode 100644 index 000000000..6cccb9cc4 Binary files /dev/null and b/assets/images/zivali/pig_pink.png differ diff --git a/assets/images/zivali/sheep_fluffy.png b/assets/images/zivali/sheep_fluffy.png new file mode 100644 index 000000000..17082ab3f Binary files /dev/null and b/assets/images/zivali/sheep_fluffy.png differ diff --git a/assets/images/zivali/susi_dachshund.png b/assets/images/zivali/susi_dachshund.png new file mode 100644 index 000000000..0a926e8db Binary files /dev/null and b/assets/images/zivali/susi_dachshund.png differ diff --git a/assets/images/zivali/unicorn.png b/assets/images/zivali/unicorn.png new file mode 100644 index 000000000..35c25b29b Binary files /dev/null and b/assets/images/zivali/unicorn.png differ diff --git a/assets/images/zivali/wolf_grey.png b/assets/images/zivali/wolf_grey.png new file mode 100644 index 000000000..61e7d1c4c Binary files /dev/null and b/assets/images/zivali/wolf_grey.png differ diff --git a/scripts/generate_background.py b/scripts/generate_background.py new file mode 100644 index 000000000..5c92fcb82 --- /dev/null +++ b/scripts/generate_background.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python3 +""" +šŸŽ® DOLINA SMRTI - Background Asset Generator +Runs unattended, generates remaining assets with transparent backgrounds +Uses Google Imagen + rembg for transparent PNG output +""" + +import os +import sys +import time +import subprocess +from pathlib import Path +from datetime import datetime + +# Paths +ARTIFACTS = Path("/Users/davidkotnik/.gemini/antigravity/brain/1359204e-4aaa-41ba-abbf-9b1bab2caa00") +OUTPUT = Path("/Users/davidkotnik/repos/novafarma/assets/images") + +# Style prefix for all assets +STYLE = "2D indie game sprite, cartoon vector style, clean smooth lines, full body visible, tight crop minimal padding, PNG game asset" + +# ============================================================================ +# COMPLETE ASSET REGISTRY +# ============================================================================ + +ASSETS = [ + # NPCs - remaining + ("npcs", "npc_mechanic", "mechanic survivor, oil stained clothes, wrench, welding goggles"), + ("npcs", "npc_soldier", "ex-military survivor, tactical vest, rifle, scarred face"), + ("npcs", "npc_medic", "field medic, white coat with blood stains, medical bag"), + ("npcs", "npc_elder", "wise tribal elder, walking stick, long white beard"), + ("npcs", "npc_child", "survivor orphan child, oversized clothes, teddy bear"), + ("npcs", "npc_cook", "camp cook, pot and ladle, big belly, friendly"), + ("npcs", "npc_scout", "nomad scout, binoculars, light armor, agile"), + + # Animation frames for main characters + ("npcs", "gronk_front_walk1", "Gronk troll, PINK dreadlocks, black baggy shirt, front facing, walking animation frame 1"), + ("npcs", "gronk_front_walk2", "Gronk troll, PINK dreadlocks, black baggy shirt, front facing, walking animation frame 2"), + ("npcs", "gronk_back_walk1", "Gronk troll, PINK dreadlocks, black baggy shirt, back view, walking animation"), + ("npcs", "kai_front_walk1", "Kai survivor, GREEN dreadlocks, blue jacket, front facing, walking animation frame 1"), + ("npcs", "kai_front_walk2", "Kai survivor, GREEN dreadlocks, blue jacket, front facing, walking animation frame 2"), + ("npcs", "kai_back_walk1", "Kai survivor, GREEN dreadlocks, blue jacket, back view, walking animation"), + ("npcs", "ana_front_walk1", "Ana explorer, PINK dreadlocks, brown vest, front facing, walking animation frame 1"), + ("npcs", "ana_front_walk2", "Ana explorer, PINK dreadlocks, brown vest, front facing, walking animation frame 2"), + + # More animals + ("zivali", "pig_pink", "pink pig, curly tail, muddy, happy, farm animal"), + ("zivali", "sheep_fluffy", "white fluffy sheep, wool, cute, farm animal"), + ("zivali", "goat_brown", "brown goat, small horns, playful"), + ("zivali", "horse_brown", "brown horse, black mane, majestic"), + ("zivali", "rabbit_white", "white rabbit, long ears, fluffy"), + ("zivali", "wolf_grey", "grey wolf, fierce, pack hunter, wildlife"), + ("zivali", "bear_brown", "brown bear, large, powerful, wildlife"), + ("zivali", "fox_red", "red fox, bushy tail, clever, wildlife"), + ("zivali", "golden_goose", "Golden Goose, shimmering gold feathers, legendary"), + ("zivali", "fire_sheep", "Fire Sheep, burning wool flames, magical mutant"), + + # More mutants + ("mutanti", "slime_red", "red fire slime monster, hot, flames"), + ("mutanti", "slime_purple", "purple poison slime, toxic, bubbling"), + ("mutanti", "mutant_dog", "mutant dog, hairless, sores, vicious"), + ("mutanti", "mutant_rat_giant", "giant rat mutant, dog sized, diseased"), + ("mutanti", "mutant_spider", "giant spider, eight legs, web, terrifying"), + ("mutanti", "zombie_bloated", "bloated zombie, huge swollen, toxic green drool"), + ("mutanti", "zombie_armored", "armored zombie, riot gear, tough, slow"), + ("mutanti", "zombie_crawler", "crawler zombie, no legs, crawling desperately"), + + # More bosses + ("bosses", "boss_slime_emperor", "Slime Emperor, gigantic rainbow slime, crown, bouncing"), + ("bosses", "boss_dragon_ice", "Ice Dragon, blue scales, frost breath, majestic"), + ("bosses", "boss_spider_queen", "Spider Queen, giant spider, egg sacs, web lair"), + ("bosses", "boss_werewolf", "Werewolf Alpha, massive wolf-human hybrid, moonlight"), + ("bosses", "boss_vampire", "Vampire Lord, ancient, cape, fangs, pale"), + ("bosses", "boss_phoenix", "Phoenix boss, giant fire bird, rebirth"), + ("bosses", "boss_hydra", "Hydra, multi-headed serpent, regenerating"), + ("bosses", "boss_golem", "Stone Golem, massive rock creature, ancient"), + ("bosses", "boss_treant", "Elder Treant, giant living tree, nature guardian"), + ("bosses", "boss_demon", "Demon Prince, hellfire, horns, terrifying"), + + # More items + ("items", "tool_pickaxe_iron", "iron pickaxe, mining tool, wooden handle"), + ("items", "tool_shovel", "shovel, digging tool, wooden handle"), + ("items", "tool_hammer", "hammer, building tool"), + ("items", "weapon_bow_wood", "wooden bow with arrows"), + ("items", "weapon_spear", "wooden spear, hunting weapon"), + ("items", "weapon_crossbow", "crossbow, powerful ranged"), + ("items", "wand_lightning", "lightning magic wand, yellow crystal, sparks"), + ("items", "wand_earth", "earth magic wand, green crystal, nature"), + ("items", "wand_shadow", "shadow magic wand, purple crystal, darkness"), + ("items", "wand_healing", "healing wand, white crystal, glow"), + ("items", "potion_mana", "mana potion, blue liquid bottle"), + ("items", "backpack_small", "small leather backpack"), + ("items", "backpack_large", "large hiking backpack"), + ("items", "helmet_metal", "metal protective helmet"), + ("items", "gas_mask", "gas mask, protection, filters"), + ("items", "food_bread", "bread loaf, fresh baked"), + ("items", "food_apple", "red apple, fresh fruit"), + ("items", "food_meat", "cooked meat, steak"), + + # More environment + ("environment", "tree_pine", "pine tree, evergreen, cone shaped"), + ("environment", "tree_dead", "dead tree, no leaves, gnarled"), + ("environment", "tree_cherry", "cherry blossom tree, pink flowers"), + ("environment", "flower_red", "red flowers patch"), + ("environment", "flower_blue", "blue flowers patch"), + ("environment", "mushroom_brown", "brown mushrooms cluster"), + ("environment", "mushroom_red", "red spotted mushrooms"), + ("environment", "fence_wood", "wooden fence section"), + ("environment", "gate_wood", "wooden gate"), + ("environment", "bridge_wood", "wooden bridge section"), + ("environment", "barrel_wood", "wooden barrel, storage"), + ("environment", "crate_wooden", "wooden shipping crate"), + ("environment", "ruin_wall", "ruined brick wall section"), + ("environment", "car_rusted", "rusted abandoned car"), + ("environment", "sign_warning", "warning sign post"), + + # Tiles (32x32) + ("environment", "tile_grass_green", "green grass ground tile, 32x32 seamless texture"), + ("environment", "tile_grass_dry", "dry brown grass tile, 32x32 seamless texture"), + ("environment", "tile_dirt_brown", "brown dirt path tile, 32x32 seamless texture"), + ("environment", "tile_sand_yellow", "yellow sand beach tile, 32x32 seamless texture"), + ("environment", "tile_snow_white", "white snow tile, 32x32 seamless texture"), + ("environment", "tile_water_shallow", "shallow blue water tile, 32x32 seamless texture"), + ("environment", "tile_stone_grey", "grey stone floor tile, 32x32 seamless texture"), + + # UI + ("ui", "ui_health_bar", "health bar UI, red hearts row"), + ("ui", "ui_energy_bar", "energy bar UI, green lightning"), + ("ui", "ui_inventory_slot", "inventory slot UI, wooden frame"), + ("ui", "ui_button_menu", "menu button UI, wooden, round"), + ("ui", "ui_cursor_hand", "hand cursor pointer"), + ("ui", "ui_icon_gold", "gold coin icon"), +] + + +def log(msg): + """Log with timestamp""" + ts = datetime.now().strftime("%H:%M:%S") + print(f"[{ts}] {msg}") + sys.stdout.flush() + + +def generate_with_gemini(prompt, name): + """Generate image using Gemini CLI tool""" + # This uses the gemini command line if available + # Falls back to placeholder for now + log(f"ā³ Would generate: {name}") + return False + + +def remove_background(src_path, dst_path): + """Remove background using rembg""" + try: + from rembg import remove + from PIL import Image + + img = remove(Image.open(src_path)) + img.save(dst_path, "PNG") + return True + except Exception as e: + log(f"āŒ rembg error: {e}") + return False + + +def main(): + log("=" * 60) + log("šŸŽ® DOLINA SMRTI - Background Asset Generator") + log("=" * 60) + + # Get already generated + existing = set() + for cat in ["npcs", "zivali", "mutanti", "bosses", "items", "environment", "ui"]: + cat_dir = OUTPUT / cat + if cat_dir.exists(): + for f in cat_dir.glob("*.png"): + existing.add(f.stem) + + log(f"šŸ“Š Existing: {len(existing)} | Total: {len(ASSETS)}") + + remaining = [(c, n, p) for c, n, p in ASSETS if n not in existing] + log(f"šŸŽÆ To generate: {len(remaining)}") + + if not remaining: + log("āœ… All assets already generated!") + return + + log("\nšŸ“‹ Queue:") + for cat, name, _ in remaining[:10]: + log(f" - {cat}/{name}") + if len(remaining) > 10: + log(f" ... and {len(remaining) - 10} more") + + log("\nāš ļø Manual generation required:") + log(" This script shows the queue.") + log(" Use the Gemini generate_image tool interactively.") + log("\nāœ… Script complete - see queue above") + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_comfyui_transparent.py b/scripts/generate_comfyui_transparent.py new file mode 100644 index 000000000..71b2ef811 --- /dev/null +++ b/scripts/generate_comfyui_transparent.py @@ -0,0 +1,349 @@ +#!/usr/bin/env python3 +""" +šŸŽ® DOLINA SMRTI - ComfyUI Local Generator +Transparent Background (Alpha Channel) +2D Indie Cartoon Style - Approved Gronk/Kai look +""" + +import os +import json +import time +import uuid +import requests +from pathlib import Path +from PIL import Image +import io + +# Configuration +COMFYUI_URL = "http://127.0.0.1:8000" +OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/images") + +# ============================================================================ +# STYLE DEFINITIONS - Approved 2D Indie Cartoon +# ============================================================================ + +STYLE_PREFIX = """2D indie game sprite, cartoon vector style, clean smooth lines, +full body visible from head to feet standing on ground, +tight crop max 5 pixel padding around subject, """ + +STYLE_SUFFIX = """, isolated on pure white background #FFFFFF, game asset""" + +NEGATIVE_PROMPT = """pixel art, pixelated, voxel, 3d render, realistic photo, +anime, manga, chibi, floating, cut off, cropped, blurry, low quality, +watermark, text, signature, green background, colored background""" + +# ============================================================================ +# MASTER REGISTRY +# ============================================================================ + +def generate_registry(): + """Generate complete asset registry""" + assets = [] + + # Main Characters + gronk = """Gronk the troll, massive green-grey skinned troll, PINK dreadlocks, + stretched earlobes with large gauges, facial piercings, holding colorful vape device with pink smoke, + wearing LOOSE BAGGY black t-shirt with band logo, LOOSE WIDE black pants, pink sneakers, + peaceful zen expression""" + + kai = """Kai teenage boy survivor, post-apocalyptic nomad style, GREEN natural dreadlocks hair, + stretched earlobes with plugs, facial piercings on nose and lip, wearing dirty worn blue jacket, + torn jeans, combat boots, survival backpack, determined serious expression, athletic build""" + + ana = """Ana teenage girl explorer, PINK dreadlocks hair, stretched earlobes with small plugs, + wearing brown adventure vest over green shirt, blue jeans, brown hiking boots, + leather backpack with map, kind curious expression""" + + main_chars = [ + ("gronk_troll", gronk), + ("kai_survivor", kai), + ("ana_explorer", ana), + ] + + for name, desc in main_chars: + assets.append({"cat": "npcs", "file": f"{name}.png", "prompt": desc}) + for d in ["front", "back", "left", "right"]: + for a in ["idle", "walk1", "walk2"]: + assets.append({ + "cat": "npcs", + "file": f"{name}_{d}_{a}.png", + "prompt": f"{desc}, {d} facing view, {a} animation frame" + }) + + # NPCs + npcs = [ + ("npc_trader", "wasteland trader, nomadic merchant with cart, weathered face, hooded cloak"), + ("npc_blacksmith", "nomadic blacksmith, leather apron, strong arms, hammer"), + ("npc_healer", "herbalist healer woman, herb pouch, kind elderly, flower crown"), + ("npc_hunter", "wasteland hunter, crossbow, animal pelts, face paint"), + ("npc_farmer", "apocalypse farmer, patched overalls, straw hat, hoe"), + ] + + for name, desc in npcs: + assets.append({"cat": "npcs", "file": f"{name}.png", "prompt": desc}) + + # Animals + animals = [ + ("susi_dachshund", "Susi dachshund dog, brown and black, long body, floppy ears, pink collar"), + ("dog_husky", "husky dog, fluffy grey white, blue eyes, friendly"), + ("cat_tabby", "orange tabby cat, striped, lazy curious"), + ("cow_spotted", "dairy cow, black white spots, friendly"), + ("chicken_white", "white chicken, red comb, pecking"), + ("phoenix_chicken", "Phoenix Chicken, fire feathers, glowing orange-red, legendary"), + ("unicorn", "magical Unicorn, white horse, rainbow mane, golden spiral horn"), + ] + + for name, desc in animals: + assets.append({"cat": "zivali", "file": f"{name}.png", "prompt": desc}) + + # Mutants + mutants = [ + ("zombie_basic", "basic zombie, shambling, torn clothes, grey-green skin, undead"), + ("zombie_runner", "fast zombie, sprinting, aggressive, rage face"), + ("zombie_dreadlocks", "zombie with dreadlocks, brown shirt, farmer style"), + ("slime_green", "green slime monster, bouncy blob, cute-creepy, small eyes"), + ("slime_blue", "blue slime, water element, wobbly, transparent"), + ] + + for name, desc in mutants: + assets.append({"cat": "mutanti", "file": f"{name}.png", "prompt": desc}) + + # Bosses + bosses = [ + ("boss_trex", "T-Rex dinosaur boss, massive predator, huge jaws, fierce"), + ("boss_kraken", "Kraken sea monster, giant octopus, many tentacles"), + ("boss_zombie_king", "Zombie King, massive undead, rotting crown"), + ("boss_slime_emperor", "Slime Emperor, gigantic rainbow slime, crown"), + ("boss_dragon_fire", "Fire Dragon, red scales, breathing flames, wings"), + ] + + for name, desc in bosses: + assets.append({"cat": "bosses", "file": f"{name}.png", "prompt": desc}) + + # Items + items = [ + ("tool_axe_iron", "iron axe, chopping tool, wooden handle"), + ("tool_pickaxe_iron", "iron pickaxe, mining tool"), + ("weapon_sword_iron", "iron sword, combat blade"), + ("weapon_bow_wood", "wooden bow with arrows"), + ("wand_fire", "fire magic wand, red crystal tip, flames"), + ("wand_ice", "ice magic wand, blue crystal, frost"), + ("ana_bracelet", "Ana's magical bracelet, glowing, family heirloom"), + ("gronk_vape", "Gronk's golden vape device, colorful, smoking"), + ("potion_health", "health potion, red liquid bottle"), + ("food_bread", "bread loaf, fresh baked"), + ] + + for name, desc in items: + assets.append({"cat": "items", "file": f"{name}.png", "prompt": desc}) + + # Environment + tiles = [ + ("tile_grass_green", "green grass ground tile, 32x32 seamless"), + ("tile_dirt_brown", "brown dirt path tile, 32x32 seamless"), + ("tile_water_shallow", "shallow blue water tile, 32x32 seamless"), + ("tile_stone_grey", "grey stone floor tile, 32x32 seamless"), + ] + + objects = [ + ("tree_oak", "oak tree, green leaves, brown trunk"), + ("tree_dead", "dead tree, no leaves, gnarled branches"), + ("rock_large", "large boulder, moss covered"), + ("bush_green", "green bush, leafy"), + ("campfire", "campfire, flames, logs"), + ("chest_wooden", "wooden treasure chest, closed"), + ] + + for name, desc in tiles + objects: + assets.append({"cat": "environment", "file": f"{name}.png", "prompt": desc}) + + return assets + + +# ============================================================================ +# COMFYUI WORKFLOW - With Background Removal +# ============================================================================ + +def create_workflow(prompt_text: str, output_name: str, size: int = 512) -> dict: + """Creates ComfyUI workflow with white background for easy removal""" + seed = int(time.time() * 1000) % 2147483647 + full_prompt = STYLE_PREFIX + prompt_text + STYLE_SUFFIX + + return { + "1": { + "class_type": "CheckpointLoaderSimple", + "inputs": {"ckpt_name": "dreamshaper_8.safetensors"} + }, + "2": { + "class_type": "EmptyLatentImage", + "inputs": {"width": size, "height": size, "batch_size": 1} + }, + "3": { + "class_type": "CLIPTextEncode", + "inputs": {"text": full_prompt, "clip": ["1", 1]} + }, + "4": { + "class_type": "CLIPTextEncode", + "inputs": {"text": NEGATIVE_PROMPT, "clip": ["1", 1]} + }, + "5": { + "class_type": "KSampler", + "inputs": { + "seed": seed, + "steps": 30, + "cfg": 7.5, + "sampler_name": "euler_ancestral", + "scheduler": "karras", + "denoise": 1.0, + "model": ["1", 0], + "positive": ["3", 0], + "negative": ["4", 0], + "latent_image": ["2", 0] + } + }, + "6": { + "class_type": "VAEDecode", + "inputs": {"samples": ["5", 0], "vae": ["1", 2]} + }, + "7": { + "class_type": "SaveImage", + "inputs": {"filename_prefix": output_name, "images": ["6", 0]} + } + } + + +def queue_prompt(workflow: dict) -> str: + try: + r = requests.post( + f"{COMFYUI_URL}/prompt", + json={"prompt": workflow, "client_id": f"ds_{uuid.uuid4().hex[:8]}"} + ) + return r.json().get("prompt_id") + except Exception as e: + print(f"Queue error: {e}") + return None + + +def wait_completion(prompt_id: str, timeout: int = 300) -> bool: + start = time.time() + while time.time() - start < timeout: + try: + r = requests.get(f"{COMFYUI_URL}/history/{prompt_id}") + data = r.json() + if prompt_id in data and data[prompt_id].get("outputs"): + return True + except: + pass + time.sleep(2) + return False + + +def download_image(prompt_id: str, output_path: Path) -> bool: + try: + h = requests.get(f"{COMFYUI_URL}/history/{prompt_id}").json() + for out in h.get(prompt_id, {}).get("outputs", {}).values(): + for img in out.get("images", []): + r = requests.get(f"{COMFYUI_URL}/view", params={ + "filename": img["filename"], + "subfolder": img.get("subfolder", ""), + "type": "output" + }) + if r.status_code == 200: + output_path.parent.mkdir(parents=True, exist_ok=True) + + # Load image and convert white background to transparent + img_data = Image.open(io.BytesIO(r.content)).convert("RGBA") + datas = img_data.getdata() + + new_data = [] + for item in datas: + # If pixel is white (or near white), make transparent + if item[0] > 240 and item[1] > 240 and item[2] > 240: + new_data.append((255, 255, 255, 0)) # Transparent + else: + new_data.append(item) + + img_data.putdata(new_data) + img_data.save(str(output_path), "PNG") + return True + return False + except Exception as e: + print(f"Download error: {e}") + return False + + +def main(): + print("=" * 70) + print("šŸŽ® DOLINA SMRTI - ComfyUI Local Generator") + print(" 2D Indie Cartoon Style | Transparent Background") + print("=" * 70) + + # Check ComfyUI + try: + r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5) + v = r.json()["system"]["comfyui_version"] + print(f"āœ… ComfyUI v{v} running on port 8000") + except: + print("āŒ ComfyUI not running!") + print(" Start with: open /Applications/ComfyUI.app") + return + + # Build registry + print("\nšŸ“‹ Building asset registry...") + ASSETS = generate_registry() + print(f"šŸ“Š Total: {len(ASSETS)} assets") + + cats = {} + for a in ASSETS: + cats[a["cat"]] = cats.get(a["cat"], 0) + 1 + print("\nBreakdown:") + for cat, count in sorted(cats.items(), key=lambda x: -x[1]): + print(f" {cat}: {count}") + + existing = sum(1 for a in ASSETS if (OUTPUT_DIR / a["cat"] / a["file"]).exists()) + print(f"\nāœ… Exist: {existing} | šŸŽÆ Generate: {len(ASSETS) - existing}") + + print("\nšŸŽ® STARTING GENERATION...\n") + + success, skip, fail = 0, 0, 0 + + for i, asset in enumerate(ASSETS, 1): + path = OUTPUT_DIR / asset["cat"] / asset["file"] + + if path.exists(): + skip += 1 + continue + + print(f"[{i}/{len(ASSETS)}] šŸŽØ {asset['file'][:40]}...") + + # Determine size + size = 512 + if "tile_" in asset["file"]: + size = 256 # Tiles are smaller + elif "boss_" in asset["file"]: + size = 768 # Bosses are larger + + wf = create_workflow(asset["prompt"], asset["file"].replace(".png", ""), size) + pid = queue_prompt(wf) + + if pid and wait_completion(pid) and download_image(pid, path): + print(f" āœ… SAVED (transparent)") + success += 1 + else: + print(f" āŒ FAILED") + fail += 1 + + if i % 10 == 0: + print(f"\nšŸ“Š [{i}/{len(ASSETS)}] āœ…{success} ā­ļø{skip} āŒ{fail}\n") + + time.sleep(0.5) + + print("\n" + "=" * 70) + print("šŸŽ® GENERATION COMPLETE!") + print(f"āœ… Success: {success} | ā­ļø Skip: {skip} | āŒ Fail: {fail}") + print(f"šŸ“ Output: {OUTPUT_DIR}") + print("\nAll images have TRANSPARENT backgrounds (alpha channel)") + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_local_final.py b/scripts/generate_local_final.py new file mode 100644 index 000000000..c99efd00a --- /dev/null +++ b/scripts/generate_local_final.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python3 +""" +šŸŽ® DOLINA SMRTI - ComfyUI Local Generator +Generates remaining assets with ComfyUI + rembg for transparent backgrounds +No API rate limits! +""" + +import os +import sys +import json +import time +import uuid +import requests +from pathlib import Path +from datetime import datetime + +# Install rembg on first run if needed +try: + from rembg import remove + from PIL import Image +except ImportError: + print("Installing dependencies...") + os.system("pip3 install --user rembg pillow onnxruntime") + from rembg import remove + from PIL import Image + +# Configuration +COMFYUI_URL = "http://127.0.0.1:8000" +OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/images") +COMFYUI_OUTPUT = Path("/Users/davidkotnik/comfyui/output") + +# Style - matches the 2D Indie Cartoon style +STYLE = "2D indie game sprite, cartoon vector style, clean smooth lines, full body visible from head to feet standing on ground, tight crop, isolated on pure white background #FFFFFF" +NEGATIVE = "pixel art, pixelated, voxel, 3d, realistic, photo, anime, manga, chibi, blurry, watermark, text, green background" + +# ============================================================================ +# REMAINING ASSETS TO GENERATE +# ============================================================================ + +ASSETS = [ + # Remaining NPCs + ("npcs", "npc_elder", "wise tribal elder NPC, walking stick, long white beard, robes"), + ("npcs", "npc_child", "survivor orphan child NPC, oversized clothes, teddy bear"), + ("npcs", "npc_cook", "camp cook NPC, pot and ladle, apron, big belly, friendly"), + ("npcs", "npc_scout", "nomad scout NPC, binoculars, light leather armor, agile"), + + # Animation frames + ("npcs", "gronk_front_walk1", "Gronk troll, PINK dreadlocks, black baggy shirt pants, front view, left leg forward walking"), + ("npcs", "gronk_front_walk2", "Gronk troll, PINK dreadlocks, black baggy shirt pants, front view, right leg forward walking"), + ("npcs", "gronk_back_idle", "Gronk troll, PINK dreadlocks, black baggy shirt pants, back view, standing idle"), + ("npcs", "kai_front_walk1", "Kai survivor, GREEN dreadlocks, blue jacket, front view, left leg forward walking"), + ("npcs", "kai_front_walk2", "Kai survivor, GREEN dreadlocks, blue jacket, front view, right leg forward walking"), + ("npcs", "kai_back_idle", "Kai survivor, GREEN dreadlocks, blue jacket, back view, standing idle"), + ("npcs", "ana_front_walk1", "Ana explorer, PINK dreadlocks, brown vest, front view, left leg forward walking"), + ("npcs", "ana_front_walk2", "Ana explorer, PINK dreadlocks, brown vest, front view, right leg forward walking"), + + # Remaining animals + ("zivali", "goat_brown", "brown goat farm animal, small horns, playful"), + ("zivali", "rabbit_white", "white rabbit, long ears, fluffy"), + ("zivali", "fox_red", "red fox wildlife, bushy tail, clever"), + ("zivali", "golden_goose", "Golden Goose legendary, shimmering gold feathers"), + + # Remaining mutants + ("mutanti", "slime_red", "red fire slime monster, hot flames"), + ("mutanti", "slime_purple", "purple poison slime, toxic bubbling"), + ("mutanti", "mutant_rat_giant", "giant rat mutant, dog sized, diseased"), + ("mutanti", "zombie_bloated", "bloated zombie, huge swollen, toxic drool"), + ("mutanti", "zombie_armored", "armored zombie, riot gear, tough"), + ("mutanti", "zombie_crawler", "crawler zombie, no legs, crawling"), + + # Remaining bosses + ("bosses", "boss_dragon_ice", "Ice Dragon boss, blue scales, frost breath"), + ("bosses", "boss_phoenix", "Phoenix boss, giant fire bird, rebirth flames"), + ("bosses", "boss_hydra", "Hydra boss, multi-headed serpent"), + ("bosses", "boss_treant", "Elder Treant boss, giant living tree, nature"), + ("bosses", "boss_demon", "Demon Prince boss, hellfire, horns"), + + # Remaining items + ("items", "tool_pickaxe_iron", "iron pickaxe mining tool"), + ("items", "tool_shovel", "shovel digging tool"), + ("items", "tool_hammer", "hammer building tool"), + ("items", "weapon_bow_wood", "wooden bow with arrows"), + ("items", "weapon_spear", "wooden spear, hunting weapon"), + ("items", "weapon_crossbow", "crossbow ranged weapon"), + ("items", "wand_lightning", "lightning magic wand, yellow crystal, sparks"), + ("items", "wand_earth", "earth magic wand, green crystal, nature"), + ("items", "wand_shadow", "shadow magic wand, purple crystal, darkness"), + ("items", "wand_healing", "healing wand, white crystal, glow"), + ("items", "potion_mana", "mana potion, blue liquid bottle"), + ("items", "backpack_small", "small leather backpack"), + ("items", "helmet_metal", "metal protective helmet"), + ("items", "gas_mask", "gas mask with filters"), + ("items", "food_bread", "bread loaf, fresh baked"), + ("items", "food_apple", "red apple, fresh fruit"), + ("items", "food_meat", "cooked meat steak"), + + # Remaining environment + ("environment", "tree_pine", "pine tree, evergreen, cone shaped"), + ("environment", "tree_dead", "dead tree, no leaves, gnarled branches"), + ("environment", "tree_cherry", "cherry blossom tree, pink flowers"), + ("environment", "flower_red", "red flowers patch"), + ("environment", "flower_blue", "blue flowers patch"), + ("environment", "mushroom_red", "red spotted mushrooms"), + ("environment", "fence_wood", "wooden fence section"), + ("environment", "barrel_wood", "wooden barrel storage"), + ("environment", "crate_wooden", "wooden shipping crate"), + ("environment", "ruin_wall", "ruined brick wall section"), + ("environment", "car_rusted", "rusted abandoned car wreck"), + ("environment", "sign_warning", "warning sign post"), +] + + +def log(msg): + ts = datetime.now().strftime("%H:%M:%S") + print(f"[{ts}] {msg}") + sys.stdout.flush() + + +def create_workflow(prompt_text, output_name, size=512): + """Create ComfyUI workflow""" + seed = int(time.time() * 1000) % 2147483647 + full_prompt = f"{STYLE}, {prompt_text}" + + return { + "1": { + "class_type": "CheckpointLoaderSimple", + "inputs": {"ckpt_name": "dreamshaper_8.safetensors"} + }, + "2": { + "class_type": "EmptyLatentImage", + "inputs": {"width": size, "height": size, "batch_size": 1} + }, + "3": { + "class_type": "CLIPTextEncode", + "inputs": {"text": full_prompt, "clip": ["1", 1]} + }, + "4": { + "class_type": "CLIPTextEncode", + "inputs": {"text": NEGATIVE, "clip": ["1", 1]} + }, + "5": { + "class_type": "KSampler", + "inputs": { + "seed": seed, + "steps": 30, + "cfg": 7.5, + "sampler_name": "euler_ancestral", + "scheduler": "karras", + "denoise": 1.0, + "model": ["1", 0], + "positive": ["3", 0], + "negative": ["4", 0], + "latent_image": ["2", 0] + } + }, + "6": { + "class_type": "VAEDecode", + "inputs": {"samples": ["5", 0], "vae": ["1", 2]} + }, + "7": { + "class_type": "SaveImage", + "inputs": {"filename_prefix": output_name, "images": ["6", 0]} + } + } + + +def queue_prompt(workflow): + try: + r = requests.post( + f"{COMFYUI_URL}/prompt", + json={"prompt": workflow, "client_id": f"ds_{uuid.uuid4().hex[:8]}"}, + timeout=10 + ) + return r.json().get("prompt_id") + except Exception as e: + log(f"āŒ Queue error: {e}") + return None + + +def wait_completion(prompt_id, timeout=120): + start = time.time() + while time.time() - start < timeout: + try: + r = requests.get(f"{COMFYUI_URL}/history/{prompt_id}", timeout=5) + data = r.json() + if prompt_id in data and data[prompt_id].get("outputs"): + return True + except: + pass + time.sleep(2) + return False + + +def download_and_process(prompt_id, output_path): + """Download from ComfyUI and remove background with rembg""" + try: + h = requests.get(f"{COMFYUI_URL}/history/{prompt_id}").json() + for out in h.get(prompt_id, {}).get("outputs", {}).values(): + for img in out.get("images", []): + r = requests.get(f"{COMFYUI_URL}/view", params={ + "filename": img["filename"], + "subfolder": img.get("subfolder", ""), + "type": "output" + }) + if r.status_code == 200: + output_path.parent.mkdir(parents=True, exist_ok=True) + + # Load and remove background + from io import BytesIO + src_img = Image.open(BytesIO(r.content)) + transparent_img = remove(src_img) + transparent_img.save(str(output_path), "PNG") + return True + return False + except Exception as e: + log(f"āŒ Download error: {e}") + return False + + +def main(): + log("=" * 60) + log("šŸŽ® DOLINA SMRTI - ComfyUI Local Generator") + log(" No API rate limits! All local processing!") + log("=" * 60) + + # Check ComfyUI + try: + r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5) + v = r.json()["system"]["comfyui_version"] + log(f"āœ… ComfyUI v{v} running") + except: + log("āŒ ComfyUI not running! Start it first.") + return + + # Get existing files + existing = set() + for cat, name, _ in ASSETS: + path = OUTPUT_DIR / cat / f"{name}.png" + if path.exists(): + existing.add(name) + + remaining = [(c, n, p) for c, n, p in ASSETS if n not in existing] + + log(f"\nšŸ“Š Status:") + log(f" Total in registry: {len(ASSETS)}") + log(f" Already generated: {len(existing)}") + log(f" Remaining: {len(remaining)}") + + if not remaining: + log("\nāœ… All assets already generated!") + return + + log(f"\nšŸš€ Starting generation of {len(remaining)} assets...") + log(" Each takes ~15-30 seconds\n") + + success, fail = 0, 0 + start_time = time.time() + + for i, (cat, name, prompt) in enumerate(remaining, 1): + path = OUTPUT_DIR / cat / f"{name}.png" + + log(f"[{i}/{len(remaining)}] šŸŽØ {name}...") + + # Determine size + size = 512 + if "boss_" in name: + size = 768 + + wf = create_workflow(prompt, name, size) + pid = queue_prompt(wf) + + if pid and wait_completion(pid) and download_and_process(pid, path): + log(f" āœ… DONE (transparent)") + success += 1 + else: + log(f" āŒ FAILED") + fail += 1 + + # Progress every 5 + if i % 5 == 0: + elapsed = time.time() - start_time + per_asset = elapsed / i + remaining_time = per_asset * (len(remaining) - i) + log(f"\nšŸ“Š Progress: {i}/{len(remaining)} | āœ…{success} āŒ{fail}") + log(f" ETA: {remaining_time/60:.1f} min\n") + + elapsed = time.time() - start_time + log("\n" + "=" * 60) + log("šŸŽ® GENERATION COMPLETE!") + log(f" āœ… Success: {success}") + log(f" āŒ Failed: {fail}") + log(f" ā±ļø Time: {elapsed/60:.1f} min") + log(f" šŸ“ Output: {OUTPUT_DIR}") + log("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_v7_final.py b/scripts/generate_v7_final.py new file mode 100644 index 000000000..db9fb2213 --- /dev/null +++ b/scripts/generate_v7_final.py @@ -0,0 +1,469 @@ +#!/usr/bin/env python3 +""" +šŸŽ® DOLINA SMRTI - FINALNI GENERATOR V7.0 +2D Indie Cartoon Style - Green Chroma-Key Background +Approved style based on Gronk/Kai test images +9000+ Assets +""" + +import os +import time +import google.generativeai as genai +from pathlib import Path +from PIL import Image +import io + +# Configuration +OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/images") +GREEN_BG = "solid bright green background RGB(0,255,0) chroma key green screen" + +# Style that worked for Gronk/Kai test images +STYLE_PREFIX = """2D indie game character sprite, cartoon vector style, clean lines, +full body visible from head to feet standing on ground, """ + +STYLE_SUFFIX = f""", {GREEN_BG}, game asset, PNG""" + +# ============================================================================ +# MASTER REGISTRY - 9000+ ASSETS +# ============================================================================ + +def generate_registry(): + """Generate complete asset registry with approved style""" + assets = [] + + # ======================================================================== + # 1. MAIN CHARACTERS (~150 with animations) + # ======================================================================== + + # GRONK - Approved style + gronk_base = """Gronk the troll, massive green-grey skinned troll, PINK dreadlocks, + stretched earlobes with large gauges, facial piercings, holding colorful vape device with pink smoke, + wearing LOOSE BAGGY black t-shirt with band logo, LOOSE WIDE black pants, pink sneakers, + peaceful zen expression""" + + # KAI - Approved style + kai_base = """Kai teenage boy survivor, post-apocalyptic nomad style, GREEN natural dreadlocks hair, + stretched earlobes with plugs, facial piercings on nose and lip, wearing dirty worn blue jacket, + torn jeans, combat boots, survival backpack, determined serious expression, athletic build""" + + # ANA - Twin sister + ana_base = """Ana teenage girl explorer, Kai's twin sister, PINK dreadlocks hair, + stretched earlobes with small plugs, wearing brown adventure vest over green shirt, + blue jeans, brown boots, leather backpack with map, kind curious expression""" + + main_chars = [ + ("gronk_troll", gronk_base), + ("kai_survivor", kai_base), + ("ana_explorer", ana_base), + ] + + # Add base sprites and animations + for name, desc in main_chars: + assets.append({"cat": "npcs", "file": f"{name}.png", "prompt": desc}) + + # 4 directions, animations + for direction in ["front", "back", "left", "right"]: + for action in ["idle", "walk1", "walk2", "walk3", "walk4"]: + assets.append({ + "cat": "npcs", + "file": f"{name}_{direction}_{action}.png", + "prompt": f"{desc}, {direction} facing view, {action} animation frame" + }) + # Work animations + for work in ["chop", "mine", "dig"]: + assets.append({ + "cat": "npcs", + "file": f"{name}_{direction}_{work}.png", + "prompt": f"{desc}, {direction} facing, {work}ping with tool animation" + }) + + # ======================================================================== + # 2. NPCs - NOMADIC SURVIVORS (~50) + # ======================================================================== + + npcs = [ + ("npc_trader", "wasteland trader, nomadic merchant with cart, weathered face, hooded cloak"), + ("npc_blacksmith", "nomadic blacksmith, leather apron, strong arms, hammer, burns"), + ("npc_healer", "herbalist healer woman, herb pouch, kind elderly, flower crown"), + ("npc_hunter", "wasteland hunter, crossbow, animal pelts, face paint"), + ("npc_farmer", "apocalypse farmer, patched overalls, straw hat, hoe"), + ("npc_mechanic", "mechanic survivor, oil stained, wrench, welding goggles"), + ("npc_soldier", "ex-military survivor, tactical vest, rifle, scarred"), + ("npc_medic", "field medic, white coat blood stains, medical bag"), + ("npc_elder", "wise tribal elder, walking stick, long white beard"), + ("npc_child", "survivor orphan child, oversized clothes, teddy bear"), + ("npc_cook", "camp cook, pot and ladle, big belly, friendly"), + ("npc_scout", "nomad scout, binoculars, light armor, agile"), + ] + + for name, desc in npcs: + assets.append({"cat": "npcs", "file": f"{name}.png", "prompt": f"2D indie game character, {desc}, full body standing"}) + + # ======================================================================== + # 3. ANIMALS - COMPANIONS & WILDLIFE (~100) + # ======================================================================== + + animals = [ + # Companions + ("susi_dachshund", "Susi dachshund dog, brown and black, long body, floppy ears, pink collar, happy"), + ("dog_husky", "husky dog, fluffy grey white, blue eyes, friendly"), + ("dog_shepherd", "german shepherd, brown black, alert protective"), + ("cat_tabby", "orange tabby cat, striped, lazy curious"), + ("cat_black", "black cat, green eyes, mysterious"), + + # Farm + ("cow_spotted", "dairy cow, black white spots, friendly"), + ("sheep_fluffy", "white sheep, very fluffy wool, cute"), + ("chicken_white", "white chicken, red comb, pecking"), + ("pig_pink", "pink pig, curly tail, muddy happy"), + ("goat_brown", "brown goat, small horns, playful"), + ("horse_brown", "brown horse, black mane, majestic"), + ("donkey_grey", "grey donkey, big ears, stubborn"), + ("rabbit_white", "white rabbit, long ears, fluffy"), + + # Wildlife + ("deer_forest", "forest deer, brown, antlers, graceful"), + ("wolf_grey", "grey wolf, fierce, pack hunter"), + ("bear_brown", "brown bear, large, powerful"), + ("fox_red", "red fox, bushy tail, clever"), + ("boar_wild", "wild boar, tusks, aggressive"), + ("owl_barn", "barn owl, white face, wise"), + ("crow_black", "black crow, intelligent, ominous"), + + # Legendary + ("phoenix_chicken", "Phoenix Chicken, fire feathers, glowing orange-red, legendary rare"), + ("unicorn", "white Unicorn, rainbow mane, golden spiral horn, magical"), + ("golden_goose", "Golden Goose, shimmering gold feathers, lays golden eggs"), + ("fire_sheep", "Fire Sheep, burning wool flames, magical mutant"), + ("three_headed_chicken", "Three-Headed Chicken mutant, bizarre, three heads"), + ] + + for name, desc in animals: + assets.append({"cat": "zivali", "file": f"{name}.png", "prompt": f"2D indie game animal sprite, {desc}, full body side view"}) + # Walk animation + for frame in ["walk1", "walk2", "idle"]: + assets.append({ + "cat": "zivali", + "file": f"{name}_{frame}.png", + "prompt": f"2D indie game animal sprite, {desc}, {frame} animation frame" + }) + + # ======================================================================== + # 4. ZOMBIES & MUTANTS (~80) + # ======================================================================== + + mutants = [ + ("zombie_basic", "basic zombie, shambling, torn clothes, grey skin, undead"), + ("zombie_runner", "fast zombie, sprinting, aggressive, rage face"), + ("zombie_bloated", "bloated zombie, huge swollen, toxic green drool"), + ("zombie_armored", "armored zombie, riot gear, tough, slow"), + ("zombie_crawler", "crawler zombie, no legs, crawling desperately"), + ("zombie_screamer", "screamer zombie, wide mouth, alerting scream"), + ("zombie_dreadlocks", "zombie with dreadlocks, brown shirt, farmer style"), + + ("mutant_dog", "mutant dog, hairless, sores, vicious"), + ("mutant_rat_giant", "giant rat mutant, dog sized, disease"), + ("mutant_spider", "giant spider, eight legs, web, terrifying"), + ("mutant_crow", "mutant crow, large, red eyes, circling"), + + ("slime_green", "green slime monster, bouncy blob, cute-creepy"), + ("slime_blue", "blue slime, water element, wobbly"), + ("slime_red", "red slime, fire element, hot"), + ("slime_purple", "purple slime, poison element, toxic"), + ] + + for name, desc in mutants: + assets.append({"cat": "mutanti", "file": f"{name}.png", "prompt": f"2D indie game monster sprite, {desc}, full body"}) + for frame in ["walk1", "walk2", "attack"]: + assets.append({ + "cat": "mutanti", + "file": f"{name}_{frame}.png", + "prompt": f"2D indie game monster sprite, {desc}, {frame} animation" + }) + + # ======================================================================== + # 5. BOSSES (~30) + # ======================================================================== + + bosses = [ + ("boss_zombie_king", "Zombie King, massive undead ruler, rotting crown, commands zombies"), + ("boss_slime_emperor", "Slime Emperor, gigantic rainbow slime, crown, bouncing"), + ("boss_trex", "T-Rex dinosaur, massive prehistoric predator, huge jaws"), + ("boss_kraken", "Kraken, giant sea monster, many tentacles, ocean terror"), + ("boss_troll_alpha", "Alpha Troll King, massive green troll, tribal crown, Gronk's enemy"), + ("boss_dragon_fire", "Fire Dragon, red scales, breathing flames, wings"), + ("boss_dragon_ice", "Ice Dragon, blue scales, frost breath, majestic"), + ("boss_spider_queen", "Spider Queen, giant spider, egg sacs, web lair"), + ("boss_werewolf", "Werewolf Alpha, massive wolf-human hybrid, moonlight"), + ("boss_vampire", "Vampire Lord, ancient, cape, fangs, pale"), + ("boss_phoenix", "Phoenix boss, giant fire bird, rebirth"), + ("boss_hydra", "Hydra, multi-headed serpent, regenerating"), + ("boss_golem", "Stone Golem, massive rock creature, ancient"), + ("boss_treant", "Elder Treant, giant living tree, nature guardian"), + ("boss_demon", "Demon Prince, hellfire, horns, terrifying"), + ] + + for name, desc in bosses: + assets.append({"cat": "bosses", "file": f"{name}.png", "prompt": f"2D indie game boss sprite, {desc}, full body, large 128px"}) + for frame in ["idle", "attack1", "attack2"]: + assets.append({ + "cat": "bosses", + "file": f"{name}_{frame}.png", + "prompt": f"2D indie game boss sprite, {desc}, {frame} animation, large" + }) + + # ======================================================================== + # 6. ENVIRONMENT - TILES & OBJECTS (~200) + # ======================================================================== + + # Biome tiles (32x32 seamless) + biome_tiles = [ + ("tile_grass_green", "green grass ground tile, 32x32 seamless"), + ("tile_grass_dry", "dry brown grass tile, 32x32 seamless"), + ("tile_dirt_brown", "brown dirt path tile, 32x32 seamless"), + ("tile_sand_yellow", "yellow sand beach tile, 32x32 seamless"), + ("tile_snow_white", "white snow tile, 32x32 seamless"), + ("tile_concrete_cracked", "cracked concrete urban tile, 32x32 seamless"), + ("tile_asphalt_broken", "broken asphalt road tile, 32x32 seamless"), + ("tile_water_shallow", "shallow blue water tile, 32x32 seamless"), + ("tile_water_deep", "deep blue water tile, 32x32 seamless"), + ("tile_swamp_mud", "murky swamp mud tile, 32x32 seamless"), + ("tile_lava_hot", "hot lava tile glowing, 32x32 seamless"), + ("tile_ice_blue", "blue ice frozen tile, 32x32 seamless"), + ("tile_rock_grey", "grey rocky ground tile, 32x32 seamless"), + ("tile_wood_plank", "wooden floor plank tile, 32x32 seamless"), + ("tile_stone_brick", "stone brick floor tile, 32x32 seamless"), + ] + + for name, desc in biome_tiles: + assets.append({"cat": "environment", "file": f"{name}.png", "prompt": f"2D game tile, {desc}"}) + + # Environment objects + env_objects = [ + ("tree_oak", "oak tree, green leaves, brown trunk"), + ("tree_pine", "pine tree, evergreen, cone shaped"), + ("tree_dead", "dead tree, no leaves, gnarled"), + ("tree_cherry", "cherry blossom tree, pink flowers"), + ("tree_palm", "palm tree, coconuts, tropical"), + + ("bush_green", "green bush, leafy"), + ("bush_berry", "berry bush, red berries"), + ("flower_red", "red flowers patch"), + ("flower_blue", "blue flowers patch"), + ("flower_yellow", "sunflowers, tall yellow"), + + ("rock_small", "small rocks pile"), + ("rock_large", "large boulder, moss"), + ("log_fallen", "fallen log, decomposing"), + ("mushroom_brown", "brown mushrooms cluster"), + ("mushroom_red", "red spotted mushrooms"), + + ("fence_wood", "wooden fence section"), + ("fence_metal", "metal chain fence section"), + ("gate_wood", "wooden gate"), + ("bridge_wood", "wooden bridge section"), + + ("campfire", "campfire, flames, logs"), + ("tent_camping", "camping tent, green"), + ("chest_wooden", "wooden treasure chest"), + ("barrel_wood", "wooden barrel, storage"), + ("crate_wooden", "wooden shipping crate"), + + ("ruin_wall", "ruined brick wall section"), + ("ruin_pillar", "broken stone pillar"), + ("car_rusted", "rusted abandoned car"), + ("sign_warning", "warning sign post"), + ] + + for name, desc in env_objects: + assets.append({"cat": "environment", "file": f"{name}.png", "prompt": f"2D indie game object sprite, {desc}"}) + + # ======================================================================== + # 7. ITEMS - WEAPONS, TOOLS, EQUIPMENT (~150) + # ======================================================================== + + items = [ + # Tools + ("tool_axe_wood", "wooden axe, chopping tool"), + ("tool_axe_iron", "iron axe, upgraded"), + ("tool_pickaxe_wood", "wooden pickaxe, mining"), + ("tool_pickaxe_iron", "iron pickaxe, upgraded"), + ("tool_shovel", "shovel, digging"), + ("tool_hoe", "farming hoe, tilling"), + ("tool_hammer", "hammer, building"), + ("tool_saw", "hand saw, cutting"), + + # Weapons + ("weapon_sword_iron", "iron sword, combat"), + ("weapon_sword_silver", "silver sword, glowing"), + ("weapon_dagger", "dagger, quick"), + ("weapon_spear", "wooden spear, hunting"), + ("weapon_bow_wood", "wooden bow with arrows"), + ("weapon_bow_silver", "silver bow, magical"), + ("weapon_crossbow", "crossbow, powerful"), + + # Magic wands (6 types) + ("wand_fire", "fire magic wand, red crystal tip, flames"), + ("wand_ice", "ice magic wand, blue crystal, frost"), + ("wand_lightning", "lightning wand, yellow crystal, sparks"), + ("wand_earth", "earth magic wand, green crystal, nature"), + ("wand_shadow", "shadow magic wand, purple crystal, darkness"), + ("wand_healing", "healing wand, white crystal, glow"), + + # Special items + ("ana_bracelet", "Ana's magical bracelet, glowing, family heirloom"), + ("gronk_vape", "Gronk's golden vape device, colorful, smoking"), + + # Equipment + ("backpack_small", "small leather backpack"), + ("backpack_large", "large hiking backpack"), + ("helmet_metal", "metal protective helmet"), + ("boots_leather", "leather boots"), + ("gloves_work", "work gloves"), + ("gas_mask", "gas mask, protection"), + + # Resources + ("resource_wood", "wood logs pile"), + ("resource_stone", "stone rocks pile"), + ("resource_iron", "iron ore chunks"), + ("resource_gold", "gold nuggets"), + ("resource_crystal", "blue crystal gem"), + + # Consumables + ("food_bread", "bread loaf"), + ("food_apple", "red apple"), + ("food_meat", "cooked meat"), + ("potion_health", "health potion red"), + ("potion_mana", "mana potion blue"), + ("water_bottle", "water bottle"), + ] + + for name, desc in items: + assets.append({"cat": "items", "file": f"{name}.png", "prompt": f"2D indie game item icon, {desc}, inventory sprite"}) + + # ======================================================================== + # 8. UI ELEMENTS (~30) + # ======================================================================== + + ui = [ + ("ui_health_bar", "health bar, red hearts row"), + ("ui_energy_bar", "energy bar, green lightning"), + ("ui_inventory_slot", "inventory slot, wooden frame"), + ("ui_button_menu", "menu button, wooden, round"), + ("ui_cursor_hand", "hand cursor pointer"), + ("ui_icon_gold", "gold coin icon"), + ("ui_icon_attack", "sword attack icon"), + ("ui_icon_defense", "shield defense icon"), + ] + + for name, desc in ui: + assets.append({"cat": "ui", "file": f"{name}.png", "prompt": f"2D game UI element, {desc}, clean"}) + + return assets + + +# ============================================================================ +# GOOGLE AI IMAGE GENERATION +# ============================================================================ + +def setup_google_ai(): + """Setup Google AI API""" + api_key = os.environ.get("GOOGLE_AI_API_KEY") or os.environ.get("GEMINI_API_KEY") + if not api_key: + # Try to read from file + key_file = Path.home() / ".config" / "google_ai_key.txt" + if key_file.exists(): + api_key = key_file.read_text().strip() + + if api_key: + genai.configure(api_key=api_key) + return True + return False + + +def generate_image_google(prompt: str, output_path: Path) -> bool: + """Generate image using Google AI""" + try: + full_prompt = STYLE_PREFIX + prompt + STYLE_SUFFIX + + # Use Imagen model + model = genai.ImageGenerationModel("imagen-3.0-generate-002") + result = model.generate_images( + prompt=full_prompt, + number_of_images=1, + aspect_ratio="1:1", + safety_filter_level="block_only_high", + person_generation="allow_adult", + ) + + if result.images: + output_path.parent.mkdir(parents=True, exist_ok=True) + result.images[0].save(str(output_path)) + return True + return False + except Exception as e: + print(f"Error: {e}") + return False + + +def main(): + print("=" * 70) + print("šŸŽ® DOLINA SMRTI V7.0 - FINALNI GENERATOR") + print(" 2D Indie Cartoon Style | Green Chroma-Key BG") + print(" Based on approved Gronk/Kai test images") + print("=" * 70) + + if not setup_google_ai(): + print("āŒ Google AI API key not found") + print(" Set GOOGLE_AI_API_KEY environment variable") + return + + print("āœ… Google AI configured") + + print("\nšŸ“‹ Building Master Registry...") + ASSETS = generate_registry() + print(f"šŸ“Š Total: {len(ASSETS)} assets") + + # Count by category + cats = {} + for a in ASSETS: + cats[a["cat"]] = cats.get(a["cat"], 0) + 1 + print("\nPo kategorijah:") + for cat, count in sorted(cats.items(), key=lambda x: -x[1]): + print(f" {cat}: {count}") + + existing = sum(1 for a in ASSETS if (OUTPUT_DIR / a["cat"] / a["file"]).exists()) + print(f"\nāœ… Exist: {existing} | šŸŽÆ Generate: {len(ASSETS) - existing}") + + print("\nšŸŽ® STARTING GENERATION...\n") + + success, skip, fail = 0, 0, 0 + + for i, asset in enumerate(ASSETS, 1): + path = OUTPUT_DIR / asset["cat"] / asset["file"] + + if path.exists(): + skip += 1 + continue + + print(f"[{i}/{len(ASSETS)}] šŸŽØ {asset['file'][:40]}...") + + if generate_image_google(asset["prompt"], path): + print(f" āœ… SAVED") + success += 1 + else: + print(f" āŒ FAILED") + fail += 1 + + if i % 25 == 0: + print(f"\nšŸ“Š [{i}/{len(ASSETS)}] āœ…{success} ā­ļø{skip} āŒ{fail}\n") + + time.sleep(1) # Rate limiting + + print("\n" + "=" * 70) + print("šŸŽ® GENERATION COMPLETE!") + print(f"āœ… Success: {success} | ā­ļø Skip: {skip} | āŒ Fail: {fail}") + + +if __name__ == "__main__": + main()