forked from: colin challenge for professionals ブラックホール

by whirlpower forked from colin challenge for professionals (diff: 676)
制限時間内に玉を集めて高得点をねらいます。
* 青が10点、黄色が20点、白が50点です。
* 
* 中央のNEWを押すとスタートします。
* 
* 玉の位置の同期や、スコアの同期がいまいちうまく行かなかったので、
* 対戦ゲーム的なものにはできませんでした。 同時接続した人はジャマする役になります。
*
* はいタイムアップ。
♥0 | Line 519 | Modified 2009-08-24 09:37:09 | MIT License
play

ActionScript3 source code

/**
 * Copyright whirlpower ( http://wonderfl.net/user/whirlpower )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3E1Y
 */

/*
 * 制限時間内に玉を集めて高得点をねらいます。
 * 青が10点、黄色が20点、白が50点です。
 * 
 * 中央のNEWを押すとスタートします。
 * 
 * 玉の位置の同期や、スコアの同期がいまいちうまく行かなかったので、
 * 対戦ゲーム的なものにはできませんでした。 同時接続した人はジャマする役になります。
 *
 * はいタイムアップ。
 */

package
{
	import flash.display.Sprite;
	import net.user1.reactor.*;
	import net.user1.logger.Logger;
	import flash.events.Event;
	import flash.display.BlendMode;
	import flash.events.MouseEvent;
	import caurina.transitions.Tweener;
	
	[SWF(width = "465", height = "465", backgroundColor = "0x000000", frameRate = "60")]
	
	// メインクラス
	public class UnionRamen extends Sprite
	{
		// Union用オブジェクト
		protected var reactor	:Reactor;
		protected var ramenRoom	:Room;
		
		// ゲーム用
		private var balls		/*Ball*/:Array = [];
		private var gravitys	/*GravityBall*/:Array = [];
		private var gravity		:GravityBall;
		private var ballMax		:int = 50;
		private var dotNew		:DotNew;
		
		// コンストラクタ
		public function UnionRamen():void
		{
			trace( "UnionRamen" );
			
			reactor = new Reactor();// 接続用のReactorオブジェクトを作成
			reactor.addEventListener(ReactorEvent.READY, readyListener);	// 接続完了したら readyListener() を起動
			
			// Unionに接続。
			reactor.connect("tryunion.com", 9100);	// "tryunion.com:9100"は自由に使えるUnionテスト用の公開サーバーです
			reactor.getLog().setLevel(Logger.DEBUG);
		}
		
		// 接続完了時に起動されるメソッド
		protected function readyListener (e:ReactorEvent):void
		{
			// このアプリ用のルームを作成
			ramenRoom = reactor.getRoomManager().createRoom( "wonderfl.whirlPowerRoom" );		// あなたのアプリ専用のIDを使ってください
			
			// プレイヤーの参加 メッセージ受け取り
			ramenRoom.addMessageListener("NEW_PLAYER", newPlayerLisner ); // 新しいプレイヤーの追加
                        ramenRoom.addMessageListener("CHANGE_POSITION", onGestPosition); // その他のプレイヤーの位置変更を受け取
                        ramenRoom.addMessageListener("DELETE_POSITION", onGestDelete); // その他のプレイヤーの位置変更を受け取る
			
			ramenRoom.join();			// ルームに入室
			gameInit();
		}
		
		// メッセージをうけとって、表示位置を変更する。
	    private function onGestPosition( from:IClient,data:String ):void
            {
                        var str		:/*String*/Array = data.split(",");
                        var id		:Number = Number( str[0] );
                        var posX	:Number = Number( str[1] );
                        var posY	:Number = Number( str[2] );
			
			var g:GravityBall = getGravityById( id );
			if ( !g ) return;
			
			g.x = posX;
			g.y = posY;			
            }
		
	    // メッセージをうけとって、重力源を削除する。
	    private function onGestDelete( from:IClient,data:String ):void
            {
                        var str		:/*String*/Array = data.split(",");
                        var id		:Number = Number( str[0] );
			
			var newArray :Array = [];
			
			var leng:int = gravitys.length;
			for (var i:int = 0; i < leng; i++) 
			{
				if ( gravitys[i].id == id )
				{
					removeChild( gravitys[i] );
				}
				else
				{
					newArray.push( gravitys[i] );
				}
			}
			gravitys = newArray;
             }
		
		// 入力のIDの重力源を取得する
		private function getGravityById( id:Number ):GravityBall
		{
			var leng:int = gravitys.length;
			for (var i:int = 0; i < leng; i++) 
				if ( gravitys[i].id == id )
					return gravitys[i];
			return null;
		}
		
		// メッセージをうけとって、新規に重力源を取得する
	    private function newPlayerLisner( from:IClient,data:String ):void
            {
                        var str		:/*String*/Array = data.split(",");
                        var id		:Number = Number( str[0] );
                        var color	:Number = Number( str[1] );
                        var posX	:Number = Number( str[2] );
                        var posY	:Number = Number( str[3] );
			//trace( "new Player  id = " + id + "color = " + color + "posX = " + posX + "posY = " + posY );
			
			// 重力源を作る
			var _gravity:GravityBall = createGravity( id, color, 4, 100, 3 );
			_gravity.x = posX; 
			_gravity.y = posY;
            }
		
		// NEWボタンが押されたとき、自分の重力源をつくる。
		private function newClick( evt:MouseEvent ):void
		{
			if ( gravity )
			{
				removeChild( gravity );
			}
			
			// 重力源を作る
			gravity = createGravity( Math.random(), Math.random() * 0xFFFFFF, 4, 100, 3 );
			gravity.addEventListener( GravityBall.DEAD, myGrvityisDead );
			
			// メッセージ送信 sendMessage( メッセージ名, 自分自身も受信するかどうか, フィルター )
			ramenRoom.sendMessage( "NEW_PLAYER", false, null, String( gravity.id +", " + gravity.color + ","+ gravity.x + "," + gravity.y ) );
			
			dotNew.visible = false;
		}
		
		// 重力源を生成する
		private function createGravity( id:Number, color:uint, radius:Number, area:int, mass:int ):GravityBall
		{
			var _gravity:GravityBall = new GravityBall( id, color, radius, area );
			_gravity.x	  = stage.stageWidth  / 2;
			_gravity.y	  = stage.stageHeight / 2;
			_gravity.mass = mass;	// 引力
			
			addChild( _gravity );
			gravitys.push( _gravity );
			
			return _gravity;
		}
		
		// ステージをクリックで場所を移動
		private function onClick( evt:MouseEvent ):void
		{
			if( gravity )
			{
				gravity.x = mouseX;
				gravity.y = mouseY;
			}
			// メッセージ送信 sendMessage( メッセージ名, 自分自身も受信するかどうか, フィルター )
			ramenRoom.sendMessage("CHANGE_POSITION", false, null, String( gravity.id +","+ gravity.x + "," + gravity.y ) );
		}
		
		// 自分の重力源が死亡
		private function myGrvityisDead( evt:Event ):void
		{
			dotNew.visible = true;
			ramenRoom.sendMessage( "DELETE_POSITION", false, null, String( gravity.id ) );
		}
		
		// ゲームの初期化
		private function gameInit():void
		{
			for (var i:uint = 0; i < 3000; i++)
			{
				createBall();
			}
			
			// new
			dotNew = new DotNew( 0xFFFFFF, 1 );
			addChild( dotNew );
			
			dotNew.x = int( stage.stageWidth/2 - dotNew.width / 2 );
			dotNew.y = int( stage.stageHeight * 0.5 );
			
			dotNew.addEventListener( MouseEvent.CLICK, newClick );
			addEventListener( Event.ENTER_FRAME, loop);
			stage.addEventListener( MouseEvent.CLICK, onClick );
		}
		
		private var count:uint = 0;
		
		// エンターフレーム
		private function loop( evt:Event ):void
		{
			var ball:Ball;
			var gravity:GravityBall;
			
			// ボールの挙動
			for each( ball in balls )
			{
				ball.next();
				
				// 画面の端っこの衝突判定
				if ( ball.x < 0 )
				{
					ball.x = 0;
					ball.vx *= -1;
				}
				if( ball.x > stage.stageWidth )
				{
					ball.x = stage.stageWidth;
					ball.vx *= -1;
				}
				if ( ball.y < 0 )
				{
					ball.y = 0;
					ball.vy *= -1;
				}
				if( ball.y > stage.stageHeight )
				{
					ball.y = stage.stageHeight;
					ball.vy *= -1;
				}
			}
			
			// 引力の影響
			for each( gravity in gravitys )
			{
				var newArray:Array = [];
				for each( ball in balls )
				{
					
					// 引力計算
					if ( gravity.inArea( ball ) )
					{
						gravitate( gravity, ball );
					}
					
					// 吸収判定と配列の作り直し
					if ( !gravity.isEat( ball ) )
					{
						newArray.push( ball )
					}
					else
					{
						removeChild( ball );
					}
				}
				balls = newArray;
			}
			
			// ボールを追加する
			createBall();
		}
		
		// 玉を生成する
		private function createBall():void
		{
			count ++;
			if ( count % 600 == 0 && balls.length < ballMax )
			{
				newBall( 0xFFFFFF, 3, 50 );
			}
			if ( count % 300 == 0 && balls.length < ballMax )
			{
				newBall( 0xFFEE33, 2, 20 );
			}
			if ( count % 30 == 0 && balls.length < ballMax )
			{
				newBall( 0x5577EE, 2, 10 );
			}
		}
		
		private function newBall( color:uint, radius:Number = 2, score:int = 10 ):void
		{
			var ball:Ball = new Ball( color, radius );
			
			ball.x	  = Math.random() * stage.stageWidth;
			ball.y	  = Math.random() * stage.stageHeight;
			ball.vx	  = Math.random() * 10 - 5;
			ball.vy	  = Math.random() * 10 - 5;
			ball.mass = 3;
			ball.score = score;
			ball.blendMode = BlendMode.ADD;
			
			addChildAt( ball, 0 );
			balls.push(ball);
		}
		
		//引力の計算
		private function gravitate( ballA:Ball, ballB:Ball ):void
		{
			var dx		:Number = ballB.x - ballA.x;
			var dy		:Number = ballB.y - ballA.y;
			var dist	:Number = Math.sqrt( dx * dx + dy * dy );
			var force	:Number = ballA.mass * ballB.mass / dist*2;
			var ax		:Number = force * dx / dist;
			var ay		:Number = force * dy / dist;
			
			ballA.vx += ax / ballA.mass;
			ballA.vy += ay / ballA.mass;
			ballB.vx -= ax / ballB.mass;
			ballB.vy -= ay / ballB.mass;
		}
	}
}

