notsanequarium/scenes/gameplay/update/fish.lua

298 lines
9.9 KiB
Lua

return function(feesh, dt, food, headerbuttons, money)
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
local followingObj = (n.shortestfood and food[n.shortestfood] and n.size ~= 4) or (n.shortestfood and feesh[n.shortestfood] and n.size == 4)
if n.eattimer <= 0 and not n.dead then -- needs to follow something
local mx, my
if n.eattimer <= 0 then
if n.size == 4 then -- carnivore
if n.shortestfood and feesh[n.shortestfood] then
local f = feesh[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(feesh) do
if f.size == 0 then
local dist = math.sqrt(math.pow(math.abs(f.render.x - n.render.x), 2) + math.pow(math.abs(f.render.y - n.render.y), 2))
if dist < mindist then
mindist = dist
minfood = i
end
end
end
if minfood ~= 0 then
n.shortestfood = minfood
end
end
else
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
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 (followingObj 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 followingObj then
e.speed = e.speed * 1.3
if n.size == 4 then e.speed = e.speed * 1.1 end
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
if n.size == 3 then type = 3 end
if n.size == 4 then type = 4 end
if n.star then type = 3 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.size == 4 then
if n.shortestfood and feesh[n.shortestfood] and frame % FISH_COLISSION_CHECK_FREQ == 0 and not n.dead then
local f = feesh[n.shortestfood]
local dist = math.abs(n.render.x - f.render.x) + math.abs(n.render.y - f.render.y)
if dist < FOOD_HITBOX then
playSound('chomp', 1, 1 + math.random() * 0.1 - 0.05)
table.remove(feesh, n.shortestfood)
n.eattimer = FISH_FOOD_3_COOLDOWN
n.render.eattimer = 0
n.shortestfood = -1
end
end
else
if n.shortestfood and food[n.shortestfood] and frame % FISH_COLISSION_CHECK_FREQ == 0 and not n.dead then
local f = food[n.shortestfood]
local dist = math.abs(n.render.x - f.x) + math.abs(n.render.y - f.y)
if dist < FOOD_HITBOX then
playSound('slurp', 1, 1 + math.random() * 0.1 - 0.05)
table.remove(food, n.shortestfood)
local cooldowns = {FISH_FOOD_1_COOLDOWN, FISH_FOOD_2_COOLDOWN, FISH_FOOD_3_COOLDOWN}
n.eattimer = cooldowns[f.type] or FISH_FOOD_3_COOLDOWN
n.render.eattimer = 0
n.shortestfood = -1
if f.type == 4 then -- star potion
if n.size == 2 or n.size == 3 then
n.star = true
else
n.eattimer = -9e9
playSound('explode')
end
else
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[2].closed then
headerbuttons[2].open = true
headerbuttons[2].openanim = 0
end
if not headerbuttons[3].open and not headerbuttons[3].closed then
headerbuttons[3].open = true
headerbuttons[3].openanim = 0
end
if not headerbuttons[4].open and not headerbuttons[4].closed then
headerbuttons[4].open = true
headerbuttons[4].openanim = 0
end
end
if n.lifetime > FISH_AGE_KING and n.size == 2 then
n.size = 3
playSound('grow')
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