I'm working on a hammer throwing game using calculus where a circle representing a hammer orbits a circle representing a player. the hammer will orbit the player until the user pushes the "space" key, setting the "thrown" state to true. I'm was hoping to use the derivative of a circle dYdX to determine the slope of the tangent line to the curve at angle ctheta and update the hammer's x value coordinates (kept in a variable called hxpos) by 1 and y value coordinates (hypos) by dYdX. When I say
if hypos < windowwidth/2 and hypos < windowheight/2 then
hxpos = hxpos + 1
hypos = hypos + dYdX
end
I was hoping to increment the y value by dYdX for every unit that hxpos increases, however when I run this code and set the state to "thrown" with the "space" key, the hammer circle does not move at a tangent to the circle at angle ctheta, but rather in a straight horizontal line. Could I have some help to determine why hypos is not being updated by dYdX?
here is my code as it stands. This is my first post here so I'm not sure what the guidelines of posting code are. I've created a pastebin link to my code so this post isn't so cluttered. Is this the way I'm supposed to post code?
https://pastebin.com/Td8ZP83f
I've written my own circle function just so I'd understand how to draw circles without using the circle() function. I've named my circle function which I've named cjrcle() and am keeping in a separate file called cjrcle.lua. here is my cjrcle() function
function cjrcle(r, x, y)
for dtheta = math.pi, 0, -math.pi/512 do
love.graphics.line(r*math.cos(dtheta) + x, r*math.sin(dtheta) + y, r*math.cos(-dtheta) + x, r*math.sin(-dtheta) + y)
end
end
using calculus to determine position
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
using calculus to determine position
- Attachments
-
- main.lua
- (8.97 KiB) Downloaded 146 times
-
- cjrcle.lua
- (430 Bytes) Downloaded 151 times
Re: using calculus to determine position
Just why?Code: Select all
function cjrcle(r, x, y) for dtheta = math.pi, 0, -math.pi/512 do love.graphics.line(r*math.cos(dtheta) + x, r*math.sin(dtheta) + y, r*math.cos(-dtheta) + x, r*math.sin(-dtheta) + y) end end
I can understand if you draw pixels or rectangles, but why lines?
Code: Select all
-- pixilated circle
points = {}
for y = -r, r do -- r is radius, integer
-- mx is min x and max x for current horizontal line
--local mx = r*math.cos (math.arcsin(y/r))
local mx = math.ceil(r*(1-(y/r)^2)^0.5)
for x = -mx, mx do
table.insert (points, x)
table.insert (points, y)
end
end
-- tested
Last edited by darkfrei on Tue Jun 22, 2021 10:09 am, edited 4 times in total.
Re: using calculus to determine position
lines don't have width to them and will thus approximate each point on the circle in π/512 increments. a rectangle would have width to it if it were larger than a pixel so it seemed easier to just use a line directly rather than using many pixels to create the line. Bottom line... it works!
Re: using calculus to determine position
The line is thicker as you think:
https://love2d.org/forums/viewtopic.php?t=88642
Yes, the line (-mx, y, mx, y) must be fast and give full filling. You can also skip some lines and get some hatching.
https://love2d.org/forums/viewtopic.php?t=88642
Yes, the line (-mx, y, mx, y) must be fast and give full filling. You can also skip some lines and get some hatching.
Re: using calculus to determine position
Seriously, why do people have that fixation of using trigonometry instead of linear algebra for linear algebra problems?
The answer to your question is, because you're not calculating dYdX correctly.
But the thing is, that's not the best way to approach this problem. In this case, the tangent to a circle at a point in the perimeter is a vector that is rotated 90° with respect to the radius that goes from the centre to that point. So, take a unit radius, rotate it 90° and you have a tangent vector. Rotating by 90° is trivial: rotating the vector (x, y) by 90° gives you (-y, x). If (x, y) is a unit vector, like the one you get from the sine and cosine of the angle, then the result will also be a unit vector, letting you multiply it by the desired velocity directly.
I see you're also doing some numeric fiddling in order to always increase one of the coordinates by 1. That's not going to give you a constant speed in all directions, and that's bad.
Proof of concept:
You also asked how you paste snippets. If they aren't too long, like in this case, you can paste them using [code]...[/code] tags, like I did in the above proof of concept.
The answer to your question is, because you're not calculating dYdX correctly.
But the thing is, that's not the best way to approach this problem. In this case, the tangent to a circle at a point in the perimeter is a vector that is rotated 90° with respect to the radius that goes from the centre to that point. So, take a unit radius, rotate it 90° and you have a tangent vector. Rotating by 90° is trivial: rotating the vector (x, y) by 90° gives you (-y, x). If (x, y) is a unit vector, like the one you get from the sine and cosine of the angle, then the result will also be a unit vector, letting you multiply it by the desired velocity directly.
I see you're also doing some numeric fiddling in order to always increase one of the coordinates by 1. That's not going to give you a constant speed in all directions, and that's bad.
Proof of concept:
Code: Select all
local px, py = 400, 300
local hradius = 50 -- radius of hammer
local hx, hy -- hammer position
local hnx, hny -- normal
local hangle = 0 -- hammer angle with respect to player
local omega = math.rad(60) -- angular velocity = 60 degrees per second
local thrown = false
local first_time = true
local unitx, unity -- unit vector with angle = hangle
function love.keypressed(k)
if k == "escape" then return love.event.quit() end
if k == "space" then
thrown = true
end
end
function love.update(dt)
-- If it's the first time and the key comes before any variable is assigned,
-- there will be errors. The variable first_time causes that in this case,
-- the hammer angle calculations are run at least once.
if first_time or not thrown then
unitx = math.cos(hangle)
unity = math.sin(hangle)
-- calculate position of hammer in the circle
hx = unitx * hradius + px
hy = unity * hradius + py
-- normal = unit rotated 90 deg
hnx = -unity
hny = unitx
-- increase angle by angular velocity
hangle = hangle + omega * dt
end
if thrown then
-- Tangential speed is omega * hradius.
-- Delta speed is tangential speed * delta time.
local dspeed = omega * hradius * dt
-- The unit direction vector is the normal, (hnx, hny).
hx = hx + dspeed * hnx
hy = hy + dspeed * hny
end
first_time = false
end
function love.draw()
love.graphics.circle("line", px, py, hradius)
love.graphics.circle("fill", hx, hy, 10)
local orig_x = px + unitx * hradius
local orig_y = py + unity * hradius
love.graphics.line(px, py, orig_x, orig_y)
love.graphics.line(orig_x, orig_y,
orig_x + hnx * hradius * omega,
orig_y + hny * hradius * omega)
end
Who is online
Users browsing this forum: Bing [Bot], Google [Bot] and 199 guests