• 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!

Animations - So close, yet so far!

M

Mili90

Guest
Hello everyone!

This is my first post on here and I'm quite a beginner so I apologise if I make some total schoolboy errors.

Here's my situation. I've managed to make my main character walk up, down, left, right and diagonally too. Perfect.

However, what I want to do now (and I've posted this on Reddit as well) is to make my character stop when two opposite buttons have been pressed (e.g. the up button and then the down button). When I start walking, let's say left, and then I press the right button, my character stops and faces the original direction he was walking in (left in this case). That's totally good.

But here's the major problem. When I let go of the right button to carry on moving left, my character only moves one pixel to the left and doesn't continue moving left like I'd like him too. However, if I let go of the left key and then start moving right, he happily goes to the right.

Here's my code (and just for the record, I think I've made things a little bit too complicated in the coding so I totally apologise. If anyone can give me any pointers on how to shorten the code or make it more simple, that'd be lovely! Finally, if someone needs a video of my problem, I'll try send one in this thread).


//Set direction to "None" if keys are not pressed
if(Direction = "Right") && (!keyboard_check(vk_right)) || (Direction = "Right") && (keyboard_check (vk_right)) && (!keyboard_lastkey = vk_left)
Direction = "None"
if(Direction = "Up") && (!keyboard_check(vk_up)) || (Direction = "Up") && (keyboard_check (vk_up)) && (keyboard_lastkey = vk_down)
Direction = "None"
if(Direction = "Down") && (!keyboard_check(vk_down)) || (Direction = "Down") && (keyboard_check (vk_down)) && (keyboard_lastkey = vk_up)
Direction = "None"
if(Direction = "Left") && (!keyboard_check(vk_left)) || (Direction = "Left") && (keyboard_check (vk_left)) && (keyboard_lastkey = vk_right)
Direction = "None"

//Move Down
if (keyboard_check(vk_down)) && (place_free(x, y+2))
{
vspeed +=3
if(Direction = "None")
{
sprite_index = spr_rundwn
Direction = "Down"
}
}

//Move Up
if (keyboard_check(vk_up)) && (place_free(x, y-2))
{
vspeed -=3
if(Direction = "None")
{
sprite_index = spr_runup
Direction = "Up"
}
}

//Move Left
if (keyboard_check(vk_left)) && (place_free(x-2, y))
{
hspeed -=3
if(Direction = "None")
{
sprite_index = spr_runlft
Direction = "Left"
}
}

//Move Right
if (keyboard_check(vk_right)) && (place_free(x+2, y))
{
hspeed +=3
if(Direction = "None")
{
sprite_index = spr_runrgt
Direction = "Right"
}
}

//Stop Animations
if (!keyboard_check (vk_down)) && (!keyboard_check (vk_up)) && (!keyboard_check (vk_left)) && (!keyboard_check (vk_right))
{
if (sprite_index = spr_rundwn)
sprite_index = spr_lookdwn

if (sprite_index = spr_runup)
sprite_index = spr_lookup

if (sprite_index = spr_runlft)
sprite_index = spr_looklft

if (sprite_index = spr_runrgt)
sprite_index = spr_lookrgt
}

//Opposite Keys (Down First)

if (keyboard_check (vk_down)) && (keyboard_lastkey = vk_up)
{
Direction = "None"
speed = 0
sprite_index = spr_lookdwn


if (keyboard_check_released (vk_up)) && (keyboard_check(vk_down))
{
vspeed +=3
sprite_index = spr_rundwn
Direction = "Down"
}
}

//Opposite Keys (Up First)

if (keyboard_check (vk_up)) && (keyboard_lastkey = vk_down)
{
Direction = "None"
speed = 0
sprite_index = spr_lookup


if (keyboard_check_released (vk_down)) && (keyboard_check(vk_up))
{
vspeed -=3
sprite_index = spr_runup
Direction = "Up"
}
}

//Opposite Keys (Left First)

