Personaggio si incastra nel terreno

Hai una curiosità o un problema con Game Maker? Domanda e ti sarà risposto!
Rispondi
Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Personaggio si incastra nel terreno

Messaggio da Cash »

Ci sto sbattendo la testa ma non riesco a capire come risolvere: sto facendo un semplice giochino platform, il personaggio può muoversi, saltare e fare walljump e tutto funziona ma alcune volte dopo un salto si blocca. Non riesco più a muovermi ne a saltare, non c'è niente che blocca il movimento tipo un IF che non va o altro. Facendo qualche test ho notato che la y del giocatore finisce sotto nel terreno di meno di 1pixel(roba di tipo 0.40px) ma anche provando ad approssimare la y al numero più alto non si risolve il problema. Nella room in cui sto provando ci sono solo degli oggetti che fanno da muro(non hanno codice, hanno solo la spunta a solid) e ovviamente il giocatore.
Collision con obj_solid:

Codice: Seleziona tutto

move_contact_solid(direction,12);
vspeed=0;
Step:

Codice: Seleziona tutto

//MOVIMENTO ORIZZONTALE
var keyL, keyR, keyUp; 
WallSlowed=false; // WallSlowed è usato se il giocatore è attaccato ad un muro e quindi deve scendere lentamente
//
keyL=keyboard_check(vk_left);
keyR=keyboard_check(vk_right);
keyUp=keyboard_check_pressed(vk_up);
if keyL &&  spd > -maxSpd
    spd-=0.2;
if keyR && spd < maxSpd 
    spd+=0.2;
if !keyL && !keyR && spd !=0
    spd-=sign(spd) * 0.2;
//Muoviti
repeat( floor( abs(spd) )  )
{
    if !place_meeting(x+sign(spd),y,obj_solid)
        x += sign(spd);
    else
    {
        spd=0;
        if (!place_meeting(x,y+1,obj_solid) && vspeed >= 0) //Scendi lentamente se attaccato ad un muro
            WallSlowed=true;
    }
}
//MOVIMENTO VERTICALE
if keyUp
{
    if place_meeting(x,y+1,obj_jump)
    {
        vspeed=-jumpHeight * instance_place(x,y+1,obj_jump).jumpPower;
    }
    if place_meeting(x,y+1,obj_solid)
        vspeed=-jumpHeight;
    //WALLJUMP
    if !place_meeting(x,y+1,obj_solid)
    {
        if place_meeting(x-1,y,obj_solid)
        {
            vspeed=-jumpHeight;
            spd=wJspd;
        }
        if place_meeting(x+1,y,obj_solid)
        {
            vspeed=-jumpHeight;
            spd=-wJspd;
        }
    }
}
// Gravità
if place_meeting(x,y+1,obj_solid)
    gravity=0;
else
{
    if ( WallSlowed )
    {
        gravity=0;
        vspeed=0;
        y+=WallSpeed;
    }
    else
        gravity=grav;
}

Avatar utente
CaptainOlon
Membro attivo
Messaggi: 441
Iscritto il: 30/07/2011, 14:56
Specialità: Programmazione
Uso: GM:Studio 1.4 Pro
Località: Salerno
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da CaptainOlon »

Potresti usare un semplice script (deriva da quello di Shaun Spalding, ma l'ho migliorato un po' credo :asd:) che usiamo noi in Serious Zeb (pubblicità occulta, lol):

Codice: Seleziona tutto

var i; i=0;
while((place_meeting(x,y-i,obj_Block))&&(place_meeting(x,y+i,obj_Block))) i+=1;
if(!place_meeting(x,y-i,obj_Block)){
    if(!place_meeting(x,y+i,obj_Block)){ y-=i; }else{ y-=i; } // {sopra&sotto (muove su)} {sopra}
}else{ y+=i; } //{sotto}
Praticamente questo script butta fuori dal blocco obj_Block l'oggetto che lo richiama.
Ecco cosa fa il codice:
  • - finché c'è collisione col blocco i pixel sopra e i pixel sotto, incrementa i
    - poi se non c'è più collisione sia sopra di i pixel che sotto di i pixel allora per default spinge l'oggetto verso l'alto di i pixel
    - se invece non c'è più la collisione solo sopra di i pixel spinge sopra di i pixel
    - se invece non c'è più la collisione solo sotto di i pixel spinge sotto di i pixel
