Sunday, December 16, 2012

Room (or scene) loader for games with non-linear storyboard

In a game with linear storyboard when the player completes the tasks in the current scene/room (henceforth: room) then the loader reads the next record from the rooms-file where all rooms are stored and the core engine of the game designs the next room.

This is the case in almost any platform, arcade game, like it is Pac-Man, Solomon’s Key, Bobble Bobble, Bob Jack etc.  But this is the easy case, the good one.

Recently I have uploaded my new game for java-phones called Vampire. You can find more details and how to install it on Liknongames - Vampire. It is a platform, multi screen game where the main ghost-like character walks inside a complex castle searching for the vampire.  On his path there are a lot of unfriendly creatures and lethal traps.

Here is a part of the huge map of some rooms in the castle including the starting one. Every rectangle with white border is a room of the castle.

Picture 1
As you can see there are rooms with one, two, three or even four openings that lead to another  room in other floor or in other side, thus it doesn’t make any sense to speak for “the next” or for “the previous” room.

Let us see now how I store every single room and how I implemented this navigation system. It will help.

This is a screenshot of the room at the right side of the starting one. 

Picture 2
You understand now that It has no meaning at all to say “…this is the second room…” because from the starting room he may either fall into the (trap-)room or exit from the right edge of the room.

And this is exactly what I am going to explain in this post: How to make an automated navigation mechanism that is responsible for the transition from one room to another in such a game world where there may be openings in all sides of the current room.

Vampire is a tile-based game. Every room is a grid of 16 cells along the horizontal and 8 cells along the vertical direction. So there are 128 tiles in each room.


Picture 3
There are (and will be) about 200 different objects (tiles, enemies, goodies, etc).  Each kind of object is given a numerical code used also for the storing into the file. So, I need values from 0 to 200 (0 is the value for an empty tile).  As we know, one byte is enough to keep such a value since a byte can keep 256 different values.  It means that each room can be considered as a sequence of 128 bytes.

Inside the rectangle is the part of the binary file with the values of the bytes of the room of the screenshot in hexadecimal system.


Picture 4
How ugly is it, isn’t it? Let’s remove the 00’s and we get a friendlier and already known picture:



Picture 5
Yes, this is the same room in picture-3 seeing it through X-rays.
Short F.A.Q. about this actinography:
Q: In the upper row I see only green tiles. The values however are different: 0x42, 0x43,0x4D, 0x45…
A: The tiles are different too. Stare at them carefully and you can see slight differences.
Q: What is the “74” in the middle column?
A: This is an almost hidden canon that throws arrows if the player is in its height and on its side.

Q: I see a “97” in the middle column under the “83” but nothing is it to be seen in the screen:
A: This is an completely transparent tile. Its value is out of the range of the tiles the player can collide with, however it belongs to the range of values that the enemies can collide with.  It forces the bird (62) in the same row not to reach the blue wall at the right, but to bounce earlier.

At the upper left side of the rectangle there is a value, 00000180h. It is the position in the room-file where this screen is started from. This is in hex. 0x180=384.

From the 384th byte begins this room. How many rooms are stored in the file before it? Since every record that represents a room has a constant length of 128 bytes, we have 384/128 = 3 rooms.

After the player has passed the right edge of the starting room the loader knew that it has to spring to the 384th position of the binary file that keeps all rooms and read from there the next 128 bytes.

How did the loader know this?

For this reason I had to split in tiles not only the room but the entire map of the game and use a coordinate system to specify the location of a room into the castle starting from the room 00x00 to be the leftmost room in the lowest basement of the castle.  The first coordinate is increased by +1 from left to the right and the second coordinate is increased by +1 when climbing in a room on the ceiling of the current one.

By this addressing the rooms in the part of the map in picture are assigned with the coordinates as in the picture


 Picture 6
Oh! I have just given away that by the starting of the game you are already in the 7th floor !!!!

Now that we always know the exactly coordination of a room in the map of the castle that is going to be visited it is easy to know from which position in the rooms-file to start reading from.

One thought would be to extend the record that stores a room from 128 bytes to 130 bytes,  keeping in the first two the coordinates of the room.  Then every time the player touches an opening the loader would scan the entire file with the levels trying to identify the possibly “next” room with the values of these first two bytes.

However I decided for a more clear solution.  I introduced another file that correlates map-coordinates into positions in the rooms-file. The first idea was to store in it records of a length of 4 bytes. The first two are the map-coordinates and the last two a short value of the position in the levels-file. 

Finally I decided to keep for the position only one byte since the position is always a multiple of 128. Thus, I multiply the value of this byte with 128 and I have the position where the pointer in the levels-file has to be spring and read from there.

I hope I didn’t ruin your mind.

If you like it please leave a comment, share it, or give it a "g+1".

In a “coming soon” tutorial I will describe how to design rooms with a freeware tile editor and how to produce from the xml (its output) the room file and correlation file.

Wednesday, March 28, 2012

(The easy way) OpenGL, Bypass the power of two (POT) restriction

Many friends have mailed me and told me that they faced difficulties when they tried to apply inside their application the algorithm in my previous post about how to bypass the ‘power of two’ restriction in Open GL ES.

Thus I decided to approach the issue with a much simpler algorithm than the previous one.

Why didn't I do that already in the first post ?

Well, the cost of the simplicity is a little loss of quality.

No, no, don't leave the page. It will be insignificant loss and you can base on this method even commercial products and nobody will observe any issue in the final product.

Let me start again by telling the same story: Your designer has drawn nice backgrounds in a 320x240 resolution like the one with the colored circles in picture 1




picture 1

During the development you test the application on the emulator and you are happy seeing that everything goes fine. Suddenly you transfer your application on the real device and instead of nice backgrounds you see a white rectangle 320x240.

What happened???

OpenGL ES binds as textures only images where the width and the height are both power of 2 (POT). This means that only 32×16, 128×64, 8×256 etc images are supported. It does not sound flexible, huh? It is a certain restriction for your designer (I bet it is you!).

Newer GPU`s that support OpenGL version 2.0 or above can load any arbitrary dimension but why to take such a huge risk for the marketing of your application?

The main idea is very simple: OpenGL is stupid enough to load a texture where width & height are of power of two but since the texture is loaded and bound OpenGL accepts to scale it even using different scale factors for width and height.
What does it mean for our example?

After the picture is ready by your artist and well painted open it in your editor ( I use GIMP) and scale it by giving for new dimensions what you believe is the nearest values that are of power of two. For our example it could be 256x128. Then you have it a stretched image like in picture 2.




picture 1


This image is perfectly loaded and bound as an OpenGL-texture.
But you don’t want it to be 256x128. You want to see circles on the screen, not ellipses.

I am sure you know what the next step will be: You have to stretch it back to the original dimensions. For this there must be calculated the scale factors for width and height.

float fScaleWidth = 320/256 = 1.25f
float fScaleHeight = 240/128 = 1.875f


Q: What values do you need to have as fixed to make it full parametrically?

And then in the render function

if  ( mesh.isBackground == true )
{
     g.glScalef(fScaleFactor*fScaleWidth, fScaleFactor*fBgrScaleHeight, 1.0f);
}


where fScaleFactor is the global scale factor, assuming that you may have designed everything in your game initially for a resolution 320x240 but you want it to fill screens even with bigger resolutions.

Good luck.