if (keyboard_check (vk_left)) && (keyboard_lastkey = vk_right)
{
Direction = "None"
speed = 0
sprite_index = spr_looklft


if (keyboard_check_released (vk_right)) && (keyboard_check(vk_left))
{
hspeed -=3
sprite_index = spr_runlft
Direction = "Left"
}
}

//Opposite Keys (Right First)

if (keyboard_check (vk_right)) && (keyboard_lastkey = vk_left)
{
Direction = "None"
speed = 0
sprite_index = spr_lookrgt


if (keyboard_check_released (vk_left)) && (keyboard_check(vk_right))
{
hspeed +=3
sprite_index = spr_runrgt
Direction = "Right"
}
}

//Other

if (speed>6) speed=6

x=min(x,room_width-32);
x=max(x,0);
y=min(y,room_height-32);
y=max(y,0);
 
R

rui.rosario

Guest
I'll be honest, I think you overcomplicated your code. I didn't understand most of it, but from what I understood you wanted something along the lines of:

Code:
// Check directions
var hDir = 0;
var vDir = 0;

// Horizontal Motion
if (keyboard_check(vk_right)) hDir++;
if (keyboard_check(vk_left))  hDir--;

// Vertical Motion
if (keyboard_check(vk_up))   vDir--;
if (keyboard_check(vk_down)) vDir++;

// Set direction to none on no keys pressed
if (hDir == 0 && vDir == 0) {
  Direction = "None";
  speed = 0;
  switch (sprite_index) {
    case spr_rundwn:
      sprite_index = spr_lookdwn;
      break;

    case spr_runup:
      sprite_index = spr_lookup;
      break;

    case spr_runrgt:
      sprite_index = spr_lookrgt;
      break;

    case spr_runlft:
      sprite_index = spr_looklft;
      break;
  }
}

// Move vertically
if (vDir != 0 && place_free(x, y + vDir * 2)) {
  vspeed += vDir * 3;
  if (Direction == "None") {
    if (vDir > 0) {
      sprite_index = spr_rundwn;
      Direction = "Down";
    } else {
      sprite_index = spr_runup;
      Direction = "Up";
    }
  }
}

// Move horizontally
if (hDir != 0 && place_free(x + hDir * 2, y)) {
  hspeed += hDir * 3;
  if (Direction == "None") {
    if (hDir > 0) {
      sprite_index = spr_runrgt;
      Direction = "Right";
    } else {
      sprite_index = spr_runlft;
      Direction = "Left";
    }
  }
}

// Speed and position cap
speed = clamp(speed, -6, 6); // Both positive and negative cap, you only had positive cap

x = clamp(x, 0, room_width - 32);
y = clamp(y, 0, room_height - 32);
This code was hacked from your original code, it may not do what you want or solve your problem, but hopefully it can help you identify a thing or two in your code that may be causing it.

EDIT: Fixed some things on the code

Also, you check for free position 2 px apart, but you increase the speed by 3, is that what you intended?
 
M

Mili90

Guest
Thank you for your reply! I've tried the code and it's fixed the problem of pressing two opposite buttons at the same time but now the problem is that when I move diagonally, my character keeps on looking in the same direction. So, if I start running left (for example), my character looks to the left, which is good. If I then press up while pressing left, I start moving diagonally (which is also good). But if I then let go of the left button and just hold the up button, I move up but my character's run animation is still left (and it's the same if I then press the right button and the down button).

Any ideas? If you would like, maybe I can send you my gmx file and you can have a quick look?
 
R

rui.rosario

Guest
Maybe adapt the movement part to something like:

Code:
// Move vertically
if (vDir != 0 && place_free(x, y + vDir * 2)) {
  vspeed += vDir * 3;
  if (Direction == "None" || hDir == 0) {
    if (vDir > 0) {
      sprite_index = spr_rundwn;
      Direction = "Down";
    } else {
      sprite_index = spr_runup;
      Direction = "Up";
    }
  }
}

