/** * Particle emitter effect actor class. * * A simple particle emitter, that does not recycle particles, but sets itself as expired() once * all child particles have expired. * * Requires a function known as the emitter that is called per particle generated. * * @namespace Arena * @class Arena.Particles */ (function() { /** * Constructor * * @param p {Vector} Emitter position * @param v {Vector} Emitter velocity * @param count {Integer} Number of particles * @param fnEmitter {Function} Emitter function to call per particle generated */ Arena.Particles = function(p, v, count, fnEmitter) { Arena.Particles.superclass.constructor.call(this, p, v); // generate particles based on the supplied emitter function this.particles = new Array(count); for (var i=0; i 1 // lookup based on particle colour e.g. points_rgb(x,y,z) ctx.drawImage( GameHandler.prerenderer.images["points_" + this.colour][this.size], 0, 0); break; case 1: // line var s = this.size; ctx.rotate(this.rotate); this.rotate += this.rotationv; // specific line colour - for enemy explosion pieces ctx.strokeStyle = this.colour; ctx.lineWidth = 2.0; ctx.beginPath(); ctx.moveTo(-s, -s); ctx.lineTo(s, s); ctx.closePath(); ctx.stroke(); break; case 2: // smudge (prerendered image) ctx.drawImage(GameHandler.prerenderer.images["smudges"][this.size - 4], 0, 0); break; } } catch (error) { if (console !== undefined) console.log(error.message); } }; } /** * Enemy explosion - Particle effect actor class. * * @namespace Arena * @class Arena.EnemyExplosion */ (function() { /** * Constructor */ Arena.EnemyExplosion = function(p, v, enemy) { Arena.EnemyExplosion.superclass.constructor.call(this, p, v, 16, function() { // randomise start position slightly var pos = p.clone(); pos.x += randomInt(-5, 5); pos.y += randomInt(-5, 5); // randomise radial direction vector - speed and angle, then add parent vector switch (randomInt(0, 2)) { case 0: var t = new Vector(0, randomInt(20, 25)); t.rotate(Rnd() * TWOPI); t.add(v); return new ArenaParticle( pos, t, ~~(Rnd() * 4), 0, 20, 15); case 1: var t = new Vector(0, randomInt(5, 10)); t.rotate(Rnd() * TWOPI); t.add(v); // create line particle - size based on enemy type return new ArenaParticle( pos, t, (enemy.type !== 3 ? Rnd() * 5 + 5 : Rnd() * 10 + 10), 1, 20, 15, enemy.colorRGB); case 2: var t = new Vector(0, randomInt(2, 4)); t.rotate(Rnd() * TWOPI); t.add(v); return new ArenaParticle( pos, t, ~~(Rnd() * 4 + 4), 2, 20, 15); } }); return this; }; extend(Arena.EnemyExplosion, Arena.Particles); })(); /** * Enemy impact effect - Particle effect actor class. * Used when an enemy is hit by player bullet but not destroyed. * * @namespace Arena * @class Arena.EnemyImpact */ (function() { /** * Constructor */ Arena.EnemyImpact = function(p, v, enemy) { Arena.EnemyImpact.superclass.constructor.call(this, p, v, 5, function() { // slightly randomise vector angle - then add parent vector var t = new Vector(0, Rnd() < 0.5 ? randomInt(-5, -10) : randomInt(5, 10)); t.rotate(Rnd() * PIO2 - PIO4); t.add(v); return new ArenaParticle( p.clone(), t, ~~(Rnd() * 4), 0, 15, 10, enemy.colorRGB); }); return this; }; extend(Arena.EnemyImpact, Arena.Particles); })(); /** * Bullet impact effect - Particle effect actor class. * Used when an bullet hits an object and is destroyed. * * @namespace Arena * @class Arena.BulletImpactEffect */ (function() { /** * Constructor */ Arena.BulletImpactEffect = function(p, v, enemy) { Arena.BulletImpactEffect.superclass.constructor.call(this, p, v, 3, function() { return new ArenaParticle( p.clone(), v.nrotate(Rnd()*PIO8), ~~(Rnd() * 4), 0, 15, 10); }); return this; }; extend(Arena.BulletImpactEffect, Arena.Particles); })(); /** * Player explosion - Particle effect actor class. * * @namespace Arena * @class Arena.PlayerExplosion */ (function() { /** * Constructor */ Arena.PlayerExplosion = function(p, v) { Arena.PlayerExplosion.superclass.constructor.call(this, p, v, 20, function() { // randomise start position slightly var pos = p.clone(); pos.x += randomInt(-5, 5); pos.y += randomInt(-5, 5); // randomise radial direction vector - speed and angle, then add parent vector switch (randomInt(1,2)) { case 1: var t = new Vector(0, randomInt(5, 8)); t.rotate(Rnd() * TWOPI); t.add(v); return new ArenaParticle( pos, t, Rnd() * 5 + 5, 1, 25, 15, "white"); case 2: var t = new Vector(0, randomInt(5, 10)); t.rotate(Rnd() * TWOPI); t.add(v); return new ArenaParticle( pos, t, ~~(Rnd() * 4 + 4), 2, 25, 15); } }); return this; }; extend(Arena.PlayerExplosion, Arena.Particles); })(); /** * Text indicator effect actor class. * * @namespace Arena * @class Arena.TextIndicator */ (function() { Arena.TextIndicator = function(p, v, msg, textSize, colour, fadeLength) { this.fadeLength = (fadeLength ? fadeLength : this.DEFAULT_FADE_LENGTH); Arena.TextIndicator.superclass.constructor.call(this, p, v, this.fadeLength); this.msg = msg; if (textSize) { this.textSize = textSize; } if (colour) { this.colour = colour; } return this; }; extend(Arena.TextIndicator, Game.EffectActor, { DEFAULT_FADE_LENGTH: 16, fadeLength: 0, textSize: 22, msg: null, colour: "rgb(255,255,255)", /** * Text indicator effect rendering method * * @param ctx {object} Canvas rendering context */ onRender: function onRender(ctx, world) { ctx.save(); if (this.worldToScreen(ctx, world, 128)) { var alpha = (1.0 / this.fadeLength) * this.lifespan; ctx.globalAlpha = alpha; ctx.shadowBlur = 0; Game.fillText(ctx, this.msg, this.textSize + "pt Courier New", 0, 0, this.colour); } ctx.restore(); } }); })(); /** * Score indicator effect actor class. * * @namespace Arena * @class Arena.ScoreIndicator */ (function() { Arena.ScoreIndicator = function(p, v, score, textSize, prefix, colour, fadeLength) { var msg = score.toString(); if (prefix) { msg = prefix + ' ' + msg; } Arena.ScoreIndicator.superclass.constructor.call(this, p, v, msg, textSize, colour, fadeLength); return this; }; extend(Arena.ScoreIndicator, Arena.TextIndicator, { }); })();