But in fact, a video is nothing more than rendering a texture each frame. If you are reusing that frame texture like an atlas, it is basically the same.
You can do instanced rendering, but you have to code your own solution. There is no support for that in the engine.
This seems like the easiest way to modify the existing code for a quick test, but the only sprite I see is the last one. Is this in your ::draw() method for your layer?
Because it really isn’t a tile based world. I used that as an example to make it clear what I was trying to do. Then as each person kept providing answers that didn’t work for my particular situation (3rd party video codec playback into a sprite) I had to keep providing more details than I thought I’d need for a response.
I’ve been writing games since the days of the C64 and Vic20, but what we are doing is NOT like how they handled it at all. Still, nice to see another long-time programmer on this site
Unfortunately that doesn’t help since the video is updating the sprites each frame. So I tried doing something similar to what you are doing, but in the update() function. I still only see one sprite being drawn instead of the 5x4 array that should be shown.
It was worth a shot. We can switch to sprite sheets instead of the videos, but then I will have to scale them down to fit them into reasonable sized texture sheets. This means poorer quality animations
I figured out a solution that doesn’t require a major rewrite of my code. I don’t know what the performance will be like on mobile devices, but the Windows build runs at 60 fps without any issues. Thanks to everyone that helped get me in the right direction.
I ported Crisis Mountain to the Vic20, and worked on “Save New York” (just some sound stuff) and “Spitball” for the C64. At Epyx I worked on “Rescue on Fractalus” and “Koronis Rift” for the Tandy Coco, and California Games on the PC, World Games and Winter Games for the Apple 2e.
You said we could use a TextureAtlas to basically use several instances of a node with different properties (position, etc) but with the same texture that would not incur in unnecessary openGL calls. Can you provide any simple example please?
I am currently using the solution suggested by @KJS but I am considering trying multiple Nodes if the performance is significantly better.
In 2,x there was batch node, which you had to feed with nodes/sprites, to group draw calls together. With version 3.x, there was auto batching introduced, so you don’t need to use a batch node anymore.
Basically the steps are as following:
Step 1: Create the asset for SpriteA(spriteA.png) and
SpriteB(spriteB.png).
Step 2: Pack those assets together into an atlas(there are free tools
and commercial tools available). The atlas is just one big asset with a data file, which represents the offsets of the single assets into the texture.
Step 3: Load in your atlas. cocos2d-x automatically loads the
atlas texture and the data file into the sprite cache and will
bind it as one single OpenGL texture.
Step 4: Use the single texture assets by calling it by their name.
cocos2d-x will read the assets as a sub-texture to the atlas by using
the offsets defined in the data file as UV coordinates.
This way OpenGL only has to bind the atlas and can group together the draw calls, as the texture state for different sprites is never changed(same texture for all sprites, but with different UV offsets).
The different sprites are created by triangle strips/degenerated strips.
With that setup, it will bind the atlas and use vertex pointers and texture pointers for drawing all those sprites in one draw call.
Step 1 and Step 2 is up to you E.g. spriteA.png and spriteB.png. Pack them into an atlas called myAtlas(the available packers support the cocos2d-x format and will generate myAtlas.png and myAtlas.plist(of course you can also pack to other formats like pvr).
Step 3:
// Get the SpriteFrameCache singleton
cocos2d::SpriteFrameCache *cache = SpriteFrameCache::getInstance();
// add the atlas to the SpriteFrameCache
cache->addSpriteFramesWithFile("myAtlas.plist");
// create the sprites form the atlas
// the string you pass to SpriteFrameCache, is the string of your asset you added to the atlas:
// spriteA.png and spriteB.png -> you can of course strip the suffix; we assume that we did that
Sprite *mySpriteA = Sprite::createWithSpriteFrameName("spriteA");
Sprite *mySpriteB = Sprite::createWithSpriteFrameName("spriteB");
// add them as childs
addChild(mySpriteA);
addChild(mySpriteB);
Now the two sprites will be drawn in one draw call, as they share the same texture(atlas), but use different UV coordinates.
Of course the same applies, if you have multiple instances of the same node/sprite with different properties like position or scale.
You can only group together draw calls, it the render state is not changed. E.g. different shaders require separate draw calls.
Thanks. Hoped it’s easy understandable and comprehensible…
You can do director->setDisplayStats(true);. It will show you the draw calls in the left corner of your app screen.
May you could report back, which is more performant/useful for you: The render to texture approach of @KJS or just using an atlas. Would be nice to see some numbers
So, I have been thinking about this and I don’t really like neither of the solutions presented. Doing that begin(), end(), render() loop is super slow on Android, but having to create several dummy nodes just doesn’t feel like a good solution either.
What did you do to handle this? We have a single Cocos2dx Sprite that needs to be drawn in multiple locations on the screen. Everything worked fine in 2.x, but we only ever see the last instance drawn in 3.x due to the change in the render code.
@miguel12345 Hi Miguel, can you by any chance post some code or maybe explain with more details on how you solved the issue? We really need this for some time now (we are still using v2 because of this). Thanks