• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Enemy platform collision

T

tijeseffff

Guest
I was doing a simple platformer by Shaun's tutorials.
Everything was kinda done except ONE thing.
When enemy is on platform, he is falling through it.
And I STILL can't find any solutions to fix this ;(
Maybe someone here can help me.
 

CloseRange

Member
it would help if you showed your enemy collision code.
It's hard to figure out what you did wrong without any look into the code.
 
T

tijeseffff

Guest
it would help if you showed your enemy collision code.
It's hard to figure out what you did wrong without any look into the code.
https://pastebin.com/NQ6KVuCL

it would help if you showed your enemy collision code.
It's hard to figure out what you did wrong without any look into the code.
//Horizontal Collision
if (place_meeting(x+hsp,y,obj_wall))
{
while(!place_meeting(x+sign(hsp),y,obj_wall))
{
x += sign(hsp);
}
hsp = 0;

dir *= -1;
}
x += hsp;

//Vertical Collision
if (place_meeting(x,y+vsp,obj_wall))
{
while(!place_meeting(x,y+sign(vsp),obj_wall))
{
y += sign(vsp);
}
vsp = 0;
if (fearofheights) && !position_meeting(x+(sprite_width/2)*dir, y+(sprite_height/2)+8, obj_wall)
{
dir *= -1;
}
}
y += vsp;

PS: platform is a child of obj_wall
 
Last edited by a moderator:

Slyddar

Member
if (round(obj_player.y + (obj_player.sprite_height/2)) > y) || (obj_player.key_down) mask_index = -1;
else mask_index = spr_platform;
Unfortunately that was one of Shaun's early tutorials, and it wasn't very good long term. It never catered for enemy units walking on the platforms at the same time as the player jumping through it, as the sprite mask for the platform is simply set to -1 at that time, meaning you don't collide with it, but it also means all enemies just fall through it.
 
T

tijeseffff

