Custom map loading technique

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
bobbymcbobface
Citizen
Posts: 52
Joined: Tue Jun 04, 2019 8:31 pm

Re: Custom map loading technique

Post by bobbymcbobface » Thu Aug 01, 2019 8:54 am

sphyrth wrote:
Mon Jul 29, 2019 11:31 am
It's been awhile since I last checked up on this, so I would ask you to show the whole code. As I remember it, the code I gave you was a twisted mess... because I have to look all over the functions as to what the code was doing in order... specifically:
1. Are the tilequads being added first? or are we defining the map first?
2. If we define the map first, doesn't that mean we have no tilequad definitions (rocks, trees, ground, etc) to check up on?
3. Since map definition different from map generation when should I define the tilequads?
ok, first of all here's my code so far it might be a bit messy because i was testing around:

Code: Select all

local tilesetImage
local tileSize = 32 -- size of tiles in pixels
local tileQuads = {} -- parts of the tileset used for different tiles
local tilesetSprite
local themap = {}
local map -- stores tiledata
local mapX, mapY -- view x,y in tiles. can be a fractional value like 3.25.
local mapWidth, mapHeight -- width and height in tiles
local dxx = 0
local dyy = 0

function tilequad(x, y, count)
   local start = #tileQuads + 1 -- The #<tablename> (in this case, the tablename is tileQuads) counts the number of max tiles.
                                           -- the +1 means we'll start at the number NEXT to the last tile.
                                           -- This means we won't override anything before the table.

   for i = start, start + count do
      tileQuads[i] = love.graphics.newQuad(x * tileSize, y * tileSize, tileSize, tileSize, tilesetImage:getWidth(), tilesetImage:getHeight())
   end
end

function setupTileset()
  tilesetImage = love.graphics.newImage( "mytileset.png" )
  --tilesetImage:setFilter("nearest", "linear")
  
  --tileQuads[1] = love.graphics.newQuad(0 * tileSize, 1 * tileSize, tileSize, tileSize,
  --tilesetImage:getWidth(), tilesetImage:getHeight())
  
  
  tilequad(0, 2, 1)   --grass
  tilequad(2, 2, 1)   --rocks
  tilequad(2, 3, 1)   --trees
  
  tilesetBatch = love.graphics.newSpriteBatch(tilesetImage, mapWidth * mapHeight)
end

function themap:load()
  setupMap()
  setupTileset()
  updateTilesetBatch()
  themap:moveMap(-150, 0)
end


function updateTilesetBatch()
  tilesetBatch:clear()
  for x=0, mapWidth do
    for y=0, mapHeight do
        tilesetBatch:add(tileQuads[map[x][y].tile], math.floor(map[x][y].x), math.
        floor(map[x][y].y))
    end
  end
  tilesetBatch:flush()
end

-- central function for moving the map
function themap:moveMap(dx, dy)
  for x = 0, mapWidth do
    for y = 0, mapHeight do
      map[x][y].x = map[x][y].x + dx
      map[x][y].y = map[x][y].y + dy
      --dxx = dxx + dx
      --dyy = dyy + dy
      
      -- Okay so I'm not "deleting" the tiles, but transferring their x and y coordinates
      
      --X
      if map[x][y].x < mapX - (tileSize / 2) then
         map[x][y].x = map[x][y].x + (tileSize * mapWidth)
      end
      if map[x][y].x > mapX + (mapWidth * tileSize) - (tileSize / 2) then
         map[x][y].x = map[x][y].x - (tileSize * mapWidth)
      end
      
      --Y
      if map[x][y].y < mapY - (tileSize / 2) then
         map[x][y].y = map[x][y].y + (tileSize * mapHeight)
      end
      if map[x][y].y > mapY + (mapHeight * tileSize) - (tileSize / 2) then
         map[x][y].y = map[x][y].y - (tileSize * mapHeight)
      end
    end
  end
  updateTilesetBatch()
end

