diff --git a/conf.lua b/conf.lua index a262028..a2718b9 100644 --- a/conf.lua +++ b/conf.lua @@ -1,7 +1,6 @@ function love.conf( t ) t.version = "11.4" t.identity = "Your Own Drum" - t.console = true t.modules.joystick = false t.modules.physics = false diff --git a/demos/yam.yod b/demos/yam.yod new file mode 100644 index 0000000..e48429b Binary files /dev/null and b/demos/yam.yod differ diff --git a/loadgame.lua b/loadgame.lua index ee93227..2981d15 100644 --- a/loadgame.lua +++ b/loadgame.lua @@ -1,17 +1,18 @@ --UI for selecting a saved game. local love = love local loadGame = {} -local _Update = love.update -local _Draw = love.draw -local _MousePressed = love.mousepressed -local _Resize = love.resize -local _KeyPressed = love.keypressed -love.mouse.setRelativeMode( false ) +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 @@ -32,7 +33,7 @@ local OnClick local function DeleteLeft() - return w * 0.75 + 15 + 6 + return love.graphics.getWidth() * 0.75 + 15 + 6 end local function DeleteRight() @@ -46,6 +47,8 @@ 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 ) @@ -74,7 +77,11 @@ 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 ) @@ -156,10 +163,18 @@ end local wheelMoved = function(x, y) - scrollOffset = math.max( 0, math.min( #gameList, scrollOffset - y * 0.1 ) ) + --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 diff --git a/main.lua b/main.lua index 5ff4a22..9f5971a 100644 --- a/main.lua +++ b/main.lua @@ -160,6 +160,7 @@ function love.load() end + loadGame = assert( require "loadgame" ) options = assert( require( "options" ) ) mouseControl = assert( require "mousecontrols" ) sitelenpona = assert( require "sitelenpona" ) @@ -231,7 +232,7 @@ OnVictory = function() state.isDemo = false else scores.Save() - recorder.Save() + recorder.Save( scores.Get(), state.tick) end particles:setParticleLifetime( 0, 30 ) @@ -262,6 +263,7 @@ OnVictory = function() marble.Update() wave.Update() + dt = dt - step end @@ -331,6 +333,11 @@ Update = function( dt ) while dt > step do 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() @@ -363,8 +370,10 @@ local function OptionsMenu() end local function LoadGame() -- Load game screen. - if not loadGame then loadGame = assert( require "loadgame" ) end + 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 @@ -375,7 +384,7 @@ local function LoadGame() -- Load game screen. if demoName then return NewGame( demoName ) end end - loadGame.LoadGameMenu() + end function love.keypressed( key, code, isRepeat ) @@ -385,6 +394,7 @@ function love.keypressed( key, code, isRepeat ) 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 ), @@ -395,10 +405,10 @@ end function love.keyreleased( key, code ) 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 ) ) + 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 function love.resize( w, h ) @@ -408,6 +418,7 @@ 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 diff --git a/marble.lua b/marble.lua index 468f36b..9a35c02 100644 --- a/marble.lua +++ b/marble.lua @@ -84,6 +84,9 @@ function marble.Update() oldState[k] = curState[k] curState[k] = newState[k] end + + --Inertia. + --ddx, ddy = ddx * 0.95, ddy * 0.95 end diff --git a/mousecontrols.lua b/mousecontrols.lua index e57e7c0..130f2e3 100644 --- a/mousecontrols.lua +++ b/mousecontrols.lua @@ -1,25 +1,37 @@ -local mouseControl = {} +local mouseControl = { isActive = false } local love = love -local t = love.timer.getTime() +local x, y = 0, 0 + +local DECAY = 0.8 +local SENSITIVITY = 0.8 function mouseControl.Reset() - t = love.timer.getTime() + x, y = 0, 0 end function mouseControl.mousemoved( dx, dy ) - local dt = love.timer.getTime() - if dt - t < 1 / 1000.0 then return end - dt, t = dt - t, dt + + dx, dy = SENSITIVITY * dx, SENSITIVITY * dy + dx, dy = dx * dx * dx , dy * dy * dy + x, y = dx + x, y - dy - dx, dy = dx * dt, -dy * dt - local norm = math.sqrt( dx * dx + dy * dy ) - if norm > 1 then dx, dy = dx / norm, dy / norm end - - if norm < 0.01 then return 0, 0 end - return dx, 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 \ No newline at end of file diff --git a/options.lua b/options.lua index 7fea86b..c00768f 100644 --- a/options.lua +++ b/options.lua @@ -16,22 +16,31 @@ if not options.initialized then options.initialized = true local keyBindCallback = function(self, code) - self.value = code + self.value = code or self.value end options.optionValues = { { name = "options", - value = "back", + value = "", callback = function(self) - return ExitMenu() + 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 == "return" or code == "backspace" then return end + if code == "backspace" then return end self.value = not( self.value ) + return false end }, @@ -43,8 +52,9 @@ if not options.initialized then 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( 1, + self.value = math.max( 0, math.min( 2, self.value + (isIncreasing * 0.05 ))) + love.audio.setVolume( self.value ) return true end @@ -85,6 +95,9 @@ 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") @@ -94,7 +107,7 @@ local function Draw() local w = love.graphics.getWidth() - love.graphics.setColor( 1,1,1,0.5 ) + love.graphics.setColor( 1,1,1,0.5 ) if isAwaitingKey then love.graphics.rectangle( "fill", w - 200, optionIdx * 50, 100, 48, 10, 10 ) else @@ -113,21 +126,53 @@ local function SelectPreviousOption() 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 code == "backspace" then return ExitMenu() end - if isAwaitingKey then - + 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 - if code == "return" and optionIdx then isAwaitingKey = true; return end - if code == "down" then return SelectNextOption() end - if code == "up" then return SelectPreviousOption() end + +end + + +local function MousePressed( ) + return KeyPress( ) end local function EnterMenu() @@ -136,13 +181,17 @@ local function EnterMenu() 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 diff --git a/recorder.lua b/recorder.lua index 6c5dcde..3483ec5 100644 --- a/recorder.lua +++ b/recorder.lua @@ -6,7 +6,7 @@ local ddxs, ddys local i = 0 function recorder.Reset() - i = 0 + i = 1 for k, _ in ipairs( recorder ) do recorder[k] = nil end end @@ -30,7 +30,8 @@ function recorder.Load( filename ) ddxs, ddys = {}, {} local s = love.filesystem.read( filename ) if not s then return end - local k, j = 1, 1 + local j = 1 + local score, ticks, k = love.data.unpack( "!16 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 + streak * streak + score = score + math.pow( streak, 1.7 ) end - - scores.score = score / math.pow( tick / 120.0, 1.5 ) + + 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() @@ -36,24 +66,53 @@ function scores.Save() 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