JavaScript, Moving at a constant speed

前回のコードに跳ね返る処理を入れるにも三角関数は必須だ。
ということで、とりあえずどの方向にも等速にボールを移動させる手段を探す。

Flashゲーム講座&ASサンプル集【三角関数を使った計算について】

‘どの方向にも一定の速度で移動するキャラクター’
というそのものズバリな解説を見つけた、よしコレでいこう。
ActionScript だけど基本計算は JavaScript と同一なはず。

endo blog: Javascript Math.atan2() X軸からポイントまでの角度を取得

って JavaScript には Math.atan2 という便利すぎ関数があるじゃないの。
HTML 中を引っ張った逆方向に移動するのだから

// 角度をラジアンで取得
ラジアン = Math.atan2(Y座標, X座標)
// 移動先の算出
X座標 -= Math.cos(ラジアン) * 移動ピクセル数
Y座標 -= Math.sin(ラジアン) * 移動ピクセル数

あれ、こんな冗談みたいに単純で本当にいいのかな?
試しに前回のを 20/1000 秒毎に 10px 移動する感じに書き換えてみる。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>一定速で移動させる</title>
<!-- for Smart Phone -->
<meta name="viewport" content="
    width=device-width,
    initial-scale=1.0,
    minimum-scale=1.0,
    maximum-scale=1.0,
    user-scalable=no" />
<style>
body {
    margin: 0;
    overflow: hidden;
    -webkit-text-size-adjust: 100%;
}
#ID_CANVAS {
    background-color: #FFEE00;
}
</style>
<script type="text/javascript"><!--

    var canvas = null;
    var context = null;
    var ball = null;
    var offset = 24;
    // struct
    var ballData = function() {
        this.timer_id = -1;
        this.timer_count = 0;
        this.x = 0;
        this.y = 0;
        //this.move_x = 0;
        //this.move_y = 0;
        this.rotation = 0;
    }
    var BallData = new ballData();

    // Event Handler
    var onBallTouchStart = function(e) {
        e.preventDefault();
    }
    var onBallTouchMove = function(e) {
        if (BallData.timer_id == -1) {
            context.clearRect(0, 0, canvas.width, canvas.height);
            BallData.x = e.touches[0].pageX;
            BallData.y = e.touches[0].pageY;
            context.beginPath();
            context.moveTo(160, 160);
            context.lineTo(BallData.x, BallData.y);
            context.stroke();
            moveBall(BallData.x, BallData.y);
        }
    }
    var onBallTouchEnd = function(e) {
        if (BallData.timer_id == -1) {
            //BallData.move_x = (BallData.x - 160) / 5;
            //BallData.move_y = (BallData.y - 160) / 5;
            BallData.rotation = Math.atan2(BallData.y - 160, BallData.x - 160)
            BallData.timer_count = 20;
            BallData.timer_id = setInterval(onTimer, 20);
        }
    }
    // Timer Handler
    var onTimer = function() {
        if (BallData.timer_count > 0) {
            //BallData.x -= BallData.move_x;
            //BallData.y -= BallData.move_y;
            BallData.x -= Math.cos(BallData.rotation) * 10;
            BallData.y -= Math.sin(BallData.rotation) * 10;
            moveBall(BallData.x, BallData.y);
            BallData.timer_count--;
        } else {
            clearInterval(BallData.timer_id);
            BallData.timer_id = -1;
            context.clearRect(0, 0, canvas.width, canvas.height);
            moveBall(160, 160);
        }
    }
    // Func
    var moveBall = function(x, y) {
        ball.style.left = x - offset + "px";
        ball.style.top  = y - offset + "px";
    }
    // Connect
    var init = function() {
        if (window.TouchEvent) {
            canvas = document.getElementById("ID_CANVAS");
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;// - 100;
            context = canvas.getContext("2d");
            ball = document.getElementById("ID_BALL");
            ball.addEventListener("touchstart",onBallTouchStart);
            ball.addEventListener("touchmove",onBallTouchMove);
            ball.addEventListener("touchend",onBallTouchEnd);
            moveBall(160, 160);
            var back = document.getElementById("ID_BACK");
            back.style.top = canvas.height - 30 + "px";
            back.addEventListener("touchstart", function() {
                document.location = ".";
            });
        }
    }
    //-->
</script>

</head>
<body onLoad="init()">

<canvas id="ID_CANVAS"></canvas>
<img id="ID_BALL" src="ball.png" style="position:absolute">
<img id="ID_BACK" src="back.png" style="position:absolute">
<!--<a id="ID_BACK" style="position:absolute" href=".">Back</a>-->

</body>
</html>

画像を引っ張って弾く

上下左右どのように引っ張っても本当にコレだけでイケた。
少しブレるかもと思ったけど一定速でスムースに動いてくれる。

目的どおりのものが少しずづできあがっていくのって楽しい!