E' improbabile se non impossibile che si verifichino tutte e due le condizioni, ma prevenire è meglio che curare :sisisi:

EDIT: dimenticavo, lo script va eseguito ad ogni step
PS:
Lo stesso discorso abbiamo fatto per le collisioni orizzontali: lo script rimane identico, solo che come default (sinistra & destra) spinge nella direzione opposta all'ultima direzione di movimento registrata.
Immagine
Immagine

Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Cash »

CaptainOlon ha scritto:Potresti usare un semplice script (deriva da quello di Shaun Spalding, ma l'ho migliorato un po' credo :asd:) che usiamo noi in Serious Zeb (pubblicità occulta, lol):

Codice: Seleziona tutto

var i; i=0;
while((place_meeting(x,y-i,obj_Block))&&(place_meeting(x,y+i,obj_Block))) i+=1;
if(!place_meeting(x,y-i,obj_Block)){
    if(!place_meeting(x,y+i,obj_Block)){ y-=i; }else{ y-=i; } // {sopra&sotto (muove su)} {sopra}
}else{ y+=i; } //{sotto}
Praticamente questo script butta fuori dal blocco obj_Block l'oggetto che lo richiama.
Ecco cosa fa il codice:
  • - finché c'è collisione col blocco i pixel sopra e i pixel sotto, incrementa i
    - poi se non c'è più collisione sia sopra di i pixel che sotto di i pixel allora per default spinge l'oggetto verso l'alto di i pixel
    - se invece non c'è più la collisione solo sopra di i pixel spinge sopra di i pixel
    - se invece non c'è più la collisione solo sotto di i pixel spinge sotto di i pixel
E' improbabile se non impossibile che si verifichino tutte e due le condizioni, ma prevenire è meglio che curare :sisisi:

EDIT: dimenticavo, lo script va eseguito ad ogni step
PS:
Lo stesso discorso abbiamo fatto per le collisioni orizzontali: lo script rimane identico, solo che come default (sinistra & destra) spinge nella direzione opposta all'ultima direzione di movimento registrata.
Non cambia niente, sto provando anche a riscrivere il codice ma continua a presentarsi lo stesso problema. Ho scoperto anche che secondo GameMaker "y mod 1" può anche fare 1, direi che c'è qualcosa di sbagliato.

Avatar utente
Wolfrost
Membro super
Messaggi: 692
Iscritto il: 03/08/2014, 13:08
Specialità: Programmazione
Uso: GM:Studio 1.4 Pro
Località: Una galassia lontana lontana...
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Wolfrost »

CaptainOlon ha scritto:Potresti usare un semplice script (deriva da quello di Shaun Spalding, ma l'ho migliorato un po' credo :asd:) che usiamo noi in Serious Zeb (pubblicità occulta, lol):

Codice: Seleziona tutto

var i; i=0;
while((place_meeting(x,y-i,obj_Block))&&(place_meeting(x,y+i,obj_Block))) i+=1;
if(!place_meeting(x,y-i,obj_Block)){
    if(!place_meeting(x,y+i,obj_Block)){ y-=i; }else{ y-=i; } // {sopra&sotto (muove su)} {sopra}
}else{ y+=i; } //{sotto}
Praticamente questo script butta fuori dal blocco obj_Block l'oggetto che lo richiama.
Ecco cosa fa il codice:
  • - finché c'è collisione col blocco i pixel sopra e i pixel sotto, incrementa i
    - poi se non c'è più collisione sia sopra di i pixel che sotto di i pixel allora per default spinge l'oggetto verso l'alto di i pixel
    - se invece non c'è più la collisione solo sopra di i pixel spinge sopra di i pixel
    - se invece non c'è più la collisione solo sotto di i pixel spinge sotto di i pixel
E' improbabile se non impossibile che si verifichino tutte e due le condizioni, ma prevenire è meglio che curare :sisisi:

EDIT: dimenticavo, lo script va eseguito ad ogni step
PS:
Lo stesso discorso abbiamo fatto per le collisioni orizzontali: lo script rimane identico, solo che come default (sinistra & destra) spinge nella direzione opposta all'ultima direzione di movimento registrata.
Andiamo molto fieri del sistema di collisione del mio progetto vedo :asd: :asd:
Comunque è molto valido, non capisco quale sia il problema, forse lo implementi male... mmm non so davvero :fapensare:
Immagine

