In need of a simple sprite sheet

I’ve been exploring ofxSpriteSheetRenderer but I think its started off being too complicated for most beginners.

All I would like from a sprite sheet class is to load an image, set rect areas for sub images that I can reference by an id/name. I don’t need animation timing control over sprites, or the ability to build sprite sheets from code.

This looks like a really useful bit of software: www.texturepacker.com

My attempt to do this with ofxSpriteSheetRenderer is leading to unknown issues, partly because its hard to get started probably.

So far I’ve done;

  
  
// .h  
        LinearTexture myTexture;  
        ofxSpriteSheetRenderer * spriteRenderer;  
  
// .cpp setup  
    myTexture.loadTexture("test.png", GL_RGBA);  
    spriteRenderer->loadTexture(&myTexture);  
    bool ok = spriteRenderer->addTile(200.0, 200.0, 500, 501, 0, 100, 200);  
  

Does anyone have an example of how to do this properly? Zachg? Would be much appreciated.

Cocos2d seems a little easier to understand
http://www.raywenderlich.com/1271/how-to-use-animations-and-sprite-sheets-in-cocos2d

An ideal spriteSheet addon that is simple to use could look like this:

  
  
spriteSheet.loadImage("blah.png");  
spriteSheet.addTile("myname", x, y, w, h);  
  

Then it would be easy to have a function that loads different xml formats, texturePacker native or cocos2d, then cycle through and add the tiles.

Does anyone have any thoughts on this?

All the best

Ok so I need to get a solution for sprite sheets working now, as too many images really isn’t good practice & sprite sheets would be cleaner/faster etc.

I’m digging around in ofxSpriteSheetRenderer to see how it works, to then strip this down to basics.

I notice it uses verts & colors in a big array. Do you see any reason not to use 1 ofMesh per sprite?

That should work, but keep in mind that there is no support in ofMesh for QUADS or QUAD_STRIP.

You could render a single quad and shift the texture coords around based on your index in the animation. That should be lighter than using an ofMesh.
Will you need color per vertex? Seems like you can just set ofColor(255); before calling the draw function.

So I’m having an issue getting started & hope someone who knows meshes/textures can help. This is on iOS by the way.

My class looks like this:

  
  
class ofxSpriteSheet{  
	public:  
		ofxSpriteSheet();  
        void draw();  
  
        void loadImage(string file);  
        void addSprite(string name, int x, int y, int w, int h);  
      
    protected:  
        void addPoint(int x, int y);  
        ofMesh      mesh;  
        ofTexture   texture;  
};  
  

in testApp i do:

  
  
    spriteSheet.loadImage("data/testsprites2.png");      
    spriteSheet.addSprite("mysprite", 2, 2, 1120, 1146);  
  

The file is a transparent 32bit png 2048x2048 in size.

  
  
// --------------------------------------------------------------------------------------  
ofxSpriteSheet::ofxSpriteSheet() {  
      
    mesh.setMode( OF_PRIMITIVE_TRIANGLES );  
    mesh.setupIndicesAuto();  
      
}  
  
// --------------------------------------------------------------------------------------  
void ofxSpriteSheet::draw(){  
      
    // draw mesh with texture  
    ofEnableAlphaBlending();  
	ofSetColor(255, 255, 255);  
	texture.bind();  
	mesh.draw();  
	texture.unbind();  
    ofDisableAlphaBlending();  
      
    // draw wireframes  
    ofSetColor(0,0,0);  
    ofNoFill();  
	mesh.drawWireframe();  
	  
    // draw texture small somewhere to make sure ok  
    ofEnableAlphaBlending();  
	ofSetColor(255, 255, 255);  
    texture.draw(0,600,100,100);  
    ofDisableAlphaBlending();  
      
      
}  
// --------------------------------------------------------------------------------------  
void ofxSpriteSheet::loadImage(string file){     
      
      
    ofImage loader;  
    loader.setUseTexture(false);  
    loader.loadImage(file);  
    texture.allocate(loader.getWidth(), loader.getHeight(), GL_RGBA);  
    texture.loadData(loader.getPixels(), loader.getWidth(), loader.getHeight(), GL_RGBA);  
  
      
}  
  
