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


6ユーザー相互作用——物体を移動する
ゲームの核心はインタラクションにあり、多くの場合、ユーザーがゲームオブジェクトを操作する必要があり、基本的な操作の一つは物体を移動することである.次に、物体をドラッグしたり、キャンバスに投げつけたりする方法を紹介します.
6.1オブジェクトの選択と解放
マウスを使用して物体をドラッグ操作するには、主に3つのステップがあります.マウスが物体の範囲に入り、押し、マウスの移動、マウスの解放です.これは、mousedown、mousemove、mouseupの3つのマウスイベントに関連します.私たちはこの考え方に従って、依然として前に紹介した小球システムで実現します.まずマウスが小球に入るかどうかを検出する必要があり,処理を簡略化するために,小球を外接矩形と等価な図形と見なす.まず、キャンバスの中で小さなボールが占める位置を得ます.次のコードがあります.
ball.prototype.getBounds=function(){
    return { x: ball.x-ball.radius,  y: ball.y-ball.radius,
          width: 2*ball.radius,  height: 2*ball.radius };
}

 
以上より,小球外接矩形の左上端点および長幅が得られた.次に、マウスが小球に入るかどうかを確認し、抽象的には点が現在の矩形の中にあるかどうかを確認する必要があります.集合思想を使用すると、対立するイベントを簡単に処理できます.次のコードがあります.
utils.containsPoint = function (rect, x, y) {
        return !(x < rect.x || x > rect.x + rect.width ||
                     y < rect.y || y > rect.y + rect.height);
};
 
私たちはまず点が小球にない4つの状況を取得し、それからその対立事件を点が小球内にあることを明らかにした.簡単に実現できます
    window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
               
                var ball=new Ball();
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
                ball.draw(context);
               //        
                canvas.addEventListener("mousedown",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        console.log("===[mousedown]===in ball");
                    }else{
                        console.log("===[mousedown]===out ball");
                    }
                },false);
               //        
                canvas.addEventListener("mouseup",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        console.log("***[mouseup]===in ball");
                    }else{
                        console.log("***[mouseup]===out ball");
                    }
                },false);
               //      
                canvas.addEventListener("mousemove",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        console.log("###[mousemove]###in ball");
                    }else{
                        console.log("###[mousemove]###out ball");
                    }
                })
            };
 
 
6.2オブジェクトをドラッグ
上記の実践的な基礎があれば、ドラッグを実現するのは簡単で、マウスが移動するときにボールの位置をマウスの位置と同じにするだけでいいです.次のコードがあります.
window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
               
                var ball=new Ball(40);
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
                ball.draw(context);
               //        
                var offset_fix_x=0;
                var offset_fix_=0;
               //               ,    ,           
                canvas.addEventListener("mousedown",function(event){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        offset_fix_x=mouse.x-ball.x;
                        offset_fix_y=mouse.y-ball.y;
                        canvas.addEventListener("mousemove",onMouseMove,false);
                        canvas.addEventListener("mouseup",onMouseUP,false);
                    }
                },false);
                //          
                function onMouseUP(){
                    canvas.removeEventListener("mouseup",onMouseUP,false);
                    canvas.removeEventListener("mousemove",onMouseMove,false);
                }
               //           
                function onMouseMove(event){
                    ball.x=mouse.x-offset_fix_x;
                    ball.y=mouse.y-offset_fix_y;
                }
               
                (function drawFrame(){
                    window.requestAnimFrame(drawFrame,canvas);
                    context.clearRect(0,0,canvas.width,canvas.height);
                   
                    ball.draw(context);
                })();
            };

