ND2D: The Main Classes II

the sprites

GameSprite.as

package frogger.sprites {

	import flash.geom.Rectangle;
	
	import frogger.*;
	
	import de.nulldesign.nd2d.display.Node2D;
	import de.nulldesign.nd2d.display.Sprite2D;
	
	public class GameSprite {
		
		public var active:Boolean = true;
		
		public var x:Number;
		public var y:Number;
		public var skin:Sprite2D;
		public var body:Rectangle;
		
		protected var _game:Game;
		
		function GameSprite (game:Game, x:int, y:int) {
			_game = game;
			this.x = x;
			this.y = y;
		}
		
		//move reference point to center of Image
		public function setSkin (skin:Sprite2D):void {
			this.skin = skin;
			skin.x = x;
			skin.y = y;
			_game.screen.spriteBatch.addChild(skin);
		}
		
		public function get width ():Number {
			return this.skin.width;
		}
		
		public function get height ():Number {
			return this.skin.height;
		}
		
		public function get right ():Number {
			return x + this.width * 0.5;
		}
		public function get left ():Number {
			return x - this.width * 0.5;;
		}
		public function get top ():Number {
			return y - this.height * 0.5;
		}
		public function get bottom ():Number {
			return y + this.height * 0.5;
		}
		
		public function get bounds ():Rectangle {
			return new Rectangle(x - skin.width * 0.2, y - skin.height * 0.2, skin.width * 0.8, skin.height * 0.8);			
		}
		
		public function reset():void {}
		
		public function update (dt:Number):void {}
		
		public function show ():void {
			if (skin) skin.visible = true;
		}
		
		public function hide ():void {
			if (skin) skin.visible = false;
		}
	}
}

NumberSprite.as

package frogger.sprites
{
	import de.nulldesign.nd2d.display.Sprite2D;
	import frogger.Game;
	
	
	public class NumberSprite extends GameSprite
	{
		public var value:int = 0;
		protected var _textures:Array;
		protected var _numbers:Vector.;
		
		public function NumberSprite(game:Game, x:int, y:int, nameRoot:String) {
			
			super(game, x, y);
			
			_textures = [];
			_numbers = new Vector.;
			
			var img:Sprite2D;
			for (i = 0; i < 8; i++) {
				img = new Sprite2D();
				_game.screen.spriteBatch.addChild(img);
				img.setFrameByName(nameRoot+"1.png");
				//img.x = x + i * (img.spriteSheet.spriteWidth + 2);
				img.x = x + i * (img.width + 2);
				img.y = y;
				img.visible = false;
				_numbers.push(img);
			}
			
			var i:int;
			
			for (i = 0; i < 10; i++) {
				_textures.push(_numbers[0].spriteSheet.getIndexForFrame(nameRoot+i+".png"));
			}
			
		}
		
		public function showValue (value:uint):void {
			this.value = value;
			var string:String = ""+value;
			var len:int = string.length;
			if (len > 8) return;
			for (var i:int = 0; i < len; i++) {
				_numbers[i].visible = true;
				_numbers[i].spriteSheet.frame = _textures[int(string.charAt(i))];
			}
		}
		
		override public function reset ():void {
			for (var i:int = 0; i < _numbers.length; i++) {
				_numbers[i].spriteSheet.frame = _textures[0];
				if (i > 0) {
					_numbers[i].visible = false;
				}
			}
		}
		
		override public function show ():void {
			hide();
			showValue(value);
		}
		
		override public function hide ():void {
			for (var i:int = 0; i < _numbers.length; i++) {
				_numbers[i].visible = false;
			}
		}
	}
}

Player.as

