Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added sound library

Added basic shooting enemies, need to refactor projectiles and weapon logic
  • Loading branch information...
commit 0ca0fdebf914e7b7210f636fc76f664097a2b205 1 parent d5db4e2
@tommoor tommoor authored
View
318 deps/zap.js
@@ -0,0 +1,318 @@
+/**
+ * Zap! - HTML5 Sound Manager
+ * Copyright (c) 2011 Tom Moor
+ * MIT Licensed
+ */
+
+var Zap = (function() {
+
+ var exports = {},
+ sounds = {},
+ groups = {},
+ events = {},
+ loaded = 0,
+ timeout = 6*1000,
+ self = this,
+ options = {
+ container: 'sounds',
+ console: true
+ };
+
+
+ // supported audio formats
+ exports.formats = {};
+
+
+ /**
+ * Initalise zap object, optionally include configs
+ *
+ * @param {Object} config object
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.init = function(opt){
+
+ options = $.extend(options, opt);
+
+ // create element to hold audio objects
+ var container = document.createElement('div');
+ container.setAttribute('id', options.container);
+ document.body.appendChild(container);
+
+ return this;
+ }
+
+
+ /**
+ * Event emitter hook
+ *
+
+ * @param {String} event
+ * @param {Function} callback to trigger on event
+ * @return {Zap} return itself to allow chaining
+ */
+ exports.on = function(event, callback){
+
+ if(! events[event]) events[event] = [];
+ events[event].push(callback);
+ return this;
+ }
+
+
+ var trigger = function(event){
+ var callbacks = events[event];
+
+ for(var c in callbacks){
+ callbacks[c].apply( this, Array.prototype.slice.call( arguments, 1 ) );
+ }
+ }
+
+
+
+ /**
+ * Allows sounds to be grouped under one reference, so that a random sound can be played
+ *
+ * @param {String} ref
+ * @param {Array} an array of sound references
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.addGroup = function(ref, sounds){
+
+ groups[ref] = sounds;
+ return this;
+ }
+
+
+ /**
+ * Add a sound to be played later
+ *
+ * @param {String} ref
+ * @param {Array} sources
+ * @param {Integer} maximum channels
+ * @param {Integer} maximum ms loading before considered to have timed out
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.addSound = function(ref, sources, channels, time){
+
+ var channels = channels || 1;
+ var element = ref;
+
+ // create reference to sound channels
+ sounds[ref] = {
+ asset: '#' + ref,
+ loaded: false,
+ failed: false,
+ duration: 0,
+ channels: channels,
+ channel: 0
+ }
+
+ // if a sound fails to load for any reason it shouldnt stop complete callback
+ var loadTimeout = setTimeout(function(){
+
+ log('Zap: sound failed to load: ' + ref);
+ sounds[ref].failed = true;
+ soundLoaded();
+ trigger('error', ref);
+
+ }, time || timeout);
+
+ // create new wrapper to categorise channels
+ $('<div/>', {
+ 'id': ref
+ }).appendTo('#' + options.container);
+
+ var c;
+ // create an audio element for each channel
+ while(channels--){
+
+ c = 'sound-' + element + '-' + channels;
+
+ // create new channel
+ $('<audio/>', {
+ 'id': c,
+ 'preload': 'auto',
+ 'autobuffer': true
+ }).appendTo('#' + ref);
+
+ // bind event handlers
+ $('#' + c).bind('canplaythrough', function(){
+ clearTimeout(loadTimeout);
+ sounds[ref].loaded = true;
+ sounds[ref].duration = $(this).get(0).duration*1000;
+ soundLoaded();
+ });
+
+ // add sound sources
+ for(var s in sources){
+ $('<source/>', {
+ 'src': sources[s]
+ }).appendTo('#' + c);
+ }
+ }
+
+ log('Zap: sound added ' + ref);
+
+ return this;
+ }
+
+
+ /**
+ * Play a sound by reference
+ *
+ * @param {String} ref
+ * @param {Float} vol
+ * @param {Integer} loops
+ * @param {Function} callback
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.play = function(ref, vol, loops, c){
+
+ // a group with this reference exists
+ if(groups[ref]){
+
+ // pick a random sample from this group
+ var l = groups[ref].length-1;
+ var r = Math.round(Math.random()*l);
+ ref = groups[ref][r];
+
+ } else if(! sounds[ref].loaded){
+ log('Zap: sound with reference "' + ref + '" is not loaded');
+ return false;
+ }
+
+
+ var callback = c || function(){};
+ var volume = vol || 1;
+ var sound = sounds[ref];
+ var element = $('#sounds #' + ref + ' audio').get(sound.channel);
+
+ log('Zap: playing "' + ref + '" on channel ' + (sound.channel+1));
+
+ // circulate through the available channels
+ if(sound.channel++ >= sound.channels-1){
+ sound.channel = 0;
+ }
+
+ // play one shot
+ element.currentTime = 0;
+ element.volume = volume;
+ element.play();
+
+ if(loops){
+ // loop, if requested
+ var count = 0;
+ var loopInterval = setInterval(function(){
+
+ if(++count < loops){
+ Zap.play(ref, vol);
+ return true;
+ }
+ clearInterval(loopInterval);
+ callback();
+ }, sound.duration);
+
+ } else {
+ // callback, if provided
+ setTimeout(callback, sound.duration);
+ }
+
+ return this;
+ }
+
+
+ /**
+ * Stop a sound by reference
+ *
+ * @param {String} ref
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.stop = function(ref){
+
+ // find all channels this sound could
+ // be playing on and stop each one individually.
+ var element = $('#sounds #' + ref + ' audio').each(function(){
+
+ $(this).get(0).pause();
+ });
+
+ return this;
+ }
+
+
+ /**
+ * Stop every sound that has been loaded
+ *
+ * @return {Zap} return itself to allow chaining
+ */
+
+ exports.stopAllSounds = function(){
+
+ $('#sounds audio').each(function(){
+
+ $(this).get(0).pause();
+ });
+
+ return this;
+ }
+
+
+ /**
+ * Utility method to find out format and codec support
+ *
+ * @return {Object} An object of possible codecs in the form 'format: boolean'
+ */
+
+ exports.supported = function(){
+
+ this.formats = {};
+ var a = document.createElement('audio');
+
+ // MP3
+ this.formats.mp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
+
+ // Vorbis
+ this.formats.vorbis = !!(a.canPlayType && a.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, ''));
+
+ // WAV
+ this.formats.wav = !!(a.canPlayType && a.canPlayType('audio/wav; codecs="1"').replace(/no/, ''));
+
+ // AAC
+ this.formats.aac = !!(a.canPlayType && a.canPlayType('audio/mp4; codecs="mp4a.40.2"').replace(/no/, ''));
+
+ return this.formats;
+ }
+
+
+ var getChannelCount = function(){
+
+ var c = 0;
+ for (var i in sounds) {
+ c += sounds[i].channels;
+ }
+ return c;
+ }
+
+ var getPercentageLoaded = function(){
+ return (loaded / getChannelCount())*100;
+ }
+
+ var soundLoaded = function(){
+ loaded++;
+ trigger('update', getPercentageLoaded() );
+
+ if(loaded == getChannelCount()) trigger('complete');
+ }
+
+ var log = function(){
+ if(window.console && options.console){
+ window.console.log( Array.prototype.slice.call(arguments) );
+ }
+ }
+
+ return exports;
+})();
View
3  index.html
@@ -20,6 +20,7 @@
<script src="deps/easel/BoxBlurFilter.js"></script>
<script src="deps/stats.js"></script>
<script src="deps/events.js"></script>
+ <script src="deps/zap.js"></script>
<script src="lib/helpers.js"></script>
<script src="lib/game.js"></script>
@@ -33,7 +34,9 @@
<script src="lib/ParticleManager.js"></script>
<script src="lib/LevelManager.js"></script>
<script src="lib/Projectile.js"></script>
+ <script src="lib/ProjectileCannon.js"></script>
<script src="lib/WeaponBasic.js"></script>
+ <script src="lib/WeaponCannon.js"></script>
<script>
$(function(){
View
8 lib/Enemy.js
@@ -8,6 +8,7 @@ condor.Enemy = condor.Body.extend({
POINTS: 100,
life: 2,
+ weapon: 0,
waypoints: [],
current: 0,
nextx: 0,
@@ -16,8 +17,14 @@ condor.Enemy = condor.Body.extend({
initialize: function () {
Container.prototype.initialize.call(this);
+ this.weapon = new condor.WeaponCannon();
this.display();
},
+
+ fire: function () {
+ var p = this.weapon.fire(this);
+ condor.interface.addChildTo(p, 'enemy_projectiles');
+ },
display: function () {
@@ -39,6 +46,7 @@ condor.Enemy = condor.Body.extend({
this.checkWaypoint();
this.move();
+ this.fire();
this.update();
},
View
4 lib/Player.js
@@ -36,6 +36,10 @@ condor.Player = condor.Body.extend({
this.addChild(this.body);
},
+ hit: function () {
+
+ console.log('Mayday!');
+ },
bindEvents: function () {
_.bindAll(this, 'moveLeft', 'moveRight', 'moveUp', 'moveDown', 'fire');
View
16 lib/ProjectileCannon.js
@@ -0,0 +1,16 @@
+condor.ProjectileCannon = condor.Projectile.extend({
+
+ WIDTH: 6,
+ HEIGHT: 6,
+ FRICTION: 1, // projectiles never slow down
+
+ display: function () {
+
+ this.body = new Shape();
+ var g = this.body.graphics;
+ g.clear();
+ g.beginFill("rgb(0, 128, 128)");
+ g.drawCircle(0,0,this.WIDTH);
+ this.addChild(this.body);
+ }
+});
View
20 lib/WeaponCannon.js
@@ -0,0 +1,20 @@
+condor.WeaponCannon = function(){return {
+
+ SPEED: 10,
+ RELOAD: 10, // in frames
+
+ reloading: 0,
+
+ fire: function (obj) {
+
+ if (--this.reloading > 0) return false;
+
+ var a = new condor.ProjectileCannon();
+ condor.ParticleManager.add(a);
+ a.position(obj.x, obj.y);
+ a.accelerate(0, this.SPEED);
+ this.reloading = this.RELOAD;
+
+ return a;
+ }
+}};
View
13 lib/game.js
@@ -8,6 +8,7 @@ condor.game = {
init: function () {
+ Zap.init();
condor.LevelManager.init();
this.stage = condor.interface.init();
this.controls = condor.controls.init();
@@ -52,6 +53,7 @@ condor.game = {
collisions: function () {
+ // collide enemies with players projectiles
for (var i in condor.interface.layers.enemies.children) {
var enemy = condor.interface.layers.enemies.children[i];
@@ -64,5 +66,16 @@ condor.game = {
}
}
}
+
+ // collide player with enemies projectiles
+ for (var j in condor.interface.layers.enemy_projectiles.children) {
+ var projectile = condor.interface.layers.enemy_projectiles.children[j];
+
+ if (this.player.boundsIntersect(projectile)) {
+ this.player.hit();
+ break;
+ }
+ }
+
}
};
View
2  lib/interface.js
@@ -89,6 +89,8 @@ condor.interface = {
addChildTo: function (children, layer) {
+ if (!children) return;
+
if (_.isArray(children)) {
for (var i in children) {
this.layers[layer].addChild(children[i]);
Please sign in to comment.
Something went wrong with that request. Please try again.