Compare commits

..

2 commits

Author SHA1 Message Date
jill
e2703105dd
a proper money system and progressive upgrades
the game is now officially playable! this marks 1.0b and perfectly recreates the "tutorial" stage of insaniquarium, with some audio and visual changes, no king guppies and no egg pieces
2021-01-23 23:04:16 +03:00
jill
74bf2a7045
money 2021-01-23 22:42:56 +03:00
17 changed files with 174 additions and 56 deletions

BIN
assets/audio/sfx/buzzer.ogg Executable file

Binary file not shown.

BIN
assets/audio/sfx/collect.ogg Executable file

Binary file not shown.

View file

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View file

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -23,7 +23,7 @@ FISH_AGE_BIG = 65 -- see above, but for big
FISH_SIZE = 6 -- how many large guppies can you fit on the screen FISH_SIZE = 6 -- how many large guppies can you fit on the screen
FOOTER_HEIGHT = 68 HEADER_HEIGHT = 68
FOOD_HITBOX = 0.08 FOOD_HITBOX = 0.08

View file

@ -8,6 +8,7 @@ function self.fish(x, y)
y = y, y = y,
size = 0, -- 0 for small, 1 for medium, 2 for big, 3 for king 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 eattimer = 0 + math.random() * 2, -- starts out hungry, with a 2s delay
moneytimer = 10 + math.random() * 5, -- min 10s before it can make money
dead = false, dead = false,
lifetime = 0, lifetime = 0,
@ -58,4 +59,19 @@ function self.food(x, y, type)
return food return food
end end
function self.money(x, y, type)
local money = {
x = x,
y = y,
speed = 0.12,
time = math.random(),
deathtimer = 0,
collected = false,
collecttimer = 0,
type = type
}
return money
end
return self return self

212
main.lua
View file

