Torque Retro 2D!
by Melv May · in Torque Game Engine · 06/17/2004 (9:58 pm) · 24 replies
This is an extract from my plan that's quite informative regarding the 2D engine stuff so I thought I'd post it here for those who are interested and may have missed it.
The (game-in-a-day) will be a great proving ground for this but I'm not there and it won't be an age before I am so watch this space. I'm running a line between hacking bits in just so I can move onto the tech-demo and doing it correctly and stable and deferring the demo for the last possible second.
*ALL* the code is independant of the standard running of the TGE and doesn't require a single byte of modification to stock code ... not one bit. This has been a guiding principle of what I've done, simple and easy to integrate. Add the C++ files and you're ready, that's it, nothing more, nothing less. ;)
Let me explain some of the details to clarify; Let's start with some names...
fxSceneGraph2D - A 2D SceneGraph that you create in the scripts. Create as many as you want and add as many objects as you like. Treat these as the 2D stage.
fxSceneObject2D - A 2D object that can be added to a fxSceneGraph2D. This is the base object that the more specialised objects such as scrolling-backgrounds are based upon. This object contains physics, spatial orientations, pivot points, networking blah blah blah. Again, no limit other than memory.
fxSceneWindow2D - A customised GUI control based upon the standard GuiControl class. You can place this as normal on the canvas with the editor and associate them with a specific fxSceneGraph2D. The world has an unbounded coordinate system and is only limited by the range of a F32. The camera is part of the actual fxSceneWindow2D itself. You can specify your view of the world really easily and in many ways. One way is to specify a rectangular area to view and the other is to specify a centered-point and the camera-view width/height. When you've set this view window (which can be changed dynamically in scripts for panning effects) you can then use the pan/zoom script functions which use this initial reference point to pan/zoom-in/out. Really easy and only a few lines of script.
The scenegraph handles the collision detection and is really fast. The way it works is similar to the container system within the TGE. Collisions are only checked on objects that are updated in anyway. Each object automatically manages a non-AA clip rectangle which is used for trivial collision rejections after the container system has decided there is a potential collision. The system then promotes the check to the core fxSceneObject2D itself whose base virtual onCollision function does an AABB check. Any objects based upon this object can call the parent for the AABB check and then decided to do a more comprehensive check if needed. A tiled-map object would want to do a fairly complex check dependant upon the tiles it contains for example.
... (cont..d)
The (game-in-a-day) will be a great proving ground for this but I'm not there and it won't be an age before I am so watch this space. I'm running a line between hacking bits in just so I can move onto the tech-demo and doing it correctly and stable and deferring the demo for the last possible second.
*ALL* the code is independant of the standard running of the TGE and doesn't require a single byte of modification to stock code ... not one bit. This has been a guiding principle of what I've done, simple and easy to integrate. Add the C++ files and you're ready, that's it, nothing more, nothing less. ;)
Let me explain some of the details to clarify; Let's start with some names...
fxSceneGraph2D - A 2D SceneGraph that you create in the scripts. Create as many as you want and add as many objects as you like. Treat these as the 2D stage.
fxSceneObject2D - A 2D object that can be added to a fxSceneGraph2D. This is the base object that the more specialised objects such as scrolling-backgrounds are based upon. This object contains physics, spatial orientations, pivot points, networking blah blah blah. Again, no limit other than memory.
fxSceneWindow2D - A customised GUI control based upon the standard GuiControl class. You can place this as normal on the canvas with the editor and associate them with a specific fxSceneGraph2D. The world has an unbounded coordinate system and is only limited by the range of a F32. The camera is part of the actual fxSceneWindow2D itself. You can specify your view of the world really easily and in many ways. One way is to specify a rectangular area to view and the other is to specify a centered-point and the camera-view width/height. When you've set this view window (which can be changed dynamically in scripts for panning effects) you can then use the pan/zoom script functions which use this initial reference point to pan/zoom-in/out. Really easy and only a few lines of script.
The scenegraph handles the collision detection and is really fast. The way it works is similar to the container system within the TGE. Collisions are only checked on objects that are updated in anyway. Each object automatically manages a non-AA clip rectangle which is used for trivial collision rejections after the container system has decided there is a potential collision. The system then promotes the check to the core fxSceneObject2D itself whose base virtual onCollision function does an AABB check. Any objects based upon this object can call the parent for the AABB check and then decided to do a more comprehensive check if needed. A tiled-map object would want to do a fairly complex check dependant upon the tiles it contains for example.
... (cont..d)
About the author
#2
// FullConfig is a compressed form of *all* the initialisation parameters. Each parameter has it's
// own function but this is easier. Some parameters here are position, layer, size, group, pivot point.
// Some of these are obvious some are not. The layer allows you to specify which rendering layer the object
// is rendered to. Layer-0 is always in front. This allows you to render to discreet layers. You can move
// objects between layers at any time. You can also use them to restrict collision to specific layers if you
// want. The pivot allows you to specify horz/vert alignments for the pivot point. This means that the
// position you specify is not necessarily the top/left but can be aligned horz as left/center/right and vert
// as top/center/right. When specifying a rotation, this is used as the pivot point. This can be handy for
// different types of games. A car would be best with the pivot in the center. A shoot-em-up might be best
// with the ship controlled from the center/bottom etc.
// setCollisions allows you to do just that. You can specify which collision groups/layers you want
// to collide with. You can specify which group(s)/layer(s) can be collided with. Other options force the
// object to only allow a single collision, automatically turn-off collision detection upon a collision etc.
// addToScene This is the explicit form of adding to a scenegraph.
// collisionsOn You can tell the object to be interested in collisions. There's also a collisionsOff.
%obj2d = new fxStaticObject2d();
%obj2d.fullConfig( 0, 0, 0, 64, 64, 0, "FX_PIVOT_LEFT", "FX_PIVOT_BOTTOM", 0 );
%obj2d.setupCollisions( BIT(0), 0XFFFFFFFF, false, false, false );
$SceneGraph2D.addToScene(%obj2d);
%obj2d.collisionsOn();
Alright, that's enough for now. I've finished with all the core functionality with the exception of networking. I'm
now working on the more useful objects based upon the core object for support such as animated sprites, path objects, tile-
support etc.
Hopefully this is a good taster in the absence of screenshots. :)
- Melv.
06/17/2004 (9:58 pm)
// Let's add an alien with all the trimmings....// FullConfig is a compressed form of *all* the initialisation parameters. Each parameter has it's
// own function but this is easier. Some parameters here are position, layer, size, group, pivot point.
// Some of these are obvious some are not. The layer allows you to specify which rendering layer the object
// is rendered to. Layer-0 is always in front. This allows you to render to discreet layers. You can move
// objects between layers at any time. You can also use them to restrict collision to specific layers if you
// want. The pivot allows you to specify horz/vert alignments for the pivot point. This means that the
// position you specify is not necessarily the top/left but can be aligned horz as left/center/right and vert
// as top/center/right. When specifying a rotation, this is used as the pivot point. This can be handy for
// different types of games. A car would be best with the pivot in the center. A shoot-em-up might be best
// with the ship controlled from the center/bottom etc.
// setCollisions allows you to do just that. You can specify which collision groups/layers you want
// to collide with. You can specify which group(s)/layer(s) can be collided with. Other options force the
// object to only allow a single collision, automatically turn-off collision detection upon a collision etc.
// addToScene This is the explicit form of adding to a scenegraph.
// collisionsOn You can tell the object to be interested in collisions. There's also a collisionsOff.
%obj2d = new fxStaticObject2d();
%obj2d.fullConfig( 0, 0, 0, 64, 64, 0, "FX_PIVOT_LEFT", "FX_PIVOT_BOTTOM", 0 );
%obj2d.setupCollisions( BIT(0), 0XFFFFFFFF, false, false, false );
$SceneGraph2D.addToScene(%obj2d);
%obj2d.collisionsOn();
Alright, that's enough for now. I've finished with all the core functionality with the exception of networking. I'm
now working on the more useful objects based upon the core object for support such as animated sprites, path objects, tile-
support etc.
Hopefully this is a good taster in the absence of screenshots. :)
- Melv.
#3
06/17/2004 (10:41 pm)
You're a God
#4
06/17/2004 (10:57 pm)
REALLY looking forward to this one :-)
#5
06/17/2004 (11:13 pm)
This is the single most exciting thing that I have heard about since I first heard of Torque. Which is funny because there are a number of 2D libraries available, and there have been major enhancements like TSE and TNL...but still...the first time I heard about this I was ga-ga. Now I'm even more excited to see the demo!
#7
As in drop them into the CVS HEAD dir on my box and compile along with the TGE code?!
That would be very, very cool...
06/18/2004 (12:36 am)
"Add the C++ files and you're ready, that's it, nothing more, nothing less."As in drop them into the CVS HEAD dir on my box and compile along with the TGE code?!
That would be very, very cool...
#8
06/18/2004 (1:08 am)
Nice work, Melv!
#10
06/18/2004 (4:49 am)
Mucho mucho exciting !
#11
- Melv.
06/18/2004 (6:13 am)
Drop them into the CVS and it will work, guaranteed. The only things I'm really using are some basic support such as vectors, a few virtual functions from the SimObject and the base datablock class, none of which have changed since the beginning of time itself so there shouldn't be any integration problems.- Melv.
#12
I'll certainly be looking forward to the release as I can think of a number of applications already!
Thanks for your efforts!
06/18/2004 (6:52 am)
@Melv: ^^That is very cool! Simple is good... 8^)I'll certainly be looking forward to the release as I can think of a number of applications already!
Thanks for your efforts!
#13
06/18/2004 (8:44 am)
Hey, if this is Torque Retro, does that mean that we're going to get the old green chatbox back?
#14
I like the sound of that -- Torque Retro. This very well might inspire me to resume work on a 2D shmup I was building before I got Torque. (Ugh, so many projects, not enough time!)
06/18/2004 (9:27 am)
Melv, I like that style of mod. Just dump it into your source tree, compile, and blam it works. Of course, you can get away with this because you don't need to touch any of the existing rendering code. :)I like the sound of that -- Torque Retro. This very well might inspire me to resume work on a 2D shmup I was building before I got Torque. (Ugh, so many projects, not enough time!)
#15
Why don't you post it as a resource. Forum threads can be erased and resources have more space to insert code on them.
06/18/2004 (10:17 am)
Melv, good work !Why don't you post it as a resource. Forum threads can be erased and resources have more space to insert code on them.
#16
I didn't think this would be much of a resource. The plans don't have the 4096 char limit so I posted this in one go there. The code will definately go up as a resource fairly soon. I'm definately starting on the tech-demo this weekend, really looking forward to using it myself. :)
I'm working really hard guys to get this out ASAP, honest.... :)
- Melv.
06/18/2004 (11:01 am)
Bruno,I didn't think this would be much of a resource. The plans don't have the 4096 char limit so I posted this in one go there. The code will definately go up as a resource fairly soon. I'm definately starting on the tech-demo this weekend, really looking forward to using it myself. :)
I'm working really hard guys to get this out ASAP, honest.... :)
- Melv.
#17
The collision system maintains debug metrics that are extremely useful in tuning the performance of the system. For hundreds of objects it's not a problem but if you intend to have thousands of collidable 'things' then you'll need to configure the collision system appropriately which is really easy and again, done from the scripts.
The system tracks potentials/actuals/hit-percentage of lots of stuff. You can turn on individual debug metrics with a command sent to any of the windows that are displaying a scene. I've limited it here to objects, renders and collisions for brevity.
In the following scene I added 4 background images (no collisions setup) and 500 spinning ships that are red when colliding and green when not. The first image shows them without b/box & aabb and the second with them on. All ships are set to potentially collide with anything else so there's a potentially *huge* collision check. Also, the worst thing is happening in that all the objects are constantly in motion so there are 500 collision system updates per frame. Let's stress this sucker!
The thing to note here is that out of 504 objects in the scene, the system has decided that 439 are potentially in the view and the actual was 439 which is a %100 hit. At the moment, I'm having difficulty getting this below 93%. The other thing to note and more impressive is that there are a potential of 2908 collisions of which 2350 resulted in a positive collision via the aabb. This obviously depends on the positions and varies accordingly but average is 89% running this demo over 5 minutes. This can be increased (or degraded) by tuning of the collision system. There's actually a way to calculate it dynamically using statistics but changing the collision bin system dynamically is another matter, an interesting problem for another time perhaps.
Note that some objects are red e.g. colliding but appear to be on their own. This is not a bug but simply shows the weak random number generator used in controlling the motions. These are several objects overlaid, some completely.
Anyway, enough talk, here are the images .... more on their way ...


