Monday, April 13, 2009

Thread safe strtok

Named "StrTok", by the convention of 'capital letters make it completely different'.

The variable "start" is used to keep track of progress through the buffer.


// thread safe strtok. Also can do multiple buffers at a time.
// returned char* must be delete[]ed when finished.
static char* StrTok(const char* buffer, const char* delims, int& start)
{
bool exec = true;
int end = -1;

for (int i = start; buffer[i] != '\0' && exec; i++)
{
for (int j = 0; delims[j] != '\0'; j++)
{
if (buffer[i] == delims[j])
{
end = i;

if (end == start)
start++;
else
{
exec = false;
break;
}
}
}
}

if (end < start)
end = start+1;

char* token = NULL;
int len = end - start;
if (len > 0)
{
token = new char[len+1];
for (int i = start; i < end; i++)
token[i-start] = buffer[i];
token[len] = 0;
}

start = end;
return token;
};

Friday, November 14, 2008

Arctan in J2ME

Presenting:


// calculation functions
public class Calculation {

// Because J2ME has no floating point numbers,
// some sort of fixed point math is required.
// My implementation is simply to shift 10 places.
// for example, 1024 (>> 10) = 1
// and 512 (>> 10) = 0.5
public static final int[] CosTable90 = {
1024, 1023, 1023, 1022, 1021, 1020, 1018,
1016, 1014, 1011, 1008, 1005, 1001, 997,
993, 989, 984, 979, 973, 968, 962,
955, 949, 942, 935, 928, 920, 912,
904, 895, 886, 877, 868, 858, 848,
838, 828, 817, 806, 795, 784, 772,
760, 748, 736, 724, 711, 698, 685,
671, 658, 644, 630, 616, 601, 587,
572, 557, 542, 527, 512, 496, 480,
464, 448, 432, 416, 400, 383, 366,
350, 333, 316, 299, 282, 265, 247,
230, 212, 195, 177, 160, 142, 124,
107, 89, 71, 53, 35, 17, 0
};

public static final int[] AtanTable = {
0, 1, 2, 3, 5, 6, 7, 8, 10, 11,
12, 13, 14, 16, 17, 18, 19, 20, 21, 22,
23, 25, 26, 27, 28, 29, 30, 30, 31, 32,
33, 34, 35, 36, 37, 37, 38, 39, 40, 40,
41, 42, 43, 43, 44, 45
};


// angle calculation function based on x = x1 - x2, y = y1 - y2
public static boolean ArcTan(int x, int y, AngleArray sincos)
{
int angle = atan( y, x );
if (angle == -300)
return false;

int rotangle = abs(angle) % 90;

int cos = CosTable90[rotangle];
int sin = CosTable90[90-rotangle];

if (angle >= 270) // quadrant IV
{
int tCos = cos;
cos = sin;
sin = -tCos;
}
else if (angle >= 180) // quadrant III
{
cos = -cos;
sin = -sin;
}
else if (angle >= 90) // quadrant II
{
int tCos = cos;
cos = -sin;
sin = tCos;
}


sincos.sin = sin;
sincos.cos = cos;

return true;
}


/// returns angle 0->359 in degrees
public static int atan( int Y, int X )
{
boolean swap = false;

int top = abs(Y);
int bottom = abs(X);
if (top > bottom)
{
int btemp = bottom;
bottom = top;
top = btemp;
swap = true;
}
else if (bottom == 0)
return -300;

// this should keep index inbounds [0, 45]
int index = (top * 45) / bottom;
int angle = AtanTable[index];

if (swap)
angle = 90 - angle;

// X & Y += 180
// X & !Y = ...90
// !X & Y = ... 270
if ( (X < 0) && (Y < 0) )
angle += 180;
else if (Y < 0)
{
angle = 90 - angle;
angle += 270;
}
else if ( X < 0)
{
angle = 90 - angle;
angle += 90;
}

if (angle == 360)
angle = 0;

return angle;
}

// for good measure, sin and cos functions
public static int sin( int angle )
{
int rotangle = abs(angle);
while (rotangle > 89)
rotangle -= 90;

int cos = CosTable90[rotangle];
int sin = CosTable90[90-rotangle];

if (angle >= 270) // quadrant IV
sin = -cos;

else if (angle >= 180) // quadrant III
sin = -sin;

else if (angle >= 90) // quadrant II
sin = cos;

return sin;
}

public static int cos( int angle )
{
int rotangle = abs(angle);
while (rotangle > 89)
rotangle -= 90;

int cos = CosTable90[rotangle];
int sin = CosTable90[90-rotangle];

if (angle >= 270) // quadrant IV
cos = sin;

else if (angle >= 180) // quadrant III
cos = -cos;

else if (angle >= 90) // quadrant II
cos = -sin;

return cos;
}

}

