epervier-framework/framework/scenes/world/camera/minimal.lua

147 lines
4.5 KiB
Lua

-- camera.lua :: a basic camera adapted to the asset/world system.
--[[
Copyright © 2019 Kazhnuz
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local CameraSystem = Object:extend()
local Vector3D = require "framework.libs.brinevector3D"
local physicsUtils = require "framework.scenes.world.actors.physics.utils"
-- INIT FUNCTIONS
-- Initialize the camera system
function CameraSystem:new(world, def)
self.world = world
self.mustFollowPlayer = true
def = def or {}
self.lock = {}
self:_initView(def.onScreen or {}, def.dimensions or {})
self:_regenerateCanvas()
end
function CameraSystem:_initView(onScreen, dimensions, target)
self.onScreen = Vector3D(onScreen.x, onScreen.y, 0)
local screenw, screenh = core.screen:getDimensions()
self.dimensions = { w = dimensions.w or screenw, h = dimensions.h or screenh, d = 1 }
self.position = Vector3D(0, 0, 0)
self.scale = 1
end
-- SETTER
-- Set some informations
function CameraSystem:lockCoordinates(x, y)
self.lock.x = x
self.lock.y = y
end
-- GETTER / COMPUTATION functions
-- Get some informations computations
function CameraSystem:getViewCoordinate()
local viewDimension = physicsUtils.dimensionsToVector(self.dimensions) / self.scale
local viewPosition = self.position - (viewDimension / 2)
return viewPosition, physicsUtils.vectorToDimensions(viewDimension)
end
-- UPDATE and MOVE functions
-- Move and update the camera system
function CameraSystem:update(dt)
if (self.mustFollowPlayer == true) then
self:_followPlayer()
end
end
function CameraSystem:moveView(position)
self.position = position
self:_limitView()
end
function CameraSystem:_limitView()
local worldPosition, worldDimensions = self.world:getBox()
local min = worldPosition + (physicsUtils.dimensionsToVector(self.dimensions) / 2)
local max = worldPosition + physicsUtils.dimensionsToVector(worldDimensions) -
(physicsUtils.dimensionsToVector(self.dimensions) / 2)
self.position.x = utils.math.between(self.position.x, min.x, max.x)
self.position.y = utils.math.between(self.position.y, min.y, max.y)
if (self.lock ~= nil and self.lock.x ~= nil) then
self.position.x = self.lock.x
end
if (self.lock ~= nil and self.lock.y ~= nil) then
self.position.y = self.lock.y
end
end
function CameraSystem:_followPlayer()
local target = self.world.player
if (target == nil) then
return
end
local position = target:getViewCenter()
position.x = math.floor(position.x)
position.y = math.floor(position.y)
self:moveView(position)
end
-- DRAWING FUNCTIONS
function CameraSystem:_regenerateCanvas()
self.canvas = love.graphics.newCanvas(self.dimensions.w, self.dimensions.h)
end
function CameraSystem:attachView()
self.previousCanvas = love.graphics.getCanvas()
love.graphics.setCanvas(self.canvas)
love.graphics.clear()
local t = self:getViewCoordinate()
love.graphics.push()
love.graphics.origin()
love.graphics.translate(math.floor(t.x) * -1, math.floor(t.y) * - 1)
end
function CameraSystem:detachView()
love.graphics.pop()
love.graphics.setCanvas(self.previousCanvas)
love.graphics.push()
love.graphics.origin()
love.graphics.translate(math.floor(self.onScreen.x), math.floor(self.onScreen.y))
love.graphics.scale(core.screen:getScale() * self.scale, core.screen:getScale() * self.scale)
love.graphics.draw(self.canvas)
local unscale = 1 / self.scale
love.graphics.scale(unscale, unscale)
love.graphics.pop()
end
return CameraSystem