Page 5 – Font, Timing, Debugging, Kinematics

Page 5

Ok so the first thing I am going to stress is that I am sort of flying by the seat of my pants here and the step system I have been using is having trouble keeping up. For instance there is no reason that any of these steps after a certain point should be in any specific order, this is just the order that my exploration into game design happens to take. Also, for steps 9 – 12 or so (this page), I am just going to explain them in steps, but give you the finished product of all the steps for the files. The reason for this is that I have already done all these steps and going back and erasing stuff just to have separate files for each part seems like more work then I feel like doing. In all likelihood nobody is going to download the files any way, and any one who actually uses this document will skip to the step they are looking for any way.

Step 9 – 12 Files

Step Nine: Font

To add font to my game I used the FontUtilities function written by Faikus and available on the wiki. In Xcode you create a new file (command – N) and name it FontUtilities.mm. The .h file should automatically be created. I don’t see any copyright on the wiki and it says it was donated so I will reproduce the code here until someone tells me not to.

fontUtilities.h


#include "../src/sio2/sio2.h"

SIO2font* createSIO2Font( const char* fontName = "Marker Felt",
const unsigned int cellSize = 32,
const unsigned int fontSize = 20,
const float spacing = 10.0f );

fontUtilities.mm


#import "FontUtilities.h"

