A Maze Engine for Flash Games, Using ActionScript 2.0

来源:互联网 发布:淘宝代销如何刷信誉 编辑:程序博客网 时间:2024/05/16 12:58
Tutorial details: this tutorial shows how to create the code necessary to build maze games in Flash. Using the new version of ActionScript, it can deal with any maze composed by horizontal and vertical lines. Diagonal and curve paths are not supported.
Tutorial name: A Maze Engine for Flash Games, Using ActionScript 2.0
Written by : Andrei R. Thomaz, andreithomaz@bol.com.br , http://www.rgbdesigndigital.com.br
Difficulty Level: advanced
Requirements: FlashMX 2004
Topics Covered: Maze games, classes, Action Script 2.0
Assumed Knowledge: some knowledge about object oriented programming and the new features introduced by Action Script 2.0
Download FLAs


This engine started with my artworks with mazes for the web. It was first implemented in SVG (Scalable Vector Graphics), using JavaScript. The engine was coded for use in the PacMan 1.0 (www.rgbdesigndigital.com.br/atravesdoespelho/pacman/), a modified version of the PacMan game (this work was selected for Rhizome Artbase and for some net art festivals). I rewrote them for ActionScript 1.0 and, now, I have completed the port for ActionScript 2.0 for use in another net art project (www.rgbdesigndigital.com.br/atravesdoespelho/pacman_minotauro/). I am very happy with the support for classes in FlashMX 2004; the new implementation is the most elegant and structured, more than the FlashMX and the SVG ones.

The engine can be used for the creation of PacMan games, and any game that has some characters moving inside a bidimensional maze. It can deal only with vertical and horizontal paths, but you can extend it for supporting diagonals, if you want.


License Information

You can use these scripts freely, but you have to give me the credits. If it is used in a commercial project, the credits has to be in some section of the game (you can put a '?' in the lower left corners, for example, and use it to show the credits). If it is not a commercial project, it can be put in a separated page.


Introduction to the Maze Engine

Because I did this to make a PacMan game, this will be our reference game along this tutorial. But these principles can be used in any maze game, I think.

First of all, we need to identify what are the elements necessary to run a maze engine. These elements are going to be implemented using the classes, the main feature introduced by ActionScript 2.0 in relation to version 1.0.

All the mazes are composed by paths that connect themselves. The characters (in my case, the PacMan and the monsters) move inside the maze, walking in these paths. Here, we can identify two structures: the groups of lines that compose the maze, and the points (PacMan, monsters, etc.) that move inside the maze.

Moving inside the maze, the point will pass by the lines of the mazes, through the crossroads found in the way. So, we need to represent this information: from one line, to what other lines is it possible to go? Here, it is the third element: the connections among the lines.

So, we have found the three main classes of this maze engine: the maze, composed by lines, the connections and the point(s) that moves inside the maze.

Sample Movie



You must use the keyboard to move the PacMan. If it doesn't move, please, click inside the maze and try again.


Line Class

The Line class is used to build the maze used by the engine. First, we need to break the maze in so many lines as nedeed.


Every one of these colored lines will be represented by a instance of Line class. This is the Line class structure:

class Line {
        var x1:Number; // the coordinates of the Line
        var y1:Number;
        var x2:Number;
        var y2:Number;
        var nType:Number = 0; // horizontal or vertical?
        
        var numConnections:Number = 0;
        var listConnections:Array;
        
        static var Vertical:Number = 1;
        static var Horizontal:Number = 2;
        static var Tolerance:Number = 10;
        
        // these will be used to define the place
        // of connections: in the beginning or in the
        // end of the line?
        static var Beginning:Boolean = true;
        static var End:Boolean = false;
        
        // ....
        // functions
}

Note: I used the static vars to emulate the #define's and enum's from C/C++. The static var was the best method that I found to set the values that I need that be the same in all the files that use them, without having to write a table of values in a paper and put it on my table, near the computer.

The methods of Line Class are:

function Line(nx1:Number, ny1:Number, nx2:Number, ny2:Number)

The constructor. Used to set the values of an Line object.

function addConnection( point:Boolean, mov:Number, Line:Number, point_destiny_line:Boolean)

Adds a connect to the listConnections array. These connections will be used the maze engine to move the points inside the maze (the connects define what movements are possible and what are not; where the maze walls are).

function InTheBeginning(x, y)

Verifies if the given point (x, y) is the beginning of the line. It is important to note that the comparison is not exact: the static var Tolerance is used for that the player not be obrigated to put its character exactly in the line beginning.

function InTheEnd(x, y)

Similar to InTheBeginning().


Connection Class

As is has been said, represents the movements possibles from the beginning or the end of one line. Its structure is the following:

class Connection {
        var bPoint:Boolean; // this connection is in the end or in the beginning of the line?
        // (for these field we use the values defined in the Line class)
        
        var nMovement:Number; // what movement is represented by the connections.
        // the values used are defined by the Direction class.
        var nLine:Number; // for what line this connections goes
        var bPointDestinyLine; // in the beginning or in the end of the destiny line?
}

Connection methods:

function Connection(connection_point:Boolean, mov:Number, destiny_line:Number, line_point:Boolean)

Builds a Connection object with the given values.


Direction Class

This class was created only for set the values for the directions (up, down, right, left) used ty the engine. Its structure is:

class Direction {
        static var Up:Number = 1;
        static var Down:Number = 2;
        static var Left:Number = 3;
        static var Right:Number = 4;
}

