diff --git a/assets/audio/sfx/buttonclick.ogg b/assets/audio/sfx/buttonclick.ogg new file mode 100644 index 0000000..66c10c4 Binary files /dev/null and b/assets/audio/sfx/buttonclick.ogg differ diff --git a/assets/audio/sfx/die.ogg b/assets/audio/sfx/die.ogg new file mode 100755 index 0000000..158ed0d Binary files /dev/null and b/assets/audio/sfx/die.ogg differ diff --git a/assets/audio/sfx/dropfood.ogg b/assets/audio/sfx/dropfood.ogg new file mode 100755 index 0000000..9eafcb1 Binary files /dev/null and b/assets/audio/sfx/dropfood.ogg differ diff --git a/assets/audio/sfx/grow.ogg b/assets/audio/sfx/grow.ogg new file mode 100644 index 0000000..564e9c3 Binary files /dev/null and b/assets/audio/sfx/grow.ogg differ diff --git a/assets/audio/sfx/slurp.ogg b/assets/audio/sfx/slurp.ogg new file mode 100755 index 0000000..e596585 Binary files /dev/null and b/assets/audio/sfx/slurp.ogg differ diff --git a/assets/audio/sfx/splash.ogg b/assets/audio/sfx/splash.ogg new file mode 100755 index 0000000..a8ae422 Binary files /dev/null and b/assets/audio/sfx/splash.ogg differ diff --git a/assets/audio/sfx/splashbig.ogg b/assets/audio/sfx/splashbig.ogg new file mode 100755 index 0000000..bce39cb Binary files /dev/null and b/assets/audio/sfx/splashbig.ogg differ diff --git a/assets/audio/sfx/tapglass.ogg b/assets/audio/sfx/tapglass.ogg new file mode 100644 index 0000000..c601e5d Binary files /dev/null and b/assets/audio/sfx/tapglass.ogg differ diff --git a/assets/sprites/footer/gif/LazerGunz.gif b/assets/sprites/footer/gif/LazerGunz.gif deleted file mode 100755 index 6155c75..0000000 Binary files a/assets/sprites/footer/gif/LazerGunz.gif and /dev/null differ diff --git a/assets/sprites/footer/gif/OPTIONSBUTTON.gif b/assets/sprites/footer/gif/OPTIONSBUTTON.gif deleted file mode 100755 index 999037e..0000000 Binary files a/assets/sprites/footer/gif/OPTIONSBUTTON.gif and /dev/null differ diff --git a/assets/sprites/footer/gif/OPTIONSBUTTONd.gif b/assets/sprites/footer/gif/OPTIONSBUTTONd.gif deleted file mode 100755 index bf616eb..0000000 Binary files a/assets/sprites/footer/gif/OPTIONSBUTTONd.gif and /dev/null differ diff --git a/assets/sprites/footer/gif/_LazerGunz.gif b/assets/sprites/footer/gif/_LazerGunz.gif deleted file mode 100755 index 4a0793c..0000000 Binary files a/assets/sprites/footer/gif/_LazerGunz.gif and /dev/null differ diff --git a/assets/sprites/footer/gif/_OPTIONSBUTTON.gif b/assets/sprites/footer/gif/_OPTIONSBUTTON.gif deleted file mode 100755 index 84db015..0000000 Binary files a/assets/sprites/footer/gif/_OPTIONSBUTTON.gif and /dev/null differ diff --git a/assets/sprites/footer/gif/_OPTIONSBUTTONd.gif b/assets/sprites/footer/gif/_OPTIONSBUTTONd.gif deleted file mode 100755 index 84db015..0000000 Binary files a/assets/sprites/footer/gif/_OPTIONSBUTTONd.gif and /dev/null differ diff --git a/assets/sprites/footer/gif/moneyflash.gif b/assets/sprites/footer/gif/moneyflash.gif deleted file mode 100755 index e36c80d..0000000 Binary files a/assets/sprites/footer/gif/moneyflash.gif and /dev/null differ diff --git a/const.lua b/const.lua index 7ebf39e..4133894 100644 --- a/const.lua +++ b/const.lua @@ -1,6 +1,6 @@ ease = require 'lib.ease' -FISH_SPLINE_QUALITY = 5 -- bigger number = more lag, smaller number = more noise +FISH_SPLINE_QUALITY = 6 -- bigger number = more lag, smaller number = more noise FISH_RENDER_ITERS = 4 -- a bigger number allows for more smoother flipper movement and rotation, but is significantly laggier FISH_RENDER_ITEROFF = 0.025 -- should be 1/iters*0.1, lower numbers will make movement snappier and higher numbers will make it smoother but glitchier @@ -11,8 +11,10 @@ FISH_EASE = ease.inOutSine -- ease used for fish movement FISH_ANGLE = 30 -- bigger angle allows for fish to swim further down/up at once FISH_FOLLOW_RANDOM = 10 -FISH_FOOD_CHECK_FREQ = 10 -- how often to check for food -FISH_FOOD_COOLDOWN = 10 +FISH_FOOD_CHECK_FREQ = 1 -- how often to check for food +FISH_FOOD_1_COOLDOWN = 10 +FISH_FOOD_2_COOLDOWN = 20 +FISH_FOOD_3_COOLDOWN = 25 FISH_FOOD_HUNGRY = -5 FISH_FOOD_DEAD = -15 diff --git a/constructors.lua b/constructors.lua index 223cd78..25dd5ef 100644 --- a/constructors.lua +++ b/constructors.lua @@ -52,7 +52,7 @@ function self.food(x, y, type) speed = 0.2, time = math.random(), deathtimer = 0, - type = 1 + type = type } return food diff --git a/lib/assets.lua b/lib/assets.lua index 8591550..1967f9d 100644 --- a/lib/assets.lua +++ b/lib/assets.lua @@ -1,3 +1,5 @@ +require 'lib.audio' + local assets = {} function assets.clear() @@ -70,8 +72,8 @@ function assets.addAudio(base, d, type) if type == "sfx" then sound_path[audioname] = dir .. "/" .. file - if sounds and sounds[audioname] then - registerSound(audioname, sounds[audioname].volume) + if sounds then + registerSound(audioname, (sounds[audioname] or {}).volume or 1) end elseif type == "bgm" then music_path[audioname] = dir .. "/" .. file diff --git a/lib/audio.lua b/lib/audio.lua new file mode 100644 index 0000000..09f29c8 --- /dev/null +++ b/lib/audio.lua @@ -0,0 +1,34 @@ +local tick = require 'lib.tick' + +sfx_volume = 1 + +sounds = {} +local current_volume = 1 +local old_volume = 1 +local sound_instances = {} + +function registerSound(sound, volume) + sounds[sound] = { + data = love.sound.newSoundData(sound_path[sound]), + volume = volume or 1 + } +end + +function playSound(sound, volume, pitch) + if sounds[sound] then + if not sound_instances[sound] then + sound_instances[sound] = 0 + end + + local source = love.audio.newSource(sounds[sound].data, "static") + + local adjusted_volume = 1/(2^sound_instances[sound]) + source:setVolume((volume or 1) * adjusted_volume * sounds[sound].volume * sfx_volume) + source:setPitch(pitch or 1) + + source:play() + + sound_instances[sound] = sound_instances[sound] + 1 + tick.delay(function() sound_instances[sound] = sound_instances[sound] - 1 end, sounds[sound].data:getDuration()/4) + end +end \ No newline at end of file diff --git a/lib/tick.lua b/lib/tick.lua new file mode 100644 index 0000000..0ae30c4 --- /dev/null +++ b/lib/tick.lua @@ -0,0 +1,166 @@ +-- +-- tick +-- +-- Copyright (c) 2015 rxi +-- +-- This library is free software; you can redistribute it and/or modify it +-- under the terms of the MIT license. See LICENSE for details. +-- + +local tick = { _version = "0.1.1" } +tick.__index = tick + + +local iscallable = function(x) + if type(x) == "function" then return true end + local mt = getmetatable(x) + return mt and mt.__call ~= nil +end + +local noop = function() +end + + +local event = {} +event.__index = event + +function event.new(parent, fn, delay, recur, err) + err = err or 0 + -- Create and return event + return setmetatable({ + parent = parent, + delay = delay, + timer = delay + err, + fn = fn, + recur = recur, + }, event) +end + + +function event:after(fn, delay) + -- Error check + if self.recur then + error("cannot chain a recurring event") + end + -- Chain event + local oldfn = self.fn + local e = event.new(self.parent, fn, delay, false) + self.fn = function() + oldfn() + e.timer = e.timer + self.parent.err + self.parent:add(e) + end + return e +end + + +function event:stop() + tick.remove(self.parent, self) +end + + + +function tick.group() + return setmetatable({ err = 0 }, tick) +end + + +function tick:add(e) + self[e] = true + table.insert(self, e) + return e +end + + +function tick:remove(e) + if type(e) == "number" then + -- Remove and return event + local idx = e + e = self[idx] + self[e] = nil + self[idx] = self[#self] + table.remove(self) + return e + end + self[e] = false + for i, v in ipairs(self) do + if v == e then + return self:remove(i) + end + end +end + + +function tick:update(dt) + for i = #self, 1, -1 do + local e = self[i] + e.timer = e.timer - dt + while e.timer <= 0 do + if e.recur then + e.timer = e.timer + e.delay + else + self:remove(i) + end + self.err = e.timer + e.fn() + if not e.recur then + break + end + end + end + self.err = 0 +end + + +function tick:event(fn, delay, recur) + delay = tonumber(delay) + -- Error check + if not iscallable(fn) then + error("expected `fn` to be callable") + end + if type(delay) ~= "number" then + error("expected `delay` to be a number") + end + if delay < 0 then + error("expected `delay` of zero or greater") + end + -- If, factoring in the timing error, the event should happen *now* the + -- function is immediately called and the error is temporarily carried + -- through. This assures nested events with delays shorter than the update() + -- delta-time do not accumulate error; several nested events with very small + -- delays may end up being called on the same frame. A dummy event is created + -- and returned so :after() still functions correctly. + local d = delay + self.err + if d < 0 then + local err = self.err + self.err = d + fn() + self.err = err + return self:add(event.new(self, noop, delay, recur, self.err)) + end + -- Create, add and return a normal event + return self:add(event.new(self, fn, delay, recur, self.err)) +end + + +function tick:delay(fn, delay) + return self:event(fn, delay, false) +end + + +function tick:recur(fn, delay) + return self:event(fn, delay, true) +end + + +local group = tick.group() + +local bound = { + update = function(...) return tick.update(group, ...) end, + delay = function(...) return tick.delay (group, ...) end, + recur = function(...) return tick.recur (group, ...) end, + remove = function(...) return tick.remove(group, ...) end, +} +setmetatable(bound, tick) + +return bound \ No newline at end of file diff --git a/main.lua b/main.lua index e93e414..a4262a6 100644 --- a/main.lua +++ b/main.lua @@ -3,9 +3,11 @@ require 'util' constr = require 'constructors' +require 'lib.audio' assets = require 'lib.assets' ease = require 'lib.ease' bench = require 'lib.benchmark' +tick = require 'lib.tick' sprites = {} sound_path = {} @@ -17,6 +19,9 @@ debug = false food = {} feesh = {} +foodtier = 1 +foodcount = 1 + footerbuttons = { { cost = 100, @@ -24,27 +29,40 @@ footerbuttons = { openanim = 1, open = true, func = function() + playSound('splash', 0.7, 0.8) table.insert(feesh, constr.fish(math.random(), 0.3)) end }, { cost = 200, sprite = 'food', - tier = 1, + tier = foodtier, openanim = 1, open = true, - func = function() - --table.insert(feesh, constr.fish(math.random(), 0.3)) + func = function(self) + self.openanim = 0 + foodtier = foodtier + 1 + if foodtier >= 3 then + self.open = false + else + self.tier = foodtier + end end }, { cost = 300, sprite = 'foodcount', - tier = 3, + tier = foodcount, openanim = 1, open = true, - func = function() - --table.insert(feesh, constr.fish(math.random(), 0.3)) + func = function(self) + self.openanim = 0 + foodcount = foodcount + 1 + if foodcount >= 9 then + self.open = false + else + self.tier = foodcount + end end } } @@ -103,8 +121,15 @@ local unfocusinterval = 5 function love.update(dt) frame = frame + 1 bench.update() + tick.update(dt) bench.startBenchmark('update') + bench.startBenchmark('update_buttons') + for _,btn in ipairs(footerbuttons) do + btn.openanim = btn.openanim + dt * 6 + end + bench.stopBenchmark('update_buttons') + bench.startBenchmark('update_food') for i,f in ipairs(food) do f.y = f.y + dt * f.speed @@ -240,16 +265,21 @@ function love.update(dt) local dist = math.abs(n.render.x - f.x) + math.abs(n.render.y - f.y) if dist < FOOD_HITBOX then + playSound('slurp') table.remove(food, n.shortestfood) - n.eattimer = FISH_FOOD_COOLDOWN + local cooldowns = {FISH_FOOD_1_COOLDOWN, FISH_FOOD_2_COOLDOWN, FISH_FOOD_3_COOLDOWN} + + n.eattimer = cooldowns[f.type] n.render.eattimer = 0 n.shortestfood = -1 - if n.lifetime > FISH_AGE_MEDIUM then + if n.lifetime > FISH_AGE_MEDIUM and n.size == 0 then n.size = 1 + playSound('grow') end - if n.lifetime > FISH_AGE_BIG then + if n.lifetime > FISH_AGE_BIG and n.size == 1 then n.size = 2 + playSound('grow') end end end @@ -293,7 +323,7 @@ function love.update(dt) n.render.turn = n.render.turn + dt * math.sign(n.render.x - n.render.prevx) * 2 n.render.turn = clamp(n.render.turn, 0, 1) if n.render.turn == 0 or n.render.turn == 1 then - n.render.swim = (n.render.swim + dt * math.abs(n.render.xspeed) * 300) % 1 + n.render.swim = (n.render.swim + dt * (math.abs(n.render.xspeed) * 250 + 0.5)) % 1 else n.render.swim = 0 end @@ -311,6 +341,9 @@ function love.update(dt) n.render.hungry = clamp(n.render.hungry + dt * m * 3, 0, 1) bench.stopBenchmark('update_fish_render') + if n.eattimer <= FISH_FOOD_DEAD and not n.dead then + playSound('die') + end if n.eattimer <= FISH_FOOD_DEAD then n.dead = true @@ -504,7 +537,7 @@ function love.draw() bench.startBenchmark('render_food') for _,f in ipairs(food) do - local sheet = sheets.food1 + local sheet = sheets['food' .. (f.type)] local x = f.x * sw local y = f.y * sh local frame = math.floor((f.time%1) * #sheet.quads) + 1 @@ -539,50 +572,52 @@ function love.draw() love.graphics.draw(sprites['footer/buttonbg'], x * size, y * size, 0, size, size) end - if btn and btn.open then - -- sprite inside - if btn.sprite == 'guppy' then - local sheet = fishsprite('medium', false, 'swim') - local frame = math.floor((love.timer.getTime() * 2) % 1 * #sheet.quads) + 1 - local scale = (sprites['footer/buttonbg']:getWidth() / sheet.width) * 0.9 - local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 - love.graphics.draw(sheet.spriteSheet, sheet.quads[frame], x * size + offset, y * size + offset*0.75, 0, size * scale, size * scale, sheet.width/2, sheet.width/2) - elseif btn.sprite == 'food' then - local sheets = {sheets.food2, sheets.food3} - local sheet = sheets[btn.tier] + if btn then + if btn.open then + -- sprite inside + if btn.sprite == 'guppy' then + local sheet = fishsprite('medium', false, 'swim') + local frame = math.floor((love.timer.getTime() * 2) % 1 * #sheet.quads) + 1 + local scale = (sprites['footer/buttonbg']:getWidth() / sheet.width) * 0.9 + local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 + love.graphics.draw(sheet.spriteSheet, sheet.quads[frame], x * size + offset, y * size + offset*0.75, 0, size * scale, size * scale, sheet.width/2, sheet.width/2) + elseif btn.sprite == 'food' then + local sheets = {sheets.food2, sheets.food3} + local sheet = sheets[btn.tier] - local scale = (sprites['footer/buttonbg']:getWidth() / sheet.width) * 0.65 - local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 - love.graphics.draw(sheet.spriteSheet, sheet.quads[1], x * size + offset, y * size + offset*0.75, 0, size * scale, size * scale, sheet.width/2, sheet.width/2) - elseif btn.sprite == 'foodcount' then - love.graphics.setFont(fonts.continuum) - local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 + local scale = (sprites['footer/buttonbg']:getWidth() / sheet.width) * 0.65 + local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 + love.graphics.draw(sheet.spriteSheet, sheet.quads[1], x * size + offset, y * size + offset*0.75, 0, size * scale, size * scale, sheet.width/2, sheet.width/2) + elseif btn.sprite == 'foodcount' then + love.graphics.setFont(fonts.continuum) + local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 - local bordersize = 1 - for _,p in ipairs({{0, 1}, {1, 0}, {1, 1}, {-1, 0}, {0, -1}, {-1, -1}, {1, -1}, {-1, 1}}) do - love.graphics.setColor(0, 0, 0, 0.5) - love.graphics.printf(btn.tier + 1, round(x * size) + p[1] * bordersize, round(y * size + offset*0.75 - fonts.continuum:getHeight()/2) + p[2] * bordersize, round(sprites['footer/buttonbg']:getWidth() * size), 'center') + local bordersize = 1 + for _,p in ipairs({{0, 1}, {1, 0}, {1, 1}, {-1, 0}, {0, -1}, {-1, -1}, {1, -1}, {-1, 1}}) do + love.graphics.setColor(0, 0, 0, 0.5) + love.graphics.printf(btn.tier + 1, round(x * size) + p[1] * bordersize, round(y * size + offset*0.75 - fonts.continuum:getHeight()/2) + p[2] * bordersize, round(sprites['footer/buttonbg']:getWidth() * size), 'center') + end + + love.graphics.setColor(0, 1, 0) + love.graphics.printf(btn.tier + 1, round(x * size), round(y * size + offset*0.75 - fonts.continuum:getHeight()/2), round(sprites['footer/buttonbg']:getWidth() * size), 'center') end + -- price + love.graphics.setFont(fonts.pix) + local font = love.graphics.getFont() love.graphics.setColor(0, 1, 0) - love.graphics.printf(btn.tier + 1, round(x * size), round(y * size + offset*0.75 - fonts.continuum:getHeight()/2), round(sprites['footer/buttonbg']:getWidth() * size), 'center') + love.graphics.printf('$' .. btn.cost, round(x * size), round(y * size + 51 * size - font:getHeight()/2), round(sprites['footer/buttonbg']:getWidth() * size), 'center') + love.graphics.setColor(1, 1, 1) + love.graphics.setFont(fonts.default) + + -- reflection + love.graphics.setBlendMode('add') + love.graphics.draw(sprites['footer/reflection'], x * size, y * size, 0, size, size) + love.graphics.setBlendMode('alpha') end - -- price - love.graphics.setFont(fonts.pix) - local font = love.graphics.getFont() - love.graphics.setColor(0, 1, 0) - love.graphics.printf('$' .. btn.cost, round(x * size), round(y * size + 51 * size - font:getHeight()/2), round(sprites['footer/buttonbg']:getWidth() * size), 'center') - love.graphics.setColor(1, 1, 1) - love.graphics.setFont(fonts.default) - - -- reflection - love.graphics.setBlendMode('add') - love.graphics.draw(sprites['footer/reflection'], x * size, y * size, 0, size, size) - love.graphics.setBlendMode('alpha') - -- open/close anim - if (btn and not btn.openanim == 1) then + if (btn and btn.openanim < 1) then local sheet = sheets.buttonopen local anim = 0 if btn then anim = btn.openanim end @@ -606,12 +641,11 @@ function love.draw() end function love.mousepressed(x, y, b) - if b == 2 then - table.insert(food, constr.food(x/love.graphics.getWidth(), y/love.graphics.getHeight(), 1)) + if b == 1 and y > FOOTER_HEIGHT and #food < foodcount then + table.insert(food, constr.food(x/love.graphics.getWidth(), y/love.graphics.getHeight(), foodtier)) + playSound('dropfood') end -end -function love.mousereleased(x, y, b) local footerheight = FOOTER_HEIGHT * love.graphics.getWidth()/640 local size = footerheight / FOOTER_HEIGHT @@ -622,7 +656,8 @@ function love.mousereleased(x, y, b) if hovered then if footerbuttons[i] and footerbuttons[i].open then - footerbuttons[i].func() + footerbuttons[i].func(footerbuttons[i]) + playSound('buttonclick') end end @@ -634,6 +669,10 @@ function love.mousereleased(x, y, b) end end +function love.mousereleased(x, y, b) + +end + function love.keypressed(key) if key == 'f3' then debug = not debug diff --git a/util.lua b/util.lua index 8dc0072..4ce99b4 100644 --- a/util.lua +++ b/util.lua @@ -55,4 +55,12 @@ end function math.sign(a) if a >= 0 then return 1 else return -1 end +end + +function string.starts(str, start) + return str:sub(1, #start) == start +end + +function string.ends(str, ending) + return ending == "" or str:sub(-#ending) == ending end \ No newline at end of file