I created a simple code using Love2d that display a map created with Tiled (pixel art style), and draw a square as a player who can freely move across the map. However there is some jitter or flickering that occur only when I move the player. It's even more visible when the map use texture that show many lines (like fence, window etc.).
For movement I use:
local moveX, moveY = 0, 0
if love.keyboard.isDown("right") then moveX = 1 end
if love.keyboard.isDown("left") then moveX = -1 end
if love.keyboard.isDown("down") then moveY = 1 end
if love.keyboard.isDown("up") then moveY = -1 end
local norm = math.sqrt(moveX^2 + moveY^2)
if norm > 0 then
player.x = player.x + (moveX / norm) * player.speed * dt
player.y = player.y + (moveY / norm) * player.speed * dt
end
However if I replace the delta time dt with a fixed value of 0.01 and a player speed of 100 it's working well, but as soon as i use a real dt or a fixed dt of 0.01 with another speed (like 150) there is some flickering.
How can I move across a simple Tiled map in Love2D without flickering?
Here is my full code, the map.lua is just a simple tiled map exported to .lua within tiled.
local sti = require("sti")
local map
local player = {}
local camera = { x = 0, y = 0 }
-- Résolution virtuelle fixe
local virtualWidth, virtualHeight = 400, 320
local screenWidth, screenHeight = 800, 640
local canvas
function createCanvas()
canvas = love.graphics.newCanvas(virtualWidth, virtualHeight)
canvas:setFilter("nearest", "nearest")
end
function love.load()
love.window.setMode(screenWidth, screenHeight, {
resizable = true,
vsync = true
})
createCanvas()
map = sti("map.lua")
-- Joueur représenté par un simple carré
player.width = 32
player.height = 32
player.x = 0
player.y = 0
player.speed = 100
end
function love.update(dt)
-- dt=0.01
local moveX, moveY = 0, 0
if love.keyboard.isDown("right") then moveX = 1 end
if love.keyboard.isDown("left") then moveX = -1 end
if love.keyboard.isDown("down") then moveY = 1 end
if love.keyboard.isDown("up") then moveY = -1 end
local norm = math.sqrt(moveX^2 + moveY^2)
if norm > 0 then
player.x = player.x + (moveX / norm) * player.speed * dt
player.y = player.y + (moveY / norm) * player.speed * dt
end
-- Caméra centrée sur le joueur
camera.x = math.floor(player.x) - virtualWidth / 2
camera.y = math.floor(player.y) - virtualHeight / 2
map:update(dt)
end
function love.draw()
love.graphics.setCanvas(canvas)
love.graphics.clear()
love.graphics.push()
love.graphics.translate(-camera.x, -camera.y)
map:draw(-camera.x, -camera.y)
-- Dessiner le joueur (carré bleu)
love.graphics.setColor(0, 0, 1)
love.graphics.rectangle("fill", player.x, player.y, player.width, player.height)
love.graphics.setColor(1, 1, 1)
love.graphics.pop()
love.graphics.setCanvas()
-- Affichage du canvas avec mise à l’échelle fluide
local scaleX = screenWidth / virtualWidth
local scaleY = screenHeight / virtualHeight
local scale = math.min(scaleX, scaleY)
local offsetX = (screenWidth - virtualWidth * scale) / 2
local offsetY = (screenHeight - virtualHeight * scale) / 2
love.graphics.setColor(1, 1, 1, 1)
love.graphics.draw(canvas, offsetX, offsetY, 0, scale, scale)
end
function love.resize(w, h)
screenWidth = w
screenHeight = h
end
You can download my simple map.lua here