From 5a24ffcd42f0524b2400cf7f52d971467ebc5aa3 Mon Sep 17 00:00:00 2001 From: yaw-man Date: Sat, 14 Jan 2023 09:48:52 -0400 Subject: [PATCH] Smoother particle display; store particle states. Forward integration remains. --- main.lua | 15 +++++++++-- marble.lua | 79 +++++++++++++++++++++++++++++++----------------------- wave.lua | 44 +++++++++++++++++++----------- 3 files changed, 87 insertions(+), 51 deletions(-) diff --git a/main.lua b/main.lua index 63cdc9e..0d7e1a8 100644 --- a/main.lua +++ b/main.lua @@ -126,7 +126,7 @@ local function OnVictory() end local function OnImpact( impact ) - + if not impact then return end local score = BeatScore( impact.t ) --DEBUG state.lastBeatScore = score @@ -150,6 +150,9 @@ local function OnImpact( impact ) end love.audio.play( sound ) + + marble.OnImpact( impact ) + wave.OnImpact( impact ) end @@ -184,7 +187,15 @@ function love.update( dt ) while dt > step do marble.Integrate( step ) wave.Integrate( step ) - + + OnImpact( + DetectCollision( + marble.Current(), marble.Next(), + wave.Current(), wave.Next() )) + + marble.Update() + wave.Update() + dt = dt - step end state.timeToSimulate = dt diff --git a/marble.lua b/marble.lua index 4ed3571..8b28456 100644 --- a/marble.lua +++ b/marble.lua @@ -3,31 +3,41 @@ local love = love --local wave = assert( require "wave" ) local oldBuffer = love.graphics.newCanvas() local newBuffer = love.graphics.newCanvas() -local state +local oldState, curState, newState + local FRICTION = 0.01 local MAXSPEED = 5.0 +local ddx, ddy = 0.0, 0.0 -local t, x, y, dx, dy, ddx, ddy +local function State( ) + return { t = 0, x = 0, y = 0, dx = 0, dy = 0 } +end + +local function Current() return curState end +local function Next() return newState end + +local function Integrate( step ) + newState.t = love.timer.getTime() + newState.dx = (1.0 - FRICTION) * curState.dx + FRICTION * ddx + newState.dy = (1.0 - FRICTION) * curState.dy + FRICTION * ddy + newState.x = curState.x + newState.dx * step * MAXSPEED + newState.y = curState.y + newState.dy * step * MAXSPEED +end local function OnImpact( impact ) - + --Adjust current trajectory according to collision. + return Integrate( impact.tNext - impact.t ) --Hmm! Maybe this should be a fixed step instead for stability's sake. end local function Update() - + --Roll the log. + for k, v in pairs( oldState ) do + oldState[k] = curState[k] + curState[k] = newState[k] + end end -local function Integrate( step ) - t = love.timer.getTime() - dx = (1.0 - FRICTION) * dx + FRICTION * ddx - dy = (1.0 - FRICTION) * dy + FRICTION * ddy - local xf = x + dx * step * MAXSPEED - local yf = y + dy * step * MAXSPEED - - x = xf - y = yf -end local function OnKey() ddx = (love.keyboard.isScancodeDown( "d" ) and 1.0 or 0.0) - (love.keyboard.isScancodeDown( "a" ) and 1.0 or 0.0) @@ -39,17 +49,18 @@ local function OnKey() end local function Draw() - local dt = love.timer.getTime() - t - local xf, yf = x + dt * dx, y + dt * dy - local w, h = love.graphics.getDimensions() - local xi, yi = transform:transformPoint( x, y ) - xf, yf = transform:transformPoint( xf, yf ) + love.graphics.print( ddx, 0, 100 ) + love.graphics.print( ddy, 0, 110 ) - love.graphics.setColor( 0, 0, 0, 1 ) - love.graphics.print( x, 0, 60 ) - love.graphics.print( y, 0, 80 ) + local xp, yp = transform:transformPoint( oldState.x, oldState.y ) + local xc, yc = transform:transformPoint( curState.x, curState.y ) + local xn, yn = transform:transformPoint( newState.x, newState.y ) + local dt = love.timer.getTime() - newState.t --Integrate forward for slightly smoother rendering. + local xf, yf = transform:transformPoint( + newState.x + dt * newState.dx, + newState.y + dt * newState.dy ) love.graphics.setCanvas( newBuffer ) love.graphics.setColor( 1.0, 1.0, 1.0 , 0.99 ) -- White. @@ -57,8 +68,13 @@ local function Draw() --Render latest segment in trail. love.graphics.setColor( 245 / 255, 169 / 255, 184 / 255, 1.0 ) --Trans pink. - love.graphics.circle( "fill", xf, yf, 4.0 ) --TODO: replace with segments. --love.graphics.line( xi, yi, xf, yf ) + --Segment stuff: + love.graphics.setLineJoin( "bevel" ) + love.graphics.setLineStyle( "smooth" ) + love.graphics.setLineWidth( 8.0 ) + love.graphics.line( xp, yp, xc, yc, xn, yn, xf, yf ) + love.graphics.circle( "fill", xf, yf, 4.0 ) love.graphics.setCanvas( oldBuffer ) love.graphics.clear( 1.0, 1.0, 1.0, 0.0 ) @@ -66,9 +82,9 @@ local function Draw() --Render circle directly to screen. love.graphics.setCanvas() love.graphics.draw( newBuffer ) - love.graphics.circle( "fill", xf, yf, 5.0 ) + --love.graphics.circle( "fill", xf, yf, 5.0 ) love.graphics.setColor( 1, 1, 1, 1.0 ) --White. - love.graphics.circle( "line", xf, yf, 5.0 ) + --love.graphics.circle( "line", xf, yf, 5.0 ) oldBuffer, newBuffer = newBuffer, oldBuffer @@ -87,14 +103,9 @@ local function Resize() end -local function Reset() - t = love.timer.getTime() - x = 0 - y = 0 - dx = 0 - dy = 0 - ddx = 0 - ddy = 0 +local function Reset() + oldState, curState, newState = State(), State(), State() + Resize() end @@ -110,4 +121,6 @@ return { Impact = Impact, Reset = Reset, Resize = Resize, + Current = Current, + Next = Next, } \ No newline at end of file diff --git a/wave.lua b/wave.lua index 4add5b0..28f6151 100644 --- a/wave.lua +++ b/wave.lua @@ -1,7 +1,11 @@ --Render and simulate 1D wave equation. local love = love +local old, cur, new --States add beginning of last tick, current tick, and next tick respectively. -local N = 11 +local N = 13 + +local function Current() return cur end +local function Next() return new end --Calculate discrete fourier transform of radius function. local DFT @@ -137,11 +141,6 @@ local function Wave( ) return setmetatable(t, mt) end - -local old = Wave() --State at beginning of tick. -local cur = Wave() --State at end of tick. - - local function Draw() -- Blue circle. @@ -157,6 +156,7 @@ local function Draw() love.graphics.setCanvas() love.graphics.setColor( 0, 0, 0, 0.5 ) love.graphics.circle( "fill", cx, cy, 0.02 ) + for k = 0.1, 1.0, 0.1 do @@ -182,6 +182,9 @@ local function Draw() --love.graphics.circle( "fill", x, y, 0.01 ) love.graphics.circle( "fill", th / math.pi - 1.0, r, 0.01) + love.graphics.setColor( 1.0, 1.0, 1.0, 0.2 ) + love.graphics.circle( "fill", 2.0 * ( i + k ) / N - 1.2, 0, 0.02 ) + end end @@ -196,23 +199,29 @@ local function OnImpact( impact ) end local function Update() - -end -local function Integrate( step ) - local t = love.timer.getTime() - for i = 1, N do - cur.radii[i] = old.radii[i] - end - - cur:DFT( ) - --Deep copy of current state to old state. for name, t in pairs( cur ) do for i = 1, N do old[name][i] = t[i] end end + + --Deep copy of new state to current state. + for name, t in pairs( new ) do + for i = 1, N do + cur[name][i] = t[i] + end + end +end + +local function Integrate( step ) + local t = love.timer.getTime() + for i = 1, N do + new.radii[i] = 0.05 * math.cos( math.sin( t * 0.05 + i ) ) + end + + cur:DFT( ) end @@ -223,6 +232,7 @@ end local function Reset() old = Wave() cur = Wave() + new = Wave() end Reset() @@ -234,4 +244,6 @@ return { OnImpact = OnImpact, DetectCollision = DetectCollision, Draw = Draw, + Current = Current, + Next = Next, } \ No newline at end of file