- Melv.
06/18/2004 (11:57 am)
The collision system is finished...The collision system maintains debug metrics that are extremely useful in tuning the performance of the system. For hundreds of objects it's not a problem but if you intend to have thousands of collidable 'things' then you'll need to configure the collision system appropriately which is really easy and again, done from the scripts.
The system tracks potentials/actuals/hit-percentage of lots of stuff. You can turn on individual debug metrics with a command sent to any of the windows that are displaying a scene. I've limited it here to objects, renders and collisions for brevity.
In the following scene I added 4 background images (no collisions setup) and 500 spinning ships that are red when colliding and green when not. The first image shows them without b/box & aabb and the second with them on. All ships are set to potentially collide with anything else so there's a potentially *huge* collision check. Also, the worst thing is happening in that all the objects are constantly in motion so there are 500 collision system updates per frame. Let's stress this sucker!
The thing to note here is that out of 504 objects in the scene, the system has decided that 439 are potentially in the view and the actual was 439 which is a %100 hit. At the moment, I'm having difficulty getting this below 93%. The other thing to note and more impressive is that there are a potential of 2908 collisions of which 2350 resulted in a positive collision via the aabb. This obviously depends on the positions and varies accordingly but average is 89% running this demo over 5 minutes. This can be increased (or degraded) by tuning of the collision system. There's actually a way to calculate it dynamically using statistics but changing the collision bin system dynamically is another matter, an interesting problem for another time perhaps.
Note that some objects are red e.g. colliding but appear to be on their own. This is not a bug but simply shows the weak random number generator used in controlling the motions. These are several objects overlaid, some completely.
Anyway, enough talk, here are the images .... more on their way ...