簡単にボールが動く機能を実現しました.注意、offset_xとoffset_yは、小球の内部で小球の縁をすばやくクリックすることによって生じる小球のジャンプ問題を処理するために使用される.マウスの押下時のマウスとボールの中心からのずれ距離を記録することで、マウスの移動時にこのずれを固定処理することで、ジャンプを避けることができます.
6.3ドラッグ移動中のオブジェクト
移動中のオブジェクトをドラッグする必要がある場合は、原理は前述した静止したオブジェクトと同じですが、マウスクリック後のボールの状態を処理しなければなりません.このときのボールの速度を0にしなければなりません.そうしないと、マウスがボールをクリックした後も、ボールはその前の速度で動き続け、ドラッグ操作が難しくなります.次のコードがあります.
window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
                var left=0,top=0,right=canvas.width,bottom=canvas.height,isMouseDown=false;
                var ball=new Ball(40);
                //      
                var fix_offset_jump_x=fix_offset_jump_y=0;
               //         
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
                ball.vx=Math.random()*10-5;
                ball.vy=-10;
                bounce=-0.7;
                gravity=0.2;
                //               ,    ,           
                canvas.addEventListener("mousedown",function(){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        isMouseDown=true;
                        //         ,       
                        ball.vx=0;
                        ball.vy=0;
                        fix_offset_jump_x=mouse.x-ball.x;
                        fix_offset_jump_y=mouse.y-ball.y;
                        canvas.addEventListener("mousemove",onMouseMove,false);
                        canvas.addEventListener("mouseup",onMouseUP,false);
                    }
                },false);
               
                function onMouseUP(){
                    isMouseDown=false;
                    canvas.removeEventListener("mousemove",onMouseMove,false);
                    canvas.removeEventListener("mouseup",onMouseUP,false);
                }
               
                function onMouseMove(){
                    ball.x=mouse.x-fix_offset_jump_x;
                    ball.y=mouse.y-fix_offset_jump_y;
                }
               //    ,    
                function checkBoundary(){
                    ball.vy+=gravity;
                    ball.x+=ball.vx;
                    ball.y+=ball.vy;
                    if(ball.y-ball.radius<top){
                        ball.y=ball.radius+top;
                        ball.vy*=bounce;
                        console.log(ball.vy);
                    }else if(ball.y+ball.radius>bottom){
                        ball.y=bottom-ball.radius;
                        ball.vy*=bounce;
                    }
                    if(ball.x-ball.radius<left){
                        ball.x=ball.radius+left;
                        ball.vx*=bounce;
                    }else if(ball.x+ball.radius>right){
                        ball.x=right-ball.radius;
                        ball.vx*=bounce;
                    }       
                }
               
                (function drawFrame(){
                    window.requestAnimFrame(drawFrame,canvas);
                    context.clearRect(0,0,canvas.width,canvas.height);
                   
                    if(!isMouseDown){
                        checkBoundary();
                    }   
                    ball.draw(context);
                })();
            };

 
6.4投げ対象
オブジェクトの投げ動作は複雑に見えますが、以前のドラッグ動作と組み合わせると、その実現は非常に簡単です.静止したボールを1フレームで元の位置から10画素水平に移動してマウスを離すと、投げ動作が実現すると仮定すると、ボールは10画素/フレームの速度で水平に投げ出されると考えられる.すなわち
ball.vx=ball.x-lastX;
ball.vy=ball.y-lastY;

 
そこで、移動中のボールを投げる動作を行います.コードは以下の通りです.
window.onload=function(){
                var canvas=document.getElementById("canvas");
                var context=canvas.getContext("2d");
                var mouse=utils.captureMouse(canvas);
                //        
                var top=0,left=0,right=canvas.width,left=0,bottom=canvas.height;
                var fix_mouse_drag_offset_x=0;
                var fix_mouse_drag_offset_y=0;
                var bounce=-0.7;
                var gravity=0.2;
                var isMouseDown=false;
                var oldX=oldY=0;

               //     
                var ball=new Ball(40);
               
                ball.x=canvas.width/2;
                ball.y=canvas.height/2;
               
                ball.vx=Math.random()*10-5;
                ball.vy=-10;
                //                 
                canvas.addEventListener("mousedown",function(){
                    if(utils.containsPoint(ball.getBounds(),mouse.x,mouse.y)){
                        isMouseDown=true; 
                        //      
                        fix_mouse_drag_offset_x=mouse.x-ball.x;
                        fix_mouse_drag_offset_y=mouse.y-ball.y;
                        //         
                        oldX=ball.x;
                        oldY=ball.y;
                        mouse.vx=mouse.vy=0;
                        canvas.addEventListener("mousemove",onMouseMove,false);
                        canvas.addEventListener("mouseup",onMouseUp,false);
                    }
                },false);
               
                function onMouseMove(){
                    ball.x=mouse.x-fix_mouse_drag_offset_x;
                    ball.y=mouse.y-fix_mouse_drag_offset_x;
                }
               
                function onMouseUp(){
                    isMouseDown=false;
                    canvas.removeEventListener("mousemove",onMouseMove,false);
                    canvas.removeEventListener("mouseup",onMouseUp,false);
                }
               //           
                function trackVelocity(){
                    ball.vx=ball.x-oldX;
                    ball.vy=ball.y-oldY;
                    oldX=ball.x;
                    oldY=ball.y;
                }
               //    ,    
                function checkBoundary(){
                    ball.vy+=gravity;
                    ball.x+=ball.vx;
                    ball.y+=ball.vy;
                   
                    if(ball.x-ball.radius<left){
                        ball.x=left+ball.radius;
                        ball.vx*=bounce;
                    }else if(ball.x+ball.radius>right){
                        ball.x=right-ball.radius;
                        ball.vx*=bounce;
                    }
                   
                    if(ball.y-ball.radius<top){
                        ball.y=top+ball.radius;
                        ball.vy*=bounce;
                    }else if(ball.y+ball.radius>bottom){
                        ball.y=bottom-ball.radius;
                        ball.vy*=bounce;
                    }
                }
               
                (function drawFrame(){
                    window.requestAnimFrame(drawFrame,canvas);
                    context.clearRect(0,0,canvas.width,canvas.height);
                    //     ,      ,             
                    if(!isMouseDown){
                        checkBoundary();   
                    }else{
                        trackVelocity();
                    }
                    ball.draw(context);
                })();
               
            };