美文网首页WebVRA-Frame教程让前端飞
A-Frame简明教程之实体组件系统

A-Frame简明教程之实体组件系统

作者: 快乐前端FedFun | 来源:发表于2018-02-08 09:00 被阅读2449次

    本文为A-Frame简明教程系列文章的第三篇,大家可以到专题里了解更多。

    实体组件系统

    1. 概述

    实体-组件-系统(Entity Component System, ECS)是三维游戏中常见且理想的设计模式,A-Frame同样采用了ECS模式。

    ECS的基本定义包括:

    • 实体是容器对象,用来包含组件。实体是场景中所有对象的基础。没有附加组件的实体不会渲染任何东西,类似于空的<div>
    • 组件是可重用的模块或数据容器,可以依附于实体以提供外观、行为、功能。组件就像即插即用的对象,所有的逻辑都是通过组件实现,并通过混合、匹配和配置组件来定义不同类型的对象。
    • 系统 为组件提供全局范围、管理和服务。系统通常是可选的,可以用来分离逻辑和数据;系统处理逻辑,组件充当数据容器。

    ECS的优势:

    • 模块化
    • 灵活性
    • 复用性
    • 扩展性

    2. 语法

    A-Frame采用声明式基于DOM的方式实现ECS,组件以实体属性的方式进行声明,语法如下。

    <a-entity ${componentName}="${propertyName1}: ${propertyValue1}; ${propertyName2:}: ${propertyValue2}">
    

    组件以a-entity标签的html属性形式出现,以类似于html标签的style属性形式出现(属性名和属性值中间用冒号,多个属性之间用分号隔开,如下代码所示)。

    <div style="color:red; font-size:18px; ">
    

    在前面我们曾经讲过a-box的使用,其实它可以采用类外一种写法。

    <a-box color="red" position="0 0 -10"></a-box>
    <!--等价于-->
    <a-entity geometry="primitive: box" material="color: red" position="0 0 -10"></a-entity>
    

    其中,geometrymaterialposition等都是以组件的方式出现的,用来给实体a-entity提供外形、行为、功能等。

    3. 组件的注册和使用

    3.1注册组件

    注册组件的语法如下:

    // Registering component in foo-component.js
    AFRAME.registerComponent('foo', {
      //定义和描述组件属性(属性类型、默认值等)
      schema: {},
      //初始化组件时调用一次。用于设置初始状态和实例化变量。
      init: function () {},
      //在组件初始化和任何组件属性更新时调用。
      update: function () {},
      //场景渲染循环的每一帧上调用。连续修改某个时间间隔上的实体或条件轮询。
      tick: function () {},
      //在组件被从实体中删除时或者当实体从场景中分离时被调用。
      remove: function () {},
      //每当场景或实体暂停来删除任意背景或动态行为时被调用。
      pause: function () {},
      //每当场景或实体播放来添加任意背景或动态行为时被调用。
      play: function () {}
    });
    

    3.2使用组件

    <!-- Usage of `foo` component. -->
    <html>
      <head>
        <script src="aframe.min.js"></script>
        <script src="foo-component.js"></script>
      </head>
      <body>
        <a-scene>
          <a-entity foo></a-entity>
        </a-scene>
      </body>
    </html>
    

    4. 案例解析

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>A-Frame简明教程之实体组件系统</title>
            <!--导入aframe库-->
            <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
            <!--注册组件的JS,一般写在外部JS中,这里为了现实方便放在页面内部JS中。-->
            <script type="text/javascript">
                //随机颜色
                AFRAME.registerComponent('random-color', {
                  schema: {
                    min: {default: {x: 0, y: 0, z: 0}, type: 'vec3'},
                    max: {default: {x: 1, y: 1, z: 1}, type: 'vec3'}
                  },
                  
                  update: function () {
                    var data = this.data;
                    var max = data.max;
                    var min = data.min;
                    this.el.setAttribute('material', 'color', '#' + new THREE.Color(
                      Math.random() * max.x + min.x,
                      Math.random() * max.y + min.y,
                      Math.random() * max.z + min.z
                    ).getHexString());
                  }
                }); 
                //随机位置
                AFRAME.registerComponent('random-position', {
                  schema: {
                    min: {default: {x: -10, y: -10, z: -10}, type: 'vec3'},
                    max: {default: {x: 10, y: 10, z: 10}, type: 'vec3'}
                  },
            
                  update: function () {
                    var data = this.data;
                    var max = data.max;
                    var min = data.min;
                    this.el.setAttribute('position', {
                      x: Math.random() * (max.x - min.x) + min.x,
                      y: Math.random() * (max.y - min.y) + min.y,
                      z: Math.random() * (max.z - min.z) + min.z
                    });
                  }
                });
                //生成盒子
                AFRAME.registerComponent('entity-generator', {
                  schema: {
                    mixin: {default: ''},
                    num: {default: 1000}
                  },
                
                  init: function () {
                    var data = this.data;
                
                    // 使用指定的mixin生成实体
                    for (var i = 0; i < data.num; i++) {
                      var entity = document.createElement('a-entity');
                      entity.setAttribute('mixin', data.mixin);
                      this.el.appendChild(entity);
                    }
                  }
                });
            </script>
        </head>
        <body>
            <a-scene>
                <!--资源库-->
                <a-assets>
                    <!--利用混合的方式定制模版-->
                    <a-mixin id="random" geometry="primitive: box" random-position random-color>
                    </a-mixin>
                </a-assets>
                <!--生成实体-->
                <a-entity entity-generator="mixin:random;num:1000;"></a-entity>
            </a-scene>
        </body>
    </html>
    

    codepen上预览、编辑效果


    案例注释写的非常清楚,就不一一给大家解释啦,有问题欢迎大家交流。

    待续

    接下来,我们将继续研究A-Frame,敬请期待!欢迎大家批评指正!!

    声明

    爱前端,乐分享。FedFun希望与您共同进步。
    欢迎任何形式的转载,烦请注明装载,保留本段文字。
    独立博客http://whqet.github.io
    极客头条http://geek.csdn.net/user/publishlist/whqet
    CSDN博客http://blog.csdn.net/whqet/
    我的简书https://www.jianshu.com/u/c11d4318b3c7

    相关文章

      网友评论

        本文标题:A-Frame简明教程之实体组件系统

        本文链接:https://www.haomeiwen.com/subject/hizazxtx.html