Hello world - Palla pallina

 

Cominciamo con un giochino facile facile, Lo conoscete?
Non vi sto a spiegare il funzionamento ne tantomeno descriverò la realizzazione per intero di tale programma.
Mi soffermerò invece sui principali aspetti ovvero, movimento della barretta, della palla e rimbalzo di quest’ultima sulla barretta

Prima di cominciare un po’ di notazioni e riferimenti

Questa è la barretta comandata dal giocatore (Paddle) si muove orizzontalmente in base allo spostamento del Mouse e la pallina vi rimbalza sopra,
Tre muri (destro, sinistro e sopra) contornano lo schermo e la pallina vi rimbalza
I mattoncini vengono distrutti non appena la pallina entra in contatto con essi

Questa è la nostra pallina (Ball) e le sue proprietà sono:
Ball.Position  // Posizione (X,Y)  del centro della pallina
Ball.OldPosition  // PosizionePrecedente (X,Y)
Ball.Radius    // Raggio
Ball.Speed     // Velocità (X,Y)

La barrettà è da considerarsi come un rettangolo, le sue proprietà sono:

Paddle.Position  // Posizione (X,Y)
NOTA poiché la Y non cambia si potrebbe ottimizzare utilizzando un solo intero per la X
Paddle.Width     // Larghezza
Paddle.Heigth    // Altezza

I tre muri (WallTop, WallLeft, WallRight) si potrebbero considerare anch’essi dei rettangoli con altezza, larghezza e posizione ma poiché tutte queste informazioni sarebbero superflue utilizzeremo un solo valore intero per ogni muro, ad indicare X per WallLeft e WallRight, la Y per WallTop.

Ad esempio:
Int WallTop = 0
Int WallLeft = 0
Int WallRight = 500

Vi siete annoiati? Bene. Passiamo al vero argomento di questo post.

Movimento

In breve. Il movimento della barretta, o meglio la sua nuova posizione in base allo spostamento del Mouse, si calcola così:

Paddle.X = Math.Min(WallRight – Paddle.Width / 2, Math.Max(WallLeft + PaddleWidth / 2, MouseX));

Vi convince? Fate una prova su carta.

La pallina
La sua posizione viene calcolata in funzione del tempo trascorso (timePassed)
Ball.Position.X = Ball.OldPosition.X + Ball.Speed.X * timePassed
Ball.Position.Y = Ball.OldPosition.Y + Ball.Speed.Y * timePassed


Ciò che accade quando la pallina interagisce con muri, barretta, mattoncini etc non è altro che una condizione che si verifica e di conseguenza vengono alterate le componenti di Ball.Speed

Per i muri

If(Ball.Position.X < WallLeft) Ball.Speed.X *= -1;  // Si inverte la direzione della velocità sulla X

Analogamente per

If(Ball.Position.X > WallRight) Ball.Speed.X *= -1;  // Si inverte la direzione della velocità sulla X

Mentre
If(Ball.Position.Y < WallTop) Ball.Speed.Y *= -1;  // Si inverte la direzione della velocità sulla Y

Bello no! Ma è tutto?
Considerazione importante (importantissima) questi controlli vengono effettuati subito dopo che la posizione della pallina è stata aggiornata.

Facciamo un esempio.
Supponiamo che all’istante 1 la pallina si trovi in posizione
X= 1, Y = 50 e la sua velocità è di X = - 5, Y = -5 (Sale e va verso sinistra)

All’istante 2 la pallina sarà in posizione X = -4, Y= 49
Adesso si è verificata la condizione (Ball.Position.X < WallLeft) per cui la velocità sulla X verrà invertita diventando Ball.Speed.X = 5  (Ball.Speed.X *= -1)

Ma intanto la pallina, prima che venga nuovamente aggiornata si troverà in parte oltre il muro, compenetrandolo, non è un bell’effetto. No no no!
La soluzione è presto fatta: oltre ad invertire la velocità bisogna riposizionare la pallina in corrispondenza del probabile punto d’impatto col muro. I tre controlli descritti sopra diventano quindi:

If(Ball.Position.X < WallLeft)
 {
   Ball.Position.X += 2 * (wallLeft - Ball.Position.X); // Compensazione
   Ball.Speed.X *= -1;  // Si inverte la direzione della velocità sulla X
}


If(Ball.Position.X > WallRight)
{
   Ball.Speed.X *= -1;  // Si inverte la direzione della velocità sulla X

   
   // Compensazione
   Ball.Position.X += 2 * (wallRight – (Ball.Position.X + Ball.Radius + Ball.Radius));
}


If(Ball.Position.Y < WallTop)
{
   Ball.Position.Y += 2 * (wallTop - Ball.Position.Y); // Compensazione
   Ball.Speed.Y *= -1;  // Si inverte la direzione della velocità sulla Y
}


Spero di aver scritto bene.
Se si sbagliano questi calcoli si può incorrere in un Bug comune. (mi è capitato tantissime volte)
La pallina è oltre il muro. La velocità viene invertita e corretta la posizione però erroneamente viene posizionata di nuovo oltre il muro.
Al controllo successivo verrà nuovamente invertita velocità e corretta posizione.
Ciò che accade visivamente è che la pallina si incastra nel muro e comincia a vibrare freneticamente senza riuscire a disincastrarsi e se lo fa potrebbe schizzare fuori dallo schermo e perdersi per sempre …

Questo articolo sta diventando più lungo di quanto credessi e temo anche abbastanza noioso. Passo infine al punto saliente e poi concludo, promesso.

Interazione pallina e barretta
Questa volta facciamo al contrario. Prima il codice poi le chiacchiere

if ((Ball.Position.Y + Ball.Radius) >= Paddle.Position.Y)
 {
     if (Ball.OldPosition.Y + Ball.Radius) < Paddle.Position.Y)
    {
       if ((Ball.Position.X + Ball.) > Paddle.Position.X)
       {
        if (Ball.Position.X – Ball.Radius < (Paddle.Position.Y + Paddle.Width))
        {
            
 // Compensazione
           Ball.Position.Y -= 2 * ((Ball.Position.Y + Ball.Radius) – (Paddle.Position.Y);
           ballDY *= -1; // Si inverte la direzione della velocità sulla Y

          // ???
          Ball.Speed.X = (Ball.Position.X - (Paddle.Position.X + (Paddle.Width / 2)) * Paddle.Curve;
      }
   }
}
else
 if (Ball.Position.Y + Ball.Radius > 400)
{
    // La pallina è scesa oltre la barretta e ormai persa continua a scendere,  

    // superata una soglia (es 400)
    // Rimuovi pallina, Reset Gioco
}


I primi 2 controlli servono a determinare se la pallina un istante prima fosse al di sopra della barretta ed ora collide con essa. Se non fosse così vorrebbe dire che questa è già scesa oltre la superficie d’impatto quindi continuerà a precipitare.
Appurato questo, bisogna verificare, oltre all’altezza, che la pallina si trovi all’interno nella barretta (tra le sue estremità). Barretta nell’angolo a sinistra e pallina in quello opposto se pur ad altezza d’impatto non deve determinare rimbalzo.
Come gestire il rimbalzo l’abbiamo già visto: Compensazione ed inversione di velocità.
Ed infine ??? usando la proprietà Paddle.Curve
Riuscite a capire cosa succede? Ditemelo nei commenti, se volete.

Ho finito. Salva e Compila

Commenti

Post popolari in questo blog

Indovinello: Soluzioni!!!

Gli indovinelli che ci avete mandato 10