Legacy GM Diagonal Movement (8 Way)

F

Frisk2401

Guest
I would like to be able to make diagonal movement. Here is my code so far.
Event Left Key:
if global.canmove=true
{
direction=180
sprite_index=spr_chara_left
speed=5
if(keyboard_check_pressed(vk_left)){
{hspeed=-p_speed}
}
}


Event Up Key:
if global.canmove=true
{
direction=90
sprite_index=spr_chara_up
speed=5
if(keyboard_check_pressed(vk_up)){
{vspeed=-p_speed}
}
}


Event Right Key:
if global.canmove=true
{
direction=0
sprite_index=spr_chara_right
speed=5
if(keyboard_check_pressed(vk_right)){
{hspeed=p_speed}
}
}


Event Down Key:
if global.canmove=true
{
direction=270
sprite_index=spr_chara_down
speed=5
if(keyboard_check_pressed(vk_down)){
{vspeed=p_speed}
}
}
 
Last edited by a moderator:
J

JON213

Guest
This should give you 8 directional movement
Create
Xsp=0
Ysp=0
Movespeed=5
Step
Var vinput = keyboard_check(vk_down)-keyboard_check(vk_up)
Var hinput = keyboard_check(vk_right)-keyboard_check(vk_left)
Ysp=vinput*movespeed
Xsp=hinput*movespeed
X+=xsp
Y+=ysp
 
A

Annoyed Grunt

Guest
Bear with me for a moment, but do you understand your code? Because you are already very close to having eight-way movement implemented, but a single issue in your code stops you in your tracks. Considering a single event, let's say Left Key, it's only 6 effective lines of code, do you know what each one of them does? If you don't, can you provide your most educated guess? Because if you think about it for a bit you should be able to arrive to it. If not, we can get to it together.

This should give you 8 directional movement
Create
Xsp=0
Ysp=0
Movespeed=5
Step
Var vinput = keyboard_check(vk_down)-keyboard_check(vk_up)
Var hinput = keyboard_check(vk_right)-keyboard_check(vk_left)
Ysp=vinput*movespeed
Xsp=hinput*movespeed
X+=xsp
Y+=ysp
While this code works, in a vacuum, it completely ignores the current implementation (which is based on built-in speed variables and key events) and as such it's not really that advisable.
 
F

Frisk2401

Guest
Bear with me for a moment, but do you understand your code? Because you are already very close to having eight-way movement implemented, but a single issue in your code stops you in your tracks. Considering a single event, let's say Left Key, it's only 6 effective lines of code, do you know what each one of them does? If you don't, can you provide your most educated guess? Because if you think about it for a bit you should be able to arrive to it. If not, we can get to it together.



While this code works, in a vacuum, it completely ignores the current implementation (which is based on built-in speed variables and key events) and as such it's not really that advisable.
Yes, I do know what it does. I'm just not too good at maths and such, so it's hard for me to do the * and /... I'll keep trying
 
A

Annoyed Grunt

Guest
Yes, I do know what it does. I'm just not too good at maths and such, so it's hard for me to do the * and /...
The problem is not with the maths, so rest easy on that, the issue is rather in the order (and nature) of instructions, which is why I encourage you to consider the code line by line.
 
F

Frisk2401

Guest
The problem is not with the maths, so rest easy on that, the issue is rather in the order (and nature) of instructions, which is why I encourage you to consider the code line by line.
Alright.. It's just I've been trying to do this for a while and I'm quite new to this whole gamemaker language.. it's been getting on my nerves that I can't figure it out. Which is why'd I'd appreciate help..
 
A

Annoyed Grunt

Guest
Alright.. It's just I've been trying to do this for a while and I'm quite new to this whole gamemaker language.. it's been getting on my nerves that I can't figure it out.
Alright, I suggest you try to figure it out by yourself one last time with one hint: in each event you set the speed twice. Ask yourself why and if it is necessary. If you still can't figure it out I'll explain it to you in long form. Figuring things out by yourself usually is better for learning, but sometimes they are out of one's grasp and that's ok, that's why we inventend the internet.
 
F

Frisk2401

Guest
Alright, I suggest you try to figure it out by yourself one last time with one hint: in each event you set the speed twice. Ask yourself why and if it is necessary. If you still can't figure it out I'll explain it to you in long form. Figuring things out by yourself usually is better for learning, but sometimes they are out of one's grasp and that's ok, that's why we inventend the internet.
Oh, I actually didn't realize I did that! When I remove one of them it only works when I tap it- Wait.. Am I using the wrong check? Edit: Yep.. I was
 

FrostyCat

Redemption Seeker
The code on this topic has basically the same problem as the code from this other topic. Each of these input actions completely negates the effect of all others without ever letting them combine, and that's a common rookie problem. The code should be replaced with an alternative that allows input to be combined, such as this:

Step:
Code:
var dx = keyboard_check(vk_right)-keyboard_check(vk_left);
var dy = keyboard_check(vk_down)-keyboard_check(vk_up);
if (dx != 0 || dy != 0) {
  direction = point_direction(0, 0, dx, dy);
  speed = 5;
} else {
  speed = 0;
}
The next time you do 8-directional movement or anything else where multiple influences cross-interact, do not code it in a way where a single influence can completely override all others. Let them cross-interact first, then operate on the net result.
 
F

Frisk2401

Guest
The code on this topic has basically the same problem as the code from this other topic. Each of these input actions completely negates the effect of all others without ever letting them combine, and that's a common rookie problem. The code should be replaced with an alternative that allows input to be combined, such as this:

