如何在画布上创建障碍 [英] How to create obstacles in canvas

查看:188
本文介绍了如何在画布上创建障碍的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



  window.onload = function(){var canvas = document.getElementById('game'); var ctx = canvas.getContext(2d); var rightKeyPress = false; var leftKeyPress = false; var upKeyPress = false; var downKeyPress = false; var playerX = canvas.width / 2; var playerY = -50; var dx = 3; var dy = 3; var dxp = 3; var dyp = 3; var dxn = 3; var dyn = 3; var prevDxp = dxp; var prevDyp = dyp; var prevDxn = dxn; var prevDyn = dyn; var playerWidth = 50; var playerHeight = 50; var obstacleWidth = 150; var obstacleHeight = 50; var obstaclePadding = 10; var G = .98; var currentVelocity = 0; var obstacles = []; var imageLoaded = false; document.addEventListener(keyup,keyUp,false); document.addEventListener(keydown,keyDown,false); function keyDown(e){if(e.keyCode == 37){leftKeyPress = true; if(currentVelocity> 2){currentVelocity- = 0.1; }} if(e.keyCode == 38){upKeyPress = true; } if(e.keyCode == 39){rightKeyPress = true; if(currentVelocity <2){currentVelocity + = 0.1; }} if(e.keyCode == 40){downKeyPress = true; }} function keyUp(e){if(e.keyCode == 37){leftKeyPress = false; } if(e.keyCode == 38){upKeyPress = false; } if(e.keyCode == 39){rightKeyPress = false; } if(e.keyCode == 40){downKeyPress = false; }} function createObstacles(){for(x = 0; x< 4; x ++){var obX =(200 * x)+ Math.round(Math.random()* 150); var oby = 50 + Math.round(Math.random()* 400); obstacles.push({x:obX,y:oby}); }} createObstacles(); function drawObstacles(){ctx.beginPath(); for(x = 0; x <4; x ++){var obX = obstacle [x] .x; var oby = obstacle [x] .y; ctx.rect(obX,oby,obstacleWidth,obstacleHeight)} ctx.fillStyle =gray; ctx.fill(); ctx.closePath(); } function initPlayer(){ctx.beginPath(); ctx.rect(playerX,playerY,50,50); ctx.fillStyle =orange; ctx.fill(); ctx.closePath(); } function KeyPressAndGravity(){checkObstacleCollision(); playerX + = currentVelocity; if(rightKeyPress&& playerX + 50< canvas.width){playerX + = dxp; } if(leftKeyPress&&& playerX> 0){playerX- = dxn; } if(upKeyPress&& playerY> 0){playerY  -  = dyn; } if(downKeyPress&& playerY + 50< canvas.height){playerY + = dyp; } if(playerY + 50< canvas.height){playerY + = G; } if(playerX< = 0){currentVelocity = 0; } else if(playerX + 50> = canvas.width){currentVelocity = 0; } dxp = prevDxp; dyp = prevDyp; dxn = prevDxn; dyn = prevDyn; G = .98; if(currentVelocity!= 0){if(currentVelocity> 0){currentVelocity  -  = .01; } else {currentVelocity + = .01; }}} / * --------------------------------------------- -------------- ------------------------------------ ------------------------- ------------------------- ------------------------------------ -------------- -------------检查这部分------------------- --------------- ---------------------------------------------- ---- -------------------------------------------------- ------- ------------------------------------------- ------------------ -------------------------------- ---------------------------- * / function checkObstacleCollision(){var obLen = obstacles.length; for(var x = 0; x  

 < canvas id =gamewidth =1000height =600style =border:1px solid#000;>< / canvas>   



问题是,有时当播放器的速度很高时,它可以通过障碍物,如下图所示。我如何阻止这种情况发生?





解决方案

在那里



你必须确定你的玩家和障碍物在任何时候是否相交 在移动期间 - 即使玩家已经移动超过障碍物的移动结束。因此,您必须考虑玩家从移动的开始到结束所移动的完整路径。



...



然后,您可以通过检查玩家的轨迹是否与障碍物相交来检查玩家是否在移动过程中与障碍物相交。





一种相对有效的方法用于测试涉及快速移动对象的碰撞


  1. 定义连接播放器起始矩形的3个顶点的3个线段


  1. 对于与障碍物相交的3条线中的任何一条,计算线段到障碍物的距离。选择起始顶点和障碍物之间的距离最短的线。


  1. 计算x所选线段的y距离。

      var dx = obstacleIntersection.x  -  start.x; 
    var dy = obstacleIntersection.y - start.y;


  2. 将玩家从起始位置移动第3点计算的距离。这导致玩家移动到它首次与障碍物碰撞的地方。

      player.x + = dx; 
    player.y + = dy;




代码和演示






  • setPlayerVertices 确定连接3个顶点的3个线段


  • hasCollided 找到最短的段连接


  • line2lineIntersection 找到交叉点点(如果有)在2线之间。这用于测试起点到终点段(从#1)和组成障碍矩形的4个线段中的任何一个之间的交叉点。 归属:此功能改编自Paul Bourke有用的



    这里是示例代码和演示如何在障碍物的碰撞点停止玩家:



      var canvas = document.getElementById(canvas); var ctx = canvas.getContext(2d); var cw = canvas.width; var ch = canvas.height; function reOffset (){var BB = canvas.getBoundingClientRect(); offsetX = BB.left; offsetY = BB.top; } var offsetX,offsetY; reOffset(); window.onscroll = function(e){reOffset(); } window.onresize = function(e){reOffset(); } var isDown = false; var startX,startY,dragging; ctx.translate(0.50,0.50); ctx.textAlign ='center'; ctx.textBaseline ='middle'; var pts; var p1 = {x:50,y :50,w:25,h:25,fill:''}; var p2 = {x:250,y:250,w:25,h:25,fill:''}; var ob = {x:100 ,y:150,w:125,h:25,fill:''}; var obVertices = [{x:ob.x,y:ob.y},{x:ob.x + ob.w,y: obj},{x:ob.x + ob.w,y:ob.y + ob.h},{x:ob.x,y:ob.y + ob.h}]; var s1,s2 ,s3,e1,e2,e3,o1,o2,o3,o4; draw(); $(#canvas)。mousedown(function(e){handleMouseDown(e);} ).mousemove(function(e){handleMouseMove(e);}); $(#canvas)。mouseup(function(e){handleMouseUpOut(e);}); function(e){handleMouseUpOut(e);}); function draw(){ctx.clearRect(0,0,cw,ch); // ctx.lineWidth = 4; ctx.globalAlpha = 0.250; ctx.strokeStyle ='blue'; ctx.strokeRect(ob.x,ob.y,ob.w,ob.h); ctx.globalAlpha = 1.00; ctx.fillStyle ='black'; ctx.fillText('obstacle',ob.x + ob.w / 2,ob.y + ob.h / 2); // ctx.globalAlpha = 0.250; ctx.strokeStyle ='gold'; ctx.strokeRect(p1.x,p1.y,p1.w,p1.h); ctx.strokeStyle ='purple'; ctx.strokeRect(p2.x,p2.y,p2.w,p2.h); ctx.fillStyle ='black'; ctx.globalAlpha = 1.00; ctx.fillText('start',p1.x + p1.w / 2,p1.y + p1.h / 2); ctx.fillText('end',p2.x + p2.w / 2,p2.y + p2.h / 2);} function handleMouseDown(e){//告诉浏览器我们正在处理这个事件e.preventDefault (); e.stopPropagation(); startX = parseInt(e.clientX-offsetX); startY = parseInt(e.clientY-offsetY); // Put your mousedown stuff here var mx = startX; var my = startY; if(mx> p1.x&& mx< p1.x + p1.w&&&&&&my> p1.y&&&&&&my< p1.y + p1.h){isDown = true; dragging = p1; } else if(mx> p2.x&& mx< p2.x + p2.w&&&&my> p2.y&&&&&my; p2.y + p2.h){isDown = true; dragging = p2; }} function handleMouseUpOut(e){//告诉浏览器我们正在处理这个事件e.preventDefault(); e.stopPropagation(); // Put your mouseup stuff here isDown = false; dragging = null;} function handleMouseMove(e){if(!isDown){return;}告诉浏览器我们正在处理这个事件e.preventDefault(); e.stopPropagation(); mouseX = parseInt(e.clientX-offsetX); mouseY = parseInt(e.clientY-offsetY); // Put your mousemove stuff here var dx = mouseX-startX; var dy = mouseY-startY; startX = mouseX; startY = mouseY; // dragging.x + = dx; dragging.y + = dy; //  画(); // setPlayerVertices(p1,p2); var c = hasCollided(obVertices); if(c.dx){ctx.strokeStyle ='gold'; ctx.strokeRect(p1.x + c.dx,p1.y + c.dy,p1.w,p1.h); ctx.fillStyle ='black'; ctx.fillText('hit',p1.x + c.dx + p1.w / 2,p1.y + c.dy + p1.h / 2);线(c.s,c.i,'red'); }} function setPlayerVertices(p1,p2){var tl1 = {x:p1.x,y:p1.y}; var tl2 = {x:p2.x,y:p2.y}; var tr1 = {x:p1.x + p1.w,y:p1.y}; var tr2 = {x:p2.x + p2.w,y:p2.y}; var br1 = {x:p1.x + p1.w,y:p1.y + p1.h}; var br2 = {x:p2.x + p2.w,y:p2.y + p2.h}; var bl1 = {x:p1.x,y:p1.y + p1.h}; var bl2 = {x:p2.x,y:p2.y + p2.h}; // if(p1.x <= p2.x&& p1.y< = p2.y){s1 = tr1; s2 = br1; s3 = bl1; e1 = tr2; e2 = br2; e3 = bl2; o1 = 0; 02 = 1; o3 = 3; o4 = 0; } else if(p1.x< = p2.x& p1.y> = p2.y){s1 = tl1; s2 = tr1; s3 = br1; e1 = tl2; e2 = tr2; e3 = br2; o1 = 2; o2 = 3; o3 = 3; o4 = 0; } else if(p1.x> = p2.x&& p1.y< = p2.y){s1 = tl1; s2 = br1; s3 = bl1; e1 = tl2; e2 = br2; e3 = b12; o1 = 0; o2 = 1; o3 = 1; o4 = 2; } else if(p1.x> = p2.x& p1.y> = p2.y){s1 = tl1; s2 = tr1; s3 = bl1; e1 = tl2; e2 = tr2; e3 = bl2; o1 = 1; o2 = 2; o3 = 2; o4 = 3; }} function hasCollided(o){// var i1 = line2lineIntersection(s1,e1,o [o1],o [o2]); var i2 = line2lineIntersection(s2,e2,o [o1],o [o2]); var i3 = line2lineIntersection(s3,e3,o [o1],o [o2]); var i4 = line2lineIntersection(s1,e1,o [o3],o [o4]); var i5 = line2lineIntersection(s2,e2,o [o3],o [o4]); var i6 = line2lineIntersection(s3,e3,o [o3],o [o4]); // var tracks = []; if(i3){tracks.push(track(s2,e2,i2));} if(i3){tracks.push (s3,e3,i3));} if(i4){tracks.push(track(s1,e1,i4) if(i6){tracks.push(track(s3,e3,i6));} // var nohitDist = 10000000; var minDistSq = nohitDist; var halt = {dx:null,dy:null,}; for(var i = 0; i  

      body {background-color :象牙} #canvas {border:1px solid red; }  

     < script src =https:// ajax .googleapis.com / ajax / libs / jquery / 1.9.1 / jquery.min.js>< / script>< h4> < br>< br>< br>< br>< br>< br>< br>< br>< br>< br>与障碍物相交的最短段是红色。 ; / canvas>  


    I am trying to make a simple platformer like game.The code i am using is shown below

    window.onload = function(){
    	var canvas = document.getElementById('game');
    	var ctx = canvas.getContext("2d");
    
    	var rightKeyPress = false;
    	var leftKeyPress = false;
    	var upKeyPress = false;
    	var downKeyPress = false;
    	var playerX = canvas.width / 2;
    	var playerY = -50;
    	var dx = 3;
    	var dy = 3;
    	var dxp = 3;
    	var dyp = 3;
    	var dxn = 3;
    	var dyn = 3;
    	var prevDxp = dxp;
    	var prevDyp = dyp;
    	var prevDxn = dxn;
    	var prevDyn = dyn;
    	var playerWidth = 50;
    	var playerHeight = 50;
    	var obstacleWidth = 150;
    	var obstacleHeight = 50;
    	var obstaclePadding = 10;
    	var G = .98;
    	var currentVelocity = 0;
    	var obstacles = [];
    	var imageLoaded = false;
    
    	document.addEventListener("keyup",keyUp,false);
    	document.addEventListener("keydown",keyDown,false);
    
    	function keyDown(e){
    		if(e.keyCode == 37){
    			leftKeyPress = true;
    			if(currentVelocity > 2){
    				currentVelocity -= .1;
    			}
    		}
    		if(e.keyCode == 38){
    			upKeyPress = true;
    		}
    		if(e.keyCode == 39){
    			rightKeyPress = true;
    			if(currentVelocity < 2){
    				currentVelocity += .1;
    			}
    		}
    		if(e.keyCode == 40){
    			downKeyPress = true;
    		}
    	}
    	function keyUp(e){
    		if(e.keyCode == 37){
    			leftKeyPress = false;
    		}
    		if(e.keyCode == 38){
    			upKeyPress = false;
    		}
    		if(e.keyCode == 39){
    			rightKeyPress = false;
    		}
    		if(e.keyCode == 40){
    			downKeyPress = false;
    		}
    	}
    	function createObstacles(){
    		for(x=0;x < 4;x++){
    			var obX = (200 * x) + Math.round(Math.random() * 150);
    			var obY = 50 + Math.round(Math.random() * 400);
    			obstacles.push({"x":obX,"y":obY});
    		}
    	}
    	createObstacles();
    	function drawObstacles(){
    		ctx.beginPath();
    		for(x=0;x < 4;x++){
    			var obX = obstacles[x].x;
    			var obY = obstacles[x].y;
    			ctx.rect(obX,obY,obstacleWidth,obstacleHeight)
    		}	
    		ctx.fillStyle = "grey";
    		ctx.fill();
    		ctx.closePath();
    	}
    	function initPlayer(){
    		ctx.beginPath();
    		ctx.rect(playerX,playerY,50,50);
    		ctx.fillStyle="orange";
    		ctx.fill();
    		ctx.closePath();
    	}
    	function KeyPressAndGravity(){
    		checkObstacleCollision();
    		playerX += currentVelocity;
    		if(rightKeyPress && playerX + 50 < canvas.width){
    			playerX += dxp;
    		}
    		if(leftKeyPress && playerX > 0){
    			playerX -= dxn;
    		}
    		if(upKeyPress && playerY > 0){
    			playerY -= dyn;
    		}
    		if(downKeyPress && playerY + 50 < canvas.height){
    			playerY += dyp;
    		}
    		if(playerY+50 < canvas.height){
    			playerY += G;
    		}
    		if(playerX <= 0){
    			currentVelocity = 0;
    		}else if(playerX + 50 >= canvas.width){
    			currentVelocity = 0;
    		}
    		dxp = prevDxp;
    		dyp = prevDyp;
    		dxn = prevDxn;
    		dyn = prevDyn;
    		G = .98;
    		if(currentVelocity != 0){
    			if(currentVelocity > 0){
    				currentVelocity -= .01;
    			}else{
    				currentVelocity += .01;
    			}
    		}
    	}
      /*-----------------------------------------------------------
      -------------------------------------------------------------
      -------------------------------------------------------------
      ---------------------------Check this part-------------------
      -------------------------------------------------------------
      -------------------------------------------------------------
      -------------------------------------------------------------
      ------------------------------------------------------------*/
    	function checkObstacleCollision(){
    		var obLen = obstacles.length;
    		for(var x=0;x<obLen;x++){
    			var obX = obstacles[x].x;
    			var obY = obstacles[x].y;
    			if((playerX + playerWidth > obX && playerX + playerWidth < obX + obstacleWidth || playerX > obX && playerX < obX + obstacleWidth) && playerY + playerHeight > obY - obstaclePadding && playerY + playerHeight < obY){
    				dyp = 0;
    				G = 0;
    			}else if((playerX + playerWidth > obX && playerX + playerWidth < obX + obstacleWidth || playerX > obX && playerX < obX + obstacleWidth) && playerY > obY + obstacleHeight && playerY < obY + obstacleHeight + obstaclePadding){
    				dyn = 0;
    			}else if(playerX + playerWidth > obX - obstaclePadding && playerX + playerWidth < obX && ((playerY + playerHeight > obY && playerY + playerHeight < obY + obstacleHeight) || (playerY > obY && playerY < obY + obstacleHeight))){
    				dxp = 0;
    			}else if(playerX  > obX + obstacleWidth && playerX < obX + obstacleWidth + obstaclePadding && ((playerY + playerHeight > obY && playerY + playerHeight < obY + obstacleHeight) || (playerY > obY && playerY < obY +  obstacleHeight))){
    				dxn = 0;
    			}
    
    		}
    	}
    	function draw(){
    		ctx.clearRect(0,0,canvas.width,canvas.height);
    		initPlayer();
    		KeyPressAndGravity();
    		drawObstacles();
    	}
    
    	setInterval(draw,15);
    }

    <canvas id="game" width="1000" height="600" style="border:1px solid #000;"></canvas>

    The problem is that sometimes when the speed of the "player" is high it can go through obstacles like the below image. How can i stop that from happening ?

    So what i want is that the player should stop right as he reaches the obstacle and not pass through it

    解决方案

    There is a complication when collision testing objects that are moving quickly

    You must determine if your player and obstacle intersected at any time during the move -- even if the player has moved beyond the obstacle by the end of the move. Therefore you must account for the complete path the player has moved from start to end of the move.

    ...

    Then you can check if the player ever intersected the obstacle during the move by checking if the player's track intersects the obstacle.

    A relatively efficient method for testing collisions involving fast moving objects

    1. Define the 3 line segments that connect the 3 vertices of the player's starting rectangle that are closest to the player's ending rectangle.

    1. For any of the 3 lines that intersect an obstacle, calculate the distance of the line segment to the obstacle. Select the line that has the shortest distance between starting vertex and the obstacle.

    1. Calculate the "x" & "y" distances of the selected line segment.

      var dx = obstacleIntersection.x - start.x;
      var dy = obstacleIntersection.y - start.y;
      

    2. Move the player from their starting position by the distance calculated in #3. This results in the player moving to the spot where it first collided with the obstacle.

      player.x += dx;
      player.y += dy;
      

    Code and Demo:

    Useful functions in the code:

    • setPlayerVertices determines the 3 line segments that connect the 3 vertices of the player's starting rectangle that are closest to the player's ending rectangle.

    • hasCollided finds the shortest segment connecting a vertex from the player's starting position with the collision point on the obstacle.

    • line2lineIntersection finds the intersection point (if any) between 2 lines. This is used to test for an intersection between a start-to-end segment (from #1) and any of the 4 line segments that make up the obstacle rectangle. Attribution: This function is adapted from Paul Bourke's useful treatice on intersections.

    Here is example code and a Demo showing how to halt the player at the collision point on the obstacle:

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    function reOffset(){
        var BB=canvas.getBoundingClientRect();
        offsetX=BB.left;
        offsetY=BB.top;        
    }
    var offsetX,offsetY;
    reOffset();
    window.onscroll=function(e){ reOffset(); }
    window.onresize=function(e){ reOffset(); }
    
    var isDown=false;
    var startX,startY,dragging;
    
    ctx.translate(0.50,0.50);
    ctx.textAlign='center';
    ctx.textBaseline='middle';
    
    var pts;
    var p1={x:50,y:50,w:25,h:25,fill:''};
    var p2={x:250,y:250,w:25,h:25,fill:''};
    var ob={x:100,y:150,w:125,h:25,fill:''};
    var obVertices=[
        {x:ob.x,y:ob.y},
        {x:ob.x+ob.w,y:ob.y},
        {x:ob.x+ob.w,y:ob.y+ob.h},
        {x:ob.x,y:ob.y+ob.h}
    ];
    var s1,s2,s3,e1,e2,e3,o1,o2,o3,o4;
    
    draw();
    
    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUpOut(e);});
    $("#canvas").mouseout(function(e){handleMouseUpOut(e);});
    
    
    function draw(){
        ctx.clearRect(0,0,cw,ch);
        //
        ctx.lineWidth=4;
        ctx.globalAlpha=0.250;
        ctx.strokeStyle='blue';
        ctx.strokeRect(ob.x,ob.y,ob.w,ob.h);
        ctx.globalAlpha=1.00;
        ctx.fillStyle='black';
        ctx.fillText('obstacle',ob.x+ob.w/2,ob.y+ob.h/2);
        //
        ctx.globalAlpha=0.250;
        ctx.strokeStyle='gold';
        ctx.strokeRect(p1.x,p1.y,p1.w,p1.h);
        ctx.strokeStyle='purple';
        ctx.strokeRect(p2.x,p2.y,p2.w,p2.h);
        ctx.fillStyle='black';
        ctx.globalAlpha=1.00;
        ctx.fillText('start',p1.x+p1.w/2,p1.y+p1.h/2);
        ctx.fillText('end',p2.x+p2.w/2,p2.y+p2.h/2);
    }
    
    
    function handleMouseDown(e){
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
      
      startX=parseInt(e.clientX-offsetX);
      startY=parseInt(e.clientY-offsetY);
    
      // Put your mousedown stuff here
      var mx=startX;
      var my=startY;
      if(mx>p1.x && mx<p1.x+p1.w && my>p1.y && my<p1.y+p1.h){
          isDown=true;
          dragging=p1;
      }else if(mx>p2.x && mx<p2.x+p2.w && my>p2.y && my<p2.y+p2.h){
          isDown=true;
          dragging=p2;
      }
    }
    
    function handleMouseUpOut(e){
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
      // Put your mouseup stuff here
      isDown=false;
      dragging=null;
    }
    
    function handleMouseMove(e){
      if(!isDown){return;}
      // tell the browser we're handling this event
      e.preventDefault();
      e.stopPropagation();
    
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
    
      // Put your mousemove stuff here
      var dx=mouseX-startX;
      var dy=mouseY-startY;
      startX=mouseX;
      startY=mouseY;
      //
      dragging.x+=dx;
      dragging.y+=dy;
      //
      draw();
      //
      setPlayerVertices(p1,p2);
      var c=hasCollided(obVertices);
      if(c.dx){
          ctx.strokeStyle='gold';
          ctx.strokeRect(p1.x+c.dx,p1.y+c.dy,p1.w,p1.h);
          ctx.fillStyle='black';
          ctx.fillText('hit',p1.x+c.dx+p1.w/2,p1.y+c.dy+p1.h/2);
          line(c.s,c.i,'red');
      }
    }
    
    function setPlayerVertices(p1,p2){
        var tl1={x:p1.x,      y:p1.y};
        var tl2={x:p2.x,      y:p2.y};
        var tr1={x:p1.x+p1.w, y:p1.y};
        var tr2={x:p2.x+p2.w, y:p2.y};
        var br1={x:p1.x+p1.w, y:p1.y+p1.h};
        var br2={x:p2.x+p2.w, y:p2.y+p2.h};
        var bl1={x:p1.x,      y:p1.y+p1.h};
        var bl2={x:p2.x,      y:p2.y+p2.h};
        //
        if(p1.x<=p2.x && p1.y<=p2.y){
            s1=tr1; s2=br1; s3=bl1;
            e1=tr2; e2=br2; e3=bl2;
            o1=0; o2=1; o3=3; o4=0;
        }else if(p1.x<=p2.x && p1.y>=p2.y){
            s1=tl1; s2=tr1; s3=br1;
            e1=tl2; e2=tr2; e3=br2;
            o1=2; o2=3; o3=3; o4=0;
        }else if(p1.x>=p2.x && p1.y<=p2.y){
            s1=tl1; s2=br1; s3=bl1;
            e1=tl2; e2=br2; e3=bl2;
            o1=0; o2=1; o3=1; o4=2;
        }else if(p1.x>=p2.x && p1.y>=p2.y){
            s1=tl1; s2=tr1; s3=bl1;
            e1=tl2; e2=tr2; e3=bl2;
            o1=1; o2=2; o3=2; o4=3;
        }
    }
    
    function hasCollided(o){
        //
        var i1=line2lineIntersection(s1,e1,o[o1],o[o2]);
        var i2=line2lineIntersection(s2,e2,o[o1],o[o2]);
        var i3=line2lineIntersection(s3,e3,o[o1],o[o2]);
        var i4=line2lineIntersection(s1,e1,o[o3],o[o4]);
        var i5=line2lineIntersection(s2,e2,o[o3],o[o4]);
        var i6=line2lineIntersection(s3,e3,o[o3],o[o4]);
        //
        var tracks=[];
        if(i1){tracks.push(track(s1,e1,i1));}
        if(i2){tracks.push(track(s2,e2,i2));}
        if(i3){tracks.push(track(s3,e3,i3));}
        if(i4){tracks.push(track(s1,e1,i4));}
        if(i5){tracks.push(track(s2,e2,i5));}
        if(i6){tracks.push(track(s3,e3,i6));}
        //
        var nohitDist=10000000;
        var minDistSq=nohitDist;
        var halt={dx:null,dy:null,};
        for(var i=0;i<tracks.length;i++){
            var t=tracks[i];
            var testdist=t.dx*t.dx+t.dy*t.dy;
            if(testdist<minDistSq){
                minDistSq=testdist;
                halt.dx=t.dx;
                halt.dy=t.dy;
                halt.s=t.s;
                halt.i=t.i;
            }
        }
        return(halt);
    }
    //
    function track(s,e,i){
        dot(s);dot(i);line(s,i);line(i,e);
        return({ dx:i.x-s.x, dy:i.y-s.y, s:s, i:i });
    }
    
    
    function line2lineIntersection(p0,p1,p2,p3) {
        var unknownA = (p3.x-p2.x) * (p0.y-p2.y) - (p3.y-p2.y) * (p0.x-p2.x);
        var unknownB = (p1.x-p0.x) * (p0.y-p2.y) - (p1.y-p0.y) * (p0.x-p2.x);
        var denominator  = (p3.y-p2.y) * (p1.x-p0.x) - (p3.x-p2.x) * (p1.y-p0.y);        
        // Test if Coincident
        // If the denominator and numerator for the ua and ub are 0
        //    then the two lines are coincident.    
        if(unknownA==0 && unknownB==0 && denominator==0){return(null);}
        // Test if Parallel 
        // If the denominator for the equations for ua and ub is 0
        //     then the two lines are parallel. 
        if (denominator == 0) return null;
        // If the intersection of line segments is required 
        // then it is only necessary to test if ua and ub lie between 0 and 1.
        // Whichever one lies within that range then the corresponding
        // line segment contains the intersection point. 
        // If both lie within the range of 0 to 1 then 
        // the intersection point is within both line segments. 
        unknownA /= denominator;
        unknownB /= denominator;
        var isIntersecting=(unknownA>=0 && unknownA<=1 && unknownB>=0 && unknownB<=1)
        if(!isIntersecting){return(null);}
        return({
            x: p0.x + unknownA * (p1.x-p0.x),
            y: p0.y + unknownA * (p1.y-p0.y)
        });
    }
    
    function dot(pt){
        ctx.beginPath();
        ctx.arc(pt.x,pt.y,3,0,Math.PI*2);
        ctx.closePath();
        ctx.fill();
    }
    
    function line(p0,p1,stroke,lw){
        ctx.beginPath();
        ctx.moveTo(p0.x,p0.y);
        ctx.lineTo(p1.x,p1.y);
        ctx.lineWidth=lw || 1;
        ctx.strokeStyle=stroke || 'gray';
        ctx.stroke();
    }

    body{ background-color: ivory; }
    #canvas{border:1px solid red; }

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <h4>Drag start & end player position rects<br>The shortest segment intersecting the obstacle is red.<br>The repositioned player is shown on the obstacle.</h4>
    <canvas id="canvas" width=400 height=400></canvas>

    这篇关于如何在画布上创建障碍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