Final FINAL physics tweaks. Game is done. Doing audio only until deadline.

This commit is contained in:
yaw-man 2023-01-15 22:38:15 -04:00
parent e600760281
commit 25a3047a10
5 changed files with 95 additions and 54 deletions

View File

@ -1,8 +1,9 @@
local love = love
local passChimes = {}
local failChimes = {}
local wineChimes = {}
local drones = {}
local N = 8
local N = 12
love.audio.setDistanceModel( "exponentclamped" )
@ -13,50 +14,70 @@ local function StartDrones()
decaytime = 20}
)
drones.fuck = love.audio.newSource("sounds/noiseloop.flac", "static" )
drones.bass = love.audio.newSource("sounds/drone.flac", "stream")
drones.alto = love.audio.newSource("sounds/drone.flac", "stream")
drones.bass:setVolume( 0 )
drones.bass:setPitch( 0.125 )
drones.alto:setVolume( 0 )
drones.bass:setPitch( 0.25 )
drones.bass:setEffect( "droneReverb", true )
drones.alto:setEffect( "droneReverb", true )
drones.bass:stop()
drones.alto:setVolume( 0 )
drones.alto:setPitch( 2 )
drones.alto:setEffect( "droneReverb", true )
drones.alto:stop()
drones.fuck:setVolume( 0 )
drones.fuck:setPitch( 0.125 )
drones.fuck:setEffect( "droneReverb", true )
drones.fuck:stop()
love.audio.play( drones.bass )
love.audio.play( drones.alto )
love.audio.play( drones.fuck )
end
love.audio.setEffect( "passChimeReverb", {
type = "reverb",
volume = 1.0, } )
volume = 1.0,
gain = 1.0,} )
local wineChime = love.audio.newSource("sounds/chimewinedolce.flac", "static")
wineChime:setEffect( "passChimeReverb", true )
local passChime = love.audio.newSource("sounds/chimeb.flac", "static")
passChime:setEffect( "passChimeReverb", true )
local failChime = love.audio.newSource("sounds/chime.flac", "static")
failChime:setEffect( "passChimeReverb", true )
for i = 1, N do
wineChimes[i] = wineChime:clone()
passChimes[i] = passChime:clone()
failChimes[i] = failChime:clone()
end
local idxNextPassChime = 1
local idxNextFailChime = 1
local function GetNextPassChime( pass )
local idxNextWineChime = 1
local function GetNextPassChime( )
idxNextPassChime = idxNextPassChime % N + 1
return passChimes[ idxNextPassChime ]
end
local function GetNextFailChime( pass )
local function GetNextFailChime( )
idxNextFailChime = idxNextFailChime % N + 1
return failChimes[ idxNextFailChime ]
end
local function GetNextWineChime( )
idxNextWineChime = idxNextWineChime % N + 1
return wineChimes[ idxNextWineChime ]
end
local pitches =
{
1/2,
3/4,
1,
2/3,
3/2,
@ -69,7 +90,7 @@ local pitches =
local function GetPitch( th )
th = 0.5 + 0.5 * th / math.pi
return pitches[ 1 + math.floor( th * 7 )]
return pitches[ 1 + math.floor( th * 9 )]
end
local function OnImpact( impact, score, pass, level )
@ -83,7 +104,8 @@ local function OnImpact( impact, score, pass, level )
love.audio.setEffect( "passChimeReverb", {
type = "reverb",
volume = 1.0,
gain = 0.1 + level / 200} )
gain = 0.1 + 0.9 * level / 120,
highgain = 0.3,} )
end
@ -94,8 +116,8 @@ local function OnImpact( impact, score, pass, level )
local chime = pass and GetNextPassChime() or GetNextFailChime()
chime:setPitch( GetPitch( th ) )
chime:setPosition( r * math.cos( th ), r * math.sin( th ) )
chime:setVolume( 0.1 + level / 200 )
local highgain = math.max( 0, math.min( score, 1.0 ) - (pass and 0.0 or 0.9))
chime:setVolume( 0.1 + 0.9 * level / 120.0 )
local highgain = math.max( 0, math.min( score, 1.0 ) - (pass and 0.5 or 0.9))
chime:setFilter{
type = "lowpass",
volume = 0.5 * impact.speed,
@ -103,6 +125,14 @@ local function OnImpact( impact, score, pass, level )
}
love.audio.stop( chime )
love.audio.play( chime )
local wineChime = GetNextWineChime()
wineChime:setPitch( GetPitch( th ) )
wineChime:setPosition( love.math.random(), love.math.random() )
wineChime:setVolume( impact.speed * math.max( 0.0, level / 60.0 - 0.5 ) )
love.audio.stop( wineChime )
love.audio.play( wineChime )
end
@ -110,21 +140,29 @@ local function OnVictory( )
love.audio.setEffect( "passChimeReverb", {
type = "reverb",
volume = 1.0,
decaytime = 20,} )
decaytime = 20,
lategain = 9.5,
gain = 1.0,
} )
love.audio.setEffect( "droneReverb", {
type = "reverb",
volume = 1.0,
decaytime = 20,} )
decaytime = 20,
lategain = 10,
gain = 1.0,} )
end
--score is the hypothetical "beat score" that would be attained
--if an impact took place at this instant.
local function Update( score, level )
if level > 2 then
drones.bass:setVolume( 0.5 * math.sqrt( score ) * (level / 120) )
drones.alto:setVolume( 0.3 * score * ( level / 120 ))
level = level / 120.0
drones.bass:setVolume( 0.5 * math.sqrt( score ) * level )
drones.alto:setVolume( 0.3 * score * level * level)
end
end

