Game Maker Community YoYo Games

Welcome Guest ( Log In | Register )

> Advanced Users Forum Rules

This is a Q&A forum for advanced GML users ONLY. Moderators will remove inappropriate topics. Make sure that you READ these rules prior to posting: Advanced Users Forum Rules

 
Reply to this topicStart new topic
Vector-based Movement Causing Player Speed Issues?, vector addition not allowing for consistent speed
bluesy_92
post Nov 3 2009, 02:30 AM
Post #1


GMC Member
Group Icon

Group: GMC Member
Posts: 8
Joined: 18-August 09
Member No.: 138175



So, i started work on a TDS, and I've made (so far) a movement and shooting system. The problem is, since I wanted to include strafing, I couldn't use direction and speed, so I used vectors. If you press more than one key, the vectors add together, which any mathematician will tell you gets a different length than either of the original vectors, so basically, if the player is strafing while walking forward(or backwards), his speed is FASTER than when he walks straight, not equal or slightly slower, like it should be. I tried using "else" statements, so the player could only hit one direction at a time, but that ruined the fluid feel. I basically need a way to use multiple keys at once, without speeding up my player. Here is the source for my player object (step event)


CODE
//player movement
if keyboard_check (68) direction -=1.5
if keyboard_check (65) direction +=1.5
{
if keyboard_check (87)
{
x += lengthdir_x(2, direction)
y += lengthdir_y(2, direction)
}
if keyboard_check (83)
{
x += lengthdir_x(1.5, direction + 180)
y += lengthdir_y(1.5, direction + 180)
}
if keyboard_check (69)
{
x += lengthdir_x(1.5, direction-90)
y += lengthdir_y(1.5, direction-90)
}
if keyboard_check (81)
{
x += lengthdir_x(1.5, direction+90)
y += lengthdir_y(1.5, direction+90)
}
}
//shooting
if weapon = 1
{
if keyboard_check_pressed(74) and pistol_timer = 0
{
instance_create(x, y, obj_bullet_pistol)
pistol_timer = 20
}
}
if weapon = 2
{
if keyboard_check(74) and mg_timer = 0
{
instance_create(x, y, obj_bullet_mg)
mg_timer = 6
}
}
//weapon timers
if pistol_timer > 0
{
pistol_timer -= 1
}
if mg_timer > 0
{
mg_timer -= 1
}
//weapon switching
if keyboard_check_pressed(90)
{
weapon += 1
}
if weapon = 3
{
weapon = 1
}


Also, I did not implement wall objects, and I never used vectors before, so if collision detection is going to be an issue, or anyone has a better idea for the movement system, I'm open to suggestions.

This post has been edited by bluesy_92: Nov 3 2009, 03:00 AM
Go to the top of the page
 
+Quote Post
Obj_Control
post Nov 3 2009, 03:08 AM
Post #2


GMC Member
Group Icon

Group: GMC Member
Posts: 2100
Joined: 9-November 08
From: Edmonton, AB, Canada
Member No.: 120699



Misunderstood.

This post has been edited by Obj_Control: Nov 4 2009, 12:41 AM
Go to the top of the page
 
+Quote Post
bluesy_92
post Nov 3 2009, 03:20 AM
Post #3


GMC Member
Group Icon

Group: GMC Member
Posts: 8
Joined: 18-August 09
Member No.: 138175



QUOTE (Obj_Control @ Nov 3 2009, 03:08 AM) *
Nothing in this code should slow your game down, the way I see it. Is there anything else of relevance you could show?


It's not slowing the game, it's speeding up the player. Basically, when 2 vectors are added, the value of the original vectors changes, so if I walk forward while strafing, the player moves faster than if he was just walking forward. I would need to find a way to make it the same speed, or slightly slower, if they player strafe-walks instead of strafing/walking by itself.
Go to the top of the page
 
+Quote Post
RandomBlackMage
post Nov 3 2009, 06:10 AM
Post #4


We all look alike
Group Icon

