Merge branch 'new-cameras' of game-projects/gamecore into master

This commit is contained in:
Kazhnuz 2019-06-29 21:53:57 +02:00 committed by Gitea
commit ce48e451c1
6 changed files with 158 additions and 22 deletions

View file

@ -23,6 +23,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **world:** Add a way to automatically load hitbox from a file
- **utils:** Add basic table functions
- **camera:** Add two new camera types: "middle" and "zoom".
### Changed
- **world2D:** Use a list for bodies (hitboxes, etc) and one other for actors
@ -35,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **world:** Make object creation more customizable by worlds
- **camera:** Make mode configuration configurable
### Fixed
- **world:** Remove a forgotten camera debug function

View file

@ -225,17 +225,14 @@ function BaseWorld:setPlayerNumber(playerNumber)
self.playerNumber = playerNumber or 1
end
function BaseWorld:addPlayer(actor, sourceid, haveCam)
function BaseWorld:addPlayer(actor, sourceid)
local player = {}
player.actor = actor
player.sourceid = sourceid or 1
table.insert(self.players, player)
if (haveCam) then
local xx, yy = player.actor:getViewCenter()
self.cameras:addView(xx, yy, player.actor)
end
self.cameras:addTarget(player.actor)
end
function BaseWorld:sendInputToPlayers(actor)
@ -319,7 +316,7 @@ function BaseWorld:newCollisionFromMap(objectlayer, object)
end
function BaseWorld:addPlayerFromMap(object, i)
self:addPlayer(self.obj.Player(self, object.x, object.y), i, true)
self:addPlayer(self.obj.Player(self, object.x, object.y), i)
end
function BaseWorld:loadMapPlayers()
@ -361,6 +358,13 @@ function BaseWorld:getBackgroundColor()
return self.backcolor[1]/256, self.backcolor[2]/256, self.backcolor[3]/256
end
function BaseWorld:resizeMap(w, h)
if self.haveMap then
local w, h = utils.math.floorCoord(w, h)
self.map:resize(w, h)
end
end
-- Lock MANAGEMENT FUNCTIONS
-- Basic function to handle the lock
@ -412,8 +416,8 @@ function BaseWorld:draw(dt)
self:drawActors()
else
for i=1, camNumber do
self.cameras:attachView(i)
self:drawMap(i)
self.cameras:attachView(i)
self:drawActors(i)
self.cameras:detachView(i)
self.cameras:drawHUD(i)
@ -448,10 +452,12 @@ function BaseWorld:drawMap(id)
-- Du à la manière dont fonctionne STI, on est obligé de récupérer les info
-- de position de camera pour afficher la carte par rapport à ces infos
tx, ty = self.cameras:getInternalCamCoordinate(id)
scale = self.cameras:getViewScale(id) or 1
scale = self.cameras:getViewScale(id) or 2
local vx, vy = self.cameras:getOnScreenViewRelativePosition(id)
tx = math.floor(tx - math.abs(vx))
ty = math.floor(ty - math.abs(vy))
local w, h = core.screen:getDimensions()
end
if self.haveMap then

View file