// --------------------------------------------------------------------------------------  
void ofxSpriteSheet::addSprite(string name, int x, int y, int w, int h){  
      
    // triangle 1  
    addPoint(x, y); // top-left  
      
    addPoint(x+w, y); // top-right  
      
    addPoint(x, y+h); // bottom-left  
      
    // triangle 2  
    addPoint(x+w, y); // top-right  
      
    addPoint(x, y+h); // bottom-left  
      
    addPoint(x+w, y+h); // bottom-right  
   
      
}  
// -----------------------------------------  
void ofxSpriteSheet::addPoint(int x, int y){  
      
    // vertex  
    ofVec3f v;  
    v.x = x;  
    v.y = y;  
    v.z = 0;  
    mesh.addVertex(v);  
  
    // text coord  
    ofVec2f t;  
    t.x = x;  
    t.y = y;  
    mesh.addTexCoord(t);  
      
    // color  
    ofFloatColor c;  
    c.set(255.0, 255.0, 255.0);  
    mesh.addColor( c );  
      
}  
  

So when I try the above code, then call draw(), I can see the mesh of two triangles but no texture binded to the mesh (just empty space).

Any ideas what I am doing wrong most appreciated.

Many thanks

Try texture.getTextureReference().bind(); instead of texture.bind().

I’m not 100% if that’s the fix, but it may be.

I’m pretty sure texture.bind() should work. I tried your suggestion and it says:

No member named ‘getTextureReference’ in ‘ofTexture’

Maybe something iOS specific that could be going wrong? Any tips of working with textures & mesh on iOS? Does the code posted above look right?

Thanks

Ah sorry, I was confusing it with the fbo getTextureReference (since it has both bind() and getTextureReference().bind()).

I can try testing your code later today maybe. It looks correct from looking over it though.

Also, there’s an ofMesh example on the OF develop github: https://github.com/openframeworks/openFrameworks/blob/develop/examples/gl/vboExample/src/testApp.cpp

Maybe that can help a bit. It could be somethings of when you’re using ofTexture. Maybe try first using the ofImage directly like in the example.

Are they ARB textures? Maybe the tex coords need to be normalized?

I just compiled the code and it worked for me for a .png of size 256x256. Maybe it is the .png export settings? Here is the example project, with a sample sprite sheet downloaded from google. :slight_smile:

I’m surprised that you see the triangles, the coord 1120, 1146 should render those tex coords, but will also draw your triangles in that location. Is your window size larger than those dimensions?

[Simple Sprite Sheet.zip](http://forum.openframeworks.cc/uploads/default/2340/Simple Sprite Sheet.zip)

Thanks all.

@Nick that image didn’t work for me either. You testing on desktop or iOS?

@seth ofImage.bind() didn’t work either.

@Nick so an ARB texture is one that isn’t power of 2? Isn’t 256 x 256 power of 2 and therefore not ARB?

Anyway, I changed the texture coords to be normalized and it works

  
  
// text coord  
ofVec2f t;  
t.x = x / (float)imageWidth;  
t.y = y / (float)imageHeight;  
mesh.addTexCoord(t);  
  

Any ideas as to why it did? Do you always have to use norm text coords on iOS?

thanks

So I have posted my progress so far here
https://github.com/chrisoshea/ofxSpriteSheet/tree/master/src

For each sprite, I have a spriteType class that holds its position, as well as the first index used when creating the mesh. For each sprite it uses 6 vertices, so every time a sprite is added it increments the indices by 6.

You call setPosition() on a sprite name, which basically pulls out the first index then changes the mesh for index+6 points to match the new position.

What I don’t understand, and mesh gurus might be able to advise:

  1. layers. how can you control which order sprites are drawn in? If the whole sprite sheet is just 1 mesh. Its the highest indices drawn last? Should I have some layer control that basically shifts the indices around to match the layer it should be on?

  2. if I want to rotate a sprite, I basically need to rotate the vertices that belong to a sprite around a point. any tips on that?

  3. is it possible to hide some vertices (hide a sprite) so that its not drawn to the screen? or should i just draw it far off screen so you dont see it, i.e. by setting the position to be -1000 or something?

Would be great to hear what you think,

many thanks

Ok so I’ve added rotating sprites now
https://github.com/chrisoshea/ofxSpriteSheet/commit/49c4210fb467c75a239debee1e0de888031a7da9

I’m resurrecting this, because I don’t think it really does what Chris wanted it to. I’ve forked it on github but I’m wondering whether I should just make it ofxTextureAtlas as my needs/goals are:

  • load an atlas created with Texture Packer
  • populate a list of sub-images (“sprites”) that I can refer to by name, maybe get an ofImage* out
  • render efficiently but flexibly

Maybe make it a different thing if it isnt the same as mine anymore? Would be interested to see whats changed.

@chrisoshea can you post a simple example how to use your sprite addon? that would be awsome. only the neccessary steps which are needed…maybe?
I am missing something and I am not sure what…