Aframe:防止两个对象重叠。

时间:2017-06-09 17:41:35

标签: javascript virtual-reality aframe

关注Minecraft demo。如何让块不在同一个地方产卵? This is the script which spawns the boxes.

我能想到两种方法:

  1. 创建我已设置框的坐标的跟踪列表,并在交点匹配(或接近阈值)时阻止创建一个。
  2. 检查标线是否与边界框匹配(使用Threejs' Box3,我不知道如何使用)。
  3. 有关最佳方法的任何想法吗?

1 个答案:

答案 0 :(得分:1)

这是我对#2的回答: 我创建了一个数组。该数组将包含evt.detail.intersection.point的点。在插入新对象之前,我应用毕达哥拉斯(x和z点),并将其与阈值进行比较。只有当它高于阈值时,我才允许它继续,并将新点存储在其中。

整个代码如下:评论:

我在这里使用了一些TypeScript,我不会包含它,因此它可以覆盖更广泛的受众。

我将cross-spawn组件与ES2015类包装起来只是为了分离代码。我不知道通过ES2015创建A-Frame的原生方式。

这是主要类" intersection-spawn.js"

export default class IntersectionSpawn {
    constructor(lamp) {
        //The array that will track the position. 
        this.positionHistory = new Array();
        //The spacing which it will allow to span another light.
        this.minSpacing = 2;
        //Captures the class' *this* so it can be used in the 
        //Event Listener.
        const _this = this;
        //Dependency Injection. Injects the lamp class that manages
        //the lamp creation. 
        this.lamp = lamp;

        AFRAME.registerComponent('intersection-spawn', {
            schema: {
                default: '',
                parse: AFRAME.utils.styleParser.parse
            },

            init: function () {
                //This data comes from the HTML's <a-entity> attribute
                const data = this.data;
                //References the current element. This comes from A-Frame.
                const el = this.el;
                //Reducing the code a little bit.
                //This will create an event listener and pass it to the
                //intersection method.
                el.addEventListener(data.event, evt => {
                    _this.intersection(evt, el, data)
                });
            }
        });
    }

    //This takes care of create the element and insert it. 
    intersection(evt, el, data) {

        //Just a safeguard. If the event data doesn't contain 
        //the intersection property, then I can't do anything. 
        if (evt.detail.hasOwnProperty("intersection") === false)
            return;
        //Define a position object to keep hold of everything.
        //Note that in here I'm just selecting points x and z
        //because in my app, those are the only ones which interests
        //me. "y" is also available by using vt.detail.intersection.point.y
        let pos = {
            x: evt.detail.intersection.point.x,
            z: evt.detail.intersection.point.z
        };

        //If true then it continues, and adds the element. 
        //Otherwise exit. 
        if (!this.canAddToGrid(pos))
            return;

        //Creates a new lamp to be inserted. 
        const elem = this.lamp.generate(data, pos);
        el.sceneEl.appendChild(elem);
        this.appendToHistory(pos);
    }
    //Adds to the current history to be tracked. 
    appendToHistory(pos) {
        this.positionHistory.push(pos);
    }

    /**
     * Checks whether it's posisble to add to the grid or not.
     * This will check if the distance of the current insertion point
     * is equal or smaller to the distance to any of the cylinders. 
     * If that's the case, it will return false. Otherwise it will return
     * true.
     * The position of the current object to be inserted.
     * @param pos 
     */
    canAddToGrid(pos) {
        for (let position of this.positionHistory) {
            if (this.calcDistance(pos.x, pos.z, position.x, position.z) <= this.minSpacing) {
                return false;
            }
        }
        return true;
    }

    /**
     * Calculates the distance from the center of the lamp to the center 
     * of the insertion points.
     * 
     * @param x1 Position x of the object to be inserted
     * @param z1 Position z of the object to be inserted
     * @param x2 Position x of the object inside the array
     * @param z2 Position z of the object inside the array
     */
    calcDistance(x1, z1, x2, z2) {
        return Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((z2 - z1), 2));
    }

}

这是lamp.js(创建灯对象的那个)并被注入到intersectionSpawn类中:

export default class Lamp {
    constructor() {

    }
    /**
     * Creates the Lamp. Right now it's a cylinder. 
     * @param pos The positions you want the lamp to be in.
     */
    create(pos) {
        let elem = (document.createElement("a-cylinder"));
        elem.setAttribute('width', "1");
        elem.setAttribute('height', "4");
        elem.setAttribute('depth', "1");
        elem.setAttribute('position', `${pos.x} 0 ${pos.z}`);
        return elem;
    }

    /**
     * This works like a decorator. this was originaly in the intersection-spawn.
     * I do not know a lot what it does, but it's necessary for the element to work.
     * @param elem The generated element from the create(pos) method.
     * @param data Comes from A-Frame's data. 
     */
    AddAframeUtils(elem, data) {
        Object.keys(data).forEach(name => {
            if (name === 'event') { return; }
            AFRAME.utils.entity.setComponentProperty(elem, name, data[name]);
        });

        return elem;

    }

    /**
     * The public method which generates a fully functional element. 
     * @param data This comes from A-Frame's data.
     * @param position The position in which I want to create the element.
     */
    generate(data, position) {
        return this.AddAframeUtils(this.create(position), data);
    }
}

                    

                                                       

script.js,包括两个类:

import Lamp from './js/lamp/lamp';
import IntersectionSpawn from './js/components/intersection-spawn';

new IntersectionSpawn(new Lamp());

现在,index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>
    <script src="https://rawgit.com/mayognaise/aframe-mouse-cursor-component/master/dist/aframe-mouse-cursor-component.min.js"></script>
    <script src="script.js"></script>
</head>

<body>
    <a-scene>
        <a-sky color="#ECECEC"></a-sky>
        <a-camera>
            <!-- We include the intersection-spawn in here:-->
            <a-cursor intersection-spawn="event: click;"></a-cursor>
        </a-camera>
    </a-scene>
</body>

</html>