239 lines
No EOL
7.6 KiB
Lua
239 lines
No EOL
7.6 KiB
Lua
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 |