Repository navigation
Releases: AlbyMiscy/NeoSnake
Release list
v8.0 - Final release (fix)
Fix: In fase di debug ho impostato come valore di soglia per il passaggio dal livello 1 al livello 2 a 1 frutto mangiato. Con questo fix ho modificato questo valore soglia: ora per passare dal livello 1 al 2 bisogna mangiare almeno 4 frutti, per finire il gioco 8 frutti.
![]() Pagina di start del gioco |
![]() Game |
📌 Descrizione
In questo step NeoSnake compie un ulteriore salto di qualità, evolvendo da semplice gioco arcade a esperienza strutturata a livelli, con una gestione completa di UI, progressione, camera dinamica e qualità del gameplay.
Il focus principale di questa pull request è il consolidamento dell’engine di gioco e l’introduzione di schermate dedicate, mappe multilayer da CSV, spawn intelligente della frutta e sistemi di supporto al giocatore come la freccia direzionale.
L’architettura viene ulteriormente modulata: la logica di gioco, la gestione dei livelli e la UI sono ora ben separate, rendendo il progetto più leggibile, estendibile e manutenibile.
🎮 Gameplay & UX
- Introduzione di un sistema di livelli progressivi basato sul numero di frutti raccolti
- Implementazione della schermata di passaggio al livello successivo
- Miglioramento del game over con restart del livello corrente
- Sistema di pausa con overlay e navigazione da tastiera
- Menu principale con sfondo tile-based e selezione interattiva
- HUD score separato dalla view di gioco
🗺️ Mappe & Rendering
- Nuovo sistema di mappe multilayer da CSV (sfondo, accessori, muri, pattuglie nemici)
- Rendering ottimizzato tramite VertexArray e tileset condiviso
- Correzione del texture bleeding tramite inset e smoothing disabilitato
- Supporto a background animati/strutturati anche per menu e schermate UI
🍎 Logica di spawn avanzata
- Spawn della frutta solo in celle valide
- Verifica che la frutta sia raggiungibile dal serpente tramite A*
- Evitata la generazione in muri, sul corpo del serpente o in aree isolate
- Fallback di sicurezza per prevenire loop infiniti
🧭 Supporto al giocatore
- Introduzione della freccia direzionale animata che indica la posizione della frutta
- La freccia compare solo quando la frutta è fuori dall’area visibile
- Rotazione e posizionamento dinamici rispetto alla camera
🎥 Camera & Movimento
- Camera dinamica che segue il serpente con interpolazione fluida
- Clamping automatico ai bordi della mappa
- Separazione tra view di gioco e view UI
🧠 Engine & Architettura
- Estensione dell’engine per:
- gestione livelli
- reset e restart controllati
- collisioni avanzate (muri, nemici, corpo)
- Migliore organizzazione della logica di update/draw/input
- Riutilizzo del pathfinding anche per controlli di gameplay (non solo nemici)
📂 File principali coinvolti
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── input.cpp
│ ├── update.cpp
│ ├── snakeFunction.cpp
│ ├── fruitFunction.cpp
│ └── arrowFunction.cpp
│
├── 📂src/
│ ├── engine.cpp
│ ├── levelMap.cpp
│ ├── enemy.cpp
│ ├── pathfinding.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── fruit.cpp
│
├── 📂ui/
│ ├── mainMenuScreen.cpp
│ ├── pauseScreen.cpp
│ ├── gameOverScreen.cpp
│ └── nextLevelScreen.cpp
│
├── 📂header/
│ ├── engine.hpp
│ ├── levelMap.hpp
│ ├── enemy.hpp
│ ├── pathfinding.hpp
│ ├── snake.hpp
│ ├── fruit.hpp
│ ├── iscreen.hpp
│ └── resource_path.h.in
│
└── 📂resources/
├── 📂maps/
│ └── levelXX/
│ ├── mapCSV_wall.csv
│ ├── mapCSV_grass.csv
│ ├── mapCSV_grass_accessories.csv
│ └── mapCSV_enemies_patrols.csv
│
├── 📂backgroundMenu/
├── 📂texture/
│ ├── 📂enemies/
│ ├── 📂skin/
│ ├── arrow.png
│ └── fruit.png
│
└── 📂fonts/
└── PressStart2P-Regular.ttf🔗 Link utili
v8.0 - Final release
![]() Pagina di start del gioco |
![]() Game |
📌 Descrizione
In questo step NeoSnake compie un ulteriore salto di qualità, evolvendo da semplice gioco arcade a esperienza strutturata a livelli, con una gestione completa di UI, progressione, camera dinamica e qualità del gameplay.
Il focus principale di questa pull request è il consolidamento dell’engine di gioco e l’introduzione di schermate dedicate, mappe multilayer da CSV, spawn intelligente della frutta e sistemi di supporto al giocatore come la freccia direzionale.
L’architettura viene ulteriormente modulata: la logica di gioco, la gestione dei livelli e la UI sono ora ben separate, rendendo il progetto più leggibile, estendibile e manutenibile.
🎮 Gameplay & UX
- Introduzione di un sistema di livelli progressivi basato sul numero di frutti raccolti
- Implementazione della schermata di passaggio al livello successivo
- Miglioramento del game over con restart del livello corrente
- Sistema di pausa con overlay e navigazione da tastiera
- Menu principale con sfondo tile-based e selezione interattiva
- HUD score separato dalla view di gioco
🗺️ Mappe & Rendering
- Nuovo sistema di mappe multilayer da CSV (sfondo, accessori, muri, pattuglie nemici)
- Rendering ottimizzato tramite VertexArray e tileset condiviso
- Correzione del texture bleeding tramite inset e smoothing disabilitato
- Supporto a background animati/strutturati anche per menu e schermate UI
🍎 Logica di spawn avanzata
- Spawn della frutta solo in celle valide
- Verifica che la frutta sia raggiungibile dal serpente tramite A*
- Evitata la generazione in muri, sul corpo del serpente o in aree isolate
- Fallback di sicurezza per prevenire loop infiniti
🧭 Supporto al giocatore
- Introduzione della freccia direzionale animata che indica la posizione della frutta
- La freccia compare solo quando la frutta è fuori dall’area visibile
- Rotazione e posizionamento dinamici rispetto alla camera
🎥 Camera & Movimento
- Camera dinamica che segue il serpente con interpolazione fluida
- Clamping automatico ai bordi della mappa
- Separazione tra view di gioco e view UI
🧠 Engine & Architettura
- Estensione dell’engine per:
- gestione livelli
- reset e restart controllati
- collisioni avanzate (muri, nemici, corpo)
- Migliore organizzazione della logica di update/draw/input
- Riutilizzo del pathfinding anche per controlli di gameplay (non solo nemici)
📂 File principali coinvolti
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── input.cpp
│ ├── update.cpp
│ ├── snakeFunction.cpp
│ ├── fruitFunction.cpp
│ └── arrowFunction.cpp
│
├── 📂src/
│ ├── engine.cpp
│ ├── levelMap.cpp
│ ├── enemy.cpp
│ ├── pathfinding.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── fruit.cpp
│
├── 📂ui/
│ ├── mainMenuScreen.cpp
│ ├── pauseScreen.cpp
│ ├── gameOverScreen.cpp
│ └── nextLevelScreen.cpp
│
├── 📂header/
│ ├── engine.hpp
│ ├── levelMap.hpp
│ ├── enemy.hpp
│ ├── pathfinding.hpp
│ ├── snake.hpp
│ ├── fruit.hpp
│ ├── iscreen.hpp
│ └── resource_path.h.in
│
└── 📂resources/
├── 📂maps/
│ └── levelXX/
│ ├── mapCSV_wall.csv
│ ├── mapCSV_grass.csv
│ ├── mapCSV_grass_accessories.csv
│ └── mapCSV_enemies_patrols.csv
│
├── 📂backgroundMenu/
├── 📂texture/
│ ├── 📂enemies/
│ ├── 📂skin/
│ ├── arrow.png
│ └── fruit.png
│
└── 📂fonts/
└── PressStart2P-Regular.ttf🔗 Link utili
v7.0.1 - Enemies (fix)
Fix: Nell'algoritmo A* se ci sono più nodi con stesso
f, viene preso il nodo conhpiù basso, in quanto identifica il numero di blocchi che servono per raggiungere la destinazione.
📌 Descrizione
In questo step ho introdotto una delle funzionalità più importanti di NeoSnake:
un sistema completo di nemici intelligenti, in grado di muoversi all’interno della mappa seguendo percorsi calcolati tramite algoritmo A*.
Questa feature rende il gameplay più dinamico e strategico, trasformando NeoSnake in un gioco più ricco e interattivo.
L’intera logica è integrata nel caricamento del livello: quando viene avviata una nuova partita, l’engine analizza la PNG del livello, identifica i punti di pattuglia (pixel gialli e verdi), costruisce la mappa e calcola una sola volta il path per ogni nemico, garantendo performance ottimali durante il gameplay.
I nemici si muovono in modo fluido, seguendo tile predefinite (waypoint) generate dall’A*, e invertendo la direzione quando raggiungono il punto finale. In caso di collisione con la testa del serpente, il gioco termina immediatamente.
Il lavoro comprende:
- implementazione completa della classe Enemy (animazione, movimento, collisioni)
- introduzione del modulo di pathfinding (GridProvider + A*)
- estensione dell’engine per gestire nemici, blocchi mappa e caricamento dei path
- parsing della PNG del livello con supporto a pixel speciali per definire i punti A/B
- integrazione nel ciclo di gioco (update, draw e check collisioni)
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── fruitFunction.cpp
│ ├── input.cpp
│ ├── snakeFunction.cpp
│ ├── arrowFunction.cpp
│ └── update.cpp
│
├── 📂header/
+ │ ├── enemy.hpp
+ │ ├── pathfinding.hpp
│ ├── engine.hpp
│ ├── fruit.hpp
│ ├── snake.hpp
│ ├── resource_path.h.in
│ └── map.hpp
│
├── 📂src/
+ │ ├── enemy.cpp
+ │ ├── pathfinding.cpp
│ ├── engine.cpp
│ ├── fruit.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── map.cpp
│
└── 📂resources/
├── 📂levels/
│ └── Level01.png
│
└── 📂texture/
+ ├── 📂enemies/
+ │ ├── enemy1.png
+ │ └── enemy2.png
├── 📂skin/
│ └── snake_skin_1-1.png
├── arrow.png
├── snake.png
└── wall.png🔗 Link utili
v7.0 - Enemis
📌 Descrizione
In questo step ho introdotto una delle funzionalità più importanti di NeoSnake:
un sistema completo di nemici intelligenti, in grado di muoversi all’interno della mappa seguendo percorsi calcolati tramite algoritmo A*.
Questa feature rende il gameplay più dinamico e strategico, trasformando NeoSnake in un gioco più ricco e interattivo.
L’intera logica è integrata nel caricamento del livello: quando viene avviata una nuova partita, l’engine analizza la PNG del livello, identifica i punti di pattuglia (pixel gialli e verdi), costruisce la mappa e calcola una sola volta il path per ogni nemico, garantendo performance ottimali durante il gameplay.
I nemici si muovono in modo fluido, seguendo tile predefinite (waypoint) generate dall’A*, e invertendo la direzione quando raggiungono il punto finale. In caso di collisione con la testa del serpente, il gioco termina immediatamente.
Il lavoro comprende:
- implementazione completa della classe Enemy (animazione, movimento, collisioni)
- introduzione del modulo di pathfinding (GridProvider + A*)
- estensione dell’engine per gestire nemici, blocchi mappa e caricamento dei path
- parsing della PNG del livello con supporto a pixel speciali per definire i punti A/B
- integrazione nel ciclo di gioco (update, draw e check collisioni)
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── fruitFunction.cpp
│ ├── input.cpp
│ ├── snakeFunction.cpp
│ ├── arrowFunction.cpp
│ └── update.cpp
│
├── 📂header/
+ │ ├── enemy.hpp
+ │ ├── pathfinding.hpp
│ ├── engine.hpp
│ ├── fruit.hpp
│ ├── snake.hpp
│ ├── resource_path.h.in
│ └── map.hpp
│
├── 📂src/
+ │ ├── enemy.cpp
+ │ ├── pathfinding.cpp
│ ├── engine.cpp
│ ├── fruit.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── map.cpp
│
└── 📂resources/
├── 📂levels/
│ └── Level01.png
│
└── 📂texture/
+ ├── 📂enemies/
+ │ ├── enemy1.png
+ │ └── enemy2.png
├── 📂skin/
│ └── snake_skin_1-1.png
├── arrow.png
├── snake.png
└── wall.png🔗 Link utili
Step06 - Aggiunta delle Schermate UI e Sistema di Score
![]() Pagina di start del gioco |
![]() Pausa |
![]() Visualizzazione punteggio |
![]() Game over |
📌 Descrizione
In questo step ho deciso di rendere NeoSnake più completo e graficamente accattivante, introducendo una UI dedicata per:
- Menu principale
- Schermata di pausa
- Schermata di game over
Ho inoltre aggiunto un sistema di punteggio, utile per future estensioni come la gestione di più livelli.
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── fruitFunction.cpp
│ ├── input.cpp
│ ├── snakeFunction.cpp
│ ├── arrowFunction.cpp
│ └── update.cpp
│
├── 📂header/
+ │ ├── 📂stateGameHandler/
+ │ │ ├── iscreen.hpp
+ │ │ ├── mainMenuScreen.hpp
+ │ │ ├── pauseScreen.hpp
+ │ │ └── gameOverScreen.hpp
│ ├── engine.hpp
│ ├── fruit.hpp
│ ├── snake.hpp
│ ├── resource_path.h.in
│ └── map.hpp
│
├── 📂src/
+ │ ├── 📂stateGameHandler/
+ │ │ ├── mainMenuScreen.cpp
+ │ │ ├── pauseScreen.cpp
+ │ │ └── gameOverScreen.cpp
│ ├── engine.cpp
│ ├── fruit.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── map.cpp
│
└── 📂resources/
├── 📂levels/
│ └── Level01.png
│
└── 📂texture/
├── 📂skin/
│ └── snake_skin_1-1.png
├── arrow.png
├── snake.png
└── wall.png
🔗 Link utili
v5.0 - Freccia direzionale per trovare la frutta nel gioco
📌 Descrizione
In questo aggiornamento di NeoSnake ho introdotto una nuova funzionalità pensata per migliorare l'esperienza di gioco nelle mappe di grandi dimensioni: una freccia direzionale animata che indica la posizione del frutto quando questo si trova al di fuori della view corrente del giocatore.
L'obiettivo è garantire che il giocatore non perda mai l'orientamento e possa raggiungere facilmente il frutto, anche negli scenari più vasti.
La freccia:
- compare solo quando il frutto è fuori dalla view
- punta sempre verso il frutto, calcolando la direzione corretta
- si posiziona automaticamente sul bordo interno della camera, evitando sovrapposizioni
- include una posizione ciclica per renderla più visibile
- ruota dinamicamente in base alla posizione del frutto
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── fruitFunction.cpp
│ ├── input.cpp
│ ├── snakeFunction.cpp
+│ ├── arrowFunction.cpp
│ └── update.cpp
│
├── 📂header/
│ ├── engine.hpp
│ ├── fruit.hpp
│ ├── snake.hpp
│ ├── resource_path.h.in
│ └── map.hpp
│
├── 📂src/
│ ├── engine.cpp
│ ├── fruit.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── map.cpp
│
└── 📂resources/
├── 📂levels/
│ └── Level01.png
│
└── 📂texture/
├─📂skin/
│ └── snake_skin_1-1.png
+ ├── arrow.png
├── snake.png
└── wall.png🔗 Link utili
v4.0 - Gestione di una texture per il serpente e per la frutta
In questo aggiornamento di NeoSnake è stato introdotto un sistema di skin dinamiche sia per il serpente che per il frutto.
Lo scopo è migliorare l’impatto visivo del gioco rendendo gli elementi più riconoscibili, vari e piacevoli per l’utente.
Di seguito sono elencate tutte le modifiche apportate ai file del progetto, con una breve spiegazione del loro ruolo.
🎨 skin del serpente
-
Aggiunta una texture dedicata al serpente: Essa contiene due frame in un'unica riga (
HEAD,BODY). -
snake.hpp: Aggiunti i metodi:setTexture(sf::Texture* texture)setTextureRect(const sf::IntRect& rect)setRotation(float angle)- Modificato
getShape(): ora ritorna un riferimento, evitando copie inutili.
-
snake.cpp: Implementazione delle nuovi funzioni. -
engine.hpp:- Aggiunto
sf::Texture snakeSkinallo scopo di conservarne in memoria l'atlas del serpente e fornirlo a tutte le sue sezioni.
- Aggiunto
-
engine.cpp:- Caricamento della skin in
startGame(). - Dopo la creazione del serpente (
newSnake()), ogni sezione ottiene:- la texture condivisa
- il frame corretto (testa o corpo)
- un'orientazione iniziale coerente
- Caricamento della skin in
-
snakeFunction.cpp- In
newSnake(): ogni sezione riceve immediatamente head/body rect e rotazione iniziale. - In
addSnakeSection(): le nuove sezioni ereditano automaticamente la skin e un frame BODY.
- In
-
update.cpp:- Durante l’update del movimento:
- La testa usa
headRecte ruota in base asnakeDirection. - Ogni sezione del corpo usa
bodyRecte ruota in base al segmento precedente.
- La testa usa
- Lo scopo è quello di orientare il serpente in modo corretto senza richiedere sprite differenti per ogni direzione.
- Durante l’update del movimento:
🍎 Skin del Frutto
Aggiunta una texture con tre frutti diversi resources/texture/fruit.png che contiene:
- banana
- mela
- ciliegia
È un atlas con tre frame affiancati orizzontalmente.
fruit.hpp
setTexture(const sf::Texture* tex, int frames)pickRandomFrame()- Lo scopo è quello di gestire un atlas multi-frame e selezionare un frutto casuale.
fruit.cpp: Implementata la logica del fruit atlas:
- calcolo automatico della larghezza di ogni frame,
- generatore casuale moderno
std::mt19937, - scelta casuale del frame,
- applicazione del
textureRectcorretto allo shape del frutto. - Lo scopo è quello di rendere il frutto diverso ad ogni spawn.
fruitFunction.cpp
- In
moveFruit()dopo aver trovato una posizione valida:- Applicata la texture del frutto,
- chiamato
fruit.pickRandomFrame()per selezionare una sprite casuale.
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── fruitFunction.cpp
│ ├── input.cpp
│ ├── snakeFunction.cpp
│ └── update.cpp
│
├── 📂header/
│ ├── engine.hpp
│ ├── fruit.hpp
│ ├── snake.hpp
│ ├── resource_path.h.in
│ └── map.hpp
│
├── 📂src/
│ ├── engine.cpp
│ ├── fruit.cpp
│ ├── main.cpp
│ ├── snake.cpp
│ └── map.cpp
│
└── 📂resources/
├── 📂levels/
│ └── Level01.png
│
└── 📂texture/
+ ├─📂skin/
+ │ └── snake_skin_1-1.png
+ ├── snake.cpp
└── wall.png🔗 Link utili
v3.0 - Creazione della prima mappa di gioco da un’immagine
📌 Descrizione
In questo aggiornamento di NeoSnake sono state introdotte importanti modifiche strutturali e funzionali al progetto, finalizzate a rendere l’esperienza di gioco più completa e coerente con un ambiente di gioco reale.
- Implementazione della mappa di gioco (
map.hpp,map.cpp): è stata aggiunta una nuova classeMapin grado di caricare una mappa da immagine e disegnarla utilizzando la texturewall.png. - Gestione dinamica della view: La view ora segue il serpente in modo fluido e viene limitata ai margini della mappa, impedendo che il giocatore possa vedere aree al di fuori del campo di gioco.
- Gestione collisione tra serpente e muri: Durante l'update, il gioco verifica se la testa del serpente si sta spostando verso una cella muro o al di fuori della mappa. In caso positivo viene impostato lo stato di Game Over (
GAMEOVER), impedendo ulteriori movimenti. - Correzione del metodo
moveFruit(): Il posizionamento del frutto è stato migliorato: ora viene generato esclusivamente su celle libere, evitando sia le sezioni del serpente sia i muri della mappa. - Generato il file
resource_path.h.ine inclusa la directory generata in CMake: Aggiunto il templateresource_path.h.ine generatoresource_path.hviaconfigure_fileper definire la macroRESOURCE_DIR(path assoluto della cartellaresources). Introdotta la variabile${GENERATED_DIR}(${CMAKE_BINARY_DIR}/generated) e aggiunta atarget_include_directories(NeoSnake)per rendere visibile l'header generato al compilatore. A questo punto i percorsi delle risorse sono corretti in fase di sviluppo/debug indipendentemente dalla working directory dell'eseguibile.
NeoSnake
│
├── 📂handlers/
│ ├── draw.cpp
│ ├── fruitFunction.cpp
│ ├── input.cpp
│ ├── snakeFunction.cpp
│ └── update.cpp
│
├── 📂header/
│ ├── engine.hpp
│ ├── fruit.hpp
│ ├── snake.hpp
+│ ├── resource_path.h.in
+│ └── map.hpp
│
├── 📂src/
│ ├── engine.cpp
│ ├── fruit.cpp
│ ├── main.cpp
│ ├── snake.cpp
+│ └── map.cpp
│
└── 📂resources/
+ ├── 📂levels/
+ │ └── Level01.png
│
+ └── 📂texture/
+ └── wall.png🔗 Link utili
v2.0.1 - Aggiunta di una camera dinamica e gestione del ridimensionamento finestra (fix)
FIX: Aggiunta la cartella
resourcesper evitare errori in fase di configurazione/compilazione
📌 Descrizione
In questo aggiornamento ho introdotto una gestione dinamica della view di gioco, che permette al giocatore di muoversi in uno spazio di gioco più ampio, mantenendo sempre il serpente centrato sullo schermo.
Il campo di gioco non ha più margini visibili: la camera segue il serpente durante il movimento, consentendo una navigazione continua in tutte le direzioni.
- Implementazione di una
sf::Viewche segue dinamicamente la testa del serpente. - Calcolo automatico delle dimensioni della view in base all’aspect ratio della finestra (
ResizeView). - Gestione del ridimensionamento runtime: la view si adatta automaticamente se l’utente modifica la finestra.
- Possibilità di ridimensionare la scala della view (zoom) per visualizzare una porzione maggiore o minore della mappa.
NeoSnake
┣ 📂 handlers
┣ draw.cpp
┣ fruitFunction.cpp
┣ input.cpp
┣ snakeFunction.cpp
┗ update.cpp
┣ 📂 header
┣ engine.hpp
┣ fruit.hpp
┗ snake.hpp
┣ 📂 resources
┣ 📂 src
┣ engine.cpp
┣ fruit.cpp
┣ main.cpp
┗ snake.cpp🔗 Link utili
v2.0 - Aggiunta di una camera dinamica e gestione del ridimensionamento finestra
📌 Descrizione
In questo aggiornamento ho introdotto una gestione dinamica della view di gioco, che permette al giocatore di muoversi in uno spazio di gioco più ampio, mantenendo sempre il serpente centrato sullo schermo.
Il campo di gioco non ha più margini visibili: la camera segue il serpente durante il movimento, consentendo una navigazione continua in tutte le direzioni.
- Implementazione di una
sf::Viewche segue dinamicamente la testa del serpente. - Calcolo automatico delle dimensioni della view in base all’aspect ratio della finestra (
ResizeView). - Gestione del ridimensionamento runtime: la view si adatta automaticamente se l’utente modifica la finestra.
- Possibilità di ridimensionare la scala della view (zoom) per visualizzare una porzione maggiore o minore della mappa.
NeoSnake
┣ 📂 handlers
┣ draw.cpp
┣ fruitFunction.cpp
┣ input.cpp
┣ snakeFunction.cpp
┗ update.cpp
┣ 📂 header
┣ engine.hpp
┣ fruit.hpp
┗ snake.hpp
┣ 📂 resources
┣ 📂 src
┣ engine.cpp
┣ fruit.cpp
┣ main.cpp
┗ snake.cpp





