PDA

View Full Version : Problemino con le Allegro sotto C


Banglit
31-08-2002, 09:54
Dunque il seguente codice:

if ((imagex+image->w>muro_ver1x) && (imagex<muro_ver1x+muro_ver->w) && (imagey+image->h>muro_ver1y) && (imagey<muro_ver1y+muro_ver->h))
{

if (direzione == 2)
{
imagex=imagex-1;
}

if (direzione == 1)
{
imagex=imagex+1;
}
}

Dovrebbe gestire la collisione (2D bounding box) fra uno sprite (image con coordinate imagey e imagex) e un'altro sprite (muro_ver con coordinate muro_ver1x e muro_ver1y). Per funzionare funziona il fatto è il se lo sprite si mette a metà del "Muro" riesce comunque a passare senza essere respinto. Ora mi chiedo:

1) Come si può ovviare a questo problema?
2) E' possibile fare una gestione generalizzata delle collisioni in modo che una sola funzione le gestisca tutte senza dover riempire il mio codice di patacche del genere?

Nuitari
31-08-2002, 12:02
Premetto che non conosco le Allegro, cmq considerato quel che hai scritto dovrebbe essere un semplice problema di logica.

Tu hai due oggetti, "image" e "muro", rispettivamente sprite e ostacolo.
Le coordinate sono:

imagex, imagey
muro_ver1x, muro_ver1y

di larghezza:

image->w, image->h
muro_ver->w, muro_ver->h

Ora, supponiamo che il tuo gioco si veda dall'alto e che i due oggetti siano rappresentabili con 2 rettangoli.

Per effettuare la verifica della collisione durante il movimento dovresti fare:


switch (direzione)
{
case 1:
if (!((imagey+image->h > muro_ver1y && imagey < muro_ver1y+muro_ver1->h) &&
(imagex+image->w+1 > muro_ver1x && imagex+1 < muro_ver1x+muro_ver1->w)))
imagex++;
break;
case 2:
if (!((imagey+image->h > muro_ver1y && imagey < muro_ver1y+muro_ver1->h) &&
(imagex+image->w-1 > muro_ver1x && imagex-1 < muro_ver1x+muro_ver1->w)))
imagex--;
break;
case 3:
if (!((imagey+image->h-1 > muro_ver1y && imagey-1 < muro_ver1y+muro_ver1->h) &&
(imagex+image->w-1 > muro_ver1x && imagex < muro_ver1x+muro_ver1->w)))
imagey--;
break;
case 4:
if (!((imagey+image->h+1 > muro_ver1y && imagey+1 < muro_ver1y+muro_ver1->h) &&
(imagex+image->w-1 > muro_ver1x && imagex < muro_ver1x+muro_ver1->w)))
imagey++;
break;
}


Dimmi se funziona :)

Banglit
31-08-2002, 13:50
Mmmm il problema è che si sovrappone anche se dovrebbe essere respinto. Ecco uno screen fatto per chiarire la situazione.

Nuitari
31-08-2002, 13:53
Uops avevo fatto un errore :p La fretta gioca brutti scherzi =)
Prova ad applicare la modifica che ho riportato sopra.
Se continua ancora a dare problemi, ti dispiacerebbe postare l'intero pezzo di codice?

Dimenticavo una precisazione.

Tieni presente che salvo diverse indicazioni tutte le coordinate sono in base 0. Le dimensioni dello sprite invece sono quasi certamente in base 1.

Questo significa che per ottenere la coordinate in pixel dei bordi dello sprite devi sempre sottrarre 1 alle dimensioni (cosa che nell'esempio non ho fatto per chiarezza).

Nuitari
31-08-2002, 15:26
Se trovi difficoltà a capire leggendo il codice ti spiego velocemente i tuoi errori.

Fondamentalmente sono 2:

Il primo è che devi negare le condizioni.
La forumula "((imagex+imagew>murox) && (imagex<murox+murow) && (imagey+imageh>muroy) && (imagey<muroy+muroh))" ti indica se uno sprite E' in collisione con l'altro, e non viceversa. Dato che se la condizione è vera allora muovi l'oggetto, devi verificare se lo sprite NON E' in condizione con l'oggetto. Tutto questo lo ottieni usando il not (!).

Il secondo errore è che devi verificare PRIMA di effettuare il movimento se le nuove coordinate genereranno una collisione. Tu effettui il controllo sulle coordinate attuali ma questo non è esatto. Per risolvere il problema devi sommare i valori dello spostamento come ho fatto io sopra.

Fammi sapere.

Banglit
01-09-2002, 01:15
Originally posted by Nuitari
Se trovi difficoltà a capire leggendo il codice ti spiego velocemente i tuoi errori.

Fondamentalmente sono 2:

Il primo è che devi negare le condizioni.
La forumula "((imagex+imagew>murox) && (imagex<murox+murow) && (imagey+imageh>muroy) && (imagey<muroy+muroh))" ti indica se uno sprite E' in collisione con l'altro, e non viceversa. Dato che se la condizione è vera allora muovi l'oggetto, devi verificare se lo sprite NON E' in condizione con l'oggetto. Tutto questo lo ottieni usando il not (!).

Il secondo errore è che devi verificare PRIMA di effettuare il movimento se le nuove coordinate genereranno una collisione. Tu effettui il controllo sulle coordinate attuali ma questo non è esatto. Per risolvere il problema devi sommare i valori dello spostamento come ho fatto io sopra.

Fammi sapere.

Ordunque... il problema lo ho risolto. Ho sostituito al mio algoritmo il tuo (per un fatto di leggibilità) e ho controllato la dichiarazione delle variabili e... trackkk ho sgamato l'errore. Infatti nel ciclo principale (main loop in gergo):

while(!key[KEY_ESC])
{
muro_ver1x = 0;
}

Ho inizializzato il valore X di muro_ver1 nel ciclo principale e ciò comporta un azzeramento ogni volta che viene compiuto il ciclo facendo in modo che non ci sia gestione della collisione ;). Infatti non si dovrebbe mai "blittare" cioè "stampare" sullo schermo a coordinata fissa cioè:

masked_blit(muro_ver1, buffer, 0,0, 10, 20, 32, 32);

pseudocodice:

stampa sullo schermo con trasparenza attivata (masked_blit)
muro_ver1 su buffer (muro_ver1, buffer)
0,0 li lasciamo perdere (gestione palette)
alle coordinate 10, 20 (10, 20)
con dimensione 32 x 32 (32, 32)

Infatti per essere corretti e poter aggiornare in maniera decente la scena avrei dovuto mettere:

masked_blit(muro_ver1,buffer,0,0, muro_ver1x, muro_ver1y, muro_ver1->w, muro_ver1->h);

In modo che se c'è un errore del genere lo si nota subito in quanto lo sprite viene stampato in una posizione non corretta dello schermo.
Spero che si capisca qualche cosa di ciò che ho scritto =)))

Nuitari
01-09-2002, 02:21
Ordunque... il problema lo ho risolto. Ho sostituito al mio algoritmo il tuo (per un fatto di leggibilità)

Spero tu abbia inserito anche la correzione delle dimensioni, che non avevo incluso nel codice ma che avevo citato nella spiegazione.

Felice d'esserti stato d'aiuto cmq :) Poi ce lo farai vedere il gioco :p

Banglit
01-09-2002, 12:28
Appena finisco il 1° livello ve lo uppo in anteprima =)