diff --git a/assets/sprites/bg/1.png b/assets/sprites/bg/1.png new file mode 100644 index 0000000..94c1775 Binary files /dev/null and b/assets/sprites/bg/1.png differ diff --git a/assets/sprites/bg/1.png~ b/assets/sprites/bg/1.png~ new file mode 100644 index 0000000..7f18b63 Binary files /dev/null and b/assets/sprites/bg/1.png~ differ diff --git a/assets/sprites/fish/big_die.png b/assets/sprites/fish/big_die.png new file mode 100644 index 0000000..5d9f51f Binary files /dev/null and b/assets/sprites/fish/big_die.png differ diff --git a/assets/sprites/fish/big_eat.png b/assets/sprites/fish/big_eat.png new file mode 100644 index 0000000..e9d6b65 Binary files /dev/null and b/assets/sprites/fish/big_eat.png differ diff --git a/assets/sprites/fish/big_hungry_eat.png b/assets/sprites/fish/big_hungry_eat.png new file mode 100644 index 0000000..206e0d6 Binary files /dev/null and b/assets/sprites/fish/big_hungry_eat.png differ diff --git a/assets/sprites/fish/big_hungry_swim.png b/assets/sprites/fish/big_hungry_swim.png new file mode 100644 index 0000000..e445ee2 Binary files /dev/null and b/assets/sprites/fish/big_hungry_swim.png differ diff --git a/assets/sprites/fish/big_hungry_turn.png b/assets/sprites/fish/big_hungry_turn.png new file mode 100644 index 0000000..903102c Binary files /dev/null and b/assets/sprites/fish/big_hungry_turn.png differ diff --git a/assets/sprites/fish/big_swim.png b/assets/sprites/fish/big_swim.png new file mode 100644 index 0000000..4365b17 Binary files /dev/null and b/assets/sprites/fish/big_swim.png differ diff --git a/assets/sprites/fish/big_turn.png b/assets/sprites/fish/big_turn.png new file mode 100644 index 0000000..a7d2c07 Binary files /dev/null and b/assets/sprites/fish/big_turn.png differ diff --git a/assets/sprites/fish/biig_die.png b/assets/sprites/fish/biig_die.png new file mode 100644 index 0000000..a118988 Binary files /dev/null and b/assets/sprites/fish/biig_die.png differ diff --git a/assets/sprites/fish/biig_eat.png b/assets/sprites/fish/biig_eat.png new file mode 100644 index 0000000..351095c Binary files /dev/null and b/assets/sprites/fish/biig_eat.png differ diff --git a/assets/sprites/fish/biig_hungry_eat.png b/assets/sprites/fish/biig_hungry_eat.png new file mode 100644 index 0000000..e1e96d1 Binary files /dev/null and b/assets/sprites/fish/biig_hungry_eat.png differ diff --git a/assets/sprites/fish/biig_hungry_swim.png b/assets/sprites/fish/biig_hungry_swim.png new file mode 100644 index 0000000..fece5fe Binary files /dev/null and b/assets/sprites/fish/biig_hungry_swim.png differ diff --git a/assets/sprites/fish/biig_hungry_turn.png b/assets/sprites/fish/biig_hungry_turn.png new file mode 100644 index 0000000..909aa7b Binary files /dev/null and b/assets/sprites/fish/biig_hungry_turn.png differ diff --git a/assets/sprites/fish/biig_swim.png b/assets/sprites/fish/biig_swim.png new file mode 100644 index 0000000..6e21849 Binary files /dev/null and b/assets/sprites/fish/biig_swim.png differ diff --git a/assets/sprites/fish/biig_turn.png b/assets/sprites/fish/biig_turn.png new file mode 100644 index 0000000..af208b6 Binary files /dev/null and b/assets/sprites/fish/biig_turn.png differ diff --git a/assets/sprites/fish/king_die.png b/assets/sprites/fish/king_die.png new file mode 100644 index 0000000..aa11eaa Binary files /dev/null and b/assets/sprites/fish/king_die.png differ diff --git a/assets/sprites/fish/king_eat.png b/assets/sprites/fish/king_eat.png new file mode 100644 index 0000000..c285b4c Binary files /dev/null and b/assets/sprites/fish/king_eat.png differ diff --git a/assets/sprites/fish/king_hungry_eat.png b/assets/sprites/fish/king_hungry_eat.png new file mode 100644 index 0000000..36b1e73 Binary files /dev/null and b/assets/sprites/fish/king_hungry_eat.png differ diff --git a/assets/sprites/fish/king_hungry_swim.png b/assets/sprites/fish/king_hungry_swim.png new file mode 100644 index 0000000..005b5a4 Binary files /dev/null and b/assets/sprites/fish/king_hungry_swim.png differ diff --git a/assets/sprites/fish/king_hungry_turn.png b/assets/sprites/fish/king_hungry_turn.png new file mode 100644 index 0000000..2a1df8e Binary files /dev/null and b/assets/sprites/fish/king_hungry_turn.png differ diff --git a/assets/sprites/fish/king_swim.png b/assets/sprites/fish/king_swim.png new file mode 100644 index 0000000..6a1c151 Binary files /dev/null and b/assets/sprites/fish/king_swim.png differ diff --git a/assets/sprites/fish/king_turn.png b/assets/sprites/fish/king_turn.png new file mode 100644 index 0000000..db4f62e Binary files /dev/null and b/assets/sprites/fish/king_turn.png differ diff --git a/assets/sprites/fish/medium_die.png b/assets/sprites/fish/medium_die.png new file mode 100644 index 0000000..afa24b8 Binary files /dev/null and b/assets/sprites/fish/medium_die.png differ diff --git a/assets/sprites/fish/medium_eat.png b/assets/sprites/fish/medium_eat.png new file mode 100644 index 0000000..383bb13 Binary files /dev/null and b/assets/sprites/fish/medium_eat.png differ diff --git a/assets/sprites/fish/medium_hungry_eat.png b/assets/sprites/fish/medium_hungry_eat.png new file mode 100644 index 0000000..51ef126 Binary files /dev/null and b/assets/sprites/fish/medium_hungry_eat.png differ diff --git a/assets/sprites/fish/medium_hungry_swim.png b/assets/sprites/fish/medium_hungry_swim.png new file mode 100644 index 0000000..f432f67 Binary files /dev/null and b/assets/sprites/fish/medium_hungry_swim.png differ diff --git a/assets/sprites/fish/medium_hungry_turn.png b/assets/sprites/fish/medium_hungry_turn.png new file mode 100644 index 0000000..7293954 Binary files /dev/null and b/assets/sprites/fish/medium_hungry_turn.png differ diff --git a/assets/sprites/fish/medium_swim.png b/assets/sprites/fish/medium_swim.png new file mode 100644 index 0000000..56dbee9 Binary files /dev/null and b/assets/sprites/fish/medium_swim.png differ diff --git a/assets/sprites/fish/medium_turn.png b/assets/sprites/fish/medium_turn.png new file mode 100644 index 0000000..3562c78 Binary files /dev/null and b/assets/sprites/fish/medium_turn.png differ diff --git a/assets/sprites/fish/sheet.kra b/assets/sprites/fish/sheet.kra new file mode 100644 index 0000000..63c9148 Binary files /dev/null and b/assets/sprites/fish/sheet.kra differ diff --git a/assets/sprites/fish/small_die.png b/assets/sprites/fish/small_die.png new file mode 100644 index 0000000..bff5a83 Binary files /dev/null and b/assets/sprites/fish/small_die.png differ diff --git a/assets/sprites/fish/small_eat.png b/assets/sprites/fish/small_eat.png new file mode 100644 index 0000000..ca2260b Binary files /dev/null and b/assets/sprites/fish/small_eat.png differ diff --git a/assets/sprites/fish/small_hungry_eat.png b/assets/sprites/fish/small_hungry_eat.png new file mode 100644 index 0000000..844ba68 Binary files /dev/null and b/assets/sprites/fish/small_hungry_eat.png differ diff --git a/assets/sprites/fish/small_hungry_swim.png b/assets/sprites/fish/small_hungry_swim.png new file mode 100644 index 0000000..548ca80 Binary files /dev/null and b/assets/sprites/fish/small_hungry_swim.png differ diff --git a/assets/sprites/fish/small_hungry_turn.png b/assets/sprites/fish/small_hungry_turn.png new file mode 100644 index 0000000..618887b Binary files /dev/null and b/assets/sprites/fish/small_hungry_turn.png differ diff --git a/assets/sprites/fish/small_swim.png b/assets/sprites/fish/small_swim.png new file mode 100644 index 0000000..22afa7d Binary files /dev/null and b/assets/sprites/fish/small_swim.png differ diff --git a/assets/sprites/fish/small_turn.png b/assets/sprites/fish/small_turn.png new file mode 100644 index 0000000..e172f2a Binary files /dev/null and b/assets/sprites/fish/small_turn.png differ diff --git a/assets/sprites/food/1.png b/assets/sprites/food/1.png new file mode 100644 index 0000000..9c93bca Binary files /dev/null and b/assets/sprites/food/1.png differ diff --git a/assets/sprites/food/2.png b/assets/sprites/food/2.png new file mode 100644 index 0000000..0fc923c Binary files /dev/null and b/assets/sprites/food/2.png differ diff --git a/assets/sprites/food/3.png b/assets/sprites/food/3.png new file mode 100644 index 0000000..d486855 Binary files /dev/null and b/assets/sprites/food/3.png differ diff --git a/assets/sprites/food/potion.png b/assets/sprites/food/potion.png new file mode 100644 index 0000000..e407c8c Binary files /dev/null and b/assets/sprites/food/potion.png differ diff --git a/assets/sprites/food/what.png b/assets/sprites/food/what.png new file mode 100644 index 0000000..af33766 Binary files /dev/null and b/assets/sprites/food/what.png differ diff --git a/assets/sprites/footer/base.png b/assets/sprites/footer/base.png new file mode 100644 index 0000000..ad463ba Binary files /dev/null and b/assets/sprites/footer/base.png differ diff --git a/assets/sprites/footer/buttonbg.png b/assets/sprites/footer/buttonbg.png new file mode 100644 index 0000000..16b2d74 Binary files /dev/null and b/assets/sprites/footer/buttonbg.png differ diff --git a/assets/sprites/footer/buttonbg_down.png b/assets/sprites/footer/buttonbg_down.png new file mode 100644 index 0000000..824c725 Binary files /dev/null and b/assets/sprites/footer/buttonbg_down.png differ diff --git a/assets/sprites/footer/buttonbg_hover.png b/assets/sprites/footer/buttonbg_hover.png new file mode 100644 index 0000000..3b78691 Binary files /dev/null and b/assets/sprites/footer/buttonbg_hover.png differ diff --git a/assets/sprites/footer/gif/HatchANIMATION.gif b/assets/sprites/footer/gif/HatchANIMATION.gif new file mode 100755 index 0000000..135b671 Binary files /dev/null and b/assets/sprites/footer/gif/HatchANIMATION.gif differ diff --git a/assets/sprites/footer/gif/LazerGunz.gif b/assets/sprites/footer/gif/LazerGunz.gif new file mode 100755 index 0000000..6155c75 Binary files /dev/null and b/assets/sprites/footer/gif/LazerGunz.gif differ diff --git a/assets/sprites/footer/gif/OPTIONSBUTTON.gif b/assets/sprites/footer/gif/OPTIONSBUTTON.gif new file mode 100755 index 0000000..999037e Binary files /dev/null and b/assets/sprites/footer/gif/OPTIONSBUTTON.gif differ diff --git a/assets/sprites/footer/gif/OPTIONSBUTTONd.gif b/assets/sprites/footer/gif/OPTIONSBUTTONd.gif new file mode 100755 index 0000000..bf616eb Binary files /dev/null and b/assets/sprites/footer/gif/OPTIONSBUTTONd.gif differ diff --git a/assets/sprites/footer/gif/_HatchANIMATION.gif b/assets/sprites/footer/gif/_HatchANIMATION.gif new file mode 100755 index 0000000..e6c2c4b Binary files /dev/null and b/assets/sprites/footer/gif/_HatchANIMATION.gif differ diff --git a/assets/sprites/footer/gif/_LazerGunz.gif b/assets/sprites/footer/gif/_LazerGunz.gif new file mode 100755 index 0000000..4a0793c Binary files /dev/null and b/assets/sprites/footer/gif/_LazerGunz.gif differ diff --git a/assets/sprites/footer/gif/_MBREFLECTION.gif b/assets/sprites/footer/gif/_MBREFLECTION.gif new file mode 100755 index 0000000..64bc0b4 Binary files /dev/null and b/assets/sprites/footer/gif/_MBREFLECTION.gif differ diff --git a/assets/sprites/footer/gif/_OPTIONSBUTTON.gif b/assets/sprites/footer/gif/_OPTIONSBUTTON.gif new file mode 100755 index 0000000..84db015 Binary files /dev/null and b/assets/sprites/footer/gif/_OPTIONSBUTTON.gif differ diff --git a/assets/sprites/footer/gif/_OPTIONSBUTTONd.gif b/assets/sprites/footer/gif/_OPTIONSBUTTONd.gif new file mode 100755 index 0000000..84db015 Binary files /dev/null and b/assets/sprites/footer/gif/_OPTIONSBUTTONd.gif differ diff --git a/assets/sprites/footer/gif/_mbuttond.gif b/assets/sprites/footer/gif/_mbuttond.gif new file mode 100755 index 0000000..f3d5a93 Binary files /dev/null and b/assets/sprites/footer/gif/_mbuttond.gif differ diff --git a/assets/sprites/footer/gif/_mbuttono.gif b/assets/sprites/footer/gif/_mbuttono.gif new file mode 100755 index 0000000..1e54d42 Binary files /dev/null and b/assets/sprites/footer/gif/_mbuttono.gif differ diff --git a/assets/sprites/footer/gif/_mbuttonu.gif b/assets/sprites/footer/gif/_mbuttonu.gif new file mode 100755 index 0000000..f20bf15 Binary files /dev/null and b/assets/sprites/footer/gif/_mbuttonu.gif differ diff --git a/assets/sprites/footer/gif/_menubar.gif b/assets/sprites/footer/gif/_menubar.gif new file mode 100755 index 0000000..578c189 Binary files /dev/null and b/assets/sprites/footer/gif/_menubar.gif differ diff --git a/assets/sprites/footer/gif/mbuttond.gif b/assets/sprites/footer/gif/mbuttond.gif new file mode 100755 index 0000000..2aff668 Binary files /dev/null and b/assets/sprites/footer/gif/mbuttond.gif differ diff --git a/assets/sprites/footer/gif/mbuttond.gif-autosave.kra b/assets/sprites/footer/gif/mbuttond.gif-autosave.kra new file mode 100644 index 0000000..ed72a69 Binary files /dev/null and b/assets/sprites/footer/gif/mbuttond.gif-autosave.kra differ diff --git a/assets/sprites/footer/gif/mbuttono.gif b/assets/sprites/footer/gif/mbuttono.gif new file mode 100755 index 0000000..ba85194 Binary files /dev/null and b/assets/sprites/footer/gif/mbuttono.gif differ diff --git a/assets/sprites/footer/gif/mbuttono.gif-autosave.kra b/assets/sprites/footer/gif/mbuttono.gif-autosave.kra new file mode 100644 index 0000000..75fdd5d Binary files /dev/null and b/assets/sprites/footer/gif/mbuttono.gif-autosave.kra differ diff --git a/assets/sprites/footer/gif/mbuttonu.gif b/assets/sprites/footer/gif/mbuttonu.gif new file mode 100755 index 0000000..7fd2693 Binary files /dev/null and b/assets/sprites/footer/gif/mbuttonu.gif differ diff --git a/assets/sprites/footer/gif/mbuttonu.gif-autosave.kra b/assets/sprites/footer/gif/mbuttonu.gif-autosave.kra new file mode 100644 index 0000000..1a633cd Binary files /dev/null and b/assets/sprites/footer/gif/mbuttonu.gif-autosave.kra differ diff --git a/assets/sprites/footer/gif/menubar.gif b/assets/sprites/footer/gif/menubar.gif new file mode 100755 index 0000000..5941eb1 Binary files /dev/null and b/assets/sprites/footer/gif/menubar.gif differ diff --git a/assets/sprites/footer/gif/menubar.gif-autosave.kra b/assets/sprites/footer/gif/menubar.gif-autosave.kra new file mode 100644 index 0000000..644ebec Binary files /dev/null and b/assets/sprites/footer/gif/menubar.gif-autosave.kra differ diff --git a/assets/sprites/footer/gif/moneyflash.gif b/assets/sprites/footer/gif/moneyflash.gif new file mode 100755 index 0000000..e36c80d Binary files /dev/null and b/assets/sprites/footer/gif/moneyflash.gif differ diff --git a/assets/sprites/footer/reflection.png b/assets/sprites/footer/reflection.png new file mode 100644 index 0000000..aaf9d7a Binary files /dev/null and b/assets/sprites/footer/reflection.png differ diff --git a/assets/sprites/shadow.png b/assets/sprites/shadow.png new file mode 100644 index 0000000..2a251fb Binary files /dev/null and b/assets/sprites/shadow.png differ diff --git a/assets/sprites/wave/wavecenter.png b/assets/sprites/wave/wavecenter.png new file mode 100644 index 0000000..5b0de01 Binary files /dev/null and b/assets/sprites/wave/wavecenter.png differ diff --git a/assets/sprites/wave/waveside.png b/assets/sprites/wave/waveside.png new file mode 100644 index 0000000..7b82cb3 Binary files /dev/null and b/assets/sprites/wave/waveside.png differ diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..d63b12e --- /dev/null +++ b/conf.lua @@ -0,0 +1,13 @@ +function love.conf(t) + t.version = "11.1" + t.release = false + t.window.title = 'notsanequarium' + t.window.resizable = true + t.window.vsync = false + t.window.minwidth = 640 + t.window.minheight = 480 + t.window.width = 640 + t.window.height = 480 + + -- t.window.msaa = 2 +end \ No newline at end of file diff --git a/const.lua b/const.lua new file mode 100644 index 0000000..d421890 --- /dev/null +++ b/const.lua @@ -0,0 +1,28 @@ +ease = require 'lib.ease' + +FISH_SPLINE_QUALITY = 5 -- 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 + +FISH_RENDER_FREQ = 4 -- only update the quality renders once every x frames +FISH_COLISSION_CHECK_FREQ = 2 -- how often to update the colission +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_COOLDOWN = 10 +FISH_FOOD_HUNGRY = -5 +FISH_FOOD_DEAD = -15 + +FISH_AGE_MEDIUM = 25 -- the age, in seconds, needed for a guppy to become a medium guppy +FISH_AGE_BIG = 65 -- see above, but for big + +FISH_SIZE = 6 -- how many large guppies can you fit on the screen + +FOOTER_HEIGHT = 68 + +FOOD_HITBOX = 0.05 + +DEBUG_FISH_PATH_SUBDIVISIONS = 50 +DEBUG_FISH_PREDICT_AMOUNT = 0.5 \ No newline at end of file diff --git a/constructors.lua b/constructors.lua new file mode 100644 index 0000000..af8ed5c --- /dev/null +++ b/constructors.lua @@ -0,0 +1,60 @@ +require 'const' + +local self = {} + +function self.fish(x, y) + local fish = { + x = x, + y = y, + size = 0, -- 0 for small, 1 for medium, 2 for big, 3 for king + eattimer = 0 + math.random() * 2, -- starts out hungry, with a 2s delay + + lifetime = 0, + + eases = { + + }, + render = { + x = 0, + y = 0, + prevx = 0, + prevy = 0, + turn = 0, + swim = 0, + angle = 0, + xspeed = 0, + yspeed = 0, + eattimer = 1, + hungry = 0, + } + } + + for i = 1, FISH_SPLINE_QUALITY do + table.insert(fish.eases, { -- we insert a fake ease that ends instantly and just hope the update loop replaces it with a valid, random one + x = x, + y = y, + fromx = x, + fromy = y, + a = 1, + speed = 1 + }) + end + + return fish +end + +function self.food(x, y, type) + local food = { + x = x, + y = y, + speed = 0.2, + time = math.random(), + deathtimer = 0, + type = 1, + goal = 0 -- assigns 0 as the fish so that hopefully the update loop replaces it with a valid, random one + } + + return food +end + +return self \ No newline at end of file diff --git a/lib/assets.lua b/lib/assets.lua new file mode 100644 index 0000000..8591550 --- /dev/null +++ b/lib/assets.lua @@ -0,0 +1,84 @@ +local assets = {} + +function assets.clear() + print("ℹ️ clearing assets") + + sprites = {} + sound_path = {} + music_path = {} +end + +function assets.load(base) + print("ℹ️ loading " .. base) + + assets.addSprites(base) + print("✓ added sprites") + + assets.addAudio(base) + print("✓ added audio") +end + +function assets.addSprites(base, d) + local dir = base.."/sprites" + if d then + dir = dir .. "/" .. d + end + local files = love.filesystem.getDirectoryItems(dir) + for _,file in ipairs(files) do + if string.sub(file, -4) == ".png" then + local spritename = string.sub(file, 1, -5) + local sprite = love.graphics.newImage(dir .. "/" .. file) + if d then + spritename = d .. "/" .. spritename + end + sprites[spritename] = sprite + --print(colr.cyan("ℹ️ added sprite "..spritename)) + elseif love.filesystem.getInfo(dir .. "/" .. file).type == "directory" then + --print(colr.cyan("ℹ️ found sprite dir: " .. file)) + local newdir = file + if d then + newdir = d .. "/" .. newdir + end + assets.addSprites(base, newdir) + end + end +end + +function assets.addAudio(base, d, type) + local dir = base.."/audio" + if d then + dir = dir .. "/" .. d + end + local files = love.filesystem.getDirectoryItems(dir) + for _,file in ipairs(files) do + if love.filesystem.getInfo(dir .. "/" .. file).type == "directory" then + local newdir = file + if d then + newdir = d .. "/" .. newdir + end + assets.addAudio(base, newdir, type or file) + else + local audioname = file + if file:ends(".wav") then audioname = file:sub(1, -5) end + if file:ends(".mp3") then audioname = file:sub(1, -5) end + if file:ends(".ogg") then audioname = file:sub(1, -5) end + if file:ends(".flac") then audioname = file:sub(1, -5) end + if file:ends(".xm") then audioname = file:sub(1, -4) end + --[[if d then + audioname = d .. "/" .. audioname + end]] + if type == "sfx" then + sound_path[audioname] = dir .. "/" .. file + + if sounds and sounds[audioname] then + registerSound(audioname, sounds[audioname].volume) + end + elseif type == "bgm" then + music_path[audioname] = dir .. "/" .. file + end + --print("ℹ️ audio "..audioname.." added") + end + end +end + +return assets \ No newline at end of file diff --git a/lib/benchmark.lua b/lib/benchmark.lua new file mode 100644 index 0000000..ab865b4 --- /dev/null +++ b/lib/benchmark.lua @@ -0,0 +1,88 @@ +local this = {} + +local updateLimit = 50 + +local benchmarkingThings = {} + +local latestBenchmark = {} +local doneBench = {} + +local function shrt(num) + return math.floor(num * 10000) / 10000 +end + +this.update = function() + doneBench = {} +end + +this.startBenchmark = function(name) + latestBenchmark[name] = love.timer.getTime() +end + +this.stopBenchmark = function(name) + if not benchmarkingThings[name] then benchmarkingThings[name] = {} end + + if doneBench[name] then + local tbl = benchmarkingThings[name] + tbl[#tbl] = tbl[#tbl] + love.timer.getTime() - latestBenchmark[name] + else + table.insert(benchmarkingThings[name], love.timer.getTime() - latestBenchmark[name]) + end + + doneBench[name] = true + if #benchmarkingThings[name] > updateLimit then table.remove(benchmarkingThings[name], 1) end +end + +this.getAverage = function(name) + local things + if name then + things = benchmarkingThings[name] + else + things = {} + for key in pairs(this.benchmarks) do + for _,n in ipairs(benchmarkingThings[key]) do + table.insert(things, n) + end + end + end + + local total = 0 + for _,n in ipairs(things) do + total = total + n + end + + return total / #things +end + +this.renderBenchmark = function() + local font = love.graphics.getFont() + local result = '' + local rowNum = 0 + + local averages = {} + local max = 0 + + for n,_ in pairs(this.benchmarks) do + local average = this.getAverage(n) + max = math.max(average, max) + averages[n] = average + end + for n,_ in pairs(this.benchmarks) do + local average = averages[n] + result = result .. '\n' .. shrt(average) .. 'ms' .. ' ' .. n + rowNum = rowNum + 1 + + local yoff = rowNum * font:getHeight() + + love.graphics.setColor(1, 1, 1, 0.7) + + love.graphics.rectangle('fill', 0, yoff, average * 1/max * love.graphics.getWidth(), font:getHeight()) + end + + love.graphics.setColor(0, 0, 0) + love.graphics.print(result) +end + +this.benchmarks = benchmarkingThings + +return this \ No newline at end of file diff --git a/lib/ease.lua b/lib/ease.lua new file mode 100644 index 0000000..a990a71 --- /dev/null +++ b/lib/ease.lua @@ -0,0 +1,140 @@ +local this = {} + +local sqrt = math.sqrt +local sin = math.sin +local cos = math.cos +local pow = math.pow +local exp = math.exp +local pi = math.pi +local abs = math.abs + +function this.linear(t) return t end +function this.inQuad(t) return t * t end +function this.outQuad(t) return -t * (t - 2) end +function this.inOutQuad(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 2 + else + return 1 - 0.5 * (2 - t) ^ 2 + end +end +function this.inCubic(t) return t * t * t end +function this.outCubic(t) return 1 - (1 - t) ^ 3 end +function this.inOutCubic(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 3 + else + return 1 - 0.5 * (2 - t) ^ 3 + end +end +function this.inQuart(t) return t * t * t * t end +function this.outQuart(t) return 1 - (1 - t) ^ 4 end +function this.inOutQuart(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 4 + else + return 1 - 0.5 * (2 - t) ^ 4 + end +end +function this.inQuint(t) return t ^ 5 end +function this.outQuint(t) return 1 - (1 - t) ^ 5 end +function this.inOutQuint(t) + t = t * 2 + if t < 1 then + return 0.5 * t ^ 5 + else + return 1 - 0.5 * (2 - t) ^ 5 + end +end +function this.inExpo(t) return 1000 ^ (t - 1) - 0.001 end +function this.outExpo(t) return 0.999 - 1000 ^ -t end +function this.inOutExpo(t) + t = t * 2 + if t < 1 then + return 0.5 * 1000 ^ (t - 1) - 0.0005 + else + return 0.9995 - 0.5 * 1000 ^ (1 - t) + end +end +function this.inCirc(t) return 1 - sqrt(1 - t * t) end +function this.outCirc(t) return sqrt(-t * t + 2 * t) end +function this.inOutCirc(t) + t = t * 2 + if t < 1 then + return 0.5 - 0.5 * sqrt(1 - t * t) + else + t = t - 2 + return 0.5 + 0.5 * sqrt(1 - t * t) + end +end + +function this.inElastic(t) + t = t - 1 + return -(pow(2, 10 * t) * sin((t - 0.075) * (2 * pi) / 0.3)) +end +function this.outElastic(t) + return pow(2, -10 * t) * sin((t - 0.075) * (2 * pi) / 0.3) + 1 +end +function this.inOutElastic(t) + t = t * 2 - 1 + if t < 0 then + return -0.5 * pow(2, 10 * t) * sin((t - 0.1125) * 2 * pi / 0.45) + else + return pow(2, -10 * t) * sin((t - 0.1125) * 2 * pi / 0.45) * 0.5 + 1 + end +end + +function this.inBack(t) return t * t * (2.70158 * t - 1.70158) end +function this.outBack(t) + t = t - 1 + return (t * t * (2.70158 * t + 1.70158)) + 1 +end +function this.inOutBack(t) + t = t * 2 + if t < 1 then + return 0.5 * (t * t * (3.5864016 * t - 2.5864016)) + else + t = t - 2 + return 0.5 * (t * t * (3.5864016 * t + 2.5864016) + 2) + end +end + +function this.outBounce(t) + if t < 1 / 2.75 then + return 7.5625 * t * t + elseif t < 2 / 2.75 then + t = t - 1.5 / 2.75 + return 7.5625 * t * t + 0.75 + elseif t < 2.5 / 2.75 then + t = t - 2.25 / 2.75 + return 7.5625 * t * t + 0.9375 + else + t = t - 2.625 / 2.75 + return 7.5625 * t * t + 0.984375 + end +end +function this.inBounce(t) return 1 - this.outBounce(1 - t) end +function this.inOutBounce(t) + if t < 0.5 then + return this.inBounce(t * 2) * 0.5 + else + return this.outBounce(t * 2 - 1) * 0.5 + 0.5 + end +end + +function this.inSine(x) + return 1 - cos(x * (pi * 0.5)) +end + +function this.outSine(x) + return sin(x * (pi * 0.5)) +end + +function this.inOutSine(x) + return 0.5 - 0.5 * cos(x * pi) +end + +return this \ No newline at end of file diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..3d8ab7a --- /dev/null +++ b/main.lua @@ -0,0 +1,491 @@ +require 'const' +require 'util' + +constr = require 'constructors' + +assets = require 'lib.assets' +ease = require 'lib.ease' +bench = require 'lib.benchmark' + +sprites = {} +sound_path = {} +music_path = {} + +debug = false + +food = {} +feesh = {} + +local sheets = {} + +local function newAnimation(image, width, height) + local animation = {} + animation.spriteSheet = image; + animation.quads = {}; + animation.width = width + animation.height = height + + for y = 0, image:getHeight() - height, height do + for x = 0, image:getWidth() - width, width do + table.insert(animation.quads, love.graphics.newQuad(x, y, width, height, image:getDimensions())) + end + end + + return animation +end + +local function fishsprite(size, hungry, anim) + -- anim is turn, swim, eat or die + if anim == 'die' then hungry = false end + + local spritename = size .. '_' .. (hungry and 'hungry_' or '') .. anim + local spr = sprites['fish/' .. spritename] + return newAnimation(spr, spr:getWidth()/10, spr:getHeight()) +end + +function love.load() + assets.clear() + assets.load('assets') + + sheets.wavecenter = newAnimation(sprites['wave/wavecenter'], sprites['wave/wavecenter']:getWidth(), sprites['wave/wavecenter']:getHeight()/12) + sheets.waveside = newAnimation(sprites['wave/waveside'], sprites['wave/waveside']:getWidth(), sprites['wave/waveside']:getHeight()/12) + + sheets.food1 = newAnimation(sprites['food/1'], sprites['food/1']:getWidth()/10, sprites['food/1']:getHeight()) + + for i = 1, 10 do + table.insert(feesh, constr.fish(math.random(), math.random())) + end +end + +local frame = 0 +local unfocusinterval = 5 +function love.update(dt) + frame = frame + 1 + bench.update() + + bench.startBenchmark('update') + bench.startBenchmark('update_food') + local fishgoals = {} + for i,f in ipairs(food) do + f.y = f.y + dt * f.speed + f.time = f.time + dt + f.y = clamp(f.y, 0, 0.9) + + if f.y == 0.9 then + f.deathtimer = f.deathtimer + dt + end + + if f.goal == 0 or not f.goal then + for i,n in ipairs(feesh) do + if not fishgoals[i] and n.eattimer <= 0 then + f.goal = i + end + end + end + + if f.deathtimer > 1 then + table.remove(food, i) + else + fishgoals[f.goal] = i + end + end + bench.stopBenchmark('update_food') + + bench.startBenchmark('update_fish') + for fi, n in ipairs(feesh) do + bench.startBenchmark('update_fish_eases') + for _, e in ipairs(n.eases) do + e.a = e.a + dt * e.speed + end + for i, e in ipairs(n.eases) do + if e.a > 1 then + local sumx = 0 + local sumy = 0 + for i2, e2 in ipairs(n.eases) do + if i ~= i2 then + sumx = sumx + mix(e2.fromx, e2.x, FISH_EASE(math.min(e2.a, 1))) + sumy = sumy + mix(e2.fromy, e2.y, FISH_EASE(math.min(e2.a, 1))) + end + end + + sumx = sumx + e.x + sumy = sumy + e.y + + n.x = sumx / #n.eases + n.y = sumy / #n.eases + e.fromx = e.x + e.fromy = e.y + + e.a = e.a - 1 + + local angle = math.random(-FISH_ANGLE, FISH_ANGLE) + local str = math.random(70, 200)/200/4 + if n.eattimer < -15 then + str = str * 1.3 + end + + if --[[love.mouse.isDown(1) or]] fishgoals[fi] then + local mx, my = love.mouse.getPosition() + mx = mx / love.graphics.getWidth() + my = my / love.graphics.getHeight() + + if fishgoals[fi] and food[fishgoals[fi]] then + mx = food[fishgoals[fi]].x + my = food[fishgoals[fi]].y + end + angle = math.deg(math.atan2(my - n.y, mx - n.x)) + math.random(-FISH_FOLLOW_RANDOM, FISH_FOLLOW_RANDOM) + end + + local x = math.cos(math.rad(angle)) * str + local y = math.sin(math.rad(angle)) * str + + if not (--[[love.mouse.isDown(1) or ]]fishgoals[fi]) then + x = x * math.sign(n.render.x - n.render.prevx) + end + + e.x = n.x + x + e.y = n.y + y + + e.x = 1 - math.abs(e.x%2-1) + e.y = 1 - math.abs(e.y%2-1) + + local fheight = (FOOTER_HEIGHT * love.graphics.getWidth()/640)/love.graphics.getHeight() + if e.y < fheight then + e.y = e.y + (fheight - e.y) * 2 + end + + e.speed = 1 / (math.sqrt(math.pow(math.abs(e.x - e.fromx), 2) + math.pow(math.abs(e.y - e.fromy), 2))/2) / 15 + end + end + bench.stopBenchmark('update_fish_eases') + + bench.startBenchmark('update_fish_position') + n.x = clamp(n.x, 0, 1) + n.y = clamp(n.y, 0, 0.5) + + n.lifetime = n.lifetime + dt + n.eattimer = n.eattimer - dt + + local sumx = 0 + local sumy = 0 + for _, e2 in ipairs(n.eases) do + sumx = sumx + mix(e2.fromx, e2.x, FISH_EASE(e2.a)) + sumy = sumy + mix(e2.fromy, e2.y, FISH_EASE(e2.a)) + end + + n.render.prevx = n.render.x + n.render.prevy = n.render.y + n.render.x = sumx / #n.eases + n.render.y = sumy / #n.eases + + n.render.x = clamp(n.render.x, 0.05, 0.95) + n.render.y = clamp(n.render.y, 0.1, 0.85) + + if fishgoals[fi] and frame % FISH_COLISSION_CHECK_FREQ == 0 then + local f = food[fishgoals[fi]] + if f then + local dist = math.abs(n.render.x - f.x) + math.abs(n.render.y - f.y) + + if dist < FOOD_HITBOX then + table.remove(food, fishgoals[fi]) + n.eattimer = FISH_FOOD_COOLDOWN + n.render.eattimer = 0 + + if n.lifetime > FISH_AGE_MEDIUM then + n.size = 1 + end + if n.lifetime > FISH_AGE_BIG then + n.size = 2 + end + end + end + end + bench.stopBenchmark('update_fish_position') + + bench.startBenchmark('update_fish_render') + if frame % FISH_RENDER_FREQ == 0 then + local dt = dt * FISH_RENDER_FREQ + + local iter = FISH_RENDER_ITERS + local iteroff = FISH_RENDER_ITEROFF + local xspeed = {} + local yspeed = {} + local angle = {} + + local sumxiter = {} + local sumyiter = {} + for i = 1, iter do + local off = i * iteroff + + local sumx2 = 0 + local sumy2 = 0 + for _, e2 in ipairs(n.eases) do + sumx2 = sumx2 + mix(e2.fromx, e2.x, FISH_EASE(e2.a + off)) + sumy2 = sumy2 + mix(e2.fromy, e2.y, FISH_EASE(e2.a + off)) + end + table.insert(xspeed, (sumx2 - (sumxiter[i - 1] or sumx)) / #n.eases) + table.insert(yspeed, (sumy2 - (sumyiter[i - 1] or sumy)) / #n.eases) + table.insert(angle, math.atan2(sumy2 - (sumyiter[i - 1] or sumy), sumx2 - (sumxiter[i - 1] or sumx))) + + table.insert(sumxiter, sumx2) + table.insert(sumyiter, sumy2) + end + + n.render.xspeed = sum(xspeed) + n.render.yspeed = sum(yspeed) + n.render.angle = sum(angle) + end + + 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) * 100) % 1 + else + n.render.swim = 0 + end + + n.render.eattimer = n.render.eattimer + dt * 3 + if n.render.eattimer < 1 then + n.render.swim = 0 + end + + n.render.turndir = math.sign(n.render.x - n.render.prevx) + + local m = n.eattimer < FISH_FOOD_HUNGRY and 1 or -1 + n.render.hungry = clamp(n.render.hungry + dt * m * 3, 0, 1) + + bench.stopBenchmark('update_fish_render') + end + bench.stopBenchmark('update_fish') + bench.stopBenchmark('update') +end + +function love.draw() + bench.startBenchmark('render') + + bench.startBenchmark('render_tank') + love.graphics.setColor(1, 1, 1) + + local sw, sh = love.graphics.getDimensions() + local footerheight = FOOTER_HEIGHT * sw/640 + local yscale = (sh-footerheight)/sh + + local sample = fishsprite('medium', false, 'swim') + local spritescale = (math.min(sw, sh)/FISH_SIZE) / math.min(sample.width, sample.height) + + stretchto(sprites['bg/1'], 0, footerheight - FOOTER_HEIGHT, 0, sw, sh - (footerheight - FOOTER_HEIGHT)) + + -- waves + bench.startBenchmark('render_wave') + local wavecount = round(sw / sprites['wave/wavecenter']:getWidth()) + local wavescale = sw / (wavecount * sprites['wave/wavecenter']:getWidth()) + for i = 1, wavecount do + local a = (i - 1) / wavecount + local x = a * sw + local frame = round((1 - math.abs(love.timer.getTime()%2-1)) * #sheets.wavecenter.quads) + love.graphics.setBlendMode('add') + + local sheet = sheets.wavecenter + local sizex = 1 + if i == 1 or i == wavecount then + sheet = sheets.waveside + end + if i == wavecount then + sizex = -1 + end + love.graphics.draw(sheet.spriteSheet, sheet.quads[math.max(frame, 1)], x + (sprites['wave/wavecenter']:getWidth() * wavescale)/2, footerheight + 20, 0, wavescale * sizex, wavescale, sprites['wave/wavecenter']:getWidth()/2) + end + love.graphics.setBlendMode('alpha') + bench.stopBenchmark('render_wave') + + -- shadow + bench.startBenchmark('render_shadow') + for i, n in ipairs(feesh) do + love.graphics.setColor(1, 1, 1, n.render.y + 0.2) + love.graphics.draw(sprites['shadow'], n.render.x * sw - (sprites['shadow']:getWidth() * spritescale)/2, sh - sh * 0.18 - (sprites['shadow']:getHeight() * spritescale)/2 + n.render.y * sh * 0.08, 0, spritescale, spritescale) + end + bench.stopBenchmark('render_shadow') + -- all the fish + bench.startBenchmark('render_fish') + for i, n in ipairs(feesh) do + local x = n.render.x * sw + local y = n.render.y * sh + + -- rest of feesh + local size = 'small' + local anim = 'swim' + + local sample = fishsprite('medium', false, 'swim') + + local sizex = 1 + local turn = n.render.turn + if n.render.turndir == -1 then turn = 1 - turn; sizex = -1 end + + local turnframe = math.floor(turn * (#sample.quads - 1)) + 1 + if #sample.quads == 10 then + sizex = -1 * sizex + turnframe = 1 + end + + local frame = math.floor(n.render.swim * (#sample.quads - 1)) + 1 + + if turnframe ~= 1 and turnframe ~= 10 then + anim = 'turn' + frame = turnframe + end + + if n.render.eattimer <= 1 then + anim = 'eat' + frame = math.floor(n.render.eattimer * (#sample.quads - 1)) + 1 + end + + local angle = n.render.angle + if angle > math.pi/2 then + angle = angle - math.pi + end + if angle < -math.pi/2 then + angle = angle + math.pi + end + + angle = angle * math.max(math.min((-math.abs(angle) + math.pi * 0.5) / (math.pi * 0.5) * 2, 1), 0) + angle = angle * 0.5 + + if n.size == 0 then + size = 'small' + elseif n.size == 1 then + size = 'medium' + elseif n.size == 2 then + size = 'big' + elseif n.size == 3 then + size = 'king' + end + + local sheet = fishsprite(size, false, anim) + local sadsheet = fishsprite(size, true, anim) + + local alpha = n.render.hungry == 1 and 0 or 1 + love.graphics.setColor(1, 1, 1, alpha) + love.graphics.draw(sheet.spriteSheet, sheet.quads[math.max(math.min(frame, #sample.quads), 1)], x, y, angle, sizex * spritescale, spritescale, sample.width/2, sample.height/2) + love.graphics.setColor(1, 1, 1, n.render.hungry) + love.graphics.draw(sadsheet.spriteSheet, sheet.quads[math.max(math.min(frame, #sample.quads), 1)], x, y, angle, sizex * spritescale, spritescale, sample.width/2, sample.height/2) + + love.graphics.setColor(1, 1, 1) + if debug then love.graphics.print(shrt(n.eattimer), x + 20, y + 20) end + + if debug then + for _,e in ipairs(n.eases) do + love.graphics.setColor(1, 0, 0, 0.75) + love.graphics.line(e.fromx * sw, e.fromy * sh, e.x * sw, e.y * sh) + + love.graphics.setColor(0, 0, 1, 0.75) + love.graphics.line(mix(e.fromx, e.x, FISH_EASE(e.a)) * sw, mix(e.fromy, e.y, FISH_EASE(e.a)) * sh, n.render.x * sw, n.render.y * sh) + end + + local subdiv = DEBUG_FISH_PATH_SUBDIVISIONS + local adv = DEBUG_FISH_PREDICT_AMOUNT + local pos = {} + local valid = {} + + for i = 1, subdiv do + local a = ((i - 1) / (subdiv - 1)) * (adv * 2) - adv + + local sumx = 0 + local sumy = 0 + local mina = 0 + local maxa = 1 + for _, e in ipairs(n.eases) do + local a = e.a + a + mina = math.min(mina, a) + maxa = math.max(maxa, a) + sumx = sumx + mix(e.fromx, e.x, FISH_EASE(a)) + sumy = sumy + mix(e.fromy, e.y, FISH_EASE(a)) + end + + table.insert(pos, sumx / #n.eases * sw) + table.insert(pos, sumy / #n.eases * sh) + table.insert(valid, not (maxa > 1 or mina < 0)) + end + + for i = 0, #pos/2 - 1 do + local x1 = pos[i * 2 + 1] + local y1 = pos[i * 2 + 1 + 1] + local x2 = pos[i * 2 + 2 + 1] + local y2 = pos[i * 2 + 3 + 1] + local valid = valid[i + 1] + + if not x2 or not y2 then break end + + love.graphics.setColor(0, 1, 0, 1) + if not valid then love.graphics.setColor(0, 0.5, 1, 0.7) end + + love.graphics.line(x1, y1, x2, y2) + end + end + end + bench.stopBenchmark('render_fish') + + bench.startBenchmark('render_food') + for _,f in ipairs(food) do + local sheet = sheets.food1 + local x = f.x * sw + local y = f.y * sh + local frame = math.floor((f.time%1) * #sheet.quads) + 1 + + love.graphics.setColor(1, 1, 1, 1 - f.deathtimer) + + love.graphics.draw(sheet.spriteSheet, sheet.quads[math.max(math.min(frame, #sheet.quads), 1)], x, y, 0, spritescale, spritescale, sheet.width/2, sheet.height/2) + end + bench.stopBenchmark('render_food') + bench.stopBenchmark('render_tank') + + bench.startBenchmark('render_footer') + local base = sprites['footer/base'] + local size = footerheight / FOOTER_HEIGHT + love.graphics.setColor(1, 1, 1, 1) + love.graphics.draw(base, 0, 0, 0, size, size) + + -- the game is making me do this. im sorry + local x = 19 + for b = 1, 7 do + local hovered = mouseOverBox(x, 3, sprites['footer/buttonbg']:getWidth(), sprites['footer/buttonbg']:getHeight()) + + if hovered and love.mouse.isDown(1) then + love.graphics.draw(sprites['footer/buttonbg_down'], x, 3) + elseif hovered then + love.graphics.draw(sprites['footer/buttonbg_hover'], x, 3) + else + love.graphics.draw(sprites['footer/buttonbg'], x, 3) + end + + -- insert sprite of item here + -- insert price of item here + love.graphics.setBlendMode('add') + love.graphics.draw(sprites['footer/reflection'], x, 3) + love.graphics.setBlendMode('alpha') + -- insert closing/opening animation here + + local incr = 69 -- its like button positions but forcefully shoved into a recursive function :D + if b == 2 then incr = 57 end + if b >= 3 then incr = 73 end + x = x + incr + end + bench.stopBenchmark('render_footer') + + love.graphics.setColor(1, 1, 1, 1) + love.graphics.print('FPS: ' .. 1 / love.timer.getDelta(), 0, sh - 16) + + if debug then bench.renderBenchmark() end + bench.stopBenchmark('render') +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)) + end +end + +function love.keypressed(key) + if key == 'f3' then + debug = not debug + end +end \ No newline at end of file diff --git a/util.lua b/util.lua new file mode 100644 index 0000000..8dc0072 --- /dev/null +++ b/util.lua @@ -0,0 +1,58 @@ +function mix(x, y, a) + return x * (1 - a) + y * a +end +function clamp(a, x, y) + return math.min(math.max(a, x), y) +end +function round(x) + if x%1 >= 0.5 then return math.ceil(x) end + return math.floor(x) +end +function sum(tbl) + local sum = 0 + for _,v in ipairs(tbl) do + sum = sum + v + end + return sum/#tbl +end +function shrt(num) + return math.floor(num * 10000) / 10000 +end + +function pointInside(px,py,x,y,w,h) + return px > x and px < x+w and py > y and py < y+h +end + +function mouseOverBox(x,y,w,h) + return pointInside(love.mouse.getX(), love.mouse.getY(), x, y, w, h) +end + +function stretchto(sprite, x, y, r, sx, sy, ox, oy) + love.graphics.draw(sprite, x, y, r, sx/sprite:getWidth(), sy/sprite:getHeight(), ox, oy) +end +function drawcenteredquad(sprite, quad, x, y, r, sx, sy, ox, oy) + local sw, sh = quad:getTextureDimensions() + love.graphics.draw(sprite, quad, x - (sw * (sx or 1))/2, y - (sh * (sy or 1))/2, r, sx, sy, (ox or 0) + sw/2, (oy or 0) + sh/2) +end +function drawcentered(sprite, x, y, r, sx, sy, ox, oy) + love.graphics.draw(sprite, x - (sprite:getWidth() * (sx or 1))/2, y - (sprite:getHeight() * (sy or 1))/2, r, sx, sy, (ox or 0) + sprite:getWidth()/2, (oy or 0) + sprite:getHeight()/2) +end + +function table.deepcopy(orig) + local orig_type = type(orig) + local copy + if orig_type == 'table' then + copy = {} + for orig_key, orig_value in next, orig, nil do + copy[table.deepcopy(orig_key)] = table.deepcopy(orig_value) + end + setmetatable(copy, table.deepcopy(getmetatable(orig))) + else -- number, string, boolean, etc + copy = orig + end + return copy +end + +function math.sign(a) + if a >= 0 then return 1 else return -1 end +end \ No newline at end of file