Fixed second derivative bug! Looks good now; breaking up Update function for better encapsulation during collision detection.

This commit is contained in:
yaw-man 2023-01-14 08:43:54 -04:00
parent 45b919c3ff
commit 64ffc31229
4 changed files with 59 additions and 40 deletions

View File

@ -1,9 +1,6 @@
local function DetectCollision( local function DetectCollision( curMarble, newMarble, curWave, newWave )
xi, yi, vx, vy, xf, yf, local t, r, th, normal
GetRadius, if t then return { t = t, r = r, th = th, normal = normal } end
GetRadialDerivative)
end end
return DetectCollision return DetectCollision

View File

@ -1,10 +1,10 @@
local love = love local love = love
step = 1.0 / 120.0 local step = 1.0 / 120.0
local step = step
local sitelenpona local sitelenpona
local text local text
local marble local marble
local wave local wave
local DetectCollision
local sounds = { local sounds = {
@ -76,6 +76,7 @@ function love.load()
text = assert( require "text" ) text = assert( require "text" )
marble = assert( require "marble" ) marble = assert( require "marble" )
wave = assert( require "wave" ) wave = assert( require "wave" )
DetectCollision = assert ( require "collision" )
return state.Reset() return state.Reset()
end end
@ -129,22 +130,26 @@ local function OnImpact( impact )
local score = BeatScore( impact.t ) local score = BeatScore( impact.t )
--DEBUG --DEBUG
state.lastBeatScore = score state.lastBeatScore = score
local sound
if score > state.beatScoreThreshold then if score > state.beatScoreThreshold then
sound = sounds.goodPing
state.beatScoreThreshold = 1.0 state.beatScoreThreshold = 1.0
state.currentBeat = state.currentBeat + 1 state.currentBeat = state.currentBeat + 1
if state.currentBeat >= 120 then if state.currentBeat >= 120 then
return OnVictory() return OnVictory()
end end
love.audio.play(sounds.goodPing)
else else
sound = sounds.badPing
state.beatScoreThreshold = state.beatScoreThreshold - 0.05 state.beatScoreThreshold = state.beatScoreThreshold - 0.05
love.audio.play(sounds.badPing)
end end
love.audio.play( sound )
end end
@ -165,7 +170,7 @@ function love.draw()
wave.Draw() wave.Draw()
love.graphics.pop() love.graphics.pop()
sitelenpona.Draw( text.tok[state.currentBeat] ) sitelenpona.Draw( text.tok[state.currentBeat] )
marble.Draw() marble.Draw()
@ -177,8 +182,9 @@ end
function love.update( dt ) function love.update( dt )
dt = dt + state.timeToSimulate dt = dt + state.timeToSimulate
while dt > step do while dt > step do
marble.Update() marble.Integrate( step )
wave.Update() wave.Integrate( step )
dt = dt - step dt = dt - step
end end
state.timeToSimulate = dt state.timeToSimulate = dt

View File

@ -3,14 +3,21 @@ local love = love
--local wave = assert( require "wave" ) --local wave = assert( require "wave" )
local oldBuffer = love.graphics.newCanvas() local oldBuffer = love.graphics.newCanvas()
local newBuffer = love.graphics.newCanvas() local newBuffer = love.graphics.newCanvas()
local step = assert( step )
local state local state
local FRICTION = 0.01 local FRICTION = 0.01
local MAXSPEED = 5.0 local MAXSPEED = 5.0
local t, x, y, dx, dy, ddx, ddy local t, x, y, dx, dy, ddx, ddy
local function OnImpact( impact )
end
local function Update() local function Update()
end
local function Integrate( step )
t = love.timer.getTime() t = love.timer.getTime()
dx = (1.0 - FRICTION) * dx + FRICTION * ddx dx = (1.0 - FRICTION) * dx + FRICTION * ddx
@ -95,6 +102,8 @@ end
Reset() Reset()
return { return {
Integrate = Integrate,
OnImpact = OnImpact,
Update = Update, Update = Update,
OnKey = OnKey, OnKey = OnKey,
Draw = Draw, Draw = Draw,

View File

@ -1,8 +1,7 @@
--Render and simulate 1D wave equation. --Render and simulate 1D wave equation.
local love = love local love = love
local step = assert( step )
local N = 25 local N = 11
--Calculate discrete fourier transform of radius function. --Calculate discrete fourier transform of radius function.
local DFT local DFT
@ -80,11 +79,11 @@ local SecondDerivative = function( wave, x )
local y = 0 local y = 0
for k = 1, N / 2 do for k = 1, N / 2 do
local c, s = k * k * math.cos( x * k ), k * k * math.sin( x * k ) local c, s = -k * k * math.cos( x * k ), -k * k * math.sin( x * k )
y = y y = y
- c * re[k + 1] + c * re[k + 1]
- s * im[k + 1] - s * im[k + 1]
- c * re[N - k + 1] + c * re[N - k + 1]
+ s * im[N - k + 1] + s * im[N - k + 1]
end end
@ -119,7 +118,7 @@ local mt = { __index = {
local function Wave( ) local function Wave( )
local t = { local t = {
--radii[k] = radius of point on curve at angle (k - 1) / 13 --radii[k] = radius of point on curve at angle (k - 1) / N
radii = {}, radii = {},
--TIME derivative of radius --TIME derivative of radius
vrad = {}, vrad = {},
@ -130,7 +129,7 @@ local function Wave( )
} }
for i = 1, N do for i = 1, N do
t.radii[i] = 1.0 t.radii[i] = 0.3 * math.sin( i * 2.0 * math.pi / N )
t.vrad[i] = 0.0 t.vrad[i] = 0.0
end end
DFT( t ) DFT( t )
@ -162,23 +161,27 @@ local function Draw()
for k = 0.1, 1.0, 0.1 do for k = 0.1, 1.0, 0.1 do
--Interpolant. --Interpolant.
love.graphics.setColor( 1.0, 0, 0, 0.5 ) love.graphics.setColor( 1.0, 0, 0, 0.7 )
th = ( i - 1 + k ) * 2.0 * math.pi / N th = ( i - 1 + k ) * 2.0 * math.pi / N
r = cur:Interpolate( th ) local r = cur:Interpolate( th )
x, y = r * math.cos( th ), r * math.sin( th ) local x, y = r * math.cos( th ), r * math.sin( th )
love.graphics.circle( "fill", x, y, 0.01 ) --love.graphics.circle( "fill", x, y, 0.01 )
love.graphics.circle( "fill", th / math.pi - 1.0 , r, 0.01)
--First derivative. --First derivative.
love.graphics.setColor( 0, 1.0, 0, 0.5 ) love.graphics.setColor( 0, 1.0, 0, 0.7 )
r = 1.0 + cur:Derivative( th ) r = cur:Derivative( th )
x, y = r * math.cos( th ), r * math.sin( th ) x, y = r * math.cos( th ), r * math.sin( th )
love.graphics.circle( "fill", x, y, 0.01 ) --love.graphics.circle( "fill", x, y, 0.01 )
love.graphics.circle( "fill", th / math.pi - 1.0, r, 0.01)
--Second derivative. --Second derivative.
love.graphics.setColor( 0, 0, 1.0, 0.5 ) love.graphics.setColor( 0, 0, 1.0, 0.7 )
r = 1.0 + cur:SecondDerivative( th ) r = cur:SecondDerivative( th )
x, y = r * math.cos( th ), r * math.sin( th ) x, y = r * math.cos( th ), r * math.sin( th )
love.graphics.circle( "fill", x, y, 0.01 ) --love.graphics.circle( "fill", x, y, 0.01 )
love.graphics.circle( "fill", th / math.pi - 1.0, r, 0.01)
end end
end end
@ -188,23 +191,25 @@ local function Draw()
love.graphics.circle( "fill", x, y, 0.02 ) love.graphics.circle( "fill", x, y, 0.02 )
end end
local function OnImpact( impact )
end
local function Update() local function Update()
end
local function Integrate( step )
local t = love.timer.getTime() local t = love.timer.getTime()
for i = 1, N do for i = 1, N do
local rxx = old:SecondDerivative( 2.0 * math.pi * (i - 1) / N ) cur.radii[i] = old.radii[i]
cur.vrad[i] = 0.7 * old.vrad[i] + 0.5 * step * rxx
cur.radii[i] = old.radii[i] + step * cur.vrad[i]
end end
cur:DFT( ) cur:DFT( )
if love.math.random( 120 ) < 3 then
cur:Impulse( 0, 0.2 )
end
--Deep copy of current state to old state. --Deep copy of current state to old state.
for name, t in pairs( cur ) do for name, t in pairs( cur ) do
for i = 1, 13 do for i = 1, N do
old[name][i] = t[i] old[name][i] = t[i]
end end
end end
@ -225,6 +230,8 @@ Reset()
return { return {
Reset = Reset, Reset = Reset,
Update = Update, Update = Update,
Integrate = Integrate,
OnImpact = OnImpact,
DetectCollision = DetectCollision, DetectCollision = DetectCollision,
Draw = Draw, Draw = Draw,
} }