Step:
Code:
var dx = keyboard_check(vk_right)-keyboard_check(vk_left);
var dy = keyboard_check(vk_down)-keyboard_check(vk_up);
if (dx != 0 || dy != 0) {
  direction = point_direction(0, 0, dx, dy);
  speed = 5;
} else {
  speed = 0;
}
The next time you do 8-directional movement or anything else where multiple influences cross-interact, do not code it in a way where a single influence can completely override all others. Let them cross-interact first, then operate on the net result.
well, thank you for the help, but i'd rather work it out step by step, i didn't really learn anything from that-
 
F

Frisk2401

Guest
Alright, I suggest you try to figure it out by yourself one last time with one hint: in each event you set the speed twice. Ask yourself why and if it is necessary. If you still can't figure it out I'll explain it to you in long form. Figuring things out by yourself usually is better for learning, but sometimes they are out of one's grasp and that's ok, that's why we inventend the internet.
taking from what frostycat said, I need to make the movement code all in the same thing?
 
A

Annoyed Grunt

Guest


GM offers two ways of handling the speed of an instance: either a combination of speed + direction, or horizontal speed + vertical speed. Setting the hspeed or vspeed changes speed and direction, and viceversa.
Basically, you can either tell the instance "move *speed* amount of units in a specific *direction*", or "move first *hspeed* units horizontally and then *vspeed* units vertically".
The first error in your code is that you first set the speed and direction and then you set the singular axes. You either do one or the other.
The second error is that there is no reason to check for keypresses in a key event, the event itself is the check! It only happens if they key is held down.

Now what you could do is get rid of the speed+direction and only use hspeed and vspeed. Since you can set the axes independently, this will automatically give you 8-way movement, because as you can see from the image above hspeed and vspeed combine to form the "speed" in a 45° angle is they are the same length.

However this would create yet another problem! You would move faster when you go diagonally. This is because of maths but you can see it clearly from the image itself: the red diagonal arrow that is the sum of the blue arrows is longer than the blue arrows.

The way frostycat uses is best because he calculates the direction considering both your horizontal and vertical keypresses (currently your keypresses override each other, so only one "wins" in the end) and still allows for 8-way movement.

You could implement 8-way movement without putting everything into the step event but the way frostycat uses is considerably simpler and more efficient.
 

FrostyCat

Redemption Seeker
well, thank you for the help, but i'd rather work it out step by step, i didn't really learn anything from that-
You learned nothing exactly because you didn't work it out step by step.

For example, consider what would happen on the line var dx = keyboard_check(vk_right)-keyboard_check(vk_left); in these 4 cases:
  • Neither left nor right key
  • Left key only
  • Right key only
  • Left and right key
Recall that keyboard_check() would return 1 when the key is held down and 0 when the key is not. dx would get a value of -1, 0 or 1. A similar effect happens on the line after. And once you look up what point_direction() does, you should understand all there is to know about the code I posted.

By the way, the code I posted has been more or less a standard solution for more than a decade. Part of learning how to code is knowing what the stock solutions are and when and how to apply them. Reinventing the wheel isn't a good way to show your expertise, getting stuff to work is.

taking from what frostycat said, I need to make the movement code all in the same thing?
If you insist on using speed and not being 40% something faster when moving diagonally, the best way is to combine the inputs in the Step event. But if you remove that constraint, it's trivial to see how you can keep the keys in separate events.

As an example, here's what you would have gotten off a pre-YouTube era tutorial on 8-directional movement:

Left key:
Code:
x -= 5;
Right key:
Code:
x += 5;
Up key:
Code:
y -= 5;
Down key:
Code:
y += 5;
Notice that all of these operate as relative influences on the current position, not absolute authorities on the direction. The principle of operating on net results over absolute cases still holds.
 
F

Frisk2401

Guest
I know I should be using some stock solutions, I just felt like I'd learn more if I figured out my own way. I understand how stupid that sounds now.
 
F

Frisk2401

Guest
You learned nothing exactly because you didn't work it out step by step.

For example, consider what would happen on the line var dx = keyboard_check(vk_right)-keyboard_check(vk_left); in these 4 cases:
  • Neither left nor right key
  • Left key only
  • Right key only
  • Left and right key
Recall that keyboard_check() would return 1 when the key is held down and 0 when the key is not. dx would get a value of -1, 0 or 1. A similar effect happens on the line after. And once you look up what point_direction() does, you should understand all there is to know about the code I posted.

By the way, the code I posted has been more or less a standard solution for more than a decade. Part of learning how to code is knowing what the stock solutions are and when and how to apply them. Reinventing the wheel isn't a good way to show your expertise, getting stuff to work is.


If you insist on using speed and not being 40% something faster when moving diagonally, the best way is to combine the inputs in the Step event. But if you remove that constraint, it's trivial to see how you can keep the keys in separate events.

As an example, here's what you would have gotten off a pre-YouTube era tutorial on 8-directional movement:

Left key:
Code:
x -= 5;
Right key:
Code:
x += 5;
Up key:
Code:
y -= 5;
Down key:
Code:
y += 5;
Notice that all of these operate as relative influences on the current position, not absolute authorities on the direction. The principle of operating on net results over absolute cases still holds.
I implemented it, but yet now there's a bug but I fixed that. Also, I'm sorry if I come off as rude...
 
Last edited by a moderator:
Top