Jump to content


Photo
* * * * * 7 votes

Top-down Collision Script Collection


  • Please log in to reply
21 replies to this topic

#1 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 06 May 2012 - 07:48 PM

  • Title: Smooth top-down wall collisions.
  • Description: This may be in the official tutorials. I don't know. Not many does. No new beginners ever look at those anyway. And if they do, they sure don't decide to learn from it.
  • GM Version: GM8
  • Registered: Only if collision_circle is pro.
  • File Type: .gmk
  • File Size: 9.86 kB
  • File Link: http://www.mediafire...9r1odr99uamtq45
  • Required Extensions: None.
  • Required DLLs: None.
Summary
Attention: The attached GMK does not contain all of the collision scripts listed below.

This is a collection of collision scripts that can be used for any and all top-down games.
Some may suit your needs to perfection.

We encourage everybody to post their own collision scripts so that they may be added to the collection for everyone to enjoy.


#1 by Jobo:
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
}

#2 by Nocturne:
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;
}

#3 by Nocturne:
This works best with centered origin sprite.
Place this in a Collision event.
//This one is a similar concept as #2, but slightly more general...
x += 0.1 * (x - (other.x));
y += 0.1 * (y - (other.y));

#4 by slayer 64:
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
}

#5 by TheSnidr:
First script is used only to slide past circular shapes.
Second script is used only to slide past rectangular shapes.
Downloadable usage example: http://www.host-a.ne...voidshapes.gm81
//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;

#6 by Nocturne:
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;}
    }

On behalf of all the contributors to this collection, I gladly say: I hope we've helped you!

Edited by Jobo, 12 May 2012 - 10:13 AM.

  • 2

#2 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 06 May 2012 - 08:29 PM

I like it but I tried it out on two computers one that is slow one that is fast paced.
in the slow computer the collision checking was extremely bothering since the computer was keep on trying to adjust to the new coords and GM tries to make collision checking.
in the fast one performance was no issue the computer processed very quickly even when the player was at ridiculous speeds, even the GM had no problem making collision checks.

so through observation this is good for fast ones and slow ones it will be bothersome.

sincerely,
CREATORS124
  • 0

#3 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 06 May 2012 - 08:35 PM

I fail to realize how any computer would be unable to run this, so I would be lying if I said I wasn't doubting your statement.

However, if you want to only run this collision check when something is nearby, simply add:
if(distance_to_object(instance_nearest(x, y, obj_block)) < 100) {
// Collision code
}

Edited by Jobo, 06 May 2012 - 08:36 PM.

  • 0

#4 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 06 May 2012 - 08:50 PM

I fail to realize how any computer would be unable to run this, so I would be lying if I said I wasn't doubting your statement.

However, if you want to only run this collision check when something is nearby, simply add:

if(distance_to_object(instance_nearest(x, y, obj_block)) < 100) {
// Collision code
}

less lag on it but the collision checking makes it hard for the slow computer. :P
when I hit a wall it stops then continues, stops, continues and so on...
effective for performance though. :D
  • 0

#5 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 22257 posts
  • Version:GM:Studio

Posted 06 May 2012 - 08:53 PM

I would LOVE to see you expand on this as there are very many more ways to do this and some are better and some are worse depending on the situation. I myself have about 4 different codes which I commonly use (I can pass them to you if you are interested) because there are different types of movement and obstacles to be taken into consideration... So, please expand on this and make it the definitive TDS collision tutorial!
  • 0

#6 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 06 May 2012 - 09:15 PM

So basically what you want, Nocturne, is a collection of all possible collision detection functions usable for top-down shooters - in one gmk?
I could do something like that, if I was interested in spending time making a large example collection whatsoever. But that would be putting time that I don't always have into something that isn't exactly completely necessary.

What we can do though, is encourage people to post their own collision codes here, and I'll gladly add them to the topic post.
  • 0

#7 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 06 May 2012 - 09:40 PM

you know what!
I think Nocturne is right expand this for people to enjoy!Posted Image
many ways to do this and many people have specific needs for a smooth collision checking.
it would have a great impact on this if you add codes regularly when you want to so you don't have to spend weeks making many at once!

Edited by creators124, 06 May 2012 - 09:41 PM.

  • 0

#8 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 22257 posts
  • Version:GM:Studio

Posted 06 May 2012 - 10:15 PM

What we can do though, is encourage people to post their own collision codes here, and I'll gladly add them to the topic post.


Fair enough! Here's one (actually two, but they are variations on the theme). These work best with centered origin sprite :

//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;
}

//COLLISION EVENT
//This one is a similar concept, but slightly more general...
x += 0.1 * (x - (other.x));
y += 0.1 * (y - (other.y));

Those are fast and work quite well, but I have better ones which I shall post when I have a bit more time...
  • 0

#9 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 07 May 2012 - 01:54 PM

Wonderful!
Added both to the collection.
  • 0

#10 slayer 64

slayer 64

    Slayer of gingers

  • GMC Member
  • 3954 posts
  • Version:GM:Studio

Posted 08 May 2012 - 03:24 AM

this goes in the step event. it makes the instance slide against horizontal and vertical walls. it checks all solid objects.
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
}

  • 0

#11 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 08 May 2012 - 03:28 AM

this goes in the step event. it makes the instance slide against horizontal and vertical walls. it checks all solid objects.

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
}

