From 0d579f9f133ad1e378d703ea9dc0f1fea6b40bea Mon Sep 17 00:00:00 2001 From: -=yb4f310 Date: Sun, 5 Nov 2017 09:36:09 +0100 Subject: [PATCH] particle system, materials, position, stable --- src/game-lib-a-component-a.js | 2 + src/game-lib-d3-api-particle-engine.js | 34 +++-- src/game-lib-d3-particle-engine.js | 35 +++-- src/game-lib-system-0.js | 6 + src/game-lib-system-particle.js | 185 +++++++++++++++++++++++++ 5 files changed, 237 insertions(+), 25 deletions(-) create mode 100644 src/game-lib-system-particle.js diff --git a/src/game-lib-a-component-a.js b/src/game-lib-a-component-a.js index b8a9163..8e28831 100644 --- a/src/game-lib-a-component-a.js +++ b/src/game-lib-a-component-a.js @@ -281,6 +281,7 @@ GameLib.Component.COMPONENT_SYSTEM_VISUALIZATION = 0x49; GameLib.Component.COMPONENT_FOG = 0x50; GameLib.Component.COMPONENT_MESH_LINE = 0x51; GameLib.Component.COMPONENT_PARTICLE_ENGINE = 0x52; +GameLib.Component.COMPONENT_SYSTEM_PARTICLE = 0x53; /** * Returns string name for component number @@ -366,6 +367,7 @@ GameLib.Component.GetComponentName = function(number) { case 0x50 : return 'GameLib.D3.Fog'; case 0x51 : return 'GameLib.D3.Mesh.Line'; case 0x52 : return 'GameLib.D3.ParticleEngine'; + case 0x53 : return 'GameLib.D3.System.Particle'; break; } diff --git a/src/game-lib-d3-api-particle-engine.js b/src/game-lib-d3-api-particle-engine.js index c6438bd..b9a8dc4 100644 --- a/src/game-lib-d3-api-particle-engine.js +++ b/src/game-lib-d3-api-particle-engine.js @@ -2,7 +2,8 @@ * Raw ParticleEngine API object - should always correspond with the ParticleEngine Schema * @param id * @param name - * @param images + * @param materials + * @param position * @param direction * @param particlesPerSecond * @param distanceType @@ -20,7 +21,8 @@ GameLib.D3.API.ParticleEngine = function( id, name, - images, + materials, + position, direction, particlesPerSecond, distanceType, @@ -45,10 +47,15 @@ GameLib.D3.API.ParticleEngine = function( } this.name = name; - if (GameLib.Utils.UndefinedOrNull(images)) { - images = []; + if (GameLib.Utils.UndefinedOrNull(materials)) { + materials = []; } - this.images = images; + this.materials = materials; + + if (GameLib.Utils.UndefinedOrNull(position)) { + position = new GameLib.API.Vector3(0, 0, 0); + } + this.position = position; if (GameLib.Utils.UndefinedOrNull(direction)) { direction = new GameLib.API.Vector3(0, 0, 1); @@ -122,14 +129,14 @@ GameLib.D3.API.ParticleEngine.prototype.constructor = GameLib.D3.API.ParticleEng */ GameLib.D3.API.ParticleEngine.FromObject = function(objectParticleEngine) { - var apiImages = []; - if (objectParticleEngine.images) { - apiImages = objectParticleEngine.images.map( - function (objectImage) { - if (objectImage instanceof Object) { - return GameLib.D3.API.Image.FromObject(objectImage); + var apiMaterials = []; + if (objectParticleEngine.materials) { + apiMaterials = objectParticleEngine.materials.map( + function (objectMaterial) { + if (objectMaterial instanceof Object) { + return GameLib.D3.API.Material.FromObject(objectMaterial); } else { - return objectImage + return objectMaterial } } ) @@ -138,7 +145,8 @@ GameLib.D3.API.ParticleEngine.FromObject = function(objectParticleEngine) { return new GameLib.D3.API.ParticleEngine( objectParticleEngine.id, objectParticleEngine.name, - apiImages, + apiMaterials, + GameLib.API.Vector3.FromObject(objectParticleEngine.position), GameLib.API.Vector3.FromObject(objectParticleEngine.direction), objectParticleEngine.particlesPerSecond, objectParticleEngine.distanceType, diff --git a/src/game-lib-d3-particle-engine.js b/src/game-lib-d3-particle-engine.js index 2b98cda..7fb2008 100644 --- a/src/game-lib-d3-particle-engine.js +++ b/src/game-lib-d3-particle-engine.js @@ -24,7 +24,8 @@ GameLib.D3.ParticleEngine = function( this, apiParticleEngine.id, apiParticleEngine.name, - apiParticleEngine.images, + apiParticleEngine.materials, + apiParticleEngine.position, apiParticleEngine.direction, apiParticleEngine.particlesPerSecond, apiParticleEngine.distanceType, @@ -39,17 +40,28 @@ GameLib.D3.ParticleEngine = function( apiParticleEngine.parentEntity ); - this.images = this.images.map( - function(image) { - if (image instanceof GameLib.D3.API.Image) { - return new GameLib.D3.Image( + this.materials = this.materials.map( + function(material) { + if (material instanceof GameLib.D3.API.Material) { + return new GameLib.D3.Material( graphics, - image + material ) } } ); + if (this.position instanceof GameLib.API.Vector3) { + this.position = new GameLib.Vector3( + graphics, + this.position, + this + ); + } else { + console.warn('position not instance of API.Vector3'); + throw new Error('position not instance of API.Vector3'); + } + if (this.direction instanceof GameLib.API.Vector3) { this.direction = new GameLib.Vector3( graphics, @@ -65,7 +77,7 @@ GameLib.D3.ParticleEngine = function( this, GameLib.Component.COMPONENT_PARTICLE_ENGINE, { - images : [GameLib.D3.Image] + materials : [GameLib.D3.Material] } ); @@ -83,9 +95,7 @@ GameLib.D3.ParticleEngine.ROTATION_TYPE_CONSTANT = 0x1; * @returns true */ GameLib.D3.ParticleEngine.prototype.createInstance = function() { - this.instance = true; - GameLib.Component.prototype.createInstance.call(this); }; @@ -106,11 +116,12 @@ GameLib.D3.ParticleEngine.prototype.toApiObject = function() { this.id, this.name, - this.images.map( - function(image){ - return GameLib.Utils.IdOrNull(image); + this.materials.map( + function(material){ + return GameLib.Utils.IdOrNull(material); } ), + this.position.toApiObject(), this.direction.toApiObject(), this.particlesPerSecond, this.distanceType, diff --git a/src/game-lib-system-0.js b/src/game-lib-system-0.js index dc2a0fc..40872c2 100644 --- a/src/game-lib-system-0.js +++ b/src/game-lib-system-0.js @@ -66,10 +66,15 @@ GameLib.System = function( if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_STORAGE) { componentType = GameLib.Component.COMPONENT_SYSTEM_STORAGE; } + if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_VISUALIZATION) { componentType = GameLib.Component.COMPONENT_SYSTEM_VISUALIZATION; } + if (apiSystem.systemType === GameLib.System.SYSTEM_TYPE_PARTICLE) { + componentType = GameLib.Component.COMPONENT_SYSTEM_PARTICLE; + } + GameLib.Component.call( this, componentType @@ -90,6 +95,7 @@ GameLib.System.SYSTEM_TYPE_PHYSICS = 0x20; GameLib.System.SYSTEM_TYPE_LINKING = 0x40; GameLib.System.SYSTEM_TYPE_CUSTOM = 0x80; GameLib.System.SYSTEM_TYPE_VISUALIZATION = 0x100; +GameLib.System.SYSTEM_TYPE_PARTICLE = 0x200; GameLib.System.SYSTEM_TYPE_ALL = 0xFFFF; GameLib.System.prototype.createInstance = function() { diff --git a/src/game-lib-system-particle.js b/src/game-lib-system-particle.js new file mode 100644 index 0000000..0405360 --- /dev/null +++ b/src/game-lib-system-particle.js @@ -0,0 +1,185 @@ +/** + * System takes care of updating all the entities (based on their component data) + * @param graphics + * @param apiSystem GameLib.API.System + * @constructor + */ +GameLib.System.Particle = function( + graphics, + apiSystem +) { + this.graphics = graphics; + this.graphics.isNotThreeThrow(); + + GameLib.System.call( + this, + apiSystem + ); + + /** + * this holds a reference to engine components and does some initial setup work so we don't have to do it during render + * like calculate frequency etc.. + * @type {Array} + */ + this.engines = []; + + this.beforeRenderSubscription = null; +}; + +GameLib.System.Particle.prototype = Object.create(GameLib.System.prototype); +GameLib.System.Particle.prototype.constructor = GameLib.System.Particle; + +/** + * Start this system (add all event listeners) + */ +GameLib.System.Particle.prototype.start = function() { + + GameLib.System.prototype.start.call(this); + + this.particleObjects = GameLib.EntityManager.Instance.queryComponents(GameLib.D3.ParticleEngine); + + this.particleObjects.map(this.initialize.bind(this)); + + this.instanceCreatedSubscription = GameLib.Event.Subscribe( + GameLib.Event.INSTANCE_CREATED, + this.instanceCreated.bind(this) + ); + + this.removeComponentSubscription = GameLib.Event.Subscribe( + GameLib.Event.REMOVE_COMPONENT, + this.removeComponent.bind(this) + ); + + this.beforeRenderSubscription = GameLib.Event.Subscribe( + GameLib.Event.BEFORE_RENDER, + this.beforeRender.bind(this) + ); + +}; + +/** + * This function does alot of work we want do have done, but we don't want to do it during 'before render' - since we + * don't want to waste cpu power + * @param component + */ +GameLib.System.Particle.prototype.initialize = function(component) { + + var lookAt = GameLib.EntityManager.Instance.defaultRenderer.camera.lookAt.instance.clone().negate(); + var frequency = Number(1 / component.particlesPerSecond); + + var meshes = []; + for (var i = 0; i < frequency; i++) { + + var apiMesh = new GameLib.D3.API.Mesh( + null, + GameLib.D3.Mesh.MESH_TYPE_PLANE, + 'Particle Mesh', + null, + null, + component.materials + ); + + var mesh = new GameLib.D3.Mesh.Plane( + this.graphics, + apiMesh, + 1, + 1, + 1, + 1 + ); + + meshes.push(mesh); + } + + var engine = { + component : component, + elapsed : 0, + frequency : frequency, + lookAt : lookAt, + meshes : meshes + }; + + this.engines.push(engine); +}; + +/** + * From now on we want to track everything about a component, only from the systems that are active + * @param data + */ +GameLib.System.Particle.prototype.instanceCreated = function(data) { + + if (data.component instanceof GameLib.D3.ParticleEngine) { + console.log('new particle engine'); + this.particleObjects.push(data.component); + this.initialize(data.component); + } + +}; + +/** + * Removes a particle engine from this system + * @param data + */ +GameLib.System.Particle.prototype.removeComponent = function(data) { + + if (data.component instanceof GameLib.D3.ParticleEngine) { + + var index = this.particleObjects.indexOf(data.component); + + if (index !== -1) { + console.log('removing particle engine from system'); + + this.particleObjects.splice(index, 1); + + this.engines = this.engines.reduce( + function(result, engine){ + if (engine.component !== data.component) { + result.push(engine); + } + return result; + }, + [] + ); + } else { + console.log('failed to find the particle engine in the system : ' + data.component.name); + } + } + +}; + +/** + * This is what actually happens to all particles before render + * @param data + */ +GameLib.System.Particle.prototype.beforeRender = function(data) { + + this.totalTime += data.delta; + + this.engines.map( + function(engine) { + + engine.elapsed += data.delta; + + if (engine.elapsed > engine.frequency) { + engine.elapsed = 0; + console.log('spawn time'); + } + + }.bind(this) + ) + +}; + + +/** + * Stop this system (remove all event listeners) + */ +GameLib.System.Particle.prototype.stop = function() { + + GameLib.System.prototype.stop.call(this); + + this.instanceCreatedSubscription.remove(); + this.removeComponentSubscription.remove(); + this.beforeRenderSubscription.remove(); + +};