[SOLVED] Tiled collision maps help
Posted: Sun Oct 20, 2019 1:57 pm
Hello dear forum users. Please have mercy on my soul if you dare to help me, as I am new to both Lua and Love2d. I am currently working on a top-down rpg zelda clone-ish. I will try to only show relevant pieces of code so you don't have to look at all of it
Importing the map is done via STI. It imports a tilemap done in Tiled. Very simple right? Which is then being updated and drawn to the screen.
Now, the player is being created, updated and drawn in it's own seperate class "player.lua" which looks like this...
Here I am using anim8 to animate the character, and windfield to create a collision box for the player which follows him wherever he goes. Everything so far works just as I want, producing this result if I choose to draw the collision boxes...
The problem comes when I try to implement collisionboxes for my map. The way I've figured out to do this is to loop through every object in my map.lua file an retrieve it's x and y cords. Then the loop also creates a new collision rectangle at those specific coordinates.
This works absolutely fine. The rectangles are placed where I want them to and the player collides with them just fine. The problem arose when I wanted to implement some kind of camera that follows the player around as he moved, scrolling the map accordingly. After testing library after library with my limited understanding for anything I came to this solution, which needed no library whatsoever
This achieves-ish what I want, as now when the player moves, the map does aswell, revealing the rest of the map depending on where you go. NOW, if you are still reading this, MY MAIN PROBLEM that I have been trying to fix for days now is to move my collision map along with my main map.lua. Which will not work the way I want. For some reason I can't post images in here so I will reply to my own post which the needed attachments and source code. Any help would be highly appreciated as I am slowly losing hope for this project.
Importing the map is done via STI. It imports a tilemap done in Tiled. Very simple right? Which is then being updated and drawn to the screen.
Code: Select all
function love.load()
map = sti("assets/maps/testmapbig.lua", {"box2d"})
end
function love.update(dt)
map:update(dt)
end
function love.draw()
map:draw(-dx, -dy, mapScale, mapScale)
end
Code: Select all
player = {}
player.width = 16
player.height = 23
player.ismoving = false
player.collider = world:newCircleCollider(width/2, height/2, 15)
--Creates a grid table and places spreadsheet into it
player.grids = {}
player.grids.walk = anim8.newGrid(player.width, player.height, sprites.linkSpriteSheet:getDimensions())
--Creates animations out of these grids
player.animations = {}
player.animations.walkDown = anim8.newAnimation(player.grids.walk('1-8', 1), 0.1)
player.animations.walkUp = anim8.newAnimation(player.grids.walk('1-8', 2), 0.1)
player.animations.walkRight = anim8.newAnimation(player.grids.walk('1-8', 3), 0.1)
player.animations.walkLeft = anim8.newAnimation(player.grids.walk('1-8', 4), 0.1)
--Stores players current animation
player.anim = player.animations.walkDown
function player:update(dt)
--Freeze animation if player isn't moving
if player.isMoving then
player.anim:update(dt)
end
local vectorX = 0
local vectorY = 0
playerX = player.collider:getX()
playerY = player.collider:getY()
--Keyboard direction checks for movement and changes animation
if love.keyboard.isDown("a", "left") then
vectorX = -1
player.anim = player.animations.walkLeft
end
if love.keyboard.isDown("d", "right") then
vectorX = 1
player.anim = player.animations.walkRight
end
if love.keyboard.isDown("w", "up") then
vectorY = -1
player.anim = player.animations.walkUp
end
if love.keyboard.isDown("s", "down") then
vectorY = 1
player.anim = player.animations.walkDown
end
player.collider:setLinearVelocity(vectorX * 100, vectorY* 100)
--Checks if player is moving
--(if players previous position if different from current position)
if vectorX == 0 and vectorY == 0 then
player.isMoving = false
player.anim:gotoFrame(1) -- Go to standing frame in current grid
else
player.isMoving = true
end
end
function player:draw()
local px = player.collider:getX()
local py = player.collider:getY()
--Sets stylesheet filter so scaling doesn't blur
sprites.linkSpriteSheet:setFilter('nearest', 'nearest')
--Draws current animation frame
player.anim:draw(sprites.linkSpriteSheet, px, py, nil, 2, 2, player.width/2, player.height/1.3)
end
The problem comes when I try to implement collisionboxes for my map. The way I've figured out to do this is to loop through every object in my map.lua file an retrieve it's x and y cords. Then the loop also creates a new collision rectangle at those specific coordinates.
Code: Select all
function love.load()
--Gets number of tables(objects) in currently loaded map
colliderLayer = map.layers[2].objects
--Loops through all objects and gets their respective x, y values
--this then creates a new collider rectangle at respective coordinates
for i, v in pairs(colliderLayer) do
local colliderObjectX = map.layers[2].objects[i].x
local colliderObjectY = map.layers[2].objects[i].y
colliderBox = world:newRectangleCollider(
(colliderObjectX*2+6), --Multiplies current cordinate by 2 too make up for map scaling in draw()
(colliderObjectY*2-28), --then adds specific numbers to allign them just perfect
20,
25)
colliderBox:setType('static')
end
end
Code: Select all
function love.draw()
dx = player.collider:getX() - (love.graphics.getWidth()/2)
dy = player.collider:getY() - (love.graphics.getHeight()/2)
love.graphics.scale(scale)
love.graphics.translate(-dx, -dy)
--Scales map to double size to fit screen
--Draws map and sets new scale
map:draw(-dx, -dy, mapScale, mapScale)
player:draw()
world:draw()
end