Thursday, July 31, 2008

Stiria Website

I've gone ahead and set up a little website for Stiria at http://galacticicecube.com. Check it out!

Thursday, July 24, 2008

Quick code sample

A rather innoculous C++ class (of static functions) for placing/extracting 32-bit ints and floats to/from a C-style byte array. As mentioned in the comment, this was written for use in UDP network programming.

DEFAULTARRAYLENGTH is a constant declared elsewhere. It's helpful if the majority of the char* buffers passed in are of the same, fixed size.



/// implements some Bit library type functions for use with UDP/char* buffers

class PBitLib
{
public:

// assumes 32bit int
static void toBuffer( int num, char* buffer, int start = 0, int buflen = DEFAULTARRAYLENGTH )
{
if (buflen < 4 + start)
return;

int x = num;
unsigned char * bytes = (unsigned char *) &x;

for (int i = 0; i < 4; i++)
buffer[i+start] = (char) (bytes[i]);
};

// assumes 32bit float
// copies float into buffer from buffer[start] to buffer[start+3]
static void toBuffer( float num, char* buffer, int start = 0, int buflen = DEFAULTARRAYLENGTH )
{
if (buflen < 4 + start)
return;

float x = num;
unsigned char * bytes = (unsigned char *) &x;

for (int i = 0; i < 4; i++)
buffer[i+start] = (char) (bytes[i]);
};

// assumes 32bit int
static int bufferToInt( char* buffer, int start = 0, int buflen = DEFAULTARRAYLENGTH )
{
if (buflen < 4 + start)
return 0;

unsigned char bytes[4];
for (int i = 0; i < 4; i++)
bytes[i] = (unsigned char) buffer[i+start];

int num = *(int*)(bytes);
return num;
};


//
static float bufferToFloat( const char* buffer, int start = 0, int buflen = DEFAULTARRAYLENGTH )
{
if (buflen < 4 + start)
return 0;

unsigned char bytes[4];
for (int i = 0; i < 4; i++)
bytes[i] = (unsigned char) buffer[i+start];

float num = *(float*)(bytes);
return num;
};
};

Thursday, July 17, 2008

Stiria - Demo 1!

There's still work to be done, as mentioned previously, but I've decided to throw caution to the wind and release the first demo of this game.

STIRIA - Galactic Ice Cube game

Download here (Stiria.jar, 152 kB)

Phone requirements:

The game runs under Java Micro Edition. As such, if your phone does not support Java, this game will not run on it. If you're not sure if your phone has Java, you can do a few things:

  1. Take a look at what games/apps you have on your cell phone. If they mention Java when they start up, you have Java.
  2. Try to install it anyway. It shouldn't cause any harm, apart from the time it takes to try.

Apart from that, your cell phone should have a reasonable resolution, something in the range of 150x150 pixels (hopefully larger) to enjoy the game experience. That last phrase is code for, "if your screen is too small you won't be able to see where you're going".  However, the game should run, and if you want to chance it on a smaller resolution, go ahead.

The current version of the game has a maximum resolution (of sorts) at 400x400 pixels. I have not tested it at that large a resolution, but some graphics stuff is likely to be messed up.

How to install on cell phone:

Download the above .jar file onto your phone.  If you can transfer files directly from your computer to your phone, that will work as well. (in that case just download the .jar onto your hard disk, then move it onto your phone)

