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

SiON TETRISizer Online

勝手にオンライン対戦化 by keno42
追加ルール
* ゲーム開始時は右の青い四角のいずれか(emptyのもの)をクリックしてください
* 2列以上消すと消した列数-1だけ敵にラインを送り込みます
* 敵を倒すと、敵のスコアの半分を自分のスコアにプラスします
* 自分でラインを消したときのLEVELの増え方がゆるやかになっています
* 敵を倒すとLEVELが+1されます
-------------------------------------------------------------------------------- 
TETRISiON ~ もし水口哲也がテトリスを作ったら
-------------------------------------------------------------------------------- 
< controls >
move;[Left]-[Right]/  drop;[Down]/  hard-drop;[Up]/  L-turn;[Z]/  R-turn;[X]
swap;[C] = Swap current block and stocked block.
< special rules >
1) The level increases by 1 erasing.
2) The game is finished at level 32.
3) The field has only 8 rows.
4) You can erase lines with "chain combo".
5) You can stock 1 block and swap it wherever.
6) The bonus is doubled over level 24.
7) [bonus] = ([erased line count]^2 + [chain combo count]^2) * 100
< notice >
This flash uses cookie to keep hi-score.
If you do not want, please press "CLEAR COOKIE" button.
-----------------------------------------------------
/**
 * Copyright keno42 ( http://wonderfl.net/user/keno42 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cifX
 */

// 勝手にオンライン対戦化 by keno42
// 追加ルール
// * ゲーム開始時は右の青い四角のいずれか(emptyのもの)をクリックしてください
// * 2列以上消すと消した列数-1だけ敵にラインを送り込みます
// * 敵を倒すと、敵のスコアの半分を自分のスコアにプラスします
// * 自分でラインを消したときのLEVELの増え方がゆるやかになっています
// * 敵を倒すとLEVELが+1されます
//-------------------------------------------------------------------------------- 
//  TETRISiON ~ もし水口哲也がテトリスを作ったら
//-------------------------------------------------------------------------------- 
//  < controls >
//     move;[Left]-[Right]/  drop;[Down]/  hard-drop;[Up]/  L-turn;[Z]/  R-turn;[X]
//     swap;[C] = Swap current block and stocked block.
//  < special rules >
//     1) The level increases by 1 erasing.
//     2) The game is finished at level 32.
//     3) The field has only 8 rows.
//     4) You can erase lines with "chain combo".
//     5) You can stock 1 block and swap it wherever.
//     6) The bonus is doubled over level 24.
//     7) [bonus] = ([erased line count]^2 + [chain combo count]^2) * 100
//  < notice >
//     This flash uses cookie to keep hi-score.
//     If you do not want, please press "CLEAR COOKIE" button.
//-------------------------------------------------------------------------------- 