import flash.display.Shape;
import flash.display.Sprite;

// 吸い込まれるボール  ------------------------------------------------------
internal class Ball extends Sprite
{
	public var core		:Shape = new Shape();
	
	public var vx		:Number = 0;
	public var vy		:Number = 0;
	public var radius	:Number = 10;
	public var mass		:Number = 10;
	public var friction	:Number = 0.998;
	public var dead		:Boolean = false;
	public var score	:int	= 10;
	
	public function Ball( color:uint, radius:Number ):void
	{
		this.radius = radius;
		core.graphics.beginFill( color, 1 );
		core.graphics.drawCircle( 0, 0, radius );
		core.graphics.endFill();
		addChild( core );
	}
	
	public function next():void
	{
		x += vx;
		y += vy;
		
		vx *= friction;
		vy *= friction;
	}
}

import caurina.transitions.Tweener;
import flash.utils.Timer;
import flash.events.Event;

// 吸い込むボール  ------------------------------------------------------
internal class GravityBall extends Ball
{
	public  var id		:Number = 0;
	public  var color	:int	= 0;
	public  var ring	:Shape = new Shape();
	
	public  var area 	 :Number = 10;
	public  var myScore  :int = 0;
	private var dotScore :DotScore;
	
	private var timer	 :Timer;
	private var dotTimer :DotScore;
	private var life	:int = 10;
	
