forked from: パーティクル崩し

by sanichiq forked from パーティクル崩し (diff: 143)
初心者がソースコードを勝手に解釈してコメント書いてみたり、適当にソースをいじって遊んでみるテスト
♥0 | Line 192 | Modified 2011-08-30 15:55:33 | MIT License
play

ActionScript3 source code

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

// forked from coppieee's パーティクル崩し
// 初心者がソースコードを勝手に解釈してコメント書いてみたり、適当にソースをいじって遊んでみるテスト
package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import net.hires.debug.Stats;
    
    [SWF(width = "465", height = "465", frameRate = "30")]
    public class BlockBreaker extends Sprite 
    {
        private static const HEIGHT:Number = 465; // 画面縦幅 
        private static const WIDTH:Number = 465; // 画面横幅
        private static const BAR_HEIGHT:Number = 10; // バー縦幅
        private static const BAR_WIDTH:Number = 200; // バー横幅
        private static const BLOCKS_HEIGHT:Number = 100; // バー縦幅
        private static const BLOCKS_WIDTH:Number = WIDTH; // バー縦幅
        
        private var _canvas:BitmapData; // キャンバス
        private var _blocks:Blocks; // ブロック
        private var _fallBlocks:Vector.<Particle>; // 落ちるブロック
        private var _balls:Vector.<Particle>; // ボール
        private var _bar:Bitmap; // バー
        
        public function BlockBreaker()
        {
            // キャンバスの生成
            _canvas = new BitmapData(WIDTH, HEIGHT,false,0x000000);
            addChild(new Bitmap(_canvas));
            
            // ブロックの生成
            _blocks = new Blocks(BLOCKS_WIDTH, BLOCKS_HEIGHT);
            
            // 落下ブロックの生成
            _fallBlocks = new Vector.<Particle>();
            
            // バーの初期化
            var b:BitmapData = new BitmapData(BAR_WIDTH, BAR_HEIGHT, false, 0x00FF00);
            addChild(_bar = new Bitmap(b));
            _bar.y = WIDTH - 50; // バーの高さを設定
            
            // 初期玉を生成
            var ball:Particle = new Particle(WIDTH / 2, HEIGHT / 2); // 実体の生成
            ball.vx = 0; // X移動量
            ball.vy = -1; // Y移動量
            ball.color = 0xFFFFFF; // 色
            
            // ボール配列を生成
            _balls = new Vector.<Particle>();
            _balls.push(ball); // 初期玉を配列に追加
            
            // 毎フレーム更新処理をイベントに追加
            addEventListener(Event.ENTER_FRAME, update);
        }
        
        private function update(e:Event):void
        {
            // キャンバスのロック
            _canvas.lock();
            
            // キャンバスに残像を残す
            _canvas.colorTransform(_canvas.rect, new ColorTransform (0.9, 0.9, 0.9));
            
            // ブロックの描画
            for each(var block:Particle in _blocks.values) {
                if (block) {
                    _canvas.setPixel(block.x, block.y, block.color);
                }
            }
            
            // ボールの更新
            var removeBalls:Vector.<Particle> = new Vector.<Particle>();
            for each(var ball:Particle in _balls)
            {
               var bvx:Number = ball.vx; // X移動量
               var bvy:Number = ball.vy; // Y移動量
               var bspeed:Number = Math.sqrt(bvx * bvx + bvy * bvy); // ボールの速さ
               var bradius:Number = Math.atan2(bvy, bvx); // ボールの半径

               // 1ドットずつ移動処理
               for (var i:int = 0; i < bspeed;i++)
               {
                   // 座標を移動
                   ball.x += ball.vx/bspeed;
                   ball.y += ball.vy/bspeed;

                   // 移動先にブロックがある場合、そのパーティクルを落下ブロックに移行
                   var hitParticle:Particle = _blocks.getParticle(ball.x, ball.y);
                   if(hitParticle)
                   {
                       // ブロックからパーティクルを抽出
                       var removedP:Particle = _blocks.removeParticle(ball.x, ball.y);

                       // パーティクルのパラメータを設定
                       removedP.vx = Math.cos(bradius+Math.PI*2/(30*Math.random())-15)*3;
                       removedP.vy = 1;
                       removedP.color = hitParticle.color;

                       // パーティクルを落下ブロックに追加
                       _fallBlocks.push(removedP);

                       // ボールの縦移動ベクトル反転
                       ball.vy = -ball.vy;
                    }

                   // 当たり判定
                   if ((ball.x < 0 && ball.vx < 0) || (ball.x > WIDTH && ball.vx > 0)) {
                       ball.vx = -ball.vx; // 横方向を反転
                   }
                   if (ball.y < 0 && ball.vy < 0) {
                       ball.vy = -ball.vy; // 縦方向を反転
                   }
                   if (_bar.hitTestPoint(ball.x, ball.y)) {
                       ball.vy = -Math.abs(ball.vy); // 縦方向を反転
                   }
                   if (ball.y > HEIGHT) {
                        removeBalls.push(ball); // ボールを削除
                   }

                   // ボールを描画
                   _canvas.setPixel(ball.x, ball.y, ball.color);
               }
            }
            
            // ブロックから条件に合うものを削除
            removeBalls.forEach(function(b:Particle, ...args):void {
                var index:int = _balls.indexOf(b);
                if (index != -1) {
                    _balls.splice(index, 1);
                }
            });

            // 落下ブロックの更新
            var removeFallBs:Vector.<Particle> = new Vector.<Particle>();
            _fallBlocks.forEach(function(fallP:Particle, ...args):void {
                fallP.vy += 0.1; // Y移動ベクトルを加速
                fallP.x += fallP.vx; // X位置を更新
                fallP.y += fallP.vy; // Y位置を更新
                _canvas.setPixel(fallP.x, fallP.y, fallP.color); // 描画

                // バーとぶつかっていればボールを生成
                if (_bar.hitTestPoint(fallP.x,fallP.y)) {
                    var newball:Particle = new Particle(fallP.x,fallP.y);
                    newball.vx = Math.random() * 20 - 10;
                    newball.vy = Math.random() * 9 + 1;
                    newball.color = fallP.color;
                    _balls.push(newball);
                    removeFallBs.push(fallP);
                }
                // 画面下まで落下しきったので削除
                else if (fallP.y > HEIGHT) {
                    removeFallBs.push(fallP);
                }
                // 壁に当たったので反転
                else if (fallP.x < 0 && fallP.vx < 0 || fallP.x > WIDTH && fallP.vx > 0) {
                       fallP.vx = -fallP.vx; // 横方向を反転
                }
            });
            
            // 落下ブロックから条件の合うものを削除
            removeFallBs.forEach(function(b:Particle,...args):void{
                var index:int = _fallBlocks.indexOf(b);
                if (index != -1) {
                    _fallBlocks.splice(index, 1);
                }
            });
            
            // バーの位置を更新
            _bar.x = stage.mouseX - BAR_WIDTH / 2;
            
            // キャンバスのロックを解除
            _canvas.unlock();
            
            // 残りブロックが0ならクリアテキストを描画して更新を停止
            if (_blocks.count == 0) {
                // イベントを削除
                removeEventListener(Event.ENTER_FRAME, update);

                // テキストを描画
                var clearTF:TextField = new TextField();
                clearTF.text = "CLEAR!\nおめでと";
                clearTF.textColor = 0xFFFFFF;
                clearTF.autoSize = TextFieldAutoSize.LEFT;
                _canvas.draw(clearTF,new Matrix(5,0,0,5,WIDTH/2-clearTF.width*5/2,HEIGHT/2-clearTF.height*5/2));
            }
        }
    }
}
import frocessing.color.ColorHSV;
class Blocks
{
    // 総数
    public function get count():int { return _count;}
    private var _count:int;

