[AwayJS] 炎のパーティクル (1)

AwayJSを使って、パーティクルを扱うよ。 :boy:

awayjs_fireparticle1

ParticleAnimationSet, ParticleAnimator を使ってみるよ。 :bouzu:
Mesh, ParticleGeometry, PrimitivePlanePrefab も使うよ。 :boy:
そして、AssetLibrary で、外部画像を読み込んでみたよ。 :sun:

パーティクルの動きとして、ParticleBillboardNode, ParticlePositionNode, ParticleVelocityNode, ParticleScaleNode, ParticleColorNode も使ってみた! :cake:
BlendMode, ColorTransform も使ってるよ! :bear:

ParticleColorState を使って、色変化を実現してみたり。 :beer:

HoverController を用いて、ぐるんぐるん動かせるようにしてみたよ。 :sun:

Main.ts
/// <reference path="libs/awayjs-core/build/awayjs-core.d.ts" />
/// <reference path="libs/awayjs-stagegl/build/awayjs-stagegl.d.ts" />
/// <reference path="libs/awayjs-renderergl/build/awayjs-renderergl.d.ts" />
/// <reference path="libs/awayjs-display/build/awayjs-display.d.ts" />
/// <reference path="libs/awayjs-methodmaterials/build/awayjs-methodmaterials.d.ts" />


import ContextGLProfile = require("awayjs-stagegl/lib/base/ContextGLProfile");
import DefaultRenderer = require("awayjs-renderergl/lib/DefaultRenderer");
import View = require("awayjs-display/lib/containers/View");
import Scene = require("awayjs-display/lib/containers/Scene");
import Camera = require("awayjs-display/lib/entities/Camera");
import Vector3D = require("awayjs-core/lib/geom/Vector3D");
import HoverController = require("awayjs-display/lib/controllers/HoverController");
import Point = require("awayjs-core/lib/geom/Point");
import RequestAnimationFrame = require("awayjs-core/lib/utils/RequestAnimationFrame");
import ParticleAnimationSet = require("awayjs-renderergl/lib/animators/ParticleAnimationSet");
import ParticleAnimator = require("awayjs-renderergl/lib/animators/ParticleAnimator");
import ParticlePropertiesMode = require("awayjs-renderergl/lib/animators/data/ParticlePropertiesMode");
import ParticleProperties = require("awayjs-renderergl/lib/animators/data/ParticleProperties");
import ParticleBillboardNode = require("awayjs-renderergl/lib/animators/nodes/ParticleBillboardNode");
import ParticlePositionNode = require("awayjs-renderergl/lib/animators/nodes/ParticlePositionNode");
import ParticleVelocityNode = require("awayjs-renderergl/lib/animators/nodes/ParticleVelocityNode");
import ParticleScaleNode = require("awayjs-renderergl/lib/animators/nodes/ParticleScaleNode");
import ParticleColorNode = require("awayjs-renderergl/lib/animators/nodes/ParticleColorNode");
import ParticleColorState = require("awayjs-renderergl/lib/animators/states/ParticleColorState");
import Mesh = require("awayjs-display/lib/entities/Mesh");
import Geometry = require("awayjs-display/lib/base/Geometry");
import ParticleGeometry = require("awayjs-renderergl/lib/base/ParticleGeometry");
import ParticleGeometryHelper = require("awayjs-renderergl/lib/utils/ParticleGeometryHelper");
import PrimitivePlanePrefab = require("awayjs-display/lib/prefabs/PrimitivePlanePrefab");
import TriangleMethodMaterial = require("awayjs-methodmaterials/lib/TriangleMethodMaterial");
import Texture2DBase = require("awayjs-core/lib/textures/Texture2DBase");
import AssetLibrary = require("awayjs-core/lib/library/AssetLibrary");
import LoaderEvent = require("awayjs-core/lib/events/LoaderEvent");
import URLRequest = require("awayjs-core/lib/net/URLRequest");
import ColorTransform = require("awayjs-core/lib/geom/ColorTransform");
import BlendMode = require("awayjs-display/lib/base/BlendMode");

class Main {

