A recipe of: Flappy birds! – (Collision Detection)

Con questo Tutorial Andremo a implementare la collision detection.

 

Ingredienti:

 

Le collisioni

Per ora, il nostro gioco, risulta al quanto facile, in quanto possiamo passare attraverso i tubi senza scontrarci contro di essi.

Ovviamente noi non vogliamo cio’, vogliamo vedere la terza legge di newton venga rispettata, e che i nostri sprite si comportino come dei corpi rigidi.

 

I rettangoli

Per fare cio’ possiamo disegnare intorno ai nostri sprite un “rettangolo” e andare a controllare quando due “rettangoli” vanno a intersecarsi, nel caso avviene un’intersezione tra i due rettangoli, allora abbiamo una collisione.

Iniziamo quindi con l’aggiungere nella classe ostacoli, due rettangoli, uno per il tubo superiore e uno per il tubo inferiore.

public class Ostacoli{

    private Texture TuboSuperiore, TuboInferiore;
    private  Vector2 posizioneSuperiore, posizioneInferiore;
    private Random rand;
    private Rectangle RettangoloTuboSuperiore, RettangoloTuboInferiore;


Quindi andiamo a settarli nel nostro costruttore, dandogli una dimensione e una posizione le quali, dovranno corrispondere alle dimensioni e alle posizioni dei nostri rettangoli.

 

public Ostacoli(int x) {
    TuboSuperiore = new Texture("TuboSuperiore.png");
    TuboInferiore = new Texture("TuboInferiore.png");
    rand = new Random();

    posizioneSuperiore = new Vector2(x, rand.nextInt(150)+ 100 + 110);
    posizioneInferiore = new Vector2(x, posizioneSuperiore.y - 150 - TuboInferiore.getHeight());

    rettangoloTuboSuperiore = new Rectangle(posizioneSuperiore.x,posizioneSuperiore.y,getTuboSuperiore().getWidth(),getTuboSuperiore().getHeight());
    rettangoloTuboInferiore = new Rectangle(posizioneInferiore.x,posizioneInferiore.y,getTuboInferiore().getWidth(),getTuboInferiore().getHeight());
    
}

Impostati i rettangoli, dobbiamo ricordarci di riposizionarli ogni volta che si riposiziona un tubo, quindi andremo a riposizionarli nella funzione riposizionamento.

 

public void riposiziona(float x){
    posizioneSuperiore.set(x, rand.nextInt(150)+ 100 + 110);
    posizioneInferiore.set(x, posizioneSuperiore.y - 150 - TuboInferiore.getHeight());
    rettangoloTuboSuperiore.setPosition(posizioneSuperiore.x,posizioneSuperiore.y);
    rettangoloTuboInferiore.setPosition(posizioneInferiore.x,posizioneInferiore.y);

}

Ora andiamo a creare una funzione, che ci servira’ a capire quando i Rettangoli dei tubi, andranno a intersecarsi con il rettangolo ( che andremo successivamente a creare ) del nostro giocatore.

public boolean collisionDetection(Rectangle giocatore){
    return giocatore.overlaps(rettangoloTuboSuperiore) || giocatore.overlaps(rettangoloTuboInferiore);
}

Ora possiamo uscire dalla classe degli ostacoli, e andare a creare il rettangolo per il nostro giocatore, andiamo quindi nella classe “Bird”.
Andiamo a fare quindi la stessa cosa implementando un rettangolo per il giocatore e posizionandolo e dimensionandolo adeguatamente.

public static final int GRAVITY = -10;
private static final int VELOCITA_ORIZZONTALE = 120;

private Vector2 velocita;
private Rectangle rettangoloGiocatore;

public Bird(int x, int y) {
    super(x, y);
    texture = new Texture("flappybird.png");
    velocita = new Vector2(0,0);
    rettangoloGiocatore = new Rectangle(x,y,texture.getWidth(),texture.getHeight());
}

E ricordiamoci di aggiornare la posizione del rettangolo mentre il giocatore si muove:

public void update(float dt) {
    if(this.posizione.y >= 0) {
        velocita.add(0, GRAVITY);
        velocita.scl(dt);
        posizione.add(VELOCITA_ORIZZONTALE * dt, velocita.y);
        velocita.scl(1 / dt);
    }
    if(this.posizione.y < 0){
        this.posizione.y = 0;
    }
    rettangoloGiocatore.setPosition(posizione.x,posizione.y);
}

Ora, non ci rimane che andare a creare una funzione che vada a restituire il rettangolo del nostro giocatore, quindi:

public Rectangle getRettangoloGiocatore(){
    return rettangoloGiocatore;
}

Controllando l’avvenuta colllisione

Ora dobbiamo controllare se durante lo stato di gioco avvengono delle collisioni tra i rettangoli, dobbiamo quindi andare nella nostra classe stato di gioco e controllare a ogni ciclo se e’ avvenuta una collisione, andiamo quindi a lavorare nell update nel ciclo che gia’ abbiamo creato.

public void update(float deltaTime) {
    InputManager();
    bird.update(deltaTime);

    camera.position.x = bird.getPosizione().x + 50;

    for(Ostacoli ostacolo : tubi){
        if(camera.position.x - (camera.viewportWidth/2) > ostacolo.getPosizioneSuperiore().x + ostacolo.getTuboSuperiore().getWidth()){
            ostacolo.riposiziona(ostacolo.getPosizioneSuperiore().x + ((55 + SPAZIO))*NUMERO_TUBI);
        }
        if (ostacolo.collisionDetection(bird.getRettangoloGiocatore())){
            gsm.set(new StatoMenu());
        }
    }

    camera.update();
}

Una volta controllato con quell’if la collisione, io ho scelto che ad avvenuta collisione il gioco sarebbe tornato nello stato del gioco resettandolo, ma successivamente andremo a creare uno stato gameOver.

yay

 

Nel prossimo tutorial andremo a disporre tutti gli elementi grafici in modo che non rappresentino un peso a ogni restart.

 

I file aggiornati fino a questo momento: game

 

 

Saluti dal vostro nabbo Developer

Marco Tamagno

Facebook

Google+

Rispondi