    // 縦幅
    public function get width():Number { return _width; }
    private var _width:Number;

    // 横幅
    public function get height():Number { return _height; }
    private var _height:Number;

    // パーティクル配列
    public var values:Vector.<Particle>;

    // コンストラクタ
    function Blocks(width:Number,height:Number)
    {
        // 初期化
        _width = width;
        _height = height;
        _count = width * height;
        values = new Vector.<Particle>(width * height, false);

        // 色を設定
        var c:ColorHSV = new ColorHSV();
        for (var i:int = 0; i < _width; i++) {
            c.h = 360 * i / _width;
            for (var j:int = 0 ; j < _height; j++ ) {
                var p:Particle = new Particle(i, j);
                p.color = c.value;
                values[i + j * _width] = p;
            }
        }
    }

    // 引数の位置にあるパーティクルを取得する(範囲外はnullを返す)
    public function getParticle(x:int, y:int):Particle
    {
        var index:int = x + y * _width;
        if (index >= values.length || index < 0) {
            return null;
        }
        return values[x + y * _width];
    }

    // 引数の位置にあるパーティクルを削除し戻り値として返す
    public function removeParticle(x:int, y:int):Particle
    {
        var p:Particle = values[x + y * _width];
        if (p) {
            _count--;
            values[x + y * _width] = undefined;
        }
        return p;
    }
}
class Particle
{
    public var x:Number; // X位置 
    public var y:Number; // Y位置
    public var vx:Number = 0; // X移動量
    public var vy:Number = 0; // Y移動量
    public var color:uint; // 色
    public function Particle(x:Number=0,y:Number=0)
    {
        this.x = x;
        this.y = y;
    }
}