🔧 Fixed generation scripts - proper image saving, gemini-1.5-flash model, full logging
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user