Immagine

Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Cash »

Ho provato a convertire tutti i place_meeting in !place_free e ora sembra funzionare. Tutto funzionava prima dell'ultimo aggiornamento di Game Maker, inizia a venirmi il dubbio che abbiano fatto qualcosa alla funzione.

Solid Snake
GMI Advanced
Messaggi: 2093
Iscritto il: 19/12/2010, 16:17
Specialità: Programmazione
Uso: GM:Studio 1.4 Standard
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Solid Snake »

Psss:

Codice: Seleziona tutto

move_outside_solid(90, -1);//move_outside_all(90, -1)
:cappa:
♥♥♥♥♥♥
Immagine
♥♥♥♥♥♥
Spoiler
Immagine

Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Cash »

Solid Snake ha scritto:Psss:

Codice: Seleziona tutto

move_outside_solid(90, -1);//move_outside_all(90, -1)
:cappa:
Ho provato ma neanche quello risolve il problema

Avatar utente
Alv
Membro
Messaggi: 133
Iscritto il: 14/11/2014, 22:33
Specialità: Programmazione
Uso: GM:Studio 1.4 Pro
Località: Sicilia
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Alv »

Cash ha scritto:Ci sto sbattendo la testa ma non riesco a capire come risolvere: sto facendo un semplice giochino platform, il personaggio può muoversi, saltare e fare walljump e tutto funziona ma alcune volte dopo un salto si blocca. Non riesco più a muovermi ne a saltare, non c'è niente che blocca il movimento tipo un IF che non va o altro. Facendo qualche test ho notato che la y del giocatore finisce sotto nel terreno di meno di 1pixel(roba di tipo 0.40px) ma anche provando ad approssimare la y al numero più alto non si risolve il problema. Nella room in cui sto provando ci sono solo degli oggetti che fanno da muro(non hanno codice, hanno solo la spunta a solid) e ovviamente il giocatore.
Collision con obj_solid:

Codice: Seleziona tutto

move_contact_solid(direction,12);
vspeed=0;
Step:

Codice: Seleziona tutto

//MOVIMENTO ORIZZONTALE
var keyL, keyR, keyUp; 
WallSlowed=false; // WallSlowed è usato se il giocatore è attaccato ad un muro e quindi deve scendere lentamente
//
keyL=keyboard_check(vk_left);
keyR=keyboard_check(vk_right);
keyUp=keyboard_check_pressed(vk_up);
if keyL &&  spd > -maxSpd
    spd-=0.2;
if keyR && spd < maxSpd 
    spd+=0.2;
if !keyL && !keyR && spd !=0
    spd-=sign(spd) * 0.2;
//Muoviti
repeat( floor( abs(spd) )  )
{
    if !place_meeting(x+sign(spd),y,obj_solid)
        x += sign(spd);
    else
    {
        spd=0;
        if (!place_meeting(x,y+1,obj_solid) && vspeed >= 0) //Scendi lentamente se attaccato ad un muro
            WallSlowed=true;
    }
}
//MOVIMENTO VERTICALE
if keyUp
{
    if place_meeting(x,y+1,obj_jump)
    {
        vspeed=-jumpHeight * instance_place(x,y+1,obj_jump).jumpPower;
    }
    if place_meeting(x,y+1,obj_solid)
        vspeed=-jumpHeight;
    //WALLJUMP
    if !place_meeting(x,y+1,obj_solid)
    {
        if place_meeting(x-1,y,obj_solid)
        {
            vspeed=-jumpHeight;
            spd=wJspd;
        }
        if place_meeting(x+1,y,obj_solid)
        {
            vspeed=-jumpHeight;
            spd=-wJspd;
        }
    }
}
// Gravità
if place_meeting(x,y+1,obj_solid)
    gravity=0;
