243 lines
5.1 KiB
Lua
243 lines
5.1 KiB
Lua
local love = love
|
|
local step = 1.0 / 120
|
|
local sitelenpona
|
|
local text
|
|
local marble
|
|
local wave
|
|
local DetectCollision
|
|
|
|
local sounds = {
|
|
|
|
|
|
}
|
|
|
|
|
|
local state
|
|
state = {
|
|
|
|
Reset = function()
|
|
state.beat = {}
|
|
state.startTime = love.timer.getTime()
|
|
state.currentBeat = 1
|
|
state.timeToSimulate = 0.0
|
|
end,
|
|
|
|
timeToSimulate = 0.0,
|
|
isGameStarted = false,
|
|
beatScoreThreshold = 1.0,
|
|
lastBeatScore = 0.0,
|
|
currentBeat = 1,
|
|
startTime = 0.0,
|
|
|
|
wave = {
|
|
x = { 1.0, 0.0, -0.5, 0.2, 0.4, 0.8, 0.3, 0.9, -0.4, 0.8, 0.5, 0.1, -0.9 },
|
|
dx = { 1.0, 0.0, -0.5, 0.2, 0.4, 0.8, 0.3, 0.9, -0.4, 0.8, 0.5, 0.1, -0.9 },
|
|
ddx = { 1.0, 0.0, -0.5, 0.2, 0.4, 0.8, 0.3, 0.9, -0.4, 0.8, 0.5, 0.1, -0.9 },
|
|
X = function(th) end,
|
|
DX = function(th) end,
|
|
DDX = function(th) end,
|
|
Draw = function() end,
|
|
AddImpulse = function( th, size ) end,
|
|
|
|
ImpactPoint = function( xi, yi, xf, yf )
|
|
local impact = { r = 0, th = 0, t = 0, x = 0, y = 0, dx = 0, dy = 0 }
|
|
return impact
|
|
end,
|
|
|
|
Update = function( dt ) end,
|
|
},
|
|
|
|
beat = {
|
|
t = nil,
|
|
mu = nil,
|
|
},
|
|
}
|
|
|
|
local function UpdateWindowTransform( w, h )
|
|
local d = math.min( w, h )
|
|
local r = love.graphics.get
|
|
local tf = love.math.newTransform()
|
|
|
|
local size = 3
|
|
|
|
tf:translate( w / 2, h / 2)
|
|
tf:scale( d / size, -d / size )
|
|
transform = tf
|
|
end
|
|
|
|
function love.load()
|
|
UpdateWindowTransform( love.graphics.getDimensions() )
|
|
|
|
love.graphics.setBackgroundColor( 245 / 255, 169 / 255, 184 / 255 ) --Trans pink.
|
|
--love.graphics.setBackgroundColor( 91 / 255, 206 / 255, 250 / 255 ) --Trans blue.
|
|
sounds.goodPing = love.audio.newSource("sounds/soundTest.ogg", "static")
|
|
sounds.badPing = love.audio.newSource("sounds/chime8.ogg", "static")
|
|
sitelenpona = assert( require "sitelenpona" )
|
|
text = assert( require "text" )
|
|
marble = assert( require "marble" )
|
|
wave = assert( require "wave" )
|
|
DetectCollision = assert ( require "collision" )
|
|
return state.Reset()
|
|
|
|
end
|
|
|
|
|
|
local function BeatScore( t )
|
|
local beat = state.beat
|
|
|
|
--Base case 1: first tap.
|
|
if not beat.t then
|
|
beat.t = t
|
|
return 2.0
|
|
end
|
|
|
|
local dt = t - beat.t
|
|
beat.t = t
|
|
|
|
--Base case 2: second tap.
|
|
if not beat.mu then
|
|
beat.mu = dt
|
|
return 2.0
|
|
end
|
|
|
|
--General case: update average beat length.
|
|
local WEIGHT = 0.25 --High number makes the last beat more significant.
|
|
local mu = ( 1.0 - WEIGHT ) * beat.mu + WEIGHT * dt
|
|
beat.mu = mu
|
|
|
|
--Safety: avoid a dbz.
|
|
if mu < 0.001 or dt < 0.001 then
|
|
return 0.0
|
|
--error( "DBZ! Beat length too small." )
|
|
end
|
|
|
|
--Calculate beat score.
|
|
local score = dt * dt / ( mu * mu )
|
|
local TOLERANCE = 1.04
|
|
if dt < mu then
|
|
return TOLERANCE * score
|
|
else
|
|
return TOLERANCE / score
|
|
end
|
|
|
|
end
|
|
|
|
local function OnVictory()
|
|
|
|
end
|
|
|
|
local function OnImpact( impact )
|
|
if not impact then return end
|
|
local score = BeatScore( impact.t )
|
|
--DEBUG
|
|
state.lastBeatScore = score
|
|
|
|
local sound
|
|
if score > state.beatScoreThreshold then
|
|
sound = sounds.goodPing
|
|
|
|
state.beatScoreThreshold = 1.0
|
|
state.currentBeat = state.currentBeat + 1
|
|
if state.currentBeat >= 120 then
|
|
return OnVictory()
|
|
end
|
|
|
|
|
|
else
|
|
|
|
sound = sounds.badPing
|
|
state.beatScoreThreshold = state.beatScoreThreshold - 0.05
|
|
|
|
end
|
|
|
|
love.audio.play( sound )
|
|
|
|
marble.OnImpact( impact )
|
|
wave.OnImpact( impact )
|
|
end
|
|
|
|
|
|
|
|
function love.draw()
|
|
|
|
|
|
--[[love.graphics.setColor(1.0, 1.0, 1.0)
|
|
love.graphics.print( state.beat.mu or 0, 0)
|
|
love.graphics.print( state.beat.t or 0, 0, 10)
|
|
love.graphics.print( state.beatScoreThreshold, 0, 20)
|
|
love.graphics.print( state.lastBeatScore, 0, 30 )]]
|
|
|
|
|
|
|
|
love.graphics.push( "transform" )
|
|
love.graphics.applyTransform( transform )
|
|
wave.Draw()
|
|
|
|
if debugRenderImpact then
|
|
|
|
love.graphics.setLineWidth( 0.01 )
|
|
love.graphics.setColor( 1, 0, 0, 0.5 ) --Red: Incoming
|
|
love.graphics.line(
|
|
debugRenderImpact.xi,
|
|
debugRenderImpact.yi,
|
|
debugRenderImpact.xf,
|
|
debugRenderImpact.yf)
|
|
love.graphics.setColor( 0, 1, 0, 0.5 ) --Green: Normal
|
|
love.graphics.line(
|
|
debugRenderImpact.xi,
|
|
debugRenderImpact.yi,
|
|
debugRenderImpact.xn,
|
|
debugRenderImpact.yn)
|
|
love.graphics.setColor( 0, 0, 1, 0.5 ) -- Blue: Outgoing
|
|
love.graphics.line(
|
|
debugRenderImpact.xi,
|
|
debugRenderImpact.yi,
|
|
debugRenderImpact.vxout,
|
|
debugRenderImpact.vyout)
|
|
|
|
end
|
|
|
|
love.graphics.pop()
|
|
|
|
sitelenpona.Draw( text.tok[state.currentBeat] )
|
|
|
|
marble.Draw()
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
function love.update( dt )
|
|
dt = dt + state.timeToSimulate
|
|
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
|
|
end
|
|
|
|
function love.keypressed( key, code, isRepeat )
|
|
if key == "escape" then return love.event.quit() end
|
|
if key == "return" then return OnImpact{ t = love.timer.getTime() } end
|
|
return marble.OnKey()
|
|
end
|
|
|
|
function love.keyreleased( key, code )
|
|
return marble.OnKey()
|
|
end
|
|
|
|
function love.resize( w, h )
|
|
UpdateWindowTransform( w, h )
|
|
if marble then marble.Resize() end
|
|
end |