// Move horizontally
if (hDir != 0 && place_free(x + hDir * 2, y)) {
  hspeed += hDir * 3;
  if (Direction == "None" || vDir == 0) {
    if (hDir > 0) {
      sprite_index = spr_runrgt;
      Direction = "Right";
    } else {
      sprite_index = spr_runlft;
      Direction = "Left";
    }
  }
}
I wouldn't be able to open the GMX file, I'm on my work PC so I don't have GM:S installed.
 

jo-thijs

Member
Hi and welcome to the GMC!

I was writing a response, butrui.rosario beat me to it.
Though, he did not offer an explenation as to what in your code went wrong,
so I decided to still post this.

Reading through your code, I'm thinking you misinterprete what keyboard_lastkey does.
keyboard_lastkey does not return what the last pressed key was,
but what key was pressed in the previous step, just like xprevious works.

You've also made this odd construction:
!keyboard_lastkey = vk_left

I'm guessing the exclemation mark is a typo there,
but it makes the expression equivalent to:
(not keyboard_lastkey) == vk_left
which is always false.

You don't do this in the next lines, which might explain the different behaviour in different directions.

I've also noticed that you use place_free, which means you use solids.
Using solids is bad practice, they often cause problems in the long run.

If you can easily get rid of solids n your game, I would advice to do so.
Now, as to rewriting your code, here is a tidied up version:
Code:
//Set direction to "None" if keys are not pressed
if Direction == "Right" && (!keyboard_check(vk_right) || (keyboard_check(vk_right) && keyboard_lastkey == vk_left))
    Direction = "None";
if Direction == "Up" && (!keyboard_check(vk_up) || (keyboard_check(vk_up) && keyboard_lastkey == vk_down))
    Direction = "None";
if Direction == "Down" && (!keyboard_check(vk_down) || (keyboard_check(vk_down) && keyboard_lastkey == vk_up))
    Direction = "None";
if Direction == "Left" && (!keyboard_check(vk_left) || (keyboard_check(vk_left) && keyboard_lastkey == vk_right))
    Direction = "None";

//Move Down
if keyboard_check(vk_down) && place_free(x, y + 2) {
    vspeed += 3;
    if Direction == "None" {
        sprite_index = spr_rundwn;
        Direction = "Down";
    }
}

//Move Up
if keyboard_check(vk_up) && place_free(x, y - 2) {
    vspeed -= 3;
    if Direction == "None" {
        sprite_index = spr_runup;
        Direction = "Up";
    }
}

//Move Left
if keyboard_check(vk_left) && place_free(x - 2, y) {
    hspeed -= 3;
    if Direction == "None" {
        sprite_index = spr_runlft;
        Direction = "Left";
    }
}

//Move Right
if keyboard_check(vk_right) && place_free(x + 2, y) {
    hspeed += 3;
    if Direction == "None" {
        sprite_index = spr_runrgt;
        Direction = "Right";
    }
}

//Stop Animations
if !keyboard_check(vk_down) && !keyboard_check(vk_up) && !keyboard_check(vk_left) && !keyboard_check(vk_right) {
    if sprite_index == spr_rundwn
        sprite_index = spr_lookdwn;
   
    if sprite_index == spr_runup
        sprite_index = spr_lookup;
   
    if sprite_index == spr_runlft
        sprite_index = spr_looklft;
   
    if sprite_index == spr_runrgt
        sprite_index = spr_lookrgt;
}

//Opposite Keys (Down First)
if keyboard_check(vk_down) && keyboard_lastkey == vk_up {
    Direction = "None";
    speed = 0;
    sprite_index = spr_lookdwn;
   
    if keyboard_check_released(vk_up) && keyboard_check(vk_down) {
        vspeed += 3;
        sprite_index = spr_rundwn;
        Direction = "Down";
    }
}

//Opposite Keys (Up First)
if keyboard_check(vk_up) && keyboard_lastkey == vk_down {
    Direction = "None";
    speed = 0;
    sprite_index = spr_lookup;
   
    if keyboard_check_released(vk_down) && keyboard_check(vk_up) {
        vspeed -= 3;
        sprite_index = spr_runup;
        Direction = "Up";
    }
}

