GameMaker Need help: strange keyboard_check issue

L

LCM

Guest
So I've started creating my first game, a really basic platformer, and I implemented all the basic movement functions (dash, double jump and walljump).
Everything worked fine, so I started coding a pause menu. When I finished it, I ran the game to check if everything was working properly and I noticed that out of nowhere, my wall jump had stopped functioning correctly.

The character still jumps when I press the spacebar, but I had added a few ligns of code so the character would "stick" to the wall for a few frames, allowing the player to press the arrow keys BEFORE the jump key to do a wall jump.
Now the character just remains stuck to the wall until he touches the ground.
here's the code:

CREATE EVENT:

hsp = 0;
vsp = 0;
hsp_frac = 0;
vsp_frac = 0;

hsp_acc = 1;
hsp_fric_ground = 0.50;
hsp_fric_air = 0.15;
movespd = 5;
hsp_wjump = 4;

vsp_jump = -7.5;
vsp_max = 10;
vsp_wjump = -6;
vsp_max_wall = 4;

grv = 0.3;
grv_wall = 0.1;

control = true;

canjump = 0;
walljumpdelay = 0;
walljumpdelay_max = 17;

canstick = true;
stuck = false;
vsppos = false;

dashcount = 1;
dashing = false;

jumpcount = 1;

onground = false;
onwall = 0;

STEP EVENT:

//Player Input

if (control)
{
key_jump = keyboard_check_pressed(vk_space);
key_jump_held = keyboard_check(vk_space);
key_right = keyboard_check(ord("D"));
key_left = keyboard_check(ord("A"));
key_shift = keyboard_check_pressed(vk_shift);
}

if (global.pause = 1) control = false;
else control = true;


//Calculate Horizontal Movement

walljumpdelay = max(walljumpdelay - 1, 0);
if (walljumpdelay == 0) && (!stuck) && (!dashing)
{
var move = key_right - key_left;

hsp += move * hsp_acc;

if(move == 0)
{
var hsp_fric_final = hsp_fric_ground;
if(!onground) hsp_fric_final = hsp_fric_air
hsp = Approach(hsp, 0, hsp_fric_final);
}
hsp = clamp(hsp, -movespd, movespd);
}


//Gravity

var grv_final = grv;
var vsp_max_final = vsp_max;
if (onwall != 0) && (vsp > 0)
{
grv_final = grv_wall
vsp_max_final = vsp_max_wall;
}

if (!dashing)
{
vsp += grv_final;
vsp = clamp(vsp, -vsp_max_final, vsp_max_final)
}


//Calculate Status

onground = place_meeting(x, y + 1, obj_Wall);
onwall = place_meeting(x + 1, y, obj_Wall) - place_meeting(x - 1, y, obj_Wall);


//Jumping

canjump -= 1

if (onground)
{
canjump = 10;
}

if (canjump > 0) && (key_jump)
{
canjump = 0;
vsp = vsp_jump;
vsp_frac = 0;
}

vsp = clamp(vsp, -vsp_max, vsp_max);

if (vsp < 0) && (!key_jump_held) vsp = max(vsp, 0);


//WallJump

if (onwall != 0) && (!onground) && (key_jump)
{
walljumpdelay = walljumpdelay_max;

hsp = -onwall * hsp_wjump;
vsp = vsp_wjump;

hsp_frac = 0;
vsp_frac = 0;
}


//AirJump

if (!place_meeting(x, y + 1, obj_Wall)) && (key_jump) && (jumpcount = 1) && (canjump < 0) && (!stuck)
{
vsp = vsp_jump;
jumpcount -= 1;
vsp_frac = 0;
}

if (onground) || (onwall != 0)
{
jumpcount = 1;
}


//StickyWall

if (onground) || (onwall = 0)
{
canstick = true;
stuck = false;
}

if(sign(vsp) != 0)
{
if (sign(vsp) = 1) vsppos = true;
else if (sign(vsp) = -1) vsppos = false;
}

if (onwall != 0) && (canstick) && (!onground) && (vsppos)
{
stuck = true;
canstick = false;
if ((onwall = -1) && (key_right)) || ((onwall = 1) && (key_left))
{
alarm[0] = 14;
}
}


//Dashing

if (onground) || (onwall != 0) dashcount = 1;

