HTML5 Canvas と JavaScript を使って作る追尾サンプル 03 – Circle に, 手前の Circle を追尾する処理を追加

phiary に引っ越しました. 毎日プログラミングやWebに関する情報を発信しています! RSS 登録してたまに覗いたり, tweet やハテブして拡散してもらえると幸いです.

Pocket

今回は, 円を追尾する処理を追加します. また見た目の調整も行います.

SAMPLE

今回制作するサンプルはこちら.

VIDEO

チュートリアルムービー

CODE

今回制作したサンプルの script 部分です.

// 定数
var FPS             = 60;
var SCREEN_WIDTH    = 640;
var SCREEN_HEIGHT   = 480;
var CIRCLE_RADIUS   = 30;
var CIRCLE_MAX_NUM  = 10;
var CIRCLE_PURSUIT_RATE = 0.1;  // 収束率

// グローバル
var global = {};
global.context      = null;
global.circleList   = [];

window.onload = function()
{
    init();
    run();
};

var init = function()
{
    var canvas = $id("c");
    global.context = canvas.getContext("2d");
    
    // Circle を生成
    for (var i=0; i<CIRCLE_MAX_NUM; ++i)
    {
        global.circleList.push(new Circle(
            Math.random() * SCREEN_WIDTH,
            Math.random() * SCREEN_HEIGHT,
            "hsla(" + (360/CIRCLE_MAX_NUM)*i +  ", 75%, 50%, 0.75)"
        ));
    }
    // 1個前に生成された Circle を Target としてセット
    for (var i=1,len=global.circleList.length; i<len; ++i)
    {
        global.circleList&#91;i&#93;.target = global.circleList&#91;i-1&#93;;
    }
};

var run = function()
{
    var _run = function()
    {
        update();
        draw();
        
        setTimeout(_run, 1000.0/FPS);
    };
    
    setTimeout(_run, 1000.0/FPS);
};

var update = function()
{
    for (var i=0,len=global.circleList.length; i<len; ++i)
    {
        global.circleList&#91;i&#93;.update();
    }
};

var draw = function()
{
    var ctx = global.context;
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    
    // 円を描画
    ctx.save();
    ctx.globalCompositeOperation = "lighter";
    for (var i=0,len=global.circleList.length; i<len; ++i)
    {
        global.circleList&#91;i&#93;.draw(ctx);
    }
    ctx.restore();
};


/**
 * Circle クラス
 */
var Circle = function(x, y, color)
{
    this.x = x || 0;
    this.y = y || 0;
    this.color = color || "white";
    this.target= null;
};

Circle.prototype = {
    x: null,
    y: null,
    color: null,
    target: null,
    
    update: function()
    {
        if (this.target) {
            this.x += (this.target.x-this.x)*CIRCLE_PURSUIT_RATE;
            this.y += (this.target.y-this.y)*CIRCLE_PURSUIT_RATE;
        }
    },
    
    draw: function(ctx)
    {
        ctx.fillStyle = this.color;
        ctx.beginPath();
        ctx.arc(this.x, this.y, CIRCLE_RADIUS, 0, Math.PI*2, false);
        ctx.fill();
        ctx.closePath();
    }
};
&#91;/code&#93;</pre>
</section>

<section>
    <h2>TIPS</h2>
    <section>
    <h3>収束させる</h3>
    <p>
        プログラムである値に収束させる小技です.
    </p>
    <p>
        今の値を a, ターゲットとなる値を b とすると
    </p>
    <pre class="prettyprint">[code]
a += (b-c)*r;

とすることで a を徐々に b に近づけることができます. rの値は 0.0~1.0 でrの値が大きければ大きいほど近づくスピードが速くなります.

ゲームプログラミングでは, UI とかの演出でよく使ったりします.

ランダムな値を生成

Math.random() で 0.0 ~ 1.0 の間でランダムな値を返してくれます. 今回のサンプルでは,

Math.random() * SCREEN_WIDTH,
Math.random() * SCREEN_HEIGHT,

とすることで画面上のランダムな位置に円を配置するようにしています.

乗算描画で見た目を派手にする

context.globalCompositeOperation = "lighter"

と書くことで乗算描画を行うことができます. 簡単に見た目を派手にできるのでオススメです.

また, 背景の塗りつぶしは乗算にしたくないので save, restore で囲うことで円を描画する際のみ乗算にするよう修正しています.

Chrome だと問題ないのですが Firefox だと乗算描画が苦手みたいでかなり重くなるので使いすぎにはご注意を!!

次回は, 円がマウスについてくる処理を追加します.

TRACK BACK URL

POST COMMENT

メールアドレスが公開されることはありません。