Pagine    Articoli    Prodotti    Forum    Cerca  
Nickname

Password


Non sei registrato?
Registrati a GPI qui!

Puoi anche attivare un vecchio utente GPI e chiedere una nuova password.
I Team

Mappa Team
I nostri utenti

Mappa Utenti
  Programmare un videogame Flash con Starling #10
Pubblicato da Andrea Venturi il 2013-08-05 21:10:05

"can’t touch me!"

 

In questo  tutorial inseriamo i nemici, e il primo passo della collision tra i nemici e i nostri proiettili.

 

Momento teoria

La creazione e gestione dei nemici avviene in maniera molto simile a quella della gestione dei proiettili.

Quindi gran parte del codice risulterà molto simile.

Dato che la nostra astronave è già in grado di sparare andiamo ad inserire un controolo di collisione tra il proiettile e il nemico.

 

Di modi per gestire la collisione ce ne sono svariati, ne ricapitolo tre che ritengo i più utilizzati:

 

1) Bounding Sphere

2) Bounding Box

3) Point vs Box

 

Bounding Sphere:

Questo è il modo più semplice per controllare se due oggetti collidono.

In pratica si calcola il raggio del minimo cerchio (sfera se in 3D) a partire dal centro dell’oggetto.

 

Stessa calcolo per l’oggetto con cui vogliamo testare la collisione.

A questo punto calcoliano la distanza tra i centri dei due oggetti e se questa è inferiore alla somma dei raggi dei due cerchi, allora i due oggetti collidono.

 

Bounding Box:

Questo metodo è leggermente più complesso di quello precedente, in quanto si deve calcolare il minimo rettangolo che rachiude il nostro oggetto e uno per l’oggetto con cui si vuole testare la collisione.

Se almeno uno dei vertici risulta dentro l’altro rettangolo allora gli oggetti collidono.

 

Perfect Point:

Questo metodo è il metodo che implementeremo, non è altro che una semplificazione del metodo precedente.

Si calcola il box che racchiude l’oggetto, e se il punto si trova nel rettangolo allora l’oggetto è colpito.

 

Ovviamente il rettangolo deve racchiudere l’immagine del nemico e il punto non è altro che il proiettile.

 

 

 

Mano al codice

Prima di tutto andiamo ad inserire nella texture atlas due immagini che rappersentano i nemici.

 

Nemico 1

 

Nemico 2

 

Andiamo a creare la classe Enemy.

Ovviamente andiamo ad estendere Sprite.

Iniziamo con creare tre variabili private: Un image e due uint (uno per la velocità e uno per il tipo)

 

private var ship:Image;
private var speed:uint = 300;
private var type:uint;

 

Il costruttore deve prendere un parametro intero che verra’ utilizzato per decidere quale delle due immagini utilizzare.

 

public function Enemy(tipo:uint)
{
    type = tipo;
    super();
    addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}

 

Quindi lo salviamo e nella funzione che gestirà l’evento added_to_stage andiamo a testarlo per caricare un’immagine o l’altra

 

private function onAddedToStage(e:Event):void
{
    removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    if ( type == 0 )
    {
        ship = new Image(Assets.getAtlas().getTexture("E1"));
    }
    else
    {
        ship = new Image(Assets.getAtlas().getTexture("E2"));
    }
    addChild(ship);
}

 

Oviamente altri due metodi servono come abbiamo visto per la classe Shoot: update per la gestione del movimento

 

public function update(time:Number):void
{
    x -= time * speed;
}

 

Come detto può essere complicata a piacere.

E l’ultimo metodo serve per impostare la posizione del nemico

 

public function setPos(X:Number,Y:Number):void
{
    x = X;
    y = Y;
}

 

Ora passiamo a modificare la classe StarField.

Andiamo a creare quattro variabili privare

 

private var ritardoEnemy:uint;
private var DelayEnemy:uint;
private var enemyList:Vector.;
private var EnemyMaxH:int;

 

