flash游戏开发-地图相关-Tile layout非常好的入门教程。

This article will show how to make a tile based layout in AS3, trying to keep OOP architecture.
The project can be compiled from pure code compiler (such as FlexBuilder, flashDevelop) or from a blank file in the flash IDE, pointing the main class from the stage.

The application will get a XML file containing map of number and will translate it to visual map on screen. This has no interaction – just the tile placement and manager.

The program will have X classes. Each class is responsible of doing specific things.

  1. main class – manage everything and create instances of all other classes
  2. XmlLoader – load an XML file and hold it's data
  3. Parser – parse the XML to rows array and cells in rows (each row is an Array)
  4. Screen – receive the array that the parser made, and build a matrix of tiles.
  5. Tile – a single tile; holds type, X position and Y position.

We will get to the Main class at the end.

First class – XmlLoader

package tools
{
	import flash.events.EventDispatcher;
	import flash.net.URLRequest;
	import flash.net.URLLoader;
	import flash.events.Event;
	
	public class XmlLoader extends EventDispatcher{
		
		private var _loader:URLLoader;
		
		private var _xml:XML;
		
		public function XmlLoader(path:String){
			_loader = new URLLoader();
			try{
				_loader.load(new URLRequest(path));
			}catch(e:Error){
				trace("error in loading the XML file")
			}
			_loader.addEventListener(Event.COMPLETE,onLoadXml);
		}
		
		private function onLoadXml(event:Event):void{
			//trace("xml loaded")
			_xml = XML(URLLoader(event.target).data)
			dispatchEvent(new Event(Event.COMPLETE));
		}	
		
		public function get xml():XML{
			return _xml;
		}
	}
}
	

