HTML5 Canvas: проблемы обнаружения столкновений - PullRequest
0 голосов
/ 20 января 2012

У меня есть скрипт, над которым я работаю, который использует библиотеку 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 ]

1 голос
/ 23 января 2012

Я все понял!

// 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 для прямоугольников, чтобы они не касалисьосновной круг, но на данный момент все они "плавают", как и положено:)

Спасибо за вашу помощь, Девин!

Кстати, я смог написать свое столкновениеалгоритм, изучив этот файл JS: http://andersonferminiano.com/html5/studies/balls_collisions/collision.js

1 голос
/ 21 января 2012

То, на что вы хотите взглянуть, - это параметрическое уравнение для кругов. По сути, он определяет точку по периметру окружности под определенным углом. Этот ответ описывает его более подробно.

Чтобы получить значения 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...