时间:2021-07-01 10:21:17 帮助过:65人阅读
在线演示源码下载
所有JavaScript代码
/** * this file was compiled by jsbuild 0.9.6 * @date Fri, 20 Jul 2012 16:21:18 UTC * @author dron * @site http://ucren.com */ void function(global){ var mapping = {}, cache = {}; global.startModule = function(m){ require(m).start(); }; global.define = function(id, func){ mapping[id] = func; }; global.require = function(id){ if(!/\.js$/.test(id)) id += '.js'; if(cache[id]) return cache[id]; else return cache[id] = mapping[id]({}); }; }(this); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\collide.js */ define("scripts/collide.js", function(exports){ var fruit = require("scripts/factory/fruit"); var Ucren = require("scripts/lib/ucren"); var fruits = fruit.getFruitInView(); /** * 碰撞检测 */ exports.check = function( knife ){ var ret = [], index = 0; fruits.forEach(function( fruit ){ var ck = lineInEllipse( knife.slice( 0, 2 ), knife.slice( 2, 4 ), [ fruit.originX, fruit.originY ], fruit.radius ); if( ck ) ret[ index ++ ] = fruit; }); return ret; }; function sqr(x){ return x * x; } function sign(n){ return n < 0 ? -1 : ( n > 0 ? 1 : 0 ); } function equation12( a, b, c ){ if(a == 0)return; var delta = b * b - 4 * a * c; if(delta == 0) return [ -1 * b / (2 * a), -1 * b / (2 * a) ]; else if(delta > 0) return [ (-1 * b + Math.sqrt(delta)) / (2 * a), (-1 * b - Math.sqrt(delta)) / (2 * a) ]; } // 返回线段和椭圆的两个交点,如果不相交,返回 null function lineXEllipse( p1, p2, c, r, e ){ // 线段:p1, p2 圆心:c 半径:r 离心率:e if (r <= 0) return; e = e === undefined ? 1 : e; var t1 = r, t2 = r * e, k; a = sqr( t2) * sqr(p1[0] - p2[0]) + sqr(t1) * sqr(p1[1] - p2[1]); if (a <= 0) return; b = 2 * sqr(t2) * (p2[0] - p1[0]) * (p1[0] - c[0]) + 2 * sqr(t1) * (p2[1] - p1[1]) * (p1[1] - c[1]); c = sqr(t2) * sqr(p1[0] - c[0]) + sqr(t1) * sqr(p1[1] - c[1]) - sqr(t1) * sqr(t2); if (!( k = equation12(a, b, c, t1, t2) )) return; var result = [ [ p1[0] + k[0] * (p2[0] - p1[0]), p1[1] + k[0] * (p2[1] - p1[1]) ], [ p1[0] + k[1] * (p2[0] - p1[0]), p1[1] + k[1] * (p2[1] - p1[1]) ] ]; if ( !( ( sign( result[0][0] - p1[0] ) * sign( result[0][0] - p2[0] ) <= 0 ) && ( sign( result[0][1] - p1[1] ) * sign( result[0][1] - p2[1] ) <= 0 ) ) ) result[0] = null; if ( !( ( sign( result[1][0] - p1[0] ) * sign( result[1][0] - p2[0] ) <= 0 ) && ( sign( result[1][1] - p1[1] ) * sign( result[1][1] - p2[1] ) <= 0 ) ) ) result[1] = null; return result; } // 判断计算线段和椭圆是否相交 function lineInEllipse( p1, p2, c, r, e ){ var t = lineXEllipse( p1, p2, c, r, e ); return t && ( t[0] || t[1] ); }; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\control.js */ define("scripts/control.js", function(exports){ var Ucren = require("scripts/lib/ucren"); var knife = require("scripts/object/knife"); var message = require("scripts/message"); var state = require("scripts/state"); var canvasLeft, canvasTop; canvasLeft = canvasTop = 0; exports.init = function(){ this.fixCanvasPos(); this.installDragger(); this.installClicker(); }; exports.installDragger = function(){ var dragger = new Ucren.BasicDrag({ type: "calc" }); dragger.on( "returnValue", function( dx, dy, x, y, kf ){ if( kf = knife.through( x - canvasLeft, y - canvasTop ) ) message.postMessage( kf, "slice" ); }); dragger.on( "startDrag", function(){ knife.newKnife(); }); dragger.bind( document.documentElement ); }; exports.installClicker = function(){ Ucren.addEvent( document, "click", function(){ if( state( "click-enable" ).ison() ) message.postMessage( "click" ); }); }; exports.fixCanvasPos = function(){ var de = document.documentElement; var fix = function( e ){ canvasLeft = ( de.clientWidth - 640 ) / 2; canvasTop = ( de.clientHeight - 480 ) / 2 - 40; }; fix(); Ucren.addEvent( window, "resize", fix ); };; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\game.js */ define("scripts/game.js", function(exports){ /** * game logic */ var timeline = require("scripts/timeline"); var Ucren = require("scripts/lib/ucren"); var sound = require("scripts/lib/sound"); var fruit = require("scripts/factory/fruit"); var score = require("scripts/object/score"); var message = require("scripts/message"); var state = require("scripts/state"); var lose = require("scripts/object/lose"); var gameOver = require("scripts/object/game-over"); var knife = require("scripts/object/knife"); // var sence = require("scripts/sence"); var background = require("scripts/object/background"); var light = require("scripts/object/light"); var scoreNumber = 0; var random = Ucren.randomNumber; var volleyNum = 2, volleyMultipleNumber = 5; var fruits = []; var gameInterval; var snd; var boomSnd; // fruit barbette var barbette = function(){ if( fruits.length >= volleyNum ) return ; var startX = random( 640 ), endX = random( 640 ), startY = 600; var f = fruit.create( startX, startY ).shotOut( 0, endX ); fruits.push( f ); snd.play(); barbette(); }; // start game exports.start = function(){ snd = sound.create( "sound/throw" ); boomSnd = sound.create( "sound/boom" ); timeline.setTimeout(function(){ state( "game-state" ).set( "playing" ); gameInterval = timeline.setInterval( barbette, 1e3 ); }, 500); }; exports.gameOver = function(){ state( "game-state" ).set( "over" ); gameInterval.stop(); gameOver.show(); // timeline.setTimeout(function(){ // // sence.switchSence( "home-menu" ); // // TODO: require 出现互相引用时,造成死循环,这个问题需要跟进,这里暂时用 postMessage 代替 // message.postMessage( "home-menu", "sence.switchSence" ); // }, 2000); scoreNumber = 0; volleyNum = 2; fruits.length = 0; }; exports.applyScore = function( score ){ if( score > volleyNum * volleyMultipleNumber ) volleyNum ++, volleyMultipleNumber += 50; }; exports.sliceAt = function( fruit, angle ){ var index; if( state( "game-state" ).isnot( "playing" ) ) return; if( fruit.type != "boom" ){ fruit.broken( angle ); if( index = fruits.indexOf( fruit ) ) fruits.splice( index, 1 ); score.number( ++ scoreNumber ); this.applyScore( scoreNumber ); }else{ boomSnd.play(); this.pauseAllFruit(); background.wobble(); light.start( fruit ); } }; exports.pauseAllFruit = function(){ gameInterval.stop(); knife.pause(); fruits.invoke( "pause" ); }; // message.addEventListener("fruit.fallOff", function( fruit ){ // var index; // if( ( index = fruits.indexOf( fruit ) ) > -1 ) // fruits.splice( index, 1 ); // }); message.addEventListener("fruit.remove", function( fruit ){ var index; if( ( index = fruits.indexOf( fruit ) ) > -1 ) fruits.splice( index, 1 ); }); var eventFruitFallOutOfViewer = function( fruit ){ if( fruit.type != "boom" ) lose.showLoseAt( fruit.originX ); }; state( "game-state" ).hook( function( value ){ if( value == "playing" ) message.addEventListener( "fruit.fallOutOfViewer", eventFruitFallOutOfViewer ); else message.removeEventListener( "fruit.fallOutOfViewer", eventFruitFallOutOfViewer ); } ); message.addEventListener("game.over", function(){ exports.gameOver(); knife.switchOn(); }); message.addEventListener("overWhiteLight.show", function(){ knife.endAll(); for(var i = fruits.length - 1; i >= 0; i --) fruits[i].remove(); background.stop(); }); message.addEventListener("click", function(){ state( "click-enable" ).off(); gameOver.hide(); message.postMessage( "home-menu", "sence.switchSence" ); });; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\layer.js */ define("scripts/layer.js", function(exports){ /** * layer manager */ var Raphael = require("scripts/lib/raphael"); var Ucren = require("scripts/lib/ucren"); var layers = {}; var zindexs = { "default": zi(), "light": zi(), "knife": zi(), "fruit": zi(), "juice": zi(), "flash": zi(), "mask": zi() }; exports.createImage = function( layer, src, x, y, w, h ){ layer = this.getLayer( layer ); return layer.image( src, x, y, w, h ); }; exports.createText = function( layer, text, x, y, fill, size ){ layer = this.getLayer( layer ); if( Ucren.isIe ) y += 2; return layer.text(x, y, text).attr({ fill: fill || "#fff", "font-size": size || "14px", "font-family": "黑体", "text-anchor": "start" }); }; exports.getLayer = function( name ){ var p, layer; name = name || "default"; if( p = layers[name] ){ return p; }else{ layer = Ucren.makeElement( "p", { "class": "layer", "style": "z-index: " + ( zindexs[name] || 0 ) + ";" } ); Ucren.Element( "extra" ).add( layer ); p = layers[name] = Raphael( layer, 640, 480 ); // if( Ucren.isSafari ) // p.safari(); return p; } }; function zi(){ return zi.num = ++ zi.num || 2; }; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\main.js */ define("scripts/main.js", function(exports){ var timeline = require("scripts/timeline"); var tools = require("scripts/tools"); var sence = require("scripts/sence"); var Ucren = require("scripts/lib/ucren"); var buzz = require("scripts/lib/buzz"); var control = require("scripts/control"); var csl = require("scripts/object/console"); var message = require("scripts/message"); var state = require("scripts/state"); var game = require("scripts/game"); var collide = require("scripts/collide"); var setTimeout = timeline.setTimeout.bind( timeline ); var log = function(){ var time = 1e3, add = 300, fn; fn = function( text ){ setTimeout( function(){ csl.log( text ); }, time ); time += add; }; fn.clear = function(){ setTimeout( csl.clear.bind( csl ), time ); time += add; }; return fn; }(); exports.start = function(){ [ timeline, sence, control ].invoke( "init" ); log( "正在加载鼠标控制脚本" ); log( "正在加载图像资源" ); log( "正在加载游戏脚本" ); log( "正在加载剧情" ); log( "正在初始化" ); log( "正在启动游戏..." ); log.clear(); setTimeout( sence.switchSence.saturate( sence, "home-menu" ), 3000 ); }; message.addEventListener("slice", function( knife ){ var fruits = collide.check( knife ), angle; if( fruits.length ) angle = tools.getAngleByRadian( tools.pointToRadian( knife.slice(0, 2), knife.slice(2, 4) ) ), fruits.forEach(function( fruit ){ message.postMessage( fruit, angle, "slice.at" ); }); }); message.addEventListener("slice.at", function( fruit, angle ){ if( state( "sence-state" ).isnot( "ready" ) ) return ; if( state( "sence-name" ).is( "game-body" ) ){ game.sliceAt( fruit, angle ); return ; } if( state( "sence-name" ).is( "home-menu" ) ){ fruit.broken( angle ); if( fruit.isHomeMenu ) switch( 1 ){ case fruit.isDojoIcon: sence.switchSence( "dojo-body" ); break; case fruit.isNewGameIcon: sence.switchSence( "game-body" ); break; case fruit.isQuitIcon: sence.switchSence( "quit-body" ); break; } return ; } }); var tip = ""; if( !Ucren.isChrome ) tip = "$为了获得最佳流畅度,推荐您使用 <span class='b'>Google Chrome</span> 体验本游戏"; if( !buzz.isSupported() ) tip = tip.replace( "$", "您的浏览器不支持 <audio> 播放声效,且" ); tip = tip.replace( "$", "" ); Ucren.Element( "browser" ).html( tip );; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\message.js */ define("scripts/message.js", function(exports){ /** * a simple message manager * @author dron * @date 2012-06-27 */ var Ucren = require("scripts/lib/ucren"); /** * send a message * @param {Any} message,message... message contents * @param {String} to message address */ exports.postMessage = function( message/*, message, message... */, to ){ var messages = [].slice.call( arguments, 0 ), splitIndex = messages.length - 1; to = messages[ splitIndex ]; messages.slice( 0, splitIndex ); Ucren.dispatch( to, messages ); }; /** * bind an message handler * @param {String} from message address * @param {Function} fn message handler */ exports.addEventListener = function( from, fn ){ Ucren.dispatch( from, fn ); }; /** * remove an message handler * @param {String} from message address * @param {Function} fn message handler */ exports.removeEventListener = function( from, fn ){ Ucren.dispatch.remove( from, fn ); };; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\sence.js */ define("scripts/sence.js", function(exports){ var Ucren = require("scripts/lib/ucren"); var sound = require("scripts/lib/sound"); var fruit = require("scripts/factory/fruit"); var flash = require("scripts/object/flash"); var state = require("scripts/state"); var message = require("scripts/message"); // the fixed elements var background = require("scripts/object/background"); var fps = require("scripts/object/fps"); // the home page elements var homeMask = require("scripts/object/home-mask"); var logo = require("scripts/object/logo"); var ninja = require("scripts/object/ninja") var homeDesc = require("scripts/object/home-desc"); var dojo = require("scripts/object/dojo"); var newGame = require("scripts/object/new-game"); var quit = require("scripts/object/quit"); var newSign = require("scripts/object/new"); var peach, sandia, boom; // the elements in game body var score = require("scripts/object/score"); var lose = require("scripts/object/lose"); // the game logic var game = require("scripts/game"); // the elements in 'developing' module var developing = require("scripts/object/developing"); var gameOver = require("scripts/object/game-over"); // commons var message = require("scripts/message"); var timeline = require("scripts/timeline"); var setTimeout = timeline.setTimeout.bind( timeline ); var setInterval = timeline.setInterval.bind( timeline ); var menuSnd; var gameStartSnd; // initialize sence exports.init = function(){ menuSnd = sound.create( "sound/menu" ); gameStartSnd = sound.create( "sound/start" ); [ background, homeMask, logo, ninja, homeDesc, dojo, newSign, newGame, quit, score, lose, developing, gameOver, flash /*, fps */ ].invoke( "set" ); // setInterval( fps.update.bind( fps ), 500 ); }; // switch sence exports.switchSence = function( name ){ var curSence = state( "sence-name" ); var senceState = state( "sence-state" ); if( curSence.is( name ) ) return ; var onHide = function(){ curSence.set( name ); senceState.set( "entering" ); switch( name ){ case "home-menu": this.showMenu( onShow ); break; case "dojo-body": this.showDojo( onShow ); break; case "game-body": this.showNewGame( onShow ); break; case "quit-body": this.showQuit( onShow ); break; } }.bind( this ); var onShow = function(){ senceState.set( "ready" ); if( name == "dojo-body" || name == "quit-body" ){ exports.switchSence( "home-menu" ); } }; senceState.set( "exiting" ); if( curSence.isunset() ) onHide(); else if( curSence.is( "home-menu" ) ) this.hideMenu( onHide ); else if( curSence.is( "dojo-body" ) ) this.hideDojo( onHide ); else if( curSence.is( "game-body" ) ) this.hideNewGame( onHide ); else if( curSence.is( "quit-body" ) ) this.hideQuit( onHide ); }; // to enter home page menu exports.showMenu = function( callback ){ var callee = arguments.callee; var times = callee.times = ++ callee.times || 1; peach = fruit.create( "peach", 137, 333, true ); sandia = fruit.create( "sandia", 330, 322, true ); boom = fruit.create( "boom", 552, 367, true, 2500 ); [ peach, sandia, boom ].forEach(function( f ){ f.isHomeMenu = 1; }); peach.isDojoIcon = sandia.isNewGameIcon = boom.isQuitIcon = 1; var group = [ [ homeMask, 0 ], [ logo, 0 ], [ ninja, 500 ], [ homeDesc, 1500 ], [ dojo, 2000 ], [ newGame, 2000 ], [ quit, 2000 ], [ newSign, 2000 ], [ peach, 2000 ], [ sandia, 2000 ], [ boom, 2000 ] ]; group.invoke( "show" ); [ peach, sandia ].invoke( "rotate", 2500 ); menuSnd.play(); setTimeout( callback, 2500 ); }; // to exit home page menu exports.hideMenu = function( callback ){ [ newSign, dojo, newGame, quit ].invoke( "hide" ); [ homeMask, logo, ninja, homeDesc ].invoke( "hide" ); [ peach, sandia, boom ].invoke( "fallOff", 150 ); menuSnd.stop(); setTimeout( callback, fruit.getDropTimeSetting() ); }; // to enter game body exports.showNewGame = function( callback ){ score.show(); lose.show(); game.start(); gameStartSnd.play(); setTimeout( callback, 1000 ); }; // to exit game body exports.hideNewGame = function( callback ){ score.hide(); lose.hide(); gameStartSnd.stop(); setTimeout( callback, 1000 ); }; // to enter dojo mode exports.showDojo = function( callback ){ developing.show( 250 ); setTimeout( callback, 1500 ); }; // to exit dojo mode exports.hideDojo = function( callback ){ // TODO: setTimeout( callback, 1000 ); }; // to enter quit page exports.showQuit = function( callback ){ developing.show( 250 ); setTimeout( callback, 1500 ); }; // to exit quit page exports.hideQuit = function( callback ){ // TODO: setTimeout( callback, 1000 ); }; message.addEventListener("sence.switchSence", function( name ){ exports.switchSence( name ); });; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\state.js */ define("scripts/state.js", function(exports){ /** * a simple state manager * @author dron * @date 2012-06-28 */ var Ucren = require("scripts/lib/ucren"); var timeline = require("scripts/timeline"); /** * usage: * state( key ).is( value ) -> determine if the value of key is the given value * state( key ).isnot( value ) -> determine if the value of key is not given value * state( key ).ison() -> determine if the value of key is the boolean value 'true' * state( key ).isoff() -> determine if the value of key is the boolean value 'false' * state( key ).isunset() -> determine if the value of key is undefined * state( key ).set( value ) -> set the value of key to a given value * state( key ).get() -> get the value of key * state( key ).on() -> set the value of key to boolean value 'true' * state( key ).off() -> set the value of key to boolean value 'false' */ var stack = {}; var cache = {}; var callbacks = {}; exports = function( key ){ if( cache[ key ] ) return cache[ key ]; return cache[ key ] = { is: function( value ){ return stack[key] === value; }, isnot: function( value ){ return stack[key] !== value; }, ison: function(){ return this.is( true ); }, isoff: function(){ return this.isnot( true ); }, isunset: function(){ return this.is( undefined ); }, set: function(){ var lastValue = NaN; return function( value ){ var c; stack[key] = value; if( lastValue !== value && ( c = callbacks[ key ] ) ) for(var i = 0, l = c.length; i < l; i ++) c[i].call( this, value ); lastValue = value; } }(), get: function(){ return stack[key]; }, on: function(){ var me = this; me.set( true ); return { keep: function( time ){ timeline.setTimeout( me.set.saturate( me, false ), time ); } } }, off: function(){ var me = this; me.set( false ); return { keep: function( time ){ timeline.setTimeout( me.set.saturate( me, true ), time ); } } }, hook: function( fn ){ var c; if( !( c = callbacks[ key ] ) ) callbacks[ key ] = [ fn ]; else c.push( fn ); }, unhook: function(){ // TODO: } } };; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\timeline.js */ define("scripts/timeline.js", function(exports){ /** * a easy timeline manager * @version 1.0 * @author dron */ var Ucren = require("scripts/lib/ucren"); var timerCache = {}; var timeline = {}; // var timer = timeline; // <or> // var timer = timeline.use( name ).init( 10 ); // to use a new timeline instance // // var t = timer.createTask(...); // t.stop(); // // timer.setTimeout(...); // timer.setInterval(...); // timer.getFPS(); function ClassTimer(){ this.tasks = []; this.addingTasks = []; this.adding = 0; } /** * initialize timeline */ ClassTimer.prototype.init = function( ms ){ var me = this; if( me.inited ) return ; else me.inited = 1; me.startTime = now(); me.intervalTime = ms || 5; me.count = 0; me.intervalFn = function(){ me.count ++; me.update( now() ); }; me.start(); return me; }; /** * create a task * @param {Object} conf the config * @return {Task} a task instance */ ClassTimer.prototype.createTask = function( conf ){ /* e.g. timer.createTask({ start: 500, duration: 2000, data: [a, b, c,..], object: module, onTimeUpdate: fn(time, a, b, c,..), onTimeStart: fn(a, b, c,..), onTimeEnd: fn(a, b, c,..), recycle: [] }); */ var task = createTask( conf ); this.addingTasks.unshift( task ); this.adding = 1; if( conf.recycle ) this.taskList( conf.recycle, task ); this.start(); return task; }; /** * use a array to recycle the task * @param {Array} queue be use for recycling task * @param {Task} task a task instance * @return {Array} this queue */ ClassTimer.prototype.taskList = function( queue, task ){ if( !queue.clear ) queue.clear = function(){ var i = this.length; while( i -- ) task = this[i], task.stop(), this.splice( i, 1 ); return this; }; if( task ) queue.unshift( task ); return queue; }; /** * create a timer for once callback * @param {Function} fn callback function * @param {Number} time time, unit: ms */ ClassTimer.prototype.setTimeout = function( fn, time ){ // e.g. setTimeout(fn, time); return this.createTask({ start: time, duration: 0, onTimeStart: fn }); }; /** * create a timer for ongoing callback * @param {Function} fn callback function * @param {Number} time time, unit: ms */ ClassTimer.prototype.setInterval = function( fn, time ){ // e.g. setInterval(fn, time); var timer = setInterval( fn, time ); return { stop: function(){ clearInterval( timer ); } }; }; /** * get the current fps * @return {Number} fps number */ ClassTimer.prototype.getFPS = function(){ var t = now(), c = this.count, fps = c / ( t - this.startTime ) * 1e3; if( c > 1e3 ) this.count = 0, this.startTime = t; return fps; }; // privates ClassTimer.prototype.start = function(){ clearInterval( this.interval ); this.interval = setInterval( this.intervalFn, this.intervalTime ); }; ClassTimer.prototype.stop = function(){ clearInterval( this.interval ); }; ClassTimer.prototype.update = function( time ){ var tasks = this.tasks, addingTasks = this.addingTasks, adding = this.adding; var i = tasks.length, t, task, start, duration, data; while( i -- ){ task = tasks[i]; start = task.start; duration = task.duration; if( time >= start ){ if( task.stopped ){ tasks.splice( i, 1 ); continue; } checkStartTask( task ); if( ( t = time - start ) < duration ) updateTask( task, t ); else updateTask( task, duration ), task.onTimeEnd.apply( task.object, task.data.slice(1) ), tasks.splice( i, 1 ); } } if( adding ) tasks.unshift.apply( tasks, addingTasks ), addingTasks.length = adding = 0; if( !tasks.length ) this.stop(); }; timeline.use = function( name ){ var module; if( module = timerCache[ name ] ) return module; else module = timerCache[ name ] = new ClassTimer; return module; }; /** * @functions */ var now = function(){ return new Date().getTime(); }; var createTask = function( conf ){ var object = conf.object || {}; conf.start = conf.start || 0; return { start: conf.start + now(), duration: conf.duration == -1 ? 86400000 : conf.duration, data: conf.data ? [ 0 ].concat( conf.data ) : [ 0 ], started: 0, object: object, onTimeStart: conf.onTimeStart || object.onTimeStart || Ucren.nul, onTimeUpdate: conf.onTimeUpdate || object.onTimeUpdate || Ucren.nul, onTimeEnd: conf.onTimeEnd || object.onTimeEnd || Ucren.nul, stop: function(){ this.stopped = 1; } } }; var updateTask = function( task, time ){ var data = task.data; data[0] = time; task.onTimeUpdate.apply( task.object, data ); }; var checkStartTask = function( task ){ if( !task.started ) task.started = 1, task.onTimeStart.apply( task.object, task.data.slice(1) ), updateTask( task, 0 ); }; /** * for compatible the old version */ exports = timeline.use( "default" ).init( 10 ); exports.use = function( name ){ if( Ucren.isIe ) exports; return timeline.use( name ); };; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\tools.js */ define("scripts/tools.js", function(exports){ exports.unsetObject = function( object ){ for(var i in object) if(object.hasOwnProperty(i) && typeof object[i] == "function") object[i] = function(){}; }; exports.getAngleByRadian = function( radian ){ return radian * 180 / Math.PI; } exports.pointToRadian = function( origin, point ){ var PI = Math.PI; if( point[0] === origin[0] ){ if ( point[1] > origin[1] ) return PI * 0.5; return PI * 1.5 }else if( point[1] === origin[1] ){ if ( point[0] > origin[0] ) return 0; return PI; } var t = Math.atan( ( origin[1] - point[1] ) / ( origin[0] - point[0] ) ); if( point[0] > origin[0] && point[1] < origin[1] ) return t + 2 * PI; if( point[0] > origin[0] && point[1] > origin[1] ) return t; return t + PI; }; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\factory\displacement.js */ define("scripts/factory/displacement.js", function(exports){ var layer = require("scripts/layer"); var timeline = require("scripts/timeline"); var tween = require("scripts/lib/tween"); /** * 位移类模块模型 */ exports.create = function( imageSrc, width, height, origX, origY, targetX, targetY, animMap, animDur ){ var module = {}; var image; var anim = {}; if( typeof animMap === "function" ) anim.show = anim.hide = animMap; else anim = animMap; var createTask = function( start, duration, sx, sy, ex, ey, anim, mode ){ timeline.createTask({ start: start, duration: duration, object: module, data: [ sx, sy, ex, ey, anim, mode ], onTimeUpdate: module.onTimeUpdate, onTimeStart: module.onTimeStart, onTimeEnd: module.onTimeEnd, recycle: module.anims }); }; module.anims = []; module.set = function(){ image = layer.createImage( "default", imageSrc, origX, origY, width, height ); }; module.show = function( start ){ createTask( start, animDur, origX, origY, targetX, targetY, anim.show, "show" ); }; module.hide = function(){ this.anims.clear(); createTask( 0, animDur, targetX, targetY, origX, origY, anim.hide, "hide" ); }; module.onTimeUpdate = function( time, sx, sy, ex, ey, anim ){ image.attr( { x: anim( time, sx, ex - sx, animDur ), y: anim( time, sy, ey - sy, animDur ) } ); }; module.onTimeStart = function(){ }; module.onTimeEnd = function( sx, sy, ex, ey, anim ){ if( anim === "hide" ) image.hide(); }; return module; };; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\factory\fruit.js */ define("scripts/factory/fruit.js", function(exports){ var layer = require("scripts/layer"); var Ucren = require("scripts/lib/ucren"); var timeline = require("scripts/timeline").use( "fruit" ).init( 1 ); var timeline2 = require("scripts/timeline").use( "fruit-apart" ).init( 1 ); var tween = require("scripts/lib/tween"); var message = require("scripts/message"); var flame = require("scripts/object/flame"); var flash = require("scripts/object/flash"); var juice = require("scripts/factory/juice"); var ie = Ucren.isIe; var safari = Ucren.isSafari; /** * 水果模块模型 */ var zoomAnim = tween.exponential.co; var rotateAnim = tween.circular; var linearAnim = tween.linear; var dropAnim = tween.quadratic.ci; var fallOffAnim = tween.quadratic.co; var random = Ucren.randomNumber; var min = Math.min; var average = function( a, b ){ return ( ( a + b ) / 2 ) >> 0; }; var dropTime = 1200, dropXScope = 200, shadowPos = 50; var infos = { // type: [ imageSrc, width, height, radius, fixAngle, isReverse, juiceColor ] boom: [ "images/fruit/boom.png", 66, 68, 26, 0, 0, null ], peach: [ "images/fruit/peach.png", 62, 59, 37, -50, 0, "#e6c731" ], sandia: [ "images/fruit/sandia.png", 98, 85, 38, -100, 0, "#c00" ], apple: [ "images/fruit/apple.png", 66, 66, 31, -54, 0, "#c8e925" ], banana: [ "images/fruit/banana.png", 126, 50, 43, 90, 0, null ], basaha: [ "images/fruit/basaha.png", 68, 72, 32, -135, 0, "#c00" ] }; // TODO: 是否水果全开? var types = [ "peach", "sandia", "apple", "banana", "basaha" ]; // var types = [ "sandia", "boom" ]; var rotateSpeed = [ 60, 50, 40, -40, -50, -60 ]; var fruitCache = []; function ClassFruit(conf){ var info = infos[ conf.type ], radius = info[3]; this.type = conf.type; this.originX = conf.originX; this.originY = conf.originY; this.radius = radius; this.startX = conf.originX; this.startY = conf.originY; this.radius = radius; this.anims = []; if( this.type === "boom" ) this.flame = flame.create( this.startX - radius + 4, this.startY - radius + 5, conf.flameStart || 0 ); } ClassFruit.prototype.set = function( hide ){ var inf = infos[ this.type ], radius = this.radius; this.shadow = layer.createImage( "fruit", "images/shadow.png", this.startX - radius, this.startY - radius + shadowPos, 106, 77 ); this.image = layer.createImage( "fruit", inf[0], this.startX - radius, this.startY - radius, inf[1], inf[2] ); if( hide ) this.image.hide(), this.shadow.hide(); return this; }; ClassFruit.prototype.pos = function( x, y ){ if( x == this.originX && y == this.originY ) return ; var r = this.radius; this.originX = x; this.originY = y; this.image.attr({ x: x -= r, y: y -= r }); this.shadow.attr({ x: x, y: y + shadowPos }); if( this.type === "boom" ) this.flame.pos( x + 4, y + 5 ); }; ClassFruit.prototype.show = function( start ){ timeline.createTask({ start: start, duration: 500, data: [ 1e-5, 1, "show" ], object: this, onTimeUpdate: this.onScaling, onTimeStart: this.onShowStart, recycle: this.anims }); }; ClassFruit.prototype.hide = function( start ){ if( this.type !== "boom" ) // if it is not a boom, it can't to be hide. return ; this.anims.clear(); this.flame.remove(); timeline.createTask({ start: start, duration: 500, data: [ 1, 1e-5, "hide" ], object: this, onTimeUpdate: this.onScaling, onTimeEnd: this.onHideEnd, recycle: this.anims }); }; ClassFruit.prototype.rotate = function( start, speed ){ this.rotateSpeed = speed || rotateSpeed[ random( 6 ) ]; this.rotateAnim = timeline.createTask({ start: start, duration: -1, object: this, onTimeUpdate: this.onRotating, recycle: this.anims }); }; ClassFruit.prototype.broken = function( angle ){ if( this.brokend )return; this.brokend = true; var index; if( ( index = fruitCache.indexOf( this ) ) > -1 ) fruitCache.splice( index, 1 ); if( this.type !== "boom" ) flash.showAt( this.originX, this.originY, angle ), juice.create( this.originX, this.originY, infos[ this.type ][6] ), this.apart( angle ); else this.hide(); }; ClassFruit.prototype.pause = function(){ if( this.brokend ) return; this.anims.clear(); if( this.type == "boom" ) this.flame.remove(); }; // 分开 ClassFruit.prototype.apart = function( angle ){ this.anims.clear(); this.image.hide(); this.shadow.hide(); this.aparted = true; var inf = infos[ this.type ], preSrc = inf[0].replace( ".png", "" ), radius = this.radius; var create = layer.createImage.saturate( layer, this.startX - radius, this.startY - radius, inf[1], inf[2] ); angle = ( ( angle % 180 ) + 360 + inf[4] ) % 360; this.bImage1 = create( "fruit", preSrc + "-1.png" ); this.bImage2 = create( "fruit", preSrc + "-2.png" ); [ this.bImage1, this.bImage2 ].invoke( "rotate", angle ); this.apartAngle = angle; timeline2.createTask({ start: 0, duration: dropTime, object: this, onTimeUpdate: this.onBrokenDropUpdate, onTimeStart: this.onBrokenDropStart, onTimeEnd: this.onBrokenDropEnd, recycle: this.anims }); }; // 抛出 ClassFruit.prototype.shotOut = function(){ var sign = [ -1, 1 ]; return function( start, endX ){ this.shotOutStartX = this.originX; this.shotOutStartY = this.originY; this.shotOutEndX = average( this.originX, endX ); this.shotOutEndY = min( this.startY - random( this.startY - 100 ), 200 ); this.fallOffToX = endX; timeline.createTask({ start: start, duration: dropTime, object: this, onTimeUpdate: this.onShotOuting, onTimeStart: this.onShotOutStart, onTimeEnd: this.onShotOutEnd, recycle: this.anims }); if( this.type != "boom" ) this.rotate( 0, ( random( 180 ) + 90 ) * sign[ random( 2 ) ] ); return this; }; }(); // 掉落 ClassFruit.prototype.fallOff = function(){ var sign = [ -1, 1 ]; var signIndex = 0; return function( start, x ){ if( this.aparted || this.brokend ) return ; var y = 600; if( typeof x !== "number" ) x = this.originX + random( dropXScope ) * sign[ ( signIndex ++ ) % 2 ]; this.fallTargetX = x; this.fallTargetY = y; timeline.createTask({ start: start, duration: dropTime, object: this, onTimeUpdate: this.onFalling, onTimeStart: this.onFallStart, onTimeEnd: this.onFallEnd, recycle: this.anims }); } }(); ClassFruit.prototype.remove = function(){ var index; this.anims.clear(); if( this.image ) this.image.remove(), this.shadow.remove(); if( this.bImage1 ) this.bImage1.remove(), this.bImage2.remove(); if( this.type === "boom" ) this.flame.remove(); if( ( index = fruitCache.indexOf( this ) ) > -1 ) fruitCache.splice( index, 1 ); for(var name in this) if( typeof this[name] === "function" ) this[name] = function( name ){ return function(){ throw new Error( "method " + name + " has been removed" ); }; }( name ); else delete this[name]; message.postMessage( this, "fruit.remove" ); }; // 显示/隐藏 相关 ClassFruit.prototype.onShowStart = function(){ this.image.show(); // this.shadow.show(); }; ClassFruit.prototype.onScaling = function( time, a, b, z ){ this.image.scale( z = zoomAnim( time, a, b - a, 500 ), z ); this.shadow.scale( z, z ); }; ClassFruit.prototype.onHideEnd = function(){ this.remove(); }; // 旋转相关 ClassFruit.prototype.onRotateStart = function(){ }; ClassFruit.prototype.onRotating = function( time ){ this.image.rotate( ( this.rotateSpeed * time / 1e3 ) % 360, true ); }; // 裂开相关 ClassFruit.prototype.onBrokenDropUpdate = function( time ){ var radius = this.radius; this.bImage1.attr({ x: linearAnim( time, this.brokenPosX - radius, this.brokenTargetX1, dropTime ), y: dropAnim( time, this.brokenPosY - radius, this.brokenTargetY1 - this.brokenPosY + radius, dropTime ) }).rotate( linearAnim( time, this.apartAngle, this.bImage1RotateAngle, dropTime ), true ); this.bImage2.attr({ x: linearAnim( time, this.brokenPosX - radius, this.brokenTargetX2, dropTime ), y: dropAnim( time, this.brokenPosY - radius, this.brokenTargetY2 - this.brokenPosY + radius, dropTime ) }).rotate( linearAnim( time, this.apartAngle, this.bImage2RotateAngle, dropTime ), true ); }; ClassFruit.prototype.onBrokenDropStart = function(){ this.brokenTargetX1 = -( random( dropXScope ) + 75 ); this.brokenTargetX2 = random( dropXScope + 75 ); this.brokenTargetY1 = 600; this.brokenTargetY2 = 600; this.brokenPosX = this.originX; this.brokenPosY = this.originY; this.bImage1RotateAngle = - random( 150 ) - 50; this.bImage2RotateAngle = random( 150 ) + 50; for(var f, i = fruitCache.length - 1; i >= 0; i --) if( fruitCache[i] === this ) fruitCache.splice( i, 1 ); }; ClassFruit.prototype.onBrokenDropEnd = function(){ this.remove(); }; // 抛出相关 ClassFruit.prototype.onShotOuting = function( time ){ this.pos( linearAnim( time, this.shotOutStartX, this.shotOutEndX - this.shotOutStartX, dropTime ), fallOffAnim( time, this.shotOutStartY, this.shotOutEndY - this.shotOutStartY, dropTime ) ); }; ClassFruit.prototype.onShotOutStart = function(){ // body... }; ClassFruit.prototype.onShotOutEnd = function(){ this.fallOff( 0, this.fallOffToX ); }; // 掉落相关 ClassFruit.prototype.onFalling = function( time ){ var y; this.pos( linearAnim( time, this.brokenPosX, this.fallTargetX - this.brokenPosX, dropTime ), y = dropAnim( time, this.brokenPosY, this.fallTargetY - this.brokenPosY, dropTime ) ); this.checkForFallOutOfViewer( y ); }; ClassFruit.prototype.onFallStart = function(){ this.brokenPosX = this.originX; this.brokenPosY = this.originY; }; ClassFruit.prototype.onFallEnd = function(){ message.postMessage( this, "fruit.fallOff" ); this.remove(); }; // privates ClassFruit.prototype.checkForFallOutOfViewer = function( y ){ if( y > 480 + this.radius ) this.checkForFallOutOfViewer = Ucren.nul, this.rotateAnim && this.rotateAnim.stop(), message.postMessage( this, "fruit.fallOutOfViewer" ); }; exports.create = function( type, originX, originY, isHide, flameStart ){ if( typeof type == "number" ) // 缺省 type isHide = originY, originY = originX, originX = type, type = getType(); var fruit = new ClassFruit({ type: type, originX: originX, originY: originY, flameStart: flameStart }).set( isHide ); fruitCache.unshift( fruit ); return fruit; }; exports.getFruitInView = function(){ return fruitCache; }; exports.getDropTimeSetting = function(){ return dropTime; }; function getType(){ if( random( 8 ) == 4 ) return "boom"; else return types[ random( 5 ) ]; }; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\factory\juice.js */ define("scripts/factory/juice.js", function(exports){ /** * 果汁 */ var Ucren = require("scripts/lib/ucren"); var layer = require("scripts/layer").getLayer("juice"); var timeline = require("scripts/timeline").use( "juice" ).init( 10 ); var tween = require("scripts/lib/tween"); var tools = require("scripts/tools"); var random = Ucren.randomNumber; var dur = 1500; var anim = tween.exponential.co; var dropAnim = tween.quadratic.co; var sin = Math.sin; var cos = Math.cos; var num = 10; var radius = 10; // if( Ucren.isIe6 || Ucren.isSafari ) // switchOn = false; // if( Ucren.isIe || Ucren.isSafari ) // num = 6; function ClassJuice( x, y, color ){ this.originX = x; this.originY = y; this.color = color; this.distance = random( 200 ) + 100; this.radius = radius; this.dir = random( 360 ) * Math.PI / 180; } ClassJuice.prototype.render = function(){ this.circle = layer.circle( this.originX, this.originY, this.radius ).attr({ fill: this.color, stroke: "none" }); }; ClassJuice.prototype.sputter = function(){ timeline.createTask({ start: 0, duration: dur, object: this, onTimeUpdate: this.onTimeUpdate, onTimeEnd: this.onTimeEnd }); }; ClassJuice.prototype.onTimeUpdate = function( time ){ var distance, x, y, z; distance = anim( time, 0, this.distance, dur ); x = this.originX + distance * cos( this.dir ); y = this.originY + distance * sin( this.dir ) + dropAnim( time, 0, 200, dur ); z = anim( time, 1, -1, dur ); this.circle.attr({ cx: x, cy: y }).scale( z, z ); }; ClassJuice.prototype.onTimeEnd = function(){ this.circle.remove(); tools.unsetObject( this ); }; exports.create = function( x, y, color ){ for(var i = 0; i < num; i ++) this.createOne( x, y, color ); }; exports.createOne = function( x, y, color ){ if( !color ) return; var juice = new ClassJuice( x, y, color ); juice.render(); juice.sputter(); };; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\factory\rotate.js */ define("scripts/factory/rotate.js", function(exports){ var layer = require("scripts/layer"); var timeline = require("scripts/timeline"); var Ucren = require("scripts/lib/ucren"); /** * 旋转类模块模型 */ exports.create = function( imageSrc, x, y, w, h, z, anim, animDur ){ var module = {}, image; var rotateDire = [12, -12][Ucren.randomNumber(2)]; var defaultAngle = Ucren.randomNumber(360); module.anims = []; module.set = function(){ image = layer.createImage( "default", imageSrc, x, y, w, h ).scale( z, z ).rotate( defaultAngle, true ); }; module.show = function(start){ timeline.createTask({ start: start, duration: animDur, object: this, data: [z, 1], onTimeUpdate: this.onZooming, onTimeEnd: this.onShowEnd, recycle: this.anims }); }; module.hide = function(start){ this.anims.clear(); timeline.createTask({ start: start, duration: animDur, object: this, data: [ 1, z ], onTimeUpdate: this.onZooming, recycle: this.anims }); }; module.onShowEnd = function(name){ this.anims.clear(); timeline.createTask({ start: 0, duration: -1, object: this, onTimeUpdate: module.onRotating, recycle: this.anims }); }; module.onZooming = function(){ var z; return function( time, a, b ){ image.scale( z = anim( time, a, b - a, animDur ), z ); } }(); module.onRotating = function(){ var lastTime = 0, an = defaultAngle; return function( time, name, a, b ){ an = ( an + ( time - lastTime ) / 1e3 * rotateDire ) % 360; image.rotate( an, true ); lastTime = time; } }(); return module; }; return exports; }); /** * @source D:\hosting\demos\fruit-ninja\output\scripts\lib\buzz.js */ define("scripts/lib/buzz.js", function(exports){ // ---------------------------------------------------------------------------- // Buzz, a Javascript HTML5 Audio library // v 1.0.x beta // Licensed under the MIT license. // http://buzz.jaysalvat.com/ // ---------------------------------------------------------------------------- // Copyright (C) 2011 Jay Salvat // http://jaysalvat.com/ // ---------------------------------------------------------------------------- // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files ( the "Software" ), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // ---------------------------------------------------------------------------- var buzz = { defaults: { autoplay: false, duration: 5000, formats: [], loop: false, placeholder: '--', preload: 'metadata', volume: 80 }, types: { 'mp3': 'audio/mpeg', 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'aac': 'audio/aac', 'm4a': 'audio/x-m4a' }, sounds: [], el: document.createElement( 'audio' ), sound: function( src, options ) { options = options || {}; var pid = 0, events = [], eventsOnce = {}, supported = buzz.isSupported(); // publics this.load = function() { if ( !supported ) { return this; } this.sound.load(); return this; }; this.play = function() { if ( !supported ) { return this; } this.sound.play(); return this; }; this.togglePlay = function() { if ( !supported ) { return this; } if ( this.sound.paused ) { this.sound.play(); } else { this.sound.pause(); } return this; }; this.pause = function() { if ( !supported ) { return this; } this.sound.pause(); return this; }; this.isPaused = function() { if ( !supported ) { return null; } return this.sound.paused; }; this.stop = function() { if ( !supported ) { return this; } this.setTime( this.getDuration() ); this.sound.pause(); return this; }; this.isEnded = function() { if ( !supported ) { return null; } return this.sound.ended; }; this.loop = function() { if ( !supported ) { return this; } this.sound.loop = 'loop'; this.bind( 'ended.buzzloop', function() { this.currentTime = 0; this.play(); }); return this; }; this.unloop = function() { if ( !supported ) { return this; } this.sound.removeAttribute( 'loop' ); this.unbind( 'ended.buzzloop' ); return this; }; this.mute = function() { if ( !supported ) { return this; } this.sound.muted = true; return this; }; this.unmute = function() { if ( !supported ) { return this; } this.sound.muted = false; return this; }; this.toggleMute = function() { if ( !supported ) { return this; } this.sound.muted = !this.sound.muted; return this; }; this.isMuted = function() { if ( !supported ) { return null; } return this.sound.muted; }; this.setVolume = function( volume ) { if ( !supported ) { return this; } if ( volume < 0 ) { volume = 0; } if ( volume > 100 ) { volume = 100; } this.volume = volume; this.sound.volume = volume / 100; return this; }; this.getVolume = function() { if ( !supported ) { return this; } return this.volume; }; this.increaseVolume = function( value ) { return this.setVolume( this.volume + ( value || 1 ) ); }; this.decreaseVolume = function( value ) { return this.setVolume( this.volume - ( value || 1 ) ); }; this.setTime = function( time ) { if ( !supported ) { return this; } this.whenReady( function() { this.sound.currentTime = time; }); return this; }; this.getTime = function() { if ( !supported ) { return null; } var time = Math.round( this.sound.currentTime * 100 ) / 100; return isNaN( time ) ? buzz.defaults.placeholder : time; }; this.setPercent = function( percent ) { if ( !supported ) { return this; } return this.setTime( buzz.fromPercent( percent, this.sound.duration ) ); }; this.getPercent = function() { if ( !supported ) { return null; } var percent = Math.round( buzz.toPercent( this.sound.currentTime, this.sound.duration ) ); return isNaN( percent ) ? buzz.defaults.placeholder : percent; }; this.setSpeed = function( duration ) { if ( !supported ) { return this; } this.sound.playbackRate = duration; }; this.getSpeed = function() { if ( !supported ) { return null; } return this.sound.playbackRate; }; this.getDuration = function() { if ( !supported ) { return null; } var duration = Math.round( this.sound.duration * 100 ) / 100; return isNaN( duration ) ? buzz.defaults.placeholder : duration; }; this.getPlayed = function() { if ( !supported ) { return null; } return timerangeToArray( this.sound.played ); }; this.getBuffered = function() { if ( !supported ) { return null; } return timerangeToArray( this.sound.buffered ); }; this.getSeekable = function() { if ( !supported ) { return null; } return timerangeToArray( this.sound.seekable ); }; this.getErrorCode = function() { if ( supported && this.sound.error ) { return this.sound.error.code; } return 0; }; this.getErrorMessage = function() { if ( !supported ) { return null; } switch( this.getErrorCode() ) { case 1: return 'MEDIA_ERR_ABORTED'; case 2: return 'MEDIA_ERR_NETWORK'; case 3: return 'MEDIA_ERR_DECODE'; case 4: return 'MEDIA_ERR_SRC_NOT_SUPPORTED'; default: return null; } }; this.getStateCode = function() { if ( !supported ) { return null; } return this.sound.readyState; }; this.getStateMessage = function() { if ( !supported ) { return null; } switch( this.getStateCode() ) { case 0: return 'HAVE_NOTHING'; case 1: return 'HAVE_METADATA'; case 2: return 'HAVE_CURRENT_DATA'; case 3: return 'HAVE_FUTURE_DATA'; case 4: return 'HAVE_ENOUGH_DATA'; default: return null; } }; this.getNetworkStateCode = function() { if ( !supported ) { return null; } return this.sound.networkState; }; this.getNetworkStateMessage = function() { if ( !supported ) { return null; } switch( this.getNetworkStateCode() ) { case 0: return 'NETWORK_EMPTY'; case 1: return 'NETWORK_IDLE'; case 2: return 'NETWORK_LOADING'; case 3: return 'NETWORK_NO_SOURCE'; default: return null; } }; this.set = function( key, value ) { if ( !supported ) { return this; } this.sound[ key ] = value; return this; }; this.get = function( key ) { if ( !supported ) { return null; } return key ? this.sound[ key ] : this.sound; }; this.bind = function( types, func ) { if ( !supported ) { return this; } types = types.split( ' ' ); var that = this, efunc = function( e ) { func.call( that, e ); }; for( var t = 0; t < types.length; t++ ) { var type = types[ t ], idx = type; type = idx.split( '.' )[ 0 ]; events.push( { idx: idx, func: efunc } ); this.sound.addEventListener( type, efunc, true ); } return this; }; this.unbind = function( types ) { if ( !supported ) { return this; } types = types.split( ' ' ); for( var t = 0; t < types.length; t++ ) { var idx = types[ t ], type = idx.split( '.' )[ 0 ]; for( var i = 0; i < events.length; i++ ) { var namespace = events[ i ].idx.split( '.' ); if ( events[ i ].idx == idx || ( namespace[ 1 ] && namespace[ 1 ] == idx.replace( '.', '' ) ) ) { this.sound.removeEventListener( type, events[ i ].func, true ); // remove event events.splice(i, 1); } } } return this; }; this.bindOnce = function( type, func ) { if ( !supported ) { return this; } var that = this; eventsOnce[ pid++ ] = false; this.bind( pid + type, function() { if ( !eventsOnce[ pid ] ) { eventsOnce[ pid ] = true; func.call( that ); } that.unbind( pid + type ); }); }; this.trigger = function( types ) { if ( !supported ) { return this; } types = types.split( ' ' ); for( var t = 0; t < types.length; t++ ) { var idx = types[ t ]; for( var i = 0; i < events.length; i++ ) { var eventType = events[ i ].idx.split( '.' ); if ( events[ i ].idx == idx || ( eventType[ 0 ] && eventType[ 0 ] == idx.replace( '.', '' ) ) ) { var evt = document.createEvent('HTMLEvents'); evt.initEvent( eventType[ 0 ], false, true ); this.sound.dispatchEvent( evt ); } } } return this; }; this.fadeTo = function( to, duration, callback ) { if ( !supported ) { return this; } if ( duration instanceof Function ) { callback = duration; duration = buzz.defaults.duration; } else { duration = duration || buzz.defaults.duration; } var from = this.volume, delay = duration / Math.abs( from - to ), that = this; this.play(); function doFade() { setTimeout( function() { if ( from < to && that.volume < to ) { that.setVolume( that.volume += 1 ); doFade(); } else if ( from > to && that.volume > to ) { that.setVolume( that.volume -= 1 ); doFade(); } else if ( callback instanceof Function ) { callback.apply( that ); } }, delay ); } this.whenReady( function() { doFade(); }); return this; }; this.fadeIn = function( duration, callback ) { if ( !supported ) { return this; } return this.setVolume(0).fadeTo( 100, duration, callback ); }; this.fadeOut = function( duration, callback ) { if ( !supported ) { return this; } return this.fadeTo( 0, duration, callback ); }; this.fadeWith = function( sound, duration ) { if ( !supported ) { return this; } this.fadeOut( duration, function() { this.stop(); }); sound.play().fadeIn( duration ); return this; }; this.whenReady = function( func ) { if ( !supported ) { return null; } var that = this; if ( this.sound.readyState === 0 ) { this.bind( 'canplay.buzzwhenready', function() { func.call( that ); }); } else { func.call( that ); } }; // privates function timerangeToArray( timeRange ) { var array = [], length = timeRange.length - 1; for( var i = 0; i <= length; i++ ) { array.push({ start: timeRange.start( length ), end: timeRange.end( length ) }); } return array; } function getExt( filename ) { return filename.split('.').pop(); } function addSource( sound, src ) { var source = document.createElement( 'source' ); source.src = src; if ( buzz.types[ getExt( src ) ] ) { source.type = buzz.types[ getExt( src ) ]; } sound.appendChild( source ); } // init if ( supported && src ) { for(var i in buzz.defaults ) { if(buzz.defaults.hasOwnProperty(i)) { options[ i ] = options[ i ] || buzz.defaults[ i ]; } } this.sound = document.createElement( 'audio' ); if ( src instanceof Array ) { for( var j in src ) { if(src.hasOwnProperty(j)) { addSource( this.sound, src[ j ] ); } } } else if ( options.formats.length ) { for( var k in options.formats ) { if(options.formats.hasOwnProperty(k)) { addSourc