Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

A single Mesh instead of 1001 sprites

edited December 2015 in Questions Posts: 116

Hey guys, now i have a little more time for Codea. So i started a new project, dont wanna to spoil it right now ;)

I said "No"! :p

So now I am trying to do a nice background scroll effect. Done it just with sprites, but now i am wondering how to do this with just a single mesh, and if this will be more efficient and productive than just sprites. Okay, just with colored rects, the mesh-method is a lot faster, but with textures... I can write the thing only with colored rects, what i am doing right now, but could you please give me a clue, how i should assign the texture to the mesh, if the mesh method is faster. Here is the code:

-- Back

function setup()
    parameter.integer("number_of_sprites", 1, 1000, 90, setupBack)
    parameter.integer("number_of_levels", 1, 20, 3, setupBack)
    setupBack()
end
function setupBack()
    back = Back()
end
function draw() 
    background(40, 40, 50)
    back:draw()
end

Back = class()

function Back:init()
    self.blocknum = number_of_sprites or 90
    self.levels = number_of_levels or 3
    self.blocks = {}
    for i = 1, self.blocknum do--initialize blocks
        local l = math.ceil((i/(self.blocknum+self.levels))*self.levels)--for three levels, 1 is back, big and slow, 3 is front, small and fast
        local s = math.random(300,800)/l--generate other attributes based on l
        local fracOf255 = math.floor(255/self.levels)
        local c = color(math.random(1,fracOf255)*l,math.random(1,fracOf255)*l,math.random(1,fracOf255)*l)
        table.insert(self.blocks, {size = s, speed = 750/s, col = c, x = WIDTH*(math.random()*2), level = l})
    end
end

function Back:draw()
    background(100, 121, 174, 255)
    for i, b in ipairs(self.blocks) do
        if b.x < -b.size then--spawn the block at the beginning, if it is out of screen
           b.x = WIDTH+WIDTH*(math.random()*2)
        end
        b.x = b.x - b.speed
        tint(b.col)
        sprite("Small World:Tree 1",b.x, 0, b.size, b.size)
        --sprite("Small World:Tree "..b.level,b.x, 0, b.size, b.size)
    end
end

P. S. Oh, and you can give me the full working copy too xD

Comments

  • dave1707dave1707 Mod
    edited December 2015 Posts: 7,676

    @TimurEke Nice effect. Because of the 3D scrolling effect, I don't think it's possible with one mesh.

    EDIT: Probably a mesh for each layer would work.

  • Posts: 735

    Have a look here for a single mesh example

    https://gist.github.com/Westenburg/5743643

  • Posts: 116

    @dave1707, i think i figured it out.

    -- Back
    
    function setup()
        parameter.integer("number_of_sprites", 1, 2000, 90, setupBack)
        parameter.integer("number_of_levels", 1, 40, 3, setupBack)
        setupBack()
    end
    function setupBack()
        back = Back()
    end
    function draw() 
        background(40, 40, 50)
        back:draw()
    end
    
    Back = class()
    
    function Back:init()
        self.mesh = mesh()
        self.mesh.texture = "Small World:Tree 1"
        self.blocknum = number_of_sprites or 90
        self.levels = number_of_levels or 3
        self.blocks = {}
        for i = 1, self.blocknum do--initialize blocks
            local l = math.ceil((i/(self.blocknum+self.levels))*self.levels)--for three levels, 1 is back, big and slow, 3 is front, small and fast
            local s = math.random(300,800)/l--generate other attributes based on l
           -- local fracOf255 = math.floor(255/self.levels)
            local fracOf255 = math.floor(223/self.levels)
            local c = color(32+math.random(1,fracOf255)*l,32+math.random(1,fracOf255)*l,32+math.random(1,fracOf255)*l)
            --local c = color(math.random(1,fracOf255)*l,math.random(1,fracOf255)*l,math.random(1,fracOf255)*l)
    
            table.insert(self.blocks, {size = s, speed = 750/s, col = c, x = WIDTH*(math.random()*2), level = l})
    
            self.mesh:addRect(0,0,s,s,0)-- coords will update at the first frame
            self.mesh:setRectTex(i,0,0,1,1) --
        end
    end
    
    function Back:draw()
        background(100, 121, 174, 255)
        for i, b in ipairs(self.blocks) do
            if b.x < -b.size then--spawn the block at the beginning, if it is out of screen
               b.x = WIDTH+WIDTH*(math.random()*2)
            end
            b.x = b.x - b.speed
            self.mesh:setRectColor(i, b.col)
            self.mesh:setRect(i, b.x, 0, b.size, b.size)
            --sprite("Small World:Tree "..b.level,b.x, 0, b.size, b.size)
        end
        self.mesh:draw()
    end
    
  • Posts: 2,020

    By far the fastest option for throwing 2D sprites around is to group them on to as few meshes as possible as rects, and move them around with setRect. A few things to be aware of though. First, if you're trying to place objects with different textures on the same mesh, you'll need to place those textures into a single image (called a Sprite sheet or a texture atlas). This isn't too hard to do.

    Second, you have limited control over the draw order: the most recently added rect will be drawn last and will appear on top of the other rects on the same sheet. If draw order is important (eg in an isometric or forced-perspective game), you can a) manipulate the draw order by changing the z value of the rect, though you will then run into issues with transparency if rects on the same sheet overlap, so you'll need a discard shader for that. Or b) dynamically assign the rects each frame.

  • dave1707dave1707 Mod
    edited December 2015 Posts: 7,676

    @TimurEke Nice, but I noticed some of the farther away sprites moving faster than the closer ones. An image that's moving faster shouldn't be behind a slower moving image.

    EDIT: I also noticed some images popping up on the screen. Need to create them off screen.

  • Posts: 116

    @dave1707, only random here xD, but when the images shouldnt pop up at the screen, the screen would be empty at the beginning. Or do you mean sprites transformed after being far left?

  • dave1707dave1707 Mod
    Posts: 7,676

    @TimurEke As I'm watching the images scroll to the left, occasionally I'll see an image pop on the screen on the right side instead of scrolling from off screen on the right side.

  • Posts: 116

    @dave1707 thanks for this bug, WIDTH*1.5+WIDTH*(math.random()*2) instead of WIDTH+WIDTH*(math.random()*2) fixes it

Sign In or Register to comment.