This class receives path to the screen XML file, and tries to load it. When the XML is loaded, the class dispatches (shoot) an event so the class that created the instance of XmlLoader will know the loading process is done and that we can move on (this is a non synchronic operation that's why we need event mechanism).
Please notice that there is one event listening – to the loading operation, and a second event dispatching – so the main class will catch. The first is internal, and the second is to connect with other classes. After loading the XML data, the instance of XmlLoader will hold the data and enable other classes get it through a special getter function it has. Another thing to notice is the try & catch thing there – that handles special error events, and prevents an error message from being send to the user on runtime.

Second class – the parser

The parser's job is very simple – get a XML object and divide it to rows, and each row to single number. Again, after doing it's part, an instance of this class will hold an Array of rows so other classes will be able to read it. This too is done with a getter function. The _rows array is actually 2 dimension array. Every cell in it represent a single row, and every row has multiple digits in it, according to the XML line.

The constructor of the class receives a XML type. Hers how this class looks like:

package tools
{
	public class Parser{
		
		private var _xml:XML;
		private var _rows:Array;
		
		
		public function Parser(xml:XML){
			_xml = xml;
			_rows = new Array();
			getRows();
		}
		
		private function getRows():void{
			// get all rows
			var rows:XMLList = _xml.screen.children();
			var singleRow:Array;
			var rowString:String = rows[i];
			for(var i:uint=0;i<rows.length();i++){
				rowString= rows[i];
				// split numbers in string to cells in singleRow array 
				singleRow = rowString.split("");
				//save singleRow in _rows array;				
				_rows.push(singleRow);
			}	
		}
		
		//return an arra of all rows (every row is an array of numbers
		public function get rows():Array{
			return _rows;
		}
		
	}
}
    

In order for this thing to work, the XML file should have this structure:

<?xml version='1.0' encoding='UTF8'?>
<data>
	<screen id="" title="">
		<row>111111111111111111111111111111</row>
		<row>100000000000000000000000000001</row>
		<row>101000000000000000003300000001</row>
		<row>101000000000000000000000000001</row>
		<row>101111110000001111000000000001</row>
		<row>100000000000004400000000000001</row>
		<row>100000000000000000000111510001</row>
		<row>100000000000000000000000000001</row>
		<row>111111111111111111111111111111</row>
	</screen>
</data>
    

Any other structure will require a change in the parser.

Both Parser and XmlLoader are in a package (folder) called 'tools'.

Third class – a visual one – Screen

The Screen class instance is actually one screen. It receives an array of rows (the kind that the Parser parses to) and build a matrix of tiles from that array. It does it with 2 for loops. The first loop is to run over the lines, and the inner loop is to run within the line over all of the numbers in it. Each time the program is in the inner loop it creates a single tile, and pushes it to an array (so in the future we can get access to all tiles).

This class and the Tile class are in a package called 'visual'.

package visual
{
	import visual.Tile;
	import flash.display.Sprite;
	
	public class Screen extends Sprite{
		
		private var _screenArray:Array;
		private var _tiles:Array;
		
		public function Screen(screenArray:Array){
			_screenArray = screenArray;
			_tiles = new Array();
			var tile:Tile;
			var row:Array;
			
			// create matrix
			for(var i:uint=0;i<_screenArray.length;i++){
				row = _screenArray[i] as Array;
				for(var j:uint=0;j<row.length;j++){
					// create a new tile and push it to _tiles
					tile = new Tile(Number(row[j]),j,i)
					addChild(tile)
					_tiles.push(tile);
				}	
			}		
		}
		
		//let other classes get the tiles array. 
		public function get allTiles():Array{
			return _tiles;
		}
	}
}
    

Fourth class – Tile

The last visual class is the Tile class. It represent a single tile, and holds 3 properties of it:

  • Type (the code in the XML that represent this tile)
  • locationX – represent it's horizontal position in the matrix – numeral location – not pixels in the screen
  • locationY - represent it's vertical position in the matrix

All 3 properties have getter function, so outer objects can "ask" each tile for it's properties. I decided to represent the difference between the tiles type with a color change, though this can be easily changed.

This is how my Tile class look like :

package visual{
	import flash.display.Sprite;
	
	public class Tile extends Sprite{
		
		private var _type:uint;
		private var _locationX:uint;
		private var _locationY:uint;
		
		// colors of tiles
		static private var TILE_TYPES:Array = [0xDDDDDD,
                                               0xFF00AA,
                                               0xCC00CC,
                                               0xCCCC00,
                                               0x3300FF];
		private const TILE_SIZE:uint = 10;
			
		public function Tile(type:uint,locationX:uint,locationY:uint){
			// get parameters 
			_type = type;
			_locationX = locationX;
			_locationY = locationY;
			//draw a square 
			graphics.lineStyle(1,0x000000,0.2);
			// different color by type parameter 
			graphics.beginFill(	TILE_TYPES[_type],1);
			graphics.drawRect(0,0,TILE_SIZE,TILE_SIZE);
			graphics.endFill();
			x=TILE_SIZE*_locationX;
			y=TILE_SIZE*_locationY;
		}
		
		public function get type():uint{
			return _type;
		}
		public function get locationX():uint{
			return _locationX;
		}
		public function get locationY():uint{
			return _locationY;
		}
	}
}
    

The Main class

Finally – the main class. This is what makes the whole thing work:

package {
	import flash.display.Sprite;
	import tools.XmlLoader;
	import flash.events.Event;
	import tools.Parser;
	import visual.Screen

	public class TileGame extends Sprite{
		
		private var _xmlLoader:XmlLoader;
		private var _xmlData:XML;
		private var _screenParser:Parser;
		private var _screenArray:Array;
		private var _screen:Screen;
		
		
		public function TileGame(){
        	var url:String = "http://www.avgil.com/as3/tilegame/screen1.xml";
			try{
			_xmlLoader = new XmlLoader(url);
			} catch(e:Error){
				trace("couldn't load XML file")
			}
			// wait till the XmlLoader will finish loading the data 
			_xmlLoader.addEventListener(Event.COMPLETE,onXmlReady);			
		}
		
		private function onXmlReady(event:Event):void{
			//recieve the XML data from the event
			_xmlData = XmlLoader(event.target).xml as XML;
			//parse and build a screen from parsed data
			_screenParser = new Parser(_xmlData);
			_screenArray = _screenParser.rows;
			_screen = new Screen(_screenArray);
			_screen.x = 50;
			_screen.y = 50;
			addChild(_screen);
		}
	}
}
    

Notice that after the creation on the XmlLoader – the program waits for the XmlLoader to say "Ok – done" , and only then (onXmlReady function), it continue doing it's things.

Here's the Flex project packed in one zip file: TileGame.zip



来自:http://www.gotoandplay.it/_articles/2007/10/tileLayout.php
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值