Compare commits
No commits in common. "d5e0e1c5da68321e13eb28f1ae2d1f04716747e7" and "9754a8269492edcf5b014c1a706cfe5016d95c49" have entirely different histories.
d5e0e1c5da
...
9754a82694
10
audio.lua
10
audio.lua
|
@ -179,11 +179,11 @@ local function Update( score, level )
|
||||||
|
|
||||||
if level > 2 then
|
if level > 2 then
|
||||||
level = level / 120.0
|
level = level / 120.0
|
||||||
drones.bass:setVolume( 0.7 * (0.0 + score) * level )
|
drones.bass:setVolume( 0.7 * (0.2 + math.pow( score, 0.25 )) * level )
|
||||||
drones.alto:setVolume( 0.3 * (0.3 + score) * level * level)
|
drones.alto:setVolume( 0.3 * (0.3 + math.pow( score, 0.25 )) * level * level)
|
||||||
drones.fuck:setVolume( 3.0 * (0.2 + score) * math.max( 0, level - 0.75 ))
|
drones.fuck:setVolume( 4.0 * math.max( 0, level - 0.75 ))
|
||||||
drones.subs:setVolume( 0.5 * (0.2 + score) * math.max( 0, level - 0.50 ))
|
drones.subs:setVolume( 0.5 * math.max( 0, level - 0.5 ))
|
||||||
drones.wail:setVolume( 1.5 * (0.5 + score) * math.max( 0, level - 0.66 ))
|
drones.wail:setVolume( 2.0 * math.max( 0, level - 0.666 ))
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
1
conf.lua
1
conf.lua
|
@ -1,6 +1,5 @@
|
||||||
function love.conf( t )
|
function love.conf( t )
|
||||||
t.version = "11.4"
|
t.version = "11.4"
|
||||||
t.identity = "Your Own Drum"
|
|
||||||
|
|
||||||
t.modules.joystick = false
|
t.modules.joystick = false
|
||||||
t.modules.physics = false
|
t.modules.physics = false
|
||||||
|
|
BIN
demos/yam.yod
BIN
demos/yam.yod
Binary file not shown.
187
loadgame.lua
187
loadgame.lua
|
@ -1,187 +0,0 @@
|
||||||
--UI for selecting a saved game.
|
|
||||||
local love = love
|
|
||||||
local loadGame = {}
|
|
||||||
local _Update
|
|
||||||
local _Draw
|
|
||||||
local _MousePressed
|
|
||||||
local _MouseMoved
|
|
||||||
local _Resize
|
|
||||||
local _KeyPressed
|
|
||||||
|
|
||||||
local function RestoreMainState()
|
|
||||||
love.update = _Update
|
|
||||||
love.draw = _Draw
|
|
||||||
love.mousepressed = _MousePressed
|
|
||||||
love.mousemoved = _MouseMoved
|
|
||||||
love.keypressed = _KeyPressed
|
|
||||||
love.resize = _Resize
|
|
||||||
love.mousemoved = nil
|
|
||||||
love.mouse.setRelativeMode( true )
|
|
||||||
end
|
|
||||||
|
|
||||||
local selectedGame = 1
|
|
||||||
local scrollOffset = 1
|
|
||||||
local deleteGame = false
|
|
||||||
local gameList = assert( love.filesystem.getDirectoryItems( "demos" ) )
|
|
||||||
local mouseX, mouseY = 0, 0
|
|
||||||
local w, h = love.graphics.getDimensions()
|
|
||||||
local canvas = love.graphics.newCanvas( w, h * (1 + #gameList) / 10.0 )
|
|
||||||
local font = love.graphics.newFont( 36 )
|
|
||||||
local deleteIcon = love.graphics.newImage( "sitelenpona/ala.png" )
|
|
||||||
local playIcon = love.graphics.newImage( "sitelenpona/li.png" )
|
|
||||||
local OnClick
|
|
||||||
|
|
||||||
|
|
||||||
local function DeleteLeft()
|
|
||||||
return love.graphics.getWidth() * 0.75 + 15 + 6
|
|
||||||
end
|
|
||||||
|
|
||||||
local function DeleteRight()
|
|
||||||
return DeleteLeft() + h / 10 - 12
|
|
||||||
end
|
|
||||||
|
|
||||||
local function DrawSelection( )
|
|
||||||
love.graphics.rectangle( "fill", 15, selectedGame * h / 10 )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function PopulateGameList()
|
|
||||||
scrollOffset = 0
|
|
||||||
gameList = assert( love.filesystem.getDirectoryItems( "demos" ) )
|
|
||||||
|
|
||||||
local w, h = love.graphics.getDimensions()
|
|
||||||
|
|
||||||
canvas = love.graphics.newCanvas( w, h * (1 + #gameList) / 10.0 )
|
|
||||||
love.graphics.setCanvas( canvas )
|
|
||||||
love.graphics.clear()
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
love.graphics.setLineWidth( 3 )
|
|
||||||
|
|
||||||
for i, name in ipairs( gameList ) do
|
|
||||||
local x, y = 15, i * h / 10
|
|
||||||
|
|
||||||
love.graphics.printf( gameList[i], font, x + 10, y, 0.75 * w, "left" )
|
|
||||||
love.graphics.draw( deleteIcon, DeleteLeft() - 8, y - 8, 0, 0.25, 0.25 )
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.setCanvas()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local resizeLoadMenu = function( newWidth, newHeight )
|
|
||||||
_Resize(newWidth, newHeight )
|
|
||||||
w, h = love.graphics.getDimensions()
|
|
||||||
canvas = love.graphics.newCanvas( w, h * (1 + #gameList) / 10.0 )
|
|
||||||
return PopulateGameList()
|
|
||||||
end
|
|
||||||
|
|
||||||
local updateLoadMenu = function() end
|
|
||||||
|
|
||||||
local drawLoadGameMenu = function()
|
|
||||||
local w, h = love.graphics.getDimensions()
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0,0,0, 1 )
|
|
||||||
end
|
|
||||||
love.graphics.draw( canvas, 0, 15 - scrollOffset * h / 10 )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
love.graphics.setColor( 1.0, 1.0, 1.0, 1.0 )
|
|
||||||
love.graphics.rectangle( "fill", 0, 0, w, 10 + h / 10 - 6 )
|
|
||||||
love.graphics.setColor( 91 / 255, 206 / 255, 250 / 255 )--
|
|
||||||
love.graphics.print( "BACK")
|
|
||||||
|
|
||||||
if not selectedGame then return end
|
|
||||||
love.graphics.setColor( 1, 1, 1, 0.4 )
|
|
||||||
if deleteGame then
|
|
||||||
love.graphics.rectangle( "fill",
|
|
||||||
DeleteLeft(), 15 + ( selectedGame - scrollOffset ) * h / 10,
|
|
||||||
48, 48,
|
|
||||||
10, 10 )
|
|
||||||
else
|
|
||||||
love.graphics.rectangle( "fill", 15, 15 + ( selectedGame - scrollOffset ) * h / 10, w * 0.75,
|
|
||||||
--h / 10 - 12, 10, 10 )
|
|
||||||
48, 10, 10)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local mouseMoved = function( x, y, dx, dy, istouch)
|
|
||||||
deleteGame = ( x > DeleteLeft() )
|
|
||||||
selectedGame = math.max( math.min( #gameList, scrollOffset + math.floor( 10 * ( y - 15 ) / h ) ), 1)
|
|
||||||
if y < 4 + h / 10 then selectedGame = nil end
|
|
||||||
end
|
|
||||||
|
|
||||||
local KeyPress = function( key, code, isRepeat )
|
|
||||||
if code == "return" then
|
|
||||||
return OnClick()
|
|
||||||
end
|
|
||||||
|
|
||||||
if not selectedGame then selectedGame = 1 end
|
|
||||||
|
|
||||||
if code == "down" then
|
|
||||||
|
|
||||||
if selectedGame < #gameList then
|
|
||||||
if selectedGame > 8 then
|
|
||||||
scrollOffset = scrollOffset + 1
|
|
||||||
end
|
|
||||||
selectedGame = selectedGame + 1
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if code == "up" then
|
|
||||||
if selectedGame > 9 then
|
|
||||||
scrollOffset = scrollOffset - 1
|
|
||||||
end
|
|
||||||
if selectedGame > 1 then
|
|
||||||
selectedGame = selectedGame - 1
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if code == "left" then deleteGame = false end
|
|
||||||
if code == "right" then deleteGame = true end
|
|
||||||
if code == "escape" or code == "backspace" then return RestoreMainState() end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
OnClick = function( x, y, button, istouch, presses )
|
|
||||||
if y and y < 4 + h / 10 then return RestoreMainState() end
|
|
||||||
if not selectedGame then return end
|
|
||||||
if #gameList < 1 then return end
|
|
||||||
|
|
||||||
if deleteGame then
|
|
||||||
love.filesystem.remove( "demos/"..gameList[selectedGame] )
|
|
||||||
return PopulateGameList()
|
|
||||||
end
|
|
||||||
|
|
||||||
--Restore main state.
|
|
||||||
RestoreMainState()
|
|
||||||
return "demos/"..gameList[selectedGame]
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local wheelMoved = function(x, y)
|
|
||||||
--scrollOffset = math.max( 0, math.min( #gameList, scrollOffset - y * 0.1 ) )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function LoadGameMenu()
|
|
||||||
_Update = love.update
|
|
||||||
_Draw = love.draw
|
|
||||||
_MousePressed = love.mousepressed
|
|
||||||
_MouseMoved = love.mousemoved
|
|
||||||
_Resize = love.resize
|
|
||||||
_KeyPressed = love.keypressed
|
|
||||||
love.mouse.setRelativeMode( false )
|
|
||||||
|
|
||||||
love.wheelmoved = wheelMoved
|
|
||||||
love.mousemoved = mouseMoved
|
|
||||||
love.draw = drawLoadGameMenu
|
|
||||||
love.update = updateLoadMenu
|
|
||||||
love.resize = resizeLoadMenu
|
|
||||||
PopulateGameList()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return { OnClick = OnClick, KeyPress = KeyPress, LoadGameMenu = LoadGameMenu }
|
|
183
main.lua
183
main.lua
|
@ -15,27 +15,25 @@ local Draw
|
||||||
local Update
|
local Update
|
||||||
local ExtrapolateBeatScore
|
local ExtrapolateBeatScore
|
||||||
local _ExtrapolateBeatScore
|
local _ExtrapolateBeatScore
|
||||||
local mouseControl
|
|
||||||
local scores
|
|
||||||
|
|
||||||
local state
|
local state
|
||||||
state = {
|
state = {
|
||||||
|
|
||||||
Reset = function()
|
Reset = function()
|
||||||
state.tick = 0
|
|
||||||
state.beat = {}
|
state.beat = {}
|
||||||
|
state.startTime = love.timer.getTime()
|
||||||
state.currentBeat = 1
|
state.currentBeat = 1
|
||||||
state.timeToSimulate = 0.0
|
state.timeToSimulate = 0.0
|
||||||
state.longestStreak = 0
|
state.longestStreak = 0
|
||||||
state.currentStreak = 0
|
state.currentStreak = 0
|
||||||
state.lastCollisionTick = 0
|
|
||||||
state.lastCollisionX = 0
|
|
||||||
state.lastCollisionY = 0
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
finishTime = 0.0,
|
||||||
timeToSimulate = 0.0,
|
timeToSimulate = 0.0,
|
||||||
|
isGameStarted = false,
|
||||||
lastBeatScore = 0.0,
|
lastBeatScore = 0.0,
|
||||||
currentBeat = 1,
|
currentBeat = 1,
|
||||||
|
startTime = 0.0,
|
||||||
longestStreak = 0,
|
longestStreak = 0,
|
||||||
currentStreak = 0,
|
currentStreak = 0,
|
||||||
|
|
||||||
|
@ -62,7 +60,6 @@ OnImpact = function( impact )
|
||||||
local score = BeatScore( impact.t )
|
local score = BeatScore( impact.t )
|
||||||
--DEBUG
|
--DEBUG
|
||||||
state.lastBeatScore = score
|
state.lastBeatScore = score
|
||||||
state.lastCollisionTick = state.tick
|
|
||||||
local pass = false
|
local pass = false
|
||||||
|
|
||||||
if score > 1.0 then
|
if score > 1.0 then
|
||||||
|
@ -82,16 +79,12 @@ OnImpact = function( impact )
|
||||||
else
|
else
|
||||||
state.currentStreak = 0
|
state.currentStreak = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
scores.OnImpact( state.tick, pass )
|
|
||||||
|
|
||||||
|
|
||||||
local x, y = impact.r * math.cos(impact.th), impact.r * math.sin(impact.th)
|
local x, y = math.cos(impact.th), math.sin(impact.th)
|
||||||
particles:setPosition( x, y )
|
particles:setPosition( impact.r * x, impact.r * y )
|
||||||
particles:setEmissionArea( "normal", 0.1, 0.2, impact.th, true )
|
particles:setEmissionArea( "normal", 0.1, 0.2, impact.th, true )
|
||||||
particles:emit( 50 * score * score )
|
particles:emit( 50 * score * score )
|
||||||
|
|
||||||
state.lastCollisionX, state.lastCollisionY = transform:transformPoint( 1.2 * x, 1.2 * y )
|
|
||||||
|
|
||||||
audio.OnImpact( impact, score, pass, state.currentBeat )
|
audio.OnImpact( impact, score, pass, state.currentBeat )
|
||||||
marble.OnImpact( impact, state.currentBeat )
|
marble.OnImpact( impact, state.currentBeat )
|
||||||
|
@ -99,17 +92,31 @@ OnImpact = function( impact )
|
||||||
end
|
end
|
||||||
local _OnImpact = OnImpact
|
local _OnImpact = OnImpact
|
||||||
|
|
||||||
local function NewGame( demoName )
|
local function NewGame()
|
||||||
love.graphics.setBackgroundColor( 245 / 255, 169 / 255, 184 / 255 ) --Trans pink.
|
love.graphics.setBackgroundColor( 245 / 255, 169 / 255, 184 / 255 ) --Trans pink.
|
||||||
OnImpact = _OnImpact
|
OnImpact = _OnImpact
|
||||||
ExtrapolateBeatScore = _ExtrapolateBeatScore
|
ExtrapolateBeatScore = _ExtrapolateBeatScore
|
||||||
love.draw = Draw
|
love.draw = Draw
|
||||||
love.update = Update
|
love.update = Update
|
||||||
|
|
||||||
do --particle shit
|
|
||||||
particles:reset()
|
particles:reset()
|
||||||
particles:setSizes( 0.0007, 0.0001, 0.0003 )
|
particles:setSizes( 0.0007, 0.0001, 0.0003 )
|
||||||
--particles:setSizes( 0.0007, 0.0001, 0.0003 )
|
state.Reset()
|
||||||
|
marble.Reset()
|
||||||
|
wave.Reset()
|
||||||
|
text.Reset()
|
||||||
|
audio.Reset()
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.load()
|
||||||
|
UpdateWindowTransform( love.graphics.getDimensions() )
|
||||||
|
|
||||||
|
|
||||||
|
do--particle system setup
|
||||||
|
particles = love.graphics.newParticleSystem(
|
||||||
|
love.graphics.newImage( "prideflag.png" ),
|
||||||
|
1024)
|
||||||
|
|
||||||
|
--particles:setSizes( 0.0007, 0.0001, 0.0003 )
|
||||||
particles:setSizeVariation( 1 )
|
particles:setSizeVariation( 1 )
|
||||||
particles:setRadialAcceleration( 0, 0.5 )
|
particles:setRadialAcceleration( 0, 0.5 )
|
||||||
particles:setSpeed( 0.2, 1 )
|
particles:setSpeed( 0.2, 1 )
|
||||||
|
@ -126,43 +133,12 @@ local function NewGame( demoName )
|
||||||
245 / 255, 169 / 255, 184 / 255, 1,
|
245 / 255, 169 / 255, 184 / 255, 1,
|
||||||
1,1,1,0,
|
1,1,1,0,
|
||||||
245 / 255, 169 / 255, 184 / 255, 1,
|
245 / 255, 169 / 255, 184 / 255, 1,
|
||||||
1,1,1,0)
|
1,1,1,0
|
||||||
end
|
|
||||||
mouseControl.Reset()
|
|
||||||
state.Reset()
|
|
||||||
marble.Reset()
|
|
||||||
wave.Reset()
|
|
||||||
text.Reset()
|
|
||||||
audio.Reset()
|
|
||||||
recorder.Reset()
|
|
||||||
scores.Reset()
|
|
||||||
|
|
||||||
state.isDemo = demoName
|
)
|
||||||
if demoName then
|
|
||||||
recorder.Load( demoName )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.load()
|
|
||||||
love.mouse.setRelativeMode( true )
|
|
||||||
|
|
||||||
UpdateWindowTransform( love.graphics.getDimensions() )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
do--particle system setup
|
|
||||||
particles = love.graphics.newParticleSystem(
|
|
||||||
love.graphics.newImage( "prideflag.png" ),
|
|
||||||
2048)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
loadGame = assert( require "loadgame" )
|
|
||||||
options = assert( require( "options" ) )
|
|
||||||
mouseControl = assert( require "mousecontrols" )
|
|
||||||
sitelenpona = assert( require "sitelenpona" )
|
sitelenpona = assert( require "sitelenpona" )
|
||||||
text = assert( require "text" )
|
text = assert( require "text" )
|
||||||
marble = assert( require "marble" )
|
marble = assert( require "marble" )
|
||||||
|
@ -170,13 +146,12 @@ function love.load()
|
||||||
DetectCollision = assert ( require "collision" )
|
DetectCollision = assert ( require "collision" )
|
||||||
audio = assert( require "audio" )
|
audio = assert( require "audio" )
|
||||||
recorder = assert( require "recorder" )
|
recorder = assert( require "recorder" )
|
||||||
scores = assert( require "scores" )
|
|
||||||
return NewGame()
|
return NewGame()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ExtrapolateBeatScore = function( )
|
ExtrapolateBeatScore = function( )
|
||||||
local t = state.tick / 120.0
|
local t = love.timer.getTime()
|
||||||
local beat = state.beat
|
local beat = state.beat
|
||||||
if not beat.t then return 2.0 end
|
if not beat.t then return 2.0 end
|
||||||
if not beat.mu then return 2.0 end
|
if not beat.mu then return 2.0 end
|
||||||
|
@ -228,13 +203,6 @@ end
|
||||||
|
|
||||||
OnVictory = function()
|
OnVictory = function()
|
||||||
|
|
||||||
if state.isDemo then
|
|
||||||
state.isDemo = false
|
|
||||||
else
|
|
||||||
scores.Save()
|
|
||||||
recorder.Save( scores.Get(), state.tick)
|
|
||||||
end
|
|
||||||
|
|
||||||
particles:setParticleLifetime( 0, 30 )
|
particles:setParticleLifetime( 0, 30 )
|
||||||
particles:setSizes( 0.001, 0.0001, 0.0005 )
|
particles:setSizes( 0.001, 0.0001, 0.0005 )
|
||||||
particles:setColors(
|
particles:setColors(
|
||||||
|
@ -251,10 +219,9 @@ OnVictory = function()
|
||||||
particles:setEmissionArea( "normal", 0.01, 0.01, 0, true )
|
particles:setEmissionArea( "normal", 0.01, 0.01, 0, true )
|
||||||
|
|
||||||
love.graphics.setCanvas( marble.Canvas() )
|
love.graphics.setCanvas( marble.Canvas() )
|
||||||
Draw()
|
|
||||||
love.graphics.setCanvas()
|
love.graphics.setCanvas()
|
||||||
|
|
||||||
local totalTime = state.tick / 120.0
|
local totalTime = love.timer.getTime() - state.startTime
|
||||||
OnImpact = function() end
|
OnImpact = function() end
|
||||||
love.update = function( dt )
|
love.update = function( dt )
|
||||||
while dt > step do
|
while dt > step do
|
||||||
|
@ -263,7 +230,6 @@ OnVictory = function()
|
||||||
marble.Update()
|
marble.Update()
|
||||||
wave.Update()
|
wave.Update()
|
||||||
|
|
||||||
|
|
||||||
dt = dt - step
|
dt = dt - step
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -279,11 +245,20 @@ OnVictory = function()
|
||||||
love.graphics.draw( particles )
|
love.graphics.draw( particles )
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
text.Draw( 119 )
|
|
||||||
scores.RenderHighScores()
|
|
||||||
|
|
||||||
|
|
||||||
|
text.Draw( 119 )
|
||||||
|
|
||||||
local score = state.longestStreak * state.longestStreak / totalTime
|
local score = state.longestStreak * state.longestStreak / totalTime
|
||||||
|
|
||||||
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
|
love.graphics.printf(
|
||||||
|
string.format( "time:\t%.2f\nstreak:\t%d\nscore:%.2f", totalTime, state.longestStreak, score):gsub( "%.", "," ),
|
||||||
|
0, 0.5 * love.graphics.getHeight() - 2.0* love.graphics.getFont():getHeight(),
|
||||||
|
love.graphics.getWidth(),
|
||||||
|
"center"
|
||||||
|
)
|
||||||
|
|
||||||
marble.Draw()
|
marble.Draw()
|
||||||
end
|
end
|
||||||
marble.OnVictory()
|
marble.OnVictory()
|
||||||
|
@ -291,8 +266,6 @@ OnVictory = function()
|
||||||
end
|
end
|
||||||
|
|
||||||
Draw = function()
|
Draw = function()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local score = ExtrapolateBeatScore()
|
local score = ExtrapolateBeatScore()
|
||||||
|
|
||||||
|
@ -303,8 +276,6 @@ Draw = function()
|
||||||
love.graphics.setColor( 1.0, 1.0, 1.0, 1.0 )
|
love.graphics.setColor( 1.0, 1.0, 1.0, 1.0 )
|
||||||
love.graphics.draw(particles, 0, 0)
|
love.graphics.draw(particles, 0, 0)
|
||||||
wave.Draw( score )
|
wave.Draw( score )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
|
@ -312,12 +283,6 @@ Draw = function()
|
||||||
sitelenpona.Draw( text.words[state.currentBeat] )
|
sitelenpona.Draw( text.words[state.currentBeat] )
|
||||||
marble.Draw()
|
marble.Draw()
|
||||||
text.Draw( state.currentBeat )
|
text.Draw( state.currentBeat )
|
||||||
|
|
||||||
love.graphics.setColor( 0.3, 0.3, 0.3, 1.0 - score )
|
|
||||||
local s = "+"..state.currentStreak..(state.currentStreak > 50 and "!" or "")
|
|
||||||
love.graphics.print( s, state.lastCollisionX, state.lastCollisionY, 0, 0.5 - 0.1 * score, 0.5 - 0.1 * score)
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -331,21 +296,7 @@ Update = function( dt )
|
||||||
|
|
||||||
--Physics tick.
|
--Physics tick.
|
||||||
while dt > step do
|
while dt > step do
|
||||||
|
recorder.Update( marble.GetAcceleration() ) --For savegames.
|
||||||
state.tick = state.tick + 1
|
|
||||||
|
|
||||||
if mouseControl.isActive then
|
|
||||||
mouseControl.update()
|
|
||||||
marble.SetAcceleration( mouseControl.getAcceleration() )
|
|
||||||
end
|
|
||||||
|
|
||||||
if state.isDemo then
|
|
||||||
local ddx, ddy = recorder.NextTick()
|
|
||||||
if ddx then marble.SetAcceleration( ddx, ddy )
|
|
||||||
else state.isDemo = false end
|
|
||||||
else
|
|
||||||
recorder.Update( marble.GetAcceleration() ) --For savegames.
|
|
||||||
end
|
|
||||||
|
|
||||||
marble.Integrate( step )
|
marble.Integrate( step )
|
||||||
wave.Integrate( step )
|
wave.Integrate( step )
|
||||||
|
@ -364,51 +315,14 @@ Update = function( dt )
|
||||||
end
|
end
|
||||||
_Update = Update
|
_Update = Update
|
||||||
|
|
||||||
local function OptionsMenu()
|
|
||||||
if not options then options = require( "options" ) end
|
|
||||||
return options.EnterMenu()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function LoadGame() -- Load game screen.
|
|
||||||
|
|
||||||
local Click, Press = assert(loadGame.OnClick), assert(loadGame.KeyPress)
|
|
||||||
loadGame.LoadGameMenu()
|
|
||||||
|
|
||||||
love.mousepressed = function( x, y, button, istouch, presses)
|
|
||||||
local demoName = Click( x, y, button, istouch, presses )
|
|
||||||
if demoName then return NewGame( demoName ) end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.keypressed = function( key, code, isRepeat)
|
|
||||||
local demoName = Press( key, code, isRepeat )
|
|
||||||
if demoName then return NewGame( demoName ) end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.keypressed( key, code, isRepeat )
|
function love.keypressed( key, code, isRepeat )
|
||||||
if code == "escape" then return love.event.quit() end
|
if key == "escape" then return love.event.quit() end
|
||||||
if code == "space" then return NewGame() end
|
if key == "space" then return NewGame() end
|
||||||
if code == "return" then return LoadGame() end --Play demo.
|
return marble.OnKey()
|
||||||
if code == "o" then return OptionsMenu() end
|
|
||||||
if state.isDemo then return end
|
|
||||||
|
|
||||||
mouseControl.isActive = false
|
|
||||||
return marble.OnKey(
|
|
||||||
love.keyboard.isScancodeDown( options.up.value ),
|
|
||||||
love.keyboard.isScancodeDown( options.left.value ),
|
|
||||||
love.keyboard.isScancodeDown( options.down.value ),
|
|
||||||
love.keyboard.isScancodeDown( options.right.value )
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.keyreleased( key, code )
|
function love.keyreleased( key, code )
|
||||||
return marble.OnKey(
|
return marble.OnKey()
|
||||||
love.keyboard.isScancodeDown( options.up.value),
|
|
||||||
love.keyboard.isScancodeDown( options.left.value),
|
|
||||||
love.keyboard.isScancodeDown( options.down.value),
|
|
||||||
love.keyboard.isScancodeDown( options.right.value) )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.resize( w, h )
|
function love.resize( w, h )
|
||||||
|
@ -416,13 +330,6 @@ function love.resize( w, h )
|
||||||
if marble then marble.Resize() end
|
if marble then marble.Resize() end
|
||||||
end
|
end
|
||||||
|
|
||||||
--TODO: make this feel better.
|
|
||||||
function love.mousemoved( x, y, dx, dy, number, istouch )
|
|
||||||
mouseControl.isActive = true
|
|
||||||
dx, dy = mouseControl.mousemoved( dx, dy )
|
|
||||||
if dx then return marble.SetAcceleration( dx, dy ) end
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.mousepressed( x, y, button, istouch, presses )
|
function love.mousepressed( x, y, button, istouch, presses )
|
||||||
return NewGame()
|
return NewGame()
|
||||||
end
|
end
|
21
marble.lua
21
marble.lua
|
@ -19,10 +19,8 @@ function marble.Next() return newState end
|
||||||
|
|
||||||
function marble.GetAcceleration( ) return ddx, ddy end
|
function marble.GetAcceleration( ) return ddx, ddy end
|
||||||
|
|
||||||
function marble.SetAcceleration( x, y ) ddx = x; ddy = y end
|
|
||||||
|
|
||||||
function marble.Integrate( step )
|
function marble.Integrate( step )
|
||||||
newState.t = curState.t + step
|
newState.t = love.timer.getTime()
|
||||||
newState.dx = (1.0 - INERTIA) * curState.dx + INERTIA * ddx
|
newState.dx = (1.0 - INERTIA) * curState.dx + INERTIA * ddx
|
||||||
newState.dy = (1.0 - INERTIA) * curState.dy + INERTIA * ddy
|
newState.dy = (1.0 - INERTIA) * curState.dy + INERTIA * ddy
|
||||||
newState.x = curState.x + newState.dx * step * MAXSPEED
|
newState.x = curState.x + newState.dx * step * MAXSPEED
|
||||||
|
@ -75,7 +73,7 @@ function marble.OnImpact( impact, level )
|
||||||
xn = 0.2 * unx + x, yn = 0.2 * uny + y,
|
xn = 0.2 * unx + x, yn = 0.2 * uny + y,
|
||||||
vxout = x + vxout, vyout = y + vyout}]]
|
vxout = x + vxout, vyout = y + vyout}]]
|
||||||
|
|
||||||
return marble.Integrate( 1 / 120.0 ) --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
|
end
|
||||||
|
|
||||||
function marble.Update()
|
function marble.Update()
|
||||||
|
@ -84,18 +82,14 @@ function marble.Update()
|
||||||
oldState[k] = curState[k]
|
oldState[k] = curState[k]
|
||||||
curState[k] = newState[k]
|
curState[k] = newState[k]
|
||||||
end
|
end
|
||||||
|
|
||||||
--Inertia.
|
|
||||||
--ddx, ddy = ddx * 0.95, ddy * 0.95
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function marble.OnKey( w, a, s, d )
|
|
||||||
--print( w, a, s, d )
|
|
||||||
ddx = (d and 1.0 or 0.0) - (a and 1.0 or 0.0)
|
|
||||||
ddy = (w and 1.0 or 0.0) - (s and 1.0 or 0.0)
|
|
||||||
|
|
||||||
--print( tick, ddx, ddy )
|
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 )
|
local n = math.sqrt( ddx * ddx + ddy * ddy )
|
||||||
if n < 0.001 then return end
|
if n < 0.001 then return end
|
||||||
ddx, ddy = ddx / n, ddy / n
|
ddx, ddy = ddx / n, ddy / n
|
||||||
|
@ -129,7 +123,7 @@ function marble.Draw()
|
||||||
|
|
||||||
--Extrapolate forward for slightly smoother rendering.
|
--Extrapolate forward for slightly smoother rendering.
|
||||||
local dt = love.timer.getTime() - curState.t
|
local dt = love.timer.getTime() - curState.t
|
||||||
marble.Integrate( 2 / 120.0 )
|
marble.Integrate( dt + 1 / 60.0 )
|
||||||
|
|
||||||
local xp, yp = transform:transformPoint( oldState.x, oldState.y )
|
local xp, yp = transform:transformPoint( oldState.x, oldState.y )
|
||||||
local xc, yc = transform:transformPoint( curState.x, curState.y )
|
local xc, yc = transform:transformPoint( curState.x, curState.y )
|
||||||
|
@ -183,7 +177,6 @@ function marble.Reset()
|
||||||
INERTIA = 0.05
|
INERTIA = 0.05
|
||||||
MAXSPEED = 2.0
|
MAXSPEED = 2.0
|
||||||
|
|
||||||
ddx, ddy = 0, 0
|
|
||||||
oldState, curState, newState = State(), State(), State()
|
oldState, curState, newState = State(), State(), State()
|
||||||
marble.Resize()
|
marble.Resize()
|
||||||
marble.Draw = marble._Draw
|
marble.Draw = marble._Draw
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
local mouseControl = { isActive = false }
|
|
||||||
local love = love
|
|
||||||
|
|
||||||
local x, y = 0, 0
|
|
||||||
|
|
||||||
local DECAY = 0.8
|
|
||||||
local SENSITIVITY = 0.8
|
|
||||||
|
|
||||||
function mouseControl.Reset()
|
|
||||||
x, y = 0, 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function mouseControl.mousemoved( dx, dy )
|
|
||||||
|
|
||||||
dx, dy = SENSITIVITY * dx, SENSITIVITY * dy
|
|
||||||
dx, dy = dx * dx * dx , dy * dy * dy
|
|
||||||
x, y = dx + x, y - dy
|
|
||||||
|
|
||||||
|
|
||||||
return mouseControl.getAcceleration()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function mouseControl.update()
|
|
||||||
local norm = math.sqrt( x * x + y * y )
|
|
||||||
local decay = DECAY * norm / ( norm + 1 )
|
|
||||||
x, y = decay * x, decay * y
|
|
||||||
end
|
|
||||||
|
|
||||||
function mouseControl.getAcceleration()
|
|
||||||
local norm = math.sqrt( x * x + y * y )
|
|
||||||
if norm > 1 then return x / norm, y / norm end
|
|
||||||
if norm < 0.001 then return 0, 0 end
|
|
||||||
return x, y
|
|
||||||
end
|
|
||||||
|
|
||||||
return mouseControl
|
|
205
options.lua
205
options.lua
|
@ -1,205 +0,0 @@
|
||||||
local love = love
|
|
||||||
|
|
||||||
local draw = love.draw
|
|
||||||
local update = love.update
|
|
||||||
local mousepressed = love.mousepressed
|
|
||||||
local keypressed = love.keypressed
|
|
||||||
local mousemoved = love.mousemoved
|
|
||||||
local ExitMenu
|
|
||||||
|
|
||||||
options = options or {}
|
|
||||||
local options = options
|
|
||||||
local optionList = {}
|
|
||||||
local option
|
|
||||||
|
|
||||||
if not options.initialized then
|
|
||||||
options.initialized = true
|
|
||||||
|
|
||||||
local keyBindCallback = function(self, code)
|
|
||||||
self.value = code or self.value
|
|
||||||
end
|
|
||||||
|
|
||||||
options.optionValues = {
|
|
||||||
{ name = "options",
|
|
||||||
value = "",
|
|
||||||
callback = function(self)
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "fullscreen",
|
|
||||||
value = false,
|
|
||||||
callback = function(self)
|
|
||||||
self.value = not(self.value)
|
|
||||||
love.window.setFullscreen( self.value )
|
|
||||||
love.event.push( "resize", love.graphics.getWidth(), love.graphics.getHeight() )
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "high contrast",
|
|
||||||
value = false,
|
|
||||||
callback = function(self, code)
|
|
||||||
if code == "backspace" then return end
|
|
||||||
self.value = not( self.value )
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "volume",
|
|
||||||
value = 1.0,
|
|
||||||
callback = function(self, code)
|
|
||||||
|
|
||||||
local isIncreasing
|
|
||||||
if (code == "left" or code == "a") then isIncreasing = -1
|
|
||||||
elseif (code == "right" or code == "d") then isIncreasing = 1
|
|
||||||
else return false end
|
|
||||||
self.value = math.max( 0, math.min( 2,
|
|
||||||
self.value + (isIncreasing * 0.05 )))
|
|
||||||
love.audio.setVolume( self.value )
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "left",
|
|
||||||
value = "a",
|
|
||||||
callback = keyBindCallback
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "right",
|
|
||||||
value = "d",
|
|
||||||
callback = keyBindCallback
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "up",
|
|
||||||
value = "w",
|
|
||||||
callback = keyBindCallback
|
|
||||||
},
|
|
||||||
|
|
||||||
{ name = "down",
|
|
||||||
value = "s",
|
|
||||||
callback = keyBindCallback
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
for i, ov in ipairs( options.optionValues ) do
|
|
||||||
options[ ov.name ] = ov
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local optionIdx = 1
|
|
||||||
local isAwaitingKey = false
|
|
||||||
|
|
||||||
local font = love.graphics.newFont( 32 )
|
|
||||||
local function Draw()
|
|
||||||
love.graphics.setColor( 1,1,1,1 )
|
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0, 0, 0, 1 )
|
|
||||||
end
|
|
||||||
for i, option in ipairs( options.optionValues ) do
|
|
||||||
love.graphics.printf( option.name, font, 100, i * 50, 1000, "left")
|
|
||||||
love.graphics.printf( tostring( option.value ), font, -100, i * 50, love.graphics.getWidth(), "right")
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local w = love.graphics.getWidth()
|
|
||||||
|
|
||||||
love.graphics.setColor( 1,1,1,0.5 )
|
|
||||||
if isAwaitingKey then
|
|
||||||
love.graphics.rectangle( "fill", w - 200, optionIdx * 50, 100, 48, 10, 10 )
|
|
||||||
else
|
|
||||||
love.graphics.rectangle( "fill", 100, optionIdx * 50, 250, 48, 10, 10 )
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function SelectNextOption()
|
|
||||||
optionIdx = math.min( #options.optionValues, optionIdx + 1 )
|
|
||||||
option = options.optionValues[ optionIdx]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function SelectPreviousOption()
|
|
||||||
optionIdx = math.max( 1, optionIdx - 1 )
|
|
||||||
option = options.optionValues[ optionIdx]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function MouseMoved( x, y )
|
|
||||||
optionIdx =
|
|
||||||
math.min( #options.optionValues,
|
|
||||||
math.max( 1,
|
|
||||||
math.floor( y / 50 )
|
|
||||||
))
|
|
||||||
option = options.optionValues[ optionIdx]
|
|
||||||
|
|
||||||
if ( x > love.graphics.getWidth() - 200 ) then
|
|
||||||
isAwaitingKey = true
|
|
||||||
else
|
|
||||||
isAwaitingKey = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local function KeyPress(key, code, isRepeat)
|
|
||||||
|
|
||||||
if not( isAwaitingKey ) then
|
|
||||||
|
|
||||||
if code == "backspace" then
|
|
||||||
return ExitMenu() end
|
|
||||||
if optionIdx and
|
|
||||||
code == "return" or
|
|
||||||
code == "right" then
|
|
||||||
isAwaitingKey = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if code == "down" then return SelectNextOption() end
|
|
||||||
if code == "up" then return SelectPreviousOption() end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
if code == "backspace" then isAwaitingKey = false end
|
|
||||||
if code == "escape" then return end
|
|
||||||
isAwaitingKey = (options.optionValues[optionIdx]):callback( code )
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local function MousePressed( )
|
|
||||||
return KeyPress( )
|
|
||||||
end
|
|
||||||
|
|
||||||
local function EnterMenu()
|
|
||||||
draw = love.draw
|
|
||||||
update = love.update
|
|
||||||
mousepressed = love.mousepressed
|
|
||||||
keypressed = love.keypressed
|
|
||||||
mousemoved = love.mousemoved
|
|
||||||
love.mouse.setRelativeMode( false )
|
|
||||||
|
|
||||||
love.draw = Draw
|
|
||||||
love.keypressed = KeyPress
|
|
||||||
love.update = function() end
|
|
||||||
love.mousemoved = MouseMoved
|
|
||||||
love.mousepressed = MousePressed
|
|
||||||
end
|
|
||||||
|
|
||||||
function ExitMenu()
|
|
||||||
love.mouse.setRelativeMode( true )
|
|
||||||
love.mousemoved = mousemoved
|
|
||||||
love.keypressed = keypressed
|
|
||||||
love.mousepressed = mousepressed
|
|
||||||
love.update = update
|
|
||||||
love.draw = draw
|
|
||||||
end
|
|
||||||
|
|
||||||
options.EnterMenu = EnterMenu
|
|
||||||
options.ExitMenu = ExitMenu
|
|
||||||
|
|
||||||
return options
|
|
43
recorder.lua
43
recorder.lua
|
@ -2,20 +2,13 @@
|
||||||
local love = love
|
local love = love
|
||||||
local recorder = {}
|
local recorder = {}
|
||||||
recorder.isLoaded = false
|
recorder.isLoaded = false
|
||||||
local ddxs, ddys
|
|
||||||
local i = 0
|
local i = 0
|
||||||
|
|
||||||
function recorder.Reset()
|
local function Reset()
|
||||||
i = 1
|
i = 0
|
||||||
for k, _ in ipairs( recorder ) do recorder[k] = nil end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function recorder.Update( ddx, ddy )
|
function recorder.Update( ddx, ddy )
|
||||||
i = i + 1
|
|
||||||
recorder[i] = love.data.pack( "string", "!16<dd", ddx, ddy )
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[function recorder.Update( ddx, ddy )
|
|
||||||
local byte = 0
|
local byte = 0
|
||||||
if ddx > 0.5 then byte = byte + 1 end
|
if ddx > 0.5 then byte = byte + 1 end
|
||||||
if ddy > 0.5 then byte = byte + 2 end
|
if ddy > 0.5 then byte = byte + 2 end
|
||||||
|
@ -23,35 +16,17 @@ end
|
||||||
if ddy < -0.5 then byte = byte + 8 end
|
if ddy < -0.5 then byte = byte + 8 end
|
||||||
|
|
||||||
i = i + 1
|
i = i + 1
|
||||||
recorder[i] = string.char( byte + 48 )
|
recorder[i] = string.char( byte )
|
||||||
end]]
|
end
|
||||||
|
|
||||||
function recorder.Load( filename )
|
function recorder.Load( )
|
||||||
ddxs, ddys = {}, {}
|
local s = love.filesystem.read( "demo" )
|
||||||
local s = love.filesystem.read( filename )
|
|
||||||
if not s then return end
|
|
||||||
local j = 1
|
|
||||||
local score, ticks, k = love.data.unpack( "!16<dJ", s, 1)
|
|
||||||
local n = s:len()
|
|
||||||
while k < n do
|
|
||||||
ddxs[j], ddys[j], k = love.data.unpack( "!16<dd", s, k)
|
|
||||||
j = j + 1
|
|
||||||
end
|
|
||||||
recorder.isLoaded = true
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
return true
|
recorder.isLoaded = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function recorder.NextTick( )
|
function recorder.Save( )
|
||||||
i = i + 1
|
assert( love.filesystem.write( "demo", table.concat( recorder ) ) )
|
||||||
return ddxs[i], ddys[i]
|
|
||||||
end
|
|
||||||
|
|
||||||
function recorder.Save( score, ticks )
|
|
||||||
recorder[1] = love.data.pack( "string", "!16<dJ", score, ticks )
|
|
||||||
love.filesystem.createDirectory( "demos" )
|
|
||||||
return assert( love.filesystem.write( "demos/"..os.time()..".yod" , table.concat( recorder ) ) )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return recorder
|
return recorder
|
118
scores.lua
118
scores.lua
|
@ -1,118 +0,0 @@
|
||||||
local love = love
|
|
||||||
local scores = {}
|
|
||||||
local highScores = {}
|
|
||||||
|
|
||||||
local letters = {
|
|
||||||
letters = { "D", "C", "B", "A", "S", "SS", "SSS" },
|
|
||||||
ticks = { 50000, 14400, 12000, 10000, 8000, 6000, 5000 },
|
|
||||||
streaks = { 1, 20, 40, 60, 80, 100, 120 },
|
|
||||||
score = { 0, 5, 10, 22, 56, 150, 300 },
|
|
||||||
}
|
|
||||||
|
|
||||||
letters.letters[0] = "!"
|
|
||||||
|
|
||||||
local function ScoreToLetter( ticks, streak, score )
|
|
||||||
local streakTier, ticksTier, scoreTier = 0, 0, 0
|
|
||||||
|
|
||||||
for i, threshold in ipairs( letters.ticks ) do
|
|
||||||
if ticks < threshold then ticksTier = i end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, threshold in ipairs( letters.streaks ) do
|
|
||||||
if streak > threshold then streakTier = i end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, threshold in ipairs( letters.score ) do
|
|
||||||
if score > threshold then scoreTier = i end
|
|
||||||
end
|
|
||||||
|
|
||||||
return letters.letters[ticksTier], letters.letters[streakTier], letters.letters[scoreTier]
|
|
||||||
end
|
|
||||||
|
|
||||||
function scores.OnImpact( tick, isHitSuccessful )
|
|
||||||
local score = 0
|
|
||||||
if isHitSuccessful then
|
|
||||||
scores.streak = scores.streak + 1
|
|
||||||
scores.longestStreak = math.max( scores.streak, scores.longestStreak )
|
|
||||||
else
|
|
||||||
table.insert( scores.streaks, scores.streak)
|
|
||||||
scores.streak = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, streak in ipairs( scores.streaks ) do
|
|
||||||
score = score + math.pow( streak, 1.7 )
|
|
||||||
end
|
|
||||||
|
|
||||||
scores.score = score / ( ( tick / 120.0 ) - 36.0 )
|
|
||||||
scores.t = tick
|
|
||||||
end
|
|
||||||
|
|
||||||
function scores.Reset()
|
|
||||||
scores.score = 0
|
|
||||||
scores.streak = 0
|
|
||||||
scores.longestStreak = 0
|
|
||||||
scores.highScore = scores.LoadHighScores()
|
|
||||||
scores.streaks = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
function scores.Get()
|
|
||||||
return scores.score
|
|
||||||
end
|
|
||||||
|
|
||||||
function scores.Save()
|
|
||||||
local i = 1
|
|
||||||
for j = 1, #highScores do
|
|
||||||
i = j
|
|
||||||
if highScores[j] < scores.score then break end
|
|
||||||
end
|
|
||||||
table.insert( highScores, i )
|
|
||||||
scores.highScore = math.max( scores.score, scores.highScore )
|
|
||||||
end
|
|
||||||
|
|
||||||
function scores.LoadHighScores()
|
|
||||||
local gameList = assert( love.filesystem.getDirectoryItems( "demos" ) )
|
|
||||||
local highScore = 0
|
|
||||||
for i, name in ipairs( gameList ) do
|
|
||||||
local s = love.filesystem.read( "demos/"..name, 64 )
|
|
||||||
if ( s:len() > 32 ) then
|
|
||||||
local gamescore, gameticks = love.data.unpack( "!16<dJ", s, 1)
|
|
||||||
highScore = math.max( gamescore, highScore )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return highScore
|
|
||||||
end
|
|
||||||
|
|
||||||
function scores.RenderHighScores()
|
|
||||||
local wb = options["high contrast"].value and 0 or 1
|
|
||||||
love.graphics.setColor( wb, wb, wb, 1 )
|
|
||||||
local h = 1.0 * love.graphics.getFont():getHeight()
|
|
||||||
local y = 0.5 * love.graphics.getHeight()
|
|
||||||
|
|
||||||
local lTick, lStreak, lScore = ScoreToLetter( scores.t, scores.longestStreak, scores.score )
|
|
||||||
love.graphics.printf(
|
|
||||||
table.concat{
|
|
||||||
"time: ",
|
|
||||||
string.format("%.1f", scores.t / 120.0):gsub("%.", ","),
|
|
||||||
".",
|
|
||||||
lTick,
|
|
||||||
"\n",
|
|
||||||
"streak: ",
|
|
||||||
scores.longestStreak,
|
|
||||||
".",
|
|
||||||
lStreak,
|
|
||||||
"\n",
|
|
||||||
"score: ",
|
|
||||||
string.format("%.1f", scores.score ):gsub("%.", ","),
|
|
||||||
".",
|
|
||||||
lScore,
|
|
||||||
"\n",
|
|
||||||
"record: ",
|
|
||||||
string.format("%.1f", math.max( scores.highScore, scores.score )):gsub("%.", ","),
|
|
||||||
".!\n"
|
|
||||||
},
|
|
||||||
love.graphics.getWidth() * 0.5 - 250, y - 2 * h, 500, "justify" )
|
|
||||||
end
|
|
||||||
|
|
||||||
scores.highScore = scores.LoadHighScores()
|
|
||||||
|
|
||||||
return scores
|
|
|
@ -10,12 +10,12 @@ end
|
||||||
sp.Draw = function( t )
|
sp.Draw = function( t )
|
||||||
local cx, cy = love.graphics.getDimensions()
|
local cx, cy = love.graphics.getDimensions()
|
||||||
cx, cy = 0.5 * cx, 0.5 * cy
|
cx, cy = 0.5 * cx, 0.5 * cy
|
||||||
love.graphics.setColor( 1.0, 1.0, 1.0, options["high contrast"].value and 0.2 or 0.5)
|
love.graphics.setColor( 1.0, 1.0, 1.0, 0.5 )
|
||||||
|
|
||||||
if #t == 1 then
|
if #t == 1 then
|
||||||
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 128, cy - 128 )
|
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 128, cy - 128 )
|
||||||
elseif #t == 2 then
|
elseif #t == 2 then
|
||||||
love.graphics.draw( sp[t[1]] or sp.pilin, cx - 160, cy - 96, 0, 0.75, 0.75 )
|
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 )
|
love.graphics.draw( sp[t[2]] or sp.pilin, cx - 16, cy - 96, 0, 0.75, 0.75 )
|
||||||
elseif #t == 3 then
|
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 )
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB |
70
text.lua
70
text.lua
|
@ -10,10 +10,9 @@ local poemLines = {[0] = 0}
|
||||||
local mt = { __index = function() return "linja" end }
|
local mt = { __index = function() return "linja" end }
|
||||||
|
|
||||||
local s = love.filesystem.read( "text/tok.txt" )
|
local s = love.filesystem.read( "text/tok.txt" )
|
||||||
local instrFont = love.graphics.newFont( 24 )
|
local enFont = love.graphics.setNewFont( "text/linja-sike.ttf", 18 )
|
||||||
local enFont = love.graphics.setNewFont( "text/yod-linja-sike.ttf", 18 )
|
local smallFont = love.graphics.setNewFont( "text/linja-sike.ttf", 24 )
|
||||||
local smallFont = love.graphics.setNewFont( "text/yod-linja-sike.ttf", 24 )
|
local largeFont = love.graphics.setNewFont( "text/linja-sike.ttf", 64 )
|
||||||
local largeFont = love.graphics.setNewFont( "text/yod-linja-sike.ttf", 64 )
|
|
||||||
|
|
||||||
|
|
||||||
local i = 1
|
local i = 1
|
||||||
|
@ -40,11 +39,11 @@ for foot in s:gmatch( ".-%-" ) do
|
||||||
local j = 1
|
local j = 1
|
||||||
|
|
||||||
for w in foot:gmatch( [["]] ) do
|
for w in foot:gmatch( [["]] ) do
|
||||||
|
|
||||||
word[j] = isTe and "te" or "to"
|
word[j] = isTe and "te" or "to"
|
||||||
isTe = not( isTe )
|
isTe = not( isTe )
|
||||||
j = j + 1
|
j = j + 1
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
for w in foot:gmatch( "%a+" ) do
|
for w in foot:gmatch( "%a+" ) do
|
||||||
|
@ -58,54 +57,25 @@ end
|
||||||
local function Draw( beat )
|
local function Draw( beat )
|
||||||
|
|
||||||
local foot = feet[ beat ]
|
local foot = feet[ beat ]
|
||||||
|
|
||||||
if beat == 1 then
|
if beat == 1 then
|
||||||
|
love.graphics.setColor(0.0, 0.0, 0.0, 1.0)
|
||||||
love.graphics.setColor(0, 0, 0, 0.5)
|
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.rectangle( "fill",
|
|
||||||
0.5 * love.graphics.getWidth() - 250, 10,
|
|
||||||
500, 1.1 * largeFont:getHeight(), 10, 10 )
|
|
||||||
|
|
||||||
love.graphics.rectangle( "fill",
|
|
||||||
0.5 * love.graphics.getWidth() - 200, love.graphics.getHeight() - 5.25 * instrFont:getHeight(),
|
|
||||||
400, 4.5 * instrFont:getHeight(), 50, 50 )
|
|
||||||
|
|
||||||
love.graphics.setColor(1.0, 1.0, 1.0, 1.0 )
|
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0, 0, 0, 1 )
|
|
||||||
end
|
|
||||||
love.graphics.printf( "your.own.drum",
|
love.graphics.printf( "your.own.drum",
|
||||||
largeFont,
|
0, 0,
|
||||||
0, 0,
|
love.graphics.getWidth(),
|
||||||
love.graphics.getWidth(),
|
"center"
|
||||||
"center"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
love.graphics.printf(
|
|
||||||
[[
|
|
||||||
WASD MOVE
|
|
||||||
SPACE RESTART
|
|
||||||
RETURN DEMOS
|
|
||||||
O OPTIONS]],
|
|
||||||
instrFont,
|
|
||||||
0.5 * love.graphics.getWidth() - 150, love.graphics.getHeight() - 5 * instrFont:getHeight(),
|
|
||||||
300,
|
|
||||||
"justify"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
love.graphics.printf( "wasd.space",
|
||||||
|
0, 0.87 * love.graphics.getHeight(),
|
||||||
|
love.graphics.getWidth(),
|
||||||
|
"center"
|
||||||
|
)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
love.graphics.setColor(1.0, 1.0, 1.0, 0.5)
|
love.graphics.setColor(1.0, 1.0, 1.0, 0.5)
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0, 0, 0, 1 )
|
|
||||||
end
|
|
||||||
local lineNumber
|
local lineNumber
|
||||||
if poemLines[beat] < 2 then lineNumber = 0
|
if poemLines[beat] < 2 then lineNumber = 0
|
||||||
else lineNumber = 2 - poemLines[beat]
|
else lineNumber = 2 - poemLines[beat]
|
||||||
|
@ -118,9 +88,6 @@ O OPTIONS]],
|
||||||
)
|
)
|
||||||
|
|
||||||
love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
|
love.graphics.setColor(1.0, 1.0, 1.0, 1.0)
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0, 0, 0, 1 )
|
|
||||||
end
|
|
||||||
love.graphics.printf( foot,
|
love.graphics.printf( foot,
|
||||||
largeFont,
|
largeFont,
|
||||||
0, 0.87 * love.graphics.getHeight(),
|
0, 0.87 * love.graphics.getHeight(),
|
||||||
|
@ -129,9 +96,6 @@ O OPTIONS]],
|
||||||
)
|
)
|
||||||
|
|
||||||
love.graphics.setColor(1.0, 1.0, 1.0, 0.5)
|
love.graphics.setColor(1.0, 1.0, 1.0, 0.5)
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0, 0, 0, 1 )
|
|
||||||
end
|
|
||||||
love.graphics.printf( poemLang[beat],
|
love.graphics.printf( poemLang[beat],
|
||||||
enFont,
|
enFont,
|
||||||
-8, 0,--(2 - poemLines[beat]) * smallFont:getHeight(),
|
-8, 0,--(2 - poemLines[beat]) * smallFont:getHeight(),
|
||||||
|
@ -143,7 +107,7 @@ O OPTIONS]],
|
||||||
end
|
end
|
||||||
|
|
||||||
s = love.filesystem.read( "text/en.txt" )
|
s = love.filesystem.read( "text/en.txt" )
|
||||||
i = 0
|
i = 1
|
||||||
--Split string into lines.
|
--Split string into lines.
|
||||||
for line in s:gmatch( ".-\n") do
|
for line in s:gmatch( ".-\n") do
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
open -la mi -jan pi -toki-
|
open -la mi -jan pi -toki-
|
||||||
ala -li mu -taso -li ken-
|
ala -li mu -taso -li ken-
|
||||||
ala -pana -toki -pilin-
|
ala -pana -toki -pilin-
|
||||||
toki -mu li -wawa -wawa-
|
toki -mu li -wawa -wawa
|
||||||
nasa -la jan -ante -li ken-
|
nasa -la jan -ante -li ken-
|
||||||
awen -pona -tawa -mi li-
|
awen -pona -tawa -mi li-
|
||||||
awen -ala-sa e -pona.-
|
awen -ala-sa e -pona.-
|
||||||
|
|
28
wave.lua
28
wave.lua
|
@ -46,10 +46,10 @@ local shader = love.graphics.newShader([[
|
||||||
vec2 p = (3.0 * screen_coords - 1.5 * love_ScreenSize.xy ) / love_ScreenSize.y;
|
vec2 p = (3.0 * screen_coords - 1.5 * love_ScreenSize.xy ) / love_ScreenSize.y;
|
||||||
p.y = -p.y;
|
p.y = -p.y;
|
||||||
|
|
||||||
float r = r( atan(p.y, p.x) ) - length( p );
|
float r = r( atan(p.y, p.x) ) - length( p );
|
||||||
float q = float( r < 0.05 ) * clamp( 1.0 - score, 0.0, 1.0 ) ;
|
float q = float( r < 0.05 ) * clamp( 0.5 - score, 0.0, 1.0 ) ;
|
||||||
|
|
||||||
return vec4( q + (1.0 + clamp( score, 0.0, 1.0 ) * r * r * 0.3) * color.xyz, float(r > 0.0) ) ;
|
return vec4( q + (1.0 + clamp( score, 0.0, 1.0 ) * r * r * 0.2) * color.xyz, float(r > 0.0) ) ;
|
||||||
}
|
}
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ end
|
||||||
|
|
||||||
--Apply bandlimited impulse to wave, adjust free parameters according to game state.
|
--Apply bandlimited impulse to wave, adjust free parameters according to game state.
|
||||||
local function OnImpact( impact, level )
|
local function OnImpact( impact, level )
|
||||||
|
|
||||||
IMPULSESIZE = 10.0 * ( level - 2.0) / 120.0
|
IMPULSESIZE = 10.0 * ( level - 2.0) / 120.0
|
||||||
SOUNDSPEED = 25 - 10 * level / 120
|
SOUNDSPEED = 25 - 10 * level / 120
|
||||||
DAMPING = 0.01 * ( 1.0 - 0.4 * level / 120 )
|
DAMPING = 0.01 * ( 1.0 - 0.4 * level / 120 )
|
||||||
|
@ -159,7 +159,7 @@ local function OnImpact( impact, level )
|
||||||
local r = cur.radii
|
local r = cur.radii
|
||||||
local theta = impact.th
|
local theta = impact.th
|
||||||
local magnitude = IMPULSESIZE * impact.speed
|
local magnitude = IMPULSESIZE * impact.speed
|
||||||
local dt = 1.0 / 120.0
|
local dt = math.max( impact.dt, 1 / 120.0 )
|
||||||
for i = 0, N - 1 do
|
for i = 0, N - 1 do
|
||||||
r[ i + 1 ] = r[ i + 1 ] + dt * magnitude * AliasedSinc( theta, 2.0 * math.pi * i / N )
|
r[ i + 1 ] = r[ i + 1 ] + dt * magnitude * AliasedSinc( theta, 2.0 * math.pi * i / N )
|
||||||
end
|
end
|
||||||
|
@ -201,11 +201,7 @@ local function Draw( score )
|
||||||
|
|
||||||
-- Blue circle.
|
-- Blue circle.
|
||||||
love.graphics.setColor( 91 / 255, 206 / 255, 250 / 255 )
|
love.graphics.setColor( 91 / 255, 206 / 255, 250 / 255 )
|
||||||
--Black circle.
|
|
||||||
if options["high contrast"].value then
|
|
||||||
love.graphics.setColor( 0, 0, 0 )
|
|
||||||
end
|
|
||||||
|
|
||||||
shader:send( "re", unpack( cur.dftre ) )
|
shader:send( "re", unpack( cur.dftre ) )
|
||||||
shader:send( "im", unpack( cur.dftim ) )
|
shader:send( "im", unpack( cur.dftim ) )
|
||||||
shader:send( "score", score )
|
shader:send( "score", score )
|
||||||
|
@ -259,7 +255,7 @@ local function Draw( score )
|
||||||
local r = cur:Interpolate( t )
|
local r = cur:Interpolate( t )
|
||||||
local x, y = r * math.cos( t ), r * math.sin( t )
|
local x, y = r * math.cos( t ), r * math.sin( t )
|
||||||
love.graphics.circle( "fill", x, y, 0.02 )]]
|
love.graphics.circle( "fill", x, y, 0.02 )]]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,12 +279,12 @@ end
|
||||||
Integrate = function( step )
|
Integrate = function( step )
|
||||||
|
|
||||||
for i = 1, N do
|
for i = 1, N do
|
||||||
|
|
||||||
local rxx = cur:SecondDerivative( math.pi * 2.0 * ( i - 1 ) / N )
|
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
|
local r = ( 1.0 - DAMPING ) * ( 2.0 * cur.radii[i] - old.radii[i] + step * step * SOUNDSPEED * rxx ) --Verlet
|
||||||
+ DAMPING --Damping: oscillate toward 1.
|
+ DAMPING --Damping: oscillate toward 1.
|
||||||
|
|
||||||
--Avoid explosions.
|
--Avoid explosions.
|
||||||
r = math.max( 0.5, math.min( r, 4.0 ) )
|
r = math.max( 0.5, math.min( r, 4.0 ) )
|
||||||
new.radii[i] = r
|
new.radii[i] = r
|
||||||
|
@ -303,11 +299,11 @@ local function DetectCollision( px, py, vpx, vpy )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function Reset()
|
local function Reset()
|
||||||
|
|
||||||
IMPULSESIZE = 1 / 10.0
|
IMPULSESIZE = 1 / 10.0
|
||||||
SOUNDSPEED = 5.0
|
SOUNDSPEED = 5.0
|
||||||
DAMPING = 0.1 / 1
|
DAMPING = 0.1 / 1
|
||||||
|
|
||||||
old = Wave()
|
old = Wave()
|
||||||
cur = Wave()
|
cur = Wave()
|
||||||
new = Wave()
|
new = Wave()
|
||||||
|
|
Loading…
Reference in New Issue