Canvasはゲームの実践を共有します(十一)


7クッションとジャンプ
よく使われるクッションやジャンプの処理をご紹介します.複雑な運動を実現する際,この2つの技術は多くの場合を処理する.バッファリングとジャンプは、既知の始点から所定の終点にオブジェクトを移動させる技術である.バッファリングとは、オブジェクトがターゲット位置にスライドして停止することを意味し、ジャンプとは、オブジェクトが摩擦力のあるスプリング振動子運動を行うことを意味する.共通点はいくつかあります.
  • 初期位置と目標位置
  • が知る.
  • 運動パラメータは距離に正相関
  • である.
    具体的な原理は,バッファの速度の大きさは距離と正に相関し,ジャンプの加速度の大きさは距離と正に相関する.
    7.1バッファ処理
    バッファには2つの種類があり、バッファが1つに入り、バッファと1つの点を離れる.正弦波でバッファリングしたり、ジャンプでバッファリングしたりするなど、具体的な動き属性もあります.バッファがある点から離れる実装について主に議論し,他のものは後で簡単に紹介する.
    7.1.1単純バッファ単純バッファは容易に理解でき、以下にその実装を簡単に説明する.1つのオブジェクトをマルチフレーム時間でAからBに移動したいと仮定します.A,Bの2点間の角度と距離を計算し,速度を直交分解した後,フレームごとのアニメーションで現在のオブジェクトを新しい位置に再描画し,オブジェクトがB点に達したときにオブジェクトの移動を停止することができる.
    上記のシナリオは簡単に実現できますが、オブジェクトをより自然に移動させたい場合は、このシナリオは間違っています.これは、前述した衝突にのみ適した速度でオブジェクトが移動し、ゴールに達するとすぐに停止することを指定しているためです.この場合,開始運動速度は非常に速く,徐々に目標に近づくにつれて速度は線形に減少し,目標位置に達すると速度は0になるバンドバッファの実現が望ましい.この単純なバッファリングには、非常に容易に実現できる近似スキームがある:1.摩擦係数と同様に0と1の間の数値(バッファシステム)を設定して,我々に近づくバッファ運動をシミュレートした.    2. 目標位置3を決定する.始点から終点までの距離を計算する.上記のバッファ係数の値に、現在のモーションオブジェクトの速度5を乗じる距離を乗じます.各フレームにおいて得られる速度で物体の速度6を決定する.上記3~5ステップを繰り返します.上記で指定したバッファ係数は距離の摩擦係数と見なすことができ,バッファ係数が1に近づくほど瞬時速度も大きくなる.上述したように,我々は依然として小球モデルで簡単なバッファリングの例を実現した.
    <!doctype html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>    </title>
    		<style type="text/css">
    			body {
    				margin: 0px;
    				padding: 0px;
    			}
    
    			canvas {
    				margin: 0px;
    				padding: 0px;
    				border: 1px solid #000;	
    			}
    		</style>
    	</head>
    	<body>
    		<canvas id="canvas" width="600" height="400"></canvas>
    		<script type="text/javascript" src="utils.js"></script>
    		<script type="text/javascript" src="ball.js"></script>
    		<script type="text/javascript">
    			window.onload=function(){
    				//       
    				var canvas=document.getElementById("canvas");
    				var context=canvas.getContext("2d");
    				//      
    				var EASING=0.1;
    				//      
    				var ball=new Ball(40);
    				ball.x=0;
    				ball.y=0;
    
    				(function animationLoop(){
    					window.requestAnimFrame(animationLoop,canvas);
    					context.clearRect(0,0,canvas.width,canvas.height);
    					//      ,            
    					ball.vx=(canvas.width/2-ball.x)*EASING;
    					ball.vy=(canvas.height/2-ball.y)*EASING;
    					//            
    					ball.x+=ball.vx;
    					ball.y+=ball.vy;
    					ball.paint(context);
    				})();
    
    			};
    		</script>
    	</body>
    </html>
    </html>

    簡単ですよね?前に説明したドラッグオブジェクトと組み合わせて、オブジェクトを1つの位置にドラッグすると、オブジェクトが元の位置にバッファリングされます.実装も非常に簡単で、以下のようになります.
                       window.onload=function(){
    				//       
    				var canvas=document.getElementById("canvas");
    				var context=canvas.getContext("2d");
    				//      
    				var EASING=0.1;
    				var mouse=utils.getMousePosition(canvas);
    				//      
    				var ball=new Ball(40);
    				ball.x=canvas.width/2;
    				ball.y=canvas.height/2;
    
    				//        ,            
    				canvas.addEventListener("mousedown",function(event){
    					if(utils.containsPoint(mouse.x,mouse.y,ball.getBounds())){
    						console.log("inner");
    						ball.isDragged=true;
    					}
    				},false);
    				//        ,             
    				canvas.addEventListener("mousemove",function(event){
    					if(ball.isDragged){
    						ball.x=mouse.x;
    						ball.y=mouse.y;
    					}
    				},false);
    				//        
    				canvas.addEventListener("mouseup",function(event){
    					ball.isDragged=false;
    				},false);
    
    				(function animationLoop(){
    					window.requestAnimFrame(animationLoop,canvas);
    					context.clearRect(0,0,canvas.width,canvas.height);
    					//             
    					if(!ball.isDragged){
    						//      ,            
    						ball.vx=(canvas.width/2-ball.x)*EASING;
    						ball.vy=(canvas.height/2-ball.y)*EASING;
    						//            
    						ball.x+=ball.vx;
    						ball.y+=ball.vy;
    					}
    
    					ball.paint(context);
    				})();
    
    			};

    上記の実装には、パフォーマンスの最適化の余地があります.モーションオブジェクトがターゲット位置に到達した後も、私たちのプログラムはオブジェクトの速度を計算し、インタフェースを再描画します.次の制約を追加するだけです.
    if (ball.x === targetX && ball.y === targetY) {
    	//      
    }

    しかし,実際には上記の要求はかなり厳しく,ジノパラドックスでは関連する問題(http://zh.wikipedia.org/wiki/ジノパラドックス).エンジニアリングでは簡単な近似スキームを見つけることができ、次のコードは明確に結論を出した.
    var position = 0,
    target = 100;
    for (var i = 0; i < 20; i++) {
        console.log(i + ": " + position);
        position += (target - position) * 0.5;
    }

    最後の出力では、positionの値は99.99904632356836であることがわかります.これは私たちの結果に非常に近い.バッファ係数に基づいて1回の回数を得て性能最適化を行うことができる.もちろん、canvasゲームの開発では、私たちの最小単位は画素であるため、エンジニアリングの実現には以下のように簡単な近似案があります.
    var animationFlag=null;
    (function drawFrame () {
           animationFlag = window.requestAnim(drawFrame, canvas);
           context.clearRect(0, 0, canvas.width, canvas.height);
            var dx = targetX – ball.x;
            //        ,    
            if (Math.abs(dx) < 1) {
                ball.x = targetX;
                window.cancelRequestAnimationFrame(animRequest);
            } else {
                 var vx = dx * EASING;
                 ball.x += vx;
            }
            ball.draw(context);
    }());

    終点が動的に決定される場合も容易であり,以前に実現したマウス位置取得と組み合わせて,マウス位置を終点とする.次のコードがあります.
    window.onload = function () {
           var canvas = document.getElementById('canvas'),
           var context = canvas.getContext('2d'),
           var mouse = utils.getMousePosition(canvas),  
           var ball = new Ball(),
           var EASING = 0.05;
           
            (function animationLoop () {
                 window.requestAnimFrame(animationLoop, canvas);
                  context.clearRect(0, 0, canvas.width, canvas.height);
                  //             
                  var vx = (mouse.x - ball.x) * EASING,
                  vy = (mouse.y - ball.y) * EASING;
                  ball.x += vx;
                  ball.y += vy;
                  ball.draw(context);
           }());
    };

    7.1.2バッファの使用シーン
    これだけ言うと、バッファはモーションアニメーションにしか使えないと思っているかもしれません.実際にはそうではありません.指定したオブジェクトの複数のプロパティの変化に対してバッファリングテクノロジーを使用することができます.
     
    角度変化の緩衝
    分かりやすいですが、スタート位置は角度に変えただけです.次のように実現します.
    rotation += (targetRotation - rotation) * easing;
    arrow.rotation = rotation * Math.PI / 180; 

    カラーバリエーションのバッファリング(グラデーション)バッファリングを使用すると、カラーバリエーションのカラー値のサイズの変化、透明度の変化をよりリアルにシミュレートできます.色変化の処理であれば、まず色値をr,g,bに分けてrgbの3つの値を独立して補正することが望ましい.次のように実現します.
    //      
    var red = 255,green = 0,blue = 0,redTarget = 0,greenTarget = 0,blueTarget = 255;
    // R,G,B       
    red += (redTarget - red) * easing;
    green += (greenTarget - green) * easing;
    blue += (blueTarget - blue) * easing;
    // R,G,B        16     
    var color = red << 16 | green << 8 | blue;
     
    透明度の処理は、このモードで行うこともできます.
    alpha += (targetAlpha - alpha) * easing;
    ball.color = "rgba(255, 0, 0," + alpha + ")";

    7.1.3複雑なバッファ
    バッファの処理については、最も簡単な処理方法を紹介します.複雑な方法は、通常、速度全体の変化を1つ以上の曲線でシミュレートすることです.http://flashblog.robertpenner.com/(flashバージョン)】およびjavascriptバージョン【https://github.com/lamberta/html5-animation/tree/master/xtras/easing-equations】