I'm somewhat of a beginner when it comes to programming and lately I've been coding a game for a school project in GameMaker Studio: Professional and have run into a small problem in terms of my player landing on top of another enemy. As it is now my player when at a high enough downward velocity will not register as to landing on and destroying the instance of the enemy and instead just get hurt (or the game will restart because I haven't implemented that part yet). Have tested a couple things and it seems that with the higher velocity the player skips over the range at which it can destroy the enemy and instead passes into the vicinity of the enemy to get hurt, though at slow speeds the player collides with the enemy just fine. The player jumps at a variable height that is controlled by the amount of time that they hold the spacebar. I believe it may be due to my gravity value as it is not a whole number but am not sure. I have also tried adding a terminal velocity to the player, but the numbers I have tried that still maintain the same game aesthetic have not solved this problem.
Here is the code for both my player object and enemy object: Player object:
Create Event:
execute code:
hsp = 0
vsp = 0
grav = 1.5
movespeed = 8
move = 0
jumpsmax = 2
jumps = 0
jumpspeed = 18
dir = 0
Step Event:
execute code:
//Movement
//Main controls
key_right = keyboard_check(ord("D"));
key_left = keyboard_check(ord("A")) * -1;
key_jump = keyboard_check_pressed(vk_space);
key_jump_held = keyboard_check(vk_space);
move = key_left + key_right;
hsp = move * movespeed;
vsp += grav;
if (place_meeting(x,y+1,obj_wall))
{
jumps = jumpsmax;
}
if (keyboard_check(vk_down) != 1)
{
if (key_jump) && (jumps > 0)
{
jumps -= 1;
vsp = -jumpspeed;
}
}
if (vsp < 0) && (!key_jump_held) vsp = max(vsp,-jumpspeed/3)
//Horizontal Collision
if (place_meeting(x+hsp,y,obj_wall))
{
while(!place_meeting(x+sign(hsp),y,obj_wall))
{
x += sign(hsp);
}
hsp = 0;
}
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;
}
y += vsp;
//Shooting
key_k = keyboard_check_pressed(ord("K"))
if (key_k > 0)
{
bullet = instance_create(x+5*move,y,obj_pellet);
bullet.hsp = image_xscale * 20;
}
//Animation
if (move!=0) image_xscale= move;
dir = image_xscale;
if (place_meeting(x,y+1,obj_wall))
{
if (move != 0)
{
sprite_index = spr_playerwalk;
}
else
{
sprite_index = spr_playeridle;
}
}
if (vsp = -18) sprite_index = spr_playerjump;
if (sprite_index = spr_playerjump) && (image_index = 11) sprite_index = spr_playerrise;
if (vsp = 1.5) sprite_index = spr_playerfall;
if (sprite_index = spr_playerfall) && (image_index = 11) sprite_index = spr_playerdescend;
//Bullet Collision
if (place_meeting(x,y,obj_badpellet))
{
with (obj_badpellet)
{
if (place_meeting(x +- 2,y,obj_player))
{
game_restart();
}
}
instance_destroy();
}
restart = keyboard_check(ord("R"))
if (restart = 1) game_restart();
Enemy Object:
execute code:
dir = 1;
hsp = 0;
vsp = 0;
grav = 0.8;
movespeed = 3;
Step Event:
execute code:
hsp = dir * movespeed;
vsp += grav;
image_xscale = dir * -1;
//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;
}
y += vsp;
//Enemy Collison
if (place_meeting(x,y,obj_player))
{
if (obj_player.y < y-16)
{
with (obj_player) vsp = -jumpspeed;
instance_destroy();
}
else
{
game_restart();
}
}
if (place_meeting(x,y,obj_pellet))
{
with (obj_pellet)
{
if (place_meeting(x,y,obj_enemy))
{
instance_destroy();
}
}
instance_destroy();
}
if (place_meeting(x,y,obj_badpellet))
{
with (obj_badpellet)
{
if (place_meeting(x,y,obj_enemy))
{
instance_destroy();
}
}
instance_destroy();
}
Looks like your problem is that when the player hits the enemy, it is too far into it to register as hitting it on the top.
It's difficult to give you an answer that will cover every eventuality but a simple fix would be:
if (obj_player.vsp > 0 and obj_player.y - obj_player.vsp < y-16)
{
with (obj_player) vsp = -jumpspeed;
instance_destroy();
}
What I am doing here is checking that the player is falling, and then checking if the player was above the enemy in the previous step (ie. before the collision occurred). This will distinguish between falling onto the enemy from above and coming in from the side.