diff --git a/CHANGELOG.md b/CHANGELOG.md index d63228f..84d802a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **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 diff --git a/gamecore/modules/world/baseworld.lua b/gamecore/modules/world/baseworld.lua index d26b48e..858cbf1 100644 --- a/gamecore/modules/world/baseworld.lua +++ b/gamecore/modules/world/baseworld.lua @@ -358,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 @@ -409,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) @@ -445,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 diff --git a/gamecore/modules/world/camera.lua b/gamecore/modules/world/camera.lua index 6570364..33fe4aa 100644 --- a/gamecore/modules/world/camera.lua +++ b/gamecore/modules/world/camera.lua @@ -39,6 +39,7 @@ function CameraSystem:new(world) self.mode = "split" self.verticalSplit = SPLITSCREEN_ISVERTICAL + self.targets = {} self:initViews() end @@ -155,6 +156,9 @@ function CameraSystem:addTarget(target) 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 @@ -219,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 @@ -234,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 @@ -303,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 @@ -337,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