C
ChiHelios
Guest
!SOLVED! Thanks everyone for your help
Solution below for reference
Thankyou everyone, I got everything working, including staying grounded and sticking. I'm really happy with the result. I set an actor parent object so all my other characters can benefit from the collisions.
I stuck with place_meeting and instance_place but now thanks to your explanations I understand WHY I'm using it. The actor collisions always set speed to zero, but recognise grounding, then after I update position I put grounded/sticking velocity back in.
Just like you suggested I did not factor in the platform movements with the player.
After getting the player solid, I used this code for the moving walls. The platforms only push actors like the player, and detect if there will be a crush using place_meeting. I'm planning to implement some different crush strategies by giving each object a script to follow. For the moment though, nice and happy, looking forward to seeing the levels I can make with this.
There was a very specific case where you could be crushed by a corner moving diagonally which caused a bug so I put another clause in which resolves this.
I've left the code for reference and will update my first post with my solution. Thanks again for all your help and feel free to offer any suggestions.
ORIGINAL POST
---------------------------------
Hi all!
I'm having some trouble with moving platforms in my platformer. I'm using vx and vy as my velocity vector, and this takes place just before I update the x and y values. This is for my player.
Stationary walls are okay, but when the walls move they overlap the player and it means the wall can pull the player. On top of that, when the moving wall changes moving right to left while pushing the player the player translocates to the right of the screen.
Any advice?
Thanks
Solution below for reference
Thankyou everyone, I got everything working, including staying grounded and sticking. I'm really happy with the result. I set an actor parent object so all my other characters can benefit from the collisions.
I stuck with place_meeting and instance_place but now thanks to your explanations I understand WHY I'm using it. The actor collisions always set speed to zero, but recognise grounding, then after I update position I put grounded/sticking velocity back in.
Just like you suggested I did not factor in the platform movements with the player.
///Detect collision
//temporary variables can be used to make sure x and y don't alter
//until the correct part of the step.
var i, tempx, tempy;
tempx = x; tempy = y; canjump = false; sticking = false; grounded = false;
dColl = false; sideColl = false; dobj = self; sideobj = self;
/// X collisions
if (place_meeting(x+vx, y, owall))
{
sideColl = true; sideobj = instance_place(x+vx,y,owall)
while(!place_meeting(tempx+sign(vx),y,owall))
{tempx += sign(vx);}
robj = instance_place(x,y+1,owall);
if sign(vx) = sign(sideobj.vx) and sideobj.vx < 4
{sticking = true;}
vx = 0;
x = tempx;
}
///////////////////////////////////////////////////////////
// Collisions in the y direction
if (place_meeting(x, y+vy, owall))
{
while(!place_meeting(x,tempy+sign(vy),owall))
{tempy += sign(vy);}
if sign(vy)=1 {dobj = instance_place(x,y+vy,owall);
dColl = true;
grounded = true;}
vy = 0;
y = tempy;
canjump =true; inair = false;
}
///////////////////////////////////////////////////////////
// Collisions in x and y direction
if (place_meeting(x+vx, y+vy, owall))
{
//Move to contact
while(!place_meeting(x+vx,tempy+sign(vy),owall))
{tempy += sign(vy);}
y = tempy;
while(!place_meeting(tempx+sign(vx),y+vy,owall))
{tempx += sign(vx);}
x = tempx;
//UPDATE speeds
vx = 0;
vy = 0;
}
///Position
x += vx;
y += vy;
if grounded {vy= dobj.vy;}
if sticking {vx= sideobj.vx;}
//temporary variables can be used to make sure x and y don't alter
//until the correct part of the step.
var i, tempx, tempy;
tempx = x; tempy = y; canjump = false; sticking = false; grounded = false;
dColl = false; sideColl = false; dobj = self; sideobj = self;
/// X collisions
if (place_meeting(x+vx, y, owall))
{
sideColl = true; sideobj = instance_place(x+vx,y,owall)
while(!place_meeting(tempx+sign(vx),y,owall))
{tempx += sign(vx);}
robj = instance_place(x,y+1,owall);
if sign(vx) = sign(sideobj.vx) and sideobj.vx < 4
{sticking = true;}
vx = 0;
x = tempx;
}
///////////////////////////////////////////////////////////
// Collisions in the y direction
if (place_meeting(x, y+vy, owall))
{
while(!place_meeting(x,tempy+sign(vy),owall))
{tempy += sign(vy);}
if sign(vy)=1 {dobj = instance_place(x,y+vy,owall);
dColl = true;
grounded = true;}
vy = 0;
y = tempy;
canjump =true; inair = false;
}
///////////////////////////////////////////////////////////
// Collisions in x and y direction
if (place_meeting(x+vx, y+vy, owall))
{
//Move to contact
while(!place_meeting(x+vx,tempy+sign(vy),owall))
{tempy += sign(vy);}
y = tempy;
while(!place_meeting(tempx+sign(vx),y+vy,owall))
{tempx += sign(vx);}
x = tempx;
//UPDATE speeds
vx = 0;
vy = 0;
}
///Position
x += vx;
y += vy;
if grounded {vy= dobj.vy;}
if sticking {vx= sideobj.vx;}
After getting the player solid, I used this code for the moving walls. The platforms only push actors like the player, and detect if there will be a crush using place_meeting. I'm planning to implement some different crush strategies by giving each object a script to follow. For the moment though, nice and happy, looking forward to seeing the levels I can make with this.
There was a very specific case where you could be crushed by a corner moving diagonally which caused a bug so I put another clause in which resolves this.
//
/*
Detect if the object is going to collide with an actor
if the actor can be moved then move it
If there will be a crush, stop the object
*/
crushing = false;
//X collisions
while instance_place(x+vx,y,oactor)
{
//Find the instance to be pushed
coll_obj = instance_place(x+vx,y,oactor);
if coll_obj != noone
with coll_obj
{
//Check for crush
if !place_meeting(x+sign(other.vx),y,owall)
{
//no crush then move
x+=other.vx;
vx = other.vx;
}
else
{
//move up to the crush point
while !place_meeting(x+sign(other.vx),y,owall)
{x+=sign(other.vx);}
other.vx = 0; vx = 0;
}
}
}
//Y collisions
while instance_place(x,y+vy,oactor)
{
//Find the instance to be pushed
coll_obj = instance_place(x,y+vy,oactor);
if coll_obj != noone
with coll_obj
{
//Check for crush
if !place_meeting(x,y+sign(other.vy),owall)
{
//no crush then move
y+=other.vy;
vy = other.vy;
}
else
{
//move up to the crush point
while !place_meeting(x,y+sign(other.vy),owall)
{y+=sign(other.vy);}
other.vy = 0; vy = 0;
}
}
}
//XY collisions
while instance_place(x+vx,y+vy,oactor)
{
//Find the instance to be pushed
coll_obj = instance_place(x+vx,y+vy,oactor);
if coll_obj != noone
with coll_obj
{
//Check for x crush
if !place_meeting(x+sign(other.vx),y,owall)
{
//no crush then move
x+=other.vx;
vx = other.vx;
}
else
{
//move up to the crush point
while !place_meeting(x+sign(other.vx),y,owall)
{x+=sign(other.vx);}
other.vx = 0; vx = 0;
}
//Check for y crush
if !place_meeting(x,y+sign(other.vy),owall)
{
//no crush then move
y+=other.vy;
vy = other.vy;
}
else
{
//move up to the crush point
while !place_meeting(x,y+sign(other.vy),owall)
{y+=sign(other.vy);}
other.vy = 0; vy = 0;
}
}
}
/*
Detect if the object is going to collide with an actor
if the actor can be moved then move it
If there will be a crush, stop the object
*/
crushing = false;
//X collisions
while instance_place(x+vx,y,oactor)
{
//Find the instance to be pushed
coll_obj = instance_place(x+vx,y,oactor);
if coll_obj != noone
with coll_obj
{
//Check for crush
if !place_meeting(x+sign(other.vx),y,owall)
{
//no crush then move
x+=other.vx;
vx = other.vx;
}
else
{
//move up to the crush point
while !place_meeting(x+sign(other.vx),y,owall)
{x+=sign(other.vx);}
other.vx = 0; vx = 0;
}
}
}
//Y collisions
while instance_place(x,y+vy,oactor)
{
//Find the instance to be pushed
coll_obj = instance_place(x,y+vy,oactor);
if coll_obj != noone
with coll_obj
{
//Check for crush
if !place_meeting(x,y+sign(other.vy),owall)
{
//no crush then move
y+=other.vy;
vy = other.vy;
}
else
{
//move up to the crush point
while !place_meeting(x,y+sign(other.vy),owall)
{y+=sign(other.vy);}
other.vy = 0; vy = 0;
}
}
}
//XY collisions
while instance_place(x+vx,y+vy,oactor)
{
//Find the instance to be pushed
coll_obj = instance_place(x+vx,y+vy,oactor);
if coll_obj != noone
with coll_obj
{
//Check for x crush
if !place_meeting(x+sign(other.vx),y,owall)
{
//no crush then move
x+=other.vx;
vx = other.vx;
}
else
{
//move up to the crush point
while !place_meeting(x+sign(other.vx),y,owall)
{x+=sign(other.vx);}
other.vx = 0; vx = 0;
}
//Check for y crush
if !place_meeting(x,y+sign(other.vy),owall)
{
//no crush then move
y+=other.vy;
vy = other.vy;
}
else
{
//move up to the crush point
while !place_meeting(x,y+sign(other.vy),owall)
{y+=sign(other.vy);}
other.vy = 0; vy = 0;
}
}
}
I've left the code for reference and will update my first post with my solution. Thanks again for all your help and feel free to offer any suggestions.
ORIGINAL POST
---------------------------------
Hi all!
I'm having some trouble with moving platforms in my platformer. I'm using vx and vy as my velocity vector, and this takes place just before I update the x and y values. This is for my player.
Stationary walls are okay, but when the walls move they overlap the player and it means the wall can pull the player. On top of that, when the moving wall changes moving right to left while pushing the player the player translocates to the right of the screen.
Any advice?
Thanks
Code:
///Detect collision
//temporary variables can be used to make sure x and y don't alter
//until the correct part of the step.
var i, tempx, tempy;
tempx = x; tempy = y;
//If no collision to happen, remove existing Coll objects.
if !place_meeting(x+vx,y,owall) or !place_meeting(x,y+vy,owall) or !place_meeting(x+vx,y+vy,owall)
{
rColl = false; dColl = false; uColl = false; lColl = false;
canjump = false;
robj = self; lobj = self; uobj = self; dobj = self;
}
/// X collisions
if (place_meeting(x+vx, y, owall))
{
if sign(vx) > 0
{rColl = true; robj =instance_place(x+vx,y,owall);
while(!place_meeting(tempx+sign(vx-robj.vx),y,owall) and sign(vx)=sign(robj.vx) and vx>robj.vx)
{tempx += sign(vx-robj.vx);}
vx = robj.vx;
}
else
{lColl = true; lobj =instance_place(x+vx,y,owall);
while(!place_meeting(tempx+sign(vx-lobj.vx),y,owall) and sign(vx)=sign(lobj.vx) and vx>robj.vx)
{tempx += sign(vx-lobj.vx);}
vx = lobj.vx;
}
x = tempx;
}
///////////////////////////////////////////////////////////
// Collisions in the y direction
if (place_meeting(x, y+vy, owall))
{
if sign(vy) > 0
{dColl = true; dobj =instance_place(x,y+vy,owall);
vy = 1.1*dobj.vy;
while(!place_meeting(x,tempy+sign(vy-dobj.vy),owall) and sign(vy)=sign(dobj.vy) and vy>dobj.vy)
{tempy += sign(vy-robj.vy);}
if vy>dobj.vy or sign(vy)!=sign(dobj.vy) {vy = dobj.vy;}
}
else
{uColl = true; uobj =instance_place(x,y+vy,owall);
while(!place_meeting(x,tempy+sign(vy-uobj.vy),owall) and sign(vy)=sign(uobj.vy) and vy>robj.vy)
{tempy += sign(vy-lobj.vy);}
if vy<uobj.vy or sign(vy)!=sign(uobj.vy) {vy = uobj.vy;}
}
y = tempy;
canjump =true; inair = false;
}
Last edited by a moderator: