I went back a few pages on here and I noticed not a lot of people do top-down games. Does anyone have any experience in top-down collision detection in game maker?
Edit: I figured it out, kinda sorta, honestly if anyone has a better option I'd switch to it, lol.
yes, i have a whole folder with code snippets from the GM forum:
This is generally for circular sprites, but can easily be adjusted to rectangular or whatever you want. Just change the collision_<shape> code.
Adjust arguments to fit your needs (below code was made for a 32x32 circular sprite). Use with a centered origin on sprite, or adjust to fit.
Place this in a Step event.
if(collision_circle(x + lengthdir_x(6, direction) + hspeed, y + lengthdir_y(6, direction) - vspeed, 16, obj_block, 1, 1)) { // Horizontal collision
hspeed = 0; // Stop horizontal movement
}
if(collision_circle(x + lengthdir_x(6, direction) - hspeed, y + lengthdir_y(6, direction) + vspeed, 16, obj_block, 1, 1)) { // Vertical collision
vspeed = 0; // Stop vertical movement
}
This works best with centered origin sprite.
Place this in a Collision event.
//This one is for 32x32 horizontal and vertical walls ONLY
var xDif, yDif;
xDif = x - other.x;
yDif = y - other.y;
if abs(xDif)>abs(yDif)
{
x = other.x + sign(xDif) * 32;
}
else
{
y = other.y + sign(yDif) * 32;
}
This works best with centered origin sprite.
Place this in a Collision event.
x += 0.1 * (x - (other.x));
y += 0.1 * (y - (other.y));
This script checks all solid objects.
Place this in a Step event.
if hspeed!=0
if !place_free(x+hspeed,y)
{
if hspeed>0 move_contact_solid(0,hspeed)
if hspeed<0 move_contact_solid(180,-hspeed)
hspeed=0
}
if vspeed!=0
if !place_free(x+hspeed,y+vspeed)
{
if vspeed>0 move_contact_solid(270,vspeed)
if vspeed<0 move_contact_solid(90,-vspeed)
vspeed=0
}
First script is used only to slide past circular shapes.
Second script is used only to slide past rectangular shapes.
//avoid_circle(player_radius,x,y,radius)
//(x,y) is the center of the circle
var d;
argument3+=argument0
d=point_distance(x,y,argument1,argument2)
if d>0 and d<argument3
{
xx=argument1+(x-argument1)*argument3/d
yy=argument2+(y-argument2)*argument3/d
return 1;
}
return 0;
//avoid_rectangle(player_radius,x,y,width,height,angle)
//(x,y) is the center of the rectangle
var xto,yto,v,h,ah,vh,d;
argument3/=2
argument4/=2
if point_distance(x,y,argument1,argument2) < point_distance(0,0,argument3,argument4)+argument0
{
xto=cos(degtorad(argument5))
yto=sin(degtorad(argument5))
xx=x-argument1
yy=y-argument2
h=(xto*xx-yto*yy)
v=(xto*yy+yto*xx)
ah=abs(h/argument3)
av=abs(v/argument4)
if max(ah,av)<=1
{
//If the object is inside the rectangle
if ah>av{
h=(argument3+argument0)*sign(h)}
else{
v=(argument4+argument0)*sign(v)}
xx=argument1+xto*h+yto*v
yy=argument2+xto*v-yto*h
return 1;
}
else
{
//If the object is touching the rectangle
h=median(h,-argument3,argument3)
v=median(v,-argument4,argument4)
xx=argument1+xto*h+yto*v
yy=argument2+xto*v-yto*h
d=point_distance(xx,yy,x,y)/argument0
if d<1
{
xx+=(x-xx)/d
yy+=(y-yy)/d
return 1;
}
}
}
xx=x
yy=y
return 0;
Argument0 = target instance (for example obj_wall)
Argument1 = resolution (1-45, low integers are slow, 15 is default)
Place this in either End Step event or Collision event.
//THIS CAN GO IN THE END STEP OF THE INSTANCE
//OR THE COLLISION EVENT WITH AN INSTANCE
//
//scr_move_slide(inst, res);
//
//argument0 = instance to check for
//argument1 = resolution. Must be between 1 and 45 (low numbers are SLOW). 15 is a good default
var xmot, ymot;
x=xprevious;
y=yprevious;
for (i = 0; i < 90; i += argument1)
{
xmot = x + lengthdir_x(speed, direction + i);
ymot = y + lengthdir_y(speed, direction + i);
if !place_meeting(xmot, ymot,argument0) {x = xmot; y = ymot; exit;}
xmot = x + lengthdir_x(speed, direction - i);
ymot = y + lengthdir_y(speed, direction - i);
if !place_meeting(xmot, ymot, argument0) {x = xmot; y = ymot; exit;}
}