More Sin\Cos Problems

BlitzMax Forums/BlitzMax Beginners Area/More Sin\Cos Problems

QuickSilva(Posted 2009) [#1]
I have a top down view object and I want it to be able to move up, down, left and right. This is easy enough. I also want it to be able to rotate both left and right, again easy stuff. The problem comes when I want to use the rotated angle as the basis for the objects movement.

For instance, if the ship is pointing upward and I press the up key then the ship should obviously move straight up, then same for the other directions, but if my ship object is pointing off to an angle then I want to follow that path instead. So if I`m at a 45 degree angle and press up then I should move forward at a 45 degree angle. I can get this working to some extent but then when I try to add in left and right movements things get tricky.

Can anyone please give me any advice on what I need to be doing to get this kind of movement? Despite trying to learn Trigonometry I`m still finding it a little hard going.

Thank you for any help,

Jason.


Dabhand(Posted 2009) [#2]
Not sure if this will help:-

http://www.krylarskreations.com/bc/show_article.pl?f=gamekrylar09302000

Its in BlitzBasic, but the meat should be there.

Dabz


jkrankie(Posted 2009) [#3]
isn't that in the code i posted in your other thread? If you want me to explain it better i can.

Cheers
Charlie


Jesse(Posted 2009) [#4]
see if this helps:
SuperStrict
Type Tship
	Field x:Float
	Field y:float
	Field dx:Float
	Field dy:Float
	Field angle:Float
	Field speed:Float
	Field image:timage
	
	Method Create(x:Float,y:Float,a:Float,s:Float)
		
		DrawOval 0,0,30,10 'image must be created horizontally with the front to the right
		image = CreateImage(30,10) 
		GrabImage(image,0,0)
		MidHandleImage(image)
		Self.x = x 
		Self.y = y
		angle = a
		speed = s
	End Method
	
	Method update()

		angle = angle + (KeyDown(key_right) - KeyDown(key_left)) 
		dx = Cos(angle)
		dy = Sin(angle)
		x :+ dx*speed
		y :+ dy*speed
	
	End Method

	Method draw()
		SetRotation angle
		DrawImage image,x,y
	End Method
End Type
Graphics 800,600
Local ship:tship = New Tship
ship.Create(100,100,0,.5)

Repeat
	Cls
	ship.update()
	ship.draw()
	Flip()
Until KeyDown(key_escape)



QuickSilva(Posted 2009) [#5]
Dabhand :
Thanks I will have a read.

jkrankie \ jesse:
I`m still having a few problems trying to grasp how to do the following despite some helpful code from you both. I am able to recreate the movement found in the above code but my problem is that I cannot understand how to do a sideways movement, for example, if I wanted to fire bullets from both sides of the ship in the code above at the correct angles.

Jason.


jkrankie(Posted 2009) [#6]
to fire a bullet at a sideways angle from the ship, you would create a new bullet with the angle of the ship + or - 90 degrees. you would move the bullet in the same way as the boat.

Cheers
Charlie


QuickSilva(Posted 2009) [#7]
OK, here`s a quick example of the part I`m having trouble with.

Move the ship with the arrow keys and rotate with Q and W. Once rotated, the ship should fly along the path of the red lines when up, down, left and right keys are pressed and not simply with the screens orientation as in this demo.

Hope this makes sense, it`s a little hard to explain. Hopefully someone can add to the code below. I know that I`ve almost got it as I have drawn the flight paths in red already. I also know that it involves changing the *50 of the Sin\Cos lines as they are controlling the radius which is what I think I am after. These obviously need to be variables and added\subtracted when I press the arrow keys. Am I thinking along the right lines?

Jason.

Graphics 640,480

DrawOval 0,0,10,30
ship=CreateImage(10,30)
GrabImage(ship,0,0)
MidHandleImage(ship) 

x=320
y=240
speed=2

While Not KeyHit(KEY_ESCAPE)
	Cls
	
	If KeyDown(KEY_Q) Then angle:-speed
	If KeyDown(KEY_W) Then angle:+speed
	
	If KeyDown(KEY_UP) Then y:-speed
	If KeyDown(KEY_DOWN) Then y:+speed
	If KeyDown(KEY_LEFT) Then x:-speed
	If KeyDown(KEY_RIGHT) Then x:+speed
	
	SetRotation angle
		DrawImage ship,x,y
	SetRotation 0
	
	SetColor 255,0,0
		DrawLine x,y,x+Cos(angle)*50,y+Sin(angle)*50
		DrawLine x,y,x+Cos(angle-180)*50,y+Sin(angle-180)*50
		DrawLine x,y,x+Cos(angle+90)*50,y+Sin(angle+90)*50
		DrawLine x,y,x+Cos(angle-90)*50,y+Sin(angle-90)*50
	SetColor 255,255,255
	
	DrawText "Q and W keys rotate ship, arrow keys move ship.",10,10
	Flip
Wend
End



jkrankie(Posted 2009) [#8]
Make sure you declare your datatypes. if you use an int (i.e if you don't specify float) for x and y this wont work properly.

Graphics 640,480

DrawOval 0,0,10,30
ship=CreateImage(10,30)
GrabImage(ship,0,0)
MidHandleImage(ship) 

x:Float=320
y:float=240
speed=0

While Not KeyHit(KEY_ESCAPE)
	Cls
	
	If KeyDown(KEY_Q) Then angle:-2
	If KeyDown(KEY_W) Then angle:+2
	
	speed=0

	If KeyDown(KEY_UP) 
 		speed=2 
		x=speed*Cos(angle)+x
		y=speed*Sin(angle)+y
	EndIf
	If KeyDown(KEY_DOWN) 
 		speed=2 
		x=-speed*Cos(angle)+x
		y=-speed*Sin(angle)+y
	EndIf
	
	If KeyDown(KEY_LEFT) 
 		speed=2
		x=speed*Cos(angle+270)+x
		y=speed*Sin(angle+270)+y
	EndIf
	
	If KeyDown(KEY_RIGHT) 
 		speed=2
		x=speed*Cos(angle+90)+x
		y=speed*Sin(angle+90)+y
	EndIf



	SetRotation angle
	DrawImage ship,x,y
	SetRotation 0
	
	SetColor 255,0,0
		DrawLine x,y,x+Cos(angle)*50,y+Sin(angle)*50
		DrawLine x,y,x+Cos(angle-180)*50,y+Sin(angle-180)*50
		DrawLine x,y,x+Cos(angle+90)*50,y+Sin(angle+90)*50
		DrawLine x,y,x+Cos(angle-90)*50,y+Sin(angle-90)*50
	SetColor 255,255,255
	
	DrawText "Q and W keys rotate ship, arrow keys move ship.",10,10
	Flip
Wend
End



is that roughly what you were after?

Cheers
Charlie


ImaginaryHuman(Posted 2009) [#9]
Not sure if you got your answer yet, but just based on reading your first post up there I would say convert the key being pressed into an angle and add it to the player's angle.

ie Up=0, Down=180, Left=270, Right=90.

So for example if the player is aiming 45 degrees up toward the top right of the screen, and you press the up key, it will be 45+0=45, will move straight, if you press right it will be 45+90=135 - ie will move down toward the bottom right.

Looks like that's basically what the above code is doing. e.g.

local PlayerAngle:Float=0
While Not KeyHit(KEY_ESCAPE)
   'Do whatever you need to do to move the player based on inertia etc here

   'Process input
   Local InputAngle:Float=0
   If KeyDown(KEY_UP) Then InputAngle=0.0
   If Keydown(KEY_RIGHT) Then InputAngle=90.0
   If KeyDown(KEY_DOWN) Then InputAngle=180.0
   If KeyDown(KEY_LEFT) Then InputAngle=270.0
   PlayerAngle:+InputAngle

   'Draw player
Wend



sswift(Posted 2009) [#10]
X = Radius * Cos(Angle)
Y = Radius * Sin(Angle)

That's all you need to move an object in a particular direction. Those are the equations to convert from polar to cartesian coordinates. Cartesian being a grid defined by X and Y, and polar being defined by Radius and Angle.

Just add X and Y to your object's current position, and set radius to the speed.

You can also use those equations to draw circles (or ellipses if you set the two radii to be different) by picking a point for your center, and adding X and Y to that location then plotting a point there.

X and Y in the above equations will vary from -Radius to +Radius as you move Angle from 0 to 360.

There's other ways to do what you want which involve transforming vectors from sprite space to global or screen space, but the math behind that is quite a bit more complicated.


Jesse(Posted 2009) [#11]
here you go:

Graphics 640,480

DrawOval 0,0,10,30
ship=CreateImage(10,30)
GrabImage(ship,0,0)
MidHandleImage(ship) 

x#=320
y#=240
speed#=2

While Not KeyHit(KEY_ESCAPE)
	Cls
	
	If KeyDown(KEY_Q) Then angle# :- speed
	If KeyDown(KEY_W) Then angle# :+ speed
	
	If KeyDown(KEY_UP) Then    y :+ Sin(angle-90) * speed ;x :+ Cos(angle-90) * speed
	If KeyDown(KEY_DOWN) Then  y :+ Sin(angle+90) * speed ;x :+ Cos(angle+90) * speed
	If KeyDown(KEY_LEFT) Then  y :+ Sin(angle-180)* speed ;x :+ Cos(angle-180)* speed
	If KeyDown(KEY_RIGHT) Then y :+ Sin(angle)* speed     ;x :+ Cos(angle) * speed
	
	SetRotation angle
		DrawImage ship,x,y
	SetRotation 0
	
	SetColor 255,0,0
		DrawLine x,y,x+Cos(angle)*50,y+Sin(angle)*50
		DrawLine x,y,x+Cos(angle-180)*50,y+Sin(angle-180)*50
		DrawLine x,y,x+Cos(angle+90)*50,y+Sin(angle+90)*50
		DrawLine x,y,x+Cos(angle-90)*50,y+Sin(angle-90)*50
	SetColor 255,255,255
	
	DrawText "Q and W keys rotate ship, arrow keys move ship.",10,10
	Flip
Wend
End

when you work with sin and cos don't mix with integers.
********** EDITED below ***********
when you want to shoot bullets make shure you save the direction of the bullet only.
'shoot right
dx = cos(angle+90) 
dy = sin(angle+90)
'shoot left
dx = cos(angle-90)
dy = sin(angle-90)
'shoot ahead
dx = cos(angle)
dy = sin(angle)
'shoot back
dx = cos(angle+180)' + or - is the same
dy = sin(angle+180) 

then you just multiply by speed add it to x and y and it will keep the direction.
x:+ dx * speed
y:+ dy * speed

is it begining to make sence?


QuickSilva(Posted 2009) [#12]
I`m starting to get it now, it`s not half as hard as I first thought. Sometimes, when you over think these things you can make them seem a lot more complicated than they actually are.

Thanks everyone for the tips. Each of you shows different methods of doing the same thing which is always helpful :)

Jason.