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
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

View File

@ -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,
}

View File

@ -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,
}