SIO2font* createSIO2Font( const char* fontName,
const unsigned int cellSize,
const unsigned int fontSize,
const float spacing )
{
const unsigned int width = cellSize * 16;
const unsigned int height = width;

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void* data = calloc(height*4, width);
CGContextRef context = CGBitmapContextCreate(data, width, height, 8,
width*4, colorSpace,
kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);

CGContextSetGrayFillColor(context, 1.0, 1.0);
CGContextTranslateCTM(context, 0.0, height);
CGContextScaleCTM(context, 1.0, -1.0);
UIGraphicsPushContext(context);
UIFont* font = [UIFont fontWithName: [NSString stringWithCString: fontName] size: fontSize];
assert(font != nil);

char buf[2] = { 0, 0 };

for (int x = 0; x < 16; ++x) {
for (int y =0; y width = width;
image->height = height;
image->bits = 4;
unsigned int size = image->width * image->height * image->bits;
image->tex = ( unsigned char * ) malloc( size );

memcpy(image->tex, data, size);
free(data);

sio2ImageGenId( image, NULL, 0.0f );

SIO2font *sio2Font = sio2FontInit("newFont");
SIO2material *fontMaterial= sio2MaterialInit( "fontMaterial" );
fontMaterial->diffuse->x = 1.0f;
fontMaterial->diffuse->y = 1.0f;
fontMaterial->diffuse->z = 1.0f;
fontMaterial->diffuse->w = 1.0f;
fontMaterial->blend = SIO2_MATERIAL_COLOR;
fontMaterial->_SIO2image[ 0 ] = image;

sio2FontCreate( sio2Font,
fontMaterial,
16,
0,
cellSize,
spacing );

CGContextRelease(context);

return sio2Font;
}

Then you have to create the font like you would a normal sio2Font, like in tutorial 5.

gameLoading

SIO2font* newFont = createSIO2Font("Marker Felt");

To print text to screen, put this code in your rendering function. Fonts are done in 2D mode, so you must add a new section after 3D mode. Don’t forget to reset the font or it will only render on the first cycle.

gameRender


sio2WindowLeaveLandscape3D();
sio2WindowEnter2D( sio2->_SIO2window, 0.0f, 100.0f );
{
sio2WindowEnterLandscape2D( sio2->_SIO2window );
{
newFont->_SIO2transform->loc->x = 10; //moves font to xy coordinates you
newFont->_SIO2transform->loc->y = 100;//wish to start printing at
sio2FontPrint( newFont, SIO2_TRANSFORM_MATRIX_APPLY, "\nGems %.0f", gem_count ); }
sio2FontReset();
}
sio2WindowLeaveLandscape2D( sio2->_SIO2window );
}
sio2WindowLeave2D();

Step Ten: Timing

To create the timing I just copied the timer from tutorial 17, which has already been incorporated into the menu.mm file. What I’ve done here though is create GAME_TIME which has a value of -3.0f:
float GAME_TIME = -3.0f;

Then I added another layer of if/then at the beginning of my rendering code:

gameRendering

/////RENDERING CODE
if( _SIO2camera )
{
if( GAME == 1 )
{
GAME_TIME += sio2->_SIO2window->d_time;

if( GAME_TIME >= 0 )
{ sio2PhysicPlay( sio2->_SIO2physic ); }

sio2WindowEnterLandscape3D();
{
sio2CameraRender( _SIO2camera );
{
/////GEM RENDERING
...
...

I also added another layer of if/then on top of that to switch between different contexts, which will be controlled by the GAME flag you see here. Something similar is already being done in menu.mm. Here though it is not really doing much yet. GAME_TIME increments, and when it reaches zero it activates the physics. The GAME_TIME will be used for bonus points, and this is later in the 2D section of the rendering function. In the last step I chopped this part up to show you just what was needed to get the font working, but here I show you my entire code for printing the countdown to screen, then printing the timer and gem count. I had trouble resizing the font using glScale() so the count down and GO! seem a little to small at this point, but I will work it out soon, and it will be in the later files.

gameRendering

sio2WindowEnter2D( sio2->_SIO2window, 0.0f, 100.0f );
{
sio2WindowEnterLandscape2D( sio2->_SIO2window );
{
if( GAME_TIME _SIO2transform->loc->x = 240.0f;
newFont->_SIO2transform->loc->y = 200.0f;
sio2FontPrint(newFont, SIO2_TRANSFORM_MATRIX_APPLY, "%.0f", (GAME_TIME - 1)* -1 );
sio2FontReset();
}
if( GAME_TIME > 0.0f & GAME_TIME = 1.0f )
{
newFont->_SIO2transform->loc->x = 10;
newFont->_SIO2transform->loc->y = 100;
if( GAME_TIME _SIO2window );
}
sio2WindowLeave2D();

I am tired for now, so I will probably finish this page tomorrow.
(two weeks later…)

Step Eleven: Debugging

In the process of trying to get my kinematic lift to work I followed people’s advice and activated the bullet debugDrawer that I found on the old forum (here). I’m not sure who originally wrote the code, but Francescu was the one who posted it on the old forum so I am attributing it to him and posting the files I have used for your convenience. First of all you need to create two new files named GLDebugDrawer.h and GLDebugDrawer.mm (see Step 9 – 12 files). Then you need to activate it in your code. In the game.mm file for these steps the code has been commented out because I was done using it (for now). I am not completely sure if it has helped because my kinematic lift isn’t working quite properly yet, but it will certainly be useful in the future.
First you must include the new files and declare a GLDebugDrawer:
<code?
#include "GLDebugDrawer.h"
GLDebugDrawer debugDrawer;

gameLoading


sio2PhysicPlay( sio2->_SIO2physic );
debugDrawer.setDebugMode(btIDebugDraw::DBG_DrawWireframe);
sio2->_SIO2physic->_btSoftRigidDynamicsWorld->setDebugDrawer(&debugDrawer);
sio2PhysicPause( sio2->_SIO2physic );

gameRendering


sio2->_SIO2physic->_btSoftRigidDynamicsWorld->debugDrawWorld();

and that is all there is to the DebugDrawer.

Step Twelve: Kinematics

Finally for this page I am going to include my code for creating kinematic objects. So far this isn’t quite working properly (see forum thread), but it is not too far off so I will show you what I have. The idea behind a kinematic object is that it will affect rigid body objects without being affected itself. In this way you can animate floating platforms that will carry your character around or whatever you like. To make an object a kinematic object you must set the mass to zero and a coulple other things. Also, the button and the kinematic lift have been move to layer 3 in Blender and therefor have not been exported into the .sio2 file. This is because I don’t intend to use them in the level I have turned iMarble.blend into. If you wish to check them out, just move them to layer 1 and re-export the level.

Declare Variables


btVector3 objectLoc;
btMatrix3x3 objectSubMatrix;
SIO2transform * _SIO2transform = NULL;

gameLoading


plane2 = sio2ResourceGetObject( sio2->_SIO2resource, "object/Cube");
if( plane2 )
{
_SIO2transform = plane2->_SIO2transform;
plane2->_SIO2objectphysic->_btRigidBody->setMassProps( btScalar( 0.0f), btVector3( 0.0f, 0.0f, 0.0f ) );
plane2->_SIO2objectphysic->mass = 0.0f;
plane2->_SIO2objectphysic->_btRigidBody->setCollisionFlags( plane2->_SIO2objectphysic->_btRigidBody->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT );
}

gameRendering


plane2 = sio2ResourceGetObject( sio2->_SIO2resource, "object/Cube");
if( plane2 )
{
objectSubMatrix.setFromOpenGLSubMatrix( plane2->_SIO2transform->mat );
plane2->_SIO2objectphysic->_btRigidBody->getWorldTransform().setBasis( objectSubMatrix );
plane2->_SIO2objectphysic->_btRigidBody->getWorldTransform().setOrigin( btVector3( _SIO2transform->mat[ 12 ], _SIO2transform->mat[ 13 ], _SIO2transform->mat[ 14 ] ) );
}

I apologize if the code on this page looks a little disorganized, but taking screen shots so it looks really nice got really labour intensive. Also if I missed any snippets of code here or there I am sorry, I wrote this code weeks ago and am just finishing the documentation now. The files that are linked at the top of the page work fine so you can always download them to see the working product. And finally I changed iMarble.blend considerably to reflect how the game will actually look, so I included that in the files too. I believe that all the textures I used should be included in the .blend file, if anyone downloads it and they are not, please let me know, and I will fix the problem. The level represented in the .blend file is far from finished, but will end up being my new Level 1.
~KeithK

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s