If you are not familiar with tile maps, please see the previous article in this series before reading this article.
A space is simply some collection of points, vectors, shapes, and other objects that we use to store the state of our game or simulation. There are various kinds of spaces that can be employed during game development, but the two that I will focus on for this article are the concepts of world spaces and screen spaces. It is important to know the distinction and differences between these two spaces because it will make your game development journey much clearer and easier. Personally, it took me awhile before the concept of separating the spaces really “clicked” for me.
The most commonly understood space is the world space of the game. This is the space that contains the positions of all entities in the game. For example, if we have a 5 x 5 tile map where each tile is 16 x 16, we can represent that map (as discovered in the previous article) as a two dimensional array where [0, 0] is the first tile and [5, 5] is the last tile. Where these tiles are drawn on screen is of no importance when you generate the tile indices in the representative array. The underlying world of your game is represented by this array. The entities live their lives in this boring, mundane, grid-like existence.
All the game interactions and logic take place within this world space because of how extremely simple and efficient it is to perform calculations if we assume our game is as simple as an evenly laid out grid. But when we plays most tile based games, we notice immediately that what we interact with certainly is not as boring as the pictured world space to the left This should make sense to you after thinking about it for a little bit. Think of games like SimCity, Diablo II, or The Legend of Zelda. Even though each of these games has different views and projections, they can still be represented by a very simple tiled world space.
So what about those various projections then? If games that rely on tiles are nothing more than glorified arrays, how do games get those pseudo 3D effects complete with movement, collisions detection, and tile selections with the mouse? This is where the screen space comes in to play. The screen space is nothing more than a visual representation (via rendering) of the underlying world space in which our entities live.
Remember when I said that isometric and oblique projections share the same data structure? I said it because they do! The world space for both projections is identical. Only when you look at their screen spaces do things begin to diverge. By performing the previously discussed transforms to our world space, we can end up with a nice looking screen space in which the player will act and react. In fact, the player does not even know or care about the world space!
World and Screen Relationship
Even though these two spaces are very different, they are related to each other. Anything that occurs in the world space that the player needs to see visually should be translated and expressed in the appropriate screen space through various transformations. Take player entity movement as an example. The player’s entity has a position within the world space that is calculated as a result of user input or other game logic.
Specifically, the picture to the left indicates (in blue) where the player’s current position is in the world space. Currently, the player is at tile index [0, 0] or coordinate (0, 0). If we transformed this world space to screen space using nothing more than the oblique projection math in the previous article, then the player would be situated in the upper left corner of the screen.
If we transform using a rotation and scaling to get an isometric effect, the player’s position shifts towards the center of the screen. This resulting position should not be confused with the player’s actual world space coordinates. It is simply a nice transformation of the world space in order to get a desired visual effect. Again, we have not altered the player’s position in the slightest. All we have done is performed a visual transformation.
If the player moves by pressing the right arrow key, the X position is incremented by 16, and the new world space tile index is [1, 0] or coordinate (16, 0) (remember each tile is 16×16). The game loop performs our draw, which performs the isometric transformation, which shows the player’s movement as down and to the right. Take a second to understand what just happened. Only the player’s X position was changed, but somehow he was visually moved along both the X and Y axes. This is due to that awesome isometric transformation from world space to screen space.
I spent awhile trying to wrap my head around just how I could move my player in an exact isometric manner by calculating how much I needed to change the
X and Y positions. It was never 100% correct, was usually inaccurate, and was not flexible if I wanted to change to another form of projection. When I finally understood the separation between world space and screen space, it became so much clearer. All I had to do was manipulate the world space, perform a transformation to screen space in my render methods, and the rest was history!
In later articles, I will discuss how this separation of spaces makes life a lot easier when it comes to collision detection between entities, event triggering based on tile positions, and tile picking.