package {
	import flash.filters.ConvolutionFilter;
    import flash.net.*;
    import flash.geom.*;
    import flash.events.*;
    import flash.display.*;
    import flash.filters.GlowFilter;
    import flash.utils.escapeMultiByte;
    import frocessing.color.FColor;
    import frocessing.math.FMath;
	import net.user1.reactor.AttributeEvent;
	import net.user1.reactor.IClient;
	import net.user1.reactor.Reactor;
	import net.user1.reactor.ReactorEvent;
	import net.user1.reactor.Room;
	import net.user1.reactor.RoomEvent;
	import net.user1.reactor.RoomManagerEvent;
	import net.user1.reactor.RoomSettings;
	import net.user1.reactor.Status;
	import net.user1.reactor.UpdateLevels;
    import org.libspark.betweenas3.BetweenAS3;
	import org.libspark.betweenas3.easing.Bounce;
	import org.libspark.betweenas3.easing.Expo;
    import org.libspark.betweenas3.tweens.ITween;
    import com.bit101.components.*;
    import org.si.sion.events.*;
	import net.wonderfl.score.basic.*;
    
    public class Main extends Sprite {
		private const TOP_LEFT_MARGIN:int = 32;
		private const NEXT_TEXT_X:int = 257;
		private const NEXT_BOX_WIDTH:int = 90;
		private const NEXT_BOX_GAP:int = 12;
		private const MAIN_BLOCK_SIZE:int = 25;
		private const SMALL_BLOCK_SIZE:int = 12;
		private const LINE_BLOCKS:int = 8;
		private const ENEMY_LEFT_MARGIN:int =TOP_LEFT_MARGIN + 2 * NEXT_BOX_GAP + NEXT_BOX_WIDTH + MAIN_BLOCK_SIZE * LINE_BLOCKS;
        private const NEXT_BLOCK_X:int = 315;
        private const NEXT_BLOCK_Y:int = 102;
        private const ROOM_WIDTH:int = 180;
        private const ROOM_HEIGHT:int = 40;
		private const ROOM_X:int = 270;
		private const ROOM_Y:int = 32;
		private const ROOM_GAP:int = 10;
		private const ROOM_NUMBER:int = 8;
		
		private var r:Reactor = new Reactor();
		private var roomObjs:Array = [];
		private var roomQualifier:String = "w.tso";
		private var roomName:String = "g"; // g4_1 for room #5, player #2
		private var gameRoomName:String = "w.tsop";
		private var room:Room;
		private var playingRoom:Room;
		
        private var sion:SiON, pv3d:PV3D;
        private var screen:BitmapData = new BitmapData(465,465,false), canvas:Shape = new Shape(), g:Graphics = canvas.graphics;
        private var blockTextures:Vector.<BitmapData> = new Vector.<BitmapData>(7, true), dropBlock:BitmapData = new BitmapData(200, 200, true); 
        private var blockSmallTextures:Vector.<BitmapData> = new Vector.<BitmapData>(7, true); 
        private var scoreLabel:Label, levelLabel:Label, linesLabel:Label, msgb:Label, msgw:Label, msgs:Label , bsf:BasicScoreForm, bsrv:BasicScoreRecordViewer;
        private var nameLabel:Label, enemyLabel:Label, winsLabel:Label;
        private var msgbd:BitmapData = new BitmapData(200, 80, true, 0), mmat:Matrix=new Matrix(3,0,0,3), msg:Bitmap, messageTween:ITween;
        private var smat:Matrix=new Matrix(1.04,0,0,1.04,-4.65,-9.3), scolt:ColorTransform=new ColorTransform();
        private var idField:Vector.<uint>=new Vector.<uint>(200), stockID:uint, nextID:uint, dropID:uint;
        private var eidField:Vector.<uint> = new Vector.<uint>(200);
        private var dropX:int, dropY:int, dropR:int, drawX:Number, drawY:Number, drawR:Number = 0.0, speed:Number;
        private var frameCount:int, phase:int, score:int, level:Number, lines:int, bestResult:*, wins:int;
        private var pt:Point=new Point(), rc:Rectangle = new Rectangle(), mat:Matrix = new Matrix();
        private var keyPushed:int, keyPressed:int, slideCount:int, _joined:Boolean = false;
        private var delLineFlag:int, delLines:int, delChains:int, lineBrghtness:Number, scaleEffect:int;
		private var mainSprite:Sprite = new Sprite();
		private var lobbySprite:Sprite = new Sprite();
		private var challengerLabel:DisplayObject;
		private var youWonLabel:DisplayObject;
        private var tetromino:Array = [
            Vector.<int>([0x0660, 0x0660, 0x0660, 0x0660, 4]), Vector.<int>([0x2222, 0x0f00, 0x4444, 0x00f0, 4]),
            Vector.<int>([0x0622, 0x0740, 0x4460, 0x02e0, 4]), Vector.<int>([0x0264, 0x0063, 0x0132, 0x0630, 3]), 
            Vector.<int>([0x0644, 0x0470, 0x2260, 0x0e20, 4]), Vector.<int>([0x0462, 0x0036, 0x0231, 0x0360, 3]),
            Vector.<int>([0x0262, 0x0072, 0x0232, 0x0270, 3])
        ];
        public var backcolor:int; // controled by betweenas3
        
    //---------------------------------------- main
        function Main() : void {
			_myName = loaderInfo.parameters["viewer.displayName"];
			if ( _myName == null ) _myName = "Anonymous";
            pv3d = new PV3D();
            sion = new SiON(_onBeat, _onNoteOn);
            addEventListener(Event.ADDED_TO_STAGE, _onAddedToStage);
            addEventListener(Event.ENTER_FRAME, _onEnterFrame);
			r.addEventListener(ReactorEvent.READY, onReady);
			r.connect("tryunion.com", 80);
		}
        
    //---------------------------------------- handlers
        private function _onAddedToStage(e:Event) : void {
			//mainSprite.alpha = 0.5;
            stage.frameRate = 30;
            Style.LABEL_TEXT = 0x808080;
            Style.BUTTON_FACE = 0x404040;
            Style.PANEL = 0x404040;
            //Style.BACKGROUND
            addChild(new Bitmap(screen));
			addChild(mainSprite);
			addChild(lobbySprite);
			for ( var i:int = 0; i < ROOM_NUMBER; i++ ) {
				var roomObj:RoomObject = new RoomObject(ROOM_WIDTH, ROOM_HEIGHT, i);
				lobbySprite.addChild(roomObj);
				roomObjs.push(roomObj);
				roomObj.addEventListener(MouseEvent.CLICK, onClick);
				roomObj.x = ROOM_X;
				roomObj.y = ROOM_Y + (ROOM_HEIGHT + ROOM_GAP) * i ;
			}
			lobbySprite.mouseChildren = false;
			if ( r.isReady() ) { _startWatching(); } else { _isWaitingForWatching = true; }
            _effectButton(225, 444).setSize(78, 18);
            _scoreButton(305, 444).setSize(78, 18);
            _tweetButton(385, 444).setSize(78, 18);
            _resetButton(2, 444).setSize(78, 18);
			challengerLabel = _makeLabel(mainSprite, "HERE COMES A NEW CHALLENGER!!", 2);
			youWonLabel = _makeLabel(mainSprite, "YOU WON!!", 3);

            new Label(mainSprite, NEXT_TEXT_X, TOP_LEFT_MARGIN, "NEXT");
            new Label(mainSprite, NEXT_TEXT_X, TOP_LEFT_MARGIN + NEXT_BOX_WIDTH + NEXT_BOX_GAP, "STOCK");
            nameLabel = _status(TOP_LEFT_MARGIN, 0, "PLAYING AS : " + _myName);
            enemyLabel = _status(257, 242, "ENEMY :");
            winsLabel = _status(257, 282, "WINS :");
            levelLabel = _status(257, 322, "LEVEL :");
            scoreLabel = _status(257, 362, "SCORE :");
            linesLabel = _status(257, 402, "LINES :");
            msgs = new Label(this, 64, 260, ""); 
            msgs.scaleX = msgs.scaleY = 1.5;
            msgs.visible = false;
            msgs.filters = [new GlowFilter(0, 0.6, 2, 2)];
            Style.LABEL_TEXT = 0x404040; msgb = new Label(null, 64, 200, "");
            Style.LABEL_TEXT = 0xc0c0c0; msgw = new Label(null, 64, 200, "");
            addChild(msg = new Bitmap(msgbd));
            msg.x = 32;
            msg.alpha = 0;
            phase = TITLE;
            _loadCookie();
            _initialize();
            _startTitle();
        }
		
		private function _makeLabel(target:DisplayObjectContainer, label:String, scale:Number):DisplayObject
		{
			var temp:Sprite = new Sprite();
			new Label(temp, 0, 0, label);
			var bmpData:BitmapData = _makeRedOutlinedBitmapData(temp);
			while ( temp.numChildren ) temp.removeChildAt(0);
			temp.addChild(new Bitmap( bmpData ) );
			temp.scaleX = temp.scaleY = scale;
			temp.x = 466;
			temp.y = 200;
			return target.addChild(temp);
		}
		
		private function _makeRedOutlinedBitmapData(DO:DisplayObject):BitmapData
		{
			var tempBmp:BitmapData = new BitmapData(DO.width + 2, DO.height + 2, true, 0x0);
			tempBmp.draw(DO, new Matrix(1, 0, 0, 1, 1, 0), new ColorTransform(1, 0, 0));
			tempBmp.draw(DO, new Matrix(1, 0, 0, 1, 1, 2), new ColorTransform(1, 0, 0));
			tempBmp.draw(DO, new Matrix(1, 0, 0, 1, 0, 1), new ColorTransform(1, 0, 0));
			tempBmp.draw(DO, new Matrix(1, 0, 0, 1, 2, 1), new ColorTransform(1, 0, 0));
			tempBmp.draw(DO, new Matrix(1, 0, 0, 1, 1, 1));
			return tempBmp;
		}
		
        private function _onEnterFrame(e:Event) : void {
            _drawBackground();
            phaseMain[phase]();
            _drawField();
            keyPushed = 0;
            lineBrghtness *= 0.9;
            ++frameCount;
        }
        
        private function _onKeyDown(e:KeyboardEvent) : void { keyPressed = keyPushed = e.keyCode; }
        private function _onKeyUp(e:KeyboardEvent) : void { keyPressed = 0; }
		
		// union
		private var _isWaitingForWatching:Boolean = false;
		private function onReady(e:ReactorEvent):void 
		{
            stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, _onKeyUp);
			r.getRoomManager().addEventListener(RoomManagerEvent.ROOM_ADDED, onRoomAdded);
			r.getRoomManager().addEventListener(RoomManagerEvent.ROOM_COUNT, onRoomCount);
			r.getRoomManager().addEventListener(RoomManagerEvent.WATCH_FOR_ROOMS_RESULT, onWatchForRoomsResult);
			r.self().setAttribute("name", _myName);
			if ( _isWaitingForWatching ) _startWatching();
			_isWaitingForWatching = false;
		}
		
		private var _roomNum:Number = 0;
		private function onRoomCount(e:RoomManagerEvent):void 
		{
			_roomNum = r.getRoomManager().getNumRooms(roomQualifier);
			if ( _roomNum == _observingRoomNum ) {
				_lobbyReady();
			}
		}
		
		private function _lobbyReady():void
		{
			for ( var i:int = 0; i < ROOM_NUMBER; i++ ) {
				var roomIndex:int = i;
				var roomObj:RoomObject = roomObjs[roomIndex];
				var room:Room = r.getRoomManager().getRoom(roomQualifier+"."+roomName+i+"_0");
				if ( !room ) {
					roomObj.setPlayer1(null, null);
				} else {
					var clients:Array = room.getOccupants();
					if ( clients.length == 0 ) {
						roomObj.setPlayer1(null, null);
					} else {
						roomObj.setPlayer1(IClient(clients[0]).getAttribute("name"), IClient(clients[0]).getAttribute("wins"));
					}
				}
				room = r.getRoomManager().getRoom(roomQualifier+"."+roomName+i+"_1");
				if ( !room ) {
					roomObj.setPlayer2(null, null);
				} else {
					clients = room.getOccupants();
					if ( clients.length == 0 ) {
						roomObj.setPlayer2(null, null);
					} else {
						roomObj.setPlayer2(IClient(clients[0]).getAttribute("name"), IClient(clients[0]).getAttribute("wins"));
					}
				}
			}
			lobbySprite.mouseChildren = true;
		}
		
		// room join
		private function onClick(e:MouseEvent):void 
		{
	
            _message("TETRISizer\nOnline", null, "Starting...");
			lobbySprite.mouseChildren = false;
			var roomObj:RoomObject = RoomObject(e.target);
			var roomSettings:RoomSettings = new RoomSettings();
			roomSettings.removeOnEmpty = true;
			roomSettings.maxClients = 1;
			if ( room && room.clientIsInRoom(r.self().getClientID()) ) {
				return;
			}
			room = r.getRoomManager().createRoom(roomQualifier + "." + roomName + roomObj.index +"_0" , roomSettings);
			room.addEventListener(RoomEvent.JOIN_RESULT, onJoinResult);
			room.join();
		}
		private function onJoinResult(e:RoomEvent):void 
		{
			var roomSettings:RoomSettings = new RoomSettings();
			roomSettings.removeOnEmpty = true;
			roomSettings.maxClients = 1;
			switch( e.getStatus() ) {
				case Status.SUCCESS:
					_onJoin(Room(e.target).getRoomID().substr(roomQualifier.length + roomName.length + 1).split("_")[0]);
					break;
				default:
					room = r.getRoomManager().createRoom(Room(e.target).getRoomID().split("_")[0]+"_1", roomSettings);
					room.addEventListener(RoomEvent.JOIN_RESULT, onJoinResult2);
					room.join();
					break;
			}
		}
		private function onJoinResult2(e:RoomEvent):void 
		{
			switch( e.getStatus() ) {
				case Status.SUCCESS:
					_onJoin(Room(e.target).getRoomID().substr(roomQualifier.length + roomName.length + 1).split("_")[0]);
					break;
				default:
					lobbySprite.mouseChildren = true;
					_message("TETRISizer\nOnline", null, "Choose a room to join!");
					break;
			}
		}
		
		private function _onJoin(roomIndex:String):void
		{
            var i:int;
            for (i=0; i<200; i++) eidField[i] = idField[i] = (i%10==0 || i%10==9 || i<10 || i>=190) ? 0xfffffff8 : 0;
			playingRoom = r.getRoomManager().createRoom(gameRoomName + roomIndex);
			playingRoom.addEventListener(RoomEvent.JOIN, onGameRoomJoin);
			playingRoom.addEventListener(RoomEvent.ADD_OCCUPANT, onAddOccupant);
			playingRoom.addEventListener(RoomEvent.REMOVE_OCCUPANT, onRemoveOccupant);
			playingRoom.addMessageListener("LOG", onLog);
			playingRoom.addMessageListener("CHANGE", onChange);
			playingRoom.addMessageListener("ERASE", onErase);
			playingRoom.addMessageListener("LOSE", onLose);
			playingRoom.addMessageListener("ATTACKED", onAttacked);
			playingRoom.join();
			_isPlaying = false;
		}
		
		private function onAttacked(from:IClient, x:String, lines:String):void 
		{
			var i:int = int(lines);
			while( i-- )
				_attacked(eidField, int(x));
		}
		
		private function onGameRoomJoin(e:RoomEvent):void 
		{
			_joined = true;
			_updateGameRoom(playingRoom);
		}
		
		
		private function onRemoveOccupant(e:RoomEvent):void 
		{
			_updateGameRoom(Room(e.target));
		}
		
		private function onAddOccupant(e:RoomEvent):void 
		{
			
			_updateGameRoom(Room(e.target));
			if ( !e.getClient().isSelf() ) {
				playingRoom.sendMessage("LOG", false, null, makeLogMessage(idField));
				if ( _isPlaying && score != 0) {
					_showChallengerLabel();
				}
			} else {
				_isPlaying = true;
			}
		}
		
		private function _showChallengerLabel():void
		{
			BetweenAS3.serial(
				BetweenAS3.func(function():void {
					sion.se(3, 2, 2, 1);
				}),
				BetweenAS3.tween(challengerLabel, { x:0.5 * (stage.stageWidth - challengerLabel.width) }, { x:466 }, 1.0, Expo.easeOut),
				BetweenAS3.tween(challengerLabel, { transform: { colorTransform: { redOffset: 255, blueOffset: 255, greenOffset: 255 }}}, null, 0.125),
				BetweenAS3.tween(challengerLabel, { transform:{colorTransform: {redOffset: 0, blueOffset: 0, greenOffset: 0}}}, null, 0.125),
				BetweenAS3.tween(challengerLabel, { x: -465 }, null, 1.0, Expo.easeIn)
			).play();
		}
		private function _showYouWonLabel():void
		{
			BetweenAS3.serial(
				BetweenAS3.func(function():void {
					sion.se(4, 2, 5, 1);
				}),
				BetweenAS3.tween(youWonLabel, { x:0.5 * (stage.stageWidth - youWonLabel.width) }, { x:466 }, 1.0, Expo.easeOut),
				BetweenAS3.tween(youWonLabel, { transform: { colorTransform: { redOffset: 255, blueOffset: 255, greenOffset: 255 }}}, null, 0.125),
				BetweenAS3.tween(youWonLabel, { transform:{colorTransform: {redOffset: 0, blueOffset: 0, greenOffset: 0}}}, null, 0.125),
				BetweenAS3.tween(youWonLabel, { x: -465 }, null, 1.0, Expo.easeIn)
			).play();
		}
		
		private function makeLogMessage(field:Vector.<uint>):String
		{
			var str:String = "";
			str = field.join(",");
			return str;
		}
		
		private function _updateGameRoom(room:Room):void
		{
			var occupants:Array = room.getOccupants();
			if ( occupants.length > 1 ) {
				_enemyExist = true;
				_enemyName = IClient(occupants[0]).isSelf()?IClient(occupants[1]).getAttribute("name"):IClient(occupants[0]).getAttribute("name");
			} else {
				_enemyExist = false;
				_enemyName = null;
			}
			_updateStatus();
		}
		
		private function onLose(from:IClient, msg:String):void 
		{
			wins ++;
			r.self().setAttribute("wins", String(wins));
			_showYouWonLabel();

			level += 1.0;
			score += Number(msg);
			sion.measure = int(level);
			pv3d.measure = int(level);
			_updateStatus();
			if (level >= 32) _changePhase(CLEAR);
		}
		private function onErase(from:IClient, msg:String):void 
		{
			var ys:Array = msg.split(",");
			for ( var i:int = 0; i < ys.length; i++ )
            for (var x:int = 0; x < 8; x++) eidField[ys[i] * 10 + x + 31] = 0;
			_attackedLines += ys.length - 1;
			sion.se(1, 5, 6, 1);
		}
		private var _attackedLines:int = 0;
		private function onChange(from:IClient, msg:String):void 
		{
			var changes:Array = msg.split(",");
			for each( var change:String in changes ) {
				var iAndValue:Array = change.split(":");
				eidField[int(iAndValue[0])] = uint(iAndValue[1]);
			}
		}
		
		private function onLog(from:IClient, msg:String):void 
		{
			var vec:Array = msg.split(",");
			var count:int = vec.length;
			var str:String = "";
			for ( var i:int = 0; i < count; i++ ) {
				eidField[i] = vec[i];
			}
		}
        
		private function onRoomAdded(e:RoomManagerEvent):void 
		{
			if( e.getRoomIdQualifier() == roomQualifier )
				_observeRoom(e.getRoomID());
		}
		
		private function _observeRoom(roomID:String):void
		{
			var updateLevels:UpdateLevels = new UpdateLevels();
			updateLevels.clearAll();
			updateLevels.occupantList = true;
			updateLevels.sharedOccupantAttributesGlobal = true;
			var room:Room = r.getRoomManager().getRoom(roomID);
			room.addEventListener(RoomEvent.OBSERVE, onObserve);
			room.addEventListener(RoomEvent.REMOVED, onRemoved);
			room.addEventListener(RoomEvent.UPDATE_CLIENT_ATTRIBUTE, onUpdate);
			room.observe(null, updateLevels);
		}
		
		private function onUpdate(e:RoomEvent):void 
		{
			if ( e.getChangedAttr().name == "wins" ) {
				_lobbyReady();
			}
		}
		
		private var _observingRoomNum:Number = 0;
		private function onRemoved(e:RoomEvent):void 
		{
			_roomNum = r.getRoomManager().getNumRooms(roomQualifier);
			_observingRoomNum--;
			if ( _observingRoomNum == _roomNum ) {
				_lobbyReady();
			}
		}
		
		private function onObserve(e:RoomEvent):void 
		{
			_observingRoomNum++;
			if ( _observingRoomNum == _roomNum ) {
				_lobbyReady();
			}
		}
		private function _startWatching():void
		{
			r.getRoomManager().watchForRooms(roomQualifier);
		}
		private function onWatchForRoomsResult(e:RoomManagerEvent):void 
		{
			// maybe SUCCESS..
			if ( _roomNum == r.getRoomManager().getNumRooms(roomQualifier) ) {
				_lobbyReady();
			}
		}

    //---------------------------------------- SiON events
        private function _onBeat(e:SiONTrackEvent) : void {
            lineBrghtness = 1;
            pv3d.tick();
        }
        
        private function _onNoteOn(e:SiONTrackEvent) : void {
            if (e.eventTriggerID == 1) _whiteOut();
        }
        
    //---------------------------------------- UI
        private function _status(x:Number, y:Number, label:String, target:DisplayObjectContainer = null) : Label {
            var inst:Label = new Label(target?target:mainSprite, x, y, label);
            inst.scaleX = inst.scaleY = 2;
            inst = new Label(target?target:mainSprite, x+90, y, "");
            inst.scaleX = inst.scaleY = 2;
            return inst;
        }
		
        private function _resetButton(x:Number, y:Number) : PushButton {
            return new PushButton(this, x, y, "CLEAR COOKIE", function(e:Event) : void {
                var so:SharedObject = SharedObject.getLocal("savedData");
                if (so) so.clear();
                bestResult = {"wins":wins, "score":score, "level":level, "lines":lines};
                if (phase == TITLE) {
                    wins = lines = level = score = 0;
                    _updateStatus();
                }
            });
        }
        
        private function _effectButton(x:Number, y:Number) : PushButton {
            return new PushButton(this, x, y, "EFFECT ON", function(e:Event) : void {
                e.target.label = _swapEffect() ? "EFFECT ON" : "EFFECT OFF";
            });
        }
        
        private function _scoreButton(x:Number, y:Number) : PushButton { return new PushButton(this, x, y, "SHOW RANKING", __showRanking); }
        private function __showRanking(e:Event) : void { new BasicScoreRecordViewer(this, 122.5, 112.5,'RANKING', 30, true); }
        
        private function _tweetButton(x:Number, y:Number) : PushButton {
            return new PushButton(this, x, y, "TWEET SCORE", function(e:Event) : void {
                navigateToURL(new URLRequest("http://twitter.com/home/?status=" + escapeMultiByte("[SiON TETRISizer Online] wins:"+ String(wins) +" score:" + String(score) + " http://wonderfl.net/c/cifX/ #TETRISizerOnline")), "_blank");
            });
        }

    //---------------------------------------- drawings
        private function _drawBackground() : void {
            g.clear();
            var col:int = backcolor * 0x10101;
            if (scaleEffect > 0) {
                smat.tx = -4.65-scaleEffect*2+25;
                scolt.alphaMultiplier = ((scaleEffect>12) ? (25-scaleEffect) : scaleEffect)*0.04;
                screen.draw(screen, smat, scolt);
                --scaleEffect;
                g.beginFill(col, 0.1);
            } else g.beginFill(col, 0.25);
            g.drawRect(0, 0, 465, 465);
            g.endFill();
            if (backcolor > 0) {
                g.beginFill(0x000000, backcolor * 0.001953125);
                g.drawRect(32,  32, 200, 400);
                g.endFill();
            }
            pv3d.update();
            screen.draw(pv3d);
            col = (int(lineBrghtness*63))*0x20304;
			if ( !mainSprite.visible ) {
				for ( var i:int = 0; i < 8; i++ ) {
					__drawVoidRect( ROOM_X, (ROOM_GAP+ROOM_HEIGHT)* i +ROOM_Y, ROOM_WIDTH, ROOM_HEIGHT, col);
				}
			} else {
				__drawVoidRect( TOP_LEFT_MARGIN, TOP_LEFT_MARGIN, 200, 400, col);
				__drawVoidRect( TOP_LEFT_MARGIN + 200 + NEXT_BOX_GAP, TOP_LEFT_MARGIN, NEXT_BOX_WIDTH, NEXT_BOX_WIDTH, col);
				__drawVoidRect( TOP_LEFT_MARGIN + 200 + NEXT_BOX_GAP, TOP_LEFT_MARGIN + NEXT_BOX_WIDTH + NEXT_BOX_GAP, NEXT_BOX_WIDTH, NEXT_BOX_WIDTH, col);
				__drawVoidRect( ENEMY_LEFT_MARGIN, TOP_LEFT_MARGIN, 96, 192, col);
			}
            screen.draw(canvas);
        }
        private function _drawField() : void {
            var dx:int, dy:int, x:int, y:int, f:int, id:uint, b:int, col:int;
			if ( !mainSprite.visible ) {
				return;
			}
            b = tetromino[col = (nextID & 7) - 1][dropR];
            dy = tetromino[col][4] * 12.5;
            for (f=1, y=0; y<4; y++) for (x=0; x<4; x++, f<<=1) if (b & f) __drawSmallBlock(screen, col, x * SMALL_BLOCK_SIZE + NEXT_BLOCK_X- dy, y * SMALL_BLOCK_SIZE + NEXT_BLOCK_Y - dy);
            col = (stockID & 7) - 1;
            b = tetromino[col][dropR];
            dy = tetromino[col][4] * 12.5;
            for (f = 1, y = 0; y < 4; y++) for (x = 0; x < 4; x++, f <<= 1) if (b & f) __drawSmallBlock(screen, col, x * SMALL_BLOCK_SIZE + NEXT_BLOCK_X - dy, y * SMALL_BLOCK_SIZE + NEXT_BLOCK_Y + NEXT_BOX_WIDTH + NEXT_BOX_GAP - dy);
            if (phase == MOVE) {
                dy = tetromino[(dropID & 7) - 1][4] * 12.5;
                mat.identity();
                mat.translate(-dy, -dy);
                mat.rotate(-drawR * 1.5707963267948965);
                mat.translate((drawX - 1) * MAIN_BLOCK_SIZE + dy + 32, (drawY - 1) * MAIN_BLOCK_SIZE + dy + 32);
                screen.draw(dropBlock, mat);
            }
            col = (int(lineBrghtness*63))*0x20304;
            for (y=0; y<16; y++) for (x=0; x<8; x++) {
                id = idField[y*10+x+31];
                __drawBlock(screen, (id & 7) - 1, dx = x * MAIN_BLOCK_SIZE + TOP_LEFT_MARGIN, dy = y * MAIN_BLOCK_SIZE + TOP_LEFT_MARGIN);
                if (id != idField[y*10+x+21] ) __drawRect(dx-1, dy-1, 27, 3, col);
                if (id != idField[y * 10 + x + 30])  __drawRect(dx - 1, dy - 1, 3, 27, col);
				// enemy
				if( _enemyExist ){
					id = eidField[y*10+x+31];
					__drawSmallBlock(screen, (id & 7) - 1, dx = x * SMALL_BLOCK_SIZE + ENEMY_LEFT_MARGIN, dy = y * SMALL_BLOCK_SIZE + TOP_LEFT_MARGIN);
					if (id != eidField[y*10+x+21] ) __drawRect(dx-1, dy-1, 14, 3, col);
					if (id != eidField[y * 10 + x + 30])  __drawRect(dx - 1, dy - 1, 3, 14, col);
				}
            }
        }
        
        private function _updateDropBlock() : void {
            var x:int, y:int, f:int, col:int = (dropID&7)-1, b:int = tetromino[col][dropR];
            dropBlock.fillRect(dropBlock.rect, 0);
            for (f=1, y=0; y<4; y++) for (x=0; x<4; x++, f<<=1) if (b & f) __drawBlock(dropBlock, col, x * 25, y * 25);
        }
        
        private function __drawBlock(bd:BitmapData, col:int, dx:Number, dy:Number) : void {
            if (col == -1) return;
            pt.x = dx; pt.y = dy;
            bd.copyPixels(blockTextures[col], blockTextures[col].rect, pt);
        }
        private function __drawSmallBlock(bd:BitmapData, col:int, dx:Number, dy:Number) : void {
            if (col == -1) return;
            pt.x = dx; pt.y = dy;
            bd.copyPixels(blockSmallTextures[col], blockSmallTextures[col].rect, pt);
        }
        
        private function __drawVoidRect(x:Number, y:Number, w:Number, h:Number, col:int) : void {
            __drawRect(x-1, y-1, w+2, 3, col);
            __drawRect(x-1, y-1, 3, h+2, col);
            __drawRect(x+1, y+h-1, w, 3, col);
            __drawRect(x+w-1, y+1, 3, h, col);
        }
        
        private function __drawRect(x:Number, y:Number, w:Number, h:Number, col:int) : void {
            rc.x = x; rc.y = y; rc.width = w; rc.height = h;
            screen.fillRect(rc, col);
        }
        
    //---------------------------------------- texts
        private function _updateStatus() : void {
            enemyLabel.text = _enemyExist?_enemyName:"";
            winsLabel.text = ("00"+String(wins)).substr(-3, 3);
            scoreLabel.text = ("0000000000"+String(score)).substr(-8, 8);
            levelLabel.text = ("0"+String(int(level))).substr(-2, 2) + "/32";
            linesLabel.text = ("00"+String(lines)).substr(-3, 3);
        }
        
        private function _message(text:String, subText:String=null, smallText:String=null) : void {
            msgbd.fillRect(msgbd.rect, 0);
            $(text, 0);
            if (subText) $(subText, 32);
            msg.y = (smallText) ? 160 : 200;
            if (messageTween && messageTween.isPlaying) messageTween.stop();
            messageTween = BetweenAS3.to(msg, {"alpha":1}, 0.3);
            messageTween.play();
            if (msgs.visible = (smallText != null)) {
                msgs.text = smallText;
                msgs.draw();
                msgs.x = 132 - msgs.width * 0.75;
                msgs.y = 280;
            }
            function $(text:String, y:Number) : void {
                msgb.text = msgw.text = text;
                msgb.draw();
                msgw.draw();
                var w:Number = msgw.width * 1.5;
                _(msgb, 103 - w, y);
                _(msgb,  97 - w, y);
                _(msgb, 100 - w, y - 3);
                _(msgb, 100 - w, y + 3);
                _(msgw, 100 - w, y);
                function _(l:Label, x:Number, y:Number) : void {
                    mmat.tx = x;
                    mmat.ty = y;
                    msgbd.draw(l, mmat);
                }
            }
        }
        
        private function _messageOff() : void {
            msgs.visible = false;
            if (messageTween && messageTween.isPlaying) messageTween.stop();
            messageTween = BetweenAS3.to(msg, {"alpha":0}, 0.3);
            messageTween.play();
        }
        
    //---------------------------------------- motions
        private function _slideAndRotate(dx:int, r:int) : void {
            if (_check(dx+dropX, dropY, (dropR + r) & 3) && (dropY-drawY<0.3 || _check(dx+dropX, dropY-1, (dropR + r) & 3))) {
                dropX += dx;
                dropR = (dropR + r) & 3;
                if (r != 0) _updateDropBlock()
            }
        }
        
        private function _stack() : void {
            var x:int, y:int, f:int, b:int = tetromino[(dropID & 7) - 1][dropR];
			var str:String = "";
            for (f = 1, y = 0; y < 4; y++) for (x = 0; x < 4; x++, f <<= 1) if (b & f) {
				idField[(y + dropY - 1) * 10 + x + dropX + 30] = dropID;
				str += ((y + dropY - 1) * 10 + x + dropX + 30) + ":" + dropID + ",";
			}
			playingRoom.sendMessage("CHANGE", false, null, str.substr(0,str.length-1));
            sion.se(0);
            _changePhase(DELETE);
        }
        
    //---------------------------------------- evaluations
        private function _check(x_:int, y_:int, r_:int) : Boolean {
            var x:int, y:int, f:int, b:int = tetromino[(dropID&7)-1][r_];
            for (f=1, y=0; y<4; y++) for (x=0; x<4; x++, f<<=1) if ((b & f) && idField[(y+y_-1)*10+x+x_+30] != 0) return false;
            return true;
        }
        
        private function _checkLine() : int {
            var x:int, y:int;
            for (delLineFlag=0, y=0; y<16; y++) {
                for (x=0; x<8; x++) if (idField[y*10+x+31] == 0) break;
                if (x == 8) delLineFlag |= 1<<y;
            }
            return delLineFlag;
        }
        private var dropData:String;
        private function _dropLine() : Boolean {
			dropData = "";
            var x:int, y:int, ret:Boolean = false;
            for (y = 15; y >= 0; y--) for (x = 0; x < 8; x++) if (__checkDropBlock(y * 10 + x + 31)) {
				idField[y * 10 + x + 31] |= 0x80000000;
				dropData += (y * 10 + x + 31) + ":" + idField[y * 10 + x + 31] + ",";
			}
            for (y=15; y>=0; y--) for (x=0; x<8; x++) if (idField[y*10+x+31] & 0x80000000) {
                idField[y*10+x+41] = idField[y*10+x+31] & 0x7fffffff;
                idField[y*10+x+31] = 0;
				dropData += (y*10+x+41) + ":" + idField[y*10+x+41] + "," + (y*10+x+31) + ":0,";
                ret = true;
            }
			if( dropData.length > 0 )
				playingRoom.sendMessage("CHANGE", false, null, dropData.substr(0,dropData.length-1));
            return ret;
        }
        
        private function __checkDropBlock(idx:int) : Boolean {
            if (idField[idx] == 0) return false;
            var id:uint = idField[idx], ret:Boolean;
            idField[idx] |= 0x80000000;
            ret = ((idField[idx+10] == 0 || idField[idx+10] == idField[idx]) && 
                   (idField[idx-1]  != id || __checkDropBlock(idx-1)) && 
                   (idField[idx+1]  != id || __checkDropBlock(idx+1)) && 
                   ((id&7) == 1 || idField[idx-10] != id || __checkDropBlock(idx-10)));
            {
				var temp:uint = idField[idx];
				idField[idx] &= 0x7fffffff;
				if( temp != idField[idx] )
					dropData += idx + ":" + idField[idx] + ",";
			}
            return ret;
        }
        
    //---------------------------------------- procedures
        private function _loadCookie() : void {
            var so:SharedObject = SharedObject.getLocal("savedData");
            bestResult = (so && "bestResult" in so.data) ? (so.data.bestResult) : {"wins":0, "score":0, "level":0, "lines":0};
        }
        
        private function _initialize() : void {
            FMath.randomSeed(uint(new Date().getTime()));
            nextID = FMath.random(8, 1) + 16;
            stockID = FMath.random(8, 1) + 8;
            lines = level = score = 0;
            lineBrghtness = 1;
            scaleEffect = 0;
            backcolor = 0;
            __createTexture();
            _updateStatus();
        }
        
        private function __createTexture() : void {
            for (var i:int=0; i<7; i++) {
                mat.createGradientBox(25, 25, 0.7853981633974483, 0, 0);
                g.clear();
                g.beginGradientFill("linear", [FColor.HSVtoValue(45*i,0.25,1), FColor.HSVtoValue(45*i,0.75,0.75)], [0.375, 0.375], [0, 255], mat);
                g.drawRect(0, 0, 25, 25);
                blockTextures[i] = new BitmapData(25, 25, true, 0);
                blockTextures[i].draw(canvas);
                g.clear();
                g.beginGradientFill("linear", [FColor.HSVtoValue(45*i,0.25,1), FColor.HSVtoValue(45*i,0.75,0.75)], [0.375, 0.375], [0, 255], mat);
                g.drawRect(0, 0, 12, 12);
                blockSmallTextures[i] = new BitmapData(12, 12, true, 0);
                blockSmallTextures[i].draw(canvas);
            }
        }
        
        private function _nextBlock() : void {
			if( _attackedLines > 0 ){
				x = 1 + int(Math.random() * 8);
				playingRoom.sendMessage("ATTACKED", false, null, x, _attackedLines);
				while ( _attackedLines ) {
					_attackedLines--;
					_attacked(idField, x);
				}
			}
				
            dropID = nextID;
            nextID = ((nextID & 0x7ffffff8) + 8) | FMath.random(8, 1);
            _updateDropBlock();
            dropX = drawX = 3;
            dropY = drawY = 0;
            speed = lines * 0.001 - int(level/10) * 0.003 + 0.01;
            slideCount = 0;
            if (!_check(dropX, dropY, dropR)) _changePhase(GAMEOVER);
        }
        
        private function _flipBlock() : void {
            var id:uint = dropID;
            dropID = stockID;
            if (_check(dropX, dropY, dropR)) {
                stockID = id;
                _updateDropBlock();
            } else dropID = id;
            sion.se(0);
        }
        
        private function _swapEffect() : Boolean {
            _effect = !_effect;
            if (!_effect) pv3d.filters = null;
            return _effect;
        }
        
        private function _whiteOut() : void { BetweenAS3.to(this, {"backcolor":255}, 60/132*8).play(); }
        private function _blackOut() : void { BetweenAS3.to(this, {"backcolor":0}, 1.5).play(); }
        
    //---------------------------------------- phases
        private var TITLE:int=0, INTRO:int=1, MOVE:int=2, DELETE:int=3, GAMEOVER:int=4, CLEAR:int=5, RESULT:int=6, nextPhase:int = -1;
        private var phaseStart:Array = [_startTitle, _startIntro, _startMove, _startDelete, _startGameover, _startClear,    _startResult];
        private var phaseMain:Array  = [_phaseTitle, _phaseIntro, _phaseMove, _phaseDelete, _returnToTitle, _returnToTitle, _doNothing];
        private var phaseEnd:Array   = [_endTitle,   _endIntro,   _endMove,   _doNothing,   _doNothing,     _doNothing,     _doNothing];
        private function _doNothing() : void {}
        private var sendStr:String = "";
        private function _changePhase(p:int) : void {
            if (nextPhase == -1) {
                nextPhase = p;
                phaseEnd[phase]();
                frameCount = 0;
                keyPushed = 0;
                do {
                    phase = nextPhase
                    phaseStart[phase]();
                } while (phase != nextPhase);
                nextPhase = -1;
            } else {
                nextPhase = p;
            }
        }
        
    //---------------------------------------- TITLE phase
        private function _startTitle() : void {
			mainSprite.visible = false;
			lobbySprite.visible = !mainSprite.visible;
            sion.start();
            wins = bestResult.wins;
            score = bestResult.score;
            level = bestResult.level;
            lines = bestResult.lines;
            _updateStatus();
            _message("TETRISizer\nOnline", null, "Choose a room to join!");
        }
		
        private function _phaseTitle() : void {if (_joined) { _joined = false; _changePhase(INTRO); mainSprite.visible = true; lobbySprite.visible = !mainSprite.visible;} }
        private function _endTitle() : void { _initialize(); }
        
    //---------------------------------------- INTRO phase
        private function _startIntro() : void { _message("? Ready ?"); }
        private function _phaseIntro() : void {
            if (frameCount == 36) _message("! Go !");
            else if (frameCount == 72) _changePhase(MOVE);
        }
        private function _endIntro() : void { _messageOff(); }
        
    //---------------------------------------- MOVE phase
        private function _startMove() : void { _nextBlock(); }
        private function _phaseMove() : void {
            drawY += (keyPressed == 40) ? 0.5 : speed;
            var y:int = int(drawY + 0.9999847412109375);
            if (y != dropY) {
                if (_check(dropX, dropY+1, dropR)) dropY = y;
                else {
                    drawY = dropY = y - 1;
                    slideCount += (keyPressed==40) ? 10 : 1;
                    if (slideCount > 30)_stack();
                }
            }
            if (keyPushed == 67) _flipBlock();
            else if (keyPushed == 38) {
                while(_check(dropX, dropY+1, dropR)) dropY++;
                score += 30-dropY;
                _updateStatus();
                _stack();
            } else if (keyPushed) {
                drawR = dropR;
                _slideAndRotate(int(keyPushed==39)-int(keyPushed==37), int(keyPushed==90)-int(keyPushed==88));
                drawR -= dropR;
                if (drawR == 3) drawR = -1;
                else if (drawR == -3) drawR = 1;
                sion.se(keyPushed, dropX*16-56);
			}
            drawX += (dropX - drawX) * 0.6;
            drawR *= 0.5;
        }
        private function _endMove() : void { delChains = delLines = 0; }
        
    //---------------------------------------- DELETE phase
        private function _startDelete() : void {
            if (_checkLine()) {
				var eraseData:String = "";
                for (var y:int = 0; y < 16; y++) if (delLineFlag & (1 << y)) {
					eraseData += y + ",";
                    delLines++;
                    for (var x:int=0; x<8; x++) idField[y*10+x+31] = 0;
                }
				if( eraseData.length > 0 )
					playingRoom.sendMessage("ERASE", false, null, eraseData.substr(0,eraseData.length-1));
                delChains++;
                if (_effect) scaleEffect = 25;
                _message("! "+String(delLines)+" Lines !", String(delChains)+" Combo");
                sion.se(1, 0, 8, 4);
            } else {
                if (delLines > 0) {
                    score += (delLines * delLines + delChains * delChains) * ((level>23) ? 200 : 100);
                    lines += delLines;
					level += 0.1 + 0.1 * int(level/4);
                    _updateStatus();
                }
                _messageOff();
				if ( level >= 32 ) _changePhase(CLEAR);
				else _changePhase(MOVE);
            }
        }
		
		private function _attacked(target:Vector.<uint>, ax:int):void
		{
			for ( var y:int = 2; y < 18; y++ ) {
				for ( var x:int = 1; x < 9; x++ ) {
					target[y * 10 + x] = target[y * 10 + x + 10];
				}
			}
			for ( x = 1; x < 9; x++ ) {
				if ( x != ax ) target[180 + x] = (ax) % 7 + 1;
				else target[180 + x] = 0;
			}
		}
        
        private function _phaseDelete() : void {
            if (frameCount < 16) for (var y:int=0; y<16; y++) if (delLineFlag & (1<<y)) {
                g.clear();
                g.beginFill(0xffffff, frameCount*0.0625);
                g.drawRect(32, y*25+32, 200, 25);
                screen.draw(canvas);
            }
            if (frameCount > 12 && !_dropLine()) _changePhase(DELETE);
        }
        
    //---------------------------------------- GAMEOVER phase
        private function _startGameover() : void {
            _blackOut();
            sion.end();
            pv3d.end();
            _message("GAME OVER", null, "Press any key");
			playingRoom.sendMessage("LOSE", false, null, score * 0.5);
			playingRoom.leave();
			room.leave();
        }
        
    //---------------------------------------- CLEAR phase
        private function _startClear() : void {
            _blackOut();
            sion.end();
            pv3d.end();
            _message("! FINISH !", null, "Press any key");
			playingRoom.leave();
			room.leave();
        }
        private function _returnToTitle() : void { if (frameCount>30 && keyPushed) _changePhase(RESULT); }
        
    //---------------------------------------- RESULT phase
        private function _startResult() : void {
            if (score > bestResult.score) {
                _messageOff();
                bestResult = {"wins":wins, "score":score, "level":level, "lines":lines};
                var so:SharedObject = SharedObject.getLocal("savedData");
                if (so) {
                    so.data.bestResult = bestResult;
                    so.flush();
                }
                bsf = new BasicScoreForm(this, 92.5, 152.5, score, 'HI SCORE !', _onCloseBSF);
                bsf.onCloseClick = _onCloseBSF;
            } else _changePhase(TITLE);
        }
        
        private function _onCloseBSF(succeeded:Boolean = false) : void {
            if (bsf != null) removeChild(bsf);
            bsrv = new BasicScoreRecordViewer(this, 122.5, 112.5,'RANKING', 30, true, _onCloseBSRV);
            bsf = null;
        }
        
        private function _onCloseBSRV() : void {
            if (bsrv != null) removeChild(bsrv);
            bsrv = null;
            _changePhase(TITLE);
        }
    }
}



