WASD movement

Blitz3D Forums/Blitz3D Programming/WASD movement

I've been toying around with moving a sprite around the screen with WASD (A and D for strafing, W and S for forward and reverse) and using the mouses' X axis for the rotation.

However, in my test runs I've noticed that if I'm moving forward and strafing at the same time, the velocity increases to more than the max velocity in a single direction. I've figured the problem out, but I can't figure a way around it. Besides, the way I'm going about it probably isn't the right way :-)

Now.... anyone care to school me how this is done?

You can check for both keys being depressed at the same time. Sort of like: If W is down and D not move 4 units forward. If D is down and not W move 4 units right. If both are down, move (4*cos45) to the right and (4*sin45) up. That way the total distance traveled is always 4 units.

Tried Sin & Cos?

Hmm, dunno why I used 2D, but the principle is the same :)

Graphics 800,600,32,2

px#=400
py#=300
mv#=4.0
img=CreateImage(64,64)
dir#=0

HandleImage img,32,32
SetBuffer ImageBuffer(img)
Oval 0,0,64,64,True
Color 255,0,0
Line 32,0,35,12
Line 32,0,29,12
Line 32,12,35,12
Color 255,255,255
SetBuffer BackBuffer()

While Not KeyDown(1)
	dir = -(400.0 - MouseX()) * .5
	If KeyDown(17) And KeyDown(30) ;up left
		px=px + Sin(315+dir)*mv
		py=py - Cos(315+dir)*mv
	Else If KeyDown(17) And KeyDown(32) ;up right
		px=px + Sin(45+dir)*mv
		py=py - Cos(45+dir)*mv
	Else If KeyDown(31) And KeyDown(30) ;down left
		px=px + Sin(225+dir)*mv
		py=py - Cos(225+dir)*mv
	Else If KeyDown(31) And KeyDown(32) ;down right
		px=px + Sin(135+dir)*mv
		py=py - Cos(135+dir)*mv
	Else If KeyDown(30) ;left
		px=px + Sin(270+dir)*mv
		py=py - Cos(270+dir)*mv
	Else If KeyDown(32) ;right
		px=px + Sin(90+dir)*mv
		py=py - Cos(90+dir)*mv
	Else If KeyDown(17) ;up
		px=px + Sin(dir)*mv
		py=py - Cos(dir)*mv
	Else If KeyDown(31) ;down
		px=px + Sin(180+dir)*mv
		py=py - Cos(180+dir)*mv
	End If

	SetBuffer ImageBuffer(img)
	Oval 0,0,64,64,True
	Color 255,0,0
	Line 32,32,32+Sin(dir)*30,32-Cos(dir)*30
	
	Color 255,255,255
	SetBuffer BackBuffer()

	Cls
	DrawImage img,px,py
	Flip
Wend


Very helpful! Thanks r0nin, and Tom :-D

This is something even AAA games miss - I've got used to running diagonally in games like Perfect Dark to get somewhere quicker!

yeah the 'semi-crab' run is quickest :P

LOL! You know, I spend too much time gazing in awe that my crappy code even runs! Thats how I recognized it :-D

you could alse check for both keys being pressed(w and d for example) and cut each speed enought to where it equals the max speed

Uhhh, Rubiks, that's exactly what the advice and code Tom and I gave him did (you have to use sine/cosine/geometry to do so)...

no hes sayign insert a if speed > max speed, speed = max speed, that way he'll never go over the 4 units.

oh lol i wasn't paying attention when i wrote that

Wouldn't work, Cruis.In. Let's say you put in a speed <= maxspeed with maxspeed = 4. The you press W to go up. You are now moving at 4 units up. Then, while holding down W, you press D. You should move up and right, but since any speed added to the object takes it above 4 units, you would continue to only move straight up, even though you had both keys down. The ONLY (I repeat ONLY) way to maintain a constant velocity when moving at non-divisible-by-90 angles is to use geometry. Without sine/cosine you have no way of knowing what portion of your maxspeed should be moved in the X direction and what portion should be in the Y, and you can't get around that because a computer monitor is nothing more than a grid of pixels.

So, sorry, but your suggestion would not work...


you could alse check for both keys being pressed(w and d for example) and cut each speed enought to where it equals the max speed



Divide forward and sideways speed by 1.4142.

Move forward: 3 units
Move sideways: 3 units

Pythagoras:
SqRT((x*x) + (y*y)) = SqRT((3*3) + (3*3)) = 4.2426

->

3/1.4142 = 2.1213

->

SqRT((2.1213 * 2.1213) + (2.1213 * 2.1213)) = 2.9999

That's still using geometry *grin*... just you've done the calculations pre-programming rather than at run-time. It's easier to write one movement function using speed and direction and then sine/cosine the input to move the player (because this preserves the ability to turn the player in smaller increments than 45 degree angles, making the code portable)...