function setupMap()
  -- We only need a tiny map for this example
  mapWidth = 60
  mapHeight = 60
  
  --Leaving a space on the right and topsides so we know if the tiles are being "deleted"
  mapX = -20
  mapY = -20
  map = {}
  for x=0, mapWidth do
    map[x] = {}
    for y=0, mapHeight do
      map[x][y] = { --Let's turn this into a table that stores 3 things:
        tile = love.math.random(1, #tileQuads), -- tile = love.math.random(1, #tileQuads) or tile = love.math.random(#tileQuads) since the default min is "1",
        x = x * tileSize,
        y = y * tileSize
      }
    end
  end
end

return themap, tilesetBatch
also as to answer your questions for my current code if you need them (well at least try to answer them :P)

1. i think the tilequads are being added first
2. blank (i don't really know for this one sorry)
3. best bet is at the top of the code and if that doesn't work keep moving the definition below another definition

i don't know if you wanted me to actually answer them but i thought it might be helpful ;)

edit: here's a cleaner version of my code

Code: Select all

local tilesetImage
local tileSize = 32 -- size of tiles in pixels
local tileQuads = {} -- parts of the tileset used for different tiles
local tilesetSprite
local themap = {}
local map -- stores tiledata
local mapX, mapY -- view x,y in tiles. can be a fractional value like 3.25.
local mapWidth, mapHeight -- width and height in tiles
local dxx = 0
local dyy = 0

function tilequad(x, y, count)
   local start = #tileQuads + 1 -- The #<tablename> (in this case, the tablename is tileQuads) counts the number of max tiles.
                                           -- the +1 means we'll start at the number NEXT to the last tile.
                                           -- This means we won't override anything before the table.

   for i = start, start + count do
      tileQuads[i] = love.graphics.newQuad(x * tileSize, y * tileSize, tileSize, tileSize, tilesetImage:getWidth(), tilesetImage:getHeight())
   end
end

function setupMap()
  -- We only need a tiny map for this example
  mapWidth = 60
  mapHeight = 60
  
  --Leaving a space on the right and topsides so we know if the tiles are being "deleted"
  mapX = -20
  mapY = -20
  map = {}
  for x=0, mapWidth do
    map[x] = {}
    for y=0, mapHeight do
      map[x][y] = { --Let's turn this into a table that stores 3 things:
        tile = love.math.random(1, #tileQuads), -- tile = love.math.random(1, #tileQuads) or tile = love.math.random(#tileQuads) since the default min is "1",
        x = x * tileSize,
        y = y * tileSize
      }
    end
  end
end

function setupTileset()
  tilesetImage = love.graphics.newImage( "mytileset.png" )
  --tilesetImage:setFilter("nearest", "linear")
  
  --tileQuads[1] = love.graphics.newQuad(0 * tileSize, 1 * tileSize, tileSize, tileSize,
  --tilesetImage:getWidth(), tilesetImage:getHeight())
  
  tilequad(0, 2, 1)   --grass
  tilequad(2, 2, 1)   --rocks
  tilequad(2, 3, 1)   --trees
  
  tilesetBatch = love.graphics.newSpriteBatch(tilesetImage, mapWidth * mapHeight)
end

function updateTilesetBatch()
  tilesetBatch:clear()
  for x=0, mapWidth do
    for y=0, mapHeight do
        tilesetBatch:add(tileQuads[map[x][y].tile], math.floor(map[x][y].x), math.
        floor(map[x][y].y))
    end
  end
  tilesetBatch:flush()
end

-- central function for moving the map
function themap:moveMap(dx, dy)
  for x = 0, mapWidth do
    for y = 0, mapHeight do
      map[x][y].x = map[x][y].x + dx
      map[x][y].y = map[x][y].y + dy
      --dxx = dxx + dx
      --dyy = dyy + dy
      
      -- Okay so I'm not "deleting" the tiles, but transferring their x and y coordinates
      
      --X
      if map[x][y].x < mapX - (tileSize / 2) then
         map[x][y].x = map[x][y].x + (tileSize * mapWidth)
      end
      if map[x][y].x > mapX + (mapWidth * tileSize) - (tileSize / 2) then
         map[x][y].x = map[x][y].x - (tileSize * mapWidth)
      end
      
      --Y
      if map[x][y].y < mapY - (tileSize / 2) then
         map[x][y].y = map[x][y].y + (tileSize * mapHeight)
      end
      if map[x][y].y > mapY + (mapHeight * tileSize) - (tileSize / 2) then
         map[x][y].y = map[x][y].y - (tileSize * mapHeight)
      end
    end
  end
  updateTilesetBatch()
end

function themap:load()
  setupMap()
  setupTileset()
  updateTilesetBatch()
  themap:moveMap(-150, 0)
end

return themap, tilesetBatch
I make games that run on potatoes :P

sphyrth
Party member
Posts: 108
Joined: Mon Jul 07, 2014 11:04 am
Contact:

Re: Custom map loading technique

Post by sphyrth » Thu Aug 01, 2019 10:48 am

Yup. It had something to do with doing things in proper order. So, here's themap:load() and I'll try to discuss the things I've done:

Code: Select all

function themap:load()
  -- From function setupMap()
  mapWidth = 60
  mapHeight = 60

  -- Switched the order from setupMap->setupTileset to setupTileset->setupMap
  setupTileset()
  setupMap()
  updateTilesetBatch()
  themap:moveMap(-150, 0)
end
1. setupTileset() goes first rather than setupMap(). The first problem was that the setupMap() didn't know what image to load first because it's trying to load rocks, trees, etc... that setupTileset() hasn't defined yet. Switching the order solves that problem.

2. setupTileset() needs mapWidth, and mapHeight. Those are in setupMap(). So this is where the twisting and turning of the code shows up. I don't know where to really put those things, so I just took out mapWidth = 60 and mapHeight = 60 from setupMap() and slapped it inside themap:load().

User avatar
bobbymcbobface
Citizen
Posts: 52
Joined: Tue Jun 04, 2019 8:31 pm

Re: Custom map loading technique

Post by bobbymcbobface » Thu Aug 01, 2019 1:40 pm

thankyou sphyrth this works perfectly :)

now all that's left is topdown collision and sorting out the camera on my game (https://love2d.org/forums/viewtopic.php?f=3&t=86895) but i think i'll spend time trying to work those out myself instead of instantly facing you with another nagging dilemma from me :)

Cya in a bit :ultrahappy:
I make games that run on potatoes :P

Post Reply

Who is online

Users browsing this forum: No registered users and 6 guests