├── README.md ├── images ├── x.png ├── logo.png ├── xf.png ├── xx.png ├── xxf.png ├── xxx.png ├── xxxf.png ├── flash.png ├── ninja.png ├── shadow.png ├── fruit │ ├── b1.png │ ├── b2.png │ ├── b3.png │ ├── b4.png │ ├── f1.png │ ├── f2.png │ ├── f3.png │ ├── f4.png │ ├── f5.png │ ├── f6.png │ ├── s1.png │ ├── s2.png │ ├── w1.png │ ├── w2.png │ ├── w3.png │ ├── zy.png │ ├── b1-1.png │ ├── b1-2.png │ ├── b2-1.png │ ├── b2-2.png │ ├── b3-1.png │ ├── b3-2.png │ ├── b4-1.png │ ├── b4-2.png │ ├── f1-1.png │ ├── f1-2.png │ ├── f2-1.png │ ├── f2-2.png │ ├── f3-1.png │ ├── f3-2.png │ ├── f4-1.png │ ├── f4-2.png │ ├── f5-1.png │ ├── f5-2.png │ ├── f6-1.png │ ├── f6-2.png │ ├── gesar.png │ ├── w1-1.png │ ├── w1-2.png │ ├── w2-1.png │ ├── w2-2.png │ ├── w3-1.png │ ├── w3-2.png │ ├── basiclaw.png │ └── ferrari.png ├── game-over.png ├── home-mask.png ├── mistake.png ├── new-game.png └── background.jpg ├── sounds ├── bun1.mp3 ├── bun2.mp3 ├── bun3.mp3 ├── bun4.mp3 ├── bun5.mp3 ├── fault1.mp3 ├── fault2.mp3 ├── fault3.mp3 ├── fault4.mp3 ├── fault5.mp3 ├── fault6.mp3 ├── fault7.mp3 ├── fault8.mp3 ├── fault9.mp3 ├── frog1.mp3 ├── frog2.mp3 ├── frog3.mp3 ├── frog4.mp3 ├── gesar1.mp3 ├── basiclaw1.mp3 ├── basiclaw2.mp3 ├── fault10.mp3 ├── ferrari1.mp3 ├── ferrari2.mp3 ├── ferrari3.mp3 ├── ferrari4.mp3 ├── ferrari5.mp3 ├── ferrari6.mp3 ├── gameover1.mp3 ├── gameover2.mp3 ├── gameover3.mp3 ├── winnie1.mp3 ├── shakespeare1.mp3 └── shakespeare2.mp3 ├── scripts ├── require.js ├── sound.js ├── object │ ├── game-over.js │ ├── score.js │ ├── background.js │ ├── logo.js │ ├── new-game.js │ └── mistake.js ├── sound-manager.js ├── flash.js ├── rotation.js ├── layout.js ├── animation.js ├── main.js ├── tools.js ├── juice.js ├── collision.js ├── lib │ ├── tween.js │ └── raphael.js ├── knife.js ├── layer.js ├── light.js ├── drag.js ├── scene.js ├── fruit-manager.js ├── game.js ├── timeline.js └── fruit.js └── index.html /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/x.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/logo.png -------------------------------------------------------------------------------- /images/xf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/xf.png -------------------------------------------------------------------------------- /images/xx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/xx.png -------------------------------------------------------------------------------- /images/xxf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/xxf.png -------------------------------------------------------------------------------- /images/xxx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/xxx.png -------------------------------------------------------------------------------- /images/xxxf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/xxxf.png -------------------------------------------------------------------------------- /sounds/bun1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/bun1.mp3 -------------------------------------------------------------------------------- /sounds/bun2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/bun2.mp3 -------------------------------------------------------------------------------- /sounds/bun3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/bun3.mp3 -------------------------------------------------------------------------------- /sounds/bun4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/bun4.mp3 -------------------------------------------------------------------------------- /sounds/bun5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/bun5.mp3 -------------------------------------------------------------------------------- /images/flash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/flash.png -------------------------------------------------------------------------------- /images/ninja.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/ninja.png -------------------------------------------------------------------------------- /images/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/shadow.png -------------------------------------------------------------------------------- /sounds/fault1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault1.mp3 -------------------------------------------------------------------------------- /sounds/fault2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault2.mp3 -------------------------------------------------------------------------------- /sounds/fault3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault3.mp3 -------------------------------------------------------------------------------- /sounds/fault4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault4.mp3 -------------------------------------------------------------------------------- /sounds/fault5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault5.mp3 -------------------------------------------------------------------------------- /sounds/fault6.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault6.mp3 -------------------------------------------------------------------------------- /sounds/fault7.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault7.mp3 -------------------------------------------------------------------------------- /sounds/fault8.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault8.mp3 -------------------------------------------------------------------------------- /sounds/fault9.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault9.mp3 -------------------------------------------------------------------------------- /sounds/frog1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/frog1.mp3 -------------------------------------------------------------------------------- /sounds/frog2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/frog2.mp3 -------------------------------------------------------------------------------- /sounds/frog3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/frog3.mp3 -------------------------------------------------------------------------------- /sounds/frog4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/frog4.mp3 -------------------------------------------------------------------------------- /sounds/gesar1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/gesar1.mp3 -------------------------------------------------------------------------------- /images/fruit/b1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b1.png -------------------------------------------------------------------------------- /images/fruit/b2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b2.png -------------------------------------------------------------------------------- /images/fruit/b3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b3.png -------------------------------------------------------------------------------- /images/fruit/b4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b4.png -------------------------------------------------------------------------------- /images/fruit/f1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f1.png -------------------------------------------------------------------------------- /images/fruit/f2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f2.png -------------------------------------------------------------------------------- /images/fruit/f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f3.png -------------------------------------------------------------------------------- /images/fruit/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f4.png -------------------------------------------------------------------------------- /images/fruit/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f5.png -------------------------------------------------------------------------------- /images/fruit/f6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f6.png -------------------------------------------------------------------------------- /images/fruit/s1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/s1.png -------------------------------------------------------------------------------- /images/fruit/s2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/s2.png -------------------------------------------------------------------------------- /images/fruit/w1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w1.png -------------------------------------------------------------------------------- /images/fruit/w2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w2.png -------------------------------------------------------------------------------- /images/fruit/w3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w3.png -------------------------------------------------------------------------------- /images/fruit/zy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/zy.png -------------------------------------------------------------------------------- /images/game-over.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/game-over.png -------------------------------------------------------------------------------- /images/home-mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/home-mask.png -------------------------------------------------------------------------------- /images/mistake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/mistake.png -------------------------------------------------------------------------------- /images/new-game.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/new-game.png -------------------------------------------------------------------------------- /sounds/basiclaw1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/basiclaw1.mp3 -------------------------------------------------------------------------------- /sounds/basiclaw2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/basiclaw2.mp3 -------------------------------------------------------------------------------- /sounds/fault10.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/fault10.mp3 -------------------------------------------------------------------------------- /sounds/ferrari1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/ferrari1.mp3 -------------------------------------------------------------------------------- /sounds/ferrari2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/ferrari2.mp3 -------------------------------------------------------------------------------- /sounds/ferrari3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/ferrari3.mp3 -------------------------------------------------------------------------------- /sounds/ferrari4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/ferrari4.mp3 -------------------------------------------------------------------------------- /sounds/ferrari5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/ferrari5.mp3 -------------------------------------------------------------------------------- /sounds/ferrari6.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/ferrari6.mp3 -------------------------------------------------------------------------------- /sounds/gameover1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/gameover1.mp3 -------------------------------------------------------------------------------- /sounds/gameover2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/gameover2.mp3 -------------------------------------------------------------------------------- /sounds/gameover3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/gameover3.mp3 -------------------------------------------------------------------------------- /sounds/winnie1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/winnie1.mp3 -------------------------------------------------------------------------------- /images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/background.jpg -------------------------------------------------------------------------------- /images/fruit/b1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b1-1.png -------------------------------------------------------------------------------- /images/fruit/b1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b1-2.png -------------------------------------------------------------------------------- /images/fruit/b2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b2-1.png -------------------------------------------------------------------------------- /images/fruit/b2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b2-2.png -------------------------------------------------------------------------------- /images/fruit/b3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b3-1.png -------------------------------------------------------------------------------- /images/fruit/b3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b3-2.png -------------------------------------------------------------------------------- /images/fruit/b4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b4-1.png -------------------------------------------------------------------------------- /images/fruit/b4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/b4-2.png -------------------------------------------------------------------------------- /images/fruit/f1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f1-1.png -------------------------------------------------------------------------------- /images/fruit/f1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f1-2.png -------------------------------------------------------------------------------- /images/fruit/f2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f2-1.png -------------------------------------------------------------------------------- /images/fruit/f2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f2-2.png -------------------------------------------------------------------------------- /images/fruit/f3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f3-1.png -------------------------------------------------------------------------------- /images/fruit/f3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f3-2.png -------------------------------------------------------------------------------- /images/fruit/f4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f4-1.png -------------------------------------------------------------------------------- /images/fruit/f4-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f4-2.png -------------------------------------------------------------------------------- /images/fruit/f5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f5-1.png -------------------------------------------------------------------------------- /images/fruit/f5-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f5-2.png -------------------------------------------------------------------------------- /images/fruit/f6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f6-1.png -------------------------------------------------------------------------------- /images/fruit/f6-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/f6-2.png -------------------------------------------------------------------------------- /images/fruit/gesar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/gesar.png -------------------------------------------------------------------------------- /images/fruit/w1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w1-1.png -------------------------------------------------------------------------------- /images/fruit/w1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w1-2.png -------------------------------------------------------------------------------- /images/fruit/w2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w2-1.png -------------------------------------------------------------------------------- /images/fruit/w2-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w2-2.png -------------------------------------------------------------------------------- /images/fruit/w3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w3-1.png -------------------------------------------------------------------------------- /images/fruit/w3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/w3-2.png -------------------------------------------------------------------------------- /images/fruit/basiclaw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/basiclaw.png -------------------------------------------------------------------------------- /images/fruit/ferrari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/images/fruit/ferrari.png -------------------------------------------------------------------------------- /sounds/shakespeare1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/shakespeare1.mp3 -------------------------------------------------------------------------------- /sounds/shakespeare2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hahaxixi/bao/HEAD/sounds/shakespeare2.mp3 -------------------------------------------------------------------------------- /scripts/require.js: -------------------------------------------------------------------------------- 1 | void function(global) { 2 | "use strict"; 3 | 4 | var modules = {}; 5 | 6 | var require = function(id) { 7 | if (!/\.js$/.test(id)) 8 | id += ".js"; 9 | var module = modules[id]; 10 | if (!module.exports) { 11 | module.exports = {}; 12 | module.call(this, module.exports, require, module); 13 | } 14 | return module.exports; 15 | }; 16 | 17 | global.define = function(id, func) { 18 | modules[id] = func; 19 | }; 20 | global.require = require; 21 | }(this); 22 | -------------------------------------------------------------------------------- /scripts/sound.js: -------------------------------------------------------------------------------- 1 | define("scripts/sound.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | function ClassSound(src) { 5 | this.sound = document.createElement("audio"); 6 | var source = document.createElement("source"); 7 | source.src = src; 8 | this.sound.appendChild(source); 9 | this.sound.preload = "auto"; 10 | this.sound.volume = 1; 11 | } 12 | 13 | ClassSound.prototype.play = function() { 14 | return this.sound.play(); 15 | }; 16 | 17 | exports.create = function(src, opts) { 18 | return new ClassSound(src, opts); 19 | }; 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /scripts/object/game-over.js: -------------------------------------------------------------------------------- 1 | define("scripts/object/game-over.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var layout = require("scripts/layout"); 6 | var scale = require("scripts/animation").scale; 7 | 8 | var image; 9 | 10 | exports.set = function() { 11 | image = layer.createImage("default", "images/game-over.png", 12 | layout.centerX(490), layout.centerY(85), 490, 85).hide().scale(1e-5, 1e-5); 13 | }; 14 | 15 | exports.show = function() { 16 | image.show(); 17 | scale(image, 1e-5, 1, 500); 18 | }; 19 | 20 | exports.hide = function() { 21 | scale(image, 1, 1e-5, 500, image.hide); 22 | }; 23 | 24 | exports.resize = function() { 25 | image.attr({ 26 | "x": layout.centerX(image.attrs.width), 27 | "y": layout.centerY(image.attrs.height) 28 | }); 29 | }; 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /scripts/object/score.js: -------------------------------------------------------------------------------- 1 | define("scripts/object/score.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var translateX = require("scripts/animation").translateX; 6 | 7 | var score; 8 | 9 | exports.set = function() { 10 | score = layer.createText("default", "", -59, 24, "90-#fc7f0c-#ffec53", "30px").hide(); 11 | }; 12 | 13 | exports.show = function() { 14 | score.attr("text", "+0s"); 15 | score.show(); 16 | translateX(score, -59, 7, 500); 17 | }; 18 | 19 | exports.hide = function() { 20 | translateX(score, 7, -59, 500, score.hide); 21 | }; 22 | 23 | exports.resize = function() { 24 | 25 | }; 26 | 27 | exports.number = function(number) { 28 | score.attr("text", "+" + number + "s"); 29 | score.attr("font-size", "36px"); 30 | setTimeout(function() { 31 | score.attr("font-size", "30px"); 32 | }, 30); 33 | }; 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /scripts/sound-manager.js: -------------------------------------------------------------------------------- 1 | define("scripts/sound-manager.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var sound = require("scripts/sound"); 5 | var random = require("scripts/tools").randomNumber; 6 | 7 | var soundArrays = { 8 | "basiclaw": 2, 9 | "shakespeare": 2, 10 | "gesar": 1, 11 | "winnie": 1, 12 | "ferrari": 6, 13 | "fault": 10, 14 | "frog": 4, 15 | "bun": 5, 16 | "gameover": 3 17 | }; 18 | 19 | function loadArrays() { 20 | var arr, count, src; 21 | for (var name in soundArrays) { 22 | arr = []; 23 | count = soundArrays[name]; 24 | for (var i = 0; i < count; i++) { 25 | arr.push(sound.create("sounds/" + name + (i + 1) + ".mp3")); 26 | } 27 | soundArrays[name] = arr; 28 | } 29 | } 30 | 31 | exports.init = function() { 32 | loadArrays(); 33 | }; 34 | 35 | exports.play = function(name) { 36 | var arr = soundArrays[name]; 37 | var len = arr.length; 38 | return arr[len == 1 ? 0 : random(len)].play(); 39 | }; 40 | 41 | }); 42 | -------------------------------------------------------------------------------- /scripts/object/background.js: -------------------------------------------------------------------------------- 1 | define("scripts/object/background.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var layout = require("scripts/layout"); 6 | var random = require("scripts/tools").randomNumber; 7 | 8 | var image, timer; 9 | 10 | exports.set = function() { 11 | image = layer.createImage("default", "images/background.jpg", 0, 0, layout.width(), layout.height()); 12 | }; 13 | 14 | exports.resize = function() { 15 | image.attr({ 16 | width: layout.width(), 17 | height: layout.height() 18 | }); 19 | }; 20 | 21 | exports.wobble = function() { 22 | if (timer) 23 | return; 24 | timer = setInterval(wobble, 50); 25 | }; 26 | 27 | exports.stop = function() { 28 | clearInterval(timer); 29 | timer = null; 30 | image.attr({ 31 | x: 0, 32 | y: 0 33 | }); 34 | }; 35 | 36 | function wobble() { 37 | var x, y; 38 | x = random(12) - 6; 39 | y = random(12) - 6; 40 | image.attr({ 41 | x: x, 42 | y: y 43 | }); 44 | }; 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /scripts/flash.js: -------------------------------------------------------------------------------- 1 | define("scripts/flash.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var timeline = require("scripts/timeline").use("flash").init(10); 6 | var tween = require("scripts/lib/tween"); 7 | 8 | var image; 9 | 10 | var anim = tween.quadratic.cio; 11 | var anims = []; 12 | var dur = 100; 13 | 14 | function createImage() { 15 | image = layer.createImage("flash", "images/flash.png", 0, 0, 358, 20).hide(); 16 | } 17 | 18 | function onTimeUpdate(time, a, b, z) { 19 | image.scale(z = anim(time, a, b - a, dur), z); 20 | } 21 | 22 | exports.showAt = function(x, y, an) { 23 | if (!image) 24 | createImage(); 25 | 26 | image.rotate(an, true).scale(1e-5, 1e-5).attr({ 27 | x: x, 28 | y: y 29 | }).show(); 30 | 31 | anims.clear && anims.clear(); 32 | 33 | timeline.createTask({ 34 | start: 0, 35 | duration: dur, 36 | data: [1e-5, 1], 37 | object: this, 38 | onTimeUpdate: onTimeUpdate, 39 | recycle: anims 40 | }); 41 | 42 | timeline.createTask({ 43 | start: dur, 44 | duration: dur, 45 | data: [1, 1e-5], 46 | object: this, 47 | onTimeUpdate: onTimeUpdate, 48 | recycle: anims 49 | }); 50 | }; 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /scripts/rotation.js: -------------------------------------------------------------------------------- 1 | define("scripts/rotation.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var timeline = require("scripts/timeline"); 5 | var randomNumber = require("scripts/tools").randomNumber; 6 | var tween = require("scripts/lib/tween"); 7 | 8 | var anim = tween.exponential.co; 9 | /** 10 | * 旋转类模块模型 11 | */ 12 | 13 | exports.create = function(object) { 14 | var module = {}; 15 | var rotateDire = [12, -12][randomNumber(2)]; 16 | var defaultAngle = randomNumber(360); 17 | 18 | module.anims = []; 19 | 20 | module.show = function() { 21 | object.rotate(defaultAngle, true); 22 | object.show(); 23 | 24 | timeline.createTask({ 25 | start: 0, 26 | duration: -1, 27 | object: this, 28 | onTimeUpdate: module.onRotating, 29 | recycle: this.anims 30 | }); 31 | }; 32 | 33 | module.hide = function() { 34 | this.anims.clear(); 35 | object.hide(); 36 | }; 37 | 38 | module.onRotating = function() { 39 | var lastTime = 0, 40 | an = defaultAngle; 41 | return function(time) { 42 | an = (an + (time - lastTime) / 1e3 * rotateDire) % 360; 43 | object.rotate(an, true); 44 | lastTime = time; 45 | } 46 | }(); 47 | 48 | return module; 49 | }; 50 | 51 | }); 52 | -------------------------------------------------------------------------------- /scripts/layout.js: -------------------------------------------------------------------------------- 1 | define("scripts/layout.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var elem = document.getElementById("container"); 5 | 6 | var minWidth = 240; 7 | var minHeight = 240; 8 | 9 | exports.x = function() { 10 | return elem.offsetLeft; 11 | }; 12 | 13 | exports.y = function() { 14 | return elem.offsetTop; 15 | }; 16 | 17 | exports.width = function() { 18 | var w = elem.offsetWidth; 19 | if (w < minWidth) 20 | w = minWidth; 21 | return w; 22 | }; 23 | 24 | exports.height = function() { 25 | var h = elem.offsetHeight; 26 | if (h < minHeight) 27 | h = minHeight; 28 | return h; 29 | }; 30 | 31 | exports.left = function(n) { 32 | n = n || 0; 33 | return n; 34 | }; 35 | 36 | exports.top = function(n) { 37 | n = n || 0; 38 | return n; 39 | }; 40 | 41 | exports.right = function(n, w) { 42 | n = n || 0; 43 | w = w || 0; 44 | return exports.width() - n - w; 45 | }; 46 | 47 | exports.bottom = function(n, h) { 48 | n = n || 0; 49 | h = h || 0; 50 | return exports.height() - n - h; 51 | }; 52 | 53 | exports.centerX = function(w) { 54 | w = w || 0; 55 | return (exports.width() >> 1) - (w >> 1); 56 | }; 57 | 58 | exports.centerY = function(h) { 59 | h = h || 0; 60 | return (exports.height() >> 1) - (h >> 1); 61 | }; 62 | 63 | }); 64 | -------------------------------------------------------------------------------- /scripts/animation.js: -------------------------------------------------------------------------------- 1 | define("scripts/animation.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var timeline = require("scripts/timeline"); 6 | var tween = require("scripts/lib/tween"); 7 | 8 | var anim = tween.exponential.co; 9 | 10 | exports.translateX = function(object, from, to, duration, callback) { 11 | return timeline.createTask({ 12 | start: 0, 13 | duration: duration, 14 | object: object, 15 | 16 | onTimeUpdate: function(time) { 17 | object.attr({ 18 | x: anim(time, from, to - from, duration) 19 | }); 20 | }, 21 | 22 | onTimeEnd: callback 23 | }); 24 | }; 25 | 26 | exports.translateY = function(object, from, to, duration, callback) { 27 | return timeline.createTask({ 28 | start: 0, 29 | duration: duration, 30 | object: object, 31 | 32 | onTimeUpdate: function(time) { 33 | object.attr({ 34 | y: anim(time, from, to - from, duration) 35 | }); 36 | }, 37 | 38 | onTimeEnd: callback 39 | }); 40 | }; 41 | 42 | exports.scale = function(object, from, to, duration, callback) { 43 | return timeline.createTask({ 44 | start: 0, 45 | duration: duration, 46 | object: object, 47 | 48 | onTimeUpdate: function(time, zoom) { 49 | object.scale(zoom = anim(time, from, to - from, duration), zoom); 50 | }, 51 | 52 | onTimeEnd: callback 53 | }); 54 | }; 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /scripts/object/logo.js: -------------------------------------------------------------------------------- 1 | define("scripts/object/logo.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var layout = require("scripts/layout"); 6 | var translateY = require("scripts/animation").translateY; 7 | 8 | var homeMask, logo, ninja; 9 | var width = [0, 150, 240]; 10 | var height = [183, 126, 90]; 11 | 12 | var x = [0, 0, 0]; 13 | var y = [-183, -182, -140]; 14 | var y2 = [0, 10, 20]; 15 | 16 | function getPos() { 17 | width[0] = layout.width(); 18 | x[1] = layout.centerX(width[1]) - 125; 19 | x[2] = x[1] + 160; 20 | } 21 | 22 | function createImage(imageSrc, x, y, width, height) { 23 | return layer.createImage("default", imageSrc, x, y, width, height).hide(); 24 | } 25 | 26 | exports.set = function() { 27 | getPos(); 28 | homeMask = createImage("images/home-mask.png", x[0], y[0], width[0], height[0]); 29 | logo = createImage("images/logo.png", x[1], y[1], width[1], height[1]); 30 | ninja = createImage("images/ninja.png", x[2], y[2], width[2], height[2]); 31 | }; 32 | 33 | exports.show = function() { 34 | homeMask.show(); 35 | logo.show(); 36 | ninja.show(); 37 | translateY(homeMask, y[0], y2[0], 1000); 38 | translateY(logo, y[1], y2[1], 1000); 39 | translateY(ninja, y[2], y2[2], 1000); 40 | }; 41 | 42 | exports.hide = function() { 43 | translateY(homeMask, y2[0], y[0], 1000, homeMask.hide); 44 | translateY(logo, y2[1], y[1], 1000, logo.hide); 45 | translateY(ninja, y2[2], y[2], 1000, ninja.hide); 46 | }; 47 | 48 | exports.resize = function() { 49 | getPos(); 50 | homeMask.attr({width: width[0]}); 51 | logo.attr({x: x[1]}); 52 | ninja.attr({x: x[2]}); 53 | }; 54 | }); 55 | -------------------------------------------------------------------------------- /scripts/main.js: -------------------------------------------------------------------------------- 1 | define("scripts/main.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var scene = require("scripts/scene"); 5 | var layer = require("scripts/layer"); 6 | var soundManager = require("scripts/sound-manager"); 7 | var fruitManager = require("scripts/fruit-manager"); 8 | 9 | var imageList = [ 10 | "images/flash.png", 11 | "images/game-over.png", 12 | "images/home-mask.png", 13 | "images/logo.png", 14 | "images/mistake.png", 15 | "images/new-game.png", 16 | "images/ninja.png", 17 | "images/shadow.png", 18 | "images/x.png", 19 | "images/xf.png", 20 | "images/xx.png", 21 | "images/xxf.png", 22 | "images/xxx.png", 23 | "images/xxxf.png" 24 | ]; 25 | 26 | function preloadImages(callback) { 27 | for (var i = 0; i < imageList.length; i++) { 28 | layer.preloadImage(imageList[i], callback); 29 | } 30 | return imageList.length; 31 | } 32 | 33 | function preload(text, callback) { 34 | var info = "正在加载 %d/%d"; 35 | info += "\n请打开声音..."; 36 | 37 | var num = 0, count = 0; 38 | var onload = function() { 39 | num++; 40 | text.attr("text", info.replace("%d", num).replace("%d", count)); 41 | if (num >= count) { 42 | callback(); 43 | } 44 | }; 45 | 46 | count += fruitManager.preloadImages(onload); 47 | count += preloadImages(onload); 48 | } 49 | 50 | exports.start = function() { 51 | soundManager.init(); 52 | 53 | var text = layer.createText("default", "", 16, 20); 54 | preload(text, function() { 55 | setTimeout(function() { 56 | text.remove(); 57 | scene.init(); 58 | scene.switchScene("home-menu"); 59 | }, 1000); 60 | }); 61 | }; 62 | 63 | }); 64 | -------------------------------------------------------------------------------- /scripts/object/new-game.js: -------------------------------------------------------------------------------- 1 | define("scripts/object/new-game.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var rotation = require("scripts/rotation"); 6 | var layout = require("scripts/layout"); 7 | var fruitManager = require("scripts/fruit-manager"); 8 | 9 | var image, component 10 | var sideLength = 195; 11 | var imageX, imageY; 12 | 13 | var icon, iconWidth, iconHeight, iconX, iconY; 14 | 15 | function getImageXY() { 16 | imageX = layout.centerX(sideLength); 17 | imageY = layout.bottom(50, sideLength); 18 | } 19 | 20 | function getIconXY() { 21 | iconX = layout.centerX(); 22 | iconY = layout.bottom(50, iconHeight); 23 | } 24 | 25 | exports.setIcon = function(groupName, w, h, callback) { 26 | if (icon) 27 | return; 28 | iconWidth = w; 29 | iconHeight = h; 30 | getIconXY(); 31 | icon = fruitManager.create(groupName, iconX, iconY, true); 32 | icon.onSlice = function(fruit, angle) { 33 | icon.break(angle); 34 | icon = null; 35 | callback(); 36 | } 37 | }; 38 | 39 | exports.set = function() { 40 | getImageXY(); 41 | image = layer.createImage("default", "images/new-game.png", imageX, imageY, sideLength, sideLength).hide(); 42 | component = rotation.create(image); 43 | }; 44 | 45 | exports.show = function() { 46 | component.show(); 47 | if (icon) { 48 | icon.show(); 49 | } 50 | }; 51 | 52 | exports.hide = function() { 53 | component.hide(); 54 | }; 55 | 56 | exports.resize = function() { 57 | getImageXY(); 58 | image.attr({ 59 | x: imageX, 60 | y: imageY 61 | }); 62 | 63 | if (icon) { 64 | getIconXY(); 65 | icon.setPos(iconX, iconY); 66 | } 67 | }; 68 | 69 | }); 70 | -------------------------------------------------------------------------------- /scripts/tools.js: -------------------------------------------------------------------------------- 1 | define("scripts/tools.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | exports.unsetObject = function(object) { 5 | for (var i in object) 6 | if (object.hasOwnProperty(i) && typeof object[i] == "function") 7 | object[i] = function() {}; 8 | }; 9 | 10 | exports.getAngleByRadian = function(radian) { 11 | return radian * 180 / Math.PI; 12 | }; 13 | 14 | exports.pointToRadian = function(origin, point) { 15 | var PI = Math.PI; 16 | 17 | if (point[0] === origin[0]) { 18 | if (point[1] > origin[1]) 19 | return PI * 0.5; 20 | return PI * 1.5 21 | } else if (point[1] === origin[1]) { 22 | if (point[0] > origin[0]) 23 | return 0; 24 | return PI; 25 | } 26 | 27 | var t = Math.atan((origin[1] - point[1]) / (origin[0] - point[0])); 28 | 29 | if (point[0] > origin[0] && point[1] < origin[1]) 30 | return t + 2 * PI; 31 | 32 | if (point[0] > origin[0] && point[1] > origin[1]) 33 | return t; 34 | 35 | return t + PI; 36 | }; 37 | 38 | exports.randomNumber = function(num) { 39 | return Math.floor(Math.random() * num); 40 | }; 41 | 42 | exports.randomArray = function(arr) { 43 | arr = arr.slice(0); 44 | var ret = [], i = arr.length; 45 | while( i -- ) 46 | ret.push( arr.splice( exports.randomNumber( i + 1 ), 1 )[0] ); 47 | return ret; 48 | }; 49 | 50 | exports.addEvent = function(target, name, fn) { 51 | var call = function() { 52 | fn.apply(target, arguments); 53 | }; 54 | if (window.attachEvent) { 55 | target.attachEvent("on" + name, call); 56 | } else if (window.addEventListener) { 57 | target.addEventListener(name, call, false); 58 | } else { 59 | target["on" + name] = call; 60 | } 61 | return call; 62 | }; 63 | 64 | exports.delEvent = function(target, name, fn) { 65 | if (window.detachEvent) { 66 | target.detachEvent("on" + name, fn); 67 | } else if (window.removeEventListener) { 68 | target.removeEventListener(name, fn, false); 69 | } else if (target["on" + name] == fn) { 70 | target["on" + name] = null; 71 | } 72 | }; 73 | 74 | }); 75 | -------------------------------------------------------------------------------- /scripts/juice.js: -------------------------------------------------------------------------------- 1 | define("scripts/juice.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | /** 5 | * 果汁 6 | */ 7 | var tools = require("scripts/tools"); 8 | var layer = require("scripts/layer").getLayer("juice"); 9 | var timeline = require("scripts/timeline").use("juice").init(10); 10 | var tween = require("scripts/lib/tween"); 11 | 12 | var random = tools.randomNumber; 13 | var dur = 1500; 14 | var anim = tween.exponential.co; 15 | var dropAnim = tween.quadratic.co; 16 | var sin = Math.sin; 17 | var cos = Math.cos; 18 | 19 | var num = 10; 20 | var radius = 10; 21 | 22 | function ClassJuice(x, y, color) { 23 | this.x = x; 24 | this.y = y; 25 | this.color = color; 26 | 27 | this.distance = random(200) + 100; 28 | this.radius = radius; 29 | this.dir = random(360) * Math.PI / 180; 30 | } 31 | 32 | ClassJuice.prototype.render = function() { 33 | this.circle = layer.circle(this.x, this.y, this.radius).attr({ 34 | fill: this.color, 35 | stroke: "none" 36 | }); 37 | }; 38 | 39 | ClassJuice.prototype.sputter = function() { 40 | timeline.createTask({ 41 | start: 0, 42 | duration: dur, 43 | object: this, 44 | onTimeUpdate: this.onTimeUpdate, 45 | onTimeEnd: this.onTimeEnd 46 | }); 47 | }; 48 | 49 | ClassJuice.prototype.onTimeUpdate = function(time) { 50 | var distance, x, y, z; 51 | 52 | distance = anim(time, 0, this.distance, dur); 53 | x = this.x + distance * cos(this.dir); 54 | y = this.y + distance * sin(this.dir) + dropAnim(time, 0, 200, dur); 55 | z = anim(time, 1, -1, dur); 56 | 57 | this.circle.attr({ 58 | cx: x, 59 | cy: y 60 | }).scale(z, z); 61 | }; 62 | 63 | ClassJuice.prototype.onTimeEnd = function() { 64 | this.circle.remove(); 65 | tools.unsetObject(this); 66 | }; 67 | 68 | exports.create = function(x, y, color) { 69 | for (var i = 0; i < num; i++) 70 | this.createOne(x, y, color); 71 | }; 72 | 73 | exports.createOne = function(x, y, color) { 74 | if (!color) 75 | return; 76 | 77 | var juice = new ClassJuice(x, y, color); 78 | juice.render(); 79 | juice.sputter(); 80 | }; 81 | 82 | }); 83 | -------------------------------------------------------------------------------- /scripts/collision.js: -------------------------------------------------------------------------------- 1 | define("scripts/collision.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | /** 5 | * 碰撞检测 6 | */ 7 | 8 | exports.check = function(knife, fruit) { 9 | return lineInEllipse( 10 | knife.slice(0, 2), 11 | knife.slice(2, 4), 12 | [fruit.x, fruit.y], 13 | fruit.radius 14 | ); 15 | }; 16 | 17 | function sqr(x) { 18 | return x * x; 19 | } 20 | 21 | function sign(n) { 22 | return n < 0 ? -1 : (n > 0 ? 1 : 0); 23 | } 24 | 25 | function equation12(a, b, c) { 26 | if (a == 0) return; 27 | 28 | var delta = b * b - 4 * a * c; 29 | if (delta == 0) 30 | return [-1 * b / (2 * a), -1 * b / (2 * a)]; 31 | else if (delta > 0) 32 | return [(-1 * b + Math.sqrt(delta)) / (2 * a), (-1 * b - Math.sqrt(delta)) / (2 * a)]; 33 | } 34 | 35 | // 返回线段和椭圆的两个交点,如果不相交,返回 null 36 | function lineXEllipse(p1, p2, c, r, e) { 37 | // 线段:p1, p2 圆心:c 半径:r 离心率:e 38 | if (r <= 0) return; 39 | e = e === undefined ? 1 : e; 40 | var t1 = r, t2 = r * e, k, a, b; 41 | 42 | a = sqr(t2) * sqr(p1[0] - p2[0]) + sqr(t1) * sqr(p1[1] - p2[1]); 43 | 44 | if (a <= 0) return; 45 | 46 | b = 2 * sqr(t2) * (p2[0] - p1[0]) * (p1[0] - c[0]) + 2 * sqr(t1) * (p2[1] - p1[1]) * (p1[1] - c[1]); 47 | c = sqr(t2) * sqr(p1[0] - c[0]) + sqr(t1) * sqr(p1[1] - c[1]) - sqr(t1) * sqr(t2); 48 | 49 | if (!(k = equation12(a, b, c, t1, t2))) return; 50 | 51 | var result = [ 52 | [p1[0] + k[0] * (p2[0] - p1[0]), p1[1] + k[0] * (p2[1] - p1[1])], 53 | [p1[0] + k[1] * (p2[0] - p1[0]), p1[1] + k[1] * (p2[1] - p1[1])] 54 | ]; 55 | 56 | if (!((sign(result[0][0] - p1[0]) * sign(result[0][0] - p2[0]) <= 0) && 57 | (sign(result[0][1] - p1[1]) * sign(result[0][1] - p2[1]) <= 0))) 58 | result[0] = null; 59 | 60 | if (!((sign(result[1][0] - p1[0]) * sign(result[1][0] - p2[0]) <= 0) && 61 | (sign(result[1][1] - p1[1]) * sign(result[1][1] - p2[1]) <= 0))) 62 | result[1] = null; 63 | 64 | return result; 65 | } 66 | 67 | // 判断计算线段和椭圆是否相交 68 | function lineInEllipse(p1, p2, c, r, e) { 69 | var t = lineXEllipse(p1, p2, c, r, e); 70 | return t && (t[0] || t[1]); 71 | }; 72 | 73 | }); 74 | -------------------------------------------------------------------------------- /scripts/lib/tween.js: -------------------------------------------------------------------------------- 1 | define("scripts/lib/tween.js", function(exports, require, module){ 2 | "use strict"; 3 | 4 | exports.exponential = function(){}; 5 | exports.exponential.co = function(index, offset, target, framesNum){ return (index == framesNum) ? offset + target : target * (-Math.pow(2, -10 * index / framesNum) + 1) + offset; }; 6 | // exports.exponential.ci = function(index, offset, target, framesNum){ return (index == 0) ? offset : target * Math.pow(2, 10 * (index / framesNum - 1)) + offset; } 7 | 8 | exports.bounce = function(){}; 9 | exports.bounce.co = function(index, offset, target, framesNum){ if((index /= framesNum) < (1 / 2.75)) return target * (7.5625 * index * index) + offset; else if(index < (2 / 2.75)) return target * (7.5625 * (index -= (1.5 / 2.75)) * index + .75) + offset; else if(index < (2.5 / 2.75)) return target * (7.5625 * (index -= (2.25 / 2.75)) * index + .9375) + offset; else return target * (7.5625 * (index -= (2.625 / 2.75)) * index + .984375) + offset; }; 10 | 11 | exports.quadratic = function(){}; 12 | exports.quadratic.ci = function(index, offset, target, framesNum){ return target * (index /= framesNum) * index + offset; }; 13 | exports.quadratic.co = function(index, offset, target, framesNum){ return - target * (index /= framesNum) * (index - 2) + offset; } 14 | exports.quadratic.cio = function(index, offset, target, framesNum){ if((index /= framesNum / 2) < 1) return target / 2 * index * index + offset; else return - target / 2 * ((-- index) * (index - 2) - 1) + offset; }; 15 | 16 | exports.circular = function(index, offset, target, framesNum){ if((index /= framesNum / 2) < 1) return - target / 2 * (Math.sqrt(1 - index * index) - 1) + offset; else return target / 2 * (Math.sqrt(1 - (index -= 2) * index) + 1) + offset; } 17 | 18 | exports.linear = function(index, offset, target, framesNum){ return target * index / framesNum + offset; }; 19 | 20 | exports.back = function(){}; 21 | exports.back.ci = function(index, offset, target, framesNum, s){ s = 1.70158; return target * (index /= framesNum) * index * ((s + 1) * index - s) + offset; }; 22 | exports.back.co = function(index, offset, target, framesNum, s){ s = 1.70158; return target * ((index = index / framesNum - 1) * index * ((s + 1) * index + s) + 1) + offset; }; 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /scripts/knife.js: -------------------------------------------------------------------------------- 1 | define("scripts/knife.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var timeline = require("scripts/timeline"); 5 | var layer = require("scripts/layer").getLayer("knife"); 6 | 7 | /** 8 | * 刀光模块 9 | */ 10 | 11 | var lastX = null, lastY = null; 12 | var abs = Math.abs; 13 | 14 | var life = 200; 15 | var stroke = 10; 16 | var color = "#cbd3db"; 17 | var anims = []; 18 | var knifes = []; 19 | 20 | function ClassKnifePart(conf) { 21 | this.sx = conf.sx; 22 | this.sy = conf.sy; 23 | this.ex = conf.ex; 24 | this.ey = conf.ey; 25 | 26 | knifes.push(this); 27 | } 28 | 29 | ClassKnifePart.prototype.set = function() { 30 | var sx, sy, ex, ey, dx, dy, ax, ay; 31 | 32 | sx = this.sx; 33 | sy = this.sy; 34 | ex = this.ex; 35 | ey = this.ey; 36 | 37 | dx = sx - ex; 38 | dy = sy - ey; 39 | ax = abs(dx); 40 | ay = abs(dy); 41 | 42 | if (ax > ay) 43 | sx += dx < 0 ? -1 : 1, 44 | sy += dy < 0 ? -(1 * ay / ax) : 1 * ay / ax; 45 | else 46 | sx += dx < 0 ? -(1 * ax / ay) : 1 * ax / ay, 47 | sy += dy < 0 ? -1 : 1; 48 | 49 | this.line = layer.path("M" + sx + "," + sy + "L" + ex + "," + ey).attr({ 50 | "stroke": color, 51 | "stroke-width": stroke + "px" 52 | }); 53 | 54 | timeline.createTask({ 55 | start: 0, 56 | duration: life, 57 | object: this, 58 | onTimeUpdate: this.update, 59 | onTimeEnd: this.end, 60 | recycle: anims 61 | }); 62 | return this; 63 | }; 64 | 65 | ClassKnifePart.prototype.update = function(time) { 66 | this.line.attr("stroke-width", stroke * (1 - time / life) + "px"); 67 | }; 68 | 69 | ClassKnifePart.prototype.end = function() { 70 | this.line.remove(); 71 | 72 | var index; 73 | if (index = knifes.indexOf(this)) 74 | knifes.splice(index, 1); 75 | }; 76 | 77 | exports.newKnife = function() { 78 | lastX = lastY = null; 79 | }; 80 | 81 | exports.through = function(x, y) { 82 | var ret = null; 83 | if (lastX !== null && (lastX != x || lastY != y)) { 84 | new ClassKnifePart({ 85 | sx: lastX, 86 | sy: lastY, 87 | ex: x, 88 | ey: y 89 | }).set(); 90 | ret = [lastX, lastY, x, y]; 91 | } 92 | 93 | lastX = x; 94 | lastY = y; 95 | return ret; 96 | }; 97 | 98 | }); 99 | -------------------------------------------------------------------------------- /scripts/layer.js: -------------------------------------------------------------------------------- 1 | define("scripts/layer.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | /** 5 | * layer manager 6 | */ 7 | 8 | var Raphael = require("scripts/lib/raphael"); 9 | var layout = require("scripts/layout"); 10 | 11 | var layers = {}; 12 | var zIndexes = { 13 | "default": zi(), 14 | "light": zi(), 15 | "knife": zi(), 16 | "fruit": zi(), 17 | "juice": zi(), 18 | "flash": zi(), 19 | "mask": zi() 20 | }; 21 | 22 | 23 | var imageCache = {}; 24 | 25 | exports.preloadImage = function(src, callback) { 26 | var img = new Image(), canvas, ctx, error; 27 | //img.crossOrigin = "anonymous"; 28 | img.src = src; 29 | img.onload = function() { 30 | canvas = document.createElement('canvas'); 31 | canvas.height = img.naturalHeight; 32 | canvas.width = img.naturalWidth; 33 | ctx = canvas.getContext('2d'); 34 | ctx.drawImage(img, 0, 0); 35 | try { 36 | imageCache[src] = canvas.toDataURL(); 37 | } catch (e) { 38 | error = e; 39 | } 40 | callback(error); 41 | }; 42 | }; 43 | 44 | exports.replaceImage = function(image, src) { 45 | src = imageCache[src] || src; 46 | image.attr("src", src); 47 | }; 48 | 49 | exports.createImage = function(layer, src, x, y, w, h) { 50 | layer = this.getLayer(layer); 51 | src = imageCache[src] || src; 52 | return layer.image(src, x, y, w, h); 53 | }; 54 | 55 | exports.createText = function(layer, text, x, y, fill, size) { 56 | layer = this.getLayer(layer); 57 | 58 | return layer.text(x, y, text).attr({ 59 | fill: fill || "#fff", 60 | "font-size": size || "14px", 61 | "text-anchor": "start" 62 | }); 63 | }; 64 | 65 | exports.getLayer = function(name) { 66 | var p, layer; 67 | name = name || "default"; 68 | 69 | if (p = layers[name]) { 70 | return p; 71 | } else { 72 | layer = document.createElement("div"); 73 | layer.className = "layer"; 74 | layer.style.cssText = "z-index: " + (zIndexes[name] || 0) + ";"; 75 | 76 | document.getElementById("extra").appendChild(layer); 77 | p = layers[name] = Raphael(layer, layout.width(), layout.height()); 78 | return p; 79 | } 80 | }; 81 | 82 | function zi() { 83 | return zi.num = ++zi.num || 2; 84 | }; 85 | 86 | exports.resize = function() { 87 | for (var name in layers) { 88 | layers[name].setSize(layout.width(), layout.height()); 89 | } 90 | }; 91 | }); 92 | -------------------------------------------------------------------------------- /scripts/light.js: -------------------------------------------------------------------------------- 1 | define("scripts/light.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | /** 5 | * 炸弹爆炸时的光线 6 | */ 7 | 8 | var layer = require("scripts/layer"); 9 | 10 | var maskLayer = layer.getLayer("mask"); 11 | layer = layer.getLayer("light"); 12 | 13 | var tools = require("scripts/tools"); 14 | var timeline = require("scripts/timeline"); 15 | var layout = require("scripts/layout"); 16 | 17 | var random = tools.randomNumber; 18 | 19 | var pi = Math.PI; 20 | var sin = Math.sin; 21 | var cos = Math.cos; 22 | 23 | var lights = []; 24 | var indexes = []; 25 | var lightsNum = 10; 26 | 27 | for (var i = 0; i < lightsNum; i++) 28 | indexes[i] = i; 29 | 30 | function removeLights() { 31 | for (var i = 0, l = lights.length; i < l; i++) 32 | lights[i].remove(); 33 | lights.length = 0; 34 | } 35 | 36 | function build(x, y, r, color) { 37 | var l = layout.width() + layout.height(); 38 | var a1, a2, x1, y1, x2, y2; 39 | 40 | a1 = r * 36 + random(10); 41 | a2 = a1 + 5; 42 | 43 | a1 = pi * a1 / 180; 44 | a2 = pi * a2 / 180; 45 | 46 | x1 = x + l * cos(a1); 47 | y1 = y + l * sin(a1); 48 | 49 | x2 = x + l * cos(a2); 50 | y2 = y + l * sin(a2); 51 | 52 | var light = layer.path(["M", x, y, "L", x1, y1, "L", x2, y2, "Z"]).attr({ 53 | stroke: "none", 54 | fill: color 55 | }); 56 | 57 | lights.push(light); 58 | } 59 | 60 | exports.start = function(fruit, callback) { 61 | var x = fruit.x, 62 | y = fruit.y, 63 | time = 0, 64 | idx = tools.randomArray(indexes); 65 | 66 | var i = lightsNum, 67 | b = function() { 68 | build(x, y, idx[this], fruit.color); 69 | }; 70 | 71 | while (i--) 72 | setTimeout(b.bind(i), time += 100); 73 | 74 | setTimeout(function() { 75 | removeLights(); 76 | callback(); 77 | }, time + 100); 78 | }; 79 | 80 | exports.showWhiteLight = function(callback) { 81 | var dur = 4e3; 82 | var mask = maskLayer.rect(0, 0, layout.width(), layout.height()).attr({ 83 | fill: "#fff", 84 | stroke: "none" 85 | }); 86 | var control = { 87 | onTimeUpdate: function(time) { 88 | mask.attr("opacity", 1 - time / dur); 89 | }, 90 | 91 | onTimeEnd: function() { 92 | mask.remove(); 93 | if (callback) 94 | callback(); 95 | } 96 | }; 97 | 98 | timeline.createTask({ 99 | start: 0, 100 | duration: dur, 101 | object: control, 102 | onTimeUpdate: control.onTimeUpdate, 103 | onTimeEnd: control.onTimeEnd 104 | }); 105 | }; 106 | 107 | }); 108 | -------------------------------------------------------------------------------- /scripts/drag.js: -------------------------------------------------------------------------------- 1 | define("scripts/drag.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var tools = require("scripts/tools"); 5 | 6 | function getCoors(e) { 7 | var coors = []; 8 | if (e.targetTouches && e.targetTouches.length) { // iPhone 9 | var thisTouch = e.targetTouches[0]; 10 | coors[0] = thisTouch.clientX; 11 | coors[1] = thisTouch.clientY; 12 | } else { // all others 13 | coors[0] = e.clientX; 14 | coors[1] = e.clientY; 15 | } 16 | return coors; 17 | } 18 | 19 | function BasicDrag() { 20 | var isTouch = this.isTouch = "ontouchstart" in window; 21 | 22 | this.TOUCH_START = isTouch ? "touchstart" : "mousedown", 23 | this.TOUCH_MOVE = isTouch ? "touchmove" : "mousemove", 24 | this.TOUCH_END = isTouch ? "touchend" : "mouseup"; 25 | } 26 | 27 | BasicDrag.prototype.init = function(el) { 28 | this.element = el; 29 | tools.addEvent(el, this.TOUCH_START, function(e) { 30 | this.startDrag(getCoors(e)); 31 | e.cancelBubble = true; 32 | e.stopPropagation && e.stopPropagation(); 33 | return e.returnValue = false; 34 | }.bind(this)); 35 | }; 36 | 37 | //private 38 | BasicDrag.prototype.startDrag = function(coors) { 39 | var element = this.element; 40 | var draging = this.draging = {}; 41 | this.isDraging = true; 42 | 43 | draging.mouseX = coors[0]; 44 | draging.mouseY = coors[1]; 45 | 46 | this.registerDocumentEvent(); 47 | }; 48 | 49 | //private 50 | BasicDrag.prototype.endDrag = function() { 51 | this.isDraging = false; 52 | this.unRegisterDocumentEvent(); 53 | }; 54 | 55 | //private 56 | BasicDrag.prototype.registerDocumentEvent = function() { 57 | var draging = this.draging; 58 | 59 | draging.documentSelectStart = 60 | tools.addEvent(document, "selectstart", function(e) { 61 | e.stopPropagation && e.stopPropagation(); 62 | e.cancelBubble = true; 63 | return e.returnValue = false; 64 | }); 65 | 66 | draging.documentMouseMove = 67 | tools.addEvent(document, this.TOUCH_MOVE, function(e) { 68 | var coors = getCoors(e); 69 | draging.newMouseX = coors[0]; 70 | draging.newMouseY = coors[1]; 71 | e.stopPropagation && e.stopPropagation(); 72 | return e.returnValue = false; 73 | }.bind(this)); 74 | 75 | draging.documentMouseUp = 76 | tools.addEvent(document, this.TOUCH_END, function() { 77 | this.endDrag(); 78 | }.bind(this)); 79 | 80 | var lx, ly; 81 | 82 | clearInterval(draging.timer); 83 | draging.timer = setInterval(function() { 84 | var dx, dy; 85 | if (draging.newMouseX != lx && draging.newMouseY != ly) { 86 | lx = draging.newMouseX; 87 | ly = draging.newMouseY; 88 | dx = draging.newMouseX - draging.mouseX; 89 | dy = draging.newMouseY - draging.mouseY; 90 | this.returnValue(dx, dy, draging.newMouseX, draging.newMouseY); 91 | } 92 | }.bind(this), 10); 93 | }; 94 | 95 | //private 96 | BasicDrag.prototype.unRegisterDocumentEvent = function() { 97 | var draging = this.draging; 98 | tools.delEvent(document, this.TOUCH_MOVE, draging.documentMouseMove); 99 | tools.delEvent(document, this.TOUCH_END, draging.documentMouseUp); 100 | tools.delEvent(document, "selectstart", draging.documentSelectStart); 101 | clearInterval(draging.timer); 102 | }; 103 | 104 | //private 105 | BasicDrag.prototype.returnValue = function(dx, dy, x, y) { 106 | //todo something 107 | }; 108 | 109 | BasicDrag.prototype.on = function(name, fn) { 110 | var method = this[name]; 111 | if (!method) 112 | return; 113 | this[name] = function() { 114 | method.apply(this, arguments); 115 | fn.apply(this, arguments); 116 | }.bind(this); 117 | }; 118 | 119 | exports.create = function() { 120 | return new BasicDrag(); 121 | }; 122 | 123 | }); 124 | -------------------------------------------------------------------------------- /scripts/scene.js: -------------------------------------------------------------------------------- 1 | define("scripts/scene.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var soundManager = require("scripts/sound-manager"); 5 | var fruitManager = require("scripts/fruit-manager"); 6 | var drag = require("scripts/drag"); 7 | var knife = require("scripts/knife"); 8 | var layout = require("scripts/layout"); 9 | var layer = require("scripts/layer"); 10 | var tools = require("scripts/tools"); 11 | 12 | var background = require("scripts/object/background"); 13 | var logo = require("scripts/object/logo"); 14 | var newGame = require("scripts/object/new-game"); 15 | var score = require("scripts/object/score"); 16 | var mistake = require("scripts/object/mistake"); 17 | var gameOver = require("scripts/object/game-over"); 18 | 19 | var game = require("scripts/game"); 20 | 21 | var newGameIcon; 22 | var gameOverState; 23 | var curScene; 24 | 25 | var playButton; 26 | function showPlayButton(cb) { 27 | if (playButton) { 28 | setTimeout(cb, 2000); 29 | return; 30 | } 31 | playButton = document.getElementById("play-button"); 32 | playButton.style.display = "block"; 33 | tools.addEvent(playButton, "ontouchend" in window ? "touchend" : "click", function() { 34 | playButton.style.display = "none"; 35 | cb(); 36 | }); 37 | } 38 | 39 | function showNewGame() { 40 | newGame.setIcon("winnie", 96, 96, function(){ 41 | soundManager.play("winnie"); 42 | switchScene("game-body"); 43 | }); 44 | newGame.show(); 45 | } 46 | 47 | var _sceneHomeMenu = { 48 | enter: function() { 49 | logo.show(); 50 | showPlayButton(showNewGame); 51 | }, 52 | 53 | exit: function() { 54 | newGame.hide(); 55 | logo.hide(); 56 | } 57 | }; 58 | 59 | var _sceneGameBody = { 60 | enter: function() { 61 | score.show(); 62 | mistake.show(); 63 | game.start(function() { 64 | switchScene("game-over"); 65 | }); 66 | }, 67 | 68 | exit: function() {} 69 | }; 70 | 71 | var _sceneGameOver = { 72 | enter: function() { 73 | soundManager.play("gameover"); 74 | gameOver.show(); 75 | setTimeout(function() { 76 | gameOverState = true; 77 | }, 1000); 78 | }, 79 | 80 | exit: function() { 81 | gameOverState = false; 82 | score.hide(); 83 | mistake.hide(); 84 | gameOver.hide(); 85 | } 86 | }; 87 | 88 | var sceneList = { 89 | "home-menu": _sceneHomeMenu, 90 | "game-body": _sceneGameBody, 91 | "game-over": _sceneGameOver 92 | }; 93 | 94 | function switchScene(name, delay) { 95 | if (curScene === name) 96 | return; 97 | if (curScene) 98 | sceneList[curScene].exit(); 99 | curScene = name; 100 | 101 | if (delay) { 102 | setTimeout(sceneList[name].enter, delay); 103 | } else { 104 | sceneList[name].enter(); 105 | } 106 | } 107 | 108 | function bindDrag() { 109 | var dragger = drag.create(); 110 | 111 | var ret; 112 | dragger.on("returnValue", function(dx, dy, x, y) { 113 | if (ret = knife.through(x - layout.x(), y - layout.y())) 114 | fruitManager.checkCollision(ret); 115 | }); 116 | 117 | dragger.on("startDrag", function() { 118 | knife.newKnife(); 119 | }); 120 | 121 | dragger.init(document.documentElement); 122 | } 123 | 124 | var inited = false; 125 | function init() { 126 | if (inited) return; 127 | 128 | logo.set(); 129 | newGame.set(); 130 | mistake.set(); 131 | score.set(); 132 | gameOver.set(); 133 | 134 | bindDrag(); 135 | 136 | tools.addEvent(document, "ontouchend" in window ? "touchend" : "click", function() { 137 | if (gameOverState) 138 | switchScene("home-menu", 1000); 139 | }); 140 | 141 | resize(); 142 | inited = true; 143 | } 144 | 145 | function resize() { 146 | layer.resize(); 147 | background.resize(); 148 | if (inited) { 149 | logo.resize(); 150 | newGame.resize(); 151 | mistake.resize(); 152 | score.resize(); 153 | gameOver.resize(); 154 | } 155 | } 156 | 157 | background.set(); 158 | tools.addEvent(window, "resize", resize); 159 | 160 | exports.init = init; 161 | exports.switchScene = switchScene; 162 | 163 | }); 164 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 切包子ÏÏ 15 | 109 | 110 | 111 |
112 |
113 |
114 | 117 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 157 | 158 | -------------------------------------------------------------------------------- /scripts/fruit-manager.js: -------------------------------------------------------------------------------- 1 | define("scripts/fruit-manager.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var fruit = require("scripts/fruit"); 6 | var collision = require("scripts/collision"); 7 | var tools = require("scripts/tools"); 8 | var random = tools.randomNumber; 9 | var getAngleByRadian = tools.getAngleByRadian; 10 | var pointToRadian = tools.pointToRadian; 11 | 12 | var groups = { 13 | "frog": [ 14 | {img: "f1", width: 96, height: 96, radius: 36, fixAngle: 5}, 15 | {img: "f2", width: 96, height: 96, radius: 36, fixAngle: 5}, 16 | {img: "f3", width: 96, height: 96, radius: 36, fixAngle: -25}, 17 | {img: "f4", width: 96, height: 96, radius: 36, fixAngle: -25}, 18 | {img: "f5", width: 96, height: 96, radius: 36, fixAngle: -45}, 19 | {img: "f6", width: 96, height: 96, radius: 36, fixAngle: -45} 20 | ], 21 | 22 | "bun": [ 23 | {img: "b1", width: 64, height: 64, radius: 32, fixAngle: -45, color: "#e6c731"}, 24 | {img: "b2", width: 64, height: 64, radius: 32, fixAngle: -85, color: "#e6c731"}, 25 | {img: "b3", width: 64, height: 64, radius: 32, fixAngle: -5, color: "#e6c731"}, 26 | {img: "b4", width: 64, height: 64, radius: 32, fixAngle: -95, color: "#e6c731"} 27 | ], 28 | 29 | "winnie": [ 30 | {img: "w1", width: 96, height: 96, radius: 36, fixAngle: 180}, 31 | {img: "w2", width: 96, height: 96, radius: 36, fixAngle: 180}, 32 | {img: "w3", width: 96, height: 96, radius: 36, fixAngle: 180} 33 | ], 34 | 35 | "gesar": [ 36 | {img: "gesar", width: 68, height: 96, radius: 36, isBomb: true, isStatic: true, color: "#c8e925"} 37 | ], 38 | 39 | "basiclaw": [ 40 | {img: "basiclaw", width: 66, height: 96, radius: 36, isBomb: true, isStatic: true, color: "#ffe155"} 41 | ], 42 | 43 | "shakespeare": [ 44 | {img: "s1", width: 66, height: 96, radius: 36, isBomb: true, isStatic: true, color: "#ea5519"}, 45 | {img: "s2", width: 72, height: 100, radius: 38, isBomb: true, isStatic: true, color: "#ea5519"} 46 | ], 47 | 48 | "ferrari": [ 49 | {img: "ferrari", width: 192, height: 192, radius: 96, isBomb: true, isStatic: true, color: "#cc453b"} 50 | ], 51 | 52 | "fault": [ 53 | {img: "zy", width: 100, height: 100, radius: 50, isBomb: true, isStatic: true} 54 | ] 55 | 56 | }; 57 | 58 | var collisionList = [], pendingRemoveList = []; 59 | 60 | function removeFromList(fruit) { 61 | var index = collisionList.indexOf(fruit); 62 | if (index > -1) { 63 | collisionList.splice(index, 1); 64 | } 65 | } 66 | 67 | exports.create = function(groupName, x, y, hide) { 68 | var group = groups[groupName]; 69 | var len = group.length; 70 | var info = len == 1 ? group[0] : group[random(len)]; 71 | var f = fruit.create(x, y, info, hide); 72 | f.groupName = groupName; 73 | collisionList.unshift(f); 74 | return f; 75 | }; 76 | 77 | exports.throw = function(groupName, x, y) { 78 | var fruit = exports.create(groupName, x, y); 79 | fruit.throw(function() { 80 | removeFromList(fruit); 81 | if (fruit.onFallOff) 82 | fruit.onFallOff(fruit); 83 | }); 84 | return fruit; 85 | }; 86 | 87 | exports.checkCollision = function(knife) { 88 | var angle; 89 | collisionList.forEach(function(fruit) { 90 | if (!collision.check(knife, fruit)) 91 | return; 92 | angle = getAngleByRadian(pointToRadian(knife.slice(0, 2), knife.slice(2, 4))); 93 | removeFromList(fruit); 94 | if (fruit.onSlice) 95 | fruit.onSlice(fruit, angle); 96 | }); 97 | }; 98 | 99 | exports.stopAll = function() { 100 | while (collisionList.length) { 101 | collisionList[0].stop(); 102 | pendingRemoveList.unshift(collisionList.shift()); 103 | } 104 | }; 105 | 106 | exports.removeAll = function() { 107 | while (pendingRemoveList.length) { 108 | pendingRemoveList[0].remove(); 109 | pendingRemoveList.shift(); 110 | } 111 | }; 112 | 113 | exports.count = function() { 114 | return collisionList.length; 115 | }; 116 | 117 | 118 | function preloadImage(name, callback) { 119 | var src = "images/fruit/" + name + ".png"; 120 | layer.preloadImage(src, callback); 121 | return 1; 122 | } 123 | 124 | function preloadGroupImage(arr, callback) { 125 | var info, imgName, count = 0; 126 | for (var i = 0; i < arr.length; i++) { 127 | info = arr[i]; 128 | imgName = info.img; 129 | count += preloadImage(imgName, callback); 130 | if (!info.isBomb) { 131 | count += preloadImage(imgName + "-1", callback); 132 | count += preloadImage(imgName + "-2", callback); 133 | } 134 | } 135 | return count; 136 | } 137 | 138 | exports.preloadImages = function(callback) { 139 | var count = 0; 140 | for (var groupName in groups) { 141 | count += preloadGroupImage(groups[groupName], callback) 142 | } 143 | return count; 144 | }; 145 | 146 | }); 147 | -------------------------------------------------------------------------------- /scripts/game.js: -------------------------------------------------------------------------------- 1 | define("scripts/game.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | /** 5 | * game logic 6 | */ 7 | var soundManager = require("scripts/sound-manager"); 8 | var fruitManager = require("scripts/fruit-manager"); 9 | var score = require("scripts/object/score"); 10 | var mistake = require("scripts/object/mistake"); 11 | var background = require("scripts/object/background"); 12 | var light = require("scripts/light"); 13 | var layout = require("scripts/layout"); 14 | var random = require("scripts/tools").randomNumber; 15 | 16 | var gameInterval; 17 | var onGameOver; 18 | 19 | var scoreNumber; 20 | var mistakeNumber; 21 | var mistakeLimit; 22 | var gameOver; 23 | 24 | function reset() { 25 | scoreNumber = 0; 26 | mistakeNumber = 0; 27 | mistakeLimit = 3; 28 | gameOver = false; 29 | } 30 | 31 | function end() { 32 | if (gameOver) 33 | return; 34 | gameOver = true; 35 | 36 | clearInterval(gameInterval); 37 | gameInterval = null; 38 | 39 | setTimeout(onGameOver, 1000); 40 | } 41 | 42 | function explode(fruit) { 43 | if (gameOver) 44 | return; 45 | gameOver = true; 46 | 47 | clearInterval(gameInterval); 48 | gameInterval = null; 49 | 50 | fruitManager.stopAll(); 51 | background.wobble(); 52 | fruit.break(0, function() { 53 | fruitManager.removeAll(); 54 | background.stop(); 55 | light.showWhiteLight(onGameOver); 56 | }); 57 | } 58 | 59 | function addScore(n) { 60 | scoreNumber += n; 61 | score.number(scoreNumber); 62 | } 63 | 64 | function addMistake(x, y) { 65 | mistake.showAt(x, y); 66 | mistake.add(); 67 | mistakeNumber++; 68 | if (mistakeNumber >= mistakeLimit) { 69 | end(); 70 | } 71 | } 72 | 73 | function subtractMistake() { 74 | if (mistakeNumber > 0) { 75 | mistake.subtract(); 76 | mistakeNumber--; 77 | 78 | } else if (mistakeLimit < 30) { 79 | mistake.addLimit(); 80 | mistakeLimit++; 81 | 82 | } else { 83 | addScore(301); 84 | } 85 | } 86 | 87 | function addMistakeLimit() { 88 | if (mistakeLimit < 30) { 89 | mistake.addLimit(); 90 | mistakeLimit++; 91 | 92 | } else if (mistakeNumber > 0) { 93 | mistake.subtract(); 94 | mistakeNumber--; 95 | 96 | } else { 97 | addScore(301); 98 | } 99 | } 100 | 101 | function subtractMistakeLimit() { 102 | mistake.subtractLimit(); 103 | mistakeLimit--; 104 | if (mistakeNumber >= mistakeLimit) { 105 | end(); 106 | } 107 | } 108 | 109 | function throwFruit(group, num) { 110 | var startX = random(layout.width()), 111 | startY = layout.height() + 120; 112 | var fruit = fruitManager.throw(group, startX, startY); 113 | fruit.onSlice = onSlice; 114 | fruit.onFallOff = onFallOff; 115 | 116 | if (num && num > 1) { 117 | num--; 118 | throwFruit(group, num); 119 | } 120 | } 121 | 122 | function onFallOff(fruit) { 123 | if (gameOver) 124 | return; 125 | 126 | if (fruit.groupName != "bun") 127 | return; 128 | addMistake(fruit.x); 129 | } 130 | 131 | function onSlice(fruit, angle) { 132 | if (gameOver) 133 | return; 134 | 135 | soundManager.play(fruit.groupName); 136 | switch (fruit.groupName) { 137 | case "fault": 138 | explode(fruit); 139 | return; 140 | 141 | case "bun": 142 | addScore(1); 143 | break; 144 | 145 | case "frog": 146 | addScore(89); 147 | addMistake(fruit.x, fruit.y); 148 | break; 149 | 150 | case "winnie": 151 | addScore(64); 152 | break; 153 | 154 | case "gesar": 155 | throwFruit("winnie", 2); 156 | throwFruit("frog", 2); 157 | throwFruit("bun", 4); 158 | break; 159 | 160 | case "basiclaw": 161 | addMistakeLimit(); 162 | break; 163 | 164 | case "ferrari": 165 | subtractMistake(); 166 | break; 167 | 168 | case "shakespeare": 169 | subtractMistakeLimit(); 170 | break; 171 | } 172 | 173 | fruit.break(angle); 174 | } 175 | 176 | function gameLogic() { 177 | var group = "bun", num = 1; 178 | var r = random(10000); 179 | 180 | if (r < 500) { 181 | // 5% 182 | group = "fault"; 183 | 184 | } else if (r < 1000) { 185 | // 5% 186 | group = "basiclaw"; 187 | 188 | } else if (r < 1500) { 189 | // 5% 190 | group = "ferrari"; 191 | 192 | } else if (r < 2000) { 193 | // 5% 194 | group = "gesar"; 195 | 196 | } else if (r < 2500) { 197 | // 5% 198 | group = "winnie"; 199 | 200 | } else if (r < 3000) { 201 | // 5% 202 | group = "shakespeare"; 203 | 204 | } else if (r < 6500) { 205 | // 35% 206 | group = "frog"; 207 | 208 | } else { 209 | // 35% 210 | num += random(2); 211 | } 212 | 213 | throwFruit(group, num); 214 | } 215 | 216 | exports.start = function(callback) { 217 | if (gameInterval) 218 | return; 219 | reset(); 220 | onGameOver = callback; 221 | setTimeout(function() { 222 | gameInterval = setInterval(gameLogic, 1000); 223 | }, 500); 224 | }; 225 | 226 | }); 227 | -------------------------------------------------------------------------------- /scripts/object/mistake.js: -------------------------------------------------------------------------------- 1 | define("scripts/object/mistake.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var tween = require("scripts/lib/tween"); 6 | var timeline = require("scripts/timeline"); 7 | var layout = require("scripts/layout"); 8 | var random = require("scripts/tools").randomNumber; 9 | 10 | function getImageSrc(size, checked) { 11 | return "images/" + size + (checked ? "f.png" : ".png"); 12 | } 13 | 14 | function ClassMistake(x, y, w, h, size, checked) { 15 | this.size = size || "x"; 16 | this.checked = !!checked; 17 | this.x = x; 18 | this.y = y; 19 | this.width = w; 20 | this.height = h; 21 | this.image = layer.createImage("default", getImageSrc(this.size, this.checked), x, y, w, h).hide(); 22 | } 23 | 24 | ClassMistake.prototype.show = function() { 25 | this.image.show(); 26 | }; 27 | 28 | ClassMistake.prototype.hide = function() { 29 | this.image.hide(); 30 | }; 31 | 32 | ClassMistake.prototype.check = function() { 33 | this.checked = true; 34 | layer.replaceImage(this.image, getImageSrc(this.size, this.checked)); 35 | }; 36 | 37 | ClassMistake.prototype.uncheck = function() { 38 | this.checked = false; 39 | layer.replaceImage(this.image, getImageSrc(this.size, this.checked)); 40 | }; 41 | 42 | var mistakes = []; 43 | var number = 0, limit = 3, count = 30; 44 | 45 | function setPos() { 46 | var x = layout.width() - 1, y = 6; 47 | var width = 31, height = 32; 48 | x -= width; 49 | mistakes[0].image.attr({x: x, y: y}); 50 | 51 | width = 27, height = 26; 52 | x -= width, y = 5; 53 | mistakes[1].image.attr({x: x, y: y}); 54 | 55 | width = 22, height = 19; 56 | x -= width; 57 | mistakes[2].image.attr({x: x, y: y}); 58 | 59 | var a = [-2, -1, 0, 1, 2]; 60 | for (var i = 3; i < count; i++) { 61 | x -= width; 62 | y += a[random(a.length)]; 63 | if (y < 0) y = 0; 64 | mistakes[i].image.attr({x: x, y: y}); 65 | } 66 | } 67 | 68 | exports.set = function() { 69 | var width = 31, height = 32, x = 0, y = 0; 70 | mistakes.push(new ClassMistake(x, y, width, height, "xxx")); 71 | 72 | width = 27, height = 26; 73 | mistakes.push(new ClassMistake(x, y, width, height, "xx")); 74 | 75 | width = 22, height = 19; 76 | mistakes.push(new ClassMistake(x, y, width, height, "x")); 77 | 78 | for (var i = 3; i < count; i++) { 79 | mistakes.push(new ClassMistake(x, y, width, height)); 80 | } 81 | setPos(); 82 | }; 83 | 84 | function reset() { 85 | number = 0, limit = 3; 86 | for (var i = 0; i < mistakes.length; i++) { 87 | mistakes[i].uncheck(); 88 | } 89 | } 90 | 91 | exports.show = function() { 92 | reset(); 93 | for (var i = 0; i < limit; i++) 94 | mistakes[i].show(); 95 | }; 96 | 97 | exports.hide = function() { 98 | for (var i = 0; i < mistakes.length; i++) { 99 | mistakes[i].hide(); 100 | } 101 | }; 102 | 103 | exports.add = function() { 104 | number++; 105 | if (number > limit) { 106 | number = limit; 107 | return; 108 | } 109 | 110 | mistakes[limit - number].check(); 111 | }; 112 | 113 | exports.subtract = function() { 114 | number--; 115 | if (number < 0) { 116 | number = 0; 117 | return; 118 | } 119 | 120 | mistakes[limit - 1 - number].uncheck(); 121 | }; 122 | 123 | exports.addLimit = function() { 124 | limit++; 125 | if (limit > mistakes.length) { 126 | limit = mistakes.length; 127 | return; 128 | } 129 | 130 | mistakes[limit - 1].show(); 131 | if (number) { 132 | mistakes[limit - 1].check(); 133 | mistakes[limit - 1 - number].uncheck(); 134 | } 135 | }; 136 | 137 | exports.subtractLimit = function() { 138 | limit--; 139 | if (limit < number) { 140 | limit = number; 141 | return; 142 | } 143 | 144 | mistakes[limit].hide(); 145 | if (number) { 146 | mistakes[limit].uncheck(); 147 | mistakes[limit - number].check(); 148 | } 149 | }; 150 | 151 | exports.resize = function() { 152 | setPos(); 153 | }; 154 | 155 | exports.showAt = function(x, y) { 156 | if (y === undefined) 157 | y = layout.height(); 158 | 159 | var image = layer.createImage("default", "images/mistake.png", x - 27, y - 74, 54, 50).scale(1e-5, 1e-5); 160 | var duration = 500; 161 | 162 | var control = { 163 | show: function(start) { 164 | timeline.createTask({ 165 | start: start, 166 | duration: duration, 167 | data: [tween.back.co, 1e-5, 1], 168 | object: this, 169 | onTimeUpdate: this.onScaling, 170 | onTimeEnd: this.onShowEnd 171 | }); 172 | }, 173 | 174 | hide: function(start) { 175 | timeline.createTask({ 176 | start: start, 177 | duration: duration, 178 | data: [tween.back.ci, 1, 1e-5], 179 | object: this, 180 | onTimeUpdate: this.onScaling, 181 | onTimeEnd: this.onHideEnd 182 | }); 183 | }, 184 | 185 | onScaling: function(time, anim, a, b, z) { 186 | image.scale(z = anim(time, a, b - a, duration), z); 187 | }, 188 | 189 | onShowEnd: function() { 190 | this.hide(1500); 191 | }, 192 | 193 | onHideEnd: function() { 194 | image.remove(); 195 | } 196 | }; 197 | 198 | control.show(200); 199 | }; 200 | 201 | }); 202 | -------------------------------------------------------------------------------- /scripts/timeline.js: -------------------------------------------------------------------------------- 1 | define("scripts/timeline.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | /** 5 | * a easy timeline manager 6 | * @version 1.0 7 | * @author dron 8 | */ 9 | 10 | var timerCache = {}; 11 | 12 | // var timer = timeline; 13 | // 14 | // var timer = timeline.use( name ).init( 10 ); // to use a new timeline instance 15 | // 16 | // var t = timer.createTask(...); 17 | // t.stop(); 18 | // 19 | // timer.getFPS(); 20 | 21 | function ClassTimer() { 22 | this.tasks = []; 23 | this.addingTasks = []; 24 | this.adding = 0; 25 | } 26 | 27 | /** 28 | * initialize timeline 29 | */ 30 | ClassTimer.prototype.init = function(ms) { 31 | var me = this; 32 | 33 | if (me.inited) { 34 | return; 35 | } 36 | 37 | me.inited = 1; 38 | 39 | me.startTime = now(); 40 | me.intervalTime = ms || 5; 41 | me.count = 0; 42 | 43 | me.intervalFn = function() { 44 | me.count++; 45 | me.update(now()); 46 | }; 47 | 48 | me.start(); 49 | 50 | return me; 51 | }; 52 | 53 | 54 | /** 55 | * create a task 56 | * @param {Object} conf the config 57 | * @return {Task} a task instance 58 | */ 59 | ClassTimer.prototype.createTask = function(conf) { 60 | /* e.g. timer.createTask({ 61 | start: 500, duration: 2000, data: [a, b, c,..], object: module, 62 | onTimeUpdate: fn(time, a, b, c,..), onTimeStart: fn(a, b, c,..), onTimeEnd: fn(a, b, c,..), 63 | recycle: [] 64 | }); */ 65 | var task = createTask(conf); 66 | this.addingTasks.unshift(task); 67 | this.adding = 1; 68 | 69 | if (conf.recycle) 70 | this.taskList(conf.recycle, task); 71 | 72 | this.start(); 73 | 74 | return task; 75 | }; 76 | 77 | /** 78 | * use an array to recycle the task 79 | * @param {Array} queue be used for recycling task 80 | * @param {Task} task a task instance 81 | * @return {Array} this queue 82 | */ 83 | ClassTimer.prototype.taskList = function(queue, task) { 84 | if (!queue.clear) 85 | queue.clear = function() { 86 | var i = this.length; 87 | while (i--) { 88 | task = this[i]; 89 | task.stop(); 90 | this.splice(i, 1); 91 | } 92 | return this; 93 | }; 94 | 95 | if (task) 96 | queue.unshift(task); 97 | 98 | return queue; 99 | }; 100 | 101 | /** 102 | * get the current fps 103 | * @return {Number} fps number 104 | */ 105 | ClassTimer.prototype.getFPS = function() { 106 | var t = now(), 107 | c = this.count, 108 | fps = c / (t - this.startTime) * 1e3; 109 | if (c > 1e3) 110 | this.count = 0, 111 | this.startTime = t; 112 | return fps; 113 | }; 114 | 115 | // privates 116 | 117 | ClassTimer.prototype.start = function() { 118 | clearInterval(this.interval); 119 | this.interval = setInterval(this.intervalFn, this.intervalTime); 120 | }; 121 | 122 | ClassTimer.prototype.stop = function() { 123 | clearInterval(this.interval); 124 | }; 125 | 126 | ClassTimer.prototype.update = function(time) { 127 | var tasks = this.tasks, 128 | addingTasks = this.addingTasks, 129 | adding = this.adding; 130 | var i = tasks.length, 131 | t, task, start, duration, data; 132 | 133 | while (i--) { 134 | task = tasks[i]; 135 | start = task.start; 136 | duration = task.duration; 137 | 138 | if (time >= start) { 139 | 140 | if (task.stopped) { 141 | tasks.splice(i, 1); 142 | continue; 143 | } 144 | 145 | checkStartTask(task); 146 | if ((t = time - start) < duration) 147 | updateTask(task, t); 148 | else 149 | updateTask(task, duration), 150 | task.onTimeEnd.apply(task.object, task.data.slice(1)), 151 | tasks.splice(i, 1); 152 | } 153 | } 154 | 155 | if (adding) 156 | tasks.unshift.apply(tasks, addingTasks), 157 | addingTasks.length = adding = 0; 158 | 159 | if (!tasks.length) 160 | this.stop(); 161 | }; 162 | 163 | function use(name) { 164 | var module; 165 | 166 | if (module = timerCache[name]) 167 | return module; 168 | else 169 | module = timerCache[name] = new ClassTimer; 170 | 171 | return module; 172 | }; 173 | 174 | /** 175 | * @functions 176 | */ 177 | 178 | var now = function() { 179 | return new Date().getTime(); 180 | }; 181 | 182 | var createTask = function(conf) { 183 | var object = conf.object || {}; 184 | conf.start = conf.start || 0; 185 | return { 186 | start: conf.start + now(), 187 | duration: conf.duration == -1 ? 86400000 : conf.duration, 188 | data: conf.data ? [0].concat(conf.data) : [0], 189 | started: 0, 190 | object: object, 191 | onTimeStart: conf.onTimeStart || object.onTimeStart || function() {}, 192 | onTimeUpdate: conf.onTimeUpdate || object.onTimeUpdate || function() {}, 193 | onTimeEnd: conf.onTimeEnd || object.onTimeEnd || function() {}, 194 | stop: function() { 195 | this.stopped = 1; 196 | } 197 | } 198 | }; 199 | 200 | var updateTask = function(task, time) { 201 | var data = task.data; 202 | data[0] = time; 203 | task.onTimeUpdate.apply(task.object, data); 204 | }; 205 | 206 | var checkStartTask = function(task) { 207 | if (!task.started) 208 | task.started = 1, 209 | task.onTimeStart.apply(task.object, task.data.slice(1)), 210 | updateTask(task, 0); 211 | }; 212 | 213 | module.exports = use("default").init(10); 214 | module.exports.use = use; 215 | 216 | }); 217 | -------------------------------------------------------------------------------- /scripts/fruit.js: -------------------------------------------------------------------------------- 1 | define("scripts/fruit.js", function(exports, require, module) { 2 | "use strict"; 3 | 4 | var layer = require("scripts/layer"); 5 | var tools = require("scripts/tools"); 6 | var timeline = require("scripts/timeline").use("fruit").init(1); 7 | var timeline2 = require("scripts/timeline").use("fruit-apart").init(1); 8 | var tween = require("scripts/lib/tween"); 9 | var juice = require("scripts/juice"); 10 | var flash = require("scripts/flash"); 11 | var light = require("scripts/light"); 12 | var layout = require("scripts/layout"); 13 | 14 | /** 15 | * 水果模块模型 16 | */ 17 | 18 | var zoomAnim = tween.exponential.co; 19 | var linearAnim = tween.linear; 20 | var dropAnim = tween.quadratic.ci; 21 | var fallOffAnim = tween.quadratic.co; 22 | 23 | var random = tools.randomNumber; 24 | var min = Math.min; 25 | var average = function(a, b) { 26 | return ((a + b) / 2) >> 0; 27 | }; 28 | var sign = [-1, 1]; 29 | 30 | var dropXScope = 200, 31 | shadowPos = 50; 32 | 33 | function ClassFruit(x, y, info, hide) { 34 | this.x = x; 35 | this.y = y; 36 | 37 | this.img = info.img; 38 | this.width = info.width; 39 | this.height = info.height; 40 | this.radius = info.radius; 41 | this.fixAngle = info.fixAngle || 0; 42 | this.isStatic = info.isStatic; 43 | this.isBomb = info.isBomb; 44 | this.color = info.color; 45 | if (this.color === undefined) 46 | this.color = this.isBomb ? "#fff" : "#c00"; 47 | this.dropTime = info.dropTime || 1000; 48 | 49 | this.anims = []; 50 | 51 | var imgSrc = "images/fruit/" + this.img + ".png"; 52 | x = this.x - (this.width >> 1); 53 | y = this.y - (this.height >> 1); 54 | this.shadow = layer.createImage("fruit", "images/shadow.png", x, y + shadowPos, 106, 77); 55 | this.image = layer.createImage("fruit", imgSrc, x, y, this.width, this.height); 56 | 57 | if (hide) { 58 | this.image.hide(); 59 | this.shadow.hide(); 60 | } 61 | } 62 | 63 | ClassFruit.prototype.show = function() { 64 | timeline.createTask({ 65 | start: 0, 66 | duration: 500, 67 | object: this, 68 | onTimeStart: function() { 69 | this.image.scale(1e-5, 1e-5); 70 | this.image.show(); 71 | }, 72 | onTimeUpdate: function(time, z) { 73 | this.image.scale(z = zoomAnim(time, 1e-5, 1 - 1e-5, 500), z); 74 | }, 75 | recycle: this.anims 76 | }); 77 | }; 78 | 79 | ClassFruit.prototype.setPos = function(x, y) { 80 | if (x === this.x && y === this.y) 81 | return; 82 | 83 | this.x = x; 84 | this.y = y; 85 | 86 | this.image.attr({ 87 | x: x -= (this.width >> 1), 88 | y: y -= (this.height >> 1) 89 | }); 90 | this.shadow.attr({ 91 | x: x, 92 | y: y + shadowPos 93 | }); 94 | 95 | }; 96 | 97 | ClassFruit.prototype.rotate = function(speed) { 98 | this.rotateAnim = timeline.createTask({ 99 | start: 0, 100 | duration: -1, 101 | object: this, 102 | onTimeUpdate: function(time) { 103 | this.image.rotate((speed * time / 1e3) % 360, true); 104 | }, 105 | recycle: this.anims 106 | }); 107 | }; 108 | 109 | ClassFruit.prototype.break = function(angle, callback) { 110 | if (this.isBroken) 111 | return; 112 | this.isBroken = true; 113 | 114 | if (!this.isBomb) { 115 | flash.showAt(this.x, this.y, angle); 116 | juice.create(this.x, this.y, this.color); 117 | this._split(angle, callback); 118 | } else { 119 | this._explode(callback); 120 | } 121 | }; 122 | 123 | // private 124 | ClassFruit.prototype._split = function(angle, callback) { 125 | this.anims.clear(); 126 | this.image.hide(); 127 | this.shadow.hide(); 128 | 129 | var dropTime = this.dropTime; 130 | var startX = this.x; 131 | var startY = this.y; 132 | var targetX1 = -(random(dropXScope) + 75); 133 | var targetY1 = layout.height() + 120; 134 | var targetX2 = random(dropXScope + 75); 135 | var targetY2 = targetY1; 136 | 137 | var bImage1RotateAngle = -random(150) - 50; 138 | var bImage2RotateAngle = random(150) + 50; 139 | 140 | var imgSrc1 = "images/fruit/" + this.img + "-1.png"; 141 | var imgSrc2 = "images/fruit/" + this.img + "-2.png"; 142 | 143 | angle = ((angle % 180) + 360 + this.fixAngle) % 360; 144 | 145 | var x = startX - (this.width >> 1); 146 | var y = startY - (this.height >> 1); 147 | this.bImage1 = layer.createImage("fruit", imgSrc1, x, y, this.width, this.height); 148 | this.bImage2 = layer.createImage("fruit", imgSrc2, x, y, this.width, this.height); 149 | 150 | this.bImage1.rotate(angle); 151 | this.bImage2.rotate(angle); 152 | 153 | timeline2.createTask({ 154 | start: 0, 155 | duration: dropTime, 156 | object: this, 157 | 158 | onTimeUpdate: function(time) { 159 | this.bImage1.attr({ 160 | x: linearAnim(time, x, targetX1, dropTime), 161 | y: dropAnim(time, y, targetY1 - y, dropTime) 162 | }).rotate(linearAnim(time, angle, bImage1RotateAngle, dropTime), true); 163 | 164 | this.bImage2.attr({ 165 | x: linearAnim(time, x, targetX2, dropTime), 166 | y: dropAnim(time, y, targetY2 - y, dropTime) 167 | }).rotate(linearAnim(time, angle, bImage2RotateAngle, dropTime), true); 168 | }, 169 | 170 | onTimeEnd: function() { 171 | if (callback) 172 | callback(); 173 | this.remove(); 174 | }, 175 | recycle: this.anims 176 | }); 177 | }; 178 | 179 | // private 180 | ClassFruit.prototype._explode = function(callback) { 181 | this.anims.clear(); 182 | var fruit = this; 183 | light.start(fruit, function() { 184 | if (callback) 185 | callback(); 186 | fruit.remove(); 187 | }); 188 | }; 189 | 190 | ClassFruit.prototype.stop = function() { 191 | if (this.isBroken) 192 | return; 193 | this.anims.clear(); 194 | }; 195 | 196 | ClassFruit.prototype.throw = function(callback) { 197 | var fallTargetX = random(layout.width()); 198 | var fallTargetY = layout.height() + 120; 199 | 200 | var dropTime = this.dropTime; 201 | var startX = this.x; 202 | var startY = this.y; 203 | var endX = average(startX, fallTargetX); 204 | var endY = min(startY - random(startY - 100), 100); 205 | 206 | timeline.createTask({ 207 | start: 0, 208 | duration: dropTime, 209 | object: this, 210 | onTimeUpdate: function(time) { 211 | this.setPos( 212 | linearAnim(time, startX, endX - startX, dropTime), 213 | fallOffAnim(time, startY, endY - startY, dropTime) 214 | ); 215 | }, 216 | onTimeEnd: function() { 217 | this._fallOff(fallTargetX, fallTargetY, callback); 218 | }, 219 | recycle: this.anims 220 | }); 221 | 222 | if (!this.isStatic) 223 | this.rotate((random(180) + 90) * sign[random(2)]); 224 | }; 225 | 226 | // private 227 | ClassFruit.prototype._fallOff = function(endX, endY, callback) { 228 | if (this.isBroken) 229 | return; 230 | 231 | var startX = this.x; 232 | var startY = this.y; 233 | var dropTime = this.dropTime; 234 | var y; 235 | var isOutside = false; 236 | 237 | timeline.createTask({ 238 | start: 0, 239 | duration: dropTime, 240 | object: this, 241 | 242 | onTimeUpdate: function(time) { 243 | this.setPos( 244 | linearAnim(time, startX, endX - startX, dropTime), 245 | y = dropAnim(time, startY, endY - startY, dropTime) 246 | ); 247 | if (!isOutside) { 248 | if (y > layout.height() + (this.height >> 1)) { 249 | isOutside = true; 250 | if (callback) 251 | callback(); 252 | } 253 | } 254 | }, 255 | 256 | onTimeEnd: function() { 257 | if (!isOutside) { 258 | isOutside = true; 259 | if (callback) 260 | callback(); 261 | } 262 | this.remove(); 263 | }, 264 | 265 | recycle: this.anims 266 | }); 267 | }; 268 | 269 | ClassFruit.prototype.remove = function() { 270 | var index; 271 | 272 | this.anims.clear(); 273 | 274 | if (this.rotateAnim) { 275 | this.rotateAnim.stop(); 276 | } 277 | 278 | if (this.image) { 279 | this.image.remove(); 280 | this.shadow.remove(); 281 | } 282 | 283 | if (this.bImage1) { 284 | this.bImage1.remove(); 285 | this.bImage2.remove(); 286 | } 287 | 288 | for (var name in this) { 289 | if (typeof this[name] === "function") { 290 | this[name] = function(name) { 291 | return function() { 292 | throw new Error("method " + name + " has been removed"); 293 | }; 294 | }(name); 295 | } else { 296 | delete this[name]; 297 | } 298 | } 299 | }; 300 | 301 | exports.create = function(x, y, info, hide) { 302 | return new ClassFruit(x, y, info, hide); 303 | }; 304 | 305 | }); 306 | -------------------------------------------------------------------------------- /scripts/lib/raphael.js: -------------------------------------------------------------------------------- 1 | define("scripts/lib/raphael.js", function(exports, require, module){ 2 | /* 3 | * Raphael 1.5.2 - JavaScript Vector Library 4 | * 5 | * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com) 6 | * Licensed under the MIT (http://raphaeljs.com/license.html) license. 7 | */ 8 | 9 | var Raphael; 10 | var window = {}; 11 | (function(){function a(){if(a.is(arguments[0],G)){var b=arguments[0],d=bV[m](a,b.splice(0,3+a.is(b[0],E))),e=d.set();for(var g=0,h=b[w];g";bg=bf.firstChild;bg.style.behavior="url(#default#VML)";if(!(bg&&typeof bg.adj=="object"))return a.type=null;bf=null}a.svg=!(a.vml=a.type=="VML");j[e]=a[e];k=j[e];a._id=0;a._oid=0;a.fn={};a.is=function(a,b){b=x.call(b);if(b=="finite")return!O[f](+a);return b=="null"&&a===null||b==typeof a||b=="object"&&a===Object(a)||b=="array"&&Array.isArray&&Array.isArray(a)||J.call(a).slice(8,-1).toLowerCase()==b};a.angle=function(b,c,d,e,f,g){{if(f==null){var h=b-d,i=c-e;if(!h&&!i)return 0;return((h<0)*180+y.atan(-i/-h)*180/D+360)%360}return a.angle(b,c,f,g)-a.angle(d,e,f,g)}};a.rad=function(a){return a%360*D/180};a.deg=function(a){return a*180/D%360};a.snapTo=function(b,c,d){d=a.is(d,"finite")?d:10;if(a.is(b,G)){var e=b.length;while(e--)if(B(b[e]-c)<=d)return b[e]}else{b=+b;var f=c%b;if(fb-d)return c-f+b}return c};function bh(){var a=[],b=0;for(;b<32;b++)a[b]=(~(~(y.random()*16)))[H](16);a[12]=4;a[16]=(a[16]&3|8)[H](16);return"r-"+a[v]("")}a.setWindow=function(a){h=a;g=h.document};var bi=function(b){if(a.vml){var c=/^\s+|\s+$/g,d;try{var e=new ActiveXObject("htmlfile");e.write("");e.close();d=e.body}catch(a){d=createPopup().document.body}var f=d.createTextRange();bi=bm(function(a){try{d.style.color=r(a)[Y](c,p);var b=f.queryCommandValue("ForeColor");b=(b&255)<<16|b&65280|(b&16711680)>>>16;return"#"+("000000"+b[H](16)).slice(-6)}catch(a){return"none"}})}else{var h=g.createElement("i");h.title="Raphaël Colour Picker";h.style.display="none";g.body[l](h);bi=bm(function(a){h.style.color=a;return g.defaultView.getComputedStyle(h,p).getPropertyValue("color")})}return bi(b)},bj=function(){return"hsb("+[this.h,this.s,this.b]+")"},bk=function(){return"hsl("+[this.h,this.s,this.l]+")"},bl=function(){return this.hex};a.hsb2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"b"in b){d=b.b;c=b.s;b=b.h;e=b.o}return a.hsl2rgb(b,c,d/2,e)};a.hsl2rgb=function(b,c,d,e){if(a.is(b,"object")&&"h"in b&&"s"in b&&"l"in b){d=b.l;c=b.s;b=b.h}if(b>1||c>1||d>1){b/=360;c/=100;d/=100}var f={},g=["r","g","b"],h,i,j,k,l,m;if(c){d<0.5?h=d*(1+c):h=d+c-d*c;i=2*d-h;for(var n=0;n<3;n++){j=b+1/3*-(n-1);j<0&&j++;j>1&&j--;j*6<1?f[g[n]]=i+(h-i)*6*j:j*2<1?f[g[n]]=h:j*3<2?f[g[n]]=i+(h-i)*(2/3-j)*6:f[g[n]]=i}}else f={r:d,g:d,b:d};f.r*=255;f.g*=255;f.b*=255;f.hex="#"+(16777216|f.b|f.g<<8|f.r<<16).toString(16).slice(1);a.is(e,"finite")&&(f.opacity=e);f.toString=bl;return f};a.rgb2hsb=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=f;{if(g==f)return{h:0,s:0,b:f,toString:bj};var k=f-g;i=k/f;b==f?h=(c-d)/k:c==f?h=2+(d-b)/k:h=4+(b-c)/k;h/=6;h<0&&h++;h>1&&h--}return{h:h,s:i,b:j,toString:bj}};a.rgb2hsl=function(b,c,d){if(c==null&&a.is(b,"object")&&"r"in b&&"g"in b&&"b"in b){d=b.b;c=b.g;b=b.r}if(c==null&&a.is(b,F)){var e=a.getRGB(b);b=e.r;c=e.g;d=e.b}if(b>1||c>1||d>1){b/=255;c/=255;d/=255}var f=z(b,c,d),g=A(b,c,d),h,i,j=(f+g)/2,k;if(g==f)k={h:0,s:0,l:j};else{var l=f-g;i=j<0.5?l/(f+g):l/(2-f-g);b==f?h=(c-d)/l:c==f?h=2+(d-b)/l:h=4+(b-c)/l;h/=6;h<0&&h++;h>1&&h--;k={h:h,s:i,l:j}}k.toString=bk;return k};a._path2string=function(){return this.join(",")[Y](ba,"$1")};function bm(a,b,c){function d(){var g=Array[e].slice.call(arguments,0),h=g[v]("►"),i=d.cache=d.cache||{},j=d.count=d.count||[];if(i[f](h))return c?c(i[h]):i[h];j[w]>=1000&&delete i[j.shift()];j[L](h);i[h]=a[m](b,g);return c?c(i[h]):i[h]}return d}a.getRGB=bm(function(b){if(!b||!(!((b=r(b)).indexOf("-")+1)))return{r:-1,g:-1,b:-1,hex:"none",error:1};if(b=="none")return{r:-1,g:-1,b:-1,hex:"none"};!(_[f](b.toLowerCase().substring(0,2))||b.charAt()=="#")&&(b=bi(b));var c,d,e,g,h,i,j,k=b.match(N);if(k){if(k[2]){g=T(k[2].substring(5),16);e=T(k[2].substring(3,5),16);d=T(k[2].substring(1,3),16)}if(k[3]){g=T((i=k[3].charAt(3))+i,16);e=T((i=k[3].charAt(2))+i,16);d=T((i=k[3].charAt(1))+i,16)}if(k[4]){j=k[4][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);k[1].toLowerCase().slice(0,4)=="rgba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100)}if(k[5]){j=k[5][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsba"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsb2rgb(d,e,g,h)}if(k[6]){j=k[6][s]($);d=S(j[0]);j[0].slice(-1)=="%"&&(d*=2.55);e=S(j[1]);j[1].slice(-1)=="%"&&(e*=2.55);g=S(j[2]);j[2].slice(-1)=="%"&&(g*=2.55);(j[0].slice(-3)=="deg"||j[0].slice(-1)=="°")&&(d/=360);k[1].toLowerCase().slice(0,4)=="hsla"&&(h=S(j[3]));j[3]&&j[3].slice(-1)=="%"&&(h/=100);return a.hsl2rgb(d,e,g,h)}k={r:d,g:e,b:g};k.hex="#"+(16777216|g|e<<8|d<<16).toString(16).slice(1);a.is(h,"finite")&&(k.opacity=h);return k}return{r:-1,g:-1,b:-1,hex:"none",error:1}},a);a.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||0.75},c=this.hsb2rgb(b.h,b.s,b.b);b.h+=0.075;if(b.h>1){b.h=0;b.s-=0.2;b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})}return c.hex};a.getColor.reset=function(){delete this.start};a.parsePathString=bm(function(b){if(!b)return null;var c={a:7,c:6,h:1,l:2,m:2,q:4,s:4,t:2,v:1,z:0},d=[];a.is(b,G)&&a.is(b[0],G)&&(d=bo(b));d[w]||r(b)[Y](bb,function(a,b,e){var f=[],g=x.call(b);e[Y](bc,function(a,b){b&&f[L](+b)});if(g=="m"&&f[w]>2){d[L]([b][n](f.splice(0,2)));g="l";b=b=="m"?"l":"L"}while(f[w]>=c[g]){d[L]([b][n](f.splice(0,c[g])));if(!c[g])break}});d[H]=a._path2string;return d});a.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=C(j,3)*a+C(j,2)*3*i*c+j*3*i*i*e+C(i,3)*g,l=C(j,3)*b+C(j,2)*3*i*d+j*3*i*i*f+C(i,3)*h,m=a+2*i*(c-a)+i*i*(e-2*c+a),n=b+2*i*(d-b)+i*i*(f-2*d+b),o=c+2*i*(e-c)+i*i*(g-2*e+c),p=d+2*i*(f-d)+i*i*(h-2*f+d),q=(1-i)*a+i*c,r=(1-i)*b+i*d,s=(1-i)*e+i*g,t=(1-i)*f+i*h,u=90-y.atan((m-o)/(n-p))*180/D;(m>o||n1){x=y.sqrt(x);c=x*c;d=x*d}var z=c*c,A=d*d,C=(f==g?-1:1)*y.sqrt(B((z*A-z*u*u-A*t*t)/(z*u*u+A*t*t))),E=C*c*u/d+(a+h)/2,F=C*-d*t/c+(b+i)/2,G=y.asin(((b-F)/d).toFixed(9)),H=y.asin(((i-F)/d).toFixed(9));G=aH&&(G=G-D*2);!g&&H>G&&(H=H-D*2)}var I=H-G;if(B(I)>k){var J=H,K=h,L=i;H=G+k*(g&&H>G?1:-1);h=E+c*y.cos(H);i=F+d*y.sin(H);m=bt(h,i,c,d,e,0,g,K,L,[H,J,E,F])}I=H-G;var M=y.cos(G),N=y.sin(G),O=y.cos(H),P=y.sin(H),Q=y.tan(I/4),R=4/3*c*Q,S=4/3*d*Q,T=[a,b],U=[a+R*N,b-S*M],V=[h+R*P,i-S*O],W=[h,i];U[0]=2*T[0]-U[0];U[1]=2*T[1]-U[1];{if(j)return[U,V,W][n](m);m=[U,V,W][n](m)[v]()[s](",");var X=[];for(var Y=0,Z=m[w];Y"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}i=f-2*d+b-(h-2*f+d);j=2*(d-b)-2*(f-d);k=b-d;l=(-j+y.sqrt(j*j-4*i*k))/2/i;n=(-j-y.sqrt(j*j-4*i*k))/2/i;B(l)>"1e12"&&(l=0.5);B(n)>"1e12"&&(n=0.5);if(l>0&&l<1){q=bu(a,b,c,d,e,f,g,h,l);p[L](q.x);o[L](q.y)}if(n>0&&n<1){q=bu(a,b,c,d,e,f,g,h,n);p[L](q.x);o[L](q.y)}return{min:{x:A[m](0,p),y:A[m](0,o)},max:{x:z[m](0,p),y:z[m](0,o)}}}),bw=bm(function(a,b){var c=bq(a),d=b&&bq(b),e={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g=function(a,b){var c,d;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null);switch(a[0]){case"M":b.X=a[1];b.Y=a[2];break;case"A":a=["C"][n](bt[m](0,[b.x,b.y][n](a.slice(1))));break;case"S":c=b.x+(b.x-(b.bx||b.x));d=b.y+(b.y-(b.by||b.y));a=["C",c,d][n](a.slice(1));break;case"T":b.qx=b.x+(b.x-(b.qx||b.x));b.qy=b.y+(b.y-(b.qy||b.y));a=["C"][n](bs(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1];b.qy=a[2];a=["C"][n](bs(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][n](br(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][n](br(b.x,b.y,a[1],b.y));break;case"V":a=["C"][n](br(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][n](br(b.x,b.y,b.X,b.Y));break}return a},h=function(a,b){if(a[b][w]>7){a[b].shift();var e=a[b];while(e[w])a.splice(b++,0,["C"][n](e.splice(0,6)));a.splice(b,1);k=z(c[w],d&&d[w]||0)}},i=function(a,b,e,f,g){if(a&&b&&a[g][0]=="M"&&b[g][0]!="M"){b.splice(g,0,["M",f.x,f.y]);e.bx=0;e.by=0;e.x=a[g][1];e.y=a[g][2];k=z(c[w],d&&d[w]||0)}};for(var j=0,k=z(c[w],d&&d[w]||0);j0.5)*2-1;C(e-0.5,2)+C(f-0.5,2)>0.25&&(f=y.sqrt(0.25-C(e-0.5,2))*g+0.5)&&f!=0.5&&(f=f.toFixed(5)-0.00001*g)}return p});b=b[s](/\s*\-\s*/);if(d=="linear"){var i=b.shift();i=-S(i);if(isNaN(i))return null;var j=[0,0,y.cos(i*D/180),y.sin(i*D/180)],k=1/(z(B(j[2]),B(j[3]))||1);j[2]*=k;j[3]*=k;if(j[2]<0){j[0]=-j[2];j[2]=0}if(j[3]<0){j[1]=-j[3];j[3]=0}}var m=bx(b);if(!m)return null;var n=a.getAttribute(I);n=n.match(/^url\(#(.*)\)$/);n&&c.defs.removeChild(g.getElementById(n[1]));var o=bG(d+"Gradient");o.id=bh();bG(o,d=="radial"?{fx:e,fy:f}:{x1:j[0],y1:j[1],x2:j[2],y2:j[3]});c.defs[l](o);for(var q=0,t=m[w];q1?G.opacity/100:G.opacity});case"stroke":G=a.getRGB(o);h[R](n,G.hex);n=="stroke"&&G[f]("opacity")&&bG(h,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity});break;case"gradient":(({circle:1,ellipse:1})[f](c.type)||r(o).charAt()!="r")&&bI(h,o,c.paper);break;case"opacity":i.gradient&&!i[f]("stroke-opacity")&&bG(h,{"stroke-opacity":o>1?o/100:o});case"fill-opacity":if(i.gradient){var H=g.getElementById(h.getAttribute(I)[Y](/^url\(#|\)$/g,p));if(H){var J=H.getElementsByTagName("stop");J[J[w]-1][R]("stop-opacity",o)}break}default:n=="font-size"&&(o=T(o,10)+"px");var K=n[Y](/(\-.)/g,function(a){return V.call(a.substring(1))});h.style[K]=o;h[R](n,o);break}}}bM(c,d);m?c.rotate(m.join(q)):S(j)&&c.rotate(j,true)},bL=1.2,bM=function(b,c){if(b.type!="text"||!(c[f]("text")||c[f]("font")||c[f]("font-size")||c[f]("x")||c[f]("y")))return;var d=b.attrs,e=b.node,h=e.firstChild?T(g.defaultView.getComputedStyle(e.firstChild,p).getPropertyValue("font-size"),10):10;if(c[f]("text")){d.text=c.text;while(e.firstChild)e.removeChild(e.firstChild);var i=r(c.text)[s]("\n");for(var j=0,k=i[w];jb.height&&(b.height=e.y+e.height-b.y);e.x+e.width-b.x>b.width&&(b.width=e.x+e.width-b.x)}}a&&this.hide();return b};bN[e].attr=function(b,c){if(this.removed)return this;if(b==null){var d={};for(var e in this.attrs)this.attrs[f](e)&&(d[e]=this.attrs[e]);this._.rt.deg&&(d.rotation=this.rotate());(this._.sx!=1||this._.sy!=1)&&(d.scale=this.scale());d.gradient&&d.fill=="none"&&(d.fill=d.gradient)&&delete d.gradient;return d}if(c==null&&a.is(b,F)){if(b=="translation")return cz.call(this);if(b=="rotation")return this.rotate();if(b=="scale")return this.scale();if(b==I&&this.attrs.fill=="none"&&this.attrs.gradient)return this.attrs.gradient;return this.attrs[b]}if(c==null&&a.is(b,G)){var g={};for(var h=0,i=b.length;h"));m.W=h.w=m.paper.span.offsetWidth;m.H=h.h=m.paper.span.offsetHeight;m.X=h.x;m.Y=h.y+Q(m.H/2);switch(h["text-anchor"]){case"start":m.node.style["v-text-align"]="left";m.bbx=Q(m.W/2);break;case"end":m.node.style["v-text-align"]="right";m.bbx=-Q(m.W/2);break;default:m.node.style["v-text-align"]="center";break}}};bI=function(a,b){a.attrs=a.attrs||{};var c=a.attrs,d,e="linear",f=".5 .5";a.attrs.gradient=b;b=r(b)[Y](bd,function(a,b,c){e="radial";if(b&&c){b=S(b);c=S(c);C(b-0.5,2)+C(c-0.5,2)>0.25&&(c=y.sqrt(0.25-C(b-0.5,2))*((c>0.5)*2-1)+0.5);f=b+q+c}return p});b=b[s](/\s*\-\s*/);if(e=="linear"){var g=b.shift();g=-S(g);if(isNaN(g))return null}var h=bx(b);if(!h)return null;a=a.shape||a.node;d=a.getElementsByTagName(I)[0]||cd(I);!d.parentNode&&a.appendChild(d);if(h[w]){d.on=true;d.method="none";d.color=h[0].color;d.color2=h[h[w]-1].color;var i=[];for(var j=0,k=h[w];j")}}catch(a){cd=function(a){return g.createElement("<"+a+" xmlns=\"urn:schemas-microsoft.com:vml\" class=\"rvml\">")}}bV=function(){var b=by[m](0,arguments),c=b.container,d=b.height,e,f=b.width,h=b.x,i=b.y;if(!c)throw new Error("VML container not found.");var k=new j,n=k.canvas=g.createElement("div"),o=n.style;h=h||0;i=i||0;f=f||512;d=d||342;f==+f&&(f+="px");d==+d&&(d+="px");k.width=1000;k.height=1000;k.coordsize=b_*1000+q+b_*1000;k.coordorigin="0 0";k.span=g.createElement("span");k.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";n[l](k.span);o.cssText=a.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",f,d);if(c==1){g.body[l](n);o.left=h+"px";o.top=i+"px";o.position="absolute"}else c.firstChild?c.insertBefore(n,c.firstChild):c[l](n);bz.call(k,k,a.fn);return k};k.clear=function(){this.canvas.innerHTML=p;this.span=g.createElement("span");this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";this.canvas[l](this.span);this.bottom=this.top=null};k.remove=function(){this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]=bF(a);return true}}var ce=navigator.userAgent.match(/Version\\x2f(.*?)\s/);navigator.vendor=="Apple Computer, Inc."&&(ce&&ce[1]<4||navigator.platform.slice(0,2)=="iP")?k.safari=function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});h.setTimeout(function(){a.remove()})}:k.safari=function(){};var cf=function(){this.returnValue=false},cg=function(){return this.originalEvent.preventDefault()},ch=function(){this.cancelBubble=true},ci=function(){return this.originalEvent.stopPropagation()},cj=(function(){{if(g.addEventListener)return function(a,b,c,d){var e=o&&u[b]?u[b]:b,g=function(e){if(o&&u[f](b))for(var g=0,h=e.targetTouches&&e.targetTouches.length;g1&&(a=Array[e].splice.call(arguments,0,arguments[w]));return new cC(a)};k.setSize=bU;k.top=k.bottom=null;k.raphael=a;function co(){return this.x+q+this.y}bO.resetScale=function(){if(this.removed)return this;this._.sx=1;this._.sy=1;this.attrs.scale="1 1"};bO.scale=function(a,b,c,d){if(this.removed)return this;if(a==null&&b==null)return{x:this._.sx,y:this._.sy,toString:co};b=b||a;!(+b)&&(b=a);var e,f,g,h,i=this.attrs;if(a!=0){var j=this.getBBox(),k=j.x+j.width/2,l=j.y+j.height/2,m=B(a/this._.sx),o=B(b/this._.sy);c=+c||c==0?c:k;d=+d||d==0?d:l;var r=this._.sx>0,s=this._.sy>0,t=~(~(a/B(a))),u=~(~(b/B(b))),x=m*t,y=o*u,z=this.node.style,A=c+B(k-c)*x*(k>c==r?1:-1),C=d+B(l-d)*y*(l>d==s?1:-1),D=a*t>b*u?o:m;switch(this.type){case"rect":case"image":var E=i.width*m,F=i.height*o;this.attr({height:F,r:i.r*D,width:E,x:A-E/2,y:C-F/2});break;case"circle":case"ellipse":this.attr({rx:i.rx*m,ry:i.ry*o,r:i.r*D,cx:A,cy:C});break;case"text":this.attr({x:A,y:C});break;case"path":var G=bp(i.path),H=true,I=r?x:m,J=s?y:o;for(var K=0,L=G[w];Kr)p=n.data[r*l];else{p=a.findDotsAtSegment(b,c,d,e,f,g,h,i,r/l);n.data[r]=p}r&&(k+=C(C(o.x-p.x,2)+C(o.y-p.y,2),0.5));if(j!=null&&k>=j)return p;o=p}if(j==null)return k},cr=function(b,c){return function(d,e,f){d=bw(d);var g,h,i,j,k="",l={},m,n=0;for(var o=0,p=d.length;oe){if(c&&!l.start){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);k+=["C",m.start.x,m.start.y,m.m.x,m.m.y,m.x,m.y];if(f)return k;l.start=k;k=["M",m.x,m.y+"C",m.n.x,m.n.y,m.end.x,m.end.y,i[5],i[6]][v]();n+=j;g=+i[5];h=+i[6];continue}if(!b&&!c){m=cq(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n);return{x:m.x,y:m.y,alpha:m.alpha}}}n+=j;g=+i[5];h=+i[6]}k+=i}l.end=k;m=b?n:c?l:a.findDotsAtSegment(g,h,i[1],i[2],i[3],i[4],i[5],i[6],1);m.alpha&&(m={x:m.x,y:m.y,alpha:m.alpha});return m}},cs=cr(1),ct=cr(),cu=cr(0,1);bO.getTotalLength=function(){if(this.type!="path")return;if(this.node.getTotalLength)return this.node.getTotalLength();return cs(this.attrs.path)};bO.getPointAtLength=function(a){if(this.type!="path")return;return ct(this.attrs.path,a)};bO.getSubpath=function(a,b){if(this.type!="path")return;if(B(this.getTotalLength()-b)<"1e-6")return cu(this.attrs.path,a).end;var c=cu(this.attrs.path,b,1);return a?cu(c,a).end:c};a.easing_formulas={linear:function(a){return a},"<":function(a){return C(a,3)},">":function(a){return C(a-1,3)+1},"<>":function(a){a=a*2;if(a<1)return C(a,3)/2;a-=2;return(C(a,3)+2)/2},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a=a-1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){if(a==0||a==1)return a;var b=0.3,c=b/4;return C(2,-10*a)*y.sin((a-c)*(2*D)/b)+1},bounce:function(a){var b=7.5625,c=2.75,d;if(a<1/c)d=b*a*a;else if(a<2/c){a-=1.5/c;d=b*a*a+0.75}else if(a<2.5/c){a-=2.25/c;d=b*a*a+0.9375}else{a-=2.625/c;d=b*a*a+0.984375}return d}};var cv=[],cw=function(){var b=+(new Date);for(var c=0;cd)return d;while(cf?c=e:d=e;e=(d-c)/2+c}return e}return n(a,1/(200*f))}bO.onAnimation=function(a){this._run=a||0;return this};bO.animate=function(c,d,e,g){var h=this;h.timeouts=h.timeouts||[];if(a.is(e,"function")||!e)g=e||null;if(h.removed){g&&g.call(h);return h}var i={},j={},k=false,l={};for(var m in c)if(c[f](m)){if(X[f](m)||h.paper.customAttributes[f](m)){k=true;i[m]=h.attr(m);i[m]==null&&(i[m]=W[m]);j[m]=c[m];switch(X[m]){case"along":var n=cs(c[m]),o=ct(c[m],n*!(!c.back)),p=h.getBBox();l[m]=n/d;l.tx=p.x;l.ty=p.y;l.sx=o.x;l.sy=o.y;j.rot=c.rot;j.back=c.back;j.len=n;c.rot&&(l.r=S(h.rotate())||0);break;case E:l[m]=(j[m]-i[m])/d;break;case"colour":i[m]=a.getRGB(i[m]);var q=a.getRGB(j[m]);l[m]={r:(q.r-i[m].r)/d,g:(q.g-i[m].g)/d,b:(q.b-i[m].b)/d};break;case"path":var t=bw(i[m],j[m]);i[m]=t[0];var u=t[1];l[m]=[];for(var v=0,x=i[m][w];v