In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

units fight

RTS的な、ユニット同士の近接戦闘をイメージして作ってみました。
青いユニットがプレーヤー、緑のユニットが敵のイメージです。
画面上をクリックするとユニットが追加できます。
@author H.Horiuchi
package 
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	
	[SWF(width = 465, height = 465, frameRate = 30, backgroundColor = "#ffffff")]
	
	/**
	 * RTS的な、ユニット同士の近接戦闘をイメージして作ってみました。
	 *  青いユニットがプレーヤー、緑のユニットが敵のイメージです。
	 *  画面上をクリックするとユニットが追加できます。
	 * @author H.Horiuchi
	 */
	public class Main extends Sprite 
	{
		private var movers1:Vector.<Mover> = new Vector.<Mover>();
		private var movers2:Vector.<Mover> = new Vector.<Mover>();
		private var board:BitmapData;
		
		private var mdata1:BitmapData;
		private var mdata2:BitmapData;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			mdata1 = create_bitmapdata1();
			mdata2 = create_bitmapdata2();
			for (var i:int = 0; i < 10; i++) {
				movers1.push(new Mover(random_point(20, 445, 20, 200), Math.PI / 2, mdata1, 200, 10));
				movers2.push(new Mover(random_point(20, 445, 265, 445), -Math.PI / 2, mdata2, 200, 10));
			}
			
			board = new BitmapData(this.stage.stageWidth, this.stage.stageHeight);
			var screen:Bitmap = new Bitmap(board);
			this.addChild(screen);
			draw_movers();
			
			this.stage.addEventListener(MouseEvent.CLICK, add_mover);
			this.addEventListener(Event.ENTER_FRAME, on_enter_frame);
		}
		private function create_bitmapdata1():BitmapData
		{
			var base:Sprite = new Sprite();
			base.graphics.lineStyle(1, 0, 1, true);
			base.graphics.beginFill(0x3333ff);
			base.graphics.drawRoundRect(1, 1, 38, 38, 30);
			base.graphics.endFill();
			
			var data:BitmapData = new BitmapData(40, 40, true, 0);
			data.draw(base);
			return data;
		}
		private function create_bitmapdata2():BitmapData
		{
			var base:Sprite = new Sprite();
			base.graphics.lineStyle(1, 0, 1, true);
			base.graphics.beginFill(0x33ff33);
			base.graphics.drawRoundRect(1, 1, 38, 38, 20);
			base.graphics.endFill();
			
			var data:BitmapData = new BitmapData(40, 40, true, 0);
			data.draw(base);
			return data;
		}
		
		private function add_mover(event:MouseEvent):void
		{
			var x:Number = event.stageX;
			if (x < 20) x = 20;
			if (x > 445) x = 445;
			
			var y:Number = event.stageY;
			if (y <= this.stage.stageHeight / 2) {
				if (y < 20) y = 20;
				if (y > 200) y = 200;
				movers1.push(new Mover(new Point(x, y), Math.PI / 2, mdata1, 200, 10));
				trace("movers1 pushd.");
			} else {
				if (y < 265) y = 265;
				if (y > 445) y = 445;
				movers2.push(new Mover(new Point(x, y), -Math.PI / 2, mdata2, 200, 10));
				trace("movers2 pushd.");
			}
		}
		
		private function draw_movers():void
		{
			board.lock();
			board.fillRect(board.rect, 0xFFFFFFFF);
			
			//var g:Graphics = this.graphics;
			//g.lineStyle(1);
			var draw_mover:Function = function(m:Mover, i:int, v:Vector.<Mover>):void {
				var p:Point = new Point(m.position.x - m.data.width / 2, m.position.y - m.data.height / 2);
				board.copyPixels(m.data, m.data.rect, p, null, null, true);
				
				//g.moveTo(m.position.x, m.position.y);
				//var append:Point = Point.polar(30, m.angle);
				//g.lineTo(m.position.x + append.x, m.position.y + append.y);
			}
			movers1.forEach(draw_mover);
			movers2.forEach(draw_mover);
			//board.draw(this);
			
			board.unlock();
		}
		
		private function on_enter_frame(event:Event):void 
		{
			// move
			var next_movers1:Vector.<Mover> = move_movers(movers1, movers2);
			var next_movers2:Vector.<Mover> = move_movers(movers2, movers1);
			movers1 = next_movers1;
			movers2 = next_movers2;
			
			// attack
			attack_movers(movers1, movers2);
			attack_movers(movers2, movers1);
			
			draw_movers();

			if (movers2.length == 0 || movers1.length == 0) {
				this.removeEventListener(Event.ENTER_FRAME, on_enter_frame);
				
				var message:String = ((movers2.length == 0)? "player": "enemy") + " is WIN!";
				var tf:TextField = new TextField();
				tf.autoSize = TextFieldAutoSize.CENTER;
				var format:TextFormat = new TextFormat();
				format.size = 36;
				format.bold = true;
				tf.defaultTextFormat = format;
				tf.text = message;
				tf.x = (this.stage.stageWidth - tf.width) / 2;
				tf.y = this.stage.stageHeight/ 2 - tf.height;
				this.addChild(tf);
			}
		}
		private function move_movers(target:Vector.<Mover>, opponent:Vector.<Mover>):Vector.<Mover>
		{
			var nexts:Vector.<Mover> = new Vector.<Mover>();
			var center:Point = new Point(this.stage.stageWidth / 2, this.stage.stageHeight / 2);
			for each (var m:Mover in target) {
				var distance:Number = 300;
				var length:Number = 2;
				var angle:Number = get_angle(m.position, center);
				for each (var o:Mover in opponent) {
					var a:Number = get_angle(m.position, o.position);
					var d:Number = Point.distance(m.position, o.position);
					if (Math.abs(m.angle - a) < Math.PI / 6 && d < distance) {
						distance = d;
						length = 3;
						angle = a;
					} else if (Math.abs(m.angle - a) < Math.PI / 2 && d < distance * 2 / 3) {
						distance = d * 3 / 2;
						length = 2;
						angle = a;
					} else if (d < distance / 3) {
						distance = d * 3;
						length = 1;
						angle = a;
					}
				}
				if (length >= distance - 20) {
					length = distance - 20;
				}
				
				var new_m:Mover = m.copy(m.position);
				new_m.position = new_m.position.add(Point.polar(length, angle));
				new_m.angle = angle;
				nexts.push(new_m);
			}
			return nexts;
		}
		private function attack_movers(target:Vector.<Mover>, opponent:Vector.<Mover>):void
		{
			for each (var m:Mover in target) {
				var nearest_index:int = -1;
				var distance:Number = 20;
				opponent.forEach(function(o:Mover, index:int, v:Vector.<Mover>):void {
					var d:Number = Point.distance(m.position, o.position);
					if (d < distance) {
						nearest_index = index;
						distance = d;
					}
				});
				
				if (nearest_index >= 0) {
					if (!opponent[nearest_index].damaged(m)) {
						trace("unit dead.");
						opponent.splice(nearest_index, 1);
					}
				}
			}
		}
		
		private function get_angle(start:Point, target:Point):Number
		{
			return Math.atan2(target.y - start.y, target.x - start.x);
		}
		
		
		private function random_point(x_min:int, x_max:int, y_min:int, y_max:int):Point
		{
			return new Point(
				rand(x_max - x_min) + x_min,
				rand(y_max - y_min) + y_min
			);
		}
		
		/**
		 * get random number in [0 to max).
		 * @param	max
		 * @return random number
		 */
		private function rand(max:int):int
		{
			return Math.floor(Math.random() * max);
		}
	}

}


import flash.display.BitmapData;
import flash.geom.Point;

class Mover
{
	public var position:Point;
	public var angle:Number;
	public var data:BitmapData;
	
	public var max_hit_point:int;
	public var now_hit_point:int;
	public var attack:int;
	public var defence:int;
	public var range:int;
	
	public function Mover(p:Point, angle:Number, data:BitmapData, hp:int, att:int, def:int = 0, r:int = 1):void
	{
		this.position = p;
		this.angle = angle;
		
		this.data = data;
		
		this.max_hit_point = hp;
		this.now_hit_point = hp;
		this.attack = att;
		this.defence = def;
		this.range = r;
	}
	
	public function copy(p:Point):Mover
	{
		var copy:Mover = new Mover(p, this.angle, this.data, this.max_hit_point, this.attack, this.defence, this.range);
		copy.now_hit_point = this.now_hit_point;
		return copy;
	}
	
	public function damaged(enemy:Mover):Boolean
	{
		this.now_hit_point -= enemy.attack - this.defence;
		return this.is_alive();
	}
	public function is_alive():Boolean
	{
		return this.now_hit_point > 0;
	}
}