HTML5 Canvas:碰撞检测问题

时间:2012-01-20 18:56:14

标签: html5 html5-canvas

我正在使用这个脚本,它利用oCanvas JS库(http://ocanvas.org/)创建HTML5画布并在画布中显示多个对象。目前,我从外部XML文档读取脚本并循环遍历每个项目节点并在画布上创建一个圆形对象。

我遇到了尝试将此对象放在画布上与中间圆圈均匀分布(下面代码中的徽标变量)的问题。

// GLOBALS
    var xmlData = '<?xml version="1.0" encoding="UTF-8"?><root name="CompanyName"><projects><project name="Project1"></project><project name="Project2"></project></projects></root>'

    var xmlObj = []
    // var angle = (360 * Math.PI)/180
    var padding = 15
    var canvas = oCanvas.create({
        canvas: '#myCanvas'
    })
    var c_width = canvas.width
    var c_height = canvas.height

    var logo = canvas.display.ellipse({
        x: c_width / 2,
        y: c_height / 3,
        radius: 80,
        fill: '#d15851'
    })

    canvas.addChild(logo)

    // var getXML = function(file){
    //  $.ajax({
    //      url: file,
    //      type: 'GET',
    //      dataType: 'xml',
    //      async: false,
    //      success: parseXML
    //  })
    // }

    var parseXML = function() {
        var xmlDoc = $.parseXML(xmlData)
        var xml = $(xmlDoc)

        xml.find('project').each(function(i){
            xmlObj[i] = canvas.display.ellipse({
                fill: '#'+'0123456789abcdef'.split('').map(function(v,i,a){
                  return i>5 ? null : a[Math.floor(Math.random()*16)] }).join(''),
                radius: 40,
                opacity: 1
            })
        });

        var angleSingleton = {
            "currentAngle": 0,
            "currentOffset": 0,
            "incrementAngle": function() {
                this.currentAngle = this.currentAngle + this.currentOffset
            }
        }

        angleSingleton.currentOffset = Math.floor((360 * Math.PI)/xmlObj.length);

        for(h = 0; h < xmlObj.length; h++) {
            xmlObj[h].x = (logo.x + logo.radius * Math.cos(angleSingleton.currentAngle)) + xmlObj[h].radius + padding;
            xmlObj[h].y = (logo.y + logo.radius * Math.sin(angleSingleton.currentAngle)) + xmlObj[h].radius + padding;

            canvas.addChild(xmlObj[h])
            angleSingleton.incrementAngle()
        }
    }

//

$(document).ready(function(){
    parseXML()
})

enter image description here

2 个答案:

答案 0 :(得分:1)

您想要了解的是圆的参数方程。基本上,它以特定角度沿圆周界定一个点。这个answer更详细地介绍了它。

要获取新圆的x和y值,请使用以下公式:

x = logo.x + logo.radius * Math.cos(angle)
y = logo.y + logo.radius * Math.sin(angle)

但是,如果您需要,您需要考虑新圈子占用的空间以及任何填充空间。

x = (logo.x + logo.radius * Math.cos(angle)) + newCircle.radius + circlePadding
y = (logo.y + logo.radius * Math.sin(angle)) + newCircle.radius + circlePadding

对于角度函数尝试这样的事情:

var angleSingleton = {
    "currentAngle": 0,
    "currentOffset": 0,
    "incrementAngle": function() {
        this.currentAngle = this.currentAngle + this.currentOffset
    }
}

angleSingleton.currentOffset = (360 * Math.PI)/xmlObj.length;

然后您可以使用它来跟踪公式所需的角度。要获取当前角度,请使用angleSingleton.currentAngle并将angle++替换为angleSingleton.incrementAngle

答案 1 :(得分:1)

我最终搞清楚了!

// EXTENDING OBJECTS
    Array.prototype.min = function(array) {
        return Math.min.apply(Math, array);
    }

    Array.prototype.max = function(array) {
        return Math.max.apply(Math, array)
    }
//

// GLOBALS
    var xmlData = '<?xml version="1.0" encoding="UTF-8"?><root name="CompanyName"><projects><project name="Project1"></project><project name="Project2"></project><project name="Project3"></project></projects></root>'

    var xmlObj = []
        var xmlDoc, xml;
    var padding = 15
    var canvas = oCanvas.create({
        canvas: '#myCanvas'
    })
    var c_width = canvas.width
    var c_height = canvas.height

    var logo = canvas.display.ellipse({
        x: c_width / 2,
        y: c_height / 3,
        radius: 80,
        fill: '#d15851'
    })

        var rectObj = function(){
            this.x =  0;
            this.y =  0;
            this.width =  100;
            this.height = 100;
            this.size = this.width + this.height; //this would equate to a circles radius if dealing with circles
            this.fillerText =  null;
            this.fillRect = function(hexVal){
                if(!hexVal)
                    return '#'+'0123456789abcdef'.split('').map(function(v,i,a){
                return i>5 ? null : a[Math.floor(Math.random()*16)] }).join('')
                else
                    return hexVal

            };
            this.drawRect = function(){
                return canvas.display.rectangle({
                    width: this.width,
                    height: this.height,
                    fill: this.fillRect(),
                    x: this.x,
                    y: this.y
                })
            };
            this.checkCollisions = function(objToCheck) {
                var centerA = { x: this.x+(this.size/2), y: this.y+(this.size/2) };
                var centerB = { x:objToCheck.x+(objToCheck.size/2), y: objToCheck.y+(objToCheck.size/2) };
                var distance = Math.sqrt(((centerB.x-centerA.x)*(centerB.x-centerA.x) + (centerB.y-centerA.y)*(centerB.y-centerA.y)));

                if(distance < (this.size+objToCheck.size)) {
                    objToCheck.x = this.x - (canvas.width/4)
                    objToCheck.fillRect = function(){
                        return 'red'
                    }
                }
            }
        }

    canvas.addChild(logo)

    var parseXML = function() {
        xmlDoc = $.parseXML(xmlData)
        xml = $(xmlDoc)

        xml.find('project').each(function(i){
                    xmlObj[i] = new rectObj()
                    xmlObj[i].fillerText = $(this).attr('name')
                    xmlObj[i].x = (logo.x + logo.radius * Math.cos((360*Math.PI) / (i + 1)) + padding) + ((xmlObj[i].width / 2) + (i+1));
                    xmlObj[i].y = (logo.y + logo.radius * Math.sin((360*Math.PI) / (i + 1)) + padding);
        });

                for(i = 0; i < xmlObj.length; i++) {
                    for(a = i+1; a < xmlObj.length; a++) {
                        xmlObj[i].checkCollisions(xmlObj[a])
                    }
                    canvas.addChild(xmlObj[i].drawRect())
                }
    }

//

$(document).ready(function(){
    parseXML()
})

截屏: enter image description here

我显然需要在Y形坐标中写入矩形,这样它们就不会触及主圆,但是现在,它们都“浮动”,因为它们应该:)

感谢Devin的所有帮助!

BTW,我能够通过研究这个JS文件来编写我的碰撞算法:http://andersonferminiano.com/html5/studies/balls_collisions/collision.js