what happens if both hspeed and vspeed is used? Posted Image
  • 0

#12 slayer 64

slayer 64

    Slayer of gingers

  • GMC Member
  • 3954 posts
  • Version:GM:Studio

Posted 08 May 2012 - 04:07 AM

what happens if both hspeed and vspeed is used? Posted Image

your computer will catch on fire
  • 3

#13 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 08 May 2012 - 02:14 PM

what happens if both hspeed and vspeed is used? Posted Image

When you're moving on 2 axises at once (moving in any direction except 0, 90, 180 and 270 - right, up, left and down) both vspeed and hspeed are greater than 0.
If this is the case, his collision script will simply check for a horizontal collision and a vertical collision.

Added script to collection.
  • 0

#14 TheSnidr

TheSnidr

    Heavy metal viking dentist

  • Global Moderators
  • 3062 posts
  • Version:GM:Studio

Posted 08 May 2012 - 03:36 PM

Made two scripts that may be useful to someone. It checks for collisions between a circle (the player) and either a rectangle or another circle, and makes the player avoid the shape. It's limited to these wo shapes (could possibly be expanded to more shapes), but it's incredibly smooth:
avoid_circle(player_radius,x,y,radius)
Spoiler

avoid_rectangle(player_radius,x,y,width,height,angle)
Spoiler

An example on how to use them
It's not perfect, and if the player makes it into a tight spot, it will be forced inside the objects. It'll be up to you to prevent that from happening
  • 0

#15 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 12 May 2012 - 09:25 AM

I came by the collision_rectangle code and I put it in the object_block.
and came up with a pretty smooth collision but the disadvantage to this is that collision box of the player object has to be small enough to do it! :'(
if (place_meeting(x+17,y-17,obj_player) == true or place_meeting(x-17,y-17,obj_player) == true)
{
    vspeed = 0;
};
else if (place_meeting(x+17,y+17,obj_player) == true or place_meeting(x-17,y+17,obj_player) == true)
{
    vspeed = 0;
};

if obj_player.vspeed < 0 and (collision_rectangle(x-16,y+16,x+16,y+20,obj_player,1,1))
{
    obj_player.vspeed = 0;
};
else if obj_player.vspeed > 0 and (collision_rectangle(x-16,y-16,x+16,y-20,obj_player,1,1))
{
    obj_player.vspeed = 0;
};
if object0.hspeed < 0 and (collision_rectangle(x+16,y+16,x+20,y-16,obj_player,1,1))
{
    obj_player.hspeed = 0;
};
else if obj_player.hspeed > 0 and (collision_rectangle(x-16,y+16,x-20,y-16,obj_player,1,1))
{
    obj_player.hspeed = 0;
};

it is effective in making the player object slide against it! :D
example:
example.zip
oh yeah note only tested with vspeed and hspeed not others please modify if needed! :P

Edited by creators124, 12 May 2012 - 09:33 AM.

  • 0

#16 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 22257 posts
  • Version:GM:Studio

Posted 12 May 2012 - 09:37 AM

Here's another nifty one :

//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;}
    }

  • 1

#17 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 12 May 2012 - 09:42 AM

Here's another nifty one :

//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;}
    }

what is the arguments? Posted Image
  • 0

#18 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 20 May 2012 - 03:22 PM

what is the arguments?

//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

Really?
  • 0

#19 creators124

creators124

    awesomeliciousmember

  • GMC Member
  • 866 posts
  • Version:GM8

Posted 20 May 2012 - 09:19 PM

what is the arguments?

//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

Really?

gah!
I need to start read better! Posted Image
thanks I think. Posted Image
  • 0

#20 Jobo

Jobo

    Freelancer

  • Local Moderators
  • 2791 posts
  • Version:GM:Studio

Posted 08 July 2012 - 10:46 AM

Just giving this a bump so it'll be visible for anyone looking for scripts like these.
  • 0

#21 gamereality

gamereality

    GMC Member

  • GMC Member
  • 577 posts
  • Version:GM:Studio

Posted 04 November 2012 - 06:52 AM

Bit of a necropost, but I have a question about one of Nocturne's sliding scripts:

The "scr_move_slide" one appears to only function with perfectly vertical and horizontal rectangles. If I rotate the sprites using image_angle, the collision just pretends that there's a large rectangular block preventing movement rather than adjusting to the angle of the object's sprite.

Would there be a way to modify it in order to support angled rectangles?
  • 0

#22 zombieattack

zombieattack

    GMC Member

  • GMC Member
  • 101 posts
  • Version:GM:Studio

Posted 26 December 2013 - 08:45 AM

 

What we can do though, is encourage people to post their own collision codes here, and I'll gladly add them to the topic post.


Fair enough! Here's one (actually two, but they are variations on the theme). These work best with centered origin sprite :

//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;
}

//COLLISION EVENT
//This one is a similar concept, but slightly more general...
x += 0.1 * (x - (other.x));
y += 0.1 * (y - (other.y));
Those are fast and work quite well, but I have better ones which I shall post when I have a bit more time...

 

 

Ahem, excuse me good sir, that second script is mine from about 2 years ago: gmc.yoyogames.com/index.php?showtopic=463523 The stumbling clay troll comes out from under his clay bridge when his credit gets taken :P


Edited by zombieattack, 26 December 2013 - 08:46 AM.

  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users