Answered by:
Newb Question: Moving My Car.
Question

Hi, after looking at asteroids I am still having some trouble understand whats going on with the way the author gets the spacecraft to move.
I have a basic Rectangle which i am trying to move as if it were a car/spacecraft.
Hers my Code/Understanding of the movements.
gameWidth =400 gameHeight = 400 GraphicsWindow.Height = gameHeight GraphicsWindow.Width = gameWidth Box = Shapes.AddRectangle (50,100) W = "W" A = "A" S = "S" D = "D" PlayerAngle = 0 PlayerSpeed = 0 GraphicsWindow.KeyDown = KeyDown Game = 1 While Game=1 Movement () endwhile Sub KeyDown If GraphicsWindow.LastKey = W then PlayerSpeed = PlayerSpeed  0.001 ElseIf GraphicsWindow.LastKey = S then PlayerSpeed = PlayerSpeed+ 0.001 elseif GraphicsWindow.LastKey = A Then PlayerAngle = PlayerAngle 1 ElseIf GraphicsWindow.LastKey = D then PlayerAngle = PlayerAngle +1 EndIf endsub Sub Movement Shapes.Rotate (Box,PlayerAngle) newX = (Math.Sin (PlayerAngle))*PlayerSpeed newY = (Math.Cos (PlayerAngle))*PlayerSpeed X = Shapes.GetLeft (Box) Y = Shapes.GetTop (Box) TotalX = X + newX TotalY = Y + newY Shapes.Move (Box,TotalX,TotalY) EndSub
Its probably really messy Please tell me where i am going wrong with my movements.
Cheers,
Plute.
Answers

I had to do three things mainly, change your increments to new values, negate cosine, and you had converted playerangle twice to radians. I also reshaped your box, maybe didnt have to. This setup has zero degrees playerangle going up, and positive speed going in the direction of playerangle. Trigonometry is extremely useful for games!
gameWidth =400 gameHeight = 400 GraphicsWindow.Height = gameHeight GraphicsWindow.Width = gameWidth Box = Shapes.AddRectangle (20,50) W = "W" A = "A" S = "S" D = "D" PlayerAngle = 0 PlayerSpeed = 0 GraphicsWindow.KeyDown = KeyDown Game = 1 While Game=1 Movement () endwhile Sub KeyDown If GraphicsWindow.LastKey = W then PlayerSpeed = PlayerSpeed + 0.1 ElseIf GraphicsWindow.LastKey = S then PlayerSpeed = PlayerSpeed  0.1 elseif GraphicsWindow.LastKey = A Then PlayerAngle = PlayerAngle  10 ElseIf GraphicsWindow.LastKey = D then PlayerAngle = PlayerAngle + 10 EndIf endsub Sub Movement PlayerSpeedCopy = Playerspeed 'PlayerAngleCopy = Math.GetRadians (PlayerAngle) PlayerAngleCopy = PlayerAngle Shapes.Rotate (Box,PlayerAngleCopy) newX = Math.sin (Math.GetRadians(PlayerAngleCopy))*PlayerSpeedCopy newY = Math.cos (Math.GetRadians(PlayerAngleCopy))*PlayerSpeedCopy X = Shapes.GetLeft (Box) Y = Shapes.GetTop (Box) TotalX = X + newX TotalY = Y + newY Shapes.Move (Box,TotalX,TotalY) endsub
 Marked as answer by FremyCompany [MSFT] Wednesday, June 24, 2009 2:14 PM
All replies

Part of the problem is that Math.Sin and Math.Cos expect the angle to be given in radians (2*pi radians = 360°). You are changing PlayerAngle in steps of about 57°. Try dividing PlayerAngle by (2 * pi) / 360 to get radians.
Could you please supply more information. Do you intend the box to move like a car with one short side always the front? Edited by Stendec Tuesday, June 23, 2009 5:25 PM Formula correction.