Guest
Unfortunately that was one of Shaun's early tutorials, and it wasn't very good long term. It never catered for enemy units walking on the platforms at the same time as the player jumping through it, as the sprite mask for the platform is simply set to -1 at that time, meaning you don't collide with it, but it also means all enemies just fall through it.
;( and what I should do?
 

Slyddar

Member
Well if you think about what you want the player to do, you can make up rules that work. I just wrote this up, so give it a try. You will need to create a parent object, that has no code, called obj_wall_parent. Then duplicate your obj_wall and call that obj_wallp. This will be the platform object that the player can jump up through, so colour it differently. Then replace your collision code with this. I commented the vertical so you can see the logic.
Code:
//Horizontal Collision
if  (place_meeting(x + hsp, y, obj_wall) and !place_meeting(x + hsp, y, obj_wallp)) or
    ((place_meeting(x + hsp, y, obj_wallp) and vsp > 0) and !place_meeting(x, y, obj_wallp)) {
    while !place_meeting(x + sign(hsp), y, obj_wall_parent) {  
        x += sign(hsp);
    }
    hsp = 0;
    dir *= -1;
}
x += hsp;

//if collision with wall and not collision with platform, or collision with platform next step and vsp > 0, but not collision with platform this step, then stop
if  (place_meeting(x, y + vsp, obj_wall) and !place_meeting(x, y + vsp, obj_wallp)) or
    ((place_meeting(x, y + vsp, obj_wallp) and vsp > 0) and !place_meeting(x, y, obj_wallp)) {
    while !place_meeting(x, y + sign(vsp), obj_wall_parent) {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
 
Last edited:
T

tijeseffff

Guest
Well if you think about what you want the player to do, you can make up rules that work. I just wrote this up, so give it a try. You will need to create a parent object, that has no code, called obj_wall_parent. Then duplicate your obj_wall and call that obj_wallp. This will be the platform object that the player can jump up through, so colour it differently. Then replace your collision code with this. I commented the vertical so you can see the logic.
Code:
if  (place_meeting(x + hsp, y, obj_wall) and !place_meeting(x + hsp, y, obj_wallp)) or
    (place_meeting(x + hsp, y, obj_wallp) and vsp > 0) {
    while !place_meeting(x + sign(hsp), y, obj_wall_parent) {   
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

//if collision with wall and not collision with platform, or collision with platform and vsp > 0, then stop
if  (place_meeting(x, y + vsp, obj_wall) and !place_meeting(x, y + vsp, obj_wallp)) or
    (place_meeting(x, y + vsp, obj_wallp) and vsp > 0) {
    while !place_meeting(x, y + sign(vsp), obj_wall_parent) {
        y += sign(vsp);
    }
    vsp = 0;
}

Thank you! You helped me too much)
y += vsp;
 
T

tijeseffff

Guest
Well if you think about what you want the player to do, you can make up rules that work. I just wrote this up, so give it a try. You will need to create a parent object, that has no code, called obj_wall_parent. Then duplicate your obj_wall and call that obj_wallp. This will be the platform object that the player can jump up through, so colour it differently. Then replace your collision code with this. I commented the vertical so you can see the logic.
Code:
if  (place_meeting(x + hsp, y, obj_wall) and !place_meeting(x + hsp, y, obj_wallp)) or
    (place_meeting(x + hsp, y, obj_wallp) and vsp > 0) {
    while !place_meeting(x + sign(hsp), y, obj_wall_parent) {   
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

//if collision with wall and not collision with platform, or collision with platform and vsp > 0, then stop
if  (place_meeting(x, y + vsp, obj_wall) and !place_meeting(x, y + vsp, obj_wallp)) or
    (place_meeting(x, y + vsp, obj_wallp) and vsp > 0) {
    while !place_meeting(x, y + sign(vsp), obj_wall_parent) {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
eh, but what I should do with obj_wall_parent? o_O
 
T

tijeseffff

Guest
Well if you think about what you want the player to do, you can make up rules that work. I just wrote this up, so give it a try. You will need to create a parent object, that has no code, called obj_wall_parent. Then duplicate your obj_wall and call that obj_wallp. This will be the platform object that the player can jump up through, so colour it differently. Then replace your collision code with this. I commented the vertical so you can see the logic.
Code:
if  (place_meeting(x + hsp, y, obj_wall) and !place_meeting(x + hsp, y, obj_wallp)) or
    (place_meeting(x + hsp, y, obj_wallp) and vsp > 0) {
    while !place_meeting(x + sign(hsp), y, obj_wall_parent) {   
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

//if collision with wall and not collision with platform, or collision with platform and vsp > 0, then stop
if  (place_meeting(x, y + vsp, obj_wall) and !place_meeting(x, y + vsp, obj_wallp)) or
    (place_meeting(x, y + vsp, obj_wallp) and vsp > 0) {
    while !place_meeting(x, y + sign(vsp), obj_wall_parent) {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
What I should do with all these objects? When player is standing on obj_wall game hangs. When standing on obj_wall_parent, everything is normal but when jumping on obj_wallp I am going "teleported" through this object.
 

Slyddar

Member
eh, but what I should do with obj_wall_parent? o_O
obj_wall is your normal solid wall, and obj_wallp should will be your platform. The obj_wall_parent object should have no sprite assigned and is never added to the room. It's created so you can place obj_wall and obj_wallp as children of it, and then reference obj_wall_parent in the code, and it will refer to both platforms and solids.

The code you pasted for the enemy should still be fine, but the platform code where you are changing the mask needs to all go.
 
T

tijeseffff

Guest
obj_wall is your normal solid wall, and obj_wallp should will be your platform. The obj_wall_parent object should have no sprite assigned and is never added to the room. It's created so you can place obj_wall and obj_wallp as children of it, and then reference obj_wall_parent in the code, and it will refer to both platforms and solids.

The code you pasted for the enemy should still be fine, but the platform code where you are changing the mask needs to all go.
So I also should put platform code into obj_wallp?
 
T

tijeseffff

Guest
obj_wall is your normal solid wall, and obj_wallp should will be your platform. The obj_wall_parent object should have no sprite assigned and is never added to the room. It's created so you can place obj_wall and obj_wallp as children of it, and then reference obj_wall_parent in the code, and it will refer to both platforms and solids.

The code you pasted for the enemy should still be fine, but the platform code where you are changing the mask needs to all go.
I still don't understand the logic. obj_wall_parent is a parent of obj_wall and obj_wallp is a child of obj_wall? Because object can only have one parent.
UPD: Got it. It works. So what I should do now with enemy?
 
No, do you know what a parent is? A parent is an object that doesn't exist in game, but gives it code to all it's children. So you would make an enemy_parent object, which has ALL the code that every enemy type shares, but you would never create enemy_parent in game. Instead, you make enemy_parent the parent of all your enemy types and then when you're doing collision functions, etc, you simply reference enemy_parent instead of each enemy type. The enemy types will also inherit the code you have in the enemy_parent. So if you wanted all the enemies to have similar behaviours, you would code those behaviours in the enemy_parent object and then simply call that code in each enemy type with the event_inherited() function.

Parenting can turn this:
Code:
if (collision_line(x,y,x+xx,y+yy,obj_enemy_walker,false,false)) {
   //Code
}
if (collision_line(x,y,x+xx,y+yy,obj_enemy_runner,false,false)) {
   //Code
}
if (collision_line(x,y,x+xx,y+yy,obj_enemy_jumper,false,false)) {
   //Code
}
if (collision_line(x,y,x+xx,y+yy,obj_enemy_croucher,false,false)) {
   //Code
}
Into this:
Code:
if (collision_line(x,y,x+xx,y+yy,obj_enemy_parent,false,false)) {
   //Code
}
And as long as you have each obj_enemy_whatever as a child of obj_enemy_parent. Parenting does lots of other things as well, but these are the basics.
 

Slyddar

Member
So what I should do now with enemy?
The enemy can use the horizontal and vertical collision code you pasted above, but every reference to obj_wall should instead reference obj_wall_parent as you want their code to work with both the solid and platform objects. You need to go read up about parenting, and what I'm saying will make more sense then.
 
T

tijeseffff

Guest
The enemy can use the horizontal and vertical collision code you pasted above, but every reference to obj_wall should instead reference obj_wall_parent as you want their code to work with both the solid and platform objects. You need to go read up about parenting, and what I'm saying will make more sense then.
So here is the collision code I am using in enemy object
//Horizontal Collision
if (place_meeting(x+hsp,y,obj_wall_parent))
{
while(!place_meeting(x+sign(hsp),y,obj_wall_parent))
{
x += sign(hsp);
}
hsp = 0;

dir *= -1;
}
x += hsp;

//Vertical Collision
if (place_meeting(x,y+vsp,obj_wall_parent))
{
while(!place_meeting(x,y+sign(vsp),obj_wall_parent))
{
y += sign(vsp);
}
vsp = 0;
}
y += vsp;

And the enemy still falls through the obj_wallp
 
T

tijeseffff

Guest
Also I tried to make this code work with moving platforms, now I am just jumping through moving platforms.
if (place_meeting(x + hsp_final, y, obj_wall) and !place_meeting(x + hsp_final, y, obj_platform)) or
(place_meeting(x + hsp_final, y, obj_platform) and vsp > 0) or (place_meeting(x + hsp_final, y, obj_moveplatform) and vsp > 0 ) {
while !place_meeting(x + sign(hsp_final), y, obj_wall_parent) {
x += sign(hsp_final);
}
hsp_final = 0;
hsp = 0;
}
x += hsp_final;

//if collision with wall and not collision with platform, or collision with platform and vsp > 0, then stop
if (place_meeting(x, y + vsp, obj_wall) and !place_meeting(x, y + vsp, obj_platform)) or
(place_meeting(x, y + vsp, obj_platform) and vsp > 0) or (place_meeting(x + hsp_final, y, obj_moveplatform) and vsp > 0 ) {
while !place_meeting(x, y + sign(vsp), obj_wall_parent) {
y += sign(vsp);
}
vsp = 0;
}
y += vsp;
 

Slyddar

Member
And the enemy still falls through the obj_wallp
Then you have something wrong, possibly the parenting, as the code works correctly. obj_wall_parent has 2 children objects, obj_wall and obj_wallp. They have no children, and all 3 objects have no events or code in them. If you set a basic enemy object up as below, then add either an obj_wall or an obj_wallp block to the room, then enemies will walk on them.

Code for obj_enemy
Code:
//create event
hsp = 0;
vsp = 0;
spd = 2;
max_spd = 2;
dir = 1;
grav = 0.5;
Code:
//step event
hsp += spd * dir;
hsp = clamp(hsp, -max_spd, max_spd);
vsp += grav;

//Horizontal Collision
if (place_meeting(x + hsp, y, obj_wall_parent))
{
  while(!place_meeting(x + sign(hsp), y, obj_wall_parent))
  {
    x += sign(hsp);
  }
  hsp = 0;
  dir *= -1;
}
x += hsp;

//Vertical Collision
if (place_meeting(x, y + vsp, obj_wall_parent))
{
  while(!place_meeting(x, y + sign(vsp), obj_wall_parent))
  {
    y += sign(vsp);
  }
  vsp = 0;
}
y += vsp;
Also I wouldn't worry too much about moving platforms until you get this working, and more importantly, you understand it.
 
Last edited:
T

tijeseffff

Guest
Then you have something wrong, possibly the parenting, as the code works correctly. obj_wall_parent has 2 children objects, obj_wall and obj_wallp. They have no children, and all 3 objects have no events or code in them. If you set a basic enemy object up as below, then add either an obj_wall or an obj_wallp block to the room, then enemies will walk on them.

Code for obj_enemy
Code:
//create event
hsp = 0;
max_spd = 3;
vsp = 0;
spd = 2;
dir = 1;
grav = 0.5;
Code:
//step event
hsp += spd * dir;
hsp = clamp(hsp, -max_spd, max_spd);
vsp += grav;

//Horizontal Collision
if (place_meeting(x + hsp, y, obj_wall_parent))
{
while(!place_meeting(x + sign(hsp), y, obj_wall_parent))
{
x += sign(hsp);
}
hsp = 0;
dir *= -1;
}
x += hsp;

//Vertical Collision
if (place_meeting(x, y + vsp, obj_wall_parent))
{
while(!place_meeting(x, y + sign(vsp), obj_wall_parent))
{
y += sign(vsp);
}
vsp = 0;
}
y += vsp;
Also I wouldn't worry too much about moving platforms until you get this working, and more importantly, you understand it.
Well, obj_wall_parent has children: obj_wall, obj_wallp
And these wall and wallp objects don't have any childrens.
I pasted your code to enemy object, well global.grav does not exist in my code so I just did grav = 0.1; And the enemy still falls through wallp
UPD: But the collision with obj_wall works o_O
UPD1: That was because of obj_platform mask changing code.
UPD2: Now it works as it should ;D FINALLY!!!!!! Now I should somehow edit your code to make it work in moving platforms.
 
Last edited by a moderator:

Slyddar

Member
Here's a project that has an enemy and the 2 platforms, as well as a jump block, so when the enemy touches it he jumps. This might help you to find your error.

Also note the platform collision was missing a check to ensure objects can jump half way through them and still fall, I've changed my code above, and in this demo to reflect that.

https://ufile.io/z5tx1
 
Last edited:
T

tijeseffff

Guest
If you have a script that checks the ground, you need to ensure it is checking with the parent object.
? With your collision code obj_player can't jump from the platform. I will fix that later, because I am at school right now.
 
T

tijeseffff

Guest
If you have a script that checks the ground, you need to ensure it is checking with the parent object.
I found my error. In the jump code I was checking obj_wall (not the parent) fixed. Now there are 2 probs.
This code is not working w/ moving platforms
I can't use key_down (well I tried, in the obj_wallp step event)
if (instance_exists(obj_player)) and (place_meeting(x,y+1,obj_wallp))
{
if (key_down) obj_wallp.mask_index = -1;
}
Does not work, but it should.
 

Slyddar

Member
Let me be clear. STOP HIDING THE MASK! It's a bad method. If you hide it the enemy will once again fall through the platform.

The code below will enable the player to fall through a platform. How it works is if we are not in a collision, but there is a platform below us, move down 1 pixel. This will mean the player will be inside a platform, which according to the collision code, means he will fall through it.
Code:
if keyboard_check_pressed(vk_down) {
    if !place_meeting(x, y, obj_wall_parent) and place_meeting(x, y + 1, obj_wallp) y+=1;
}
 
T

tijeseffff

Guest
Let me be clear. STOP HIDING THE MASK! It's a bad method. If you hide it the enemy will once again fall through the platform.

The code below will enable the player to fall through a platform. How it works is if we are not in a collision, but there is a platform below us, move down 1 pixel. This will mean the player will be inside a platform, which according to the collision code, means he will fall through it.
Code:
if keyboard_check_pressed(vk_down) {
    if !place_meeting(x, y, obj_wall_parent) and place_meeting(x, y + 1, obj_wallp) y+=1;
}
Okay, I got it. Now I will try to make it work with moving platforms.
Do you have a PayPal? I can donate to you :oops:
 
T

tijeseffff

Guest
YAY! I did it MYSELF! Now it works with moving platforms (still need to edit key_down code but it works)
You are the best guy I've ever seen!
//obj_wallm is the moving platform
if (place_meeting(x, y + vsp, obj_wall) and !place_meeting(x, y + vsp, obj_wallp)) or
((place_meeting(x, y + vsp, obj_wallp) and vsp > 0) and !place_meeting(x, y, obj_wallp)) or
((place_meeting(x, y + vsp, obj_wallm)) and !place_meeting(x, y, obj_wallp) and !place_meeting(x, y, obj_wall))
{
while !place_meeting(x, y + sign(vsp), obj_wall_parent) {
y += sign(vsp);
}
vsp = 0;
}
y += vsp;
Hacky, but it works.
 
T

tijeseffff

Guest
Congrats mate. Probably the longest support thread I've helped in. lol.
No need to Paypal, but you might benefit from the Gamemaker course in my sig if you like. Either way, good you kept at it. Keep learning!
Ok, so I changed code a little bit so it looks more beautiful. Now it's time to get back "fearofheights" to the enemy object and build my game for android.
How to close the thread? I can't see a button, I am familiar with XenForo forum engine. But I can't find that button.
PS: Downloading TWOS into my phone.
 
Top