.jad installer - Certain phones may require an installer to help them figure out what to do with the .jar.  This is it.  Transfer it onto your phone with the .jar, then (if it doesn't auto-install), run it from wherever it is on your phone.

Hopefully these instructions are enough to get the game up and running.  If not, complain in the comments section of this post or something. Hopefully I'll be able to resolve most issues. =)

How to play

Okay, now that the lame stuff is out of the way, it's hopefully running on your phone.  You have no idea what you've gotten yourself into!

  • Control our nameless, heroic ice cube as he adventures in OUTER SPACE! Why is he in outer space? That's a mystery.
  • Up = jump.
  • Right = accelerate to the right.
  • Left = accelerate to the left.
  • Fire = attack with ICE FURY (less impressive than it sounds)
  • Select = pause/unpause the game.
  • Up, Down, and Fire navigate the pause menu.

Tips:

  • Space is an unforgiving place. A jump in the wrong place or at the wrong time may result in your heading in exactly the direction you want to avoid. So plan ahead! That's how NASA does it.
  • There's no direct penalty for dying, apart from forcing you to restart the level.  There are many hazards in space, including asteroids and fire.  Ice cubes happen to be very negatively impacted by fire.
  • You have a mini-map than can be accessed when the game is paused.  On the map, the center of the screen is marked as your current location.  Things marked with a light blue "X" will lead to the completion of the level.
  • There are two levels in total.  Both are rather difficult.

That's it! Have fun, and don't be afraid to die!

Thursday, July 10, 2008

Stiria - status update

Slowly but surely, the demo is approaching completion. There's some stuff that needs to be done but is best left until after the demo -- an overhaul of the slow collision detection code, for example -- but by and large it's getting very close to where I'm comfortable releasing it into the wild.

The current plan is for the demo to have two levels and a boss. Initially I had planned to have a single level demo, but I don't want to waste anybody's time by making the gameplay shorter than the download time. =)

Stay tuned.

Saturday, May 24, 2008

UIUC Senior Project

This project carried over my two final semesters at the University of Illinois, as a senior project in conjunction with a business interested in exploring 3D gaming as a learning tool. To satisfy their curiosity, our group of 4 used the Torque Game Engine, along with Autodesk Maya for modeling purposes to model part of the business complex and create a prototype learning tool and first person game for both teaching an escape route, as well as providing some small sample of what it might be like to be within the building when it was on fire.

The modeling work was rather extensive, and mostly handled by other members of the group. In general, the work for the project was rather extensive as well. However, by April we were more or less finished, and the client was by all rights satisfied with what we had accomplished. In all honesty, I'm not sure he had initially thought we would end with a completely working prototype. As four full-time university students with no outside help, completing a full 3D videogame of sorts seemed both then and now to be a monumental task. Thankfully, we had a great, motivated group.


There are a number of ongoing activities that go into a project like this: from the seemingly endless and sometimes irrelevant administrative reports, requirement specifications, and detailed documentation, to the modeling of a large portion of a building, to finally the actual coding of things like smoke and program flow, the placement of objects like fire extinguishers, and the constant reassessment of what features belong in the game, and which might be better left out. This final point had an atypically large role in our project. A few of us had made small videogames before it, but out of the four of us not one had any experience working on a 3D game. We didn't know what to look for, or what to expect to some extent. We made this clear to the client, however, and thankfully were able to overcome it with some flexibility on his part.

My favorite accomplishment of this project is probably that we finished. But beyond that, I'm pretty happy with how some of the stuff I put together worked out: Those light blue arrows on the edge of the screen that point the player in the direction of the exit are mine, both programmatically and Paint Shop Programmatically. The smoke effect is something I figured out as well, as is the annoying fire alarm which mercifully none of us can hear. (it is extremely annoying, I'm not going to lie.)

I also made those subpar tables obscured by smoke on the right, not that that was much of an accomplishment.


As mentioned in brief above, we used GarageGames Torque in the creation of this game. Despite our inexperience with actually making 3D games, it seemed clear from the start that mucking around with low level things like lighting effects and collision detection would only give us an extra degree of difficulty towards finishing the project. Torque has lighting tools built in, as well as collision detection and particle effects. All of these things came in handy immensely. Of course, an otherwise helpful tool like Torque wouldn't be complete without a plethora of frustrating shortcomings, some of which forced us to modify parts of the project. However, by and large it proved to be a boon.

One final, slightly odd note about this project. You may have noticed that after referring to them as "a business" and "the client", I have not referred to the company we made this prototype for. That is due to an NDA they required us to sign at the start of the project, stating among other things that we would not mention their company in relation to this game, so as to keep their videogame related research a secret, I suppose. It seems pretty bizarre, but I'm not one to judge. In any case, that agreement also prevents me from posting the game here. It's theirs, though for only internal use.

(This last fact is not a big deal. While I'm proud of the game, etc, it's ultimately a learning tool and not much of a fun game. The two aren't necessarily mutually exclusive, but for this game they were.)