diff --git a/scenes/game.lua b/scenes/game.lua index e855ccc..169717f 100644 --- a/scenes/game.lua +++ b/scenes/game.lua @@ -1,273 +1,365 @@ local state = lib "stager" local game = state:new("Game") local global = require "global" local config = require "conf" local util = include "util" +local flux = lib "flux" + local bounds local world local skybox local sandMaterial local objects local groundOffset = -0.5 -local fogRatio local fogScale = 2 +local transitions + function game:load() + transitions = {} + bounds = (class "Bounds"):new({ x = 0, y = 1.8, z = 1.8, width = 500, height = 1.4, depth = 500 }) world = lovr.physics.newWorld(0, -9.81, 0, true, {}) world:setSleepingAllowed(false) skybox = lovr.graphics.newTexture({ left = 'images/underwater/uw_lf.jpg', right = 'images/underwater/uw_rt.jpg', top = 'images/underwater/uw_up.jpg', bottom = 'images/underwater/uw_dn.jpg', front = 'images/underwater/uw_ft.jpg', back = 'images/underwater/uw_bk.jpg' }) local sandTexture = lovr.graphics.newTexture("images/sand.jpg") sandMaterial = lovr.graphics.newMaterial(sandTexture) sandMaterial:setTransform(0, 0, math.log(bounds:getWidth()) * 5, math.log(bounds:getDepth()) * 5, 0) game.fishModel = (class "TransformedModel"):new({ model = lovr.graphics.newModel("models/Fish3_out/Fish3.gltf"), x = 0, y = 0, z = 0, scale = -0.1, angle = 0, ax = 0, ay = 0, az = 0 }) game.shaders = { animatedFog = lovr.graphics.newShader("shaders/shader.vert", "shaders/shader.frag", { flags = { animated = true } }), regularFog = lovr.graphics.newShader("shaders/shader.vert", "shaders/shader.frag", { flags = { animated = false } }), } - fogRatio = 0 + game.fogRatio = 0 game.shaders.animatedFog:send("CameraEye", { 0, 0, 0, 0 }) - game.shaders.animatedFog:send("FogBounds", { 4, 22 * ((1 - fogRatio) * fogScale + 1) }) + game.shaders.animatedFog:send("FogBounds", { 4, 22 * ((1 - game.fogRatio) * fogScale + 1) }) game.shaders.animatedFog:send("causticsScale", 1) game.shaders.regularFog:send("CameraEye", { 0, 0, 0, 0 }) - game.shaders.regularFog:send("FogBounds", { 4, 20 * ((1 - fogRatio) * fogScale + 1) }) + game.shaders.regularFog:send("FogBounds", { 4, 20 * ((1 - game.fogRatio) * fogScale + 1) }) game.shaders.regularFog:send("causticsScale", 1) game.causticsTexture = lovr.graphics.newTexture("images/caustics.jpg") game.shaders.animatedFog:send("causticsTexture", game.causticsTexture) game.shaders.animatedFog:send("causticsAmount", 1.0) game.shaders.regularFog:send("causticsTexture", game.causticsTexture) game.shaders.regularFog:send("causticsAmount", 1.0) game.swarm = (class "boids.BoidsSwarm"):new({ bounds = bounds }) local x, y, z = 0, 1.8, -3 for iz = 0, 2 do for i = 1, 10 do local boid = (class "boids.SelfControlledBoid"):new({ world = world, x = x + i - 10/2, y = y + lovr.math.random() * 0.3, z = z - iz, angle = 0, ax = 0, ay = 1, az = 0, model = game.fishModel }) game.swarm:addBoid(boid) end end global.playerBoid = (class "boids.CelluloControlledBoid"):new({ world = world, cellulo = -1, -- will be later set by menu.lua controlMethod = "absolute", celluloPlane = (class "CelluloPlane"):new(config.CELLULO_PLANE), hapticFeedbackEnabled = false, x = 0, y = 0, z = 0, angle = 0, ax = 0, ay = 1, az = 0, model = game.fishModel }) game.swarm:addBoid(global.playerBoid) objects = { shipwreck = (class "TransformedModel"):new({ model = lovr.graphics.newModel("models/shipwreck/0.gltf"), x = 0, y = 0, z = 0, scale = 0.002, angle = -0.6, ax = 1, ay = 1, az = 0.5 }), rock = (class "TransformedModel"):new({ model = lovr.graphics.newModel("models/rock/Rock1.gltf"), x = 0, y = -0.01, z = 0, scale = 0.8, angle = 0, ax = 0, ay = 1, az = 0 }) } + game.levelLabel = "LEVEL" + game.levelOffset = 0 + game.subLabel = "SUB" + game.subOffset = 0 + + game.hasStarted = false + game.currentLevel = -1 + game.currentTargetCount = 0 + + --flux.to(game, 2, { levelOffset = 1, subOffset = 1 }):after(game, 2, { levelOffset = 0, subOffset = 0}) + end function game:unload() world:destroy() end function game:update(dt) + flux.update(dt) + game.shaders.regularFog:send("time", lovr.timer.getTime()) - game.swarm:setTargetPosition({ math.cos(lovr.timer.getTime() / 3) * 4, 1, -10 + math.sin(lovr.timer.getTime() / 3) * 4 }) + if game.currentLevel == -1 then + game.swarm:setTargetPosition({ math.cos(lovr.timer.getTime() / 8) * 6, 1.6, -10 + math.sin(lovr.timer.getTime() / 8) * 6 }) + end world:update(dt) game.fishModel:animate(1, lovr.timer.getTime()) --game.swarm:setPosition(math.cos(lovr.timer.getTime()*0.1) * 5, 0, math.sin(lovr.timer.getTime()*0.1) * 5) game.swarm:update(dt) global.camera:setPosition(global.playerBoid:getPosition()) global.camera:setAngle(global.playerBoid:getAngle()) end function game:draw() lovr.graphics.setColor(0, 0.35, 0.482, 1) lovr.graphics.fill() lovr.graphics.setColor(1, 1, 1, 1) global.camera:draw(function () lovr.graphics.setColor(1, 1, 1, 1) game.shaders.regularFog:send("FogColor", { 0, 0.1, 0.2, 1 }) util.withShader(game.shaders.regularFog, function () game.shaders.regularFog:send("causticsScale", 8) - game.shaders.regularFog:send("FogBounds", { 2, 12 * ((1 - fogRatio) * fogScale + 1) }) + game.shaders.regularFog:send("FogBounds", { 2, 12 * ((1 - game.fogRatio) * fogScale + 1) }) lovr.graphics.setColor(0.2, 0.6, 0.9, 1) lovr.graphics.push() -- floor lovr.graphics.translate(0, groundOffset, 0) lovr.graphics.plane(sandMaterial, 0, 0, 0, bounds:getWidth(), bounds:getDepth(), math.pi / 2, 1, 0, 0) game:drawScene() local target = game.swarm:getTargetPosition() if target then game.shaders.regularFog:send("causticsAmount", 0) lovr.graphics.setColor(0.2, 0.6, 0.9, 0.2) lovr.graphics.cube('fill', target[1], target[2], target[3], 0.2, lovr.timer.getTime()) lovr.graphics.setColor(1, 1, 1, 1) lovr.graphics.cube('line', target[1], target[2], target[3], 0.2, lovr.timer.getTime()) game.shaders.regularFog:send("causticsAmount", 1) end lovr.graphics.pop() -- roof game.shaders.regularFog:send("causticsScale", 4) - game.shaders.regularFog:send("FogBounds", { 2, 40 * ((1 - fogRatio) * fogScale + 1) }) + game.shaders.regularFog:send("FogBounds", { 2, 40 * ((1 - game.fogRatio) * fogScale + 1) }) lovr.graphics.setColor(0.3, 0.7, 1) lovr.graphics.plane("fill", 0, 6, 0, bounds:getWidth(), bounds:getDepth(), math.pi / 2, 1, 0, 0) end) game.shaders.animatedFog:send("FogColor", { 0, 0.1, 0.3, 0 }) util.withShader(game.shaders.animatedFog, function () lovr.graphics.setColor(0.7, 0.9, 1, 1) game.swarm:draw() end) end) global:drawHud(function () game:drawLevelAndObjective() game:drawCelluloPosition() end) end function game:drawScene() game.shaders.regularFog:send("causticsAmount", 0.1) lovr.graphics.setColor(0.2, 0.6, 0.9, 1) - game.shaders.regularFog:send("FogBounds", { 4, 22 * ((1 - fogRatio) * fogScale + 1) }) + game.shaders.regularFog:send("FogBounds", { 4, 22 * ((1 - game.fogRatio) * fogScale + 1) }) game.shaders.regularFog:send("causticsScale", 0.2) - objects.shipwreck:draw(-3, 0, -2) - objects.rock:draw(7, 0, 2) + objects.shipwreck:draw(-5, 0, -2) + objects.rock:draw(9, 0, 2) game.shaders.regularFog:send("causticsAmount", 1) end function game:drawLevelAndObjective() lovr.graphics.push() lovr.graphics.transform(-0.175, 0.175, 0, 1, 1, 1, 0.6, 0.5, 1, 0) local s = 0.05 lovr.graphics.scale(s, s, s) - lovr.graphics.setColor(1, 1, 1, 1) - lovr.graphics.print("Level 1", 0, 0, 0, 1, 0, 0, 1, 0, 0, "left") + lovr.graphics.setColor(1, 1, 1, 1-game.levelOffset) + lovr.graphics.print(game.levelLabel, 0, game.levelOffset, 0, 1, 0, 0, 1, 0, 0, "left") + lovr.graphics.setColor(1, 1, 1, 1-game.subOffset) + lovr.graphics.print(game.subLabel, -math.pow(game.subOffset, 2) * 3, -1, 0, 1, 0, 0, 1, 0, 0, "left") lovr.graphics.pop() end function game:drawCelluloPosition() -- draw position of cellulo on paper lovr.graphics.push() lovr.graphics.transform(0.175, -0.175, 0, 1, 1, 1, -0.6, 0.5, 1, 0) local s = 0.05 lovr.graphics.scale(s, s, s) lovr.graphics.setColor(0, 0, 0, 0.5) lovr.graphics.plane("fill", 0, 0, 0, 2, 2) local sqrt2d2 = math.sqrt(2) / 2 local polygon = { 0, 1, 0, -- top pointing arrow 1, 0, 0, sqrt2d2, -sqrt2d2, 0, sqrt2d2, -sqrt2d2, 0, -sqrt2d2, -sqrt2d2, 0, 0, 1, 0, -- top pointing arrow -sqrt2d2, -sqrt2d2, 0, -1, 0, 0, 0, 1, 0 -- top pointing arrow } local x, y = global.playerBoid:getCelluloPlane():normalizedRelative(global.robot:getX(), global.robot:getY()) lovr.graphics.translate(x, -y, 0.1) local ps = 0.2 lovr.graphics.scale(ps, ps, ps) lovr.graphics.rotate(global.robot:getTheta(), 0, 0, -1) lovr.graphics.setColor(1, 1, 1, 0.75) lovr.graphics.triangle("fill", polygon) lovr.graphics.pop() end function game:buttonpressed(device, button) if button == "b" then local s = global.camera:getX() .. " " .. global.camera:getY() .. " " .. global.camera:getZ() global.toastManager:addToast(s) + elseif button == "a" then + end if button == "touchpad" then state:push("scenes/menu") end return true end +function game:stopGame() + game.hasStarted = false + for i = 1, #transitions do + transitions[i]:stop() + end + table.insert(transitions, flux.to(game, 1, { levelOffset = 1, subOffset = 1, fogRatio = 0 })) +end + +function game:spawnRandomTarget() + game.swarm:setTargetPosition({ + (lovr.math.random()-.5) * 30, + 1.6, + (lovr.math.random()-.5) * 30 + }) +end + +function game:startGame() + game.hasStarted = true + game:levelOne() +end + +function game:levelOne() + game.currentLevel = 1 + game.currentTargetCount = 0 + game.levelLabel = "level 1" + game.subLabel = "reach the target (0/3)" + table.insert(transitions, flux.to(game, 1, { levelOffset = 0, subOffset = 0 })) + game:spawnRandomTarget() +end + +function game:levelTwo() + game.currentLevel = 2 + game.currentTargetCount = 0 + game.levelLabel = "level 2" + game.subLabel = "reach the target (0/3)" + table.insert(transitions, flux.to(game, 1, { levelOffset = 0, subOffset = 0 })) + table.insert(transitions, flux.to(game, 3, { fogRatio = 1 })) + game:spawnRandomTarget() +end + +function game:youWin() + game.currentLevel = -1 + game.levelLabel = "you win!" + game.subLabel = "" + table.insert(transitions, flux.to(game, 1, { levelOffset = 0, subOffset = 0 })) + table.insert(transitions, flux.to(game, 3, { fogRatio = 0 })) +end + +function game:onReachedTarget() + if game.hasStarted and game.currentTargetCount < 3 then + game.currentTargetCount = game.currentTargetCount + 1 + game.subLabel = "reach the target (" .. game.currentTargetCount .. "/3)" + if game.currentTargetCount == 3 then + table.insert(transitions, flux.to(game, 1, {}):oncomplete(function() + table.insert(transitions, flux.to(game, 1, { levelOffset = 1, subOffset = 1 }):oncomplete(function() + if currentLevel == 1 then + game:levelTwo() + else + game:youWin() + end + end)) + end)) + else + game:spawnRandomTarget() + end + end +end + return game \ No newline at end of file