
GUIDE PER ASPIRANTI PROGRAMMATORI
Fase 3: creiamo gli invaders!
Creazione della Classe Invader Per rappresentare gli invaders alieni, creeremo una nuova classe chiamata Invader. Questa classe sarà simile a quella del Player, ma con alcune differenze. Gli invadersi si muoveranno automaticamente da sinistra a destra e, occasionalmente, spareranno dei proiettili verso la tua navicella. Aggiungi questo codice al tuo file index.js: class Invader…


Vuoi avviare una nuova carriera o fare un upgrade?
Trova il corso Digital & Tech più adatto a te nel nostro catalogo!
Creazione della Classe Invader
Per rappresentare gli invaders alieni, creeremo una nuova classe chiamata Invader. Questa classe sarà simile a quella del Player, ma con alcune differenze. Gli invadersi si muoveranno automaticamente da sinistra a destra e, occasionalmente, spareranno dei proiettili verso la tua navicella.
Aggiungi questo codice al tuo file index.js:
class Invader { constructor({ position }) { this.velocity = { x: 0, y: 0 }; const image = new Image(); image.src = './img/invader.png'; image.onload = () => { const scale = 1; this.image = image; this.width = image.width * scale; this.height = image.height * scale; this.position = { x: position.x, y: position.y }; }; } draw() { c.drawImage(this.image, this.position.x, this.position.y, this.width, this.height); } update({ velocity }) { if (this.image) { this.draw(); this.position.x += velocity.x; this.position.y += velocity.y; } } shoot(invaderProjectiles) { invaderProjectiles.push( new InvaderProjectile({ position: { x: this.position.x + this.width / 2, y: this.position.y + this.height }, velocity: { x: 0, y: 5 } }) ); } }
Cosa fa questo codice?
- Creare un Invader (Invader): ogni invader è un nuovo oggetto creato con questa classe. Ha una posizione iniziale e una velocità di movimento (che all’inizio è 0).
- Caricare l’immagine dell’invader: carichiamo un’immagine che rappresenta l’invader, la ridimensioniamo e la posizioniamo sullo schermo.
- Disegnare e Aggiornare l’Invader (draw e update): draw si occupa di disegnare l’invader sullo schermo, mentre update lo sposta in base alla sua velocità.
- Sparare Proiettili (shoot): gli invaders possono sparare proiettili verso la tua navicella. Questa funzione crea un nuovo proiettile che si muove verso il basso.
Generazione degli Invaders sullo schermo
Ora che abbiamo una classe per gli invaders, dobbiamo creare un gruppo di invaders che appaiano sullo schermo e si muovano insieme. Per fare questo, creeremo una classe Grid (griglia) che gestisce un insieme di invaders.
Aggiungi questo codice al tuo file index.js:
class Grid { constructor() { this.position = { x: 0, y: 0 }; this.velocity = { x: 3, y: 0 }; this.invaders = []; const columns = Math.floor(Math.random() * 10 + 5); const rows = Math.floor(Math.random() * 5 + 2); this.width = columns * 30; for (let x = 0; x < columns; x++) { for (let y = 0; y < rows; y++) { this.invaders.push( new Invader({ position: { x: x * 30, y: y * 30 } }) ); } } } update() { this.position.x += this.velocity.x; this.position.y += this.velocity.y; this.velocity.y = 0; if (this.position.x + this.width > canvas.width || this.position.x <= 0) { this.velocity.x = -this.velocity.x; this.velocity.y = 30; } } }
Cosa fa questo codice?
- Creare una Griglia (Grid): la classe Grid crea una disposizione di invaders sullo schermo. Ogni griglia ha una posizione e una velocità.
- Posizionare gli invaders (invaders): la griglia genera un numero casuale di colonne e righe di invaders. Ogni invader viene posizionato a una distanza regolare dagli altri, formando una griglia.
- Muovere la Griglia (update): la griglia si muove orizzontalmente e cambia direzione quando raggiunge il bordo dello schermo. Inoltre, si sposta verso il basso ogni volta che cambia direzione.
Movimento e comportamento degli Invaders
Ora che abbiamo creato gli invaders e la griglia che li contiene, dobbiamo assicurarci che si muovano sullo schermo e interagiscano con la navicella del giocatore.
Modifica la funzione animate come segue:
const grids = []; const invaderProjectiles = []; function animate() { requestAnimationFrame(animate); c.fillStyle = 'black'; c.fillRect(0, 0, canvas.width, canvas.height); player.update(); projectiles.forEach((projectile, index) => { if (projectile.position.y + projectile.radius <= 0) { setTimeout(() => { projectiles.splice(index, 1); }, 0); } else { projectile.update(); } }); grids.forEach((grid, gridIndex) => { grid.update(); if (frames % 100 === 0 && grid.invaders.length > 0) { grid.invaders[Math.floor(Math.random() * grid.invaders.length)].shoot(invaderProjectiles); } grid.invaders.forEach((invader, i) => { invader.update({ velocity: grid.velocity }); // Gestione delle collisioni tra proiettili del giocatore e invaders projectiles.forEach((projectile, j) => { if ( projectile.position.y - projectile.radius <= invader.position.y + invader.height && projectile.position.x + projectile.radius >= invader.position.x && projectile.position.x - projectile.radius <= invader.position.x + invader.width && projectile.position.y + projectile.radius >= invader.position.y ) { setTimeout(() => { const invaderFound = grid.invaders.find(invader2 => invader2 === invader); const projectileFound = projectiles.find(projectile2 => projectile2 === projectile); if (invaderFound && projectileFound) { score += 100; scoreElement.innerHTML = score; createParticles({ object: invader, fades: true }); grid.invaders.splice(i, 1); projectiles.splice(j, 1); if (grid.invaders.length > 0) { const firstInvader = grid.invaders[0]; const lastInvader = grid.invaders[grid.invaders.length - 1]; grid.width = lastInvader.position.x - firstInvader.position.x + lastInvader.width; grid.position.x = firstInvader.position.x; } else { grids.splice(gridIndex, 1); } } }, 0); } }); }); }); invaderProjectiles.forEach((invaderProjectile, idx) => { if (invaderProjectile.position.y + invaderProjectile.height >= canvas.height) { setTimeout(() => { invaderProjectiles.splice(idx, 1); }, 0); } else { invaderProjectile.update(); } }); if (keys.arrowLeft.pressed && player.position.x >= 0) { player.velocity.x = -10; player.rotation = -0.15; } else if (keys.arrowRight.pressed && player.position.x + player.width <= canvas.width) { player.velocity.x = 10; player.rotation = 0.15; } else { player.velocity.x = 0; player.rotation = 0; } if (frames % randomInterval === 0) { grids.push(new Grid()); randomInterval = Math.floor(Math.random() * 500 + 500); frames = 0; } frames++; } animate();
Cosa fa questo codice?
- Aggiungere griglie di invaders (grids): ogni tanto, una nuova griglia di invaders viene aggiunta al gioco, creando nuovi nemici.
- Muovere e sparare: gli invaders si muovono e sparano proiettili verso la tua navicella. Se i proiettili degli invaders colpiscono il bordo inferiore dello schermo, vengono rimossi.
- Gestire le collisioni: se un proiettile della tua navicella colpisce un invader, sia il proiettile che l’invader vengono rimossi dal gioco, e il punteggio aumenta. Viene anche creato un effetto visivo per simulare l’esplosione dell’invader.
- Aggiornare il gioco di continuo (animate): questa funzione fa sì che il gioco continui a funzionare, aggiornando costantemente la posizione di tutti gli elementi e verificando le interazioni tra di essi.
Ora hai una flotta di invaders che si muovono sullo schermo, sparano alla tua navicella e possono essere abbattuti dai tuoi proiettili! Il gioco sta prendendo forma, ma ci sono ancora alcune cose da sistemare, come i proiettili degli invaders e la gestione della fine del gioco.
Manca poco al termine del nostro tutorial!
CONTENUTI GRATUITI IN EVIDENZA
Guide per aspiranti programmatori 👨🏻🚀
Vuoi muovere i primi passi nel Digital e Tech? Abbiamo preparato alcune guide per aiutarti a orientarti negli ambiti più richiesti oggi.