One problem you'll run into is the Keydown subroutine is modifying PlayerSpeed, which can occur anytime you press a key at any point in execution of the rest of the code. I think most people will do this until they find out the effects of it, i found out the hard way too, I'm not sure it's explained anywhere. In this case your Movement subroutine might use two different values of PlayerSpeed if a keypress occurs in the middle of the execution of these two lines:
newX = (Math.Sin (PlayerAngle))*PlayerSpeed
newY = (Math.Cos (PlayerAngle))*PlayerSpeed
What you want to do in this case is in Movement make a copy of PlayerSpeed, and use that instead in there. Then it wont change on you between the two lines above.
From what Stendec says, you'll want to change your increment of PlayerAngle instead of +/1 to something like +/ 0.1 or smaller. Remember there are about 6.28 radians for one revolution or 360 degrees of rotation.
Also PlayerSpeed is incremented in too small of a number, i would change that to +/1 or so. This is in units of pixels per update period of your Movement routine.
I bet it'll work after you do the above.
After you do get it working, you probably want to make sure that any input into sin/cos function is within +/ 2 * pi = about 6.2832. Often a compiler will generate growing errors of the returned value if you go too far out. To do this, use the Math.Remainder(x, 6.2832) 
Ok. first off thank you for replying.
Here is my edited subroutine, taking both your comments into account.
Sub Movement PlayerSpeedCopy = Playerspeed PlayerAngleCopy = Math.GetRadians (PlayerAngle) Shapes.Rotate (Box,PlayerAngleCopy) newX = (Math.Sin (Math.GetRadians(PlayerAngleCopy)))*PlayerSpeedCopy newY = (Math.Cos (Math.GetRadians(PlayerAngleCopy)))*PlayerSpeedCopy X = Shapes.GetLeft (Box) Y = Shapes.GetTop (Box) TotalX = X + newX TotalY = Y + newY Shapes.Move (Box,TotalX,TotalY)
I wasn't sure of how to get an accurate pi on the computer. (without just typing 3.14) So i used the getradians command.
Thanks for the tip on the changing playerspeed, i Made the copies as you can see.
However, even using the tips, my guy still has A LOT of bugs.
If i change the increment on playerspeed, my box just goes flying off the graphicswindow :\
Here is the movement from Asteroids:
x = Math.Remainder(Shapes.GetLeft(player) + (Math.Cos(Math.GetRadians(playerAngle  90)) * playerSpeed) + gameWidth, gameWidth) y = Math.Remainder(Shapes.GetTop(player) + (Math.Sin(Math.GetRadians(playerAngle  90)) * playerSpeed) + gameHeight, gameHeight) Shapes.Move(player, x, y)
Can someone please explain, how this works :) cheers.

I had to do three things mainly, change your increments to new values, negate cosine, and you had converted playerangle twice to radians. I also reshaped your box, maybe didnt have to. This setup has zero degrees playerangle going up, and positive speed going in the direction of playerangle. Trigonometry is extremely useful for games!
gameWidth =400 gameHeight = 400 GraphicsWindow.Height = gameHeight GraphicsWindow.Width = gameWidth Box = Shapes.AddRectangle (20,50) W = "W" A = "A" S = "S" D = "D" PlayerAngle = 0 PlayerSpeed = 0 GraphicsWindow.KeyDown = KeyDown Game = 1 While Game=1 Movement () endwhile Sub KeyDown If GraphicsWindow.LastKey = W then PlayerSpeed = PlayerSpeed + 0.1 ElseIf GraphicsWindow.LastKey = S then PlayerSpeed = PlayerSpeed  0.1 elseif GraphicsWindow.LastKey = A Then PlayerAngle = PlayerAngle  10 ElseIf GraphicsWindow.LastKey = D then PlayerAngle = PlayerAngle + 10 EndIf endsub Sub Movement PlayerSpeedCopy = Playerspeed 'PlayerAngleCopy = Math.GetRadians (PlayerAngle) PlayerAngleCopy = PlayerAngle Shapes.Rotate (Box,PlayerAngleCopy) newX = Math.sin (Math.GetRadians(PlayerAngleCopy))*PlayerSpeedCopy newY = Math.cos (Math.GetRadians(PlayerAngleCopy))*PlayerSpeedCopy X = Shapes.GetLeft (Box) Y = Shapes.GetTop (Box) TotalX = X + newX TotalY = Y + newY Shapes.Move (Box,TotalX,TotalY) endsub
 Marked as answer by FremyCompany [MSFT] Wednesday, June 24, 2009 2:14 PM