//---------------------------------------- global variables
var _effect:Boolean = true;
var _enemyExist:Boolean = false;
var _enemyName:String = "";
var _myName:String = "";
var _isPlaying:Boolean = false;

// View Class
import flash.display.*;
import com.bit101.components.*;
class RoomObject extends Sprite {
	private var _playerNum:int = 0;
	private var _index:int = 0;
	private var _p1label:Label;
	private var _p2label:Label;
	private var _p1:int = -1;
	private var _p2:int = -1;
	private var _width:Number;
	private var _height:Number;
	public function RoomObject(width:Number, height:Number, index:int) {
		_width = width;
		_height = height;
		_index = index;
		_p1label = new Label(this, 5, 0, "loading...");
		_p2label = new Label(this, 5, 20, "loading...");
		setBG(0x0);
	}
	public function setPlayer1(name:String, wins:String ):void {
		if ( name ) {
			_p1 = int(wins);
			_p1label.text = "PLAYER 1: (" + _p1 + ")" + name;
		} else {
			_p1 = -1;
			_p1label.text = "empty";
		}
		_updateNum();
	}
	public function setPlayer2(name:String, wins:String ):void {
		if ( name ) {
			_p2 = int(wins);
			_p2label.text = "PLAYER 2: (" + _p2 + ")" + name;
		} else {
			_p2 = -1;
			_p2label.text = "empty";
		}
		_updateNum();
	}
	