	public static const DEAD:String = "dead";
	
	public function GravityBall( id:Number, color:int, radius:Number, area:Number ):void
	{
		super( color, radius );
		this.area = area;
		this.color = color
		this.id = id;
		
		mouseEnabled = false;
		mouseChildren = false;
		
		// スコアの表示
		dotScore = new DotScore( 0xFFFFFF, 4, 1 );
		dotScore.score = myScore;
		addChild( dotScore );
		
		dotScore.x = int( -dotScore.width / 2 );
		dotScore.y = int( radius + 2 );
		
		// 吸引範囲の表示
		ring.graphics.beginFill( 0xFFFFFF, 0.15 );
		ring.graphics.drawCircle( 0, 0, 10 );
		ring.graphics.endFill();
		addChild( ring );
		
		Tweener.addTween( ring, { scaleX:area * 0.1, scaleY:area * 0.1, time:0.5, transition:"easeOutSine" } );	
		
		// タイマー
		timer = new Timer( 1000, 0 );
		timer.addEventListener( "timer", onTimerCount );
		timer.start();
		
		dotTimer = new DotScore( 0xFFFFFF, 2, 1 );
		dotTimer.score = life;
		addChild( dotTimer );
		
		dotTimer.x = int( -dotTimer.width / 2 );
		dotTimer.y = int( -radius - 2 -dotTimer.height );
	}
	