Position Class

This class "is" the maze engine, i.e., it contains the biggest part of the code of the engine. It is used to represent the point that moves inside the maze. A Flash game can use several Position objects. Think about the PacMan game: the Pacman and about five monsters move inside the same maze. So, a PacMan that used this engine would have six Position objects, sharing the same maze.

Here is the structure of the Position Class:

class Position {
        var mcMovie:MovieClip; // the movieclip with the object
        // in the screen
        var x:Number = 0;
        var y:Number = 0;
        var nLine:Number = -1;
        var nDirection:Number = 1;
        var bBeginning:Boolean = true;
        var bAutomatic:Boolean = false; // if the connections are
        // done in response to the user actions or if they must
        // be done automatically (in the case of PacMan game,
        // this field would be true for the monsters and false to
        // the PacMan, moved by the user)
        static var maze:Array; // the maze (this is an array of
        // Line objects);
        private static var Step:Number = 5; // how many pixels are
        // there in a step?
        private static var bMazeDone:Boolean = false;
        // when the first Position object used by a Flash game
        // is created, the maze is created too.
        // But this has to be done just once
}

How the Engine Works

The engine works processing the movements of the Position object inside the maze. This movements can be generated by the user (through some scripts that process the keyboard input) or by the game, in the case of objects that are not moved by the user. These movement have to be confronted to the maze (the group of Line objects, in the maze Array) by the engine, that decides if these movements can or can't be done. So, the game communicates with the maze engine through four functions that make the Position object move inside the maze: Up(), Down(), Right(), Left().


Building the maze

Before these four functions, the game's creator has to deal with the maze member of Position class. All the other engine stuff can be ignored by the programmer.

The maze element is an Array object, that contains several Line objects, one Line for one segment in the maze. Personally, I recomend you draw tha maze, break it in the minimum segments needed, and numerate them, as in the following picture:


After doing that, you need to write the code that will build the necessary Line objects. This code is in the createMaze() method of Position class:

private function createMaze(){
        maze = new Array(12); // you need to create an array // as large as your maze
        maze[0] = new Line(0,0,2,0); // one segment
        // the connections from the end and from the beginning of
        // this segment. Set carefully the direction, the destiny
        // line and the point in the destiny line
        maze[0].addConnection(Line.Beginning, Direction.Down, 2, Line.Beginning);
        maze[0].addConnection(Line.End, Direction.Down, 3, Line.Beginning);
        maze[0].addConnection(Line.End, Direction.Right, 1, Line.Beginning);
        
        ...
}

I have created another function, scaleMaze(), that moves and scales the maze coordinates, so it stays with the right size in the screen.


The methods of Position Class

function Position(strMovie:String, line:Number, beginning:Boolean, direction:Number, automatic:Boolean)

The class constructor. If the maze hasn't been built yet, the function createMaze() is invoked. After, an instance of the movie with the strMovie name is created in the stage; this will be the character controlled by the Position object. The line and the beginning parameters set the character's place in the maze. The direction and the automatic parameters are used in the case of characters that are controlled by the computer, i.e., that move by themselves, in the user point of view.

function MakeConnection(connection:Connection)

Invoked by another functions of Position class, is doesn't need to be used by the game itself. It changes the actual line, in the maze, of the character.

functions MakeConnectionAutoBeginning() and
MakeConnectionAutoEnd()

These functions works as MakeConnection, but for the characters moved by the computer. They randomly choose the connection to be done.

functions Up(), Down(), Right() and Left()

These are the Position methods that need to be invoked by the function that processes the user's input. They move the character, if possible. If not, they try to make a connection in the respective direction. If there is no connection available, they make nothing, and the user has to change its direction, for move his/her character.

function updateMovie()

Sets the coordinates of the MovieClip object that is controlled by the Position.

private function createMaze() and scaleMaze()

They have been described above.


Using the Maze Engine

The sample movie show a very simple use of the maze engine, but all the basic concepts are there: there is a function that processes the keyboard input, and calls the correspondents functions of the maze engine. That is the code in the first and only one frame of the movie:

function procKeyboard(){
        if (Key.isDown(Key.LEFT))
        posPacMan.Left();
        if (Key.isDown(Key.RIGHT))
        posPacMan.Right();
        if (Key.isDown(Key.UP))
        posPacMan.Up();
        if (Key.isDown(Key.DOWN))
        posPacMan.Down();
}

// PacManSizeOk is the movie with the PacMan in the right size.
// You need to set it to be exported for ActionScript
var posPacManosition = new Position("PacManSizeOk",0,Line.Beginning,Directio.Down,false);

someListener = new Object();
someListener.onKeyDown = procKeyboard;
Key.addListener(someListener);

stop();

Conclusion

If you look at the work PacMan 1.0, you will see that the maze engine created in SVG has a feature missing in this maze engine, built in Flash: when the PacMan is near of some screen edge, the PacMan stops to move, and the maze moves. I am implementing this feature in some of the works of my new net art project, PacMan and the Minotaur (www.rgbdesigndigital.com.br/atravesdoespelho/pacman_minotauro), but I think this can be done easily. You can see the SVG code to understand how to implement it in this engine.

Others developments possible are the use of diagonal lines and (the most difficult) curves. I don't have the mathemmatic skills nedeed to make that but, if anybody can do it, please, I would like to see the results.


Contact

If you have some doubt or wants to make a comment, feel free to send me a private message or an email to andreithomaz@bol.com.br. Bye. 
原创粉丝点击