	private function _updateNum():void
	{
		_playerNum = 0;
		if ( _p1 >= 0 ) {
			_playerNum++;
		}
		if ( _p2 >= 0 ) {
			_playerNum++;
		}
		if ( _playerNum == 2 ) {
			setBG(0xFF0000);
			this.mouseChildren = this.mouseEnabled = this.buttonMode = false;
		} else {
			setBG(0x0000FF);
			this.mouseChildren = this.mouseEnabled = this.buttonMode = true;
		}
	}
	
	public function setBG(col:uint):void {
		this.graphics.clear();
		this.graphics.beginFill(col, 0.2);
		this.graphics.drawRect(0, 0, _width, _height);
		this.graphics.endFill();
	}
	
	public function get index():int { return _index; }
}


//---------------------------------------- SiON
import org.si.sion.*;
import org.si.sion.events.*;
import org.si.sion.effector.*;
import org.si.sion.sequencer.*;
import org.si.sound.*;
import org.si.sound.synthesizers.*;

class SiON extends SiONDriver {
    private var bs:BassSequencer = new BassSequencer("o3C", 15);
    private var dm:DrumMachine = new DrumMachine(0,0,0,2,2,2);
    private var back:SiONData, fill:SiONData, fill2:SiONData;
    private var analogSynth:AnalogSynth = new AnalogSynth();

