3.2. BASICS OF 2D MAPS - ENTITIES IN A MAP

 Intro

As usual, look at the BoF2 screenshot.
Breath of Fire II for SNES
Breath of Fire II for SNES

Now you know how to make a simple map, and how to manage very basic physical laws, as movement and line-of-sight. But we don't have explained how to "include" living and non-living entities (as NPCs), and how to manage the physics between those entities (collisions). This is the task of this lesson - explain what entities "live" inside a map and "where". But listen: In this lesson you'll learn how NPCs and other entities are represented in the map, but not how they are really managed. This is task for other lessons.

 Entities in a map

Finally, we have a (lame :-P) map (lesson 3-0), and some (sqr(lame) :-P) physics implemented on it (lesson 3-1). But inside the map live "real" entities, that have some kind of behaviour.  Who are they?. In lesson 4, you'll know. But now, let's introduce them...

 NPCs
Of Course, NPCs are one of the most important elements that live inside a map. They are the people that interacts with our avatars, people to talk with, to cheat with, or to fight with.

 Objects
Every treasure chest you see in every CRPG is an object. Is something you can interact with, use or take.

 Eggs
This is a very important concept. An egg is something you don't see, but you can interact with it. In a more simple way: they are the mechanisms of the game that (among other things) creates the cinematic scenes, that open the doors, and that teleports you to a new map. An example: In the Breath of Fire screenshot: Who teleports you outside the town. And who teleports you inside the houses?. The eggs ^_-.

 Effects
Fire, Lighting, Lasers,... all these things that are created by other entites or by the map, are effects.

 Entities and the map. Map coordinates

All the entities seen in the previous section exist somewhere in the game world. I's not the same thing to be inside the town and outside the town, in front of one house and in front of another. Therefore, they must have some coordinates that  locate them inside the map. Let's review again the example of the past lesson, involving Wolv (the cat), Rui (the human) and Bug (the green thing).
 
  0
1
2
3
 0 
1 1 2 1
 1
1 1 2 2
 2
1 1 1 1
 3
3 3 3 3
 4
1 1 1 1

Now, look at the numbers. They identify every row and column of our grid, locating every tile inside our map. We can use those numbers to represent the coordinates of the entities inside the game world, in tiles. Horizontal row is called X, and Vertical row is called Y. So, if we represent the coordinates of the entities like <X,Y> pairs, we can see that Wolv is in <0,0>, Bug is in <3,0>, and Rui is in <1,4>. Now, the players are located inside the map ^_-.

There is another way of locating players inside a map: using the coordinates in pixels of the upper-left corner of the entity. Thus, if every tile is 24x24 pixels, Wolv would be at <0,0>, Bug would be at <72,0>, and Rui would be at <24,96>. This is the most common way to manage positions in the map, and we'll see why in next lessons (an hint: when NPCs move they don't move tile by tile - they move pixel by pixel).

Summarizing - Entities are located inside a map...
  1. ...using tile coordinates, knowing that the upper-left corner of the map is <0,0> (i.e. Rui is in <1,4>)
  2. ...using pixel coordinates, knowing that the upper-left corner of the map is <0,0> (i.e. Rui is in <24,96>)

 Physical interactions between entities

In the last lesson we saw how to implement simple physics in a 2D map. Now that we have add entities living inside that map, we have a new physical law to manage: collisions.
Two entities collide when one part of their bodies are at the same place in the same time. This is absolutely impossible for "real" things, so we must add some type of management. The usual way to manage this is to "block" - one entity cannot go where another entity is.
There is another type of management, "warn" - when "fake" entities (non-real) are involved. One example is the eggs. When a NPC step into (collide with) an egg, the egg receives a warning. The warning "hatchs" the egg, that executes some property/code (open a dor, launch a cinematic scnee,...). Consider this an spoiler for new lessons ^_-

Well, back to the point. When we can know when two entities collide?. Easy: When they are in the same place at the same time. Or in other words - when they are going to be in the same place at the same time.
 
  0
1
2
3
 0 
1 1 1 1
 1
1 1 1 1

Review the above map. Rui is in <0,1>, and Wolv is in <0,0>. Now imagine that Rui wants to move up. In the next turn, he should be in <0,0>. But wait... Wolv is in that tile now!. Well, this means that Rui and Wolv have collisioned.

If NPCs move only from one tile to other tile, collisions are that simple - just check for every NPC if their coordinates are equal to my future coordinates. However, things aren't that simple. NPCs usually moves pixel-by-pixel, not tile-by-tile. What we can do in this case?. The secret lies on consider the NPCs as squares - they have their upper-corner in a certain pixel, and have a size.
 
  0
1
2
 0 
(24,0) =>
- <= (47,23)
 1
- - -

So, a NPC located in <(1,0)> [tile coordinates, being a tile 24x24 pixels] with size 24x24, will be in the square <(24,0),(47,23)> [Translation: <(1 * Tam_Tile_X , 0 * Tam_Tile_Y) , ((1 * Tam_Tile_X) + (Tam_Pnj_X - 1) , (0 * Tam_Tile_Y) + (Tam_Pnj_Y - 1))>]
 
  0
1
2
3
 0 
wolv - - -
 1
rui - - -

In this case, collision detection means testing if one rectangle is inside of another. Consider Rui is in <0,24>, and Wolv is in <0,0>. Both has 24x24 as size. We can say that Wolv is in the square <(0,0),(23,23)> [not 0-24 because 0,1,...,22,23 are 24 pixels] and Rui is in the square <(0,24),(23,47)>. If Rui wants to move up 1 pixel, he would be in <(0,23),(23,46)>. But look!. Rui's square overlaps Wolv square!. So... they collide.

Finally, there is a simple optimization if your NPCs move from one tile to another - just create a grid storing where are your NPCs

X
0
1
2
0
W
-
B
1
R
-
-

... and the collision checking is only test if the next tile is occupied by other NPC. This way, we don't have to navigate through all the NPCs to check whether we collide or not.