Group: GMC Member
Posts: 289
Joined: 31-December 04
From: Far away from you.
Member No.: 19000



The thing that's going on here is that for each case of the key presses, the x and y variables are being updated immediately for each key. If you want to set a maximum speed, you should have each key allocate a certain amount to temporary x and y values. Then, after all the updates from the controls, check to see if your values exceed the maximum speed and set them accordingly.

Example:
CODE
//player movement
xtemp=0 //Reset for each update.
ytemp=0

if keyboard_check (68) direction -=1.5
if keyboard_check (65) direction +=1.5
{
if keyboard_check (87)
{
xtemp += lengthdir_x(2, direction)
ytemp += lengthdir_y(2, direction)
}
if keyboard_check (83)
{
xtemp += lengthdir_x(1.5, direction + 180)
ytemp += lengthdir_y(1.5, direction + 180)
}
if keyboard_check (69)
{
xtemp += lengthdir_x(1.5, direction-90)
ytemp += lengthdir_y(1.5, direction-90)
}
if keyboard_check (81)
{
xtemp += lengthdir_x(1.5, direction+90)
ytemp += lengthdir_y(1.5, direction+90)
}
}

while sqr(xtemp)+sqr(ytemp)>sqr(maxspeed){ //Pythagorean theorem to check the vector's length doesn't exceed the maximum allowed.
xtemp*=0.9 //Decrease to improve speed, increase to improve accuracy (keep below 1).
ytemp*=0.9 //Not the most efficient method, but the simplest that comes to mind.
}

x+=xtemp
y+=ytemp


That should work for you while maintaining for the most part the degree and partial magnitude of the original vector. Definitely not the most efficient nor the most accurate method, but it should work.