    function SiON(onBeat:Function, onNoteOn:Function) : void {
        super();
        setVoice(0, new SiONVoice(5,2,63,63,-10,0,2,20));
        back = compile("#EFFECT1{delay312,30,1};%5@0,40@v64,32q1s24$o6b-r2.;");
        fill = compile("#A=o7[crgrfrcrgrfcrgfr];r1^1%6@0l16@v32,16q8$A(7)A(5);%2@f0,2,16q8s20@0,10%t1,1,0c1^1^8;%2q0s32l16v4[cc(]16;@v128%5@5q0s32,-128o3$c;");//)
        fill2= compile("#A=o7[drargrdrargaragr];%6@0l16@v16,8q8$AA");
        bpm = 132;
        setSamplerData(0, render("%2@v128q0s32o4g16"));
        setSamplerData(1, render("#A=%6@0q0s20o3c*<<<g;A;kt7A"));
        setSamplerData(2, render("t160;#A=@v96q0s32l32o7e-crb-;A"));
        setSamplerData(3, render("t160;#A=%1@1@v128p2q0s32l32o5c<fcr<gb-frrb-16b-16;k4A;k-4A"));
        setSamplerData(4, render("t160;#A=@v128p2@al2i1@dt760q0s32l32o5cg<cf<ag>b-e-b-<e->>acagv11abv10adv8adv7adv6adv5adv4ad;k4A;k-4A"));
        setSamplerData(5, render("t160;#A=@v128p2@al2i1@dt760q0s32l32o5b;k-4A"));
        setSamplerData(6, render("t160;#A=@v128p2@al2i1@dt760q0s32l32o5c;k-4A"));
        setSamplerData(37, render("%6@0o7q8l64cb-f"));
        setSamplerData(39, render("%6@0o7q8l64gcd"));
        setSamplerData(88, render("%6@0o4q8l32g*<<g"));
        setSamplerData(90, render("%6@0o4q8l32f*<<f"));
        addEventListener(SiONTrackEvent.BEAT, onBeat);
        addEventListener(SiONTrackEvent.NOTE_ON_FRAME, onNoteOn);
        addEventListener(SiONEvent.STREAM_STOP, _onStreamStop);
        dm.volume = 0.6;
        bs.synthesizer = analogSynth;
        bs.volume = 0.4;
        analogSynth.setVCAEnvelop(0,   0.3, 0.7, 0.2);
        analogSynth.setVCFEnvelop(0.4, 0.3, 0.1, 0.6, 0.7);
    }