	public function onTimerCount( evt:Event ):void
	{
		life -= 1;
		dotTimer.score = life;
		
		if ( life <= 0 )
		{
			dispatchEvent( new Event( DEAD ) );
			timer.stop();
			Tweener.addTween( ring, { scaleX:0, scaleY:0, time:0.5, transition:"easeOutSine" } );	
		}
	}
	
	public function isEat( ball:Ball ):Boolean
	{
		// 寿命が尽きていたら処理しない
		if ( !life ) return false;
		
		if ( radius > dist( ball ) )
		{
			myScore += ball.score;
			dotScore.score = myScore;
			return true;
		}
		
		return false;
	}
	
	public function inArea( ball:Ball ):Boolean
	{
		// 寿命が尽きていたら処理しない
		if ( !life ) return false;
		
		if ( dist( ball ) < area )
		{
			return true;
		}
		
		return false;
	}
	
	public function dist( ball:Ball ):Number
	{
		var dx:Number = x -ball.x;
		var dy:Number = y -ball.y;
		return Math.sqrt( dx * dx + dy * dy );
	}
}


// ドット数字のスコアのグラフィック ------------------------------------------------------
internal class DotScore extends Shape
{
	private var maxCount	:int = 1;
	private var padding		:int = 1;
	private var dotSize		:int = 2;
	private var color		:int = 0x000000;
	private var currentX	:int = 0;
	
	private var _score:int = 0;
	public function set score( v:int ):void
	{
		if ( v >= maxCount ) return;
		draw( v );
	}
	public function get score():int { return _score; }
	
	public function DotScore( color:uint, padding:int, dotSize:int = 2 )
	{
		this.padding = padding;
		this.dotSize = dotSize;
		this.color	 = color;
		
		setGraphic();
		
		for (var i:int = 0; i < padding; i++)
			maxCount *= 10;
	}
	
	private function draw( num:int ):void
	{
		graphics.clear();
		currentX = 0;
		
		var numList:Array = [];
		var tempNum:int = num;
		var i:int = 0;
		
		// 入力の数字を解体する
		for ( i = 0; i < padding; i++ ) 
		{
			var drawNum:int = tempNum % 10;
			numList.push( drawNum );
			tempNum = int( tempNum * 0.1 );
		}
		
		// 描画する
		for ( i = numList.length-1; i >= 0; i-- ) 
		{
			drawGraph( numList[i] );
		}
	}
	