Another simple enough method would be to rewrite the keyboard checks for combination presses (making sure to put the and not's in the single key presses), which would be a lot more accurate for what you're looking for, but the coding will be a bit longer and will take some effort to write.

This post has been edited by RandomBlackMage: Nov 3 2009, 06:27 AM
Go to the top of the page
 
+Quote Post
icuurd12b42
post Nov 3 2009, 08:38 AM
Post #5


GMC Member
Group Icon

Group: GMC Member
Posts: 7701
Joined: 26-October 06
Member No.: 62394



step event... 2 version, diffrent movement as I could not tell from your code (I tried it, weird) which one you wanted...
CODE
//up down, rotation does not affect movement
spd = 4;
rotspd = 5;
image_angle+=(keyboard_check(ord('A')) - keyboard_check(ord('D'))) * rotspd;
direction = image_angle;
dx = (keyboard_check(vk_right) - keyboard_check(vk_left));
dy = (keyboard_check(vk_down) - keyboard_check(vk_up));
if(dx<>0 or dy <>0)
{
    a = point_direction(0,0,dx,dy)
    x+=lengthdir_x(spd,a);
    y+=lengthdir_y(spd,a);
}

exit;
//for rotating and moving to pointing direction
//and straffing... Confusing
spd = 4;
rotspd = 5;
image_angle+=(keyboard_check(ord('A')) - keyboard_check(ord('D'))) * rotspd;
direction = image_angle;
dx = (keyboard_check(vk_up) - keyboard_check(vk_down));
dy = (keyboard_check(vk_right) - keyboard_check(vk_left));
if(dx<>0 or dy <>0)
{
    a = point_direction(0,0,dx,dy)
    x+=lengthdir_x(spd,image_angle+a);
    y+=lengthdir_y(spd,image_angle+a);
}
Go to the top of the page
 
+Quote Post
Tepi
post Nov 3 2009, 01:32 PM
Post #6


GMC Member
Group Icon

Group: GMC Member
Posts: 3355
Joined: 1-June 07
From: Finland
Member No.: 80090



This is a good example that you can't simplify human movement like this. The forces and therefore accelerations are not even near to being 0, so just simple vector addition to the position (i.e. constant velocity) is not the correct system. If it was, this vector adition would be expected. But here it's not.

The most simple way of doing this is indeed to limit the speed at which the person moves. But that makes using directions and speeds easier than using vectors. So if you insist to stick with the vector movement, normalize the movement vector after the addition. Copy the RandomBlackMage's code but replace the while loop with:
CODE
var D;
D = sp / point_distance(0,0,xtemp,ytemp);
xtemp *= D;
ytemp *= D;
where sp is the speed in which you want the movement to happen.
Go to the top of the page
 
+Quote Post
bluesy_92
post Nov 3 2009, 03:31 PM
Post #7


GMC Member
Group Icon

Group: GMC Member
Posts: 8
Joined: 18-August 09
Member No.: 138175



QUOTE (Tepi @ Nov 3 2009, 02:32 PM) *
This is a good example that you can't simplify human movement like this. The forces and therefore accelerations are not even near to being 0, so just simple vector addition to the position (i.e. constant velocity) is not the correct system. If it was, this vector adition would be expected. But here it's not.

The most simple way of doing this is indeed to limit the speed at which the person moves. But that makes using directions and speeds easier than using vectors. So if you insist to stick with the vector movement, normalize the movement vector after the addition. Copy the RandomBlackMage's code but replace the while loop with:
CODE
var D;
D = sp / point_distance(0,0,xtemp,ytemp);
xtemp *= D;
ytemp *= D;
where sp is the speed in which you want the movement to happen.


If I was to use direction and speed (which I prefer) how would I use strafing? I tried several direction and speed methods before, and several ways of using variables, to get strafing....it never worked, which is why I used a vector-based method.
Go to the top of the page
 
+Quote Post
slayer 64
post Nov 3 2009, 04:09 PM
Post #8


GMC Member
Group Icon

Group: GMC Member
Posts: 1357
Joined: 9-October 07
Member No.: 90249



i don't know what you mean by strafing. this is a top down shooter so maybe you want to do this.
CODE
x+=(keyboard_check(ord("A"))-keyboard_check(ord("D")))*4;
y+=(keyboard_check(ord("W"))-keyboard_check(ord("S")))*4;

but from looking at the other posts you are doing something slightly more complicated. maybe you are trying to strafe according to the direction your facing? i'm not really sure what your long term goal is.
CODE
var dx,dy;

dx=keyboard_check(ord("A"))-keyboard_check(ord("D"));
dy=keyboard_check(ord("W"))-keyboard_check(ord("S"));
        
if dx!=0
or dy!=0
{
    a=point_direction(0,0,dy,dx)+image_angle;
    x+=lengthdir_x(4,a);
    y+=lengthdir_y(4,a);
}


This post has been edited by slayer 64: Nov 3 2009, 04:10 PM
Go to the top of the page
 
+Quote Post
bluesy_92
post Nov 3 2009, 06:02 PM
Post #9


GMC Member
Group Icon

Group: GMC Member
Posts: 8
Joined: 18-August 09
Member No.: 138175



QUOTE (slayer 64 @ Nov 3 2009, 05:09 PM) *
i don't know what you mean by strafing. this is a top down shooter so maybe you want to do this.
CODE
x+=(keyboard_check(ord("A"))-keyboard_check(ord("D")))*4;
y+=(keyboard_check(ord("W"))-keyboard_check(ord("S")))*4;

but from looking at the other posts you are doing something slightly more complicated. maybe you are trying to strafe according to the direction your facing? i'm not really sure what your long term goal is.
CODE
var dx,dy;

dx=keyboard_check(ord("A"))-keyboard_check(ord("D"));
dy=keyboard_check(ord("W"))-keyboard_check(ord("S"));
        
if dx!=0
or dy!=0
{
    a=point_direction(0,0,dy,dx)+image_angle;
    x+=lengthdir_x(4,a);
    y+=lengthdir_y(4,a);
}


By "strafe", I mean like an FPS strafing. I have WASD movement, but I use Q and E to strafe left and right, while looking forward. It is all based on vectors, you can see the code in my original post.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 23rd November 2009 - 10:54 AM