DR HACK

Davide Rosa Hack

GameOfLife3D

🧬 Game of Life 3D

Un'implementazione del Gioco della Vita di Conway in tre dimensioni, sviluppata in C# (.NET 8) con interfaccia grafica Avalonia UI 11.

La simulazione si svolge su una griglia cubica toroidale (i bordi si collegano tra loro). Il rendering 3D avviene tramite proiezione prospettica e SkiaSharp, senza dipendenze da OpenGL o GPU dedicata.


Screenshot

3D Game of Life


FunzionalitΓ 

  • πŸ”² Griglia 3D toroidale con vicinato di Moore a 26 celle
  • Simulazione in tempo reale con velocitΓ  configurabile (1–60 step/s)
  • πŸ–±οΈ Camera orbitale β€” trascina per ruotare, rotella per zoom
  • πŸ” Zoom con bottoni e tastiera β€” pulsanti βˆ’ + βŒ‚ nella toolbar, shortcut + - 0
  • πŸŽ›οΈ Regole configurabili β€” modifica le condizioni di sopravvivenza e nascita a caldo
  • πŸ“ Dimensione griglia regolabile β€” da 10Β³ a 50Β³ celle
  • 🎨 Renderer Skia β€” funziona su macOS, Windows e Linux senza OpenGL
  • πŸ–ΌοΈ Icona personalizzata β€” icona isometrica 3D nel dock/taskbar e nella titlebar

Requisiti


Build e avvio

# Compila la soluzione
dotnet build

# Avvia l'applicazione
dotnet run --project src/GameOfLife3D.App

Struttura del progetto

GameOfLife3D/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ GameOfLife3D.Core/          # Logica di simulazione (senza dipendenze UI)
β”‚   β”‚   β”œβ”€β”€ Grid3D.cs               # Griglia 3D con doppio buffer thread-safe
β”‚   β”‚   β”œβ”€β”€ SimulationEngine.cs     # Step, Randomize, Clear
β”‚   β”‚   └── Rules/
β”‚   β”‚       β”œβ”€β”€ IRule3D.cs          # Interfaccia regola
β”‚   β”‚       └── StandardRule3D.cs  # Regola "445" (sopravvive 5-7, nasce su 6)
β”‚   └── GameOfLife3D.App/           # Applicazione Avalonia
β”‚       β”œβ”€β”€ Assets/
β”‚       β”‚   └── icon.png            # Icona isometrica 3D (256Γ—256 RGBA)
β”‚       β”œβ”€β”€ Controls/
β”‚       β”‚   └── GameOfLifeGlControl.cs   # Renderer 3D (Skia + proiezione prospettica)
β”‚       β”œβ”€β”€ ViewModels/
β”‚       β”‚   └── MainViewModel.cs         # Stato e comandi (CommunityToolkit.Mvvm)
β”‚       β”œβ”€β”€ Views/
β”‚       β”‚   └── MainWindow.axaml         # Layout UI (toolbar, slider, viewport)
β”‚       └── MacDockIcon.cs               # Icona dock macOS via ObjC runtime
└── .github/
    └── copilot-instructions.md

Regole di default β€” "445"

La regola predefinita Γ¨ la cosiddetta "445" (o "Clouds"):

Puoi modificare le regole direttamente dall'interfaccia nei campi Survive e Birth, inserendo i valori separati da virgola (es. 4,5 oppure 6,7,8).

Alcune regole interessanti da provare:


Forme predefinite

La dropdown Shape nel pannello impostazioni permette di inserire pattern in una posizione casuale. Le forme con prefisso πŸ”’ (still life) e 🌱 (seed) sono matematicamente verificate per la regola "445"; πŸ” (Blinker) Γ¨ verificato come oscillatore periodo-2.

Nota: Le forme con prefisso πŸ”’ e 🌱 sono verificate per la regola "445". La forma πŸ” Blinker Γ¨ un oscillatore periodo-2 giΓ  sotto "445". La forma πŸš€ Glider Γ¨ uno spaceship di Carter Bays: si sposta solo sotto la regola Survive=4,7 / Birth=5; "Piazzala" applica automaticamente tale regola prima di stamparla, cosΓ¬ la vedi camminare. Sotto "445" non si muove.


Controlli


Architettura

Il progetto Γ¨ diviso in due layer netti:

GameOfLife3D.Core β€” libreria pura, senza dipendenze UI, testabile in isolamento. La griglia usa un doppio buffer (_front / _back): Step() scatta uno snapshot di _front (sotto lock) e lo usa per tutti i calcoli, scrivendo il risultato su _back e chiamando Swap() (thread-safe con lock) al termine. Grazie allo snapshot, eventuali scritture UI concorrenti (Randomize/Clear/PlaceShape) non possono corrompere uno step in corso.

GameOfLife3D.App — applicazione Avalonia con pattern MVVM. Il rendering 3D avviene in GameOfLifeRenderOp (implementa ICustomDrawOperation): le celle vive e i tubi che collegano i vicini ortogonali vengono proiettati nello spazio schermo tramite matrici System.Numerics e inseriti in un'unica lista ordinata per profondità (algoritmo del pittore, dal più lontano al più vicino), così le celle e i tubi si sovrappongono correttamente. Equals/GetHashCode sono implementati per valore, permettendo ad Avalonia di riusare i frame invariati.

La camera è in coordinate sferiche (_radius, _theta, _phi). Il raggio viene aggiornato solo quando cambia la dimensione della griglia, così le operazioni di zoom (rotella, pulsanti, tastiera) persistono correttamente tra un frame e l'altro.

Su macOS, l'icona del dock viene impostata programmaticamente in MacDockIcon.cs tramite l'ObjC runtime (NSApplication.setApplicationIconImage:), necessario quando l'app gira fuori da un bundle .app.


Licenza

MIT

Apri il progetto su GitHub

Per il codice sorgente e gli altri progetti visita il profilo GitHub di rsodvd79 .