Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/454.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 获取画布绘制的上下文线的边界(位置)_Javascript_Html_Canvas - Fatal编程技术网

Javascript 获取画布绘制的上下文线的边界(位置)

Javascript 获取画布绘制的上下文线的边界(位置),javascript,html,canvas,Javascript,Html,Canvas,我在做一个物理测试。我用画布和上下文画了一个带线的圆圈: function drawAngles () { var d = 50; //start line at (10, 20), move 50px away at angle of 30 degrees var angle = 80 * Math.PI/180; ctx.beginPath(); ctx.moveTo(300,0); ctx.lineTo(300,600); //x, y ct

我在做一个物理测试。我用画布和上下文画了一个带线的圆圈:

function drawAngles () {
    var d = 50; //start line at (10, 20), move 50px away at angle of 30 degrees
    var angle = 80 * Math.PI/180;
    ctx.beginPath();
    ctx.moveTo(300,0);
    ctx.lineTo(300,600); //x, y
    ctx.moveTo(0,300);
    ctx.lineTo(600,300);
    ctx.arc(300,300,300,0,2*Math.PI);
    ctx.stroke();
}
我想以某种方式得到圆的曲线边界,这样我就可以判断球元素是否发生了碰撞

如果我在典型的
div
上测试边界,我可以这样做:

var divCoords= $(".boundingBoxDiv").position();
var top = divCoords.top;
etc...
如何使用上下文行执行此操作

这是一张照片。。。球应该弹离圆圈


你研究过光线投射吗?碰撞检测的另一个巧妙技巧是创建一个新的隐藏画布,该画布仅用于碰撞检测。然后,您可以仅使用黑白在其上绘制圆。如果画布上填充了黑色和白色圆圈,则可以通过检查点x处特定像素的颜色来测试碰撞。如果点x为黑色,则对象发生碰撞,否则不会发生碰撞。

这很容易实现,在基于半径的碰撞中,如果距离比对象碰撞的半径更近,则只需检查距离。在本例中,我们需要执行相反的操作,如果对象距离大于边界半径,我们需要更改角度以保持对象在其中

首先我们需要确定边界中心点和边界半径

var boundaryRadius = 300,
    boundaryX = 300,
    boundaryY = 300;
稍后在
ball.update
方法中,我将对照这些值进行检查

    var dx = boundaryX - this.x,
        dy = boundaryY - this.y
我们需要得到我们的球和边界中心点之间的距离

        dist = Math.sqrt(dx * dx + dy * dy);
现在我们需要得到基于当前角度的速度

    this.radians = this.angle * Math.PI/ 180;
    this.velX = Math.cos(this.radians) * this.speed;
    this.velY = Math.sin(this.radians) * this.speed;
接下来,我们检查是否仍在边界内。在这个例子中,如果我们的距离小于300——我们自己的半径(10)那么290,那么继续移动

    if (dist < boundaryRadius-this.radius) {
        this.x += this.velX;
        this.y += this.velY;

完整的代码

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    width = 600,
    height = 600;

canvas.width = width;
canvas.height = height;

var boundaryRadius = 300,
    boundaryX = 300,
    boundaryY = 300;

var Ball = function (x, y, speed) {
    this.x = x || 0;
    this.y = y || 0;
    this.radius = 10;
    this.speed = speed || 10;
    this.color = "rgb(255,0,0)";
    this.angle = Math.random() * 360;
    this.radians = this.angle * Math.PI/ 180;
    this.velX = 0;
    this.velY = 0;
}

Ball.prototype.update = function () {
    var dx = boundaryX - this.x,
        dy = boundaryY - this.y,
        dist = Math.sqrt(dx * dx + dy * dy);

    this.radians = this.angle * Math.PI/ 180;
    this.velX = Math.cos(this.radians) * this.speed;
    this.velY = Math.sin(this.radians) * this.speed;

    // check if we are still inside of our boundary.
    if (dist < boundaryRadius-this.radius) {
        this.x += this.velX;
        this.y += this.velY;
    } else {
        // collision, step back and choose an opposite angle with a bit of randomness.
        this.x -= this.velX;
        this.y -= this.velY;
        this.angle += 180+Math.random()*45;
    }
};

Ball.prototype.render = function () {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    // draw our circle with x and y being the center
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(this.x, this.y);
    ctx.lineTo(this.px, this.py);
    ctx.closePath();
};

var balls = [],
    ballNum = 10;

for(var i = 0; i < ballNum; i++){
    balls.push(new Ball(boundaryX + Math.random()*30, boundaryY + Math.random() * 30,  5 + Math.random()*15));
}


function drawAngles() {
    var d = 50; //start line at (10, 20), move 50px away at angle of 30 degrees
    var angle = 80 * Math.PI / 180;
    ctx.beginPath();
    ctx.moveTo(300, 0);
    ctx.lineTo(300, 600); //x, y
    ctx.moveTo(0, 300);
    ctx.lineTo(600, 300);
    ctx.arc(boundaryX, boundaryY, boundaryRadius, 0, 2 * Math.PI);
    ctx.strokeStyle = "#000";
    ctx.stroke();
}


function render() {
    ctx.clearRect(0, 0, width, height);
    drawAngles();

    balls.forEach(function(e){
        e.update();
        e.render();
    });

    requestAnimationFrame(render);
}

render();
var canvas=document.getElementById(“canvas”),
ctx=canvas.getContext(“2d”),
宽度=600,
高度=600;
画布宽度=宽度;
canvas.height=高度;
var boundaryRadius=300,
边界x=300,
边界Y=300;
var Ball=功能(x、y、速度){
这个.x=x | | 0;
这个.y=y | | 0;
这个半径=10;
这个。速度=速度| | 10;
this.color=“rgb(255,0,0)”;
this.angle=Math.random()*360;
this.radians=this.angle*Math.PI/180;
这个.velX=0;
该值为0;
}
Ball.prototype.update=函数(){
var dx=边界x-this.x,
dy=boundaryY-这个.y,
dist=Math.sqrt(dx*dx+dy*dy);
this.radians=this.angle*Math.PI/180;
this.velX=Math.cos(this.radians)*this.speed;
this.velY=Math.sin(this.radians)*this.speed;
//检查我们是否仍在边界内。
if(距离<边界半径此半径){
this.x+=this.velX;
this.y+=this.y;
}否则{
//碰撞,后退一步,选择一个有点随机性的相反角度。
this.x-=this.velX;
this.y-=this.y;
this.angle+=180+Math.random()*45;
}
};
Ball.prototype.render=函数(){
ctx.fillStyle=this.color;
ctx.beginPath();
//以x和y为中心画圆
ctx.arc(this.x,this.y,this.radius,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(this.x,this.y);
ctx.lineTo(this.px,this.py);
ctx.closePath();
};
var=[],
ballNum=10;
对于(变量i=0;i
我确实喜欢使用第二种方法进行碰撞检测,并且已经使用过几次,但是我通常认为,当您要检查的区域是奇数形状时,最好使用第二种方法,使用该方法时,您也会损失一点精度。在OP的情况下,检查到中心的距离要容易得多,而且不需要另一个画布,开销也要小得多。
var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    width = 600,
    height = 600;

canvas.width = width;
canvas.height = height;

var boundaryRadius = 300,
    boundaryX = 300,
    boundaryY = 300;

var Ball = function (x, y, speed) {
    this.x = x || 0;
    this.y = y || 0;
    this.radius = 10;
    this.speed = speed || 10;
    this.color = "rgb(255,0,0)";
    this.angle = Math.random() * 360;
    this.radians = this.angle * Math.PI/ 180;
    this.velX = 0;
    this.velY = 0;
}

Ball.prototype.update = function () {
    var dx = boundaryX - this.x,
        dy = boundaryY - this.y,
        dist = Math.sqrt(dx * dx + dy * dy);

    this.radians = this.angle * Math.PI/ 180;
    this.velX = Math.cos(this.radians) * this.speed;
    this.velY = Math.sin(this.radians) * this.speed;

    // check if we are still inside of our boundary.
    if (dist < boundaryRadius-this.radius) {
        this.x += this.velX;
        this.y += this.velY;
    } else {
        // collision, step back and choose an opposite angle with a bit of randomness.
        this.x -= this.velX;
        this.y -= this.velY;
        this.angle += 180+Math.random()*45;
    }
};

Ball.prototype.render = function () {
    ctx.fillStyle = this.color;
    ctx.beginPath();
    // draw our circle with x and y being the center
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(this.x, this.y);
    ctx.lineTo(this.px, this.py);
    ctx.closePath();
};

var balls = [],
    ballNum = 10;

for(var i = 0; i < ballNum; i++){
    balls.push(new Ball(boundaryX + Math.random()*30, boundaryY + Math.random() * 30,  5 + Math.random()*15));
}


function drawAngles() {
    var d = 50; //start line at (10, 20), move 50px away at angle of 30 degrees
    var angle = 80 * Math.PI / 180;
    ctx.beginPath();
    ctx.moveTo(300, 0);
    ctx.lineTo(300, 600); //x, y
    ctx.moveTo(0, 300);
    ctx.lineTo(600, 300);
    ctx.arc(boundaryX, boundaryY, boundaryRadius, 0, 2 * Math.PI);
    ctx.strokeStyle = "#000";
    ctx.stroke();
}


function render() {
    ctx.clearRect(0, 0, width, height);
    drawAngles();

    balls.forEach(function(e){
        e.update();
        e.render();
    });

    requestAnimationFrame(render);
}

render();