@ -18,16 +18,20 @@ debug = false
food = {} food = {}
feesh = {} feesh = {}
money = {}
local balance = 100
foodtier = 1 foodtier = 1
foodcount = 1 foodcount = 1
footerbuttons = { headerbuttons = {
{ {
cost = 100, cost = 100,
sprite = 'guppy', sprite = 'guppy',
openanim = 1, openanim = 0,
open = true, open = false,
closed = false,
func = function() func = function()
playSound('splash', 0.7, 0.8) playSound('splash', 0.7, 0.8)
table.insert(feesh, constr.fish(math.random(), 0.3)) table.insert(feesh, constr.fish(math.random(), 0.3))
@ -37,8 +41,9 @@ footerbuttons = {
cost = 200, cost = 200,
sprite = 'food', sprite = 'food',
tier = foodtier, tier = foodtier,
openanim = 1, openanim = 0,
open = true, open = false,
closed = false,
func = function(self) func = function(self)
self.openanim = 0 self.openanim = 0
foodtier = foodtier + 1 foodtier = foodtier + 1
@ -53,8 +58,9 @@ footerbuttons = {
cost = 300, cost = 300,
sprite = 'foodcount', sprite = 'foodcount',
tier = foodcount, tier = foodcount,
openanim = 1, openanim = 0,
open = true, open = false,
closed = false,
func = function(self) func = function(self)
self.openanim = 0 self.openanim = 0
foodcount = foodcount + 1 foodcount = foodcount + 1
@ -105,9 +111,12 @@ function love.load()
sheets.food2 = newAnimation(sprites['food/2'], sprites['food/2']:getWidth()/10, sprites['food/2']: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.food3 = newAnimation(sprites['food/3'], sprites['food/3']:getWidth()/10, sprites['food/3']:getHeight())
sheets.buttonopen = newAnimation(sprites['footer/button_open'], sprites['footer/button_open']:getWidth()/3, sprites['footer/button_open']:getHeight()) sheets.buttonopen = newAnimation(sprites['header/button_open'], sprites['header/button_open']:getWidth()/3, sprites['header/button_open']:getHeight())
for i = 1, 3 do 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())) table.insert(feesh, constr.fish(math.random(), math.random()))
end end
@ -125,7 +134,7 @@ function love.update(dt)
bench.startBenchmark('update') bench.startBenchmark('update')
bench.startBenchmark('update_buttons') bench.startBenchmark('update_buttons')
for _,btn in ipairs(footerbuttons) do for _,btn in ipairs(headerbuttons) do
btn.openanim = btn.openanim + dt * 6 btn.openanim = btn.openanim + dt * 6
end end
bench.stopBenchmark('update_buttons') bench.stopBenchmark('update_buttons')
@ -146,6 +155,27 @@ function love.update(dt)
end end
bench.stopBenchmark('update_food') 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') bench.startBenchmark('update_fish')
for fi, n in ipairs(feesh) do for fi, n in ipairs(feesh) do
bench.startBenchmark('update_fish_eases') bench.startBenchmark('update_fish_eases')
@ -175,6 +205,7 @@ function love.update(dt)
local angle = math.random(-FISH_ANGLE, FISH_ANGLE) local angle = math.random(-FISH_ANGLE, FISH_ANGLE)
local str = math.random(70, 200)/200/4 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 if n.eattimer <= 0 and not n.dead then -- needs to follow something
local mx, my local mx, my
@ -219,7 +250,7 @@ function love.update(dt)
e.x = 1 - math.abs(e.x%2-1) e.x = 1 - math.abs(e.x%2-1)
e.y = 1 - math.abs(e.y%2-1) e.y = 1 - math.abs(e.y%2-1)
local fheight = (FOOTER_HEIGHT * love.graphics.getWidth()/640)/love.graphics.getHeight() local fheight = (HEADER_HEIGHT * love.graphics.getWidth()/640)/love.graphics.getHeight()
if e.y < fheight then if e.y < fheight then
e.y = e.y + (fheight - e.y) * 2 e.y = e.y + (fheight - e.y) * 2
end end
@ -241,6 +272,17 @@ function love.update(dt)
n.lifetime = n.lifetime + dt n.lifetime = n.lifetime + dt
n.eattimer = n.eattimer - 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 sumx = 0
local sumy = 0 local sumy = 0
@ -276,10 +318,24 @@ function love.update(dt)
if n.lifetime > FISH_AGE_MEDIUM and n.size == 0 then if n.lifetime > FISH_AGE_MEDIUM and n.size == 0 then
n.size = 1 n.size = 1
playSound('grow') playSound('grow')
if not headerbuttons[1].open and not headerbuttons[1].closed then
headerbuttons[1].open = true
headerbuttons[1].openanim = 0
end
end end
if n.lifetime > FISH_AGE_BIG and n.size == 1 then if n.lifetime > FISH_AGE_BIG and n.size == 1 then
n.size = 2 n.size = 2
playSound('grow') 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
end end
@ -370,13 +426,13 @@ function love.draw()
love.graphics.setColor(1, 1, 1) love.graphics.setColor(1, 1, 1)
local sw, sh = love.graphics.getDimensions() local sw, sh = love.graphics.getDimensions()
local footerheight = FOOTER_HEIGHT * sw/640 local headerheight = HEADER_HEIGHT * sw/640
local yscale = (sh-footerheight)/sh local yscale = (sh-headerheight)/sh
local sample = fishsprite('medium', false, 'swim') local sample = fishsprite('medium', false, 'swim')
local spritescale = (math.min(sw, sh)/FISH_SIZE) / math.min(sample.width, sample.height) 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)) stretchto(sprites['bg/1'], 0, headerheight - HEADER_HEIGHT, 0, sw, sh - (headerheight - HEADER_HEIGHT))
-- waves -- waves
bench.startBenchmark('render_wave') bench.startBenchmark('render_wave')
@ -396,11 +452,24 @@ function love.draw()
if i == wavecount then if i == wavecount then
sizex = -1 sizex = -1
end 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) 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 end
love.graphics.setBlendMode('alpha') love.graphics.setBlendMode('alpha')
bench.stopBenchmark('render_wave') 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 -- shadow
bench.startBenchmark('render_shadow') bench.startBenchmark('render_shadow')
for i, n in ipairs(feesh) do for i, n in ipairs(feesh) do
@ -534,24 +603,11 @@ function love.draw()
end end
end end
bench.stopBenchmark('render_fish') bench.stopBenchmark('render_fish')
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')
bench.stopBenchmark('render_tank') bench.stopBenchmark('render_tank')
bench.startBenchmark('render_footer') bench.startBenchmark('render_header')
local base = sprites['footer/base'] local base = sprites['header/base']
local size = footerheight / FOOTER_HEIGHT local size = headerheight / HEADER_HEIGHT
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(base, 0, 0, 0, size, size) love.graphics.draw(base, 0, 0, 0, size, size)
@ -559,17 +615,17 @@ function love.draw()
local x = 19 local x = 19
local y = 3 local y = 3
for b = 1, 7 do for b = 1, 7 do
local hovered = mouseOverBox(x * size, y * size, sprites['footer/buttonbg']:getWidth() * size, sprites['footer/buttonbg']:getHeight() * size) local hovered = mouseOverBox(x * size, y * size, sprites['header/buttonbg']:getWidth() * size, sprites['header/buttonbg']:getHeight() * size)
local btn = footerbuttons[b] local btn = headerbuttons[b]
if (btn and not btn.open) or not btn then if (btn and not btn.open) or not btn then
-- draw nothing -- draw nothing
elseif hovered and love.mouse.isDown(1) then elseif hovered and love.mouse.isDown(1) then
love.graphics.draw(sprites['footer/buttonbg_down'], x * size, y * size, 0, size, size) love.graphics.draw(sprites['header/buttonbg_down'], x * size, y * size, 0, size, size)
elseif hovered then elseif hovered then
love.graphics.draw(sprites['footer/buttonbg_hover'], x * size, y * size, 0, size, size) love.graphics.draw(sprites['header/buttonbg_hover'], x * size, y * size, 0, size, size)
else else
love.graphics.draw(sprites['footer/buttonbg'], x * size, y * size, 0, size, size) love.graphics.draw(sprites['header/buttonbg'], x * size, y * size, 0, size, size)
end end
if btn then if btn then
@ -578,41 +634,41 @@ function love.draw()
if btn.sprite == 'guppy' then if btn.sprite == 'guppy' then
local sheet = fishsprite('medium', false, 'swim') local sheet = fishsprite('medium', false, 'swim')
local frame = math.floor((love.timer.getTime() * 2) % 1 * #sheet.quads) + 1 local frame = math.floor((love.timer.getTime() * 2) % 1 * #sheet.quads) + 1
local scale = (sprites['footer/buttonbg']:getWidth() / sheet.width) * 0.9 local scale = (sprites['header/buttonbg']:getWidth() / sheet.width) * 0.9
local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 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) 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 elseif btn.sprite == 'food' then
local sheets = {sheets.food2, sheets.food3} local sheets = {sheets.food2, sheets.food3}
local sheet = sheets[btn.tier] local sheet = sheets[btn.tier]
local scale = (sprites['footer/buttonbg']:getWidth() / sheet.width) * 0.65 local scale = (sprites['header/buttonbg']:getWidth() / sheet.width) * 0.65
local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 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) 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 elseif btn.sprite == 'foodcount' then
love.graphics.setFont(fonts.continuum) love.graphics.setFont(fonts.continuum)
local offset = (sprites['footer/buttonbg']:getWidth() * size) / 2 local offset = (sprites['header/buttonbg']:getWidth() * size) / 2
local bordersize = 1 local bordersize = 1
for _,p in ipairs({{0, 1}, {1, 0}, {1, 1}, {-1, 0}, {0, -1}, {-1, -1}, {1, -1}, {-1, 1}}) do 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.setColor(0, 0, 0, 0.5)
love.graphics.printf(btn.tier + 1, round(x * size) + p[1] * bordersize, round(y * size + offset*0.75 - fonts.continuum:getHeight()/2) + p[2] * bordersize, round(sprites['footer/buttonbg']:getWidth() * size), 'center') 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 end
love.graphics.setColor(0, 1, 0) love.graphics.setColor(0, 1, 0)
love.graphics.printf(btn.tier + 1, round(x * size), round(y * size + offset*0.75 - fonts.continuum:getHeight()/2), round(sprites['footer/buttonbg']:getWidth() * size), 'center') love.graphics.printf(btn.tier + 1, round(x * size), round(y * size + offset*0.75 - fonts.continuum:getHeight()/2), round(sprites['header/buttonbg']:getWidth() * size), 'center')
end end
-- price -- price
love.graphics.setFont(fonts.pix) love.graphics.setFont(fonts.pix)
local font = love.graphics.getFont() local font = love.graphics.getFont()
love.graphics.setColor(0, 1, 0) love.graphics.setColor(0, 1, 0)
love.graphics.printf('$' .. btn.cost, round(x * size), round(y * size + 51 * size - font:getHeight()/2), round(sprites['footer/buttonbg']:getWidth() * size), 'center') love.graphics.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.setColor(1, 1, 1)
love.graphics.setFont(fonts.default) love.graphics.setFont(fonts.default)
-- reflection -- reflection
love.graphics.setBlendMode('add') love.graphics.setBlendMode('add')
love.graphics.draw(sprites['footer/reflection'], x * size, y * size, 0, size, size) love.graphics.draw(sprites['header/reflection'], x * size, y * size, 0, size, size)
love.graphics.setBlendMode('alpha') love.graphics.setBlendMode('alpha')
end end
@ -631,7 +687,27 @@ function love.draw()
if b >= 3 then incr = 73 end if b >= 3 then incr = 73 end
x = x + incr x = x + incr
end end
bench.stopBenchmark('render_footer')
-- 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')
love.graphics.setColor(1, 1, 1, 1) love.graphics.setColor(1, 1, 1, 1)
love.graphics.print('FPS: ' .. 1 / love.timer.getDelta(), 0, sh - 16) love.graphics.print('FPS: ' .. 1 / love.timer.getDelta(), 0, sh - 16)
@ -641,23 +717,49 @@ function love.draw()
end end
function love.mousepressed(x, y, b) function love.mousepressed(x, y, b)
if b == 1 and y > FOOTER_HEIGHT and #food < foodcount then if b == 1 then
table.insert(food, constr.food(x/love.graphics.getWidth(), y/love.graphics.getHeight(), foodtier)) for _,m in ipairs(money) do
playSound('dropfood') 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 end
local footerheight = FOOTER_HEIGHT * love.graphics.getWidth()/640 if b == 1 and y > HEADER_HEIGHT and #food < foodcount then
local size = footerheight / FOOTER_HEIGHT 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 if b == 1 then
local x = 19 local x = 19
for i = 1, 7 do for i = 1, 7 do
local hovered = mouseOverBox(x * size, 3 * size, sprites['footer/buttonbg']:getWidth() * size, sprites['footer/buttonbg']:getHeight() * size) local hovered = mouseOverBox(x * size, 3 * size, sprites['header/buttonbg']:getWidth() * size, sprites['header/buttonbg']:getHeight() * size)
if hovered then if hovered then
if footerbuttons[i] and footerbuttons[i].open then if headerbuttons[i] and headerbuttons[i].open then
footerbuttons[i].func(footerbuttons[i]) if balance >= headerbuttons[i].cost then
playSound('buttonclick') headerbuttons[i].func(headerbuttons[i])
playSound('buttonclick')
balance = balance - headerbuttons[i].cost
else
playSound('buzzer')
end
end end
end end