if (dashcount >= 1) && (key_shift) && ((key_right) || (key_left))
{
if (key_right)
{
dashcount -= 1;
dashing = true;
hsp = 18;
vsp = 0;
alarm[1] = 10;
}
if (key_left)
{
dashcount -= 1;
dashing = true;
hsp = -18;
vsp = 0;
alarm[1] = 10;
}
}

if (dashing)
{
if (key_jump) && (jumpcount >= 1)
{
vsp = vsp_jump;
vsp_frac = 0;
hsp_frac = 0;
dashing = false
jumpcount -= 1;
}

if (hsp = 0) dashing = false;
}



//Dump Fractions and get final integer speed

hsp += hsp_frac;
vsp += vsp_frac;
hsp_frac = frac(hsp);
vsp_frac = frac(vsp);
hsp -= hsp_frac;
vsp -= vsp_frac;


//WallJump - Dust

if(!onground)
{
if(onwall != 0)
{
var side = bbox_left;

if (onwall == 1) side = bbox_right;

dust++;

if((dust > 2) && (vsp >0)) with (instance_create_layer(side, bbox_top, "Effects", obj_Dust))
{
other.dust = 0;
hspeed = other.onwall * 0.5;
}
}
else
{
dust = -10;
}
}

//Horizontal Collision

if (place_meeting(x + hsp, y, obj_Wall))
{
while (!place_meeting(x + sign(hsp), y, obj_Wall))
{
x = x + sign(hsp);
}
hsp = 0;
hsp_frac = 0;
}

x += hsp;

//Vertical Collision

if (place_meeting(x, y + vsp, obj_Wall))
{
while (!place_meeting(x, y + sign(vsp), obj_Wall))
{
y = y + sign(vsp);
}
vsp = 0;
vsp_frac = 0;
}

y = y + vsp;

ALARM[1]:

stuck = false;

END



If I delete the (key_right) and (key_left) in the code below, the character is stuck against the wall for 14 frames and can then can move freely, but if I don't, it remains stuck to the wall even when I press my arrow keys

if (onwall != 0) && (canstick) && (!onground) && (vsppos)
{
stuck = true;
canstick = false;
if ((onwall = -1) && (key_right)) || ((onwall = 1) && (key_left))
{
alarm[0] = 14;
}
}

I really don't understand why it's happening so I'd really like help because I'm starting to lose my mind...

Thanks for your time!
 

Nidoking

Member
Is it maybe a failure to set the "stuck" variable back to false when you do the wall-jump? There's a lot there, and you didn't use a Code block to format it readably.
 

Yal

🐧 *penguin noises*
GMC Elder
You keep setting walljumpdelay to the max value each step if there's a wall collision, might that be related?

Also, two strong recommendations: put your code in a code=gml tag so you get proper syntax highlightning, it's really hard to understand as plain text.
GML:
//example(x,y)
return argument0 + argument1*pi;
Also, your player logic might be easier to work with if you convert it into a state machine, with separate states for normal movement, dashing, and wall jumping.
GML:
#macro state_NORMAL 0
#macro state_WALLJUMP 1
#macro state_DASH 2
switch(state){
  case state_NORMAL:
     //most of your current code goes here
  break

  case state_WALLJUMP:
     //checks to leave the walljump state goes here, including the stickiness timer and sliding off the wall
  break

  case state_DASHING:
     //move forward automatically, end after a certain counter expires (which you set when starting a dash and slowly reduce while in a dash)
  break
}
The problem with your current code is that it's a forest of variables that all interact with each other, state machines lets you compartmentalize so your code won't fight itself when you have competing rules (like the rules for normal movement and wall jumps)
 
L

LCM

Guest
Okay, thank you! Will try that right away after learning how it works!
Have any idea why it started "bugging" after I implemented something totally unrelated? Because it's too messy and there's too much to "calculate"?
 

Yal

🐧 *penguin noises*
GMC Elder
Have any idea why it started "bugging" after I implemented something totally unrelated? Because it's too messy and there's too much to "calculate"?
Yeah, that's my guess - though it's more likely it's because your code is so complicated you missed a check somewhere rather than GM being unable to handle it. The harder code is to understand, the easier it is to add new bugs, so always try to keep it simple~
 
L

LCM

Guest
I managed to pinpoint the problem thanks to your advice, thank you so much!
And it's indeed way easier to read and to understand, it'll be a time saver in the future :D
Thanks again!
 
Top