如何检查画布中是否有两个图纸(线条)发生碰撞?

时间:2016-05-10 15:26:10

标签: javascript canvas html5-canvas

所以我一直在做一个跑棒男子游戏。不幸的是,我遇到过这个问题,我似乎无法弄明白。我想要一个警报出现并说'#34; Game Over"如果一个名为障碍的图画通过我的棍子人。然而,如果我的火柴人踢(他变成红色)并且障碍物右脚接触图纸那么它会说"你赢了"。任何帮助将不胜感激!

以下是我到目前为止的情况:顺便说一句,我考虑检查障碍物通过的给定像素是否为红色,然后说"你赢了#34;但这似乎不起作用。

$(document).ready(function(e){

//get canvas from drawcanvas div
var canvas = document.getElementById("drawCanvas"),

//utilize 2D canvas
context = canvas.getContext('2d'),

//get width of canvas
width = canvas.width,

//get height of canvas
height = canvas.height,

//create stickman to keep track of body parts
stickman = {head: [200, 200, 10,0,  2*Math.PI ],
body: [195, 210, 178, 250],
rightArm: [192,215,200,230,210,230],
leftArm: [192,215,178 ,222,178,230],
rightLeg: [178, 250,190,260,185,275,192, 275],
leftLeg: [178, 250, 168, 260, 155, 262,153, 268]
} ;

//create obstacle 1
obstacle1  = { circle: [450,200, 8, 0, 2* Math.PI],
ob1_mv1:  [455, 200],
ob1_l1: [470, 200],
ob1_mv2:  [445, 200],
ob1_l2: [430, 200] };
var ob1Distance = 0;


var id = context.createImageData(1,1);
var d = id.data;
d[0] = 0;
d[1] = 0;
d[2] = 0;
d[3] = 0;

/function to render normal obstacle
function obstacle1_norm(ob1Distance) {
context.strokeStyle =  "rgb(0,0,0)";

context.beginPath();
//obstacle core
context.arc(obstacle1.circle[0] +ob1Distance,
obstacle1.circle[1],
obstacle1.circle[2],
obstacle1.circle[3],
obstacle1.circle[4],
obstacle1.circle[5]) ;
context.moveTo(obstacle1.ob1_mv1[0] + ob1Distance,obstacle1.ob1_mv1[1]);
context.lineTo(obstacle1.ob1_l1[0] + ob1Distance,obstacle1.ob1_l1[1]);
context.moveTo(obstacle1.ob1_mv2[0] +ob1Distance, obstacle1.ob1_mv2[1]);
context.lineTo(obstacle1.ob1_l2[0] +ob1Distance, obstacle1.ob1_l2[1]);
context.stroke();
}

//function render normal obstacle spin
function obstacle1_spin(ob1Distance){
context.strokeStyle =  "rgb(0,0,0)";

context.beginPath();
context.arc(obstacle1.circle[0] +ob1Distance,
obstacle1.circle[1],
obstacle1.circle[2],
obstacle1.circle[3],
obstacle1.circle[4],
obstacle1.circle[5]) ;
context.moveTo(obstacle1.ob1_mv1[0] - 5  + ob1Distance ,obstacle1.ob1_mv1[1]);
context.lineTo(obstacle1.ob1_l1[0] - 18 + ob1Distance ,obstacle1.ob1_l1[1]);
context.moveTo(obstacle1.ob1_mv2[0] - 5 + ob1Distance  ,obstacle1.ob1_mv2[1]);
context.lineTo(obstacle1.ob1_l2[0] - 20 + ob1Distance,obstacle1.ob1_l2[1]);
context.stroke();
}

function costume1(){
context.strokeStyle =  "rgb(0,0,0)";
context.beginPath();
//head
context.arc(stickman.head[0], stickman.head[1], stickman.head[2], stickman.head[3], stickman.head[4]);
//body
context.moveTo(stickman.body[0],stickman.body[1]);
context.lineTo(stickman.body[2],stickman.body[3]);

//right arm
context.moveTo(stickman.leftArm[0],stickman.leftArm[1]);
context.lineTo(stickman.leftArm[2] ,stickman.leftArm[3]);
context.lineTo(stickman.leftArm[4], stickman.leftArm[5]);

//left arm
context.moveTo(stickman.rightArm[0], stickman.rightArm[1]);
context.lineTo(stickman.rightArm[2], stickman.rightArm[3]);
context.lineTo(stickman.rightArm[4] , stickman.rightArm[5]);

//left leg
context.moveTo(stickman.rightLeg[0], stickman.rightLeg[1]);
context.lineTo(stickman.rightLeg[2],stickman.rightLeg[3]);
context.lineTo(stickman.rightLeg[4] , stickman.rightLeg[5]);
context.lineTo(stickman.rightLeg[6], stickman.rightLeg[7]);


//right leg
context.moveTo(stickman.leftLeg[0], stickman.leftLeg[1]);
context.lineTo(stickman.leftLeg[2], stickman.leftLeg[3]);
context.lineTo(stickman.leftLeg[4], stickman.leftLeg[5]);
context.lineTo(stickman.leftLeg[6] , stickman.leftLeg[7]);
context.stroke();
}

//stick figure costume 2
function costume2(){
context.strokeStyle =  "rgb(0,0,0)";

context.beginPath();
//head
context.arc(stickman.head[0], stickman.head[1], stickman.head[2], stickman.head[3], stickman.head[4]);
//body
context.moveTo(stickman.body[0],stickman.body[1]);
context.lineTo(stickman.body[2],stickman.body[3]);
//left arm
context.moveTo(stickman.leftArm[0],stickman.leftArm[1]);
context.lineTo(stickman.leftArm[2] +10 ,stickman.leftArm[3]+5);
context.lineTo(stickman.leftArm[4] +20, stickman.leftArm[5]-8);
//right arm
context.moveTo(stickman.rightArm[0]    ,  stickman.rightArm[1]);
context.lineTo(stickman.rightArm[2] -20 , stickman.rightArm[3] -5);
context.lineTo(stickman.rightArm[4] -20, stickman.rightArm[5]-5);
//right leg
context.moveTo(stickman.rightLeg[0], stickman.rightLeg[1]);
context.lineTo(stickman.rightLeg[2] - 8 ,stickman.rightLeg[3]);
context.lineTo(stickman.rightLeg[4] -20, stickman.rightLeg[5]);
context.lineTo(stickman.rightLeg[6] -20, stickman.rightLeg[7]);
//left leg
context.moveTo(stickman.leftLeg[0], stickman.leftLeg[1]);
context.lineTo(stickman.leftLeg[2] + 20 , stickman.leftLeg[3]);
context.lineTo(stickman.leftLeg[4] +8, stickman.leftLeg[5] + 8 );
context.lineTo(stickman.leftLeg[6] +15 , stickman.leftLeg[7] + 4);
context.stroke();
}

function fight_kick(){
context.strokeStyle =  "rgba(255,0,0,255)";

context.beginPath();
//head
context.arc(stickman.head[0] - 20, stickman.head[1], stickman.head[2], stickman.head[3], stickman.head[4]);
//body
context.moveTo(stickman.body[0] - 15,stickman.body[1]);
context.lineTo(stickman.body[2],stickman.body[3]);
//left arm
context.moveTo(stickman.leftArm[0] - 13,stickman.leftArm[1]);
context.lineTo(stickman.leftArm[2] - 15 ,stickman.leftArm[3]+5);
context.lineTo(stickman.leftArm[4] - 20, stickman.leftArm[5]-15);
//right arm
context.moveTo(stickman.rightArm[0] - 13    ,  stickman.rightArm[1]+1);
context.lineTo(stickman.rightArm[2]  , stickman.rightArm[3] - 22);
context.lineTo(stickman.rightArm[4] , stickman.rightArm[5] - 35);
//right leg
context.moveTo(stickman.rightLeg[0], stickman.rightLeg[1]);
context.lineTo(stickman.rightLeg[2] - 20 ,stickman.rightLeg[3]);
context.lineTo(stickman.rightLeg[4] -20, stickman.rightLeg[5]);
context.lineTo(stickman.rightLeg[6] -30, stickman.rightLeg[7]);
//left leg
context.moveTo(stickman.leftLeg[0], stickman.leftLeg[1]);
context.lineTo(stickman.leftLeg[2] + 25 , stickman.leftLeg[3]-18);
context.lineTo(stickman.leftLeg[4] + 55, stickman.leftLeg[5] -30 );
context.lineTo(stickman.leftLeg[6] +60, stickman.leftLeg[7] - 40);

context.stroke();
}

var ob1_flag = true ;
function ob1_spinning(){
 if (ob1_flag == true  ) {

   obstacle1_spin(ob1Distance);
   ob1_flag = false;
  }else  if (ob1_flag == false ) {

   obstacle1_norm(ob1Distance) ;
   ob1_flag = true;
  }
 ob1Distance -= 20;

}


//create board
function board(){
context.fillStyle="#FFF";
context.fill();
context.beginPath();
context.moveTo(0,276);
context.lineTo(width,276);
context.stroke();
context.strokeStyle="#000";
context.strokeRect(0,0,width,height);
//setInterval(function(){ob1_spinning();}, 100);

}


function collision() {

var dataPixel = context.getImageData(stickman.rightLeg[4] -20, stickman.rightLeg[5],
canvas.width, canvas.height).data;
if ( obstacle1.circle[0] + ob1Distance - 30  < stickman.head[0] + 10      )  {
}
 if (dataPixel[0] + dataPixel[1]  + dataPixel[2]  <  255 && dataPixel[0] + dataPixel[1]  + dataPixel[2] >= 241 ){
 alert("red") 
}
// context.putImageData(id,stickman.rightLeg[4] -20, stickman.rightLeg[5]);

 }




timer =  setInterval(function(){running();} , 200);
//function check  space key press if so kick
function check(e) {
    var code = e.keyCode;
    //Up arrow pressed
     if (code == 32 ) {
       context.clearRect(150,125.25, 70, 150);
       board();
       clearInterval(timer);
       setTimeout(fight_kick(), 250);
 }
 timer = setInterval(function() { running();}, 250);
}

//check for event keydown
window.addEventListener('keydown',check,false);

//flag for switching costumes
flag = true;

//running function to switch between all costumes
function running(){
if (flag == true) {
 context.clearRect(150,125.25, 70, 150);
 board();
 costume2();
 flag = false;
}else if(flag == false) {
 context.clearRect(150,125.25, 70, 150);
 board();
 costume1();
 flag = true;
}
 }
setInterval(function(){collision();}, 5);
setInterval(function(){
context.clearRect(400+ob1Distance,162, 90 , 50 );
ob1_spinning()
;} , 300);

});