package frogger.elements {
	
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	import flash.utils.setTimeout;
	import flash.events.Event;
	
	import frogger.*;
	import frogger.screens.GameScreen;
	import frogger.sprites.*;
	import de.nulldesign.nd2d.display.Sprite2D;
	import de.nulldesign.nd2d.materials.texture.ASpriteSheetBase;
	import de.nulldesign.nd2d.events.SpriteSheetAnimationEvent;
	
	
	public class Player extends MovingSprite {
		
		public static const MOVE_TOP:int = 0;
		public static const MOVE_DOWN:int = 1;
		public static const MOVE_LEFT:int = 2;
		public static const MOVE_RIGHT:int = 3;
		
		public var tierSpeed:Number = 0;
		public var dead:Boolean = false;
		
		public var moving:Boolean = false;
		
		public var moveTimer:Timer;
		public var tierIndex:int = 0;
		public var hasBonus:Boolean = false;
		
		private var _frogStand:uint;
		private var _frogJump:uint;
		private var _frogSide:uint;
		private var _frogSideJump:uint;
		private var _restFrame:uint;
		private var _sideStep:int = 22;
		private var _startPoint:Point;
		
		private var _moveCnt:Number = 0.0;
		private var _moveInterval:int = 6;
		
		function Player (game:Game, x:int, y:int) {
			
			super(game, x, y);
			
			_startPoint = new Point(x,y);
			
			//death animation
			//must create animation before adding the skin that will play it, inside the sprite batch
			_game.screen.textureAtlas.addAnimation("death_animation", [
					"death_1.png", 
					"death_2.png", 
					"death_3.png", 
					"death_4.png", 
					"death_4.png", 
					"death_4.png", 
					"death_4.png", 
					"death_4.png"], false);
			
			setSkin(new Sprite2D);
			
			
			//store textures for frog
			_frogStand = skin.spriteSheet.getIndexForFrame("frog_stand.png");
			_frogJump = skin.spriteSheet.getIndexForFrame("frog_jump.png");
			_frogSide = skin.spriteSheet.getIndexForFrame("frog_side.png");
			_frogSideJump = skin.spriteSheet.getIndexForFrame("frog_side_jump.png");
			
			skin.spriteSheet.frame = _frogStand;

			_restFrame = _frogStand;
			
			moveTimer = new Timer(200, 1);
			moveTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onFrogRest);
			moveTimer.start();
		
			
		}
		
		override public function reset ():void {
			
			skin.spriteSheet.frame = _frogStand;
			
			x = skin.x = nextX = _startPoint.x;
			y = skin.y = nextY = _startPoint.y;
			
			active = true;
			hasBonus = false;
			dead = false;
			
			show();
			
			tierIndex = 0;
			skin.scaleX = skin.scaleY = 1;
			skin.spriteSheet.removeEventListener(SpriteSheetAnimationEvent.ANIMATION_FINISHED, onDeathComplete);
		}
		
		public function moveFrogUp ():void {
			if (!moving) {
				tierIndex++;
				if (tierIndex >= Tier.TIER_Y.length) tierIndex = Tier.TIER_Y.length - 1;
				nextY = Tier.TIER_Y[tierIndex] + skin.height*0.5;
				moveTimer.reset();
				moveTimer.start();
				showMoveFrame(MovingSprite.UP);
				_game.gameData.addScore(GameData.POINTS_JUMP);
				_game.sounds.play(Sounds.SOUND_JUMP);
			}
		}
		
		public function moveFrogDown ():void {
			if (!moving) {
				moving = true;
				tierIndex--;
				if (tierIndex < 0) tierIndex = 0;
				nextY = Tier.TIER_Y[tierIndex] + skin.height*0.5;
				_game.gameData.addScore(GameData.POINTS_JUMP);
				_game.sounds.play(Sounds.SOUND_JUMP);
				showMoveFrame(MovingSprite.DOWN);
			}
		}
		
		public function moveFrogLeft ():void {
			if (!moving) {
				moving = true;
				nextX -= _sideStep;
				_game.sounds.play(Sounds.SOUND_JUMP);
				showMoveFrame(MovingSprite.LEFT);
			}
		}
		
		public function moveFrogRight ():void {
			if (!moving) {
				moving = true;
				nextX += _sideStep;
				_game.sounds.play(Sounds.SOUND_JUMP);
				showMoveFrame(MovingSprite.RIGHT);
			}
		}
		
		override public function update (dt:Number):void {
			//play animation if dead
			if (dead) {
				return;
			}
			
			if (moving) {
				if (_moveCnt > _moveInterval) {
					moving = false;
					skin.spriteSheet.frame = _restFrame;
					_moveCnt = 0.0;
				}
				_moveCnt += 20*dt;
			}
			
			//add tier speed if player is on top of a moving object
			nextX += tierSpeed * dt;
			
			place();
		}
		
		
		override public function place ():void {
			//limit movement if player is not on water Tiers so frog does not leave the screen
			if (tierIndex < 7) {	
				if (nextX < width * 0.5) 
					nextX = width * 0.5;
				if (nextX > _game.screenWidth - width * 0.5)
					nextX = _game.screenWidth - width * 0.5
			} else {
				//make player go back to start if frog leaves screen on water Tiers
				if (nextX < -width*0.5 || nextX > _game.screenWidth + width*0.5) {
					_game.sounds.play(Sounds.SOUND_OUTOFBOUNDS);
					reset();
				}
					
			}
			super.place();	
		}
				
		public function kill ():void {
			active = false;
			tierSpeed = 0;
			_game.gameData.gameMode = Game.GAME_STATE_ANIMATE;
			moving = false;
			skin.scaleX = skin.scaleY = 1;
			skin.spriteSheet.playAnimation("death_animation", 0, false, true);
			skin.spriteSheet.addEventListener(SpriteSheetAnimationEvent.ANIMATION_FINISHED, onDeathComplete, false, 0, true);
			dead = true;
		}
		
		private function showMoveFrame (dir:int):void {
			switch (dir) {
				case MovingSprite.LEFT:
					skin.scaleX = -1;
					skin.spriteSheet.frame = _frogSideJump;
					_restFrame = _frogSide;
					break;
				case MovingSprite.RIGHT:
					skin.scaleX = 1;
					skin.spriteSheet.frame = _frogSideJump;
					_restFrame = _frogSide;
					break;
				case MovingSprite.UP:
					skin.scaleY = 1;
					skin.spriteSheet.frame = _frogJump;
					_restFrame = _frogStand;
					break;
				case MovingSprite.DOWN:
					skin.scaleY = -1;
					skin.spriteSheet.frame = _frogJump;
					_restFrame = _frogStand;
					break;
			}
			
		}
		
		private function onFrogRest (event:TimerEvent):void {
			skin.spriteSheet.frame = _restFrame; 
		}

		private function onDeathComplete (event:Event):void {
			
			skin.spriteSheet.stopCurrentAnimation();
			skin.spriteSheet.removeEventListener(SpriteSheetAnimationEvent.ANIMATION_FINISHED, onDeathComplete);
			skin.visible = false;
			
			if (_game.gameData.lives >= 0) {
				setTimeout (
					function ():void {
						reset();
						_game.gameData.gameMode = Game.GAME_STATE_PLAY;
					}, 500
				);
			} else {
				GameScreen(_game.screen).gameOver();
			}
		}
		
	}
}