- Melv.
#18
06/18/2004 (12:06 pm)
Melv, man that's just so awesome!
#20
06/18/2004 (12:52 pm)
Think we all should bow to God May ;)
Associate Melv May
I've also added preliminary networking support but I don't intend to pad this completely out immediately; I want to work single-player for the moment.
All objects can have all their settings set by selecting a datablock but I don't enforce it in-case you don't want to. This is a change from what the TGE typically preaches. Create a standard datablock and specify it when generating the object or not, it's up to you. If you do use a datablock, you can still change the settings that you originally set with the datablock, it's not fixed. This is pretty flexible and again, is not typical for the TGE.
// Create a single scene graph.
$SceneGraph2D = new fxSceneGraph2D()
// Make my Scene Window GUI render my scenegraph.
// In this case it's come from a standard GUI but I could've created it dynamically if I wanted.
sceneWindow2D.setSceneGraph( $SceneGraph2D );
// Setup the part of the world I want to see for now. Top-Left, Width/Height.
sceneWindow2D.setCameraWindow( -1000, -1000, 2000, 2000 );
// Or do it this way... (Center X/Y, Width/height)
sceneWindow2D.setCameraWindow( 0, 0, 2000, 2000 );
// Change the zoom just for fun ... extreeeem close-up!
sceneWindow2D.setZoom( 2.5 );
// If you haven't already noticed, you can have as many of these screens viewing as many scenegraphs as you like. You could have defender/space-invaders running at the same-time. You could have a whole arcade running and windows simply 'looking' at different ones dynamically, it's up to your imagination. :)
// Let's add some sky without using a datalock.
%backObj1 = new fxStaticObject2D();
// Set it up.
%backObj1.setPosition(-320,-240);
%backObj1.setSize(640,480);
%backObj1.setTexture("phase/client/images/skyback1");
// Add it to the scene graph.
$SceneGraph2D.addToScene(%backObj1);
// That was too hard so, let's generate a scrolling mountain but
// this time do it datablock-style...
datablock fxStaticObjectDatablock2D(staticMountainBack1)
{
position = "-320 -240";
size = "640 480";
textureName = "phase/client/images/back2";
repeatMode = true;
repeatX = 1;
repeatY = 1;
layer = 31;
};
// Let's create the sucker...
// Note the 'scenegraph' field. All objects have this ability that means I don't have to explicitly add them to the scenegraph.
new fxStaticObject2D()
{
datablock = staticMountainBack1;
scenegraph = $SceneGraph2D;
};
// Any of the datablock fields can be omitted, it's really flexible. For instance, you probably won't want position but you might for a set of layered backgrounds.
// Let's tell the mountain to start scrolling horz 0.5 pix/sec & 0 vert. True/false enable/disable it.
%backObj1.setScrollMode(true, -0.5, 0)
... (cont..d)