1 个答案:

答案 0 :(得分:1)

您可以使用线交叉算法。如果非空结果它们相交,则输入要检查的两条线。然后根据您输入的线或结果中的线上位置确定哪个线被击中并相应地提供动作。

要进行优化,您可以首先检查边界框,然后检查边界框,检查形状的每一行部分。

这是一个线交叉函数(source):

第1行作为p0x,p0y,p1x,p1y,第2行给出为p2x,p2y,p3x,p3y。如果与对象相交,则返回包含属性xy

的对象
var intPoint = intersection( .... );
if (intPoint) {
  ... some action here...
}

function intersection(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) {

    var d1x = p1x - p0x,
        d1y = p1y - p0y,
        d2x = p3x - p2x,
        d2y = p3y - p2y,

        // determinator
        d = d1x * d2y - d2x * d1y,
        px, py, s, t;

    // continue if intersecting/is not parallel
    if (d) {

      px = p0x - p2x;
      py = p0y - p2y;

      s = (d1x * py - d1y * px) / d;
      if (s >= 0 && s <= 1) {

        // if s was in range, calc t
        t = (d2x * py - d2y * px) / d;
        if (t >= 0 && t <= 1) {
          return {x: p0x + (t * d1x),
                  y: p0y + (t * d1y)}
        }
      }
    }
    return null
}