    public function set measure(m:int) : void {
        switch (m) {
        case 1: dm.bass.mute = false; break;
        case 4: dm.hihat.mute = false; break;
        case 8: bs.mute = false; bs.fadeIn(16); break;
        case 10: bpm = 105; break;
        case 12: bpm = 110; analogSynth.setVCFEnvelop(0.45, 0.3, 0.1, 0.6, 0.75); break; 
        case 14: bpm = 115; analogSynth.setVCFEnvelop(0.5,  0.3, 0.1, 0.6, 0.8);  break;
        case 16: bpm = 120; analogSynth.setVCFEnvelop(0.55, 0.3, 0.1, 0.6, 0.85); break;
        case 18: bpm = 125; analogSynth.setVCFEnvelop(0.6,  0.3, 0.1, 0.6, 0.85); break;
        case 20: bpm = 132; dm.snare.mute = false; dm.hihatPatternNumber = 2; break;
        case 24: sequenceOn(fill, null, 0, 0, 16); break;
        case 28: sequenceOn(fill2, null, 0, 0, 16); break;
        }
    }

    public function start() : void {
        bpm = 100;
        fadeIn(4);
        play(back);
        dm.snarePatternNumber = 0;
        dm.hihatPatternNumber = 13;
        dm.snare.mute = true;
        dm.hihat.mute = true;
        dm.bass.mute = true;
        bs.mute = true;
        dm.play();
        bs.play();
    }
    
