]> git.mcshandy.xyz Git - sumeriangame/commitdiff
NESFreeRoam camera finally working save some inter-map bugs
authorRandy McShandy <randy@mcshandy.xyz>
Thu, 26 Feb 2026 03:24:17 +0000 (21:24 -0600)
committerRandy McShandy <randy@mcshandy.xyz>
Thu, 26 Feb 2026 03:24:17 +0000 (21:24 -0600)
main/assets.lua
main/handlers.lua
main/main.lua
main/render.lua
main/tiled/side_scroll.lua
main/tiled/side_scroll.tmx
main/tiled/test_1.lua
main/tiled/test_1.tmx

index 91cde40e3df6523fee910a5ba788ee48ae482ff9..14f6879fa0932b11c9037c555027a3da17ec69b3 100644 (file)
@@ -44,13 +44,17 @@ function assets.integrate_object_layers(pmap)
       -- of a map will override the first position an object is drawn in (and worse).
       for ok,ov in pairs(new_layer.objects) do
         local object = assets.get_object(ov.name)
+
+        pmap[ov.name] = {}
+        pmap[ov.name].vec = vector.new_xy(ov.x, ov.y)
+        pmap[ov.name].name = ov.name
+        utils.shallow_dump('ovec', ov)
+
         if object and utils.flag_set(object.properties, PropertyFlag.HasSprite) then
           object.image = love.graphics.newImage(object.path)
+          -- Tiled does y values from the bottom of the sprite so pull up 1
+          pmap[ov.name].vec.y = ov.y - pmap.tileheight
         end
-        pmap[ov.name] = {}
-        -- Tiled does y values from the bottom of the sprite so pull up 1
-        pmap[ov.name].vec = vector.new_xy(ov.x, ov.y - pmap.tileheight)
-        pmap[ov.name].name = ov.name
       end
 
       new_layer.draw = function(self)
index 643dc3d3d7a7d57c781c3e4094efb149b09dd301..0af8f0900f4093dc7335865672456ce9da6313ee 100644 (file)
@@ -13,15 +13,14 @@ function love.handlers.map_changed(new_map_name)
   else
     print('invalid map: '..new_map_name)
   end
-  render.viewport = render.update_viewport()
 end
 
 -- Anything interested in a movement control should register its own handler here.
 function love.handlers.movement_control(key, value)
   player:movement_control(key, value)
 
-  render.map.topleft = render.map.active_camera(player)
   render.viewport = render.update_viewport()
+  render.map.active_map.topleft = render.map.active_camera(player)
 
   local n = math.random(1, assets.walk_sfx.size)
   love.audio.play(assets.walk_sfx[n])
index 47b15d2374cf4d096bccea9ad2d57949ad851468..4ac30d941f40cabe0c4979670ae0f9a0983dc540 100644 (file)
@@ -53,12 +53,10 @@ function love.draw()
     'replace', 1)
   love.graphics.setStencilTest('greater', 0)
 
-  render.map.active_map:draw(render.map.topleft.x, render.map.topleft.y, render.map.scale)
+  render.map.active_map:draw(render.map.active_map.topleft.x, render.map.active_map.topleft.y, render.map.scale)
 
   last_color = { love.graphics.getColor() }
   love.graphics.setColor(render.color.dark)
-  local adjust = render.worldspace_to_viewspace(player.vec)
-  love.graphics.rectangle('line', adjust.x, adjust.y, tile.w, tile.h)
-  --love.graphics.print(IntroMessage, math.floor((conf.window.width/16) * 1), math.floor((conf.window.height/16) * 1))
+  love.graphics.print(IntroMessage, math.floor((conf.window.width/16) * 1), math.floor((conf.window.height/16) * 1))
   love.graphics.setColor(last_color)
 end
index 3c79517d2586b30c1f08e5e520705ba21a39a00d..39c313164599770268928666a0714a1914256f50 100644 (file)
@@ -4,7 +4,7 @@ assets = require('assets')
 conf = require('conf')
 utils = require('utils')
 
