Tilemapping:

The Tilemap


What’s immediately noticeable upon going into a chapter of fire emblem? It is played on a grid system of squares!The player and enemy AI moves their cursor and units based on the grid system.Before, I code anything else involving gameplay and logic, this is paramount to making sure the strategy portion of the game works properly.


Immediately studying the grid system they have, I dissected the parts that make the whole.
Each square( or as I am going to refer to as a tile hereon thereforth), has its own texture,
terrain effects(I will explain once we get to the game logic, for now it's unimportant),
and always at some points the player cursor will hover over it.
As well, for the most part, only one unit can occupy one tile at all times.
Finally, I do need to consider how big every tile is and where it is on the map.

Creating a square


Start off simple. I needed to be able to draw a single tile to the screen,
without any textures or specific positioning.

The simplest way of doing so was just to make a drawTile function within my tile class and initialize a global tile object for testing.
The drawTile will only be placed in render() for now.

I kept the background color to a random color, and drew a square of  tileSize 64.0. Why 64.0? For aesthetically pleasing reasons, I needed to keep only a certain number of tiles on screen so each tile needed to be a certain size. The program is only running at a resolution of 640x640, and 640/64 which is 10.
This means I can draw only 10 tiles in any single cardinal direction.
Later on, I will explain how I handled getting the offscreen tiles.

I used GL_QUADS to make the squares, and used the tile size for each vertex location of the square.
An issue that occured in early testing was that the square was not fully visible.
This is because openGL will only consider the origin of the square as spot to put it,
so the bottom half and left half was cut off.
I then included a glTranslate() function and passed in the tileSize of that tile
to move it in the proper position

Chess


Since I considered ahead of time how the map works, I deduced how to make a tilemap. The next challenge on the board is that I need to draw many tiles.
I decided on a nice map size of 32x32 for simplicity sake, although it may be shortened in the future.
In the Map class, the tile 2D array was given a [32][32] size to represent this.

Ok, since all the work for drawing one tile was already complete, all I needed to do was perform this for every tile in the 2D array. Simple enough. In my Map class, I created an initMap() function. The only purpose of this was to load in maps before the game starts, and to create their respective data. This way, all the information was already stored before I began drawing the tiles. I also created a drawMap function.
It has one simple job, iterate through the Tile map[32][32] object, and call each tile’s own drawTile() function.
Since each tile has its own tileSize, and properties,
this seemed the most elegant solution.

Is this that appeared after doing that? Nope!
I did not consider each tile’s position in respect to the one before it. I solved this issue by adding position X,Y variables in the Tile class. Then in the initMap() function, I set the current X,Y using temporary variables beginning at 0.
For the inner loop, since it drew tiles based on the Y position, I incremented my temporary Y by the constant TILE_SIZE, then in the outer loop, increment X by TILE_SIZE.

Okay, this gave each tile its own position, based on where it is in the 2D array.

The next job was to include this the glTranslate() function in drawTile.
Since I gave each tile its own position variables,
I only needed to add this to the function to move each tile.

One minor thing to add, is that I added a color variable that alternated between each square,
and determined whether if it was one color or the other, this is unimportant and was only for demonstration purposes.

Now that the above picture is created, we have to consider how a player moves.

Movement


First of all, we need to show the player where exactly their cursor is. The simplest method is the color one tile a different color, later on I will create a function that will draw a defining cursor over the current tile.

In my tile class, there is an activeTile variable that is initialized to 0. Because I only need to consider only one tile is hovered over, and the tiles are the object in question here, it makes complete sense to put it there.

How do I then determine which tile is hovered over?
While I can likely include this in a global scope, or in the tileClass itself, the best method was to begin my Player Class.

This player class for now will only hold position variables, and functions that act on those variables for now. We will add a playerCursorX, playerCursorY, and initialize them to 0,0 at instantiation. While I can initialize them to anything I want, this is for simplicity sake.
This also includes why I chose separate variables over an array for the position variables.

We then needed to check when a key was pressed,
I included the check_keys(changed to camelCase for consistency), and called a changePlayerCursorPosition(x,y) function whenever a respective key was pressed. This would add 1, or -1 to either variable in the Player object. This is where I needed to consider boundary checking. I did not want the player to traverse outside the limits of my map array. Thus, I needed to check whether the player was at the 0 in X or Y, and the MAX_MAP_SIZE-1,
and if they chose to move off the map the function would move them back before the game rendered the next frame.

Cool, now that we have boundary checking, we need to display where the player is. In my Map Class, a checkCursorTile() was made. It was called if and if only X11 detected an event. This function iterated through the map 2D array, and checked if the current iteration of i was == PlayerCursorX, and j == PlayerCursorY, and set the activeTile variable in that tile of map[i][j] to 1. Else, it set activeTile to 0.

Now we have movement in any direction and it indicates it to the player.
Is it the most efficient method of programming it? Most likely not. Does it work as I expected it to?
Yup.



Textures

While usually in a game environment, graphics would need to be one of the later things to consider,
I needed to build the barebones of the tile’s effect on units. Along the way, I also needed to
be sure I can load any map, and have a decent looking screen. I might as well then include texturing these tiles in the process.  This also gave me good reason to make my map loading functionality.

So, since I knew each tile needed its own texture, I created a texture class. This will also give some modularity later on for character sprites.
The Texture class included information about the texture itself, and included functions to set these parameters and retrieve them.

I as well grabbed the Image class from my 3350 project that was originally from Rainforest.cpp, just a heads up Gordon and anyone who reads this.

Back to the Tile class, I appended a tileID, Image* tileIMG, Texture class object named terrain,
and functions that set and retrieved these parameters.
The tileID is used for now to only choose specific terrain, and tileIMG is the image used for the texture terrain variable.

To explain the tileID, in fire emblem and in many 2D games, each tile has an image and properties to it.
Above all the class code, I also included an enum function, which I could use to use meaningful names for setting the correct tile texture and effects. For example, if I wanted to use grass as my texture, I only needed to check ‘Grass’. These would correspond to a position in the global Image object.
If ‘Grass’ was enumerated as ‘0’, my setTileType() function would check  if the tileID was equal to ‘Grass’.
If my TileID was 0, then it would set it to grass and grab from the Image array, img[Grass]. Later on, this tileID will have more effect on the gameplay loop,
but for now it is used to determine texture used.

Before we move onto setting the TileID, I needed to determine how to get this tileID. What determines it? I then created a mapLoad function in my map class,
that will read in a file from the /chapter/ directory.
When a map class object is instantiated, my constructor will take in a filename, and call this function.
This function just reads in integers from a .map file(Just a cheeky .txt file, I am just having fun at this point), and stores them into the mapData variable I made so long ago.
So now I have another 2D array, this time only filled with numbers corresponding to the type of tile that will live there.

Then in initMap(), I included a function that gets the integer stored in the mapData variable and sets it as the tileID in the map[][] array. Immediately following this, the setTileType function is called, and using the new tileID, it sets the appropriate parameters and img tied to that tile I wish to use at that spot.

One last thing, we need to set and generate the textures for each tile using the image.  In setTileType, a function of the Tile Class, I explained it checks the tileID and sets the appropriate image already.
It also calls grabbing the height and width of that image, and generates a texture for that image.

Now we just need to bind the corresponding texture of the texture to the tile. Since I already have a texture for each tile, I only need to get the texture from the terrain variable and use glBindTexture(GL_TEXTURE_2D, terrain.getTexture()) to do so. Now each square has a binded texture and image, and some future proofing for gameplay logic.

I also tried my map making, by making a lake.
And the map file itself for the lake.

Scrolling


Thought I was done with this? Nope.
I never considered the possibility if the player legally moves offscreen. I only considered if they moved off the map.

Remember, that usually when we move around in space in openGL, we are not actually moving the camera, rather, moving the space around the camera.
To apply this concept here, I just needed to translate each square.

Good thing I was already doing so in drawTile().
In Fire emblem, when the player moves offscreen, the screen moves one row/column over until they reach the edge.

To accomplish this, I knew I only needed to add a multiplier*tileSize to the glTranslatef() function in drawTile.

Back to the Player Class, I created a function named isPlayerOffScreen(), and variables called playerOffsetX, and playerOffsetY.  In addition, the global class now has variables named offsetX, and offsetY in respect.
In changePlayerCursorPosition, playerOffsetX and playerOffsetY are incremented at the same time as playerX and playerY and follow the same constraints.

At the bottom of this function, I call isPlayerOffScreen()
The function only keeps the running value of the playerOffSet between 0 and 9.

I kept it as 0 and 9 because I only want to draw 10 tiles in any direction at once. If the player is on the last tile to the right(Tile 9, playerOffsetX = 10), it would add a negative 1 to the global offsetX and change the playerOffsetX back to 9.  If the moved offscreen to the left, it added 1 to offsetX. Similarly for Y.

Remember the multiplier I mentioned earlier?
Yup, it is global offsetX and offsetY. When the game begins, the global offset is at 0. So this means not to move any squares anymore than their initial position when the map is created.

When it is -1, it would subtract one square distance.
This means if the square was on the last column on the right, it is now moved to the left. If it is 1, it moves everything right.

One last thing to consider, what if the player is on the boundaries of the map? In changePlayerCursorPosition() I checked if they were.
If they were on the left/bottom(0,0), the playerOffSet is not subtracted and is reset to 0.

If they were on the right/top, playerOffset is not added, and is reset back to 9(meaning they are at the edge).

And now we can scroll. Later on, I can assume I can reuse this concept to shift sprites in respect to the tile’s position.