RPG Enemy Attacking – Part 1

November 12th, 2008

Every RPG will an enemy, and there several ways to go about implementing enemies into our RPG game, the two ways I can think of off the top of my head are:

• Enemies on the map will chase the Hero if the Hero gets too close
• Random battle encounter every so many steps the Hero takes

If we go with option 2, we simply check what type of map/level it is, set a random number, and every step the Hero takes we decrement that random number, and if that random number reaches below 0, we go to a battle scene. If we go with option 1, there would be 2 kinds of ways to have our Enemies chase our Hero. One way is, we can have the enemies chase the Hero straight on, or secondly, use a little path finding.

Most of the time, developers develop path finding for tiled base games. They use either a true or false value, or 1 or 0 value, in their two dimensional array to check if that tile is walkable or not, and using that array information and some path finding algorithms they are able to find the quickest path from start to finish. The most popular kind of path finding algorithm is the A* for flash. And we will be using that (I won’t be showing how to use that yet, but more of how to set up or RPG game to prepare ourselves to be using that).

When developers use this path finding, they know its commonly used for tiled base, and tend to think to develop a tiled base game without considering how to develop a work around. Like our RPG game for example, its not a tiled base game so therefore developers would commonly think to go with option 1 of our enemies chasing the Hero option and have our enemies follow the Hero straight on. This is ok, but what if your Hero runs around a wall or a bush to hide? You will most likely end up noticing that the enemy who was chasing you will keep running directory into the wall or bush without any sense of walking around it. Pathetic.

So lets brain storm on how we can implement tiled base path finding into our RPG game.

Problem: Enemies chasing our Hero in a vector RPG world, we can’t use A* because of this.
Solution/Work-Around: Simply check what is walkable and non-walkable. Create temporary tiles on top of the vector world doing a collision detection with that tile and the objects to determine what is walkable and non-walkable.

Create a new movie clip and call it “Tile”. Click on the “Export for Actionscript” check box and hit “OK”. Now in your “Tile” movie clip, create a 32×32 gray border-less rectangle and have it be centered within the movie clip, as shown below:

You can of course change the width and height of the rectangle for a more accurate path, but the smaller you make it, the longer it will take to find the path from start to finish.

Let me try to demonstrate to you by code “exactly” how this process will work. In the first frame on the main time line on the “–script–” layer, write this right after the hero object. This will be a global array for our tiles:

[as]
// tiles, will be a 2 dimensional array to determine if that ’tile’ is walkable or not
var tiles:Array;
[/as]

In the function game_begin at the bottom of the script, apple this piece of code after the set_level_items function is being executed:

[as]
// create the walkable tile array
set_tiles(lvl);
[/as]

Finally, lets create the function set_tiles. This function serves as a purpose to create the walkable and non-walkable tiles in our tiles array, and display what tiles are walkable for testing purposes. Right above the game_begin function, create the function set_tiles like so:

[as]
// determines what parts of the map is walkable and not walkable in our level
function set_tiles(lvl_mc:MovieClip):void {

// set to empty
tiles = new Array();

// attach tile movie clip to level movie clip
var t:Tile = new Tile();
lvl_mc.addChild(t);

// get the width and height of the level movie clip
var num_children:int = lvl_mc.numChildren;
var w:int = lvl_mc.width;
var h:int = lvl_mc.height;

// loop as if it was a tile based game, replacing the tile as we go

// height
for(var i:int = 0; i < (h / t.height); i++) { // create a new array tiles[i] = new Array(); // width for(var j:int = 0; j < (w / t.width); j++) { // assume the tile is walkable tiles[i][j] = 1; // reposition the tile t.x = j * t.width; t.y = i * t.height; // loop through the number of children in the level movie clip for(var k:int = 0; k < num_children; k++) { // holder of movie clip var mc = lvl_mc.getChildAt(k); // if the movie clip doesn't have the name 'instance' in it, we assume its not walkable if(mc.name.indexOf("instance") == -1 && mc.name.indexOf("item") == -1) { // set either 1 or 0 if this tile is walkable if(tiles[i][j] == 1) { tiles[i][j] = (hit_test(t, mc, true) ? 0 : 1); } } } // end for k loop // remove this if statement completely, its just for testing/displaying purposes only if(tiles[i][j] == 1) { var tile:Tile = new Tile(); tile.x = t.x; tile.y = t.y; tile.alpha = .5; tile.name = "test"; lvl_mc.addChild(tile); } } } // remove the tile, we don't need it anymore lvl_mc.removeChild(t); } [/as] 2. Create the function set_tiles, requiring the level movie clip that was passed
5. With the global variable tiles, clean it out by declaring it as a new Array()
8 – 9. This variable t will hold the temporary Tile while we loop through determining what tiles are walkable and are non-walkable. At the end of the function we get rid of this.
12 – 14. Here we get the number of children the passed lvl_mc has, and store its width and height into local variables
19. Start looping for the i’s, which is the height of the map
22. Create a new array element for the tiles array with i being its new index value
25. Start looping for the j’s, which is the width of the map
28. Here we set a value by default, which will come in handy a couple lines down. We set it to 1 assuming that this tile will be walkable
31 – 32. Reposition the temporary Tile to the new position on the level
35. Start looping through all the number of children the level has
38. This simply acts as a holder for grabbing that instance at that particular index
41. If the holder (mc) does not contain the word “instance” and contains the word “item”, continue inside the if statement. This is to make sure that we only test with mc what could be non-walkable.
44 – 46. Here we check to see if the tiles[i][j] value is 1, and if it is, we do a collision detection/hit test with the mc and the temporary Tile t. If you recall, we have made this function hit_test in our previous tuts.
50. Stop looping through the number of children in the lvl_mc
53 – 60 These lines of code are just for demonstrating purposes. It checks to see if tiles[i][j] value is 1, and if it is, it will create another temporary Tile and place it where the walkable tiles are… so you can see what is walkable and non-walkable.
62 – 63. Stop the for i and for j loop
66. Remove the temporary Tile t since we are no need of it.
68. Close the function set_tiles function

Next time we will attach some enemies to the stage and have them chase the Hero around the stage. If all goes well, you should have something like this in the end:

Download the fla file here

AS3 > Games > RPG

5 Responses to “RPG Enemy Attacking – Part 1”

  1. annonymous Says:

    Great work, keep it up! can’t wait for the next piece!

  2. Jeff Says:

    accessing this page from google sends me to a spyware site, typed in your domain and browsed to here and everything worked fine, not sure if its your site or my computer, just letting you know in case its the first.

  3. admin Says:

    Its the shared web host we have (my wife and I). We plan on changing web hosts in the next couple of months.

    Sorry everyone, I can’t fix it until then

  4. Simasuu Says:

    Good site, good tutorials! I’m somewhat fluent with flash coding and I have a rpg pet project of my own. Making a Npc chace a target in a non-tile environment is interesting task, and in my own game I created a solution where a helper movieclip “stick” is scaled, rotated and positioned so that movieclip origo is in npc current location and the “end of the stick” is where the target is. The stick clip has arrays of points, making straight and curved paths. Once the “stick” is positioned, the paths are checked for collision detection (using localToGlobal), and if a free path is found the points of the path are stored in npc destination array. Just with 3 paths NPC:S will chase player character around corners really convincingly. If you are intersted seeing this in more detail, send me an email.

  5. Simasuu Says:

    And as addition to my previous reply, I have a working example of the freeform pathfinding in Flash here: http://www.flare-rpg.org – Go check, its cool =)