    public function end() : void {
        fadeOut(4);
    }
    
    public function se(i:int, pan:int=0, len:int=0, qnt:int=1) : void {
        var t:SiMMLTrack = playSound(i, len, 0, qnt);
        t.effectSend1 = 32;
        t.pan = pan;
    }
    
    private function _onStreamStop(e:SiONEvent) : void {
        bs.stop();
        dm.stop();
    }
}


//---------------------------------------- PV3D
import flash.events.Event;
import flash.filters.GlowFilter;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.ITween;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.objects.primitives.Cube;
import org.papervision3d.view.BasicView;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.geom.renderables.*;

class PV3D extends BasicView {
    public var light:PointLight3D = new PointLight3D(), scale:Number, glows:Array = []; 
    public var cube:Cube = new Cube(new MaterialsList({all:new FlatShadeMaterial(light, 0x203040, 0x000000)}),60,60,60,3,3,3);
    public var nvs:Vector.<Number3D> = new Vector.<Number3D>(cube.geometry.vertices.length);
    public var cbs:Vector.<Number3D> = new Vector.<Number3D>(cube.geometry.vertices.length);
    public var s:Vector.<Number> = new Vector.<Number>(cube.geometry.vertices.length);
    public var omegaX:Number=0.2, omegaY:Number=0.4, omegaZ:Number=0.7, omegaTween:ITween=null;
    
