Smoother particle display; store particle states. Forward integration remains.

This commit is contained in:
yaw-man 2023-01-14 09:48:52 -04:00
parent 64ffc31229
commit 5a24ffcd42
3 changed files with 87 additions and 51 deletions

View File

@ -126,7 +126,7 @@ local function OnVictory()
end end
local function OnImpact( impact ) local function OnImpact( impact )
if not impact then return end
local score = BeatScore( impact.t ) local score = BeatScore( impact.t )
--DEBUG --DEBUG
state.lastBeatScore = score state.lastBeatScore = score
@ -150,6 +150,9 @@ local function OnImpact( impact )
end end
love.audio.play( sound ) love.audio.play( sound )
marble.OnImpact( impact )
wave.OnImpact( impact )
end end
@ -185,6 +188,14 @@ function love.update( dt )
marble.Integrate( step ) marble.Integrate( step )
wave.Integrate( step ) wave.Integrate( step )
OnImpact(
DetectCollision(
marble.Current(), marble.Next(),
wave.Current(), wave.Next() ))
marble.Update()
wave.Update()
dt = dt - step dt = dt - step
end end
state.timeToSimulate = dt state.timeToSimulate = dt

View File

@ -3,31 +3,41 @@ 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 state local oldState, curState, newState
local FRICTION = 0.01 local FRICTION = 0.01
local MAXSPEED = 5.0 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 ) 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 end
local function Update() local function Update()
--Roll the log.
for k, v in pairs( oldState ) do
oldState[k] = curState[k]
curState[k] = newState[k]
end
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() local function OnKey()
ddx = (love.keyboard.isScancodeDown( "d" ) and 1.0 or 0.0) - (love.keyboard.isScancodeDown( "a" ) and 1.0 or 0.0) 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 end
local function Draw() local function Draw()
local dt = love.timer.getTime() - t
local xf, yf = x + dt * dx, y + dt * dy
local w, h = love.graphics.getDimensions() love.graphics.print( ddx, 0, 100 )
local xi, yi = transform:transformPoint( x, y ) love.graphics.print( ddy, 0, 110 )
xf, yf = transform:transformPoint( xf, yf )
love.graphics.setColor( 0, 0, 0, 1 ) local xp, yp = transform:transformPoint( oldState.x, oldState.y )
love.graphics.print( x, 0, 60 ) local xc, yc = transform:transformPoint( curState.x, curState.y )
love.graphics.print( y, 0, 80 ) 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.setCanvas( newBuffer )
love.graphics.setColor( 1.0, 1.0, 1.0 , 0.99 ) -- White. love.graphics.setColor( 1.0, 1.0, 1.0 , 0.99 ) -- White.
@ -57,8 +68,13 @@ local function Draw()
--Render latest segment in trail. --Render latest segment in trail.
love.graphics.setColor( 245 / 255, 169 / 255, 184 / 255, 1.0 ) --Trans pink. 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 ) --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.setCanvas( oldBuffer )
love.graphics.clear( 1.0, 1.0, 1.0, 0.0 ) love.graphics.clear( 1.0, 1.0, 1.0, 0.0 )
@ -66,9 +82,9 @@ local function Draw()
--Render circle directly to screen. --Render circle directly to screen.
love.graphics.setCanvas() love.graphics.setCanvas()
love.graphics.draw( newBuffer ) 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.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 oldBuffer, newBuffer = newBuffer, oldBuffer
@ -88,13 +104,8 @@ local function Resize()
end end
local function Reset() local function Reset()
t = love.timer.getTime() oldState, curState, newState = State(), State(), State()
x = 0 Resize()
y = 0
dx = 0
dy = 0
ddx = 0
ddy = 0
end end
@ -110,4 +121,6 @@ return {
Impact = Impact, Impact = Impact,
Reset = Reset, Reset = Reset,
Resize = Resize, Resize = Resize,
Current = Current,
Next = Next,
} }

View File

@ -1,7 +1,11 @@
--Render and simulate 1D wave equation. --Render and simulate 1D wave equation.
local love = love 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. --Calculate discrete fourier transform of radius function.
local DFT local DFT
@ -137,11 +141,6 @@ local function Wave( )
return setmetatable(t, mt) return setmetatable(t, mt)
end end
local old = Wave() --State at beginning of tick.
local cur = Wave() --State at end of tick.
local function Draw() local function Draw()
-- Blue circle. -- Blue circle.
@ -159,6 +158,7 @@ local function Draw()
love.graphics.circle( "fill", cx, cy, 0.02 ) love.graphics.circle( "fill", cx, cy, 0.02 )
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.7 ) love.graphics.setColor( 1.0, 0, 0, 0.7 )
@ -182,6 +182,9 @@ local function Draw()
--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) 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
end end
@ -197,16 +200,6 @@ end
local function Update() 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. --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, N do for i = 1, N do
@ -214,6 +207,22 @@ local function Integrate( step )
end end
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 end
local function DetectCollision( px, py, vpx, vpy ) local function DetectCollision( px, py, vpx, vpy )
@ -223,6 +232,7 @@ end
local function Reset() local function Reset()
old = Wave() old = Wave()
cur = Wave() cur = Wave()
new = Wave()
end end
Reset() Reset()
@ -234,4 +244,6 @@ return {
OnImpact = OnImpact, OnImpact = OnImpact,
DetectCollision = DetectCollision, DetectCollision = DetectCollision,
Draw = Draw, Draw = Draw,
Current = Current,
Next = Next,
} }