Vector-based Movement Causing Player Speed Issues?, vector addition not allowing for consistent speed |
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
![]() ![]() |
Vector-based Movement Causing Player Speed Issues?, vector addition not allowing for consistent speed |
Nov 3 2009, 02:30 AM
Post
#1
|
|
|
GMC Member 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 |
|
|
|
Nov 3 2009, 03:08 AM
Post
#2
|
|
|
GMC Member 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 |
|
|
|
Nov 3 2009, 03:20 AM
Post
#3
|
|
|
GMC Member Group: GMC Member Posts: 8 Joined: 18-August 09 Member No.: 138175 |
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. |
|
|
|
Nov 3 2009, 06:10 AM
Post
#4
|
|
|
We all look alike 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 |
|
|
|
Nov 3 2009, 08:38 AM
Post
#5
|
|
|
GMC Member 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); } |
|
|
|
Nov 3 2009, 01:32 PM
Post
#6
|
|
|
GMC Member 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; where sp is the speed in which you want the movement to happen.
D = sp / point_distance(0,0,xtemp,ytemp); xtemp *= D; ytemp *= D; |
|
|
|
Nov 3 2009, 03:31 PM
Post
#7
|
|
|
GMC Member Group: GMC Member Posts: 8 Joined: 18-August 09 Member No.: 138175 |
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; where sp is the speed in which you want the movement to happen.D = sp / point_distance(0,0,xtemp,ytemp); xtemp *= D; ytemp *= D; 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. |
|
|
|
Nov 3 2009, 04:09 PM
Post
#8
|
|
|
GMC Member 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 |
|
|
|
Nov 3 2009, 06:02 PM
Post
#9
|
|
|
GMC Member Group: GMC Member Posts: 8 Joined: 18-August 09 Member No.: 138175 |
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. |
|
|
|
![]() ![]() |
|
Lo-Fi Version | Time is now: 23rd November 2009 - 10:54 AM |