CanvasMark/scripts/asteroids_effects.js
2013-07-23 23:57:10 +01:00

420 lines
12 KiB
JavaScript

/**
* Basic explosion effect actor class.
*
* @namespace Asteroids
* @class Asteroids.Explosion
*/
(function()
{
Asteroids.Explosion = function(p, v, s)
{
Asteroids.Explosion.superclass.constructor.call(this, p, v, this.FADE_LENGTH);
this.size = s;
return this;
};
extend(Asteroids.Explosion, Game.EffectActor,
{
FADE_LENGTH: 10,
/**
* Explosion size
*/
size: 0,
/**
* Explosion rendering method
*
* @param ctx {object} Canvas rendering context
*/
onRender: function onRender(ctx)
{
// fade out
var brightness = Math.floor((255 / this.FADE_LENGTH) * this.lifespan);
var rad = (this.size * 8 / this.FADE_LENGTH) * this.lifespan;
var rgb = brightness.toString();
ctx.save();
ctx.globalAlpha = 0.75;
ctx.fillStyle = "rgb(" + rgb + ",0,0)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, rad, 0, TWOPI, true);
ctx.closePath();
ctx.fill();
ctx.restore();
}
});
})();
/**
* Player Explosion effect actor class.
*
* @namespace Asteroids
* @class Asteroids.PlayerExplosion
*/
(function()
{
Asteroids.PlayerExplosion = function(p, v)
{
Asteroids.PlayerExplosion.superclass.constructor.call(this, p, v, this.FADE_LENGTH);
return this;
};
extend(Asteroids.PlayerExplosion, Game.EffectActor,
{
FADE_LENGTH: 15,
/**
* Explosion rendering method
*
* @param ctx {object} Canvas rendering context
*/
onRender: function onRender(ctx)
{
ctx.save();
var alpha = (1.0 / this.FADE_LENGTH) * this.lifespan;
ctx.globalCompositeOperation = "lighter";
ctx.globalAlpha = alpha;
var rad;
if (this.lifespan > 5 && this.lifespan <= 15)
{
var offset = this.lifespan - 5;
rad = (48 / this.FADE_LENGTH) * offset;
ctx.fillStyle = "rgb(255,170,30)";
ctx.beginPath();
ctx.arc(this.position.x-2, this.position.y-2, rad, 0, TWOPI, true);
ctx.closePath();
ctx.fill();
}
if (this.lifespan > 2 && this.lifespan <= 12)
{
var offset = this.lifespan - 2;
rad = (32 / this.FADE_LENGTH) * offset;
ctx.fillStyle = "rgb(255,255,50)";
ctx.beginPath();
ctx.arc(this.position.x+2, this.position.y+2, rad, 0, TWOPI, true);
ctx.closePath();
ctx.fill();
}
if (this.lifespan <= 10)
{
var offset = this.lifespan;
rad = (24 / this.FADE_LENGTH) * offset;
ctx.fillStyle = "rgb(255,70,100)";
ctx.beginPath();
ctx.arc(this.position.x+2, this.position.y-2, rad, 0, TWOPI, true);
ctx.closePath();
ctx.fill();
}
ctx.restore();
}
});
})();
/**
* Impact effect (from bullet hitting an object) actor class.
*
* @namespace Asteroids
* @class Asteroids.Impact
*/
(function()
{
Asteroids.Impact = function(p, v)
{
Asteroids.Impact.superclass.constructor.call(this, p, v, this.FADE_LENGTH);
return this;
};
extend(Asteroids.Impact, Game.EffectActor,
{
FADE_LENGTH: 12,
/**
* Impact effect rendering method
*
* @param ctx {object} Canvas rendering context
*/
onRender: function onRender(ctx)
{
// fade out alpha
var alpha = (1.0 / this.FADE_LENGTH) * this.lifespan;
ctx.save();
ctx.globalAlpha = alpha * 0.75;
if (BITMAPS)
{
ctx.fillStyle = "rgb(50,255,50)";
}
else
{
ctx.shadowColor = ctx.strokeStyle = "rgb(50,255,50)";
}
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, 2, 0, TWOPI, true);
ctx.closePath();
if (BITMAPS) ctx.fill(); else ctx.stroke();
ctx.globalAlpha = alpha;
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, 1, 0, TWOPI, true);
ctx.closePath();
if (BITMAPS) ctx.fill(); else ctx.stroke();
ctx.restore();
}
});
})();
/**
* Text indicator effect actor class.
*
* @namespace Asteroids
* @class Asteroids.TextIndicator
*/
(function()
{
Asteroids.TextIndicator = function(p, v, msg, textSize, colour, fadeLength)
{
this.fadeLength = (fadeLength ? fadeLength : this.DEFAULT_FADE_LENGTH);
Asteroids.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(Asteroids.TextIndicator, Game.EffectActor,
{
DEFAULT_FADE_LENGTH: 16,
fadeLength: 0,
textSize: 12,
msg: null,
colour: "rgb(255,255,255)",
/**
* Text indicator effect rendering method
*
* @param ctx {object} Canvas rendering context
*/
onRender: function onRender(ctx)
{
// fade out alpha
var alpha = (1.0 / this.fadeLength) * this.lifespan;
ctx.save();
ctx.globalAlpha = alpha;
Game.fillText(ctx, this.msg, this.textSize + "pt Courier New", this.position.x, this.position.y, this.colour);
ctx.restore();
}
});
})();
/**
* Score indicator effect actor class.
*
* @namespace Asteroids
* @class Asteroids.ScoreIndicator
*/
(function()
{
Asteroids.ScoreIndicator = function(p, v, score, textSize, prefix, colour, fadeLength)
{
var msg = score.toString();
if (prefix)
{
msg = prefix + ' ' + msg;
}
Asteroids.ScoreIndicator.superclass.constructor.call(this, p, v, msg, textSize, colour, fadeLength);
return this;
};
extend(Asteroids.ScoreIndicator, Asteroids.TextIndicator,
{
});
})();
/**
* Power up collectable.
*
* @namespace Asteroids
* @class Asteroids.PowerUp
*/
(function()
{
Asteroids.PowerUp = function(p, v)
{
Asteroids.PowerUp.superclass.constructor.call(this, p, v);
return this;
};
extend(Asteroids.PowerUp, Game.EffectActor,
{
RADIUS: 8,
pulse: 128,
pulseinc: 8,
/**
* Power up rendering method
*
* @param ctx {object} Canvas rendering context
*/
onRender: function onRender(ctx)
{
ctx.save();
ctx.globalAlpha = 0.75;
var col = "rgb(255," + this.pulse.toString() + ",0)";
if (BITMAPS)
{
ctx.fillStyle = col;
ctx.strokeStyle = "rgb(255,255,128)";
}
else
{
ctx.lineWidth = 2.0;
ctx.shadowColor = ctx.strokeStyle = col;
}
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.RADIUS, 0, TWOPI, true);
ctx.closePath();
if (BITMAPS)
{
ctx.fill();
}
ctx.stroke();
ctx.restore();
this.pulse += this.pulseinc;
if (this.pulse > 255)
{
this.pulse = 256 - this.pulseinc;
this.pulseinc =- this.pulseinc;
}
else if (this.pulse < 0)
{
this.pulse = 0 - this.pulseinc;
this.pulseinc =- this.pulseinc;
}
},
radius: function radius()
{
return this.RADIUS;
},
collected: function collected(game, player, scene)
{
// randomly select a powerup to apply
var message = null;
switch (randomInt(0, 9))
{
case 0:
case 1:
// boost energy
message = "Energy Boost!";
player.energy += player.ENERGY_INIT/2;
if (player.energy > player.ENERGY_INIT)
{
player.energy = player.ENERGY_INIT;
}
break;
case 2:
// fire when shieled
message = "Fire When Shielded!";
player.fireWhenShield = true;
break;
case 3:
// extra life
message = "Extra Life!";
game.lives++;
break;
case 4:
// slow down asteroids
message = "Slow Down Asteroids!";
for (var n = 0, m = scene.enemies.length, enemy; n < m; n++)
{
enemy = scene.enemies[n];
if (enemy instanceof Asteroids.Asteroid)
{
enemy.vector.scale(0.75);
}
}
break;
case 5:
// smart bomb
message = "Smart Bomb!";
var effectRad = 96;
// add a BIG explosion actor at the smart bomb weapon position and vector
var boom = new Asteroids.Explosion(
this.position.clone(), this.vector.clone().scale(0.5), effectRad / 8);
scene.effects.push(boom);
// test circle intersection with each enemy actor
// we check the enemy list length each iteration to catch baby asteroids
// this is a fully fledged smart bomb after all!
for (var n = 0, enemy, pos = this.position; n < scene.enemies.length; n++)
{
enemy = scene.enemies[n];
// test the distance against the two radius combined
if (pos.distance(enemy.position) <= effectRad + enemy.radius())
{
// intersection detected!
enemy.hit(-1);
scene.generatePowerUp(enemy);
scene.destroyEnemy(enemy, this.vector, true);
}
}
break;
case 6:
// twin cannon primary weapon upgrade
message = "Twin Cannons!";
player.primaryWeapons["main"] = new Asteroids.TwinCannonsWeapon(player);
break;
case 7:
// v spray cannons
message = "Spray Cannons!";
player.primaryWeapons["main"] = new Asteroids.VSprayCannonsWeapon(player);
break;
case 8:
// rear guns
message = "Rear Gun!";
player.primaryWeapons["rear"] = new Asteroids.RearGunWeapon(player);
break;
case 9:
// side guns
message = "Side Guns!";
player.primaryWeapons["side"] = new Asteroids.SideGunWeapon(player);
break;
}
if (message)
{
// generate a effect indicator at the destroyed enemy position
var vec = new Vector(0, -3.0);
var effect = new Asteroids.TextIndicator(
new Vector(this.position.x, this.position.y - this.RADIUS), vec, message, null, null, 32);
scene.effects.push(effect);
}
}
});
})();