Scrolling a tile map

Hi All,
Haven’t posted for a while - life sometimes just takes over. But - I still managed to play a little and, in doing so, I dug into some old projects that I never finished. One of them was a tile map that I wanted to complete. I managed to get most of it running but ran into a problem when I wanted to slowly scroll a cell width or height at a time. Delved into Tweens but me and them never seem to get on. So I considered several alternatives - mainly grouped round scrolling a sprite one or several pixels at a time.

I thought my options were:

  1. rebuild the map with sprites moving it several pixels at a time, by filling out each of the sprites directly, in a couple of loops.
  2. Building a larger sprite up, with set context() and scrolling that then rebuilding the sprite once one of the directional limits was met. Masking the peripheral sprites out on screen.
  3. Building the whole sprite map up and scrolling that - a total of 3200 separate sprites in an 80 x 40 grid.

Got most of them to work but feel that the latter will be heavy on memory (each small sprite is 64 x 64 pixels).

Just wondered how other members have dealt with this?

Also, I ran into an old problem when I tried to move the map with the Touched() function. I would like to be able to have an extended touch so the map moves smoothly, but the only way I can do that is by moving my finger, whilst touching the screen, to facilitate smooth movement. Hence my initial interest in Tweens.

Can anybody point out posted routines to help in this and will V4 enable better Touched() options - most of the previous posts I’ve seen are quite involved. The simplest option seemed to be using CurrentTouch() within the Draw() function. Are there any plans to extend the facility of CurrentTouch() ?

Have you considered using mesh() and a texture atlas combined with translate() calls to move the map? The texture atlas could also be auto-generated at runtime using context()

If you consider generating even larger tile maps, I’d suggest splitting the map into chunks (e.g. 32x32 tiles) and generating the corresponding meshes and translating them appropriately as you scroll around the map. That should reduce memory usage while allowing for potentially huge tilemaps.

Hi @Steppers - I hadn’t considered using translate() but that does sound like a good option. What I was doing was making a submap of 11 by 11 sprites and then displaying it as a sprite centred on the screen. I prepared a mask with the border black (1 sprite in diameter) and transparent centre. so you could move on sprite distance in any direction. I used an offset to move the sprite 2 pixels at a time to give gradual motion using buttons but can’t get tweens to work so a simple touch would only move one substep at a time. I even tried @dave1707’s tween class but struggled to get it working.

Does building a mesh have any advantages over that ?

Bare bones of what you might be after? No tweening but smooth scrolling. Should be straightforward to add a tween to shift the offset values by multiples of 64 if you’re going for a dungeon crawler vibe

-- Scroll Test
viewer.mode=FULLSCREEN
-- Use this function to perform your initial setup
function setup()
    spd=10
    touches={}
    tileimg={asset.builtin.Blocks.Cactus_Side,asset.builtin.Blocks.Dirt_Sand,asset.builtin.Blocks.Cotton_Blue}
    map={}
for i=1,80 do
        map[i]={}
        for j=1,40 do
            map[i][j]= math.random(3)
        end
    end
    
    offset=vec2(0,0)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)
pushMatrix()
    translate(offset.x,offset.y)
    for i=1,80 do

        for j=1,40 do
sprite(tileimg[map[i][j]],i*64,j*64,64)
        end
    end

    popMatrix()
    
    for i,t in pairs(touches) do
        
        if t.x>WIDTH*0.6 then offset.x=offset.x-spd elseif t.x<WIDTH*0.4 then
            offset.x=offset.x+spd
        end
        
        if t.y>HEIGHT*0.6 then offset.y=offset.y-spd elseif t.y<HEIGHT*0.4 then
            offset.y=offset.y+spd
        end
    end
    
end

function touched(touch)
    if touch.state==ENDED or touch.state==CANCELLED then
        touches[touch.id] = nil
    else
        touches[touch.id] = touch
    end
end


Now with single tile tweening

-- Scroll Test
viewer.mode=FULLSCREEN
-- Use this function to perform your initial setup
function setup()
    spd=0.4
    touches={}
    moving=false
    tileimg={asset.builtin.Blocks.Cactus_Side,asset.builtin.Blocks.Dirt_Sand,asset.builtin.Blocks.Cotton_Blue}
    map={}
for i=1,80 do
        map[i]={}
        for j=1,40 do
            map[i][j]= math.random(3)
        end
    end
    
    offset=vec2(0,0)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)
pushMatrix()
    translate(offset.x,offset.y)
    for i=1,80 do

        for j=1,40 do
sprite(tileimg[map[i][j]],i*64,j*64,64)
        end
    end

    popMatrix()
    

        

    
end

function touched(touch)
    if touch.state==ENDED or touch.state==CANCELLED then
        touches[touch.id] = nil
        
        processTouch(touch)
    else
        touches[touch.id] = touch
    end
end

function processTouch(t)
    
if not moving then
    local ox=0
    local oy=0    
        if t.x>WIDTH*0.6 then ox=-64 elseif t.x<WIDTH*0.4 then
            ox=64
        end
        
        if t.y>HEIGHT*0.6 then oy=-64 elseif t.y<HEIGHT*0.4 then
oy=64
        end
    

    tween(spd,offset,{x=offset.x+ox,y=offset.y+oy},    -- time, start variable, end position
    {easing=tween.easing.quadInOut,loop=tween.loop.once},function() moving=false end) 
    
    moving=true
    
   end 
end

@West - thanks for htese examples - will try now to incorporate them in my project. Will feed back on them.

p.s. Just remembered clip() when I was searching Translate(). Looks like I may not need to mask !

Thanks again.

@West - tried out both your routines and solved my problem thanks.

Also clipping works which made my project simpler and less complicated.

@Bri_G glad these worked for you!

@Bri_G I don’t know if this would help or not, but here’s something I posted long ago. Do a search for “starter game 4”. Move your finger on the screen to scroll the map, use the arrows to move the guy.

@dave1707 - thanks for that. Looking at the list of posts that ‘starter game’ search generated just shows how much you’ve put into Codea. Some of the posts also show up changes in Codea - an interesting one from touch() is that MOVING was a condition that looks like it’s not parsed as a command as it doesn’t adopt the command colour. Suggesting it was either dropped or is not on the command list anymore, but still works. What say you on that @Simeon ?