Multi-Sprite Objects (Tech Demo 5)
by Charlie Patterson · 05/29/2012 (9:01 pm) · 4 comments
I'm gonna keep this much shorter. Video is at the end as always.
(Also, if you enjoy this tech demo, please consider "paying forward" with a click on my game's like button, here: facebook.com/RednecksVsRobots. Gonna look for some funding soon and likes will help, I hope!)
In my last tech demo, I imported Flash "puppets" into Torque2D. These are Flash characters that are made up of smaller parts, like arms and legs, that rotate, move, and skew independently to create an animated whole for the character.
The flash puppet for a robot had 30 parts and, in Torque2D, I did this as a series of 30 different scene objects moving in concert. It turns out that moving all those parts -- by script -- every frame -- took its toll on frame rate. Even if I didn't move the character, but simply redrew it, I ran into timing issues because every character is really 30 scene objects.
There have always been t2d*Static*Sprites and t2d*Animated*Sprites. For both, a single image is pasted over the entire object. The idea of an assembly sprite was to subclass the t2dSceneObject for one more sprite type, but this time it is a t2d*Assembly*Sprite. The idea is that an assembly sprite is one object that holds any number of images each with its own orientation within the sprite.
Quick tests showed that about 8 OpenGL textures could be drawn per sprite without noticeable cost. In other words, Torque has many other costs to maintaining a scene object -- culling, sorting, and spatially planning -- and this eats up time beyond rendering... and alternatively a modern graphics card can draw a handful of textures very fast!
The biggest savings is by creating a C++ structure to hold the animation of all the little parts of an assembly sprite. To cut straight to the chase, I created a datablock (so it can be shared in real-time between copies of a character) for animation. Using TorqueScript, you can set the number of animation frames and the number of parts in the datablock. This creates a 2-dimensional array of "spatial" information for the parts. For any frame, the engine can immediately access all the parts and their positions/sizes/etc in that frame. I call this structure, heh, t2dAssemblyAnimationDatablock.
Then I go about the business of using TorqueScript for setting the spatial information gleaned from XML files that were in turn created from Flash.
Finally, I set an assembly sprite to use the animation and, that's it!
How well does it work to move this stuff from TorqueScript to the engine? Well, before when using only torquescript and lots of scene objects, I dropped to about 15 FPS to show 2 robots! Three robots was Right Out. With assembly sprites it has 40 or so robots, each with 30 parts, running at 100+ fps. Check out the video!
I'm still working through a few of the weirder issues. For instance, if a frame of the animation moves the parts far apart, or sets them big, the scene object should expand to cover that. (Seems to be working) And if an animation ends larger than it started, or farther left than it started, that should certainly stick. In this way one can "blow up" a balloon or "jump over a hedge" using Flash animations. I have that working, but it feels a little volatile just yet. There is a LOT of math. :P
Now that I can render a few extra textures at almost no cost, I'm considering a few possibilities beyond "puppets." For instance, how about shadows under the players? Or how about a damage gauge above the head?
Another thing I'm excited about it providing for swapping out parts in an animation. Say a robot gets shot up pretty badly. I could swap out the body for a dented and dying body but keep the same animation running.
That's it for now. Lemme know what you think!
(That like button again. facebook.com/RednecksVsRobots!)
Here's a video.
(Also, if you enjoy this tech demo, please consider "paying forward" with a click on my game's like button, here: facebook.com/RednecksVsRobots. Gonna look for some funding soon and likes will help, I hope!)
In my last tech demo, I imported Flash "puppets" into Torque2D. These are Flash characters that are made up of smaller parts, like arms and legs, that rotate, move, and skew independently to create an animated whole for the character.
The flash puppet for a robot had 30 parts and, in Torque2D, I did this as a series of 30 different scene objects moving in concert. It turns out that moving all those parts -- by script -- every frame -- took its toll on frame rate. Even if I didn't move the character, but simply redrew it, I ran into timing issues because every character is really 30 scene objects.
So I created an "Assembly" Sprite.
There have always been t2d*Static*Sprites and t2d*Animated*Sprites. For both, a single image is pasted over the entire object. The idea of an assembly sprite was to subclass the t2dSceneObject for one more sprite type, but this time it is a t2d*Assembly*Sprite. The idea is that an assembly sprite is one object that holds any number of images each with its own orientation within the sprite.
Quick tests showed that about 8 OpenGL textures could be drawn per sprite without noticeable cost. In other words, Torque has many other costs to maintaining a scene object -- culling, sorting, and spatially planning -- and this eats up time beyond rendering... and alternatively a modern graphics card can draw a handful of textures very fast!
And an Animation Datablock
The biggest savings is by creating a C++ structure to hold the animation of all the little parts of an assembly sprite. To cut straight to the chase, I created a datablock (so it can be shared in real-time between copies of a character) for animation. Using TorqueScript, you can set the number of animation frames and the number of parts in the datablock. This creates a 2-dimensional array of "spatial" information for the parts. For any frame, the engine can immediately access all the parts and their positions/sizes/etc in that frame. I call this structure, heh, t2dAssemblyAnimationDatablock.
Then I go about the business of using TorqueScript for setting the spatial information gleaned from XML files that were in turn created from Flash.
Finally, I set an assembly sprite to use the animation and, that's it!
Results
How well does it work to move this stuff from TorqueScript to the engine? Well, before when using only torquescript and lots of scene objects, I dropped to about 15 FPS to show 2 robots! Three robots was Right Out. With assembly sprites it has 40 or so robots, each with 30 parts, running at 100+ fps. Check out the video!
Difficulties
I'm still working through a few of the weirder issues. For instance, if a frame of the animation moves the parts far apart, or sets them big, the scene object should expand to cover that. (Seems to be working) And if an animation ends larger than it started, or farther left than it started, that should certainly stick. In this way one can "blow up" a balloon or "jump over a hedge" using Flash animations. I have that working, but it feels a little volatile just yet. There is a LOT of math. :P
Future Uses?
Now that I can render a few extra textures at almost no cost, I'm considering a few possibilities beyond "puppets." For instance, how about shadows under the players? Or how about a damage gauge above the head?
Another thing I'm excited about it providing for swapping out parts in an animation. Say a robot gets shot up pretty badly. I could swap out the body for a dented and dying body but keep the same animation running.
That's it for now. Lemme know what you think!
(That like button again. facebook.com/RednecksVsRobots!)
demo
Here's a video.
#2
T2D does sort by Z, actually called layer order. However, to get speed up, each robot is a self-contained object with one Z value. Then *internally* the parts are sorted by an internal Z. What this means is that, when the engine is sorting, it sees an assembly sprite as one thing and calls it to draw once. The sprite won't know that part of it should be above another object and part below that other object. Etc.
05/30/2012 (10:46 am)
Thanks @lukas. How are those T3D shader effects coming along? :PT2D does sort by Z, actually called layer order. However, to get speed up, each robot is a self-contained object with one Z value. Then *internally* the parts are sorted by an internal Z. What this means is that, when the engine is sorting, it sees an assembly sprite as one thing and calls it to draw once. The sprite won't know that part of it should be above another object and part below that other object. Etc.
#3
Although I believe the ease of modification of the objects ( just swapping an image out with another to equip the character with new items ) is something that has been needed for awhile :P I believe i have read a couple of threads about this on the forums.
Then again, what do I know, I am just a T3D user :P
05/30/2012 (1:38 pm)
Hmm, too bad it would make for some smart solutions otherwise!Although I believe the ease of modification of the objects ( just swapping an image out with another to equip the character with new items ) is something that has been needed for awhile :P I believe i have read a couple of threads about this on the forums.
Then again, what do I know, I am just a T3D user :P
#4
This is nice work. It is really cool to see all that action on the screen. Good job!
The lame part in the action is when they are showing the character building something, walking, looking behind walls, goofing off, etc. Then the music picks back up to get some more gritty action. You fulfilled that role nicely by asking the question: Why this lame part in the music? So your pause in the action was a goofing off comic relief. So that makes you the plucky narrator or a non-self absorbed super hero. You get to choose. Of course, with all this awesome coding you got going I am voting for the less understood super hacker that nobody would know was a nerd at heart because you actually can attract women.
05/30/2012 (11:20 pm)
Are you my mummy?This is nice work. It is really cool to see all that action on the screen. Good job!
The lame part in the action is when they are showing the character building something, walking, looking behind walls, goofing off, etc. Then the music picks back up to get some more gritty action. You fulfilled that role nicely by asking the question: Why this lame part in the music? So your pause in the action was a goofing off comic relief. So that makes you the plucky narrator or a non-self absorbed super hero. You get to choose. Of course, with all this awesome coding you got going I am voting for the less understood super hacker that nobody would know was a nerd at heart because you actually can attract women.

Torque Owner Lukas Joergensen
WinterLeaf Entertainment
Well one thing:
I believe Torque 2D has some kind of z-index to define what textures is above others amirite?
One use for this would be to optionally have different z-indexes on the textures, so if the sprite were to like, put it's leg over a fence, that part would be behind the fence and the rest of the body would be in front of it. But I guess that might slow down the engine, and you could just customize the texture to simulate it instead.
But good work Charlie!