主要源码如下

/* This code is from "ActionScript 3.0 Game Programming University" by Gary Rosenzweig
Copyright 2007
http://flashgameu.com
See the book or site for more information */

package {
	import flash.display.*;
	import flash.events.*;
	import flash.text.*;
	import flash.geom.*;
	import flash.utils.getTimer;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	
	public class TopDownDrive extends MovieClip {
		
		// constants
		static const speed:Number = .3;
		static const turnSpeed:Number = .2;
		static const carSize:Number = 50;
		static const mapRect:Rectangle = new Rectangle(-1150,-1150,2300,2300);
		static const numTrashObjects:uint = 100;
		static const maxCarry:uint = 10;
		static const pickupDistance:Number = 30;
		static const dropDistance:Number = 40;
		
		// game objects
		private var blocks:Array;
		private var trashObjects:Array;
		private var trashcans:Array;
	
		// game variables
		private var arrowLeft, arrowRight, arrowUp, arrowDown:Boolean;
		private var lastTime:int;
		private var gameStartTime:int;
		private var onboard:Array;
		private var totalTrashObjects:int;
		private var score:int;
		private var lastObject:Object;
		
		// sounds
		var theHornSound:HornSound = new HornSound();
		var theGotOneSound:GotOneSound = new GotOneSound();
		var theFullSound:FullSound = new FullSound();
		var theDumpSound:DumpSound = new DumpSound();

		public function startTopDownDrive() {
			
			// get blocks
			findBlocks();
			
			// place trash items
			placeTrash();
			
			// set trash cans 
			trashcans = new Array(gamesprite.Trashcan1,gamesprite.Trashcan2,gamesprite.Trashcan3);
			
			// make sure car is on top
			gamesprite.setChildIndex(gamesprite.car,gamesprite.numChildren-1);
			
			// add listeners
			this.addEventListener(Event.ENTER_FRAME,gameLoop);
			stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
			stage.addEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
			
			// set up game variables
			gameStartTime = getTimer();
			onboard = new Array(0,0,0);
			totalTrashObjects = 0;
			score = 0;
			centerMap();
			showScore();
			
			playSound(theHornSound);
		}

		// find all Block objects
		public function findBlocks() {
			blocks = new Array();
			for(var i=0;i<gamesprite.numChildren;i++) {
				var mc = gamesprite.getChildAt(i);
				if (mc is Block) {
					// add to array and make invisible
					blocks.push(mc);
					mc.visible = false;
				}
			}
		}
		
		// create random Trash objects 
		public function placeTrash() {
			trashObjects = new Array();
			for(var i:int=0;i<numTrashObjects;i++) {
				
				// loop forever
				while (true) {
					
					// random location
					var x:Number = Math.floor(Math.random()*mapRect.width)+mapRect.x;
					var y:Number = Math.floor(Math.random()*mapRect.height)+mapRect.y;
					
					// check all blocks to see if it is over any
					var isOnBlock:Boolean = false;
					for(var j:int=0;j<blocks.length;j++) {
						if (blocks[j].hitTestPoint(x+gamesprite.x,y+gamesprite.y)) {
							isOnBlock = true;
							break;
						}
					}
					
					// not over any, so use location
					if (!isOnBlock) {
						var newObject:TrashObject = new TrashObject();
						newObject.x = x;
						newObject.y = y;
						newObject.gotoAndStop(Math.floor(Math.random()*3)+1);
						gamesprite.addChild(newObject);
						trashObjects.push(newObject);
						break;
					}
				}
			}
		}
		
		// note key presses, set properties
		public function keyDownFunction(event:KeyboardEvent) {
			if (event.keyCode == 37) {
				arrowLeft = true;
			} else if (event.keyCode == 39) {
				arrowRight = true;
			} else if (event.keyCode == 38) {
				arrowUp = true;
			} else if (event.keyCode == 40) {
				arrowDown = true;
			}
		}
		
		public function keyUpFunction(event:KeyboardEvent) {
			if (event.keyCode == 37) {
				arrowLeft = false;
			} else if (event.keyCode == 39) {
				arrowRight = false;
			} else if (event.keyCode == 38) {
				arrowUp = false;
			} else if (event.keyCode == 40) {
				arrowDown = false;
			}
		}

		// main game code
		public function gameLoop(event:Event) {
			
			// calculate time passed
			if (lastTime == 0) lastTime = getTimer();
			var timeDiff:int = getTimer()-lastTime;
			lastTime += timeDiff;
			
			// rotate left or right
			if (arrowLeft) {
				rotateCar(timeDiff,"left");
			}
			if (arrowRight) {
				rotateCar(timeDiff,"right");
			}
			
			// move car
			if (arrowUp) {
				moveCar(timeDiff);
				centerMap();
				checkCollisions();
			}
			
			// update time and check for end of game
			showTime();
		}
		
		// make sure car stays at center of screen
		public function centerMap() {
			gamesprite.x = -gamesprite.car.x + 275;
			gamesprite.y = -gamesprite.car.y + 200;
		}
		
		public function rotateCar(timeDiff:Number, direction:String) {
			if (direction == "left") {
				gamesprite.car.rotation -= turnSpeed*timeDiff;
			} else if (direction == "right") {
				gamesprite.car.rotation += turnSpeed*timeDiff;
			}
		}
		
		// move car forward
		public function moveCar(timeDiff:Number) {
			// calculate current car area
			var carRect = new Rectangle(gamesprite.car.x-carSize/2, gamesprite.car.y-carSize/2, carSize, carSize);
			
			// calculate new car area
			var newCarRect = carRect.clone();
			var carAngle:Number = (gamesprite.car.rotation/360)*(2.0*Math.PI);
			var dx:Number = Math.cos(carAngle);
			var dy:Number = Math.sin(carAngle);
			newCarRect.x += dx*speed*timeDiff;
			newCarRect.y += dy*speed*timeDiff;
			
			// calculate new location
			var newX:Number = gamesprite.car.x + dx*speed*timeDiff;
			var newY:Number = gamesprite.car.y + dy*speed*timeDiff;
			
			// loop through blocks and check collisions
			for(var i:int=0;i<blocks.length;i++) {
				
				// get block rectangle, see if there is a collision
				var blockRect:Rectangle = blocks[i].getRect(gamesprite);
				if (blockRect.intersects(newCarRect)) {
		
					// horizontal push-back
					if (carRect.right <= blockRect.left) {
						newX += blockRect.left - newCarRect.right;
					} else if (carRect.left >= blockRect.right) {
						newX += blockRect.right - newCarRect.left;
					}
					
					// vertical push-back
					if (carRect.top >= blockRect.bottom) {
						newY += blockRect.bottom-newCarRect.top;
					} else if (carRect.bottom <= blockRect.top) {
						newY += blockRect.top - newCarRect.bottom;
					}
				}
				
			}
			
			// check for collisions with sidees
			if ((newCarRect.right > mapRect.right) && (carRect.right <= mapRect.right)) {
				newX += mapRect.right - newCarRect.right;
			}
			if ((newCarRect.left < mapRect.left) && (carRect.left >= mapRect.left)) {
				newX += mapRect.left - newCarRect.left;
			}
			
			if ((newCarRect.top < mapRect.top) && (carRect.top >= mapRect.top)) {
				newY += mapRect.top-newCarRect.top;
			}
			if ((newCarRect.bottom > mapRect.bottom) && (carRect.bottom <= mapRect.bottom)) {
				newY += mapRect.bottom - newCarRect.bottom;
			}
		
			// set new car location
			gamesprite.car.x = newX;
			gamesprite.car.y = newY;
		}
		
		// turn car left or right
		// check for collisions with trash and trash cans
		public function checkCollisions() {
			
				
			// loop through trash cans
			for(var i:int=trashObjects.length-1;i>=0;i--) {
		
				// see if close enough to get trash objects
				if (Point.distance(new Point(gamesprite.car.x,gamesprite.car.y), new Point(trashObjects[i].x, trashObjects[i].y)) < pickupDistance) {
						
					// see if there is room
					if (totalTrashObjects < maxCarry) {
						// get trash object
						onboard[trashObjects[i].currentFrame-1]++;
						gamesprite.removeChild(trashObjects[i]);
						trashObjects.splice(i,1);
						showScore();
						playSound(theGotOneSound);
					} else if (trashObjects[i] != lastObject) {
						playSound(theFullSound);
						lastObject = trashObjects[i];
					}
				}
			}
			
			// drop off trash if close to trashcan
			for(i=0;i<trashcans.length;i++) {
				
				// see if close enough
				if (Point.distance(new Point(gamesprite.car.x,gamesprite.car.y), new Point(trashcans[i].x, trashcans[i].y)) < dropDistance) {
					
					// see if player has some of that type of trash
					if (onboard[i] > 0) {
						
						// drop off
						score += onboard[i];
						onboard[i] = 0;
						showScore();
						playSound(theDumpSound);
						
						// see if all trash has been dropped off
						if (score >= numTrashObjects) {
							endGame();
							break;
						}
					}
				}
			}
		}
		
		// update the time shown
		public function showTime() {
			var gameTime:int = getTimer()-gameStartTime;
			timeDisplay.text = clockTime(gameTime);
		}
		
		// convert to time format
		public function clockTime(ms:int):String {
			var seconds:int = Math.floor(ms/1000);
			var minutes:int = Math.floor(seconds/60);
			seconds -= minutes*60;
			var timeString:String = minutes+":"+String(seconds+100).substr(1,2);
			return timeString;
		}
		
		// update the score text elements
		public function showScore() {
			
			// set each trash number, add up total
			totalTrashObjects = 0;
			for(var i:int=0;i<3;i++) {
				this["onboard"+(i+1)].text = String(onboard[i]);
				totalTrashObjects += onboard[i];
			}
			
			// set color of all three based on whether full
			for(i=0;i<3;i++) {
				if (totalTrashObjects >= 10) {
					this["onboard"+(i+1)].textColor = 0xFF0000;
				} else {
					this["onboard"+(i+1)].textColor = 0xFFFFFF;
				}
			}
			
			// set number left and score
			numLeft.text = String(trashObjects.length);
			scoreDisplay.text = String(score);
		}
		
		// game over, remove listeners
		public function endGame() {
			blocks = null;
			trashObjects = null;
			trashcans = null;
			this.removeEventListener(Event.ENTER_FRAME,gameLoop);
			stage.removeEventListener(KeyboardEvent.KEY_DOWN,keyDownFunction);
			stage.removeEventListener(KeyboardEvent.KEY_UP,keyUpFunction);
			gotoAndStop("gameover");
		}
		
		// show time on final screen
		public function showFinalMessage() {
			showTime();
			var finalDisplay:String = "";
			finalDisplay += "Time: "+timeDisplay.text+"\n";
			finalMessage.text = finalDisplay;
		}
		
		public function playSound(soundObject:Object) {
			var channel:SoundChannel = soundObject.play();
		}
	}
		
}