	private function drawGraph( num:int ):void
	{
		var dot:Array =	dotNumData[num];
		
		for (var i:int = 0; i < 3; i++) // 横
		{
			for (var j:int = 0; j < 5; j++) // 縦
			{
				if ( dot[j][i] )
				{
					graphics.beginFill( color, 1 );
					graphics.drawRect( currentX + i*dotSize, j*dotSize, dotSize, dotSize );
					graphics.endFill();
				}
			}
		}
		currentX += dotSize * 4;
	}
	
	private var dotNumData /*Array*/:Array = [];
	private function setGraphic():void
	{
		var array:Array;
		
		// 0
		array = [
				[ 1, 1, 1 ],
				[ 1, 0, 1 ],
				[ 1, 0, 1 ],
				[ 1, 0, 1 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
		
		// 1
		array = [
				[ 1, 1, 0 ],
				[ 0, 1, 0 ],
				[ 0, 1, 0 ],
				[ 0, 1, 0 ],
				[ 0, 1, 0 ]
			]
		dotNumData.push( array );
		
		// 2
		array = [
				[ 1, 1, 1 ],
				[ 0, 0, 1 ],
				[ 1, 1, 1 ],
				[ 1, 0, 0 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
		// 3
		array = [
				[ 1, 1, 1 ],
				[ 0, 0, 1 ],
				[ 1, 1, 1 ],
				[ 0, 0, 1 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
		// 4
		array = [
				[ 1, 0, 1 ],
				[ 1, 0, 1 ],
				[ 1, 1, 1 ],
				[ 0, 0, 1 ],
				[ 0, 0, 1 ]
			]
		dotNumData.push( array );
		// 5
		array = [
				[ 1, 1, 1 ],
				[ 1, 0, 0 ],
				[ 1, 1, 1 ],
				[ 0, 0, 1 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
		// 6
		array = [
				[ 1, 1, 1 ],
				[ 1, 0, 0 ],
				[ 1, 1, 1 ],
				[ 1, 0, 1 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
		// 7
		array = [
				[ 1, 1, 1 ],
				[ 1, 0, 1 ],
				[ 0, 0, 1 ],
				[ 0, 0, 1 ],
				[ 0, 0, 1 ]
			]
		dotNumData.push( array );
		// 8
		array = [
				[ 1, 1, 1 ],
				[ 1, 0, 1 ],
				[ 1, 1, 1 ],
				[ 1, 0, 1 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
		// 9
		array = [
				[ 1, 1, 1 ],
				[ 1, 0, 1 ],
				[ 1, 1, 1 ],
				[ 0, 0, 1 ],
				[ 1, 1, 1 ]
			]
		dotNumData.push( array );
	}
}

// ドットのNEW ------------------------------------------------------
internal class DotNew extends Sprite
{
	private var currentX	:int = 0;
	private var dotNumData /*Array*/:Array =
		[
			[ 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1 ],
			[ 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1 ],
			[ 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1 ],
			[ 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1 ],
			[ 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1 ]
		];
		
	public function DotNew( color:uint, dotSize:int = 2 )
	{		
		buttonMode = true;
		
		graphics.beginFill( color, 0.2 );
		graphics.drawRect( -3, -3, dotNumData[0].length * dotSize + 6, dotNumData.length * dotSize + 6 );
		graphics.endFill();
		
		for (var i:int = 0; i < dotNumData[0].length; i++) // 横
		{
			for (var j:int = 0; j < dotNumData.length; j++) // 縦
			{
				if ( dotNumData[j][i] )
				{
					graphics.beginFill( color, 1 );
					graphics.drawRect( currentX + i*dotSize, j*dotSize, dotSize, dotSize );
					graphics.endFill();
				}
			}
		}
	}
}