From fddc9021bbdec2495d8cb1040d3628e0ba11ce26 Mon Sep 17 00:00:00 2001 From: David Kotnik Date: Wed, 31 Dec 2025 10:17:19 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Fixed=20generation=20scripts=20-?= =?UTF-8?q?=20proper=20image=20saving,=20gemini-1.5-flash=20model,=20full?= =?UTF-8?q?=20logging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/generate_anomalous_fauna.py | 152 ++++++++++++++++------- scripts/generate_dino_valley_complete.py | 2 +- 2 files changed, 108 insertions(+), 46 deletions(-) diff --git a/scripts/generate_anomalous_fauna.py b/scripts/generate_anomalous_fauna.py index 2d7bb1178..786819bd8 100644 --- a/scripts/generate_anomalous_fauna.py +++ b/scripts/generate_anomalous_fauna.py @@ -2,7 +2,6 @@ """ šŸ¦– ANOMALOUS ZONE FAUNA GENERATOR Generates creatures for all 8 remaining anomalous zones - Based on DLC_TO_BASE_GAME_COMPLETE.md specifications """ @@ -10,6 +9,7 @@ import os import sys import time from pathlib import Path +from PIL import Image try: import google.generativeai as genai @@ -30,16 +30,13 @@ if not api_key: sys.exit(1) genai.configure(api_key=api_key) -model = genai.GenerativeModel("gemini-2.0-flash-exp") # Style prompts -STYLE_A = """2D indie game creature sprite, cartoon vector art style, bold black outlines, -flat colors, cute and playful aesthetic, NO shadows, NO gradients, simple clean design, -centered on white background, full body visible, game asset""" +STYLE_A = """ISOLATED ON PURE WHITE BACKGROUND. 2D indie game creature sprite, cartoon vector art style, bold black outlines, +flat colors, cute and playful aesthetic, NO shadows, NO gradients, simple clean design, centered, full body visible, game asset""" -STYLE_B = """2D indie game creature sprite, dark hand-drawn gritty noir style, -dramatic shadows, high contrast, sketchy atmospheric lines, mature 90s cartoon aesthetic, -centered on white background, full body visible, game asset""" +STYLE_B = """ISOLATED ON PURE WHITE BACKGROUND. 2D indie game creature sprite, dark hand-drawn gritty noir style, +dramatic shadows, high contrast, sketchy atmospheric lines, mature 90s cartoon aesthetic, centered, full body visible, game asset""" # All anomalous zones with their creatures ANOMALOUS_ZONES = { @@ -116,81 +113,146 @@ ANOMALOUS_ZONES = { ], } -def generate_creature(zone_name: str, creature_name: str, description: str, style: str) -> bool: +def create_preview(image_path: Path, size=256): + """Create preview version""" + try: + img = Image.open(image_path) + preview = img.resize((size, size), Image.Resampling.LANCZOS) + preview_path = image_path.parent / f"{image_path.stem}_preview_{size}x{size}.png" + preview.save(preview_path, 'PNG', optimize=True) + return preview_path + except Exception as e: + print(f" āš ļø Preview failed: {e}") + return None + +def generate_creature(zone_name: str, creature_name: str, description: str, style: str, log_file) -> bool: """Generate a single creature sprite""" + start = time.time() style_suffix = "stylea" if style == "A" else "styleb" output_path = ASSETS / zone_name / f"{creature_name}_{style_suffix}.png" # Skip if exists if output_path.exists(): + print(f" ā­ļø Already exists") return True # Create prompt style_prompt = STYLE_A if style == "A" else STYLE_B - full_prompt = f"{style_prompt}, {description}" + full_prompt = f"{style_prompt}\n\n{description}\n\nGame sprite asset." try: + print(f" šŸŽØ Generating {style_suffix}: {creature_name}") + log_file.write(f"{time.strftime('%H:%M:%S')} - Generating {output_path.name}\n") + log_file.flush() + # Generate image - result = model.generate_content([full_prompt]) + model = genai.GenerativeModel("gemini-1.5-flash") + response = model.generate_content([full_prompt]) - # Save (this is placeholder - actual implementation needs image saving) - output_path.parent.mkdir(parents=True, exist_ok=True) - - # Note: Actual saving logic would go here - # For now, this is a template - - return True + if hasattr(response, '_result') and response._result.candidates: + image_data = response._result.candidates[0].content.parts[0].inline_data.data + + # Save original + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, 'wb') as f: + f.write(image_data) + + # Create preview + preview = create_preview(output_path) + + elapsed = time.time() - start + print(f" āœ… Saved ({elapsed:.1f}s)") + log_file.write(f"{time.strftime('%H:%M:%S')} - SUCCESS {output_path.name} ({elapsed:.1f}s)\n") + log_file.flush() + + return True + else: + print(f" āŒ No image data") + log_file.write(f"{time.strftime('%H:%M:%S')} - FAILED {output_path.name} - No data\n") + log_file.flush() + return False except Exception as e: print(f" āŒ Error: {e}") + log_file.write(f"{time.strftime('%H:%M:%S')} - ERROR {output_path.name} - {e}\n") + log_file.flush() return False def main(): + # Create log + log_dir = REPO / "logs" + log_dir.mkdir(exist_ok=True) + log_file = open(log_dir / f"anomalous_fauna_{time.strftime('%Y%m%d_%H%M%S')}.log", 'w') + print("="*70) print("šŸ¦– ANOMALOUS ZONE FAUNA GENERATOR") print("="*70) - print(f"\nGenerating creatures for {len(ANOMALOUS_ZONES)} zones...") total_creatures = sum(len(creatures) for creatures in ANOMALOUS_ZONES.values()) total_images = total_creatures * 2 # styleA + styleB - print(f"Total: {total_creatures} creatures Ɨ 2 styles = {total_images} images") + print(f"\n{len(ANOMALOUS_ZONES)} zones | {total_creatures} creatures Ɨ 2 styles = {total_images} images") print() + log_file.write(f"ANOMALOUS FAUNA GENERATION - {time.strftime('%Y-%m-%d %H:%M:%S')}\n") + log_file.write(f"Total: {total_images} images\n") + log_file.write("="*70 + "\n\n") + log_file.flush() + success = 0 failed = 0 current = 0 - for zone_name, creatures in ANOMALOUS_ZONES.items(): - print(f"\nšŸŒ {zone_name.upper().replace('_', ' ')}") - print(f" {len(creatures)} creatures") - - for creature_name, description in creatures: - current += 1 - print(f"\n[{current}/{total_creatures}] {creature_name}") + try: + for zone_name, creatures in ANOMALOUS_ZONES.items(): + print(f"\n{'='*70}") + print(f"šŸŒ {zone_name.upper().replace('_', ' ')}") + print(f"{'='*70}") + print(f" {len(creatures)} creatures") - # Generate both styles - for style in ["A", "B"]: - style_name = "Cartoon" if style == "A" else "Noir" - print(f" šŸŽØ Style {style} ({style_name})...", end=" ") + log_file.write(f"\n{'='*70}\n") + log_file.write(f"ZONE: {zone_name}\n") + log_file.write(f"{'='*70}\n\n") + log_file.flush() + + for creature_name, description in creatures: + current += 1 + print(f"\n[{current}/{total_creatures}] {creature_name}") - if generate_creature(zone_name, creature_name, description, style): - print("āœ…") - success += 1 - else: - print("āŒ") - failed += 1 + # Generate both styles + for style in ["A", "B"]: + if generate_creature(zone_name, creature_name, description, style, log_file): + success += 1 + else: + failed += 1 + + # Rate limiting + time.sleep(2) - # Rate limiting - time.sleep(2) + # Progress + progress = ((current / total_creatures) * 100) + print(f"\nšŸ“Š Progress: {progress:.1f}% | Success: {success}/{total_images} | Failed: {failed}") + + # Final summary + print("\n" + "="*70) + print("šŸŽ‰ GENERATION COMPLETE!") + print("="*70) + print(f"āœ… Success: {success}/{total_images}") + print(f"āŒ Failed: {failed}/{total_images}") + print(f"šŸ“Š Success rate: {(success/total_images)*100:.1f}%") + + log_file.write(f"\n{'='*70}\n") + log_file.write(f"GENERATION COMPLETE\n") + log_file.write(f"Success: {success}\n") + log_file.write(f"Failed: {failed}\n") + + except KeyboardInterrupt: + print(f"\n\nāš ļø INTERRUPTED at creature {current}") + log_file.write(f"\n\nINTERRUPTED at creature {current}\n") - print("\n" + "="*70) - print("šŸŽ‰ GENERATION COMPLETE!") - print("="*70) - print(f"āœ… Success: {success}/{total_images}") - print(f"āŒ Failed: {failed}/{total_images}") - print(f"šŸ“Š Success rate: {(success/total_images)*100:.1f}%") + finally: + log_file.close() if __name__ == "__main__": main() diff --git a/scripts/generate_dino_valley_complete.py b/scripts/generate_dino_valley_complete.py index a5ea52186..145a95fdf 100644 --- a/scripts/generate_dino_valley_complete.py +++ b/scripts/generate_dino_valley_complete.py @@ -43,7 +43,7 @@ def generate_image(prompt: str, output_path: Path, log_file): log_file.write(f"{time.strftime('%H:%M:%S')} - Generating {output_path.name}\n") log_file.flush() - model = genai.GenerativeModel('gemini-2.0-flash-exp') + model = genai.GenerativeModel('gemini-1.5-flash') response = model.generate_content([prompt]) if hasattr(response, '_result') and response._result.candidates: