BIG big commit, tweak physics parameters. Fix beat detection bug.
Scale down particle sprite. Fix sitelen pona rendering, fix text rendering. Invert white border feedback, more intuitive semantics. &c. &c.
|
@ -1,2 +1,3 @@
|
|||
build/
|
||||
screenshots/
|
||||
cover.png
|
39
audio.lua
|
@ -4,20 +4,26 @@ local failChimes = {}
|
|||
local drones = {}
|
||||
local N = 8
|
||||
|
||||
love.audio.setDistanceModel( "exponentclamped" )
|
||||
|
||||
local function StartDrones()
|
||||
love.audio.setEffect( "droneReverb", {
|
||||
type = "reverb",
|
||||
volume = 1.0, }
|
||||
volume = 1.0,
|
||||
decaytime = 20}
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
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.25 )
|
||||
drones.bass:setPitch( 0.125 )
|
||||
drones.alto:setVolume( 0 )
|
||||
drones.bass:setPitch( 0.5 )
|
||||
drones.bass:setPitch( 0.25 )
|
||||
drones.bass:setEffect( "droneReverb", true )
|
||||
drones.alto:setEffect( "droneReverb", true )
|
||||
drones.bass:stop()
|
||||
drones.alto:stop()
|
||||
|
||||
love.audio.play( drones.bass )
|
||||
love.audio.play( drones.alto )
|
||||
|
@ -72,6 +78,13 @@ local function OnImpact( impact, score, pass, level )
|
|||
if not pass then
|
||||
--drones.bass:seek( level )
|
||||
-- drones.alto:seek( level )
|
||||
else
|
||||
|
||||
love.audio.setEffect( "passChimeReverb", {
|
||||
type = "reverb",
|
||||
volume = 1.0,
|
||||
gain = 0.1 + level / 200} )
|
||||
|
||||
end
|
||||
|
||||
local th = impact.th
|
||||
|
@ -81,6 +94,7 @@ 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.5))
|
||||
chime:setFilter{
|
||||
type = "lowpass",
|
||||
|
@ -92,11 +106,22 @@ local function OnImpact( impact, score, pass, level )
|
|||
|
||||
end
|
||||
|
||||
local function OnVictory( )
|
||||
love.audio.setEffect( "passChimeReverb", {
|
||||
type = "reverb",
|
||||
volume = 1.0,
|
||||
decaytime = 20,} )
|
||||
end
|
||||
|
||||
--score is the hypothetical "beat score" that would be attained
|
||||
--if an impact took place at this instant.
|
||||
local function Update( score )
|
||||
local function Update( score, level )
|
||||
|
||||
if level > 2 then
|
||||
drones.bass:setVolume( 0.5 * math.sqrt( score ) )
|
||||
--drones.alto:setVolume( 0.3 * score )
|
||||
drones.alto:setVolume( 0.3 * score )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function Reset( )
|
||||
|
@ -108,4 +133,4 @@ local function Reset( )
|
|||
end
|
||||
|
||||
Reset()
|
||||
return { OnImpact = OnImpact, Update = Update, Reset = Reset}
|
||||
return { OnImpact = OnImpact, Update = Update, Reset = Reset, OnVictory = OnVictory}
|
144
main.lua
|
@ -10,7 +10,10 @@ local recorder
|
|||
local DetectCollision
|
||||
local OnImpact
|
||||
local OnVictory
|
||||
|
||||
local BeatScore
|
||||
local Draw
|
||||
local ExtrapolateBeatScore
|
||||
local _ExtrapolateBeatScore
|
||||
|
||||
local state
|
||||
state = {
|
||||
|
@ -22,9 +25,9 @@ state = {
|
|||
state.timeToSimulate = 0.0
|
||||
end,
|
||||
|
||||
finishTime = 0.0,
|
||||
timeToSimulate = 0.0,
|
||||
isGameStarted = false,
|
||||
beatScoreThreshold = 1.0,
|
||||
lastBeatScore = 0.0,
|
||||
currentBeat = 1,
|
||||
startTime = 0.0,
|
||||
|
@ -47,11 +50,50 @@ local function UpdateWindowTransform( w, h )
|
|||
transform = tf
|
||||
end
|
||||
|
||||
OnImpact = function( impact )
|
||||
if not impact then return end
|
||||
local score = BeatScore( impact.t )
|
||||
--DEBUG
|
||||
state.lastBeatScore = score
|
||||
local pass = false
|
||||
|
||||
if score > 1.0 then
|
||||
|
||||
pass = true
|
||||
state.currentBeat = state.currentBeat + 1
|
||||
if state.currentBeat >= 120 then
|
||||
return OnVictory()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
local x, y = math.cos(impact.th), math.sin(impact.th)
|
||||
particles:setPosition( impact.r * x, impact.r * y )
|
||||
particles:setEmissionArea( "normal", 0.1, 0.2, impact.th, true )
|
||||
particles:emit( 50 * score * score )
|
||||
|
||||
audio.OnImpact( impact, score, pass, state.currentBeat )
|
||||
marble.OnImpact( impact )
|
||||
wave.OnImpact( impact, state.currentBeat )
|
||||
end
|
||||
local _OnImpact = OnImpact
|
||||
|
||||
local function NewGame()
|
||||
love.graphics.setBackgroundColor( 245 / 255, 169 / 255, 184 / 255 ) --Trans pink.
|
||||
OnImpact = _OnImpact
|
||||
ExtrapolateBeatScore = _ExtrapolateBeatScore
|
||||
love.draw = Draw
|
||||
particles:reset()
|
||||
state.Reset()
|
||||
marble.Reset()
|
||||
wave.Reset()
|
||||
text.Reset()
|
||||
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.
|
||||
|
||||
do--particle system setup
|
||||
particles = love.graphics.newParticleSystem(
|
||||
|
@ -84,22 +126,23 @@ function love.load()
|
|||
DetectCollision = assert ( require "collision" )
|
||||
audio = assert( require "audio" )
|
||||
recorder = assert( require "recorder" )
|
||||
return state.Reset()
|
||||
return NewGame()
|
||||
|
||||
end
|
||||
|
||||
local function ExtrapolateBeatScore( )
|
||||
ExtrapolateBeatScore = function( )
|
||||
local t = love.timer.getTime()
|
||||
local beat = state.beat
|
||||
if not beat.t then return 2.0 end
|
||||
if not beat.mu then return 2.0 end
|
||||
if beat.mu < 0.001 then return 2.0 end
|
||||
|
||||
t = 1.1 * math.sin( math.pi * ( t - beat.t ) / beat.mu )
|
||||
t = 1.1 * math.sin( 0.5 * math.pi * ( t - beat.t ) / beat.mu )
|
||||
return t * t * t * t
|
||||
end
|
||||
_ExtrapolateBeatScore = ExtrapolateBeatScore
|
||||
|
||||
local function BeatScore( t )
|
||||
BeatScore = function( t )
|
||||
local beat = state.beat
|
||||
|
||||
--Base case 1: first tap.
|
||||
|
@ -117,73 +160,51 @@ local function BeatScore( t )
|
|||
return 2.0
|
||||
end
|
||||
|
||||
local score = 1.1 * math.sin( math.pi * dt / beat.mu )
|
||||
local score = 1.1 * math.sin( 0.5 * math.pi * dt / beat.mu )
|
||||
score = score * score * score * score
|
||||
|
||||
--General case: update average beat length.
|
||||
if dt > 0.2 then
|
||||
|
||||
local WEIGHT = 0.85 --High number makes the last beat more significant.
|
||||
--Debounce: max BPM 200
|
||||
if dt > 60.0 / 200.0 then
|
||||
|
||||
local WEIGHT = 0.75 --High number makes the last beat more significant.
|
||||
local mu = ( 1.0 - WEIGHT ) * beat.mu + WEIGHT * dt
|
||||
beat.mu = mu
|
||||
|
||||
else
|
||||
score = 0
|
||||
end
|
||||
|
||||
return score
|
||||
end
|
||||
|
||||
OnImpact = function( impact )
|
||||
if not impact then return end
|
||||
local score = BeatScore( impact.t )
|
||||
--DEBUG
|
||||
state.lastBeatScore = score
|
||||
local pass = false
|
||||
|
||||
if score > 1.0 then
|
||||
|
||||
pass = true
|
||||
state.currentBeat = state.currentBeat + 1
|
||||
if state.currentBeat >= 120 then
|
||||
return OnVictory()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local x, y = math.cos(impact.th), math.sin(impact.th)
|
||||
particles:setPosition( impact.r * x, impact.r * y )
|
||||
particles:setEmissionArea( "normal", 0.1, 0.2, impact.th, true )
|
||||
particles:emit( 50 * score * score )
|
||||
|
||||
audio.OnImpact( impact, score, pass, state.currentBeat )
|
||||
marble.OnImpact( impact )
|
||||
wave.OnImpact( impact )
|
||||
end
|
||||
local _OnImpact = OnImpact
|
||||
|
||||
|
||||
local function NewGame()
|
||||
OnImpact = _OnImpact
|
||||
state.Reset()
|
||||
marble.Reset()
|
||||
wave.Reset()
|
||||
end
|
||||
|
||||
|
||||
OnVictory = function()
|
||||
|
||||
local totalTime = love.timer.getTime() - state.startTime
|
||||
OnImpact = function() end
|
||||
love.draw = function()
|
||||
love.graphics.setColor( 1, 1, 1, 1 )
|
||||
|
||||
text.Draw( 120 )
|
||||
love.graphics.printf(
|
||||
"your.time:\n"..totalTime,
|
||||
0, 0.5 * love.graphics.getHeight(),
|
||||
love.graphics.getWidth(),
|
||||
"center"
|
||||
)
|
||||
|
||||
marble.Draw()
|
||||
end
|
||||
marble.OnVictory()
|
||||
love.graphics.setBackgroundColor( 91 / 255, 206 / 255, 250 / 255 ) --Trans blue.
|
||||
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 )]]
|
||||
Draw = function()
|
||||
|
||||
local score = ExtrapolateBeatScore()
|
||||
|
||||
|
||||
love.graphics.push( "transform" )
|
||||
love.graphics.applyTransform( transform )
|
||||
|
||||
|
@ -219,10 +240,9 @@ function love.draw()
|
|||
end]]
|
||||
|
||||
love.graphics.pop()
|
||||
|
||||
sitelenpona.Draw( text.tok[state.currentBeat] )
|
||||
|
||||
sitelenpona.Draw( text.words[state.currentBeat] )
|
||||
marble.Draw()
|
||||
text.Draw( state.currentBeat )
|
||||
|
||||
|
||||
end
|
||||
|
@ -231,7 +251,7 @@ end
|
|||
|
||||
function love.update( dt )
|
||||
|
||||
audio.Update( ExtrapolateBeatScore() )
|
||||
audio.Update( ExtrapolateBeatScore(), state.currentBeat )
|
||||
particles:update( dt )
|
||||
dt = dt + state.timeToSimulate
|
||||
|
||||
|
@ -270,3 +290,7 @@ function love.resize( w, h )
|
|||
UpdateWindowTransform( w, h )
|
||||
if marble then marble.Resize() end
|
||||
end
|
||||
|
||||
function love.mousepressed( x, y, button, istouch, presses )
|
||||
return NewGame()
|
||||
end
|
84
marble.lua
|
@ -1,5 +1,6 @@
|
|||
--Character controller. Renders point particle.
|
||||
local love = love
|
||||
local marble = {}
|
||||
local oldBuffer = love.graphics.newCanvas()
|
||||
local newBuffer = love.graphics.newCanvas()
|
||||
local oldState, curState, newState
|
||||
|
@ -12,14 +13,14 @@ local function State( )
|
|||
return { t = 0, x = 0, y = 0, dx = 0, dy = 0 }
|
||||
end
|
||||
|
||||
local function GetAcceleration( )
|
||||
return ddx, ddy
|
||||
end
|
||||
|
||||
local function Current() return curState end
|
||||
local function Next() return newState end
|
||||
function marble.Current() return curState end
|
||||
|
||||
local function Integrate( step )
|
||||
function marble.Next() return newState end
|
||||
|
||||
function marble.GetAcceleration( ) return ddx, ddy end
|
||||
|
||||
function marble.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
|
||||
|
@ -27,7 +28,7 @@ local function Integrate( step )
|
|||
newState.y = curState.y + newState.dy * step * MAXSPEED
|
||||
end
|
||||
|
||||
local function OnImpact( impact )
|
||||
function marble.OnImpact( impact )
|
||||
--Adjust current trajectory according to collision.
|
||||
if not impact.dt then return end
|
||||
|
||||
|
@ -66,14 +67,14 @@ local function OnImpact( impact )
|
|||
curState.x, curState.y = x, y
|
||||
curState.dx, curState.dy = vxout, vyout
|
||||
|
||||
debugRenderImpact = { xi = x, yi = y, xf = x - vx, yf = y - vy,
|
||||
--[[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}
|
||||
vxout = x + vxout, vyout = y + vyout}]]
|
||||
|
||||
return Integrate( math.max( impact.dt , 1 / 120 ) ) --Hmm! Maybe this should be a fixed step instead for stability's sake.
|
||||
return marble.Integrate( math.max( impact.dt , 1 / 120 ) ) --Hmm! Maybe this should be a fixed step instead for stability's sake.
|
||||
end
|
||||
|
||||
local function Update()
|
||||
function marble.Update()
|
||||
--Roll the log.
|
||||
for k, v in pairs( oldState ) do
|
||||
oldState[k] = curState[k]
|
||||
|
@ -83,7 +84,7 @@ end
|
|||
|
||||
|
||||
|
||||
local function OnKey()
|
||||
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)
|
||||
|
||||
|
@ -92,11 +93,35 @@ local function OnKey()
|
|||
ddx, ddy = ddx / n, ddy / n
|
||||
end
|
||||
|
||||
local function Draw()
|
||||
function marble.OnVictory()
|
||||
|
||||
marble.Draw = function()
|
||||
|
||||
--Extrapolate forward for slightly smoother rendering.
|
||||
local dt = love.timer.getTime() - curState.t
|
||||
Integrate( dt + 1 / 60.0 )
|
||||
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 )
|
||||
|
||||
love.graphics.setColor( 91 / 255, 206 / 255, 250 / 255, 1.0 ) --Trans blue.
|
||||
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()
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
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 )
|
||||
|
@ -130,12 +155,14 @@ local function Draw()
|
|||
|
||||
end
|
||||
|
||||
local function Impact( impact )
|
||||
marble._Draw = marble.Draw
|
||||
|
||||
function marble.Impact( impact )
|
||||
|
||||
end
|
||||
|
||||
--Window resize.
|
||||
local function Resize()
|
||||
function marble.Resize()
|
||||
newBuffer = love.graphics.newCanvas()
|
||||
--TODO: render oldBuffer to new newBuffer, but scaled down.
|
||||
oldBuffer = love.graphics.newCanvas()
|
||||
|
@ -143,25 +170,18 @@ local function Resize()
|
|||
|
||||
end
|
||||
|
||||
local function Reset()
|
||||
function marble.Reset()
|
||||
oldState, curState, newState = State(), State(), State()
|
||||
Resize()
|
||||
marble.Resize()
|
||||
marble.Draw = marble._Draw
|
||||
end
|
||||
|
||||
function marble.Canvas()
|
||||
return newBuffer
|
||||
end
|
||||
|
||||
|
||||
|
||||
Reset()
|
||||
marble.Reset()
|
||||
|
||||
return {
|
||||
Integrate = Integrate,
|
||||
OnImpact = OnImpact,
|
||||
Update = Update,
|
||||
OnKey = OnKey,
|
||||
Draw = Draw,
|
||||
Impact = Impact,
|
||||
Reset = Reset,
|
||||
Resize = Resize,
|
||||
Current = Current,
|
||||
Next = Next,
|
||||
GetAcceleration = GetAcceleration,
|
||||
}
|
||||
return marble
|
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 990 B |
After Width: | Height: | Size: 49 KiB |
|
@ -6,12 +6,32 @@ local info = love.filesystem.getInfo( "sitelenpona" )
|
|||
for _, filename in ipairs(love.filesystem.getDirectoryItems( "sitelenpona" )) do
|
||||
sp[filename:gsub( ".png", "" )] = love.graphics.newImage( "sitelenpona/"..filename )
|
||||
end
|
||||
--Render one glyph in the center.
|
||||
sp.Draw = function( str )
|
||||
--Render one or two glyphs in the center.
|
||||
sp.Draw = function( t )
|
||||
local cx, cy = love.graphics.getDimensions()
|
||||
cx, cy = 0.5 * cx, 0.5 * cy
|
||||
love.graphics.setColor( 1.0, 1.0, 1.0, 0.5 )
|
||||
|
||||
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 )
|
||||
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 )
|
||||
love.graphics.draw( sp[t[2]] or sp.pilin, cx, cy - 64, 0, 0.5, 0.5 )
|
||||
end
|
||||
--[[ w in str:gmatch( "%a+") do
|
||||
t[i] = w
|
||||
i = i + 1
|
||||
end
|
||||
for _, str in ipairs( t ) do
|
||||
local w, h = love.graphics.getDimensions()
|
||||
local x, y = 0.5 * w - 128, 0.5 * h - 128
|
||||
love.graphics.setColor( 1.0, 1.0, 1.0, 0.5 )
|
||||
love.graphics.draw( sp[str] or sp.q, x, y )
|
||||
|
||||
love.graphics.draw( sp[str] or sp.pilin, x, y )
|
||||
end]]
|
||||
end
|
||||
|
||||
|
||||
|
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 903 B |
77
text.lua
|
@ -1,17 +1,72 @@
|
|||
--Load poems.
|
||||
local love = love
|
||||
local txt = {}
|
||||
local feet = {}
|
||||
local feetNL = {}
|
||||
local words = {} --Sequence of tables.
|
||||
local poem = {[0] = ""}
|
||||
local poemLines = {[0] = 0}
|
||||
|
||||
local mt = { __index = function() return "linja" end }
|
||||
|
||||
local s = love.filesystem.read( "text/tok.txt" )
|
||||
local smallFont = love.graphics.setNewFont( "text/linja-sike.ttf", 12 )
|
||||
local largeFont = love.graphics.setNewFont( "text/linja-sike.ttf", 32 )
|
||||
|
||||
local i = 1
|
||||
--Split string into feet.
|
||||
for foot in s:gmatch( ".-%-") do
|
||||
|
||||
feet[i] = foot:gsub( "-", "" ):gsub( " $", "" ):gsub( "%c", "") --Remove hyphens, trailing spaces, newlines.
|
||||
feetNL[i] = foot:gsub( "-", "" ):gsub(" ", "")--:gsub( "%.", " " ) --Remove hyphens, spaces, transform periods to spaces
|
||||
|
||||
|
||||
poem[i] = poem[ i - 1 ]..feetNL[i]
|
||||
poemLines[i] = poemLines[i - 1] + (feetNL[i]:match( "\n") and 1 or 0)
|
||||
|
||||
|
||||
local info = love.filesystem.getInfo( "text" )
|
||||
for _, filename in ipairs(love.filesystem.getDirectoryItems( "text" )) do
|
||||
local s = love.filesystem.read( "text/"..filename )
|
||||
local t = {}
|
||||
local i = 1
|
||||
for w in s:gmatch( "%a+") do
|
||||
t[i] = w
|
||||
i = i + 1
|
||||
end
|
||||
txt[filename:gsub( ".txt", "" )] = t
|
||||
end
|
||||
|
||||
return txt
|
||||
--Split string into words.
|
||||
i = 1
|
||||
local isTe = true
|
||||
for foot in s:gmatch( ".-%-" ) do
|
||||
--Split foot into words.
|
||||
local word = {}
|
||||
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
|
||||
word[j] = w
|
||||
j = j + 1
|
||||
end
|
||||
words[i] = word
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
local function Draw( beat )
|
||||
|
||||
local foot = feet[ beat ]
|
||||
|
||||
|
||||
love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
|
||||
love.graphics.printf(
|
||||
foot,
|
||||
0, (9/10) * love.graphics.getHeight(),
|
||||
love.graphics.getWidth(),
|
||||
"center")
|
||||
|
||||
love.graphics.setColor(1.0, 1.0, 1.0, 0.5)
|
||||
love.graphics.print( poem[beat], 0, (3 - poemLines[beat]) * 32 )
|
||||
|
||||
|
||||
end
|
||||
|
||||
local Reset = function() end
|
||||
|
||||
return { feet = feet, words = words, feetNL = feetNL, Reset = Reset, Draw = Draw }
|
173
text/tok.txt
|
@ -1,120 +1,53 @@
|
|||
a
|
||||
akesi
|
||||
ala
|
||||
alasa
|
||||
ale
|
||||
anpa
|
||||
ante
|
||||
anu
|
||||
awen
|
||||
e
|
||||
en
|
||||
esun
|
||||
ijo
|
||||
ike
|
||||
ilo
|
||||
insa
|
||||
jaki
|
||||
jan
|
||||
jelo
|
||||
jo
|
||||
kala
|
||||
kalama
|
||||
kama
|
||||
kasi
|
||||
ken
|
||||
kepeken
|
||||
kili
|
||||
kiwen
|
||||
ko
|
||||
kon
|
||||
kule
|
||||
kulupu
|
||||
kute
|
||||
la
|
||||
lape
|
||||
laso
|
||||
lawa
|
||||
len
|
||||
lete
|
||||
li
|
||||
lili
|
||||
linja
|
||||
lipu
|
||||
loje
|
||||
lon
|
||||
luka
|
||||
lukin
|
||||
lupa
|
||||
ma
|
||||
mama
|
||||
mani
|
||||
meli
|
||||
mi
|
||||
mije
|
||||
moku
|
||||
moli
|
||||
monsi
|
||||
mu
|
||||
mun
|
||||
musi
|
||||
mute
|
||||
nanpa
|
||||
nasa
|
||||
nasin
|
||||
nena
|
||||
ni
|
||||
nimi
|
||||
noka
|
||||
o
|
||||
olin
|
||||
ona
|
||||
open
|
||||
pakala
|
||||
pali
|
||||
palisa
|
||||
pan
|
||||
pana
|
||||
pi
|
||||
pilin
|
||||
pimeja
|
||||
pini
|
||||
pipi
|
||||
poka
|
||||
poki
|
||||
pona
|
||||
pu
|
||||
sama
|
||||
seli
|
||||
selo
|
||||
seme
|
||||
sewi
|
||||
sijelo
|
||||
sike
|
||||
sin
|
||||
sina
|
||||
sinpin
|
||||
sitelen
|
||||
sona
|
||||
soweli
|
||||
suli
|
||||
suno
|
||||
supa
|
||||
suwi
|
||||
tan
|
||||
taso
|
||||
tawa
|
||||
telo
|
||||
tenpo
|
||||
toki
|
||||
tomo
|
||||
tu
|
||||
unpa
|
||||
uta
|
||||
utala
|
||||
walo
|
||||
wan
|
||||
waso
|
||||
wawa
|
||||
weka
|
||||
wile
|
||||
open -la mi -jan pi -toki-
|
||||
ala -li mu -taso -li ken-
|
||||
ala -pana -toki -pilin-
|
||||
toki -mu li -wawa -wawa
|
||||
nasa -la jan -ante -li ken-
|
||||
awen -pona -tawa -mi li-
|
||||
awen -ala-sa e -pona.-
|
||||
moku -mi li -tan jan -pona-
|
||||
mama -mi li -pona -mute-
|
||||
mama -tu li -lon. tu -ona-
|
||||
o mi -taso. -wile -mute-
|
||||
li lon -sije-lo mi -ike.-
|
||||
mute -la mi -pilin -nasa-
|
||||
a mi -wile -musi -mute-
|
||||
wile -mi li -ni: ko -jelo-
|
||||
ni o -kama -tomo -wawa-
|
||||
tomo -ni li -jo e -poki-
|
||||
poki l-a jan -mi li -lawa-
|
||||
lawa -la jan -ni li -toki-
|
||||
"tomo -mi li -pona -mute-
|
||||
paka-la o -kama -ala-
|
||||
weka -o ken -ala -kama"-
|
||||
wile -ala -mi la -ni li-
|
||||
kama: -jan li -paka-la e-
|
||||
tomo -suli -pona -mi a-
|
||||
ni li -ike -tawa -pilin-
|
||||
jan li -ni tan -seme -ike-
|
||||
mi ken -ala -sona -pona-
|
||||
wile -toki -li lon -ala-
|
||||
la mi -tawa -mama -kiwen-
|
||||
|
||||
tenpo ni -mute li -kama li -weka la-
|
||||
sijelo -ike li -ante a -mute
|
||||
pilin mi -ala li -awen kin -sama-
|
||||
wile mi su-li en wi-le mi li-li li-
|
||||
nasa lon -tenpo ni. -mi kama -suli-
|
||||
toki pi jan mute li kama ike. jan
|
||||
mute li wile e pakala taso
|
||||
lili li wile e sona e nasin
|
||||
mute li wile e ni ala. nasa
|
||||
mi toki ala lon poka pi jan ni
|
||||
seme la mi wile alasa toki
|
||||
jan ni la pilin mi li nasa mute
|
||||
jan ni la musi mi li musi ala
|
||||
seme la mi o lon poka jan ike
|
||||
jan ike ni li ken pona e ala
|
||||
mute la ona li wile e tawa
|
||||
ala la wile ona li lon pali
|
||||
mute la mi awen lon insa lawa
|
||||
lawa la mi toki mute e pilin
|
||||
lon lawa ala la mi lukin mute
|
||||
lukin li wile e musi e sona
|
||||
sitelen la m ken moku ni mute
|
32
wave.lua
|
@ -1,9 +1,9 @@
|
|||
--Render and simulate 1D wave equation.
|
||||
local love = love
|
||||
local N = 33
|
||||
local SOUNDSPEED = 0.5
|
||||
local IMPULSESIZE = 5
|
||||
local DAMPING = 0.01
|
||||
local SOUNDSPEED
|
||||
local IMPULSESIZE
|
||||
local DAMPING
|
||||
|
||||
|
||||
local old, cur, new --States add beginning of last tick, current tick, and next tick respectively.
|
||||
|
@ -47,8 +47,9 @@ local shader = love.graphics.newShader([[
|
|||
p.y = -p.y;
|
||||
|
||||
float r = r( atan(p.y, p.x) ) - length( p );
|
||||
float q = float( r < 0.01 ) * clamp( 1.0 - score, 0.0, 1.0 ) ;
|
||||
|
||||
return vec4( (1.0 + float(score > 1.0) * r * 0.1) * color.xyz, float(r > -0.01)) ;
|
||||
return vec4( q + (1.0 + clamp( score, 0.0, 1.0 ) * r * r * 0.2) * color.xyz, float(r > 0.0)) ;
|
||||
}
|
||||
]])
|
||||
|
||||
|
@ -146,9 +147,15 @@ local function AliasedSinc( theta, x )
|
|||
return n / d
|
||||
end
|
||||
|
||||
--Apply bandlimited impulse to wave.
|
||||
local function OnImpact( impact )
|
||||
--Apply bandlimited impulse to wave, adjust free parameters according to game state.
|
||||
local function OnImpact( impact, level )
|
||||
|
||||
IMPULSESIZE = 10.0 * math.sqrt( level / 120.0 )
|
||||
SOUNDSPEED = 50.0 - 35 * level / 120
|
||||
DAMPING = 0.03 * ( 1.0 - 0.4 * level / 120 )
|
||||
|
||||
|
||||
--Apply bandlimited impulse.
|
||||
local r = cur.radii
|
||||
local theta = impact.th
|
||||
local magnitude = IMPULSESIZE * impact.speed
|
||||
|
@ -272,11 +279,14 @@ end
|
|||
Integrate = function( step )
|
||||
|
||||
for i = 1, N do
|
||||
|
||||
local rxx = cur:SecondDerivative( math.pi * 2.0 * ( i - 1 ) / N )
|
||||
|
||||
local r = ( 1.0 - DAMPING ) * ( 2.0 * cur.radii[i] - old.radii[i] + step * step * SOUNDSPEED * rxx ) --Verlet
|
||||
+ DAMPING --Damping: oscillate toward 1.
|
||||
if r > 1.5 then r = 1.5 end
|
||||
if r < 0.5 then r = 0.5 end
|
||||
|
||||
--Avoid explosions.
|
||||
r = math.max( 0.5, math.min( r, 4.0 ) )
|
||||
new.radii[i] = r
|
||||
end
|
||||
|
||||
|
@ -290,9 +300,9 @@ end
|
|||
|
||||
local function Reset()
|
||||
|
||||
SOUNDSPEED = 0.5
|
||||
IMPULSESIZE = 5
|
||||
DAMPING = 0.02
|
||||
IMPULSESIZE = 1 / 10.0
|
||||
SOUNDSPEED = 5.0
|
||||
DAMPING = 0.1 / 1
|
||||
|
||||
old = Wave()
|
||||
cur = Wave()
|
||||
|
|