@ -37,11 +37,19 @@ function CameraSystem:new(world)
self.scene = world.scene
self.world = world
self.verticalSplit = SPLITSCREEN_ISVERTICAL
self.mode = "split"
self.verticalSplit = SPLITSCREEN_ISVERTICAL
self.targets = {}
self:initViews()
end
function CameraSystem:setMode(mode)
self.mode = mode
print("Camera system mode set to " .. mode)
return mode
end
function CameraSystem:initViews()
self.views = {}
@ -143,6 +151,18 @@ end
-- WRAPPER and UTILS
-- Access data from the views
function CameraSystem:addTarget(target)
if (#self.views < SCREEN_LIMIT) then
if (#self.views.list == 0) or (self.mode == "split") then
local x, y = target:getViewCenter()
self:addView(x, y, target)
table.insert(self.targets, target)
elseif (self.mode == "middle") or (self.mode == "zoom") then
table.insert(self.targets, target)
end
end
end
function CameraSystem:addView(x, y, target)
if (#self.views.list < SCREEN_LIMIT) then
local id = #self.views.list + 1
@ -203,13 +223,14 @@ end
function CameraSystem:getViewCoordinate(id)
local view = self:getView(id)
local cam = self:getViewCam(id)
local viewx, viewy, vieww, viewh
viewx = view.pos.x - (self.views.width/2)
viewy = view.pos.y - (self.views.height/2)
viewx = view.pos.x - ((self.views.width/2) / cam.scale)
viewy = view.pos.y - ((self.views.height/2) / cam.scale)
vieww = self.views.width
viewh = self.views.height
vieww = self.views.width / cam.scale
viewh = self.views.height / cam.scale
return viewx, viewy, vieww, viewh
end
@ -218,10 +239,12 @@ function CameraSystem:getInternalCamCoordinate(id)
local cam = self:getViewCam(id)
local viewx, viewy, vieww, viewh
viewx = cam.x - (self.views.width/2)
viewy = cam.y - (self.views.height/2)
viewx = cam.x - ((self.views.width/2) / cam.scale)
viewy = cam.y - ((self.views.height/2) / cam.scale)
vieww, viewh = core.screen:getDimensions()
vieww = vieww / cam.scale
viewh = viewh / cam.scale
return viewx, viewy, vieww, viewh
end
@ -287,7 +310,11 @@ end
function CameraSystem:update(dt)
for i,v in ipairs(self.views.list) do
self:followActor(i)
if (self.mode == "middle") or (self.mode == "zoom") then
self:followAllActors(i)
else
self:followActor(i)
end
end
end
@ -321,6 +348,53 @@ function CameraSystem:followActor(id)
end
end
function CameraSystem:followAllActors(id)
local view = self:getView(id)
local PADDING = 16
-- TODO: make all the padding and stuff part of object definition instead ?
-- It would especially allow better work in future fake3D worlds
if (#self.targets > 0) then
local minX, minY, maxX, maxY
for i, target in ipairs(self.targets) do
local xx, yy = target:getViewCenter()
-- If start by initializing the value at the first found value
if (minX == nil) then minX = xx - (target.w/2) end
if (maxX == nil) then maxX = xx + (target.w/2) end
if (minY == nil) then minY = yy - (target.h/2) end
if (maxY == nil) then maxY = yy + (target.h/2) end
minX = math.min(minX, xx - (target.w/2))
maxX = math.max(maxX, xx + (target.w/2))
minY = math.min(minY, yy - (target.h/2))
maxY = math.max(maxY, yy + (target.h/2))
end
-- Add padding
minX = minX - PADDING
minY = minY - PADDING
maxX = maxX + PADDING
maxY = maxY + PADDING
local x, y
x = (minX + maxX) / 2
y = (minY + maxY) / 2
local scale = 1
if (self.mode == "zoom") then
local ww, hh = core.screen:getDimensions()
local scalex = (maxX-minX)/ww
local scaley = (maxY-minY)/hh
scale = math.max(scale, scalex, scaley)
view.cam.scale = 1/scale
self.world:resizeMap(ww * 3, hh * 3)
end
self:moveView(id, x, y)
end
end
-- DRAW FUNCTIONS
-- Basic callback to draw stuff

View file

@ -82,10 +82,7 @@ function World2D:addPlayer(actor, sourceid, haveCam)
table.insert(self.players, player)
if (haveCam) then
local xx, yy = player.actor:getViewCenter()
self.cameras:addView(xx, yy, player.actor)
end
self.cameras:addTarget(player.actor)
end
-- MAP LOADING FUNCTIONS
@ -119,7 +116,7 @@ function World2D:newCollisionFromMap(objectlayer, object)
end
function World2D:addPlayerFromMap(object, i)
self:addPlayer(self.obj.Player(self, object.x, object.y), i, true)
self:addPlayer(self.obj.Player(self, object.x, object.y), i)
end
-- BODIES MANAGEMENT FUNCTIONS

View file

@ -27,5 +27,6 @@ local cwd = (...):gsub('%.init$', '') .. "."
return {
math = require(cwd .. "math"),
graphics = require(cwd .. "graphics"),
filesystem = require(cwd .. "filesystem")
filesystem = require(cwd .. "filesystem"),
table = require(cwd .. "table")
}

52
gamecore/utils/table.lua Normal file
View file

@ -0,0 +1,52 @@
-- loveutils.table : simple functions for table manipulation and computation.
-- TODO: could be a part of loveutils.math ?
--[[
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 Table = {}
function Table.reduce(list, fn)
local acc
for k, v in ipairs(list) do
if 1 == k then
acc = v
else
acc = fn(acc, v)
end
end
return acc
end
function Table.sum(table)
local sum = 0
for _, v in pairs(table) do
sum = sum + v
end
return sum
end
function Table.average(table)
return Table.sum(table) / #table
end
return Table