//Opposite Keys (Left First)
if keyboard_check(vk_left) && keyboard_lastkey == vk_right {
    Direction = "None";
    speed = 0;
    sprite_index = spr_looklft;
   
    if keyboard_check_released(vk_right) && keyboard_check(vk_left) {
        hspeed -= 3;
        sprite_index = spr_runlft;
        Direction = "Left";
    }
}

//Opposite Keys (Right First)
if keyboard_check (vk_right) && keyboard_lastkey == vk_left {
    Direction = "None";
    speed = 0;
    sprite_index = spr_lookrgt;
   
    if keyboard_check_released(vk_left) && keyboard_check(vk_right) {
        hspeed += 3;
        sprite_index = spr_runrgt;
        Direction = "Right";
    }
}

//Other
if speed > 6
    speed = 6;

x = clamp(x, 0, room_width - 32);
y = clamp(y, 0, room_height - 32);
And here is a version I'd suggest you'd use:
(did not get to this in time)
 
M

Mili90

Guest
jo-thijs, I've almost cracked it! I understand (at least I have a basic understanding) about the keyboard_lastkey stuff. I've altered the code now and now we're super duper close!

//Opposite Keys (Down First)
if keyboard_check(vk_down) && keyboard_check(vk_up) {

if keyboard_lastkey = vk_up{

Direction = "None";
sprite_index = spr_lookdwn;
}

if keyboard_lastkey = vk_down
{
Direction = "Down";
sprite_index = spr_rundwn;
}
}

//Opposite Keys (Up First)
if keyboard_check(vk_up) && keyboard_check(vk_down) {
if keyboard_lastkey = vk_down{

Direction = "None";
sprite_index = spr_lookup;
}

if keyboard_lastkey = vk_up
{
Direction = "Up";
sprite_index = spr_runup;
}
}

//Opposite Keys (Left First)
if keyboard_check(vk_left) && keyboard_check(vk_right) {
if keyboard_lastkey = vk_right{

Direction = "None";
sprite_index = spr_looklft;
}

if keyboard_lastkey = vk_left
{
Direction = "Left";
sprite_index = spr_runlft;
}
}

//Opposite Keys (Right First)
if keyboard_check(vk_right) && keyboard_check(vk_left) {
if keyboard_lastkey = vk_left{

Direction = "None";
sprite_index = spr_lookrgt;
}

if keyboard_lastkey = vk_right
{
Direction = "Right";
sprite_index = spr_runrgt;
}
}


When I run to the right and then press left, my character stops and carries on looking to the right. When I let go of the left key, he continues running. This is the same with holding the up button and then pressing . So two of them work perfectly.

Unfortunately, if I do the same thing with the down button (and then press the up button) or press the left button (and then the right button), the character turns around in the opposite direction. So when I'm holding down the left button and then I press the right button, my character turns to the right instead of staying to the left.

It is like the right and up buttons are "dominant". I can see something is wrong with my code but I'm not 100% what right now. It's getting late here in China! Any ideas would be wonderful. Thank you!
 
M

Mili90

Guest
I've done it! I've fixed it! I'd like to thank you both for all our help. I'm going to post my code beneath and just explain what happened and what I've got the code to do now.

Code:
//Opposite Keys (Y Axis)

if keyboard_check(vk_down) && keyboard_check(vk_up) {
   
if keyboard_lastkey = vk_up{

    Direction = "None";
    sprite_index = spr_lookdwn;
    }
else if keyboard_lastkey = vk_down
    {
    Direction = "None";
    sprite_index = spr_lookup;
    }
}

//Opposite Keys (X Axis)

if keyboard_check(vk_left) && keyboard_check(vk_right) {
   
if keyboard_lastkey = vk_left{

    Direction = "None";
    sprite_index = spr_lookrgt;
    }
else if keyboard_lastkey = vk_right
    {
    Direction = "None";
    sprite_index = spr_looklft;
    }

So, I've only got two blocks of code that determine whether two buttons are being pressed at the same time. One is for the Y axis and for the X axis. I've just used an if else statement to tell the code how to stop and start.

Again, thank you both for your help!
 
Top