--Character controller. Renders point particle. local love = love --local wave = assert( require "wave" ) local oldBuffer = love.graphics.newCanvas() local newBuffer = love.graphics.newCanvas() local oldState, curState, newState local FRICTION = 0.01 local MAXSPEED = 5.0 local ddx, ddy = 0.0, 0.0 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. if not impact.tNext then return end 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 OnKey() ddx = (love.keyboard.isScancodeDown( "d" ) and 1.0 or 0.0) - (love.keyboard.isScancodeDown( "a" ) and 1.0 or 0.0) ddy = (love.keyboard.isScancodeDown( "w" ) and 1.0 or 0.0) - (love.keyboard.isScancodeDown( "s" ) and 1.0 or 0.0) local n = math.sqrt( ddx * ddx + ddy * ddy ) if n < 0.001 then return end ddx, ddy = ddx / n, ddy / n end local function Draw() --Extrapolate forward for slightly smoother rendering. local dt = love.timer.getTime() - curState.t Integrate( dt + 1 / 60.0 ) 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 ) love.graphics.setCanvas( newBuffer ) love.graphics.setColor( 1.0, 1.0, 1.0 , 0.99 ) -- White. love.graphics.draw( oldBuffer ) --Time-dependent fade: overlay canvas over itself. --Render latest segment in trail. love.graphics.setColor( 245 / 255, 169 / 255, 184 / 255, 1.0 ) --Trans pink. --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) love.graphics.circle( "fill", xn, yn, 4.0 ) love.graphics.setCanvas( oldBuffer ) love.graphics.clear( 1.0, 1.0, 1.0, 0.0 ) --Render circle directly to screen. love.graphics.setCanvas() love.graphics.draw( newBuffer ) --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 ) oldBuffer, newBuffer = newBuffer, oldBuffer end local function Impact( impact ) end --Window resize. local function Resize() newBuffer = love.graphics.newCanvas() --TODO: render oldBuffer to new newBuffer, but scaled down. oldBuffer = love.graphics.newCanvas() end local function Reset() oldState, curState, newState = State(), State(), State() Resize() end Reset() return { Integrate = Integrate, OnImpact = OnImpact, Update = Update, OnKey = OnKey, Draw = Draw, Impact = Impact, Reset = Reset, Resize = Resize, Current = Current, Next = Next, }