else
{
    if ( WallSlowed )
    {
        gravity=0;
        vspeed=0;
        y+=WallSpeed;
    }
    else
        gravity=grav;
}
Dando un'occhiata veloce al codice, il problema potrebbe essere la riga 59 (y+=WallSpeed). Prova a commentarla, e vedere come si comporta. Se non entra più nel muro, vuol dire che il problema era quello. Allora bisognerebbe rivedere la porzione di codice che pone WallSlowed=true. (Non vedo altro motivo per cui l'oggetto debba entrare nel muro.)
Ultima modifica di Alv il 21/12/2020, 14:49, modificato 1 volta in totale.

Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Cash »

Alv ha scritto:...
Avevo già provato a commentare quella parte ma niente.

Avatar utente
Alv
Membro
Messaggi: 133
Iscritto il: 14/11/2014, 22:33
Specialità: Programmazione
Uso: GM:Studio 1.4 Pro
Località: Sicilia
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Alv »

Cash ha scritto:Facendo qualche test ho notato che la y del giocatore finisce sotto nel terreno di meno di 1pixel(roba di tipo 0.40px)
Ho provato il tutorial ufficiale sui platform in modalità debug. Anche lì sembra che il giocatore entri nel muro (es. y=192,50), ma non si incastra (cioè la collisione effettivamente non si verifica). Questo perchè probabilmente, nel rilevamento collisioni, Game Maker arrotonda la posizione (la x e la y) all'intero più vicino (cioè 192,50 è come se fosse 192). Quindi il problema dev'essere un altro.
Ultima modifica di Alv il 17/01/2021, 20:01, modificato 4 volte in totale.

Avatar utente
Alv
Membro
Messaggi: 133
Iscritto il: 14/11/2014, 22:33
Specialità: Programmazione
Uso: GM:Studio 1.4 Pro
Località: Sicilia
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Alv »

Ho fatto copia incolla e ho testato il codice in un progetto di prova (uso Game Maker 8.0). E' da un po' che lo provo, non sembra incastrarsi. Quindi il problema non sta nel codice, perlomeno non in quello che hai postato. Potrebbe essere qualcosa legato alle nuove feature di Game Maker, oppure alle impostazioni degli sprite (collision checking). Ovviamente se cambi lo sprite a runtime il giocatore potrebbe sovrapporsi con il muro (perchè i pixel dei due sprite differiscono). Se il problema è quello, puoi risolvere impostando una collision mask per l'oggetto giocatore.
Ultima modifica di Alv il 29/11/2020, 23:22, modificato 1 volta in totale.

Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Cash »

Alv ha scritto:Ho fatto copia incolla è ho testato il codice in un progetto di prova (uso Game Maker 8.0). E' da un pò che lo provo, non sembra incastrarsi. Quindi il problema non sta nel codice, perlomeno non in quello che hai postato. Potrebbe essere qualcosa legato alle nuove features di Game Maker, oppure alle impostazioni degli sprites (collision checking). Ovviamente se cambi lo sprite a runtime il giocatore potrebbe sovrapporsi con il muro (perchè i pixel dei due sprites differiscono). Se il problema è quello, puoi risolvere impostando una collision mask per l'oggetto giocatore.
Cavolo, ho appena provato anche io su GM 8 e funziona perfettamente senza nessuna modifica. Lo sprite dell'oggetto è letteralmente un quadrato, non cambia mai sprite e non ha animazioni. Inizia seriamente a venirmi il dubbio che sia un bug dell'ultima versione di game maker

Avatar utente
Cash
Membro super
Messaggi: 933
Iscritto il: 09/11/2013, 20:40
Uso: GM:Studio 1.4 Pro
Contatta:

Re: Personaggio si incastra nel terreno

Messaggio da Cash »

http://gmc.yoyogames.com/index.php?show ... try4781283
Dubbio confermato, nuovo bug di Game Maker. Da un report fatto da un utente:
place_meeting no longer shares the same accuracy as the collision event.

Collision event triggers on a .5 pixel overlap.

place_meeting returns true on a 1 pixel overlap.

This breaks collision resolution code that is triggered on a collision event and uses place_meeting to resolve it.

This is inconsistent with previous stable build 1.4.1474, and was not mentioned as an intentional change anywhere in the release notes. So I assume its a bug.

I also see no reason why you would not want these two things to match, as essentially they should be doing the same thing.

I have not tested but suspect it might effect other function as well like, instance_place, place_free, ect...

Rispondi

Chi c’è in linea

Visitano il forum: Nessuno e 158 ospiti