3am refactoring lets go

This commit is contained in:
jill 2021-01-24 02:30:01 +03:00
parent e2703105dd
commit 5fbf569c65
Signed by: oat
GPG key ID: DD83A9617A252385
11 changed files with 769 additions and 708 deletions

725
main.lua
View file

@ -9,6 +9,13 @@ ease = require 'lib.ease'
bench = require 'lib.benchmark'
tick = require 'lib.tick'
scenes = {
gameplay = require('scenes/gameplay/main')
}
local defaultscene = scenes.gameplay
scene = defaultscene
sprites = {}
sound_path = {}
music_path = {}
@ -16,66 +23,7 @@ fonts = {}
debug = false
food = {}
feesh = {}
money = {}
local balance = 100
foodtier = 1
foodcount = 1
headerbuttons = {
{
cost = 100,
sprite = 'guppy',
openanim = 0,
open = false,
closed = false,
func = function()
playSound('splash', 0.7, 0.8)
table.insert(feesh, constr.fish(math.random(), 0.3))
end
},
{
cost = 200,
sprite = 'food',
tier = foodtier,
openanim = 0,
open = false,
closed = false,
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 = foodcount,
openanim = 0,
open = false,
closed = false,
func = function(self)
self.openanim = 0
foodcount = foodcount + 1
if foodcount >= 9 then
self.open = false
else
self.tier = foodcount
end
end
}
}
local sheets = {}
local function newAnimation(image, width, height)
function newAnimation(image, width, height)
local animation = {}
animation.spriteSheet = image;
animation.quads = {};
@ -91,623 +39,35 @@ local function newAnimation(image, width, height)
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())
sheets.food2 = newAnimation(sprites['food/2'], sprites['food/2']:getWidth()/10, sprites['food/2']:getHeight())
sheets.food3 = newAnimation(sprites['food/3'], sprites['food/3']:getWidth()/10, sprites['food/3']:getHeight())
sheets.buttonopen = newAnimation(sprites['header/button_open'], sprites['header/button_open']:getWidth()/3, sprites['header/button_open']:getHeight())
sheets.money1 = newAnimation(sprites['money/coin1'], sprites['money/coin1']:getWidth()/10, sprites['money/coin1']:getHeight())
sheets.money2 = newAnimation(sprites['money/coin2'], sprites['money/coin2']:getWidth()/10, sprites['money/coin2']:getHeight())
for i = 1, 2 do
table.insert(feesh, constr.fish(math.random(), math.random()))
end
fonts.pix = love.graphics.newFont('assets/fonts/pix.ttf', 6)
fonts.continuum = love.graphics.newFont('assets/fonts/cont.ttf', 14)
fonts.default = love.graphics.newFont(12)
if scene.load then scene.load() end
end
local frame = 0
local unfocusinterval = 5
frame = 0
function love.update(dt)
frame = frame + 1
bench.update()
tick.update(dt)
bench.startBenchmark('update')
bench.startBenchmark('update_buttons')
for _,btn in ipairs(headerbuttons) 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
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.deathtimer > 1 then
table.remove(food, i)
end
end
bench.stopBenchmark('update_food')
bench.startBenchmark('update_money')
for i,f in ipairs(money) do
if not f.collected then
f.y = f.y + dt * f.speed
f.y = clamp(f.y, 0, 0.9)
end
f.time = f.time + dt
if f.y == 0.9 and not f.collected then
f.deathtimer = f.deathtimer + dt
end
if f.collected then
f.collecttimer = f.collecttimer + dt
end
if f.deathtimer > 1 or f.collecttimer > 1 then
table.remove(money, i)
end
end
bench.stopBenchmark('update_money')
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
angle = mix(angle, math.deg(math.atan2((0.5 + math.sin(love.timer.getTime()/10 + fi) * 0.2) - n.y, 0)), 0.1) -- slightly head towards the middle, to prevent getting stuck at the bottom or top
if n.eattimer <= 0 and not n.dead then -- needs to follow something
local mx, my
if n.eattimer <= 0 then
if n.shortestfood and food[n.shortestfood] then
local f = food[n.shortestfood]
mx, my = f.x, f.y
elseif frame % FISH_FOOD_CHECK_FREQ == 0 then
local minfood = 0
local mindist = 9e9
for i,f in ipairs(food) do
local dist = math.sqrt(math.pow(math.abs(f.x - n.render.x), 2) + math.pow(math.abs(f.y - n.render.y), 2))
if dist < mindist then
mindist = dist
minfood = i
end
end
if minfood ~= 0 then
n.shortestfood = minfood
end
end
end
if mx and my then
angle = math.deg(math.atan2(my - n.y, mx - n.x)) + math.random(-FISH_FOLLOW_RANDOM, FISH_FOLLOW_RANDOM)
str = math.random(70, 200)/200/8
end
end
local x = math.cos(math.rad(angle)) * str
local y = math.sin(math.rad(angle)) * str
if not ((n.shortestfood and food[n.shortestfood]) or n.dead) 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 = (HEADER_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
if n.eattimer < FISH_FOOD_HUNGRY or (n.shortestfood and food[n.shortestfood]) then
e.speed = e.speed * 1.3
end
if n.dead then
e.speed = e.speed * 0.2
end
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
n.moneytimer = n.moneytimer - dt
if n.moneytimer < 0 and not n.dead then
n.moneytimer = n.moneytimer + math.random() * 5 + 5
if n.size > 0 then
local type = 2
if n.size == 1 then type = 1 end
table.insert(money, constr.money(n.render.x, n.render.y, type))
end
end
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)
bench.stopBenchmark('update_fish_position')
bench.startBenchmark('update_fish_colission')
if n.shortestfood and food[n.shortestfood] and frame % FISH_COLISSION_CHECK_FREQ == 0 then
local f = food[n.shortestfood]
if f then
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)
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 and n.size == 0 then
n.size = 1
playSound('grow')
if not headerbuttons[1].open and not headerbuttons[1].closed then
headerbuttons[1].open = true
headerbuttons[1].openanim = 0
end
end
if n.lifetime > FISH_AGE_BIG and n.size == 1 then
n.size = 2
playSound('grow')
if not headerbuttons[2].open and not headerbuttons[1].closed then
headerbuttons[2].open = true
headerbuttons[2].openanim = 0
end
if not headerbuttons[3].open and not headerbuttons[1].closed then
headerbuttons[3].open = true
headerbuttons[3].openanim = 0
end
end
end
end
end
bench.stopBenchmark('update_fish_colission')
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) * 250 + 0.5)) % 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
if not n.dead then
n.render.turndir = math.sign(n.render.x - n.render.prevx)
end
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')
if n.eattimer <= FISH_FOOD_DEAD and not n.dead then
playSound('die')
end
if n.eattimer <= FISH_FOOD_DEAD then
n.dead = true
local timeSinceDead = math.abs(n.eattimer - FISH_FOOD_DEAD)
n.render.y = n.render.y + timeSinceDead/5 * math.min(timeSinceDead, 1)
n.render.y = clamp(n.render.y, 0, 0.85)
if n.render.y == 0.85 then
n.render.deathanim = n.render.deathanim + dt
if n.render.deathanim > 1 then
table.remove(feesh, fi)
end
end
end
end
bench.stopBenchmark('update_fish')
if scene.update then scene.update(dt) end
bench.stopBenchmark('update')
end
function love.draw()
love.graphics.setFont(fonts.default)
love.graphics.setColor(1, 1, 1)
local sw, sh = love.graphics.getDimensions()
bench.startBenchmark('render')
bench.startBenchmark('render_tank')
love.graphics.setColor(1, 1, 1)
local sw, sh = love.graphics.getDimensions()
local headerheight = HEADER_HEIGHT * sw/640
local yscale = (sh-headerheight)/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, headerheight - HEADER_HEIGHT, 0, sw, sh - (headerheight - HEADER_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, headerheight + 20, 0, wavescale * sizex, wavescale, sprites['wave/wavecenter']:getWidth()/2)
end
love.graphics.setBlendMode('alpha')
bench.stopBenchmark('render_wave')
bench.startBenchmark('render_food')
for _,f in ipairs(food) do
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
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')
-- shadow
bench.startBenchmark('render_shadow')
for i, n in ipairs(feesh) do
love.graphics.setColor(1, 1, 1, n.render.y + 0.2 - n.render.deathanim)
local sizes = {0.55, 0.7, 1}
local size = sizes[n.size + 1] or 1
love.graphics.draw(sprites['shadow'], n.render.x * sw - (sprites['shadow']:getWidth() * spritescale * size)/2, sh - sh * 0.18 - (sprites['shadow']:getHeight() * spritescale * size)/2 + n.render.y * sh * 0.08, 0, spritescale * size, spritescale * size)
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 == turnframe then
sizex = -1 * sizex
turnframe = 1
end
local frame = math.floor(n.render.swim * (#sample.quads - 1)) + 1
if turnframe ~= 1 and turnframe ~= #sample.quads 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
if n.dead then
anim = 'die'
local a = math.min(math.abs(n.eattimer - FISH_FOOD_DEAD) * 1.4, 1) - n.render.deathanim * 0.4
frame = math.floor(a * (#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 - n.render.deathanim)
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 - n.render.deathanim)
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.stopBenchmark('render_tank')
bench.startBenchmark('render_header')
local base = sprites['header/base']
local size = headerheight / HEADER_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
local y = 3
for b = 1, 7 do
local hovered = mouseOverBox(x * size, y * size, sprites['header/buttonbg']:getWidth() * size, sprites['header/buttonbg']:getHeight() * size)
local btn = headerbuttons[b]
if (btn and not btn.open) or not btn then
-- draw nothing
elseif hovered and love.mouse.isDown(1) then
love.graphics.draw(sprites['header/buttonbg_down'], x * size, y * size, 0, size, size)
elseif hovered then
love.graphics.draw(sprites['header/buttonbg_hover'], x * size, y * size, 0, size, size)
else
love.graphics.draw(sprites['header/buttonbg'], x * size, y * size, 0, size, size)
end
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['header/buttonbg']:getWidth() / sheet.width) * 0.9
local offset = (sprites['header/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['header/buttonbg']:getWidth() / sheet.width) * 0.65
local offset = (sprites['header/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['header/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['header/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['header/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.cost, round(x * size), round(y * size + 51 * size - font:getHeight()/2), round(sprites['header/buttonbg']:getWidth() * size), 'center')
love.graphics.setColor(1, 1, 1)
love.graphics.setFont(fonts.default)
-- reflection
love.graphics.setBlendMode('add')
love.graphics.draw(sprites['header/reflection'], x * size, y * size, 0, size, size)
love.graphics.setBlendMode('alpha')
end
-- open/close anim
if (btn and btn.openanim < 1) then
local sheet = sheets.buttonopen
local anim = 0
if btn then anim = btn.openanim end
local frame = math.floor(anim % 1 * #sheet.quads) + 1
love.graphics.draw(sheet.spriteSheet, sheet.quads[frame], x * size, y * size, 0, size, size)
end
end
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
-- money count
love.graphics.setFont(fonts.continuum)
love.graphics.setColor(179/255, 254/255, 89/255)
local leftpad = 100
love.graphics.printf(balance, round(sw * 0.965 - leftpad), round(HEADER_HEIGHT - 25), leftpad, 'right')
love.graphics.setFont(fonts.default)
bench.stopBenchmark('render_header')
bench.startBenchmark('render_money')
for _,f in ipairs(money) do
local sheet = sheets['money' .. (f.type)]
local x = mix(f.x * sw, sw / 9 * 8, ease.outCubic(f.collecttimer))
local y = mix(f.y * sh, HEADER_HEIGHT - 20, ease.outCubic(f.collecttimer))
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_money')
if scene.draw then scene.draw() end
love.graphics.setColor(1, 1, 1, 1)
love.graphics.print('FPS: ' .. 1 / love.timer.getDelta(), 0, sh - 16)
@ -717,62 +77,11 @@ function love.draw()
end
function love.mousepressed(x, y, b)
if b == 1 then
for _,m in ipairs(money) do
local dist = math.abs(x/love.graphics.getWidth() - m.x) + math.abs(y/love.graphics.getHeight() - m.y)
if dist < 0.1 and not m.collected then
m.collected = true
m.deathtimer = 0
playSound('collect', 1, 1 + math.random() * 0.2 - 0.1)
if m.type == 1 then balance = balance + 15 end
if m.type == 2 then balance = balance + 35 end
return
end
end
end
if b == 1 and y > HEADER_HEIGHT and #food < foodcount then
if balance >= 5 then
table.insert(food, constr.food(x/love.graphics.getWidth(), y/love.graphics.getHeight(), foodtier))
playSound('dropfood')
balance = balance - 5
else
playSound('buzzer')
end
end
local headerheight = HEADER_HEIGHT * love.graphics.getWidth()/640
local size = headerheight / HEADER_HEIGHT
if b == 1 then
local x = 19
for i = 1, 7 do
local hovered = mouseOverBox(x * size, 3 * size, sprites['header/buttonbg']:getWidth() * size, sprites['header/buttonbg']:getHeight() * size)
if hovered then
if headerbuttons[i] and headerbuttons[i].open then
if balance >= headerbuttons[i].cost then
headerbuttons[i].func(headerbuttons[i])
playSound('buttonclick')
balance = balance - headerbuttons[i].cost
else
playSound('buzzer')
end
end
end
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
end
if scene.mousepressed then scene.mousepressed(x, y, b) end
end
function love.mousereleased(x, y, b)
if scene.mousereleased then scene.mousereleased(x, y, b) end
end
function love.keypressed(key)

View file

@ -0,0 +1,124 @@
return function(feesh, spritescale, fishsprite)
local sw, sh = love.graphics.getDimensions()
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 == turnframe then
sizex = -1 * sizex
turnframe = 1
end
local frame = math.floor(n.render.swim * (#sample.quads - 1)) + 1
if turnframe ~= 1 and turnframe ~= #sample.quads 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
if n.dead then
anim = 'die'
local a = math.min(math.abs(n.eattimer - FISH_FOOD_DEAD) * 1.4, 1) - n.render.deathanim * 0.4
frame = math.floor(a * (#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 - n.render.deathanim)
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 - n.render.deathanim)
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
end

View file

@ -0,0 +1,13 @@
return function(food, sheets, spritescale)
local sw, sh = love.graphics.getDimensions()
for _,f in ipairs(food) do
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
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
end

View file

@ -0,0 +1,91 @@
return function(headerheight, fishsprite, headerbuttons, sheets, balance)
local sw, sh = love.graphics.getDimensions()
local base = sprites['header/base']
local size = headerheight / HEADER_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
local y = 3
for b = 1, 7 do
local hovered = mouseOverBox(x * size, y * size, sprites['header/buttonbg']:getWidth() * size, sprites['header/buttonbg']:getHeight() * size)
local btn = headerbuttons[b]
if (btn and not btn.open) or not btn then
-- draw nothing
elseif hovered and love.mouse.isDown(1) then
love.graphics.draw(sprites['header/buttonbg_down'], x * size, y * size, 0, size, size)
elseif hovered then
love.graphics.draw(sprites['header/buttonbg_hover'], x * size, y * size, 0, size, size)
else
love.graphics.draw(sprites['header/buttonbg'], x * size, y * size, 0, size, size)
end
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['header/buttonbg']:getWidth() / sheet.width) * 0.9
local offset = (sprites['header/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['header/buttonbg']:getWidth() / sheet.width) * 0.65
local offset = (sprites['header/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['header/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['header/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['header/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.cost, round(x * size), round(y * size + 51 * size - font:getHeight()/2), round(sprites['header/buttonbg']:getWidth() * size), 'center')
love.graphics.setColor(1, 1, 1)
love.graphics.setFont(fonts.default)
-- reflection
love.graphics.setBlendMode('add')
love.graphics.draw(sprites['header/reflection'], x * size, y * size, 0, size, size)
love.graphics.setBlendMode('alpha')
end
-- open/close anim
if (btn and btn.openanim < 1) then
local sheet = sheets.buttonopen
local anim = 0
if btn then anim = btn.openanim end
local frame = math.floor(anim % 1 * #sheet.quads) + 1
love.graphics.draw(sheet.spriteSheet, sheet.quads[frame], x * size, y * size, 0, size, size)
end
end
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
-- money count
love.graphics.setFont(fonts.continuum)
love.graphics.setColor(179/255, 254/255, 89/255)
local leftpad = 100
love.graphics.printf(balance, round(sw * 0.965 - leftpad), round(HEADER_HEIGHT - 25), leftpad, 'right')
love.graphics.setFont(fonts.default)
end

View file

@ -0,0 +1,12 @@
return function(money, sheets, spritescale)
local sw, sh = love.graphics.getDimensions()
for _,f in ipairs(money) do
local sheet = sheets['money' .. (f.type)]
local x = mix(f.x * sw, sw / 9 * 8, ease.outCubic(f.collecttimer))
local y = mix(f.y * sh, HEADER_HEIGHT - 20, ease.outCubic(f.collecttimer))
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
end

View file

@ -0,0 +1,9 @@
return function(feesh, spritescale)
local sw, sh = love.graphics.getDimensions()
for i, n in ipairs(feesh) do
love.graphics.setColor(1, 1, 1, n.render.y + 0.2 - n.render.deathanim)
local sizes = {0.55, 0.7, 1}
local size = sizes[n.size + 1] or 1
love.graphics.draw(sprites['shadow'], n.render.x * sw - (sprites['shadow']:getWidth() * spritescale * size)/2, sh - sh * 0.18 - (sprites['shadow']:getHeight() * spritescale * size)/2 + n.render.y * sh * 0.08, 0, spritescale * size, spritescale * size)
end
end

View file

@ -0,0 +1,22 @@
return function(headerheight, sheets)
local sw, sh = love.graphics.getDimensions()
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, headerheight + 20, 0, wavescale * sizex, wavescale, sprites['wave/wavecenter']:getWidth()/2)
end
love.graphics.setBlendMode('alpha')
end

207
scenes/gameplay/main.lua Normal file
View file

@ -0,0 +1,207 @@
local self = {}
local sheets = {}
local food = {}
local feesh = {}
local money = {}
local balance = 100
local foodtier = 1
local foodcount = 1
local headerbuttons = {
{
cost = 100,
sprite = 'guppy',
openanim = 1,
open = false,
closed = false,
func = function()
playSound('splash', 0.7, 0.8)
table.insert(feesh, constr.fish(math.random(), 0.3))
end
},
{
cost = 200,
sprite = 'food',
tier = foodtier,
openanim = 1,
open = false,
closed = false,
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 = foodcount,
openanim = 1,
open = false,
closed = false,
func = function(self)
self.openanim = 0
foodcount = foodcount + 1
if foodcount >= 9 then
self.open = false
else
self.tier = foodcount
end
end
}
}
local sheets = {}
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 self.load()
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())
sheets.food2 = newAnimation(sprites['food/2'], sprites['food/2']:getWidth()/10, sprites['food/2']:getHeight())
sheets.food3 = newAnimation(sprites['food/3'], sprites['food/3']:getWidth()/10, sprites['food/3']:getHeight())
sheets.buttonopen = newAnimation(sprites['header/button_open'], sprites['header/button_open']:getWidth()/3, sprites['header/button_open']:getHeight())
sheets.money1 = newAnimation(sprites['money/coin1'], sprites['money/coin1']:getWidth()/10, sprites['money/coin1']:getHeight())
sheets.money2 = newAnimation(sprites['money/coin2'], sprites['money/coin2']:getWidth()/10, sprites['money/coin2']:getHeight())
for i = 1, 2 do
table.insert(feesh, constr.fish(math.random(), math.random()))
end
end
function self.update(dt)
bench.startBenchmark('update_buttons')
for _,btn in ipairs(headerbuttons) do
btn.openanim = btn.openanim + dt * 6
end
bench.stopBenchmark('update_buttons')
bench.startBenchmark('update_food')
require('scenes.gameplay.update.food')(food, dt)
bench.stopBenchmark('update_food')
bench.startBenchmark('update_money')
require('scenes.gameplay.update.money')(money, dt)
bench.stopBenchmark('update_money')
bench.startBenchmark('update_fish')
require('scenes.gameplay.update.fish')(feesh, dt, food)
bench.stopBenchmark('update_fish')
end
function self.draw()
bench.startBenchmark('render_tank')
local sw, sh = love.graphics.getDimensions()
local headerheight = HEADER_HEIGHT * sw/640
local yscale = (sh-headerheight)/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, headerheight - HEADER_HEIGHT, 0, sw, sh - (headerheight - HEADER_HEIGHT))
-- waves
bench.startBenchmark('render_wave')
require('scenes.gameplay.draw.wave')(headerheight, sheets)
bench.stopBenchmark('render_wave')
-- shadow
bench.startBenchmark('render_shadow')
require('scenes.gameplay.draw.shadow')(feesh, spritescale)
bench.stopBenchmark('render_shadow')
bench.startBenchmark('render_food')
require('scenes.gameplay.draw.food')(food, sheets, spritescale)
bench.stopBenchmark('render_food')
-- all the fish
bench.startBenchmark('render_fish')
require('scenes.gameplay.draw.fish')(feesh, spritescale, fishsprite)
bench.stopBenchmark('render_fish')
bench.stopBenchmark('render_tank')
bench.startBenchmark('render_header')
require('scenes.gameplay.draw.header')(headerheight, fishsprite, headerbuttons, sheets, balance)
bench.stopBenchmark('render_header')
bench.startBenchmark('render_money')
require('scenes.gameplay.draw.money')(money, sheets, spritescale)
bench.stopBenchmark('render_money')
end
function self.mousepressed(x, y, b)
if b == 1 then
for _,m in ipairs(money) do
local dist = math.abs(x/love.graphics.getWidth() - m.x) + math.abs(y/love.graphics.getHeight() - m.y)
if dist < 0.1 and not m.collected then
m.collected = true
m.deathtimer = 0
playSound('collect', 1, 1 + math.random() * 0.2 - 0.1)
if m.type == 1 then balance = balance + 15 end
if m.type == 2 then balance = balance + 35 end
return
end
end
end
if b == 1 and y > HEADER_HEIGHT and #food < foodcount then
if balance >= 5 then
table.insert(food, constr.food(x/love.graphics.getWidth(), y/love.graphics.getHeight(), foodtier))
playSound('dropfood')
balance = balance - 5
else
playSound('buzzer')
end
end
local headerheight = HEADER_HEIGHT * love.graphics.getWidth()/640
local size = headerheight / HEADER_HEIGHT
if b == 1 then
local x = 19
for i = 1, 7 do
local hovered = mouseOverBox(x * size, 3 * size, sprites['header/buttonbg']:getWidth() * size, sprites['header/buttonbg']:getHeight() * size)
if hovered then
if headerbuttons[i] and headerbuttons[i].open then
if balance >= headerbuttons[i].cost then
headerbuttons[i].func(headerbuttons[i])
playSound('buttonclick')
balance = balance - headerbuttons[i].cost
else
playSound('buzzer')
end
end
end
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
end
end
return self

View file

@ -0,0 +1,239 @@
return function(feesh, dt, food)
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
angle = mix(angle, math.deg(math.atan2((0.5 + math.sin(love.timer.getTime()/10 + fi) * 0.2) - n.y, 0)), 0.1) -- slightly head towards the middle, to prevent getting stuck at the bottom or top
if n.eattimer <= 0 and not n.dead then -- needs to follow something
local mx, my
if n.eattimer <= 0 then
if n.shortestfood and food[n.shortestfood] then
local f = food[n.shortestfood]
mx, my = f.x, f.y
elseif frame % FISH_FOOD_CHECK_FREQ == 0 then
local minfood = 0
local mindist = 9e9
for i,f in ipairs(food) do
local dist = math.sqrt(math.pow(math.abs(f.x - n.render.x), 2) + math.pow(math.abs(f.y - n.render.y), 2))
if dist < mindist then
mindist = dist
minfood = i
end
end
if minfood ~= 0 then
n.shortestfood = minfood
end
end
end
if mx and my then
angle = math.deg(math.atan2(my - n.y, mx - n.x)) + math.random(-FISH_FOLLOW_RANDOM, FISH_FOLLOW_RANDOM)
str = math.random(70, 200)/200/8
end
end
local x = math.cos(math.rad(angle)) * str
local y = math.sin(math.rad(angle)) * str
if not ((n.shortestfood and food[n.shortestfood]) or n.dead) 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 = (HEADER_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
if n.eattimer < FISH_FOOD_HUNGRY or (n.shortestfood and food[n.shortestfood]) then
e.speed = e.speed * 1.3
end
if n.dead then
e.speed = e.speed * 0.2
end
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
n.moneytimer = n.moneytimer - dt
if n.moneytimer < 0 and not n.dead then
n.moneytimer = n.moneytimer + math.random() * 5 + 5
if n.size > 0 then
local type = 2
if n.size == 1 then type = 1 end
table.insert(money, constr.money(n.render.x, n.render.y, type))
end
end
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)
bench.stopBenchmark('update_fish_position')
bench.startBenchmark('update_fish_colission')
if n.shortestfood and food[n.shortestfood] and frame % FISH_COLISSION_CHECK_FREQ == 0 then
local f = food[n.shortestfood]
if f then
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)
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 and n.size == 0 then
n.size = 1
playSound('grow')
if not headerbuttons[1].open and not headerbuttons[1].closed then
headerbuttons[1].open = true
headerbuttons[1].openanim = 0
end
end
if n.lifetime > FISH_AGE_BIG and n.size == 1 then
n.size = 2
playSound('grow')
if not headerbuttons[2].open and not headerbuttons[1].closed then
headerbuttons[2].open = true
headerbuttons[2].openanim = 0
end
if not headerbuttons[3].open and not headerbuttons[1].closed then
headerbuttons[3].open = true
headerbuttons[3].openanim = 0
end
end
end
end
end
bench.stopBenchmark('update_fish_colission')
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) * 250 + 0.5)) % 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
if not n.dead then
n.render.turndir = math.sign(n.render.x - n.render.prevx)
end
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')
if n.eattimer <= FISH_FOOD_DEAD and not n.dead then
playSound('die')
end
if n.eattimer <= FISH_FOOD_DEAD then
n.dead = true
local timeSinceDead = math.abs(n.eattimer - FISH_FOOD_DEAD)
n.render.y = n.render.y + timeSinceDead/5 * math.min(timeSinceDead, 1)
n.render.y = clamp(n.render.y, 0, 0.85)
if n.render.y == 0.85 then
n.render.deathanim = n.render.deathanim + dt
if n.render.deathanim > 1 then
table.remove(feesh, fi)
end
end
end
end
end

View file

@ -0,0 +1,15 @@
return function(food, dt)
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.deathtimer > 1 then
table.remove(food, i)
end
end
end

View file

@ -0,0 +1,20 @@
return function(money, dt)
for i,f in ipairs(money) do
if not f.collected then
f.y = f.y + dt * f.speed
f.y = clamp(f.y, 0, 0.9)
end
f.time = f.time + dt
if f.y == 0.9 and not f.collected then
f.deathtimer = f.deathtimer + dt
end
if f.collected then
f.collecttimer = f.collecttimer + dt
end
if f.deathtimer > 1 or f.collecttimer > 1 then
table.remove(money, i)
end
end
end