I started with one of the smooth tile scrolling tutorials, which obviously scrolled awesomely. I tried to mod it such that instead of a fixed map size, I would have endless scrolling (and world generation) and that's where things went downhill fast.
User stuff is broken, just in there as placeholders. What I cant figure out is 2 things:
Why does the map jitter when moving left and right fairly quickly?
Why does the map offset so bad that you see black on the left? (Right is messed too, dont know why yet, and I think solving the first question will probably fix this too!)
If anyone can spot the obvious I would be very grateful!
Code: Select all
local player = {}
--hold player level objects
local layer
local tileQuads = {}
local screen = {}
--holds the info on what tiled objects the world has
local knownMap = {}
--spriteBatch for the level up to ground level and buildings.
local tileSet
--hack for now to turn white into a transparent color
function loadTransparent(imagePath, transR, transG, transB)
imageData = love.image.newImageData( imagePath )
function mapFunction(x, y, r, g, b, a)
if r == transR and g == transG and b == transB then a = 0 end
return r,g,b,a
end
imageData:mapPixel( mapFunction )
return love.graphics.newImage( imageData )
end
function getQuad(obj, x, y, tilesetImage)
obj.tile = love.graphics.newQuad(x * screen.tileSize, y * screen.tileSize,
screen.tileSize, screen.tileSize, tilesetImage:getWidth(), tilesetImage:getHeight())
end
--rounds method
function round(num)
if num >= 0 then
return math.floor(num+.5)
else
return math.ceil(num-.5)
end
end
function love.load()
screen.width = 900
screen.height = 650
screen.tileSize = 32
screen.tileDisplayWidth = math.floor(screen.width/screen.tileSize)
screen.tileDisplayHeight = math.floor(screen.height/screen.tileSize)
screen.posX = 0
screen.posY = 0
screen.lastMovedX = 0
screen.lastMovedY = 0
screen.tileOffsetX = 0
screen.tileOffsetY = 0
--set screen res
love.window.setMode(screen.width,screen.height,{fullscreen=false,resizable=false})
--setup map max tiles
--map.width = 60
--map.height = 60
--load tileset
tilesetImage = loadTransparent( "tileset.png",255,255,255 )
tilesetImage:setFilter("nearest", "linear") -- this "linear filter" removes some artifacts if we were to scale the tiles
for x = 1, 6 do
tileQuads[x] = {}
tileQuads[x].obstacle = false
tileQuads[x].removeable = true
end
-- grass
getQuad(tileQuads[1],5,18,tilesetImage)
-- grass flower
getQuad(tileQuads[2],6,18,tilesetImage)
-- grass rock
getQuad(tileQuads[3],4,18,tilesetImage)
tileQuads[2].obstacle = true
-- gras pebble
getQuad(tileQuads[4],5,19,tilesetImage)
-- manhole -currently our 'player'
getQuad(tileQuads[5],10,26,tilesetImage)
--dirt
getQuad(tileQuads[6],5,15,tilesetImage)
--setup spritebatch
tileSet = love.graphics.newSpriteBatch(tilesetImage,screen.tileDisplayWidth*screen.tileDisplayHeight,"dynamic");
--setup initial layer, can support 1000 objects
layer = love.graphics.newSpriteBatch(tilesetImage,1000,"dynamic");
--setup player initial position
player.x = math.floor(screen.tileDisplayWidth/2)
player.y = math.floor(screen.tileDisplayHeight/2)
player.rate = 0.2
updateLayer()
updateMap()
end
--retuns obj indicating tileQuad number, depth (0 is ground, -1 is under, 1 is over)
function getTile(x,y)
--print("getTile for: "..x.." "..y)
-- x doesnt exist, create
if not knownMap[x] then
knownMap[x] = {}
end
-- y doesnt exist, create
if not knownMap[x][y] then
knownMap[x][y] = {}
knownMap[x][y].tile = math.random(1,3)
knownMap[x][y].depth = 0
--print("new Tile at: "..x.." "..y)
end
return knownMap[x][y]
end
function updateMap()
print("update map")
tileSet:clear()
for x = 0, screen.tileDisplayWidth + 1 do
for y = 0, screen.tileDisplayHeight + 1 do
--if x == 0 then
--print(x.." "..screen.posX.." "..round(x+screen.posX).." "..x*screen.tileSize)
--end --print(x+math.floor(screen.posX))
tileSet:add(tileQuads[getTile(round(x+screen.posX),math.floor(screen.posY)+y).tile].tile,
x*screen.tileSize,y*screen.tileSize)
end
end
end
function updateLayer()
layer:clear()
layer:add(tileQuads[5].tile,player.x*screen.tileSize,player.y*screen.tileSize)
end
--so generally the player will be in the middle of the screen
--we can calculate when to move the map vs the screen.
function move(dx,dy)
--calc new position of player
x = player.x + dx
y = player.y + dy
-- TODO: collision detection goes here
player.x = x
player.y = y
moveMap(dx,dy)
end
function moveMap(dx,dy)
oldX = screen.posX
oldY = screen.posY
screen.posX = screen.posX + dx
screen.posY = screen.posY + dy
--print(screen.posX..screen.posY)
screen.tileOffsetX = round((1-screen.posX%1)*screen.tileSize)
print(screen.posX.." "..(1-screen.posX%1).." "..(screen.tileSize*(1-screen.posX%1)))
print("tileSet will render x starting at: "..screen.tileOffsetX)
print("moveMap: "..screen.posX.." "..screen.lastMovedX.." "..screen.posX-screen.lastMovedX.." "..math.abs(screen.posX-screen.lastMovedX))
--update tileSet only if we moved x or y by a whole unit from lastMoved
if math.abs(screen.posX - screen.lastMovedX) >= 1 then
screen.lastMovedX = round(screen.posX)
--screen.tileOffsetX = 0
updateMap()
elseif math.abs(screen.posY-screen.lastMovedY) >= 1 then
screen.lastMovedY = round(screen.posY)
updateMap()
end
end
function love.update(dt)
if love.keyboard.isDown("up") then
move(0, -player.rate * screen.tileSize * dt)
end
if love.keyboard.isDown("down") then
move(0, player.rate * screen.tileSize * dt)
end
if love.keyboard.isDown("left") then
move(-player.rate * screen.tileSize * dt, 0)
end
if love.keyboard.isDown("right") then
move(player.rate * screen.tileSize * dt, 0)
end
end
function love.draw()
love.graphics.draw(tileSet,screen.tileOffsetX,round(-(screen.posY%1)*screen.tileSize),0,1,1)
--love.graphics.draw(layer,(screen.posX%1)*screen.tileSize,(screen.posY%1)*screen.tileSize,0, 1,1)
love.graphics.draw(layer,(screen.posX%1),(screen.posY%1),0, 1,1)
love.graphics.print("FPS: "..love.timer.getFPS(), 10, 20)
love.graphics.print("Player: "..player.x.." "..player.y, 10, 30)
love.graphics.print("SPOS: "..screen.posX.." "..screen.posY, 10, 40)
love.graphics.print("offset: "..screen.tileOffsetX.." "..round(-(screen.posY%1)*screen.tileSize),10,50)
love.graphics.print("Mod: "..screen.posX%1, 10, 60)
end
function love.keypressed(key)
print(key)
if key == 'escape' then
love.event.push("quit")
end
end