  private renderer:DefaultRenderer;
  private view:View;
  private scene:Scene;
  private camera:Camera;
  private controller:HoverController;
  private timer:RequestAnimationFrame;
  private animation:ParticleAnimationSet;
  private animator:ParticleAnimator;
  private particle:Mesh;
  private material:TriangleMethodMaterial;
  private texture:Texture2DBase;
  private colorNode:ParticleColorNode;
  private startColorTrans:ColorTransform;
  private endColorTrans:ColorTransform;
  private radius:number = 500;
  private moving:boolean = false;
  private angle:number = 180;
  private degree:number = 0;
  private deceleration:number = 0.3;
  private point:Point = new Point();
  private center:Vector3D = new Vector3D();
  private filePath:string = "assets/particle.png";

  constructor() {
    this.renderer = new DefaultRenderer(false, ContextGLProfile.BASELINE);
    this.renderer.antiAlias = 4;
    this.view = new View(this.renderer);
    this.scene = this.view.scene;
    this.camera = this.view.camera;
    this.controller = new HoverController(this.camera, null, this.angle, this.degree);
    this.setup();
    //this.initialize();
    window.onresize = (evt:UIEvent) => this.resize(evt);
    this.resize();
    this.timer = new RequestAnimationFrame(this.render, this);
    this.timer.start();
    AssetLibrary.addEventListener(LoaderEvent.RESOURCE_COMPLETE, (evt:LoaderEvent) => this.loaded(evt));
    AssetLibrary.load(new URLRequest(this.filePath));

    document.onmousedown = (evt:MouseEvent) => this.press(evt);
    document.onmouseup = (evt:MouseEvent) => this.release(evt);
    document.onmousemove = (evt:MouseEvent) => this.move(evt);
    if (window["TouchEvent"]) {
      document.body["ontouchstart"] = (evt) => this.touchstart(evt);
      document.body["ontouchend"] = (evt) => this.touchend(evt);
      document.body["ontouchmove"] = (evt) => this.touchmove(evt);
    }
  }

