Trigonometry Help

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
walesmd
Prole
Posts: 22
Joined: Fri Oct 08, 2010 3:11 am
Location: Augusta, GA
Contact:

Trigonometry Help

Post by walesmd »

After the successful Snake prototype I decided to tackle an Asteroids prototype. I don't know if it's the 12-pack in me or what but I am having a hard time wrapping my head around the math in determining where to redraw the ship after acceleration. Here's the code I have thus far, below that you will find my current train of thought.

Code: Select all

-- Asteroids Clons
-- Author: Michael Wales ([email protected])
-- License: Creative Commons BSD (http://creativecommons.org/licenses/BSD)



function love.load()
	love.graphics.setMode(1024, 768, false, false)

	game = {}
	game.width = love.graphics.getWidth()
	game.height = love.graphics.getHeight()
	
	player = {}
	player.sprite = love.graphics.newImage("player.png")
	player.x = game.width / 2
	player.y = game.height / 2
	player.accelerating = false
	player.velocity = 0
	player.max_velocity = 10.0
	player.acceleration = 0.5
	player.rotate = 0
	player.rotation_speed = 0.25


	-- Preload image resources
	background = love.graphics.newImage("background.png")
end


function love.update(dt)
	if love.keyboard.isDown("up") then
		player.accelerating = true
	else
		player.accelerating = false
	end
	
	if love.keyboard.isDown("right") then
		player.rotate = player.rotate + player.rotation_speed
		print("RIGHT")
	elseif love.keyboard.isDown("left") then
		player.rotate = player.rotate - player.rotation_speed
		print("LEFT")
	end


	if player.accelerating then
		player.velocity = player.velocity + player.acceleration
		if player.velocity >= player.max_velocity then
			player.velocity = player.max_velocity
		end
	else
		player.velocity = player.velocity - player.acceleration
		if player.velocity <= 0 then
			player.velocity = 0
		end
	end
end


function love.draw()
	love.graphics.draw(background, 0, 0)
	love.graphics.draw(player.sprite, player.x, player.y, player.rotate * (math.pi / 180), 1, 1, player.sprite:getWidth() / 2, player.sprite:getHeight() / 2)
	
	
	-- Debug Info
	love.graphics.print("FPS: " .. love.timer.getFPS(), 10, 10)
end


function love.keypressed(key)
end
So, player.rotate is in degrees and after converting that to radians (player.rotate * (math.pi / 180)) and drawing it on the screen, LOVE interprets that as North, 90 is East, 180 is South and 270 is West. I know the distance of my hypotenuse (player.velocity) and I know the starting location of the player (player.x + player.sprite:getWidth() / 2, player.y + player.sprite.getHeight() / 2). This appears to be enough information to determine the redraw point in according to the Euclidean distance formula but my brain right now just isn't making the connection.

Another thought I had was using slope grade and I did a bit of proofing in regards to that:
0-degrees = -player.velocity/0
90-degrees = 0/velocity
180-degrees = velocity/0
270-degrees = 0/-velocity
45-degrees = -(velocity/2)/(velocity/2)

Even running through those scenarios hasn't pointed me in the right direction. I'm confident that math.tan() is going to point me in the right direction but the grid coordinate system is messing with my brain (as opposed to the grid coordinate system we always learned in school, where (0, 0) was center).

Can anyone give me a helpful hint in the right direction? Not looking for completed code here, just a helpful nudge to send me into the "AHA!" moment.
User avatar
zac352
Party member
Posts: 496
Joined: Sat Aug 28, 2010 8:13 pm
Location: In your head.
Contact:

Re: Trigonometry Help

Post by zac352 »

Uh... math.rad(n)? :huh:
Hello, I am not dead.
User avatar
walesmd
Prole
Posts: 22
Joined: Fri Oct 08, 2010 3:11 am
Location: Augusta, GA
Contact:

Re: Trigonometry Help

Post by walesmd »

All math.rad(n) does is convert degrees to radians, which is what I am doing with the following bit of code:

Code: Select all

player.rotate * (math.pi / 180)
I'm past the degree-to-radian conversion point, I am now trying to take the players current position, their angle, and their velocity and determine the next point in which to redraw the player sprite.
User avatar
zac352
Party member
Posts: 496
Joined: Sat Aug 28, 2010 8:13 pm
Location: In your head.
Contact:

Re: Trigonometry Help

Post by zac352 »

I see your problem.. You can't make an asteroid game with a 1D velocity system.
It just wouldn't work. It's extremely basic physics.. :/

Here's the code for accelerating a rocket:

Code: Select all

vx=vx+math.sin(rotation)*acceleration
vy=vy+math.cos(rotation)*acceleration
Hello, I am not dead.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Trigonometry Help

Post by ivan »

Hi. I don't really understand your question but I might have some useful suggestions.
If I remember correctly, in Asteroids, you can rotate your ship in any direction without affecting the direction of its movement.
That is, I don't think it would be enough to represent its velocity as a number.
How about:

Code: Select all

	player = {}
	player.sprite = love.graphics.newImage("player.png")
	player.x = game.width / 2
	player.y = game.height / 2
	player.accelerating = false
	player.velocity_x = 0
	player.velocity_y = 0
	player.max_velocity = 10.0
	player.acceleration = 0.5
	player.rotate = 0
	player.rotation_speed = 0.25
During the update, you can do the following.

Code: Select all

if player.accelerating == true then
  player.velocity_x = player.velocity_x + math.sin ( math.rad ( player.rotation ) ) * player.acceleration
  player.velocity_y = player.velocity_y + math.cos ( math.rad ( player.rotation ) ) * player.acceleration

  -- clamps the velocity vector to max_velocity while preserving its direction
  local dist = math.sqrt ( player.velocity_x * player.velocity_x + player.velocity_y * player.velocity_y )
  if dist > player.max_velocity then
     player.velocity_x = player.velocity_x / dist * player.max_velocity
     player.velocity_y = player.velocity_y / dist * player.max_velocity
  end
end

player.x = player.x + player.velocity_x
player.y = player.y + player.velocity_y
User avatar
Adamantos
Prole
Posts: 27
Joined: Sun May 16, 2010 10:47 pm

Re: Trigonometry Help

Post by Adamantos »

Hi walesmd,

so... it's a little bit more complicated... :ehem:
You have to keep track of your position.x/y and your velocity.x/y
But because you can accelerate in a direction other than your travalling direction, you need
also keep track of your acceleration.x/y

The rest is simple math/physics... maybe you can remember the "free fall" experiment from
your physics class in school ?

so... you have a constant acceleration
a = const

than your velocity will be
v = v0 + a * dt
(v0 is your initial speed)

and your position will be
r = r0 + v0 * dt + a*dt^2
(r0 is your initial position)

When you derivate these equations, you can simple check, that these are correct.
For example:
The speed of an object, is the change of postion over time... so speed is equal
to dr / dt

I modified your code... this should help
(And it is independent of fps !!!)

Code: Select all

-- Asteroids Clons
-- Author: Michael Wales ([email protected])
-- License: Creative Commons BSD (http://creativecommons.org/licenses/BSD)



function love.load()
	love.graphics.setMode(1024, 768, false, false)

	game = {}
	game.width 	= love.graphics.getWidth()
	game.height = love.graphics.getHeight()

	player = {}
	player.sprite = love.graphics.newImage("player.png")
	player.position 		= { game.width / 2 , game.height / 2 }
	player.velocity 		= {0,0}
	player.acceleration = {0,0}
	player.rotation 		= 0

	player.max_velocity 		= 50.0								-- pixel per second
	player.max_acceleration = 20
	player.rotation_speed 	= 60 / 180 * math.pi	-- degrees per second

	-- Preload image resources
	background = love.graphics.newImage("background.png")
end


function love.update(dt)

	-- calculate the acceleration vector
	if love.keyboard.isDown("up") then
		player.acceleration[1] =  player.max_acceleration * math.sin(player.rotation)
		player.acceleration[2] = -player.max_acceleration * math.cos(player.rotation)
	else
		player.acceleration = {0,0}
	end

	-- rotate ship
	if love.keyboard.isDown("right") then
		player.rotation = player.rotation + player.rotation_speed * dt
	elseif love.keyboard.isDown("left") then
		player.rotation = player.rotation - player.rotation_speed * dt
	end

	-- calculate velocity
	for i = 1,2 do
		player.velocity[i] = player.velocity[i] + player.acceleration[i] * dt
	end
  
  -- limit max speed
  local len = math.sqrt(player.velocity[1]^2 + player.velocity[2]^2)
  if len > player.max_velocity then
  	for i = 1,2 do
      player.velocity[i] = player.velocity[i] / len * player.max_velocity
    end
  end
  
  -- calculate position
	for i = 1,2 do
		player.position[i] = player.position[i] + player.velocity[i] * dt
	end  
end


function love.draw()
	love.graphics.draw(background, 0, 0)
	love.graphics.draw(player.sprite, player.position[1], player.position[2], player.rotation , 1, 1, player.sprite:getWidth() / 2, player.sprite:getHeight() / 2)


	-- Debug Info
	love.graphics.print("speed: "..math.floor(math.sqrt(player.velocity[1]^2 + player.velocity[2]^2)), 100,10)
	love.graphics.print("FPS: " .. love.timer.getFPS(), 10, 10)
end
User avatar
walesmd
Prole
Posts: 22
Joined: Fri Oct 08, 2010 3:11 am
Location: Augusta, GA
Contact:

Re: Trigonometry Help

Post by walesmd »

Thank you very much Adamantos your explanation was very good and I have a better understanding of where I was going wrong. Thanks!
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 1 guest