View File

@ -75,7 +75,7 @@ OnImpact = function( impact )
particles:emit( 50 * score * score )
audio.OnImpact( impact, score, pass, state.currentBeat )
marble.OnImpact( impact )
marble.OnImpact( impact, state.currentBeat )
wave.OnImpact( impact, state.currentBeat )
end
local _OnImpact = OnImpact
@ -191,19 +191,17 @@ OnVictory = function()
particles:setParticleLifetime( 0, 30 )
particles:setSizes( 0.001, 0.0001, 0.0005 )
particles:setColors(
1, 1, 1, 1,
245 / 255, 169 / 255, 184 / 255, 1,
1, 1, 1, 1,
1, 1, 1, 0,
0, 0, 0, 1,
245 / 255, 169 / 255, 184 / 255, 1,
0, 0, 0, 1,
1, 1, 1, 0,
245 / 255, 169 / 255, 184 / 255, 1,
1, 1, 1, 0
)
particles:setPosition( 0, 0 )
particles:setEmissionArea( "normal", 0.5, 0.5, 0, true )
particles:emit( 500 )
particles:setEmissionArea( "normal", 0.1, 0.1, 0, true )
particles:setEmissionArea( "normal", 0.01, 0.01, 0, true )
love.graphics.setCanvas( marble.Canvas() )
love.graphics.setCanvas()
@ -221,7 +219,7 @@ OnVictory = function()
end
local marblePos = marble.Current()
particles:emit( 10 )
particles:emit( 1 )
particles:update( dt )
particles:moveTo( marblePos.x, marblePos.y )
end

View File