Per gestire la lista dei nemici attivi, la tempistica di uscita e lo spazio verticale in cui far partire i nemici in maniera casuale.

 

Andiamo ad aggiungere nel metodo drawScreen l’inizializzazione delle variabili create.

 

ritardoEnemy = 0;
DelayEnemy = 30;
enemyList = new Vector.();
EnemyMaxH = int(buttomLimit - topLimit);

 

A questo punto andiamo a creare il metodo per gestire i nemici.

 

private function EnemyApproach():void
{

 

Dichiariamo due variabili temporanee, una di tipo Enemy e una di tipo Rectangle.

 

var tmp:Enemy;
var hitArea:Rectangle;

 

Andiamo ad aumentare la variabile che gestisce il ritardo di uscita del nemico

 

ritardoEnemy++;

 

Se è trascorso abbastanza tempo per far uscire un nuovo nemico, andiamo ad azzerare il la variabile che gestisce il ritardo e per rendere meno monotona l’uscita dei nemici ricalcoliamoci la soglia di ritardo.

 

if (ritardoEnemy > DelayEnemy)
{
  ritardoEnemy = 0;
  DelayEnemy = (int(Math.random() * 100) )+ 3;

 

Ora andiamo a crearci unaa nuova istanza di Enemy, calcoliamo l’altezza a cui deve comparire e posizioniamolo, aggiungiamolo allo contesto e mettiamolo nella lista.

 

  tmp = new Enemy(DelayEnemy%2);
  var Y:int = ((Math.random() * stage.stageHeight) % EnemyMaxH) + topLimit - tmp.height;
  var X:Number = stage.stageWidth + tmp.width;
  tmp.setPos(X, Y);
  addChild(tmp);
  enemyList.push(tmp);
}

 

[Notate che uso il DelayEnemy per ricavare il tipo.]

 

A questo punto scorriamo l’intera lista di nemici per aggiornare la loro posizione

 

for (var it:int; it < enemyList.length;++it )
{
  tmp = enemyList[it];
  tmp.update(elapsed);

 

Testiamo se l’invasore spaziale ha supertao la parte sinistra dello schermo lo eliminiamo.

 

if (tmp.x < -tmp.width )
{
  removeChild(tmp);
  enemyList.splice(it, 1);
}

 

altrimenti...

 

altrimenti dobbiamo controllare se colllide con qualche proiettile.

 

Quindi andiamo a calcolarci l’area di collisione e per ogni proiettile testiamo la loro collisione

Se collidono elimino sia il proiettile che il nemico.

 

else
{
  hitArea = new Rectangle(tmp.x, tmp.y, tmp.width, tmp.height);
  for (var itp:int=0; itp < proiettiliPG.length;++itp )
  {
    var sh:Shoot = proiettiliPG[itp];
    if (hitArea.contains(sh.x, sh.y))
    {
      removeChild(tmp);
      enemyList.splice(it, 1);
      removeChild(sh);
      proiettiliPG.splice(itp, 1);
      break;        
    }
  }
}

 

Manca soltanto andare ad inserire la chiamata a questo metodo, e andiamo ad inserirla esattamento subito dopo la chiamata alla funzione che gestisce lo sparo dell'astronave. 

 

Come ultima cosa, dato che dobbiamo controllare le prestazioni, andiamo nel file main.as e andiamo ad aggiungere il pannello che indica molte cose, tra cui i frame al secondo e la memoria utilizzata.

 

Quindi includiamo la classe

 

import net.hires.debug.Stats;

 

dichiariamo la variabile

 

private var stats:Stats;

 

Nel main andiamo ad inizializzarla e aggiungiamola allo stage, come prima cosa.

 

stats = new Stats();
addChild(stats);

 

Compilate e provate

 

E qui il link al codice.

 

 

Campagne crowfunding

Just One Line
Siamo presenti su

     
Copyright ©2016 - Manifesto - Privacy - Termini di Servizio - Community - Collaboratori - Contattaci