Timemap is above the player?

Tips on what to include in your question:
Mac SDK latest

Player should be on top of the tilemap but appears to be under it - not sure why
if I call the gfx.sprite.update() after the tile map the map is no longer visible only the player
Cant work out why the player (sprite) is not by default on top of the tilemap

import "CoreLibs/object"
import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"
import "CoreLibs/easing"
import 'CoreLibs/crank'

local gfx <const> = playdate.graphics
local geom <const> = playdate.geometry

-- player
local decelerate = true  -- whether we should decelerate or not
local playerShip = nil
local maxSpeed = 6
local thrustSpeed = 0


-- viewport
-- 400 x 240 screen
local xOffsetmin = 100
local xOffsetmax = 300
local yOffsetmin = 60
local yOffsetmax = 180
local levelOne = nil

function myGameSetUp()
    -- set up player
    playerShip = gfx.sprite.new()
    playerShip.polygon = geom.polygon.new(16,0, 24,16, 32,16, 16,32, 0,16, 8,16, 16,0)
    playerShip.ship_transform = geom.affineTransform.new()
    playerShip:moveTo(200,120)
    playerShip:setZIndex(50)
    playerShip:add()

    -- setup level map 
    imageTable = gfx.imagetable.new("images/bck")    
    assert(imageTable)
    levelOne = gfx.tilemap.new()
    levelOne:setImageTable(imageTable)
    levelOne:setSize(1,1)

    for y = 1,1 do
        for x = 1,1 do
            levelOne:setTileAtPosition(x,y,1)
        end
    end

    -- local grid = {1}
    -- levelOne:setTiles(grid, 5)
    -- gfx.sprite.setBackgroundDrawingCallback(
    --     function (x,y,width,height)
    --         levelOne:draw(0,0,400,240)
    --     end
    -- )
  
end

myGameSetUp()

function playerShip:update()
    -- draw the ship polygon to the sprite's image
    local img = gfx.image.new(32, 32)
    gfx.pushContext(img)
    gfx.drawPolygon(playerShip.polygon)
    gfx.popContext()
    playerShip:setImage(img)

    -- rotate the transform
    playerShip.ship_transform:rotate(playdate.getCrankChange(), 16, 16)
   
    -- apply the transform to the ship polygon
    playerShip.ship_transform:transformPolygon(playerShip.polygon)
  
    -- reset the transform so that crank change doesn’t accumulate over time
    playerShip.ship_transform:reset()
end

function playdate.upButtonDown()
    decelerate = false
    local function timerCallback()
        if (thrustSpeed < maxSpeed)
        then 
            thrustSpeed += 1 
        end
    end
    keyTimer = playdate.timer.keyRepeatTimer(timerCallback)
  end

function decelerateShip()
    if decelerate == true then
        if (thrustSpeed > 0) then
            thrustSpeed -= 1
        end
        if (thrustSpeed == 0) then 
            decelerate = false
        end
    end
end

function playdate.upButtonUp()
    decelerate = true
    thrustSpeed = 0
    keyTimer:remove()
    --end   
end

function playdate.update()
    local angle = playdate.getCrankPosition()
    local gravity = 1.5
    decelerateShip()
    local dx = thrustSpeed * math.sin(math.rad(angle))
    local dy = thrustSpeed *-1 * math.cos(math.rad(angle)) +gravity
    playerShip:moveBy(dx,dy)
    local spX, spY = playerShip:getPosition()
    -- print(spX, spY)
    local offSetX = 0
    local offSetY = 0
    if (spX < xOffsetmin) then
        offSetX = -dx
    end
    if (spX > xOffsetmax) then
        offSetX = dx
    end

    if (spY < yOffsetmin) then
        offSetY = -dy
    end

    if (spY > yOffsetmax) then
        offSetY = dy
    end

    -- gfx.setDrawOffset(offSetX, offSetY)
    -- print(offSetX, offSetY)
    
    playdate.timer.updateTimers()
   
    -- gfx.clear()
    gfx.sprite.update()   
    levelOne:draw(offSetX, offSetY) 
  
end

didnt realise needed to put the tile map into a sprite.. happy days :slight_smile:

2 Likes

Hi! What does this mean that you need to "put the tile map into a sprite"?
I'm running into the same issue.

You have to create a sprite and then do sprite:setTilemap(tilemap)

1 Like

@adamprocter or @Gamma
Can this be expanded on?

Do I have to put it in a sprite everytime it updates?

Option 1

local BUFFER_TILES = 20 
local TILES_ON_SCREEN = 15

local tiles = gfx.imagetable.new('assets/tilesprite') -- Getting Tiles
local map = gfx.tilemap.new() -- Creating Tilemap

map:setImageTable(tiles)
map:setSize(TILES_ON_SCREEN, BUFFER_TILES)

function initializeTiles()
    for row = 1, BUFFER_TILES do
        for column = 1, TILES_ON_SCREEN do
            local block = math.random(1,2)
            map:setTileAtPosition(column, row, block) -- Assigning tiles to tilemap
        end
    end
end

function playdate.update()
    local tileSprite = gfx.sprite.new() -- Creating a sprite to put the tilemap
    tileSprite:setTilemap(map)
    tileSprite:setZIndex(1000)

    gfx.sprite.update()   
end

Or can I put the tiles in a sprite then use that throughout the game?

Option 2

local BUFFER_TILES = 20 
local TILES_ON_SCREEN = 15


local tiles = gfx.imagetable.new('assets/tilesprite') -- Getting Tiles
local map = gfx.tilemap.new() -- Creating Tilemap
local tileSprite = gfx.sprite.new() -- Creating sprite for tiles

map:setImageTable(tiles)
map:setSize(TILES_ON_SCREEN, BUFFER_TILES)

function initializeTiles()
    for row = 1, BUFFER_TILES do
        for column = 1, TILES_ON_SCREEN do
            local block = math.random(1,2)
            map:setTileAtPosition(column, row, block) -- Assigning tiles to tilemap
        end
    end

  tileSprite:setTilemap(map) -- Assigning tilemap to sprite 
  tileSprite:setZIndex(1000)

end

function playdate.update()
    gfx.sprite.update()   
end

With option 1 I feel like I'm needlessly creating a sprite every frame which feels wrong.

With option 2, it feels like ok now the tiles are associated with a sprite, but now how do I manipulate the tileset? I don't see a sprite.getTileset() or anything so....

Can you please help me understand this a bit more?

Option 2 is the way to go imo, you’d change the tilemap by using your map variable that references the tilemap. The sprite should update automatically when the tilemap changes!