Howdy, Stranger!

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

Does Codea support sprite sheets?

edited September 2012 in Suggestions Posts: 3

From what I know sprite sheets save memory used or so I've heard. Wouldn't adding sprite sheet support be beneficial? How do you animate something in codea without a sprite sheet? Is it just redrawing the scene and the sprite being a different image in the animation?

Comments

  • today it's roll-your-own , or dig through the forums and find someone else's.

  • PTNPTN
    Posts: 39

    Try using meshes, and setting the texture coordinates...

  • edited September 2012 Posts: 666

    That's a good idea. Someone make a sprite sheet demo. I'm still trying to understand all these matrices and viewports.

  • Sprite sheets in codea don't save any memory.
    Codea uses a texture atlas for all textures (works just like a sprite sheet), but the issue some people face is speed. The idea being that managing your own sprite sheet will be faster than the inbuilt lookup of the entire texture atlas.
    But I have to say just calling each 'image' to draw for each frame is fast enough in my experience.

  • edited September 2012 Posts: 725

    Here's a demo of an animation from a sprite sheet using meshes. You probably want to ship out the sprite handling to a separate class, but this is just to demo the concept.
    You can get the sprite sheet here (hopefully!)
    http://db.tt/eMJa1tsS


    -- ZombieAnimationDemo -- by West -- Use this function to perform your initial setup function setup()      --load up the sprite sheet into a mesh -- in this case the sprite sheet contains 5 by 5 sprites, each 32 by 32 pixels -- the file is available from --http://db.tt/eMJa1tsS zombie=mesh() -- you may need to change this to the location where you save the file img=readImage("Dropbox:ZombieSpriteSheet") zombie.texture=img rows=5 --number of rows in the sprite sheet cols=5 -- number of columns in the sprite sheet sizex=64 -- width of the sprite image to display on screen - note this does not need to be the original pixel size sizey=64 -- height of the sprite image --set up some constants walkleft=0 walkright=1 turnlefttoright=2 turnrighttoleft=3 --set up some arrays to hold the animations animdelay=0 animdelaymax=3 animx={} animy={} movex={} movey={} --define the animation frames --starting from bottom left as 0,0, enter the column (animx) and row (animy) of the frame you want --walking left animx[0]={0,1,2,3,4,0,1,2} animy[0]={4,4,4,4,4,3,3,3} movex[0]={-1,-1,-1,-1,-1,-1,-1,-1} movey[0]={0,0,0,0,0,0,0,0} --walking right animx[1]={0,1,2,3,4,0,1,2} animy[1]={2,2,2,2,2,1,1,1} movex[1]={1,1,1,1,1,1,1,1} movey[1]={0,0,0,0,0,0,0,0} --turning left to right animx[2]={3,4,3} animy[2]={3,3,1} movex[2]={0,0,0} movey[2]={0,0,0} --turning right to left animx[3]={3,4,3} animy[3]={1,3,3} movex[3]={0,0,0} movey[3]={0,0,0} x=150  --initial  x coordinate of the sprite y=HEIGHT/2  -- initial y coordinate of the sprite state=walkleft -- initial state of the sprite curFrame=1 -- the initial frame of the animation in terms of the position in the animx and animy arrays speed=3 -- a factor by which to speed up the movement (alternatively change the values in movex but this provides greater flexibilty end -- This function gets called once every frame function draw()     -- This sets a dark background color      background(40, 40, 50)     --clear the mesh     zombie:clear() --cycle through the animation --add a delay to solw the animation down animdelay = animdelay + 1 if animdelay>animdelaymax then     --move to the next frame in the animation     curFrame = curFrame + 1     --check to see if this frame is past the end of the animation array for the current state and if so, reset     if curFrame>#animx[state] and state==turnlefttoright then         state=walkright         curFrame=1     elseif curFrame>#animx[state] and state==turnrighttoleft then         state=walkleft         curFrame=1     elseif curFrame>#animx[state] then         curFrame=1     end     --reset the animation delay counter     animdelay=0 end     --adjust the position according to the values in the movement arrays     x = x + movex[state][curFrame]*speed     y = y + movey[state][curFrame]*speed -- not needed in this demo as there is no vertical movement --check to see if the edges of the screen have been met if x>WIDTH-100 and state~=turnrighttoleft then     state=turnrighttoleft     curFrame=1 -- reset the animation elseif x<100 and state~=turnlefttoright then     state=turnlefttoright     curFrame=1 end     -- Do your drawing here      local idx=zombie:addRect(x,y,sizex,sizey)     zombie:setRectTex(idx,(animx[state][curFrame])/cols,(animy[state][curFrame])/rows,1/cols,1/rows)             --draw the mesh     zombie:draw() end
  • edited September 2012 Posts: 666

    Could't get the sheet, though i tried from my ipad and i wasn't logged in. Your public link does not go to your account.

  • Posts: 725

    Hmmm not sure how to post the link then

  • Posts: 725

    Ok this should now work. Have edited the original post above too

    http://db.tt/eMJa1tsS

  • Posts: 68

    I could copy and paste it on my ipad. Thank you for the really helpfull example.

  • Hi all,

    I tried this sample and it works fine but I get some artifacts at the top and bottom of the animated sprite in the form of a thin horizontal line. It's not that noticeable with the Zombie example since the colours are dark, but when I tried it with a more colourful image it was more noticeable.

    Has anyone got an idea why it might be happening?

    Paul.

  • Posts: 688

    If your running on a retina device then it might be due to the texture bleeding in from the edges. This is a common problem on a lot of high resolution graphic devices and the reason why texturepacker and similar tools allow for a degree of padding between elements - try shifting your texture u.v coords in by half a pixel

  • Yes, i'm running on iPad Air 1. You're also correct that my sprite sheet doesn't have any padding between elements. I'll try and fix that first in the sprite sheet image.

    Many thanks!

  • Posts: 1,976

    @osullivp You could also try noSmooth() to disable the smoothing that causes bleeding, but your graphics will be pixelated (I would assume that would be fine, people don't typically use high-res spritesheets).

  • dave1707dave1707 Mod
    Posts: 7,530

    Here's a version saving each image in a table. Tap the screen to move thru the images. It's possible the artifacts in the other code is caused by capturing some of the image above or below the current image.


    displayMode(FULLSCREEN) function setup() i=1 spriteMode(CORNER) img1=readImage("Dropbox:ZombieSpriteSheet") img2=image(80,80) setContext(img2) sprite(img1,0,0) setContext() tab={} count=0 for y=64,1,-16 do for x=1,64,16 do count=count+1 if count<20 then table.insert(tab,img2:copy(x,y,16,16)) end end end end function draw() background(40,40,50) sprite(img1,50,200,200) sprite(tab[i],350,200,200) end function touched(t) if t.state==BEGAN then i=i+1 if i>#tab then i=1 end end end
  • @dave1707 there's something wrong with your code. the tab[i] rendering looks terrible, and isn't extracting properly from the original sprite sheet. can you post a screen shot of what yours is supposed to look like when working properly?

  • dave1707dave1707 Mod
    Posts: 7,530

    @matkatmusic What is the size of the ZombieSpriteSheet that's in your Dropbox. It should have a size of 80 x 80 . That's what this code is set up for. If it still doesn't work, maybe I'll change the code to read the sheet from the link given above.

  • dave1707dave1707 Mod
    Posts: 7,530

    @matkatmusic As for what it's supposed to look like, the whole sprite sheet will be on the left of the screen and an individual character the same size of the sprite sheet will be on the right. Each time you tap the screen, the next character in the sprite sheet will be shown.

  • i see that, it's just way zoomed in on the right. like, i see a partial view of the dude's legs.

  • I fixed it. the spritesheet was 160x160

    function setup()
        i=1
        spriteMode(CORNER)
        img1=readImage("Dropbox:ZombieSpriteSheet")    
        img2=image( spriteSize(img1)  )    
        setContext(img2)
        sprite(img1,0,0)
        setContext()
        print( spriteSize( img1 ) )
        w,h = spriteSize( img1 ) 
        tab={}
        count=0
        for y=128,1,-32 do
            for x=1,128,32 do
                count=count+1
                if count<20 then
                    print( x, y, w/5, h/5 )
                    table.insert(tab,img2:copy(x,y,w/5,h/5))
                end
            end
        end
    
        counter = 1
        fr = 0
    end
    
    function draw()
        background(40,40,50)
        sprite(img1,50,200 )
        sprite(tab[counter],350,200)
        fr = fr + 1
        if( fr > 3 ) then 
            fr = 0
            counter = counter + 1
            if( counter > #tab ) then counter = 1 end
        end
    end
    

    the sprite sheet in question was one of those dropbox links above. not sure which one. it's whichever one was 160x160

  • dave1707dave1707 Mod
    Posts: 7,530

    @matkatmusic I guess that would explain the problem. I was looking at my code again and noticed that there's an error in it. The column of sprites on the very right of the sprite sheet aren't being shown. I guess I could fix it, but every sprite sheet is going to have it own unique code setup anyways.

Sign In or Register to comment.