  private setup():void {
    this.view.backgroundColor = 0x000000;
    this.camera.x = 0;
    this.camera.y = 0;
    this.camera.z = - this.radius;

    this.controller.distance = this.radius;
    this.controller.yFactor = 1;
    this.controller.minTiltAngle = 0;
    this.controller.maxTiltAngle = 90;
  }
  private loaded(evt:LoaderEvent):void {
    switch (evt.url) {
      case this.filePath :
        this.texture = <Texture2DBase> evt.assets[0];
        break;
    }
    if (this.texture) {
      this.initialize();
    }
  }
  private initialize():void {
    var material:TriangleMethodMaterial = new TriangleMethodMaterial(0x333333);
    var ground:Mesh = <Mesh> new PrimitivePlanePrefab(500, 500, 1, 1, true, true).getNewObject();
    ground.material = material;
    ground.y = - 180;
    ground.rotationY = 45;
    this.scene.addChild(ground);

    this.material = new TriangleMethodMaterial(this.texture);
    this.material.blendMode = BlendMode.ADD;

    var plane:PrimitivePlanePrefab = new PrimitivePlanePrefab(60, 60, 1, 1, false, false);
    var planes:Array<Geometry> = new Array<Geometry>();
    for (var n:number = 0; n < 120; n++) {
      planes.push(plane.geometry);
    }
    var geometry:ParticleGeometry = ParticleGeometryHelper.generateGeometry(planes);
    this.particle = new Mesh(geometry, this.material);
    this.scene.addChild(this.particle);
    this.particle.y = - 140;

    this.startColorTrans = new ColorTransform(1, 1, 0, 1);
    this.endColorTrans = new ColorTransform(1, 0, 0, 0);

    this.animation = new ParticleAnimationSet(true, true);
    this.animation.addAnimation(new ParticleBillboardNode());
    this.animation.addAnimation(new ParticlePositionNode(ParticlePropertiesMode.LOCAL_STATIC));
    this.animation.addAnimation(new ParticleVelocityNode(ParticlePropertiesMode.LOCAL_STATIC));
    this.animation.addAnimation(new ParticleScaleNode(ParticlePropertiesMode.LOCAL_STATIC, false, false, 1, 0));
    this.colorNode = new ParticleColorNode(ParticlePropertiesMode.GLOBAL, true, false, false, false, this.startColorTrans, this.endColorTrans);
    this.animation.addAnimation(this.colorNode);
    this.animation.initParticleFunc = this.initParticle;
    this.animation.initParticleScope = this;

    this.animator = new ParticleAnimator(this.animation);
    this.particle.animator = this.animator;
    this.animator.start();
  }
  private initParticle(prop:ParticleProperties):void {
    prop.startTime = Math.random()*2.4;
    prop.duration = 2.4;
    prop[ParticlePositionNode.POSITION_VECTOR3D] = new Vector3D((Math.random() - 0.5)*50, (Math.random() - 0.5)*20, (Math.random() - 0.5)*50);
    prop[ParticleVelocityNode.VELOCITY_VECTOR3D] = new Vector3D((Math.random() - 0.5)*40, 180 + (Math.random() - 0.5)*40, (Math.random() - 0.5)*40);
    var scale:number = 1 + Math.random()*0.5;
    prop[ParticleScaleNode.SCALE_VECTOR3D] = new Vector3D(scale, 0, 0);
    this.startColorTrans.redMultiplier = 0.8 + Math.random()*0.24;
    this.startColorTrans.greenMultiplier = 0.24 + Math.random()*0.12;
    this.endColorTrans.redMultiplier = 0.8 + Math.random()*0.24;
    this.endColorTrans.greenMultiplier = 0.24 + Math.random()*0.12;
    var state:ParticleColorState = < ParticleColorState> this.animator.getAnimationState(this.colorNode);
    state.startColor = this.startColorTrans;
    state.endColor = this.endColorTrans;
  }
  private render(dt:number):void {
    this.camera.lookAt(this.center);
    this.view.render();
  }
  private press(evt:MouseEvent):void {
    this.moving = true;
    this.angle = this.controller.panAngle;
    this.degree = this.controller.tiltAngle;
    this.point.x = evt.clientX;
    this.point.y = evt.clientY;
    evt.preventDefault();
  }
  private release(evt:MouseEvent):void {
    this.moving = false;
  }
  private move(evt:MouseEvent):void {
    if (this.moving) {
      this.controller.panAngle = this.angle + (evt.clientX - this.point.x)*this.deceleration;
      this.controller.tiltAngle = this.degree + (evt.clientY - this.point.y)*this.deceleration;
    }
    evt.preventDefault();
  }
  private touchstart(evt):void {
    var clientX = evt["touches"][0].clientX;
    var clientY = evt["touches"][0].clientY;
    this.moving = true;
    this.angle = this.controller.panAngle;
    this.degree = this.controller.tiltAngle;
    this.point.x = clientX;
    this.point.y = clientY;
    evt.preventDefault();
  }
  private touchend(evt):void {
    this.moving = false;
  }
  private touchmove(evt):void {
    if (this.moving) {
      var clientX = evt["touches"][0].clientX;
      var clientY = evt["touches"][0].clientY;
      this.controller.panAngle = this.angle + (clientX - this.point.x)*this.deceleration;
      this.controller.tiltAngle = this.degree + (clientY - this.point.y)*this.deceleration;
    }
    evt.preventDefault();
  }
  private resize(evt:UIEvent = null):void {
    this.view.width = window.innerWidth;
    this.view.height = window.innerHeight;
  }
}

window.onload = function() {
  new Main();
}

build.txt
src/Main.ts
-target ES5
-module commonjs
-outDir bin

build.txt 上で、[Command + B] して、ビルド。

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
<title>[AwayJS] 炎のパーティクル (1)</title>
<script type="text/javascript" src="js/awayjs-core.min.js">/script>
<script type="text/javascript" src="js/awayjs-stagegl.min.js">/script>
<script type="text/javascript" src="js/awayjs-renderergl.min.js">/script>
<script type="text/javascript" src="js/awayjs-display.min.js">/script>
<script type="text/javascript" src="js/awayjs-methodmaterials.min.js">/script>
<script type="text/javascript" src="Main.js">/script>
<style type="text/css">
  html { overflow:hidden; }
  body { margin:0; padding:0; }
</style>
</head>
<body style="background-color:#000000;">
</body>
</html>


:banana: [TypeScript] AwayJSを始めよう! 参照。


[修正] (14/12/27 Sat 18:48)
HoverController操作に対してTouchEvent対応した。
[修正] (14/12/27 Sat 19:52)
HTML記述を変更。