@ -5,8 +5,8 @@ local oldBuffer = love.graphics.newCanvas()
local newBuffer = love.graphics.newCanvas()
local oldState, curState, newState
local INERTIA= 0.03
local MAXSPEED = 3
local INERTIA = 0.01
local MAXSPEED = 6
local ddx, ddy = 0.0, 0.0
local function State( )
@ -21,20 +21,19 @@ function marble.GetAcceleration( ) return ddx, ddy end
function marble.Integrate( step )
newState.t = love.timer.getTime()
newState.dx = (1.0 - INERTIA
) * curState.dx + INERTIA
* ddx
newState.dy = (1.0 - INERTIA
) * curState.dy + INERTIA
* ddy
newState.dx = (1.0 - INERTIA) * curState.dx + INERTIA * ddx
newState.dy = (1.0 - INERTIA) * curState.dy + INERTIA * ddy
newState.x = curState.x + newState.dx * step * MAXSPEED
newState.y = curState.y + newState.dy * step * MAXSPEED
end
function marble.OnImpact( impact )
function marble.OnImpact( impact, level )
--Adjust current trajectory according to collision.
if not impact.dt then return end
INERTIA = 0.05 - 0.04 * ( level / 120.0 )
MAXSPEED = 2.0 + 4.0 * ( level / 120.0 )
local x, y = impact.r * math.cos( impact.th ), impact.r * math.sin( impact.th )
local vx, vy = newState.dx, newState.dy --Velocity of particle going into collision.
local unx, uny = math.cos( impact.normal ), math.sin( impact.normal ) --Outward-facing normal of wave.
@ -49,16 +48,16 @@ function marble.OnImpact( impact )
else
uvx, uvy = vx / speed , vy / speed
end
--Get signed angle between normal and incoming velocity (both unit vectors)
local dot = unx * uvy - uny * uvx
--Fudge factor: apply an impulse inward so that you don't stick or slide on the wave.
local inward = ( dot > 0 ) and dot or -dot
inward = inward * inward * inward
--Calculate the rotation matrix:
--counterclockwise rotation by 2 * pi - 2 * arccos( n dot v )
local c, s = 1 - 2 * dot * dot, - 2 * dot * math.sqrt( 1 - dot * dot )
@ -66,14 +65,14 @@ function marble.OnImpact( impact )
local vxout, vyout =
inward * (- math.cos(impact.th) ) - (1.0 - inward) * ( vx * c - vy * s ),
inward * (- math.sin(impact.th) ) - (1.0 - inward) * ( x * s + vy * c )
curState.x, curState.y = x, y
curState.dx, curState.dy = vxout, vyout
--[[debugRenderImpact = { xi = x, yi = y, xf = x - vx, yf = y - vy,
xn = 0.2 * unx + x, yn = 0.2 * uny + y,
vxout = x + vxout, vyout = y + vyout}]]
return marble.Integrate( math.max( impact.dt , 1 / 120 ) ) --Hmm! Maybe this should be a fixed step instead for stability's sake.
end
@ -90,14 +89,14 @@ end
function marble.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
function marble.OnVictory()
--[[marble.Draw = function()
--Extrapolate forward for slightly smoother rendering.
@ -125,7 +124,7 @@ function marble.Draw()
--Extrapolate forward for slightly smoother rendering.
local dt = love.timer.getTime() - curState.t
marble.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 )
@ -133,7 +132,7 @@ function marble.Draw()
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 )
@ -143,17 +142,17 @@ function marble.Draw()
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.setColor( 1, 1, 1, 1.0 ) --White.
love.graphics.setLineWidth( 1.0 )
--love.graphics.circle( "line", xn, yn, 4 )
oldBuffer, newBuffer = newBuffer, oldBuffer
end
@ -161,7 +160,7 @@ end
marble._Draw = marble.Draw
function marble.Impact( impact )
end
--Window resize.
@ -169,11 +168,15 @@ function marble.Resize()
newBuffer = love.graphics.newCanvas()
--TODO: render oldBuffer to new newBuffer, but scaled down.
oldBuffer = love.graphics.newCanvas()
end
function marble.Reset()
function marble.Reset()
INERTIA = 0.05
MAXSPEED = 2.0
oldState, curState, newState = State(), State(), State()
marble.Resize()
marble.Draw = marble._Draw

View File

@ -15,8 +15,8 @@ sp.Draw = function( t )
if #t == 1 then
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 128, cy - 128 )
elseif #t == 2 then
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 128, cy - 64, 0, 0.5, 0.5 )
love.graphics.draw( sp[t[2]] or sp.pilin, cx, cy - 64, 0, 0.5, 0.5 )
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 144, cy - 96, 0, 0.75, 0.75 )
love.graphics.draw( sp[t[2]] or sp.pilin, cx - 16, cy - 96, 0, 0.75, 0.75 )
elseif #t == 3 then
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 128, cy - 64, 0, 0.5, 0.5 )
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 128, cy - 64, 0, 0.5, 0.5 )

View File

@ -39,9 +39,11 @@ for foot in s:gmatch( ".-%-" ) do
local j = 1
for w in foot:gmatch( [["]] ) do
word[j] = isTe and "te" or "to"
isTe = not( isTe )
j = j + 1
end
for w in foot:gmatch( "%a+" ) do
@ -59,7 +61,7 @@ local function Draw( beat )
if beat == 1 then
love.graphics.setColor(0.0, 0.0, 0.0, 1.0)
love.graphics.printf( "wasd.space",
0, 0.5 * love.graphics.getHeight(),
0, 0,
love.graphics.getWidth(),
"center"
)