particle explosions

beta.r3js.org
-=yb4f310 2017-11-16 13:54:51 +01:00
parent 7cd8a2a3d0
commit 4569ad90b8
12 changed files with 280 additions and 19 deletions

View File

@ -69,7 +69,7 @@ GameLib.Event.COMPONENT_DELETED = 0x33;
GameLib.Event.COMPONENT_TYPES_UPDATED = 0x34;
GameLib.Event.AUDIO_ENDED = 0x35;
GameLib.Event.COMPONENT_LINKED = 0x36;
//GameLib.Event.SOLVER_INSTANCE_CREATED = 0x37;
GameLib.Event.DONE_SAVING = 0x37;
GameLib.Event.BEFORE_RENDER = 0x38;
GameLib.Event.AFTER_RENDER = 0x39;
GameLib.Event.ARRAY_ITEM_ADDED = 0x3a;
@ -84,7 +84,7 @@ GameLib.Event.PARENT_WORLD_CHANGE = 0x42;
GameLib.Event.ANIMATE = 0x43;
GameLib.Event.ANIMATION_COMPILE_SUCCESS = 0x44;
GameLib.Event.ANIMATION_COMPILE_FAILED = 0x45;
//GameLib.Event.CUSTOM_CODE_SYSTEM_STARTED = 0x46;
GameLib.Event.SAVING = 0x46;
GameLib.Event.GAME_OVER = 0x47;
GameLib.Event.GAME_START = 0x48;
GameLib.Event.TOUCH_START = 0x49;
@ -176,7 +176,7 @@ GameLib.Event.GetEventName = function(number) {
case 0x34 : return 'component_types_updated';
case 0x35 : return 'audio_ended';
case 0x36 : return 'component_linked';
case 0x37 : return 'unused';//'solver_instance_created';
case 0x37 : return 'done_saving';
case 0x38 : return 'before_render';
case 0x39 : return 'after_render';
case 0x3a : return 'array_item_added';
@ -191,7 +191,7 @@ GameLib.Event.GetEventName = function(number) {
case 0x43 : return 'animate';
case 0x44 : return 'animation_compile_success';
case 0x45 : return 'animation_compile_failed';
case 0x46 : return 'unused';
case 0x46 : return 'saving';
case 0x47 : return 'game_over';
case 0x48 : return 'game_start';
case 0x49 : return 'touch_start';

View File

@ -632,8 +632,80 @@ GameLib.Component.prototype.saveToRemoteAPI = function() {
GameLib.Component.prototype.save = function(remote) {
var toSave = [];
var saved = [];
var failed = [];
this.buildIdToObject();
if (this.saveSubscription || this.saveErrorSubscription) {
console.warn('another save is in progress');
return;
}
GameLib.Event.Emit(
GameLib.Event.SAVING,
{
component: this
}
);
this.saveSubscription = GameLib.Event.Subscribe(
GameLib.Event.COMPONENT_SAVED,
function(data) {
saved.push(data.component);
if (failed.length + saved.length === toSave.length) {
this.saveSubscription.remove();
this.saveSubscription = null;
this.saveErrorSubscription.remove();
this.saveErrorSubscription = null;
GameLib.Event.Emit(
GameLib.Event.DONE_SAVING,
{
failed: failed,
saved: saved
}
)
}
}.bind(this)
);
this.saveErrorSubscription = GameLib.Event.Subscribe(
GameLib.Event.SAVE_COMPONENT_ERROR,
function(data) {
failed.push(data.component);
if (failed.length + saved.length === toSave.length) {
this.saveSubscription.remove();
this.saveSubscription = null;
this.saveErrorSubscription.remove();
this.saveErrorSubscription = null;
GameLib.Event.Emit(
GameLib.Event.DONE_SAVING,
{
failed: failed,
saved: saved
}
)
}
}.bind(this)
);
for (var property in this.idToObject) {
if (
this.idToObject.hasOwnProperty(property) &&
@ -644,6 +716,8 @@ GameLib.Component.prototype.save = function(remote) {
apiObject.componentType = this.idToObject[property].componentType;
toSave.push(apiObject);
this.publish(
GameLib.Event.SAVE_COMPONENT,
{

View File

@ -6,6 +6,7 @@
* @param loop
* @param volume
* @param camera
* @param overplay
* @param parentEntity
* @constructor
*/
@ -16,6 +17,7 @@ GameLib.D3.API.Audio = function(
loop,
volume,
camera,
overplay,
parentEntity
) {
@ -49,6 +51,11 @@ GameLib.D3.API.Audio = function(
}
this.camera = camera;
if (GameLib.Utils.UndefinedOrNull(overplay)) {
overplay = false;
}
this.overplay = overplay;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
@ -81,6 +88,7 @@ GameLib.D3.API.Audio.FromObject = function(objectAudio) {
objectAudio.loop,
objectAudio.volume,
apiCamera,
objectAudio.overplay,
objectAudio.parentEntity
);

View File

@ -10,6 +10,7 @@
* @param frequency
* @param elapsed
* @param camera
* @param pulse
* @param parentEntity
* @constructor
*/
@ -24,6 +25,7 @@ GameLib.D3.API.ParticleEngine = function(
frequency,
elapsed,
camera,
pulse,
parentEntity
) {
@ -77,6 +79,11 @@ GameLib.D3.API.ParticleEngine = function(
}
this.camera = camera;
if (GameLib.Utils.UndefinedOrNull(pulse)) {
pulse = false;
}
this.pulse = pulse;
if (GameLib.Utils.UndefinedOrNull(parentEntity)) {
parentEntity = null;
}
@ -103,6 +110,15 @@ GameLib.D3.API.ParticleEngine.FromObject = function(objectParticleEngine) {
}
}
var apiCamera = null;
if (objectParticleEngine.camera) {
if (objectParticleEngine.camera instanceof Object) {
apiCamera = GameLib.D3.API.Camera.FromObject(objectParticleEngine.camera);
} else {
apiCamera = objectParticleEngine.camera;
}
}
var apiPosition = null;
if (objectParticleEngine.position) {
apiPosition = GameLib.API.Vector3.FromObject(objectParticleEngine.position);
@ -124,7 +140,8 @@ GameLib.D3.API.ParticleEngine.FromObject = function(objectParticleEngine) {
objectParticleEngine.particlesPerSecond,
objectParticleEngine.frequency,
objectParticleEngine.elapsed,
objectParticleEngine.camera,
apiCamera,
objectParticleEngine.pulse,
objectParticleEngine.parentEntity
);

View File

@ -15,6 +15,7 @@
* @param scale
* @param direction
* @param directionFn
* @param speedType
* @param speed
* @param scaleFn
* @param scaleType
@ -38,6 +39,7 @@ GameLib.D3.API.Particle = function(
directionType,
direction,
directionFn,
speedType,
speed,
scaleType,
scale,
@ -114,6 +116,11 @@ GameLib.D3.API.Particle = function(
}
this.directionFn = directionFn;
if (GameLib.Utils.UndefinedOrNull(speedType)) {
speedType = GameLib.D3.Particle.SPEED_TYPE_CONSTANT;
}
this.speedType = speedType;
if (GameLib.Utils.UndefinedOrNull(speed)) {
speed = 1;
}
@ -193,6 +200,7 @@ GameLib.D3.API.Particle.FromObject = function(objectParticle) {
objectParticle.directionType,
GameLib.API.Vector3.FromObject(objectParticle.direction),
objectParticle.directionFn,
objectParticle.speedType,
objectParticle.speed,
objectParticle.scaleType,
GameLib.API.Vector3.FromObject(objectParticle.scale),

View File

@ -28,6 +28,7 @@ GameLib.D3.Audio = function(
apiAudio.loop,
apiAudio.volume,
apiAudio.camera,
apiAudio.overplay,
apiAudio.parentEntity
);
@ -121,6 +122,7 @@ GameLib.D3.Audio.prototype.toApiObject = function() {
this.loop,
this.volume,
GameLib.Utils.IdOrNull(this.camera),
this.overplay,
GameLib.Utils.IdOrNull(this.parentEntity)
);

View File

@ -32,6 +32,7 @@ GameLib.D3.ParticleEngine = function(
apiParticleEngine.frequency,
apiParticleEngine.elapsed,
apiParticleEngine.camera,
apiParticleEngine.pulse,
apiParticleEngine.parentEntity
);
@ -271,6 +272,7 @@ GameLib.D3.ParticleEngine.prototype.toApiObject = function() {
this.frequency,
this.elapsed,
GameLib.Utils.IdOrNull(this.camera),
this.pulse,
GameLib.Utils.IdOrNull(this.parentEntity)
);

View File

@ -35,6 +35,7 @@ GameLib.D3.Particle = function(
apiParticle.directionType,
apiParticle.direction,
apiParticle.directionFn,
apiParticle.speedType,
apiParticle.speed,
apiParticle.scaleType,
apiParticle.scale,
@ -121,7 +122,8 @@ GameLib.D3.Particle.POSITION_OFFSET_TYPE_FUNCTION = 0x3;
GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.DIRECTION_TYPE_RANDOM = 0x2;
GameLib.D3.Particle.DIRECTION_TYPE_FUNCTION = 0x3;
GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED = 0x3;
GameLib.D3.Particle.DIRECTION_TYPE_FUNCTION = 0x4;
GameLib.D3.Particle.SCALE_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.SCALE_TYPE_LINEAR = 0x2;
@ -130,6 +132,14 @@ GameLib.D3.Particle.SCALE_TYPE_RANDOM = 0x4;
GameLib.D3.Particle.SCALE_TYPE_RANDOM_X_EQUALS_Y = 0x6;
GameLib.D3.Particle.SCALE_TYPE_FUNCTION = 0x7;
GameLib.D3.Particle.SPEED_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.SPEED_TYPE_LINEAR = 0x2;
GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL = 0x3;
GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC = 0x4;
GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG = 0x5;
GameLib.D3.Particle.SPEED_TYPE_EXP = 0x6;
GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP = 0x7;
GameLib.D3.Particle.ROTATION_TYPE_CONSTANT = 0x1;
GameLib.D3.Particle.ROTATION_TYPE_RANDOM = 0x2;
GameLib.D3.Particle.ROTATION_TYPE_FUNCTION = 0x3;
@ -232,6 +242,54 @@ GameLib.D3.Particle.prototype.cloneInstance = function() {
}
}
clone.userData.direction = this.direction.clone();
if (this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT) {
/**
* Nothing to do
*/
} else if (
this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM ||
this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED
) {
addX = GameLib.Utils.GetRandomIntInclusive(1,2);
addY = GameLib.Utils.GetRandomIntInclusive(1,2);
addZ = GameLib.Utils.GetRandomIntInclusive(1,2);
clone.userData.direction.x = 0;
clone.userData.direction.y = 0;
clone.userData.direction.z = 0;
if (addX === 1) {
clone.userData.direction.x += Math.random() * this.direction.x;
} else {
clone.userData.direction.x -= Math.random() * this.direction.x;
}
if (addY === 1) {
clone.userData.direction.y -= Math.random() * this.direction.y;
} else {
clone.userData.direction.y += Math.random() * this.direction.y;
}
if (addZ === 1) {
clone.userData.direction.z -= Math.random() * this.direction.z;
} else {
clone.userData.direction.z += Math.random() * this.direction.z;
}
if (this.directionType === GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED) {
clone.userData.direction.normalize();
}
} else {
throw new Error('not yet implemented')
}
if (this.scaleType === GameLib.D3.Particle.SCALE_TYPE_CONSTANT) {
clone.scale.x += this.scale.x;
clone.scale.y += this.scale.y;
@ -270,9 +328,10 @@ GameLib.D3.Particle.prototype.cloneInstance = function() {
}
}
clone.userData.direction = this.direction.clone();
clone.userData.scale = this.scale.clone();
clone.userData.lifeTime = this.lifeTime;
clone.userData.speedType = this.speedType;
clone.userData.speed = this.speed;
clone.userData.scene = this.mesh.parentScene.instance;
@ -303,6 +362,7 @@ GameLib.D3.Particle.prototype.toApiObject = function() {
this.directionType,
this.direction.toApiObject(),
this.directionFn,
this.speedType,
this.speed,
this.scaleType,
this.scale.toApiObject(),

View File

@ -80,10 +80,18 @@ GameLib.System.Audio.prototype.playAudio = function(data) {
this.audioComponents.map(
function(audio) {
if (audio.name === data.name) {
if (audio.instance.isPlaying && audio.overplay) {
audio.instance.stop();
}
if (!audio.instance.isPlaying) {
audio.instance.play();
audio.instance.onEnded = function() {
this.isPlaying = false;
GameLib.Event.Emit(
GameLib.Event.AUDIO_ENDED,
{

View File

@ -756,10 +756,27 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate,
{
'constant': GameLib.D3.Particle.DIRECTION_TYPE_CONSTANT,
'random': GameLib.D3.Particle.DIRECTION_TYPE_RANDOM,
'random normalized': GameLib.D3.Particle.DIRECTION_TYPE_RANDOM_NORMALIZED,
'function': GameLib.D3.Particle.DIRECTION_TYPE_FUNCTION
}
)
);
} else if (property === 'speedType') {
controllers.push(
folder.add(
object,
property,
{
'constant': GameLib.D3.Particle.SPEED_TYPE_CONSTANT,
'linear': GameLib.D3.Particle.SPEED_TYPE_LINEAR,
'exponential': GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL,
'logarithmic': GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC,
'1 / log': GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG,
'exp' : GameLib.D3.Particle.SPEED_TYPE_EXP,
'1 / exp' : GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP
}
)
);
} else if (property === 'scaleType') {
controllers.push(
folder.add(
@ -1159,7 +1176,8 @@ GameLib.System.GUI.prototype.buildControl = function(folder, componentTemplate,
property === 'opacity' ||
property === 'opacityFactor' ||
property === 'metalness' ||
property === 'roughness'
property === 'roughness' ||
property === 'volume'
) {
controllers.push(folder.add(object, property, 0, 1.0, 0.001));
} else if (

View File

@ -130,10 +130,46 @@ GameLib.System.Particle.prototype.beforeRender = function(data) {
particleEngine.particles = particleEngine.particles.reduce(
function(result, particle){
particle.position.x += particle.userData.direction.x * data.delta * particle.userData.speed;
particle.position.y += particle.userData.direction.y * data.delta * particle.userData.speed;
particle.position.z += particle.userData.direction.z * data.delta * particle.userData.speed;
var speed = particle.userData.speed;
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_CONSTANT) {
speed = data.delta * particle.userData.speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_LINEAR) {
speed = data.delta * particle.userData.speed;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_EXPONENTIAL) {
speed = Math.pow(particle.userData.speed, 2) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_LOGARITHMIC) {
speed = Math.log(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_LOG) {
speed = 1 / Math.log(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_EXP) {
speed = Math.exp(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
if (particle.userData.speedType === GameLib.D3.Particle.SPEED_TYPE_ONE_OVER_EXP) {
speed = 1 / Math.exp(particle.userData.speed) * data.delta;
particle.userData.speed += speed;
}
particle.position.x += particle.userData.direction.x * speed;
particle.position.y += particle.userData.direction.y * speed;
particle.position.z += particle.userData.direction.z * speed;
if (particleEngine.templateParticle.scaleType === GameLib.D3.Particle.SCALE_TYPE_CONSTANT) {
/**
@ -187,13 +223,37 @@ GameLib.System.Particle.prototype.beforeRender = function(data) {
if (particleEngine.enabled && !particleEngine.disabledForRemoval) {
if (particleEngine.elapsed > particleEngine.frequency) {
var instanceClone = null;
particleEngine.elapsed = 0;
if (particleEngine.pulse) {
var instanceClone = particleEngine.templateParticle.cloneInstance();
if (particleEngine.particles.length === 0) {
particleEngine.particles.push(instanceClone);
particleEngine.elapsed = 0;
/**
* This is a 'pulse' engine - so spawn all the particles at once and spawn again when all particles
* are gone
*/
for (var i = 0; i < particleEngine.particlesPerSecond; i++) {
instanceClone = particleEngine.templateParticle.cloneInstance();
particleEngine.particles.push(instanceClone);
}
}
} else {
/**
* This is a 'stream' engine - spawn particles one at a time when its time to do so
*/
if (particleEngine.elapsed > particleEngine.frequency) {
particleEngine.elapsed = 0;
instanceClone = particleEngine.templateParticle.cloneInstance();
particleEngine.particles.push(instanceClone);
}
}
}

View File

@ -291,7 +291,8 @@ GameLib.System.Storage.prototype.save = function(data) {
GameLib.Event.Emit(
GameLib.Event.SAVE_COMPONENT_ERROR,
{
message: this.responseText
message: this.responseText,
component : data.apiObject
}
)
}
@ -300,14 +301,16 @@ GameLib.System.Storage.prototype.save = function(data) {
GameLib.Event.Emit(
GameLib.Event.COMPONENT_SAVED,
{
message: response.message || 'Successfully saved the component'
message: response.message || 'Successfully saved the component',
component : data.apiObject
}
)
} else {
GameLib.Event.Emit(
GameLib.Event.SAVE_COMPONENT_ERROR,
{
message: response.message || 'The server responded but failed to save the component'
message: response.message || 'The server responded but failed to save the component',
component : data.apiObject
}
)
}
@ -651,6 +654,7 @@ GameLib.System.Storage.prototype.loadComponent = function(apiUrl, toProcess, inc
apiUrl + '/component/load/' + id
);
xhr.send();
}.bind(this)