    function PV3D() {
        glows.push(new GlowFilter(0x405080,1,4,4));
        glows.push(new GlowFilter(0x405080,1,8,8));
        glows.push(new GlowFilter(0x405080,1,16,16));
        glows.push(new GlowFilter(0x405080,1,32,32));
        super(465, 465);
        scene.addChild(cube);
        scale = 1;
        for (var i:int=0; i<nvs.length; i++) {
            var v:Vertex3D = cube.geometry.vertices[i];
            cbs[i] = new Number3D(v.x, v.y, v.z);
            nvs[i] = new Number3D(v.x, v.y, v.z);
            nvs[i].normalize();
            s[i] = 1;
        }
    }
    
    public function update() : void {
        cube.scale += (scale - cube.scale) * 0.05;
        cube.rotationX += omegaX;
        cube.rotationY += omegaY;
        cube.rotationZ += omegaZ;
        for (var i:int=0; i<nvs.length; i++) {
            var n:Number3D = nvs[i], c:Number3D = cbs[i], v:Vertex3D = cube.geometry.vertices[i], r:Number = s[i];
            v.x = n.x * r + c.x;
            v.y = n.y * r + c.y;
            v.z = n.z * r + c.z;
            s[i] += (1 - r) * 0.12;
        }
        for each(var f:Triangle3D in cube.geometry.faces) f.createNormal();
        singleRender();
    }
    
    public function end() : void {
        if (omegaTween && omegaTween.isPlaying) omegaTween.stop();
        omegaTween = BetweenAS3.to(this, {"omegaX":0.2 ,"omegaY":0.4 ,"omegaZ":0.7}, 2);
        omegaTween.play();
        scale = 1;
        filters = null;
    }
    
    public function tick() : void {
        for (var i:int=0; i<s.length; i++) s[i] += Math.random() * 6 * (scale - 1);
    }
    
    public function set measure(m:int) : void {
        scale = 1 + m*0.2;
        if (_effect && (m&7)==1) filters = [glows[m>>3]];
        if (omegaTween && omegaTween.isPlaying) omegaTween.stop();
        omegaTween = BetweenAS3.to(this, {"omegaX":$() ,"omegaY":$() ,"omegaZ":$()}, 4);
        omegaTween.play();
        function $():Number { return (Math.random() - 0.5) * scale; }
    }
}