-local render = {}
+render = {}
 
 ViewClass =
 {
@@ -29,7 +29,8 @@ render.color.light  = { love.math.colorFromBytes(229, 229, 229) }
 
 -- Map rendering info
 render.map = {}
-render.map.topleft = { x = 0, y = 0 }
+render.map.active_map = {}
+render.map.active_map.topleft = nil --{ x = 0, y = 0 }
 render.map.scale = 2.0
 render.map.active_map = nil
 
@@ -52,6 +53,7 @@ function render.activate_map(new_map_name)
     render.map.active_map = new_map
     render.map.scale = new_map.args.scale
     render.active_viewclass = render.ViewClassData[new_map.properties.viewclass]
+    render.viewport = render.update_viewport()
 
     -- Find all stored objects in the map we're switching to, and update their positional
     -- info with the unique copy stored in each map.
@@ -60,8 +62,8 @@ function render.activate_map(new_map_name)
       if object_in_map then
         object.vec = object_in_map.vec
         if object_in_map.name == 'Player' then
-          render.map.active_map.first_loop = true
-          render.map.topleft = render.map.active_camera(object)
+          render.map.active_map.first_loop = (render.map.active_map.topleft == nil)
+          render.map.active_map.topleft = render.map.active_camera(object)
         end
       end
     end
@@ -96,26 +98,6 @@ function render.update_viewport()
   return new_viewport
 end
 
--- Convert an absolute position in the map/gameworld
--- to where it would show up in the viewport.
-function render.worldspace_to_viewspace(world_position)
-  local view_position = utils.shallow_copy(world_position)
-  local tile = {
-    w = render.map.active_map.tilewidth ,
-    h = render.map.active_map.tileheight,
-  }
-
-  local offsets =
-  {
-    x = (render.viewport.ex * math.floor((render.map.scale * world_position.x) / render.viewport.ex)),
-    y = (render.viewport.ey * math.floor((render.map.scale * world_position.y) / render.viewport.ey)),
-  }
-  view_position.x = (render.map.scale * world_position.x) + (render.viewport.ox) - offsets.x
-  view_position.y = (render.map.scale * world_position.y) + (render.viewport.oy) - offsets.y
-
-  return view_position
-end
-
 render.CameraClass = {
   -- Constantly place the player in the dead center of the window
   PlayerInMiddle = 1,
@@ -152,27 +134,30 @@ function(focus)
     h = render.map.active_map.tileheight * render.map.scale,
   }
 
+  local cf = utils.shallow_copy(render.map.active_map['CameraFocus'].vec)
+  cf.x = cf.x * render.map.scale
+  cf.y = cf.y * render.map.scale
+
   -- On the first focusing of a map in this mode, find the map's CameraFocus object
   -- and use that for our topleft
   if render.map.active_map.first_loop then
     render.map.active_map.first_loop = false
     return
     {
-      x = render.map.active_map['CameraFocus'].vec.x + (tile.w / 2),
-      y = render.map.active_map['CameraFocus'].vec.y + (tile.h),
+      x = -render.map.active_map['CameraFocus'].vec.x + (tile.w / render.map.scale),
+      y = -render.map.active_map['CameraFocus'].vec.y + (tile.h / render.map.scale),
     }
   end
 
-  local new_topleft = render.map.topleft
-  local viewspace_focus = render.worldspace_to_viewspace(focus.vec)
+  local new_topleft = utils.shallow_copy(render.map.active_map.topleft)
 
-  if ((focus.vec.heading == utils.Headings.East) and viewspace_focus.x <= render.viewport.ox) then
+  if ((focus.vec.heading == utils.Headings.East) and (((focus.vec.x * render.map.scale) - cf.x) % render.viewport.ex) == 0) then
     new_topleft.x = new_topleft.x - (render.viewport.ex / render.map.scale)
-  elseif ((focus.vec.heading == utils.Headings.West) and viewspace_focus.x >= render.viewport.ex) then
+  elseif ((focus.vec.heading == utils.Headings.West) and (((focus.vec.x * render.map.scale) - cf.x) % render.viewport.ex) == (render.viewport.ex - tile.w)) then
     new_topleft.x = new_topleft.x + (render.viewport.ex / render.map.scale)
-  elseif ((focus.vec.heading == utils.Headings.South) and viewspace_focus.y <= render.viewport.oy) then
+  elseif ((focus.vec.heading == utils.Headings.South) and (((focus.vec.y * render.map.scale) - cf.y) % render.viewport.ey) == 0) then
     new_topleft.y = new_topleft.y - (render.viewport.ey / render.map.scale)
-  elseif ((focus.vec.heading == utils.Headings.North) and viewspace_focus.y >= render.viewport.ey) then
+  elseif ((focus.vec.heading == utils.Headings.North) and (((focus.vec.y * render.map.scale) - cf.y) % render.viewport.ey) == (render.viewport.ey - tile.h)) then
     new_topleft.y = new_topleft.y + (render.viewport.ey / render.map.scale)
   end
   return new_topleft
index f8c89a36b94450ff387b78718ed9c857967e0b23..063ae60f8ae5c1dec26123fd7ae37e3c370164b3 100644 (file)
@@ -108,11 +108,11 @@ return {
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+        873, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        872, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        871, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        870, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+        869, 870, 871, 872, 873, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
       }
     },
     {
index d1f2c250b3b4334934b235d05ddb9592cd89e417..2fb186173b224ba4d748b78eb093b4f6294e95d7 100644 (file)
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+873,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+872,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+871,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+870,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+869,870,871,872,873,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
 </data>
  </layer>
  <layer id="3" name="CityWalls_bg" width="30" height="20">
index 39600e8a1b1aeb9d0ec503dabe9a3e2b47f0a9e4..be6d3cc67a1ea796cc87ea596d6fd93fc1653860 100644 (file)
@@ -236,8 +236,8 @@ return {
           name = "Player",
           type = "",
           shape = "rectangle",
-          x = 16,
-          y = 32,
+          x = 80,
+          y = 160,
           width = 16,
           height = 16,
           rotation = 0,
@@ -250,8 +250,8 @@ return {
           name = "CameraFocus",
           type = "Meta",
           shape = "point",
-          x = 0,
-          y = 0,
+          x = 32,
+          y = 48,
           width = 0,
           height = 0,
           rotation = 0,
index 31cc2aeb26054b5b85015c02a020aa306f349ea1..de6deaaa444aea571f4299ac22d06d10ba724934 100644 (file)
 </data>
  </layer>
  <objectgroup id="2" name="Object Layer 1">
-  <object id="11" name="Player" gid="515" x="16" y="32" width="16" height="16"/>
-  <object id="13" name="CameraFocus" type="Meta" x="0" y="0">
+  <object id="11" name="Player" gid="515" x="80" y="160" width="16" height="16"/>
+  <object id="13" name="CameraFocus" type="Meta" x="32" y="48">
    <point/>
   </object>
  </objectgroup>