diff --git a/MIT-LICENCE.txt b/MIT-LICENCE.txt new file mode 100644 index 0000000..8668d02 --- /dev/null +++ b/MIT-LICENCE.txt @@ -0,0 +1,7 @@ +Copyright (c) 2013 Fabrice ECAILLE aka Febbweiss + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README b/README index 762b2f4..d8708c7 100644 --- a/README +++ b/README @@ -1 +1,10 @@ -gq-pacman is a jQuery implementation of the famous Namco's Pacman +gq-pacman is a jQuery implementation of the famous Namco's Pacman. + +Credits : + +Graphics : Fabrice Ecaille aka Febbweiss +Code : Fabrice Ecaille aka Febbweiss +Algorithm : Based on the "Pacman Dossier" (http://home.comcast.net/~jpittman2/pacman/pacmandossier.html) +Tools : gameQuery (http://gamequeryjs.com/) +Sounds : Sound FX Center (http://soundfxcenter.com/sound_effect/search.php?sfx=Pacman) + diff --git a/css/hack/csshover3.htc b/css/hack/csshover3.htc new file mode 100644 index 0000000..4fa021f --- /dev/null +++ b/css/hack/csshover3.htc @@ -0,0 +1,12 @@ + + \ No newline at end of file diff --git a/css/pacman.css b/css/pacman.css new file mode 100644 index 0000000..f4c0b9e --- /dev/null +++ b/css/pacman.css @@ -0,0 +1,267 @@ +#playgroundContainer { + width: 448px; + height: 512px; + background-color: black; + margin-left: auto; + margin-right: auto; +} + +.actor { + width: 32px; + height: 32px; + position: relative; + margin-top: -16px; + margin-left: -16px; +} + +/** TILES **/ + +.tile { + width: 16px; + height: 16px; + float: left; + margin: 0px; + padding: 0px; +} + +.corner1 { + background-image: url('../img/sprite.png'); + background-position: -0px -0px; +} + +.corner2 { + background-image: url('../img/sprite.png'); + background-position: -16px -0px; +} + +.corner3 { + background-image: url('../img/sprite.png'); + background-position: -32px 0px; +} + +.corner4 { + background-image: url('../img/sprite.png'); + background-position: -48px 0px; +} + +.horizontalMidUp { + background-image: url('../img/sprite.png'); + background-position: -96px -0px; +} + +.horizontalMidDown { + background-image: url('../img/sprite.png'); + background-position: -112px -0px; +} + +.verticalMidLeft { + background-image: url('../img/sprite.png'); + background-position: -64px -0px; +} + +.verticalMidRight { + background-image: url('../img/sprite.png'); + background-position: -80px -0px; +} + +.squareCornerTopLeft { + background-image: url('../img/sprite.png'); + background-position: -128px -0px; +} + +.squareCornerTopRight { + background-image: url('../img/sprite.png'); + background-position: -144px -0px; +} + +.squareCornerBottomLeft { + background-image: url('../img/sprite.png'); + background-position: -160px -0px; +} + +.squareCornerBottomRight { + background-image: url('../img/sprite.png'); + background-position: -176px -0px; +} + +.gate { + background-image: url('../img/sprite.png'); + background-position: -192px -0px; +} + +.dot { + background-image: url('../img/sprite.png'); + background-position: -208px -0px; +} + +.bigDot { + background-image: url('../img/sprite.png'); + background-position: -208px -16px; +} + +.ghost { + width: 32px; + height: 32px; + float: left; +} + +.blinky { + background-image: url('../img/sprite.png'); + background-position: -160px -48px; +} +.pinky { + background-image: url('../img/sprite.png'); + background-position: -160px -80px; +} +.inky { + background-image: url('../img/sprite.png'); + background-position: -160px -112px; +} +.clyde { + background-image: url('../img/sprite.png'); + background-position: -160px -144px; +} + +.cherries { + background-image: url('../img/sprite.png'); + background-position: -208px -32px; +} + +.strawberry { + background-image: url('../img/sprite.png'); + background-position: -208px -48px; +} + +.peach { + background-image: url('../img/sprite.png'); + background-position: -208px -64px; +} + +.apple { + background-image: url('../img/sprite.png'); + background-position: -208px -80px; +} + +.grapes { + background-image: url('../img/sprite.png'); + background-position: -208px -96px; +} + +.galaxian { + background-image: url('../img/sprite.png'); + background-position: -208px -112px; +} + +.bell { + background-image: url('../img/sprite.png'); + background-position: -208px -128px; +} + +.key { + background-image: url('../img/sprite.png'); + background-position: -208px -144px; +} + +.description { + padding-left: 40px; + line-height: 3em; + vertical-align: middle; +} +/** HUD **/ + +#message { + position : absolute; + left : 50%; + top : 50%; +} + +#level { + position : relative; + top: -10px; + left: 5px; +} + +#levelNumber { + position : relative; + top: -14px; + float: left; + margin-left: 100px; +} + +#lives { + position: absolute; + top: -1px; + right: 10px; +} + +#scoreMessage { + position: absolute; + right: 0px; +} + +.life { + width: 32px; + height: 32px; + float: left; + background-image: url('../img/sprite.png'); + background-position: 0px -16px; +} + +/** SCOREBOARD**/ + +.clock { + background : transparent url("../img/font.png") no-repeat top left; + height:32px; + width:32px; + float:left; +} + +.clock.red { + background : transparent url("../img/font-red.png") no-repeat top left; +} + +.clock.yellow { + background : transparent url("../img/font-yellow.png") no-repeat top left; +} + +.clock.small { + position: relative; + top: 45%; + height: 16px; + width: 16px; +} + +.n0 { + background-position : 0px 0px; +} +.n1 { + background-position : -32px 0px; +} +.n2 { + background-position : -64px 0px; +} +.n3 { + background-position : -96px 0px; +} +.n4 { + background-position : -128px 0px; +} +.n5 { + background-position : -160px 0px; +} +.n6 { + background-position : -192px 0px; +} +.n7 { + background-position : -224px 0px; +} +.n8 { + background-position : -256px 0px; +} +.n9 { + background-position : -288px 0px; +} + +.hiddenDot { + visibility: hidden; +} diff --git a/img/banner.png b/img/banner.png new file mode 100644 index 0000000..2cabdb7 Binary files /dev/null and b/img/banner.png differ diff --git a/img/font-red.png b/img/font-red.png new file mode 100644 index 0000000..65d6f9c Binary files /dev/null and b/img/font-red.png differ diff --git a/img/font-yellow.png b/img/font-yellow.png new file mode 100644 index 0000000..718446e Binary files /dev/null and b/img/font-yellow.png differ diff --git a/img/font.png b/img/font.png new file mode 100644 index 0000000..d22022b Binary files /dev/null and b/img/font.png differ diff --git a/img/sprite.png b/img/sprite.png new file mode 100644 index 0000000..fe94a65 Binary files /dev/null and b/img/sprite.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..0c974b6 --- /dev/null +++ b/index.html @@ -0,0 +1,82 @@ + + + + + Pacman + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+

+ Famous Namco©'s Pacman© is now available !!! +

+

+ Use your keyboard arrows to move Pacman to eat all energizer to complete the level.
+ Ghosts become frightened when Pacman eats a big energizer. Eat them !!!
+

+

+ Beware of ghost who haunt the maze !!! Each one has his own personality : +

+
Blinky tracks Pacman as his shadow.
+
+
Pinky perfoms ambushes to Pacman.
+
+
Inky is the least predictable.
+
+
Clyde pretends ignorance and is one who lags behind.
+ +

+

+

+
+
+
+
+
+ Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +
+ + + + diff --git a/js/pacman-core.js b/js/pacman-core.js new file mode 100644 index 0000000..355866f --- /dev/null +++ b/js/pacman-core.js @@ -0,0 +1,1009 @@ +/* +Copyright (c) 2013 Fabrice ECAILLE aka Febbweiss + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var Game = { + id : null, + type : "offline", + player : 1, + + PACMAN_START_X : 14 * TILE_SIZE, + PACMAN_START_Y : 24 * TILE_SIZE, + + GHOST_STATE_CHASE : 1, + GHOST_STATE_SCATTER : 2, + GHOST_STATE_FRIGHTENED : 3, + GHOST_STATE_IN_JAIL : 4, + GHOST_STATE_EATEN : 5, + GHOST_STATE_FRIGHTENED_BLINK : 6, + + + GHOST_EVENT_CHASE : "ghost_event_chase", + GHOST_EVENT_SCATTER : "ghost_event_scatter", + GHOST_EVENT_DOT_EATEN : "ghost_event_dot_eaten", + + DOT_POINTS : 10, + BIG_DOT_POINTS : 50, + totalDots : 0, + + dots : {}, + timer : null, + frightTimer : null, + bonusTimer : null, + level : -1, + levelData : null, + step : 0, + score : 0, + eatenDots : 0, + lives : 3, + running : false, + mode : 2, // Game.GHOST_STATE_SCATTER + frightMode : false, + eaten: 0, + + pacman : null, + miss : null, + hero : null, + blinky : null, + pinky : null, + inky : null, + clyde : null, + ghosts : new Array(), + actors : {}, + heroes : new Array(), + maze : MAZE, + + init : function() { + + GUI.updateMessage("READY"); + + $(".dot.hiddenDot").each( function(incr, elt) { + Game.dots[elt.id] = "dot"; + }); + $(".dot.hiddenDot").removeClass("hiddenDot"); + + $(".bigDot.hiddenDot").each( function(incr, elt) { + Game.dots[elt.id] = "bigDot"; + }); + $(".bigDot.hiddenDot").removeClass("hiddenDot") + + Game.totalDots = $(".dot").length + $(".bigDot").length; + + SCOREBOARD.init(); + SCOREBOARD.set_score( Game.score ); + + Game.level++; + Game.step = 0; + Game.eatenDots = 0; + + GUI.updateLevelNumber( Game.level + 1 ); + + Game.build(LEVELS[Math.min(Game.level, LEVELS.length)]); + }, + + build : function(data) { + Game.levelData = data; + Game.addPacman(); + Game.addGhosts(); + Sound.play("opening"); + setTimeout("Game.start();", 4500); + }, + + start : function() { + //if( $.browser.webkit ) + $(document).keydown( function( event ) { + if( event.which > 36 && event.which < 41 ) + return false; + } ); + // $(document).keypress(scrollPreventFct ); + + GUI.updateMessage(""); + Game.timer = new PausableTimer(Game.timerManager, Game.levelData.mode[Game.step] * 1000); + Game.running = true; + }, + + levelComplete : function() { + Game.running = false; + Game.timer.stop(); + Game.timer = null; + + setTimeout("Game.init();", 3000); + }, + + eat : function(type) { + Game.eatenDots++; + if( type === "bigDot" ) { + Game.score += Game.BIG_DOT_POINTS; +// console.log( "Eating big dot " + Game.score ); + SCOREBOARD.add( Game.BIG_DOT_POINTS ); + } else { + Game.score += Game.DOT_POINTS; +// console.log( "Eating dot " + Game.score ); + SCOREBOARD.add( Game.DOT_POINTS ); + } + + if( Game.eatenDots == 70 || Game.eatenDots == 170 ) { + Game.bonusTimer = setTimeout("Game.hideBonus();", ( 9 + Math.random() ) * 1000 ); + $("#" + Game.maze.bonus_target).addClass( Game.levelData.bonus.type); + } + + if( Game.eatenDots === Game.totalDots ) + Game.levelComplete(); + }, + + eatGhost : function(ghost) { + Sound.play("ghost"); + Game.eaten++; + var points = Game.eaten * 200; + Game.score += points; +// console.log(new Date() + " Eating " + ghost.id + " " + (Game.eaten * 200) + " "+ Game.score ); + SCOREBOARD.add( points ); + }, + + hideBonus : function() { + $("#" + Game.maze.bonus_target).removeClass( Game.levelData.bonus.type); + Game.bonusTimer = null; + }, + + die : function() { + Game.running = false; + $.each( Game.actors, function(index, actor) { + actor.speed = 0; + }) + Game.pacman.die(); + Game.timer.stop(); + Game.step = 0; + Game.timer = null; + $("#life" + Game.lives).effect( "pulsate", {times:3, mode:"hide"}, 500 ); + Game.lives--; + if( Game.lives > 0 ) + setTimeout( "Game.startAfterDie();", 3000); + else { + GUI.drawText( $("#message"), "GAME OVER", true ); + Game.show_game_over(); + } + }, + + show_game_over: function() { + }, + + startAfterDie : function() { + var dotsCounters = new Array(); + $.each(Game.ghosts, function(index, ghost ) { + dotsCounters[index] = ghost.dotsCounter; + }); + + Game.addGhosts(); + Game.addPacman(); + //Game.addMissPacman(); + + $.each(Game.ghosts, function(index, ghost ) { + ghost.dotsCounter = dotsCounters[index]; + if( ghost.dotsCounter >= ghost.dotsLimits[Math.min(Game.level, ghost.dotsLimits.length - 1)] ) { + ghost.speed = ghost.initialSpeed; + ghost.state_to(Game.GHOST_STATE_SCATTER); + } + }); + + Game.running = true; + Game.step = 0; + Game.timer = new PausableTimer(Game.timerManager, Game.levelData.mode[Game.step] * 1000); + }, + + timerManager : function() { + Game.step++; + if( Game.step % 2 == 1 ) { + $(".actor").trigger(Game.GHOST_EVENT_CHASE); + Game.mode = Game.GHOST_STATE_CHASE; + } else { + $(".actor").trigger(Game.GHOST_EVENT_SCATTER); + Game.mode = Game.GHOST_STATE_SCATTER; + } + if( Game.step < Game.levelData.mode.length - 1 && Game.levelData.mode[Game.step] != INFINITY ) + Game.timer = new PausableTimer(Game.timerManager, Game.levelData.mode[Game.step] * 1000); + }, + + addPacman : function() { + if( $("#pacman").length == 0) { + Game.pacman = new Pacman(); + $("#actors").addSprite("pacman", {animation: Game.pacman.animations["right"], posx:Game.pacman.x, posy: Game.pacman.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.pacman.node = $("#pacman"); + Game.pacman.node.addClass( "actor" ); + Game.actors[ "pacman" ] = Game.pacman; + Game.heroes[ "pacman" ] = Game.pacman; + + Game.hero = Game.pacman; + } + Game.pacman.init(); + Game.pacman.speed = Game.levelData.pacman.speed; + Game.pacman.left(); + }, + + addMissPacman : function() { + if( $("#miss_pacman").length == 0) { + Game.miss = new Pacman(); + Game.miss.animations["right"] = new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsety: 272, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }); + Game.miss.animations["up"] = new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsetx: 96, offsety: 272, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }); + + $("#actors").addSprite("miss_pacman", {animation: Game.miss.animations["right"], posx:Game.miss.x, posy: Game.miss.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.miss.node = $("#miss_pacman"); + Game.miss.node.addClass( "actor" ); + Game.actors[ "miss_pacman" ] = Game.miss; + Game.heroes[ "miss_pacman" ] = Game.miss; + } + Game.miss.init(); + Game.miss.x = Game.MISS_PACMAN_START_X; + Game.miss.y = Game.MISS_PACMAN_START_Y; + Game.miss.speed = Game.levelData.pacman.speed; + Game.miss.right(true); + Game.miss.left(true); + Game.miss.node.x(Game.miss.x); + Game.miss.node.y(Game.miss.y); + Game.miss.right(); + }, + + addGhosts : function() { + Game.addBlinky(); + Game.addPinky(); + Game.addInky(); + Game.addClyde(); + }, + + addBlinky : function() { + if( $("#blinky").length == 0 ) { + Game.blinky = new Ghost("blinky", 0, {x: 14 * TILE_SIZE, y: 14 * TILE_SIZE}, {x: 25, y: 0 }, function() { + var prey = Game.actors[ "blinky" ].prey; + return {x: prey.getTileX(), y: prey.getTileY()}; + }, [0,0,0], Game.GHOST_STATE_SCATTER); + Game.blinky.center(); + $("#actors").addSprite("blinky", {animation: Game.blinky.animations["right"], posx:Game.blinky.x, posy: Game.blinky.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.blinky.node = $("#blinky"); + Game.blinky.node.addClass( "actor" ); + Game.actors[ "blinky" ] = Game.blinky; + Game.blinky.loadBindings(); + + Game.blinky.originalTarget = Game.blinky.target; + Game.blinky.target = function() { + var remainingDots = Game.totalDots - Game.eatenDots; + var elroySpecs = Game.levelData.ghost; + if( ( Game.blinky.state == Game.GHOST_STATE_SCATTER || Game.blinky.state == Game.GHOST_STATE_CHASE ) && remainingDots <= elroySpecs.elroy1Dots ) { + if( remainingDots <= elroySpecs.elroy2Dots ) { + Game.blinky.speed = elroySpecs.elroy2Speed; + } + else { + Game.blinky.speed = elroySpecs.elroy1Speed; + } + + return Game.blinky.personnalTarget(); + } + return Game.blinky.originalTarget(); + }; + + Game.ghosts.push( Game.blinky ); + } else { + Game.blinky.init(); + } + Game.blinky.state = Game.GHOST_STATE_SCATTER; + Game.blinky.left(); + Game.blinky.initialSpeed = Game.levelData.ghost.speed; + Game.blinky.speed = Game.blinky.initialSpeed; + }, + + addPinky : function() { + if( $("#pinky").length == 0 ) { + Game.pinky = new Ghost("pinky", 1, {x: 14 * TILE_SIZE, y: 16 * TILE_SIZE}, {x: 2, y: 0 }, function() { + var prey = Game.actors[ "pinky" ].prey; + var direction = this.prey.direction; + if( direction % 2 == 0 ) + return {x: prey.getTileX() + (direction == LEFT ? -4 : 4), y: prey.getTileY()}; + else + return {x: prey.getTileX(), y: prey.getTileY() + (direction == UP ? -4 : 4) }; + }, [0,0,0], Game.GHOST_STATE_IN_JAIL); + Game.pinky.center(); + $("#actors").addSprite("pinky", {animation: Game.pinky.animations["right"], posx: Game.pinky.x, posy: Game.pinky.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.pinky.node = $("#pinky"); + Game.pinky.node.addClass( "actor" ); + Game.actors[ "pinky" ] = Game.pinky; + Game.pinky.loadBindings(); + + Game.ghosts.push( Game.pinky ); + } else { + Game.pinky.init(); + } + Game.pinky.initialSpeed = Game.levelData.ghost.speed; + Game.pinky.left(); + }, + + addInky : function() { + if( $("#inky").length == 0 ) { + Game.inky = new Ghost("inky", 2, {x: 12 * TILE_SIZE, y: 16 * TILE_SIZE}, {x: 27, y: 34 }, function() { + var prey = Game.actors[ "inky" ].prey; + var direction = prey.direction; + if( direction % 2 == 0 ) + direction = {x: prey.getTileX() + (direction == LEFT ? -2 : 2) - Game.blinky.getTileX(), y: prey.getTileY() - Game.blinky.getTileY()}; + else + direction = {x: prey.getTileX() - Game.blinky.getTileX(), y: prey.getTileY() + (direction == UP ? -2 : 2) - Game.blinky.getTileY()}; + return {x: direction.x * 2, y: direction.y * 2}; + }, [30,0,0], Game.GHOST_STATE_IN_JAIL); + Game.inky.center(); + $("#actors").addSprite("inky", {animation: Game.inky.animations["right"], posx:Game.inky.x, posy: Game.inky.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.inky.node = $("#inky"); + Game.inky.node.addClass( "actor" ); + Game.actors[ "inky" ] = Game.inky; + Game.inky.loadBindings(); + + Game.ghosts.push( Game.inky ); + } else { + Game.inky.init(); + } + Game.inky.initialSpeed = Game.levelData.ghost.speed; + Game.inky.right(); + }, + + addClyde : function() { + if( $("#clyde").length == 0 ) { + Game.clyde = new Ghost("clyde", 3, {x: 16 * TILE_SIZE, y: 16 * TILE_SIZE}, {x: 0, y: 34 }, function() { + var prey = Game.actors[ "clyde" ].prey; + return distance( {x: this.getTileX(), y: this.getTileY()} , {x: prey.getTileX(), y: prey.getTileY()}) < 8 ? + this.scatterTarget : {x: prey.getTileX(), y: prey.getTileY()}; + }, [60,50,0], Game.GHOST_STATE_IN_JAIL); + Game.clyde.center(); + $("#actors").addSprite("clyde", {animation: Game.clyde.animations["right"], posx:Game.clyde.x, posy: Game.clyde.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.clyde.node = $("#clyde"); + Game.clyde.node.addClass( "actor" ); + Game.actors[ "clyde" ] = Game.clyde; + Game.clyde.loadBindings(); + + Game.ghosts.push( Game.clyde ); + } else { + Game.clyde.init(); + } + Game.clyde.initialSpeed = Game.levelData.ghost.speed; + Game.clyde.left(); + }, + + moveGhosts : function() { + $.each(Game.ghosts, function(index, ghost ) { + ghost.move(); + }); + }, + + nearEndFright : function() { + $.each(Game.ghosts, function(index, ghost ) { + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_FRIGHTENED_BLINK); + }); + + setTimeout( 'Game.endFright();', 160 * 4 * Game.levelData.frightFlashesCount); + }, + + endFright : function() { + if( Game.timer ) + Game.timer.resume(); + Game.frightTimer = null; + Game.eaten = 0; + $('.actor').trigger( Game.mode == Game.GHOST_STATE_CHASE ? Game.GHOST_EVENT_CHASE : Game.GHOST_EVENT_SCATTER ); + } +} + +function distance(currentTile, target) { + return Math.sqrt( (target.x - currentTile.x) * (target.x - currentTile.x) + (target.y - currentTile.y)*(target.y - currentTile.y)); +}; + +//Game objects: +function Actor(){} +Actor.prototype = { + node : null, + animations : null, + x : null, + y : null, + speed : null, + direction : null, // 1: up, 2: left, 3:down, 4: right + directionX : 0, + directionY : 0, + + getX : function() { + return x; + }, + + getY : function() { + return y; + }, + + getTileX : function() { + return Math.floor(this.x / TILE_SIZE); + }, + + getTileY : function() { + return Math.floor(this.y / TILE_SIZE); + }, + + getTile : function() { + return this.getTileX() + this.getTileY() * WIDTH_TILE_COUNT; + }, + + getInsideTileX : function() { + return this.x % TILE_SIZE; + }, + + getInsideTileY : function() { + return this.y % TILE_SIZE; + }, + + move : function() { + if( !Game.running ) + return; + this.x += this.directionX * this.speed * ACTOR_SPEED; + this.y += this.directionY * this.speed * ACTOR_SPEED; + this.node.x(this.x ); + this.node.y(this.y ); + }, + + up : function( force ) { + if( force || this.direction != UP ) { + this.directionX = 0; + this.directionY = -1; + this.direction = UP; + this.node.setAnimation(this.animations["up"]); + this.node.flipv(false); + this.node.fliph(false); + this.center(); + } + }, + + down : function( force ) { + if( force || this.direction != DOWN ) { + this.directionX = 0; + this.directionY = 1; + this.direction = DOWN; + if( this.animations["down"] ) { + this.node.setAnimation(this.animations["down"]); + this.node.fliph( false ); + } else { + this.node.setAnimation(this.animations["up"]); + this.node.flipv( true ); + this.node.fliph( false ); + } + this.center(); + } + }, + + left : function( force ) { + if( force || this.direction != LEFT ) { + this.directionX = -1; + this.directionY = 0; + this.direction = LEFT; + this.node.flipv( false ); + if( this.animations["left"] ) { + this.node.setAnimation(this.animations["left"]); + } else { + this.node.setAnimation(this.animations["right"]); + this.node.fliph( true ); + } + this.center(); + } + }, + + right : function( force ) { + if( force || this.direction != RIGHT ) { + this.directionX = 1; + this.directionY = 0; + this.direction = RIGHT; + this.node.setAnimation(this.animations["right"]); + this.node.fliph( false ); + this.node.flipv( false ); + this.center(); + } + }, + + canLeft : function() { + return Game.maze.structure[this.getTileX() + this.getTileY() * WIDTH_TILE_COUNT - 1] <= 0; + }, + + canRight : function() { + return Game.maze.structure[this.getTileX() + this.getTileY() * WIDTH_TILE_COUNT + 1] <= 0; + }, + + canUp : function() { + return Game.maze.structure[this.getTileX() + (this.getTileY() - 1 ) * WIDTH_TILE_COUNT ] <= 0; + }, + + canDown : function() { + return Game.maze.structure[this.getTileX() + (this.getTileY() + 1 ) * WIDTH_TILE_COUNT ] <= 0; + }, + + isNearMiddleTile : function() { + return Math.abs( HALF_TILE_SIZE - this.getInsideTileX() ) < 4 && Math.abs( HALF_TILE_SIZE - this.getInsideTileY() ) < 4; + }, + + center : function() { + this.x = this.getTileX() * TILE_SIZE + HALF_TILE_SIZE; + this.y = this.getTileY() * TILE_SIZE + HALF_TILE_SIZE; + }, + + isInTunnel : function() { + var tile = this.getTile(); + return $.inArray(tile, Game.maze.tunnel) > -1; + } +}; + +/*********************************************/ +/****************** PACMAN *******************/ +/*********************************************/ +function Pacman() { + this.animations = { + "right": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsety: 16, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "up": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsetx: 64, offsety: 16, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "die": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 7, offsety: 208, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL | $.gameQuery.ANIMATION_ONCE | $.gameQuery.ANIMATION_CALLBACK }), + "die2": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 4, offsety: 240, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL | $.gameQuery.ANIMATION_ONCE }) + } +}; +Pacman.prototype = { + x : Game.PACMAN_START_X, + y : Game.PACMAN_START_Y, + speed : null, + directionX : 0, + directionY : 0, + lastEatenGhost : null, + + stop : false, + previousTile : null, + + init : function() { + this.x = Game.PACMAN_START_X; + this.y = Game.PACMAN_START_Y; + this.speed = Game.levelData.pacman.speed; + this.right(true); + this.left(true); + this.node.x(this.x); + this.node.y(this.y); + }, + + left : function() { + if( this.direction != LEFT && this.canLeft() ) { + this.stop = false; + this._super("left", arguments); + } + }, + + right : function() { + if( this.direction != RIGHT && this.canRight() ) { + this.stop = false; + this._super("right", arguments); + } + }, + + up : function() { + if( this.direction != UP && this.canUp() ) { + this.stop = false; + this._super("up", arguments); + } + }, + + down : function() { + if( this.direction != DOWN && this.canDown() ) { + this.stop = false; + this._super("down", arguments); + } + }, + + move : function() { + if( !this.stop ) { + this.previousTile = {x: this.getTileX(), y: this.getTileY()}; + this._super("move", arguments); + var currentTile = {x: this.getTileX(), y: this.getTileY()}; + if( this.previousTile.x !== currentTile.x || this.previousTile.y !== currentTile.y ) { + var id = this.getTile(); + if( Game.dots[ id ] ) + this.eatDot( id ); + if( id == Game.maze.bonus_target ) + this.eatBonus(); + this.eatGhosts(); + } + + var inTunnel = this.isInTunnel(); + if( this.x < 0 ) + this.x += PLAYGROUND_WIDTH; + if( this.x > PLAYGROUND_WIDTH ) + this.x -= PLAYGROUND_WIDTH; + switch( this.direction ) { + case LEFT : + if( !inTunnel && !this.canLeft() ) + this.stop = true; + break; + case RIGHT : + if( !inTunnel && !this.canRight() ) + this.stop = true; + break; + case UP : + if( !this.canUp() ) + this.stop = true; + break; + case DOWN : + if( !this.canDown() ) + this.stop = true; + break; + } + } + }, + + eatDot : function(id) { + Game.eat(Game.dots[id]); + $('.actor').trigger(Game.GHOST_EVENT_DOT_EATEN); + if( Game.dots[id] === "bigDot" ) { + $.each(Game.ghosts, function(index, ghost ) { + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_FRIGHTENED) + }); + + Game.timer.pause(); + if( Game.frightTimer ) + clearTimeout( Game.frightTimer ); + Game.frightTimer = setTimeout( 'Game.nearEndFright();', Game.levelData.frightTime * 1000 - 160 * 4 * Game.levelData.frightFlashesCount); + } + + Game.dots[id] = null; + $("#" + id ).addClass("hiddenDot"); + }, + + eatGhosts : function() { + var tile = this.getTile(); + $.each(Game.ghosts, function(index, ghost ) { + if( tile == ghost.getTile() ) { + Game.pacman.eatGhost( ghost ); + } + }); + }, + + eatGhost : function( ghost ) { + if( ghost.state == Game.GHOST_STATE_EATEN ) { +// console.log( ghost.id + " already eaten" ); + return; + } + if( ghost.state != Game.GHOST_STATE_FRIGHTENED && ghost.state != Game.GHOST_STATE_FRIGHTENED_BLINK ) { + Game.die(); + } else if( Game.pacman.lastEatenGhost !== ghost.id ){ + ghost.state_to(Game.GHOST_STATE_EATEN); +// console.log( "Eating " + ghost.id + " " + ghost.state ); + Game.eatGhost(ghost); + } + }, + + eatBonus : function() { + if( !$("#" + Game.maze.bonus_target).hasClass( Game.levelData.bonus.type) && Game.bonusTimer == null ) + return; + + Sound.play("fruit"); + + eatenBonus.push(Game.levelData.bonus.type); + Game.score += Game.levelData.bonus.points; +// console.log( "Eating bonus " + Game.levelData.bonus.points + " " + Game.score ); + SCOREBOARD.add( Game.levelData.bonus.points ); + Game.hideBonus(); + }, + + die : function() { + Sound.play("dies"); + this.node.setAnimation(this.animations["die"], function(node) { + Game.pacman.node.setAnimation(Game.pacman.animations["die2"]); + }); + } +}; + +// Overriding Actor.methods() method +heriter(Pacman.prototype, Actor.prototype); + +function Ghost(id, ghostIndex, start, scatterTarget, personnalTarget, dotsLimits, state ) { + this.animations = { + "normal_up": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsety: 48 + ghostIndex * 32, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "normal_right": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsetx: 128, offsety: 48 + ghostIndex * 32, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "normal_down": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsetx: 64, offsety: 48 + ghostIndex * 32, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "frightened": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsetx: 0, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "frightened_blink": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 4, offsetx: 0, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "eaten_up": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 1, offsetx: 128, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "eaten_down": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 1, offsetx: 160, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "eaten_right": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 1, offsetx: 192, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }) + } + this.animations["up"] = this.animations["normal_up"]; + this.animations["down"] = this.animations["normal_down"]; + this.animations["right"] = this.animations["normal_right"]; + + this.id = id; + this.scatterTarget = scatterTarget; + this.personnalTarget = personnalTarget; + this.x = start.x; + this.y = start.y; + this.startingTileX = start.x; + this.startingTileY = start.y; + + this.state = state; + + this.dotsLimits = dotsLimits; + + this.prey = Game.pacman; +}; + +Ghost.prototype = { + id : null, + startingTileX : 0, + startingTileY : 0, + initialSpeed : 0, + speed : 0, + directionX : 0, + directionY : 0, + + state: null, + scatterTarget : null, + lastDirectionTile : null, + + prey : null, + + dotsCounter : 0, + dotsLimits : [], + + init : function() { + this.dotsCounter = 0; + this.speed = 0; + this.x = this.startingTileX; + this.y = this.startingTileY; + this.right(true); + this.left(true); + this.state = Game.GHOST_STATE_IN_JAIL; + this.node.x(this.x); + this.node.y(this.y); + }, + + target : function() { + switch( this.state ) { + case Game.GHOST_STATE_CHASE : + return this.personnalTarget(); + case Game.GHOST_STATE_SCATTER : + return this.scatterTarget; + case Game.GHOST_STATE_FRIGHTENED : + var currentTile = {x: this.getTileX(), y: this.getTileY()}; + var targets = new Array(); + if( this.canUp() && this.direction != DOWN ) + targets.push( {x:currentTile.x, y:currentTile.y - 1} ); + if( this.canDown() && this.direction != UP ) + targets.push( {x:currentTile.x, y:currentTile.y + 1} ); + if( this.canLeft() && this.direction != RIGHT ) + targets.push( {x:currentTile.x - 1, y:currentTile.y} ); + if( this.canRight() && this.direction != LEFT ) + targets.push( {x:currentTile.x + 1, y:currentTile.y} ); + return targets[ parseInt(Math.random() * targets.length ) ]; + case Game.GHOST_STATE_IN_JAIL : + case Game.GHOST_STATE_EATEN : + return {x: 13, y: 14}; + } + }, + + loadBindings : function() { + this.node.bind(Game.GHOST_EVENT_CHASE, {ghost: this}, function(evt) { + var ghost = evt.data.ghost; + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_CHASE); + }); + this.node.bind(Game.GHOST_EVENT_SCATTER, {ghost: this}, function(evt) { + var ghost = evt.data.ghost; + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_SCATTER); + }); + this.node.bind(Game.GHOST_EVENT_DOT_EATEN, {ghost: this}, function(evt) { + var ghost = evt.data.ghost; + if( ghost.state == Game.GHOST_STATE_IN_JAIL && ghost.dotsCounter++ >= ghost.dotsLimits[Math.min(Game.level, ghost.dotsLimits.length - 1)] ) { + ghost.speed = ghost.initialSpeed; + ghost.state_to(Game.mode); + } + }); + }, + + personnalTarget : function() { + }, + + state_to : function( state ) { + var up; + var down; + var right; + var reverse = this.state != Game.GHOST_STATE_FRIGHTENED && this.state != Game.GHOST_STATE_IN_JAIL; // previous state + this.state = state; + switch( state ) { + case Game.GHOST_STATE_CHASE : + this.speed = Game.levelData.ghost.speed; + case Game.GHOST_STATE_SCATTER : + this.speed = Game.levelData.ghost.speed; + case Game.GHOST_STATE_IN_JAIL : + up = this.animations["normal_up"]; + down = this.animations["normal_down"]; + right = this.animations["normal_right"]; + break; + case Game.GHOST_STATE_FRIGHTENED : + up = down = right = this.animations["frightened"]; + this.speed = Game.levelData.ghost.frightSpeed; + break; + case Game.GHOST_STATE_FRIGHTENED_BLINK : + up = down = right = this.animations["frightened_blink"]; + this.state = Game.GHOST_STATE_FRIGHTENED; + break; + case Game.GHOST_STATE_EATEN : + up = this.animations["eaten_up"]; + down = this.animations["eaten_down"]; + right = this.animations["eaten_right"]; + this.speed = 1; + break; + } + + + this.animations["up"] = up; + this.animations["down"] = down; + this.animations["right"] = right; + + if( reverse ) + switch( this.direction ) { + case UP: + this.direction = DOWN; + break; + case LEFT: + this.direction = RIGHT; + break; + case DOWN: + this.direction = UP; + break; + case RIGHT: + this.direction = LEFT; + break; + } + + var inTunnel = this.isInTunnel(); + var distances = [ + {direction: UP, distance: this.canUp() && this.direction != DOWN ? 1 : INFINITY}, + {direction: LEFT, distance: (inTunnel && this.direction == LEFT ) || (this.canLeft() && this.direction != RIGHT) ? 1 : INFINITY}, + {direction: DOWN, distance: this.canDown() && this.direction != UP ? 1 : INFINITY}, + {direction: RIGHT, distance: (inTunnel && this.direction == RIGHT ) || (this.canRight() && this.direction != LEFT) ? 1 : INFINITY}, + ]; + distances.sort( function(a, b) { + if( a.distance == b.distance ) + return a.direction - b.direction; + return a.distance - b.distance; + }) + var selected = distances[0]; + + switch( selected.direction ) { + case UP: + this.up(true); + break; + case LEFT: + this.left(true); + break; + case DOWN: + this.down(true); + break; + case RIGHT: + this.right(true); + break; + } + + }, + + canUp : function() { + switch( this.getTile() ) { + case 404: + case 407: + case 684: + case 687: + return false; + case 461: + case 462: + return true; + default: + return Game.maze.structure[ this.getTileX() + (this.getTileY() - 1 ) * WIDTH_TILE_COUNT ] <= 0; + } + }, + + canDown : function() { + switch( this.getTile() ) { + case 405: + case 406: + return false; + default: + return Game.maze.structure[ this.getTileX() + (this.getTileY() + 1 ) * WIDTH_TILE_COUNT ] <= 0; + } + }, + + move : function() { + this._super("move", arguments); + var currentTile = {x: this.getTileX(), y: this.getTileY()}; + var id = this.getTile();; + if( this.lastDirectionTile != id && this.isNearMiddleTile()) { + this.lastDirectionTile = id; + this.eaten(); + + var distances = null; + var target = this.target(); + if( this.state == Game.GHOST_STATE_EATEN && id == Game.maze.ghost_frightened_target ) { + this.state_to(Game.mode); + } + + var inTunnel = this.isInTunnel(); + if( inTunnel ) + this.speed = Game.levelData.ghost.tunnelSpeed; + else if( this.state != Game.GHOST_STATE_IN_JAIL ) + this.speed = this.state == Game.GHOST_STATE_FRIGHTENED ? Game.levelData.ghost.frightSpeed : Game.levelData.ghost.speed; + + if( this.x < 0 ) + this.x += PLAYGROUND_WIDTH; + if( this.x > PLAYGROUND_WIDTH ) + this.x -= PLAYGROUND_WIDTH; + + if( Game.maze.choice_tiles.indexOf( id ) != -1 ) { + distances = [ + {direction: UP, distance: this.canUp() && this.direction != DOWN ? distance({x:currentTile.x, y:currentTile.y - 1}, target ) : INFINITY}, + {direction: LEFT, distance: this.canLeft() && this.direction != RIGHT ? distance( {x:currentTile.x - 1, y:currentTile.y }, target ) : INFINITY}, + {direction: DOWN, distance: this.canDown() && this.direction != UP ? distance({x:currentTile.x, y:currentTile.y + 1}, target ) : INFINITY}, + {direction: RIGHT, distance: this.canRight() && this.direction != LEFT ? distance({x:currentTile.x + 1, y:currentTile.y}, target ) : INFINITY}, + ]; + } else { + distances = [ + {direction: UP, distance: this.canUp() && this.direction != DOWN ? 1 : INFINITY}, + {direction: LEFT, distance: (inTunnel && this.direction == LEFT ) || (this.canLeft() && this.direction != RIGHT) ? 1 : INFINITY}, + {direction: DOWN, distance: this.canDown() && this.direction != UP ? 1 : INFINITY}, + {direction: RIGHT, distance: (inTunnel && this.direction == RIGHT ) || (this.canRight() && this.direction != LEFT) ? 1 : INFINITY}, + ]; + } + distances.sort( function(a, b) { + if( a.distance == b.distance ) + return a.direction - b.direction; + return a.distance - b.distance; + }) + var selected = distances[0]; + + switch( selected.direction ) { + case LEFT : + if( this.direction != LEFT ) + this.left(); + break; + case RIGHT : + if( this.direction != RIGHT ) + this.right(); + break; + case UP : + if( this.direction != UP ) + this.up(); + break; + case DOWN : + if( this.direction != DOWN ) + this.down(); + break; + } + } + + var inTunnel = this.isInTunnel(); + if( this.x < 0 ) + this.x += PLAYGROUND_WIDTH; + if( this.x > PLAYGROUND_WIDTH ) + this.x -= PLAYGROUND_WIDTH; + + }, + + eaten : function(target) { + if( typeof target === "undefined" ) + target = this; + if( target.getTile() == Game.pacman.getTile() ) { +// console.log(" Eaten from ghost" ); + Game.pacman.eatGhost(target); +// if( target.state != Game.GHOST_STATE_FRIGHTENED && target.state != Game.GHOST_STATE_EATEN ) { +// Game.die(); +// } else { +// target.state_to(Game.GHOST_STATE_EATEN); +// Game.eatGhost(this); +// } + } + } +}; + +heriter(Ghost.prototype, Actor.prototype); diff --git a/js/pacman-core.js~ b/js/pacman-core.js~ new file mode 100644 index 0000000..2439e15 --- /dev/null +++ b/js/pacman-core.js~ @@ -0,0 +1,999 @@ +var Game = { + id : null, + type : "offline", + player : 1, + + PACMAN_START_X : 14 * TILE_SIZE, + PACMAN_START_Y : 24 * TILE_SIZE, + + GHOST_STATE_CHASE : 1, + GHOST_STATE_SCATTER : 2, + GHOST_STATE_FRIGHTENED : 3, + GHOST_STATE_IN_JAIL : 4, + GHOST_STATE_EATEN : 5, + GHOST_STATE_FRIGHTENED_BLINK : 6, + + + GHOST_EVENT_CHASE : "ghost_event_chase", + GHOST_EVENT_SCATTER : "ghost_event_scatter", + GHOST_EVENT_DOT_EATEN : "ghost_event_dot_eaten", + + DOT_POINTS : 10, + BIG_DOT_POINTS : 50, + totalDots : 0, + + dots : {}, + timer : null, + frightTimer : null, + bonusTimer : null, + level : -1, + levelData : null, + step : 0, + score : 0, + eatenDots : 0, + lives : 3, + running : false, + mode : 2, // Game.GHOST_STATE_SCATTER + frightMode : false, + eaten: 0, + + pacman : null, + miss : null, + hero : null, + blinky : null, + pinky : null, + inky : null, + clyde : null, + ghosts : new Array(), + actors : {}, + heroes : new Array(), + maze : MAZE, + + init : function() { + + GUI.updateMessage("READY"); + + $(".dot.hiddenDot").each( function(incr, elt) { + Game.dots[elt.id] = "dot"; + }); + $(".dot.hiddenDot").removeClass("hiddenDot"); + + $(".bigDot.hiddenDot").each( function(incr, elt) { + Game.dots[elt.id] = "bigDot"; + }); + $(".bigDot.hiddenDot").removeClass("hiddenDot") + + Game.totalDots = $(".dot").length + $(".bigDot").length; + + SCOREBOARD.init(); + SCOREBOARD.set_score( Game.score ); + + Game.level++; + Game.step = 0; + Game.eatenDots = 0; + + GUI.updateLevelNumber( Game.level + 1 ); + + Game.build(LEVELS[Math.min(Game.level, LEVELS.length)]); + }, + + build : function(data) { + Game.levelData = data; + Game.addPacman(); + Game.addGhosts(); + Sound.play("opening"); + setTimeout("Game.start();", 4500); + }, + + start : function() { + //if( $.browser.webkit ) + $(document).keydown( function( event ) { + if( event.which > 36 && event.which < 41 ) + return false; + } ); + // $(document).keypress(scrollPreventFct ); + + GUI.updateMessage(""); + Game.timer = new PausableTimer(Game.timerManager, Game.levelData.mode[Game.step] * 1000); + Game.running = true; + }, + + levelComplete : function() { + Game.running = false; + Game.timer.stop(); + Game.timer = null; + + setTimeout("Game.init();", 3000); + }, + + eat : function(type) { + Game.eatenDots++; + if( type === "bigDot" ) { + Game.score += Game.BIG_DOT_POINTS; +// console.log( "Eating big dot " + Game.score ); + SCOREBOARD.add( Game.BIG_DOT_POINTS ); + } else { + Game.score += Game.DOT_POINTS; +// console.log( "Eating dot " + Game.score ); + SCOREBOARD.add( Game.DOT_POINTS ); + } + + if( Game.eatenDots == 70 || Game.eatenDots == 170 ) { + Game.bonusTimer = setTimeout("Game.hideBonus();", ( 9 + Math.random() ) * 1000 ); + $("#" + Game.maze.bonus_target).addClass( Game.levelData.bonus.type); + } + + if( Game.eatenDots === Game.totalDots ) + Game.levelComplete(); + }, + + eatGhost : function(ghost) { + Sound.play("ghost"); + Game.eaten++; + var points = Game.eaten * 200; + Game.score += points; +// console.log(new Date() + " Eating " + ghost.id + " " + (Game.eaten * 200) + " "+ Game.score ); + SCOREBOARD.add( points ); + }, + + hideBonus : function() { + $("#" + Game.maze.bonus_target).removeClass( Game.levelData.bonus.type); + Game.bonusTimer = null; + }, + + die : function() { + Game.running = false; + $.each( Game.actors, function(index, actor) { + actor.speed = 0; + }) + Game.pacman.die(); + Game.timer.stop(); + Game.step = 0; + Game.timer = null; + $("#life" + Game.lives).effect( "pulsate", {times:3, mode:"hide"}, 500 ); + Game.lives--; + if( Game.lives > 0 ) + setTimeout( "Game.startAfterDie();", 3000); + else { + GUI.drawText( $("#message"), "GAME OVER", true ); + Game.show_game_over(); + } + }, + + show_game_over: function() { + }, + + startAfterDie : function() { + var dotsCounters = new Array(); + $.each(Game.ghosts, function(index, ghost ) { + dotsCounters[index] = ghost.dotsCounter; + }); + + Game.addGhosts(); + Game.addPacman(); + //Game.addMissPacman(); + + $.each(Game.ghosts, function(index, ghost ) { + ghost.dotsCounter = dotsCounters[index]; + if( ghost.dotsCounter >= ghost.dotsLimits[Math.min(Game.level, ghost.dotsLimits.length - 1)] ) { + ghost.speed = ghost.initialSpeed; + ghost.state_to(Game.GHOST_STATE_SCATTER); + } + }); + + Game.running = true; + Game.step = 0; + Game.timer = new PausableTimer(Game.timerManager, Game.levelData.mode[Game.step] * 1000); + }, + + timerManager : function() { + Game.step++; + if( Game.step % 2 == 1 ) { + $(".actor").trigger(Game.GHOST_EVENT_CHASE); + Game.mode = Game.GHOST_STATE_CHASE; + } else { + $(".actor").trigger(Game.GHOST_EVENT_SCATTER); + Game.mode = Game.GHOST_STATE_SCATTER; + } + if( Game.step < Game.levelData.mode.length - 1 && Game.levelData.mode[Game.step] != INFINITY ) + Game.timer = new PausableTimer(Game.timerManager, Game.levelData.mode[Game.step] * 1000); + }, + + addPacman : function() { + if( $("#pacman").length == 0) { + Game.pacman = new Pacman(); + $("#actors").addSprite("pacman", {animation: Game.pacman.animations["right"], posx:Game.pacman.x, posy: Game.pacman.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.pacman.node = $("#pacman"); + Game.pacman.node.addClass( "actor" ); + Game.actors[ "pacman" ] = Game.pacman; + Game.heroes[ "pacman" ] = Game.pacman; + + Game.hero = Game.pacman; + } + Game.pacman.init(); + Game.pacman.speed = Game.levelData.pacman.speed; + Game.pacman.left(); + }, + + addMissPacman : function() { + if( $("#miss_pacman").length == 0) { + Game.miss = new Pacman(); + Game.miss.animations["right"] = new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsety: 272, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }); + Game.miss.animations["up"] = new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsetx: 96, offsety: 272, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }); + + $("#actors").addSprite("miss_pacman", {animation: Game.miss.animations["right"], posx:Game.miss.x, posy: Game.miss.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.miss.node = $("#miss_pacman"); + Game.miss.node.addClass( "actor" ); + Game.actors[ "miss_pacman" ] = Game.miss; + Game.heroes[ "miss_pacman" ] = Game.miss; + } + Game.miss.init(); + Game.miss.x = Game.MISS_PACMAN_START_X; + Game.miss.y = Game.MISS_PACMAN_START_Y; + Game.miss.speed = Game.levelData.pacman.speed; + Game.miss.right(true); + Game.miss.left(true); + Game.miss.node.x(Game.miss.x); + Game.miss.node.y(Game.miss.y); + Game.miss.right(); + }, + + addGhosts : function() { + Game.addBlinky(); + Game.addPinky(); + Game.addInky(); + Game.addClyde(); + }, + + addBlinky : function() { + if( $("#blinky").length == 0 ) { + Game.blinky = new Ghost("blinky", 0, {x: 14 * TILE_SIZE, y: 14 * TILE_SIZE}, {x: 25, y: 0 }, function() { + var prey = Game.actors[ "blinky" ].prey; + return {x: prey.getTileX(), y: prey.getTileY()}; + }, [0,0,0], Game.GHOST_STATE_SCATTER); + Game.blinky.center(); + $("#actors").addSprite("blinky", {animation: Game.blinky.animations["right"], posx:Game.blinky.x, posy: Game.blinky.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.blinky.node = $("#blinky"); + Game.blinky.node.addClass( "actor" ); + Game.actors[ "blinky" ] = Game.blinky; + Game.blinky.loadBindings(); + + Game.blinky.originalTarget = Game.blinky.target; + Game.blinky.target = function() { + var remainingDots = Game.totalDots - Game.eatenDots; + var elroySpecs = Game.levelData.ghost; + if( ( Game.blinky.state == Game.GHOST_STATE_SCATTER || Game.blinky.state == Game.GHOST_STATE_CHASE ) && remainingDots <= elroySpecs.elroy1Dots ) { + if( remainingDots <= elroySpecs.elroy2Dots ) { + Game.blinky.speed = elroySpecs.elroy2Speed; + } + else { + Game.blinky.speed = elroySpecs.elroy1Speed; + } + + return Game.blinky.personnalTarget(); + } + return Game.blinky.originalTarget(); + }; + + Game.ghosts.push( Game.blinky ); + } else { + Game.blinky.init(); + } + Game.blinky.state = Game.GHOST_STATE_SCATTER; + Game.blinky.left(); + Game.blinky.initialSpeed = Game.levelData.ghost.speed; + Game.blinky.speed = Game.blinky.initialSpeed; + }, + + addPinky : function() { + if( $("#pinky").length == 0 ) { + Game.pinky = new Ghost("pinky", 1, {x: 14 * TILE_SIZE, y: 16 * TILE_SIZE}, {x: 2, y: 0 }, function() { + var prey = Game.actors[ "pinky" ].prey; + var direction = this.prey.direction; + if( direction % 2 == 0 ) + return {x: prey.getTileX() + (direction == LEFT ? -4 : 4), y: prey.getTileY()}; + else + return {x: prey.getTileX(), y: prey.getTileY() + (direction == UP ? -4 : 4) }; + }, [0,0,0], Game.GHOST_STATE_IN_JAIL); + Game.pinky.center(); + $("#actors").addSprite("pinky", {animation: Game.pinky.animations["right"], posx: Game.pinky.x, posy: Game.pinky.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.pinky.node = $("#pinky"); + Game.pinky.node.addClass( "actor" ); + Game.actors[ "pinky" ] = Game.pinky; + Game.pinky.loadBindings(); + + Game.ghosts.push( Game.pinky ); + } else { + Game.pinky.init(); + } + Game.pinky.initialSpeed = Game.levelData.ghost.speed; + Game.pinky.left(); + }, + + addInky : function() { + if( $("#inky").length == 0 ) { + Game.inky = new Ghost("inky", 2, {x: 12 * TILE_SIZE, y: 16 * TILE_SIZE}, {x: 27, y: 34 }, function() { + var prey = Game.actors[ "inky" ].prey; + var direction = prey.direction; + if( direction % 2 == 0 ) + direction = {x: prey.getTileX() + (direction == LEFT ? -2 : 2) - Game.blinky.getTileX(), y: prey.getTileY() - Game.blinky.getTileY()}; + else + direction = {x: prey.getTileX() - Game.blinky.getTileX(), y: prey.getTileY() + (direction == UP ? -2 : 2) - Game.blinky.getTileY()}; + return {x: direction.x * 2, y: direction.y * 2}; + }, [30,0,0], Game.GHOST_STATE_IN_JAIL); + Game.inky.center(); + $("#actors").addSprite("inky", {animation: Game.inky.animations["right"], posx:Game.inky.x, posy: Game.inky.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.inky.node = $("#inky"); + Game.inky.node.addClass( "actor" ); + Game.actors[ "inky" ] = Game.inky; + Game.inky.loadBindings(); + + Game.ghosts.push( Game.inky ); + } else { + Game.inky.init(); + } + Game.inky.initialSpeed = Game.levelData.ghost.speed; + Game.inky.right(); + }, + + addClyde : function() { + if( $("#clyde").length == 0 ) { + Game.clyde = new Ghost("clyde", 3, {x: 16 * TILE_SIZE, y: 16 * TILE_SIZE}, {x: 0, y: 34 }, function() { + var prey = Game.actors[ "clyde" ].prey; + return distance( {x: this.getTileX(), y: this.getTileY()} , {x: prey.getTileX(), y: prey.getTileY()}) < 8 ? + this.scatterTarget : {x: prey.getTileX(), y: prey.getTileY()}; + }, [60,50,0], Game.GHOST_STATE_IN_JAIL); + Game.clyde.center(); + $("#actors").addSprite("clyde", {animation: Game.clyde.animations["right"], posx:Game.clyde.x, posy: Game.clyde.y, width: ACTOR_SIZE, height: ACTOR_SIZE}); + Game.clyde.node = $("#clyde"); + Game.clyde.node.addClass( "actor" ); + Game.actors[ "clyde" ] = Game.clyde; + Game.clyde.loadBindings(); + + Game.ghosts.push( Game.clyde ); + } else { + Game.clyde.init(); + } + Game.clyde.initialSpeed = Game.levelData.ghost.speed; + Game.clyde.left(); + }, + + moveGhosts : function() { + $.each(Game.ghosts, function(index, ghost ) { + ghost.move(); + }); + }, + + nearEndFright : function() { + $.each(Game.ghosts, function(index, ghost ) { + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_FRIGHTENED_BLINK); + }); + + setTimeout( 'Game.endFright();', 160 * 4 * Game.levelData.frightFlashesCount); + }, + + endFright : function() { + if( Game.timer ) + Game.timer.resume(); + Game.frightTimer = null; + Game.eaten = 0; + $('.actor').trigger( Game.mode == Game.GHOST_STATE_CHASE ? Game.GHOST_EVENT_CHASE : Game.GHOST_EVENT_SCATTER ); + } +} + +function distance(currentTile, target) { + return Math.sqrt( (target.x - currentTile.x) * (target.x - currentTile.x) + (target.y - currentTile.y)*(target.y - currentTile.y)); +}; + +//Game objects: +function Actor(){} +Actor.prototype = { + node : null, + animations : null, + x : null, + y : null, + speed : null, + direction : null, // 1: up, 2: left, 3:down, 4: right + directionX : 0, + directionY : 0, + + getX : function() { + return x; + }, + + getY : function() { + return y; + }, + + getTileX : function() { + return Math.floor(this.x / TILE_SIZE); + }, + + getTileY : function() { + return Math.floor(this.y / TILE_SIZE); + }, + + getTile : function() { + return this.getTileX() + this.getTileY() * WIDTH_TILE_COUNT; + }, + + getInsideTileX : function() { + return this.x % TILE_SIZE; + }, + + getInsideTileY : function() { + return this.y % TILE_SIZE; + }, + + move : function() { + if( !Game.running ) + return; + this.x += this.directionX * this.speed * ACTOR_SPEED; + this.y += this.directionY * this.speed * ACTOR_SPEED; + this.node.x(this.x ); + this.node.y(this.y ); + }, + + up : function( force ) { + if( force || this.direction != UP ) { + this.directionX = 0; + this.directionY = -1; + this.direction = UP; + this.node.setAnimation(this.animations["up"]); + this.node.flipv(false); + this.node.fliph(false); + this.center(); + } + }, + + down : function( force ) { + if( force || this.direction != DOWN ) { + this.directionX = 0; + this.directionY = 1; + this.direction = DOWN; + if( this.animations["down"] ) { + this.node.setAnimation(this.animations["down"]); + this.node.fliph( false ); + } else { + this.node.setAnimation(this.animations["up"]); + this.node.flipv( true ); + this.node.fliph( false ); + } + this.center(); + } + }, + + left : function( force ) { + if( force || this.direction != LEFT ) { + this.directionX = -1; + this.directionY = 0; + this.direction = LEFT; + this.node.flipv( false ); + if( this.animations["left"] ) { + this.node.setAnimation(this.animations["left"]); + } else { + this.node.setAnimation(this.animations["right"]); + this.node.fliph( true ); + } + this.center(); + } + }, + + right : function( force ) { + if( force || this.direction != RIGHT ) { + this.directionX = 1; + this.directionY = 0; + this.direction = RIGHT; + this.node.setAnimation(this.animations["right"]); + this.node.fliph( false ); + this.node.flipv( false ); + this.center(); + } + }, + + canLeft : function() { + return Game.maze.structure[this.getTileX() + this.getTileY() * WIDTH_TILE_COUNT - 1] <= 0; + }, + + canRight : function() { + return Game.maze.structure[this.getTileX() + this.getTileY() * WIDTH_TILE_COUNT + 1] <= 0; + }, + + canUp : function() { + return Game.maze.structure[this.getTileX() + (this.getTileY() - 1 ) * WIDTH_TILE_COUNT ] <= 0; + }, + + canDown : function() { + return Game.maze.structure[this.getTileX() + (this.getTileY() + 1 ) * WIDTH_TILE_COUNT ] <= 0; + }, + + isNearMiddleTile : function() { + return Math.abs( HALF_TILE_SIZE - this.getInsideTileX() ) < 4 && Math.abs( HALF_TILE_SIZE - this.getInsideTileY() ) < 4; + }, + + center : function() { + this.x = this.getTileX() * TILE_SIZE + HALF_TILE_SIZE; + this.y = this.getTileY() * TILE_SIZE + HALF_TILE_SIZE; + }, + + isInTunnel : function() { + var tile = this.getTile(); + return $.inArray(tile, Game.maze.tunnel) > -1; + } +}; + +/*********************************************/ +/****************** PACMAN *******************/ +/*********************************************/ +function Pacman() { + this.animations = { + "right": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsety: 16, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "up": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 3, offsetx: 64, offsety: 16, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "die": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 7, offsety: 208, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL | $.gameQuery.ANIMATION_ONCE | $.gameQuery.ANIMATION_CALLBACK }), + "die2": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 4, offsety: 240, delta: ACTOR_SIZE, rate: 120, type: $.gameQuery.ANIMATION_HORIZONTAL | $.gameQuery.ANIMATION_ONCE }) + } +}; +Pacman.prototype = { + x : Game.PACMAN_START_X, + y : Game.PACMAN_START_Y, + speed : null, + directionX : 0, + directionY : 0, + lastEatenGhost : null, + + stop : false, + previousTile : null, + + init : function() { + this.x = Game.PACMAN_START_X; + this.y = Game.PACMAN_START_Y; + this.speed = Game.levelData.pacman.speed; + this.right(true); + this.left(true); + this.node.x(this.x); + this.node.y(this.y); + }, + + left : function() { + if( this.direction != LEFT && this.canLeft() ) { + this.stop = false; + this._super("left", arguments); + } + }, + + right : function() { + if( this.direction != RIGHT && this.canRight() ) { + this.stop = false; + this._super("right", arguments); + } + }, + + up : function() { + if( this.direction != UP && this.canUp() ) { + this.stop = false; + this._super("up", arguments); + } + }, + + down : function() { + if( this.direction != DOWN && this.canDown() ) { + this.stop = false; + this._super("down", arguments); + } + }, + + move : function() { + if( !this.stop ) { + this.previousTile = {x: this.getTileX(), y: this.getTileY()}; + this._super("move", arguments); + var currentTile = {x: this.getTileX(), y: this.getTileY()}; + if( this.previousTile.x !== currentTile.x || this.previousTile.y !== currentTile.y ) { + var id = this.getTile(); + if( Game.dots[ id ] ) + this.eatDot( id ); + if( id == Game.maze.bonus_target ) + this.eatBonus(); + this.eatGhosts(); + } + + var inTunnel = this.isInTunnel(); + if( this.x < 0 ) + this.x += PLAYGROUND_WIDTH; + if( this.x > PLAYGROUND_WIDTH ) + this.x -= PLAYGROUND_WIDTH; + switch( this.direction ) { + case LEFT : + if( !inTunnel && !this.canLeft() ) + this.stop = true; + break; + case RIGHT : + if( !inTunnel && !this.canRight() ) + this.stop = true; + break; + case UP : + if( !this.canUp() ) + this.stop = true; + break; + case DOWN : + if( !this.canDown() ) + this.stop = true; + break; + } + } + }, + + eatDot : function(id) { + Game.eat(Game.dots[id]); + $('.actor').trigger(Game.GHOST_EVENT_DOT_EATEN); + if( Game.dots[id] === "bigDot" ) { + $.each(Game.ghosts, function(index, ghost ) { + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_FRIGHTENED) + }); + + Game.timer.pause(); + if( Game.frightTimer ) + clearTimeout( Game.frightTimer ); + Game.frightTimer = setTimeout( 'Game.nearEndFright();', Game.levelData.frightTime * 1000 - 160 * 4 * Game.levelData.frightFlashesCount); + } + + Game.dots[id] = null; + $("#" + id ).addClass("hiddenDot"); + }, + + eatGhosts : function() { + var tile = this.getTile(); + $.each(Game.ghosts, function(index, ghost ) { + if( tile == ghost.getTile() ) { + Game.pacman.eatGhost( ghost ); + } + }); + }, + + eatGhost : function( ghost ) { + if( ghost.state == Game.GHOST_STATE_EATEN ) { +// console.log( ghost.id + " already eaten" ); + return; + } + if( ghost.state != Game.GHOST_STATE_FRIGHTENED && ghost.state != Game.GHOST_STATE_FRIGHTENED_BLINK ) { + Game.die(); + } else if( Game.pacman.lastEatenGhost !== ghost.id ){ + ghost.state_to(Game.GHOST_STATE_EATEN); +// console.log( "Eating " + ghost.id + " " + ghost.state ); + Game.eatGhost(ghost); + } + }, + + eatBonus : function() { + if( !$("#" + Game.maze.bonus_target).hasClass( Game.levelData.bonus.type) && Game.bonusTimer == null ) + return; + + Sound.play("fruit); + + eatenBonus.push(Game.levelData.bonus.type); + Game.score += Game.levelData.bonus.points; +// console.log( "Eating bonus " + Game.levelData.bonus.points + " " + Game.score ); + SCOREBOARD.add( Game.levelData.bonus.points ); + Game.hideBonus(); + }, + + die : function() { + Sound.play("dies"); + this.node.setAnimation(this.animations["die"], function(node) { + Game.pacman.node.setAnimation(Game.pacman.animations["die2"]); + }); + } +}; + +// Overriding Actor.methods() method +heriter(Pacman.prototype, Actor.prototype); + +function Ghost(id, ghostIndex, start, scatterTarget, personnalTarget, dotsLimits, state ) { + this.animations = { + "normal_up": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsety: 48 + ghostIndex * 32, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "normal_right": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsetx: 128, offsety: 48 + ghostIndex * 32, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "normal_down": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsetx: 64, offsety: 48 + ghostIndex * 32, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "frightened": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 2, offsetx: 0, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "frightened_blink": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 4, offsetx: 0, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "eaten_up": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 1, offsetx: 128, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "eaten_down": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 1, offsetx: 160, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }), + "eaten_right": new $.gameQuery.Animation({imageURL: "img/sprite.png", numberOfFrame: 1, offsetx: 192, offsety: 176, delta: ACTOR_SIZE, rate: 160, type: $.gameQuery.ANIMATION_HORIZONTAL }) + } + this.animations["up"] = this.animations["normal_up"]; + this.animations["down"] = this.animations["normal_down"]; + this.animations["right"] = this.animations["normal_right"]; + + this.id = id; + this.scatterTarget = scatterTarget; + this.personnalTarget = personnalTarget; + this.x = start.x; + this.y = start.y; + this.startingTileX = start.x; + this.startingTileY = start.y; + + this.state = state; + + this.dotsLimits = dotsLimits; + + this.prey = Game.pacman; +}; + +Ghost.prototype = { + id : null, + startingTileX : 0, + startingTileY : 0, + initialSpeed : 0, + speed : 0, + directionX : 0, + directionY : 0, + + state: null, + scatterTarget : null, + lastDirectionTile : null, + + prey : null, + + dotsCounter : 0, + dotsLimits : [], + + init : function() { + this.dotsCounter = 0; + this.speed = 0; + this.x = this.startingTileX; + this.y = this.startingTileY; + this.right(true); + this.left(true); + this.state = Game.GHOST_STATE_IN_JAIL; + this.node.x(this.x); + this.node.y(this.y); + }, + + target : function() { + switch( this.state ) { + case Game.GHOST_STATE_CHASE : + return this.personnalTarget(); + case Game.GHOST_STATE_SCATTER : + return this.scatterTarget; + case Game.GHOST_STATE_FRIGHTENED : + var currentTile = {x: this.getTileX(), y: this.getTileY()}; + var targets = new Array(); + if( this.canUp() && this.direction != DOWN ) + targets.push( {x:currentTile.x, y:currentTile.y - 1} ); + if( this.canDown() && this.direction != UP ) + targets.push( {x:currentTile.x, y:currentTile.y + 1} ); + if( this.canLeft() && this.direction != RIGHT ) + targets.push( {x:currentTile.x - 1, y:currentTile.y} ); + if( this.canRight() && this.direction != LEFT ) + targets.push( {x:currentTile.x + 1, y:currentTile.y} ); + return targets[ parseInt(Math.random() * targets.length ) ]; + case Game.GHOST_STATE_IN_JAIL : + case Game.GHOST_STATE_EATEN : + return {x: 13, y: 14}; + } + }, + + loadBindings : function() { + this.node.bind(Game.GHOST_EVENT_CHASE, {ghost: this}, function(evt) { + var ghost = evt.data.ghost; + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_CHASE); + }); + this.node.bind(Game.GHOST_EVENT_SCATTER, {ghost: this}, function(evt) { + var ghost = evt.data.ghost; + if( ghost.state != Game.GHOST_STATE_IN_JAIL && ghost.state != Game.GHOST_STATE_EATEN ) + ghost.state_to(Game.GHOST_STATE_SCATTER); + }); + this.node.bind(Game.GHOST_EVENT_DOT_EATEN, {ghost: this}, function(evt) { + var ghost = evt.data.ghost; + if( ghost.state == Game.GHOST_STATE_IN_JAIL && ghost.dotsCounter++ >= ghost.dotsLimits[Math.min(Game.level, ghost.dotsLimits.length - 1)] ) { + ghost.speed = ghost.initialSpeed; + ghost.state_to(Game.mode); + } + }); + }, + + personnalTarget : function() { + }, + + state_to : function( state ) { + var up; + var down; + var right; + var reverse = this.state != Game.GHOST_STATE_FRIGHTENED && this.state != Game.GHOST_STATE_IN_JAIL; // previous state + this.state = state; + switch( state ) { + case Game.GHOST_STATE_CHASE : + this.speed = Game.levelData.ghost.speed; + case Game.GHOST_STATE_SCATTER : + this.speed = Game.levelData.ghost.speed; + case Game.GHOST_STATE_IN_JAIL : + up = this.animations["normal_up"]; + down = this.animations["normal_down"]; + right = this.animations["normal_right"]; + break; + case Game.GHOST_STATE_FRIGHTENED : + up = down = right = this.animations["frightened"]; + this.speed = Game.levelData.ghost.frightSpeed; + break; + case Game.GHOST_STATE_FRIGHTENED_BLINK : + up = down = right = this.animations["frightened_blink"]; + this.state = Game.GHOST_STATE_FRIGHTENED; + break; + case Game.GHOST_STATE_EATEN : + up = this.animations["eaten_up"]; + down = this.animations["eaten_down"]; + right = this.animations["eaten_right"]; + this.speed = 1; + break; + } + + + this.animations["up"] = up; + this.animations["down"] = down; + this.animations["right"] = right; + + if( reverse ) + switch( this.direction ) { + case UP: + this.direction = DOWN; + break; + case LEFT: + this.direction = RIGHT; + break; + case DOWN: + this.direction = UP; + break; + case RIGHT: + this.direction = LEFT; + break; + } + + var inTunnel = this.isInTunnel(); + var distances = [ + {direction: UP, distance: this.canUp() && this.direction != DOWN ? 1 : INFINITY}, + {direction: LEFT, distance: (inTunnel && this.direction == LEFT ) || (this.canLeft() && this.direction != RIGHT) ? 1 : INFINITY}, + {direction: DOWN, distance: this.canDown() && this.direction != UP ? 1 : INFINITY}, + {direction: RIGHT, distance: (inTunnel && this.direction == RIGHT ) || (this.canRight() && this.direction != LEFT) ? 1 : INFINITY}, + ]; + distances.sort( function(a, b) { + if( a.distance == b.distance ) + return a.direction - b.direction; + return a.distance - b.distance; + }) + var selected = distances[0]; + + switch( selected.direction ) { + case UP: + this.up(true); + break; + case LEFT: + this.left(true); + break; + case DOWN: + this.down(true); + break; + case RIGHT: + this.right(true); + break; + } + + }, + + canUp : function() { + switch( this.getTile() ) { + case 404: + case 407: + case 684: + case 687: + return false; + case 461: + case 462: + return true; + default: + return Game.maze.structure[ this.getTileX() + (this.getTileY() - 1 ) * WIDTH_TILE_COUNT ] <= 0; + } + }, + + canDown : function() { + switch( this.getTile() ) { + case 405: + case 406: + return false; + default: + return Game.maze.structure[ this.getTileX() + (this.getTileY() + 1 ) * WIDTH_TILE_COUNT ] <= 0; + } + }, + + move : function() { + this._super("move", arguments); + var currentTile = {x: this.getTileX(), y: this.getTileY()}; + var id = this.getTile();; + if( this.lastDirectionTile != id && this.isNearMiddleTile()) { + this.lastDirectionTile = id; + this.eaten(); + + var distances = null; + var target = this.target(); + if( this.state == Game.GHOST_STATE_EATEN && id == Game.maze.ghost_frightened_target ) { + this.state_to(Game.mode); + } + + var inTunnel = this.isInTunnel(); + if( inTunnel ) + this.speed = Game.levelData.ghost.tunnelSpeed; + else if( this.state != Game.GHOST_STATE_IN_JAIL ) + this.speed = this.state == Game.GHOST_STATE_FRIGHTENED ? Game.levelData.ghost.frightSpeed : Game.levelData.ghost.speed; + + if( this.x < 0 ) + this.x += PLAYGROUND_WIDTH; + if( this.x > PLAYGROUND_WIDTH ) + this.x -= PLAYGROUND_WIDTH; + + if( Game.maze.choice_tiles.indexOf( id ) != -1 ) { + distances = [ + {direction: UP, distance: this.canUp() && this.direction != DOWN ? distance({x:currentTile.x, y:currentTile.y - 1}, target ) : INFINITY}, + {direction: LEFT, distance: this.canLeft() && this.direction != RIGHT ? distance( {x:currentTile.x - 1, y:currentTile.y }, target ) : INFINITY}, + {direction: DOWN, distance: this.canDown() && this.direction != UP ? distance({x:currentTile.x, y:currentTile.y + 1}, target ) : INFINITY}, + {direction: RIGHT, distance: this.canRight() && this.direction != LEFT ? distance({x:currentTile.x + 1, y:currentTile.y}, target ) : INFINITY}, + ]; + } else { + distances = [ + {direction: UP, distance: this.canUp() && this.direction != DOWN ? 1 : INFINITY}, + {direction: LEFT, distance: (inTunnel && this.direction == LEFT ) || (this.canLeft() && this.direction != RIGHT) ? 1 : INFINITY}, + {direction: DOWN, distance: this.canDown() && this.direction != UP ? 1 : INFINITY}, + {direction: RIGHT, distance: (inTunnel && this.direction == RIGHT ) || (this.canRight() && this.direction != LEFT) ? 1 : INFINITY}, + ]; + } + distances.sort( function(a, b) { + if( a.distance == b.distance ) + return a.direction - b.direction; + return a.distance - b.distance; + }) + var selected = distances[0]; + + switch( selected.direction ) { + case LEFT : + if( this.direction != LEFT ) + this.left(); + break; + case RIGHT : + if( this.direction != RIGHT ) + this.right(); + break; + case UP : + if( this.direction != UP ) + this.up(); + break; + case DOWN : + if( this.direction != DOWN ) + this.down(); + break; + } + } + + var inTunnel = this.isInTunnel(); + if( this.x < 0 ) + this.x += PLAYGROUND_WIDTH; + if( this.x > PLAYGROUND_WIDTH ) + this.x -= PLAYGROUND_WIDTH; + + }, + + eaten : function(target) { + if( typeof target === "undefined" ) + target = this; + if( target.getTile() == Game.pacman.getTile() ) { +// console.log(" Eaten from ghost" ); + Game.pacman.eatGhost(target); +// if( target.state != Game.GHOST_STATE_FRIGHTENED && target.state != Game.GHOST_STATE_EATEN ) { +// Game.die(); +// } else { +// target.state_to(Game.GHOST_STATE_EATEN); +// Game.eatGhost(this); +// } + } + } +}; + +heriter(Ghost.prototype, Actor.prototype); diff --git a/js/pacman-data.js b/js/pacman-data.js new file mode 100644 index 0000000..5e1b030 --- /dev/null +++ b/js/pacman-data.js @@ -0,0 +1,2 @@ +MAZE = {"structure":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,9,9,9,9,9,9,9,9,9,9,9,2,1,9,9,9,9,9,9,9,9,9,9,9,9,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,11,-1,1,9,9,2,-1,1,9,9,9,2,-1,11,10,-1,1,9,9,9,2,-1,1,9,9,2,-1,10,11,-2,10,0,0,11,-1,11,0,0,0,10,-1,11,10,-1,11,0,0,0,10,-1,11,0,0,10,-2,10,11,-1,3,9,9,4,-1,3,9,9,9,4,-1,3,4,-1,3,9,9,9,4,-1,3,9,9,4,-1,10,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,11,-1,1,9,9,2,-1,1,2,-1,1,9,9,9,9,9,9,2,-1,1,2,-1,1,9,9,2,-1,10,11,-1,3,9,9,4,-1,10,11,-1,3,9,9,2,1,9,9,4,-1,10,11,-1,3,9,9,4,-1,10,11,-1,-1,-1,-1,-1,-1,10,11,-1,-1,-1,-1,11,10,-1,-1,-1,-1,10,11,-1,-1,-1,-1,-1,-1,10,3,9,9,9,9,2,-1,10,3,9,9,2,0,11,10,0,1,9,9,4,11,-1,1,9,9,9,9,4,0,0,0,0,0,10,-1,10,1,9,9,4,0,3,4,0,3,9,9,2,11,-1,11,0,0,0,0,0,0,0,0,0,0,10,-1,10,11,0,0,0,0,0,0,0,0,0,0,10,11,-1,11,0,0,0,0,0,9,9,9,9,9,4,-1,3,4,0,5,9,9,12,12,9,9,6,0,3,4,-1,3,9,9,9,9,9,0,0,0,0,0,0,-1,0,0,0,11,0,0,0,0,0,0,10,0,0,0,-1,0,0,0,0,0,0,9,9,9,9,9,2,-1,1,2,0,7,9,9,9,9,9,9,8,0,1,2,-1,1,9,9,9,9,9,0,0,0,0,0,10,-1,11,10,0,0,0,0,0,0,0,0,0,0,11,10,-1,11,0,0,0,0,0,0,0,0,0,0,10,-1,11,10,0,1,9,9,9,9,9,9,2,0,11,10,-1,11,0,0,0,0,0,1,9,9,9,9,4,-1,3,4,0,3,9,9,2,1,9,9,4,0,3,4,-1,3,9,9,9,9,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,11,-1,1,9,9,2,-1,1,9,9,9,2,-1,11,10,-1,1,9,9,9,2,-1,1,9,9,2,-1,10,11,-1,3,9,2,10,-1,3,9,9,9,4,-1,3,4,-1,3,9,9,9,4,-1,11,1,9,4,-1,10,11,-2,-1,-1,10,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,10,-1,-1,-2,10,3,9,2,-1,10,10,-1,1,2,-1,1,9,9,9,9,9,9,2,-1,1,2,-1,11,10,-1,1,9,4,1,9,4,-1,3,4,-1,11,10,-1,3,9,9,2,1,9,9,4,-1,11,10,-1,3,4,-1,3,9,2,11,-1,-1,-1,-1,-1,-1,11,10,-1,-1,-1,-1,11,10,-1,-1,-1,-1,11,10,-1,-1,-1,-1,-1,-1,10,11,-1,1,9,9,9,9,4,3,9,9,2,-1,11,10,-1,1,9,9,4,3,9,9,9,9,2,-1,10,11,-1,3,9,9,9,9,9,9,9,9,4,-1,3,4,-1,3,9,9,9,9,9,9,9,9,4,-1,10,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,3,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,4],"bonus_target":518,"tunnel":[448,449,450,451,452,471,472,473,474,475],"ghost_frightened_target":405,"choice_tiles":[118,133,225,230,233,236,239,242,245,250,314,329,404,407,454,457,466,469,513,522,594,597,606,609,678,681,684,687,690,693,759,780,852,855]}; + var LEVELS = [{"pacman":{"speed":0.8,"eating":0.71,"frightSpeed":0.9,"frightSpeedEating":0.79},"ghost":{"speed":0.75,"tunnelSpeed":0.4,"elroy1Speed":0.8,"elroy1Dots":20,"elroy2Speed":0.85,"elroy2Dots":10,"frightSpeed":0.5},"frightTime":6,"frightFlashesCount":5,"mode":[7,20,7,20,5,20,5,1410065407],"bonus":{"type":"cherries","points":100}},{"pacman":{"speed":0.9,"eating":0.79,"frightSpeed":0.95,"frightSpeedEating":0.83},"ghost":{"speed":0.85,"tunnelSpeed":0.45,"elroy1Speed":0.9,"elroy1Dots":30,"elroy2Speed":0.95,"elroy2Dots":15,"frightSpeed":0.55},"frightTime":5,"frightFlashesCount":5,"mode":[7,20,7,20,5,1033,0.0166666667,1410065407],"bonus":{"type":"strawberry","points":300}},{"pacman":{"speed":0.9,"eating":0.79,"frightSpeed":0.95,"frightSpeedEating":0.83},"ghost":{"speed":0.85,"tunnelSpeed":0.45,"elroy1Speed":0.9,"elroy1Dots":40,"elroy2Speed":0.95,"elroy2Dots":20,"frightSpeed":0.55},"frightTime":4,"frightFlashesCount":5,"mode":[7,20,7,20,5,1033,0.0166666667,1410065407],"bonus":{"type":"peach","points":500}},{"pacman":{"speed":0.9,"eating":0.79,"frightSpeed":0.95,"frightSpeedEating":0.83},"ghost":{"speed":0.85,"tunnelSpeed":0.45,"elroy1Speed":0.9,"elroy1Dots":40,"elroy2Speed":0.95,"elroy2Dots":20,"frightSpeed":0.55},"frightTime":3,"frightFlashesCount":5,"mode":[7,20,7,20,5,1033,0.0166666667,1410065407],"bonus":{"type":"peach","points":500}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":40,"elroy2Speed":1.05,"elroy2Dots":20,"frightSpeed":0.6},"frightTime":2,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"apple","points":700}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":50,"elroy2Speed":1.05,"elroy2Dots":25,"frightSpeed":0.6},"frightTime":5,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"apple","points":700}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":50,"elroy2Speed":1.05,"elroy2Dots":25,"frightSpeed":0.6},"frightTime":2,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"grapes","points":1000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":50,"elroy2Speed":1.05,"elroy2Dots":25,"frightSpeed":0.6},"frightTime":2,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"grapes","points":1000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":60,"elroy2Speed":1.05,"elroy2Dots":30,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"galaxian","points":2000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":60,"elroy2Speed":1.05,"elroy2Dots":30,"frightSpeed":0.6},"frightTime":5,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"galaxian","points":2000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":60,"elroy2Speed":1.05,"elroy2Dots":30,"frightSpeed":0.6},"frightTime":2,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"bell","points":3000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":80,"elroy2Speed":1.05,"elroy2Dots":40,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"bell","points":3000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":80,"elroy2Speed":1.05,"elroy2Dots":40,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":80,"elroy2Speed":1.05,"elroy2Dots":40,"frightSpeed":0.6},"frightTime":3,"frightFlashesCount":5,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":100,"elroy2Speed":1.05,"elroy2Dots":50,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":100,"elroy2Speed":1.05,"elroy2Dots":50,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":100,"elroy2Speed":1.05,"elroy2Dots":50,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":100,"elroy2Speed":1.05,"elroy2Dots":50,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":120,"elroy2Speed":1.05,"elroy2Dots":60,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":1,"eating":0.87,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":120,"elroy2Speed":1.05,"elroy2Dots":60,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}},{"pacman":{"speed":0.9,"eating":0.79,"frightSpeed":1,"frightSpeedEating":0.87},"ghost":{"speed":0.95,"tunnelSpeed":0.5,"elroy1Speed":1,"elroy1Dots":120,"elroy2Speed":1.05,"elroy2Dots":60,"frightSpeed":0.6},"frightTime":1,"frightFlashesCount":3,"mode":[7,20,7,20,5,1037,0.0166666667,1410065407],"bonus":{"type":"key","points":5000}}]; diff --git a/js/pacman-ui.js b/js/pacman-ui.js new file mode 100644 index 0000000..06c6d46 --- /dev/null +++ b/js/pacman-ui.js @@ -0,0 +1,255 @@ +/* +Copyright (c) 2013 Fabrice ECAILLE aka Febbweiss + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +var SOUND_ACTIVATED = false; + +var WIDTH_TILE_COUNT = 28; +var HEIGHT_TILE_COUNT = 34; +var TILE_SIZE = 16; +var HALF_TILE_SIZE = 8; +var ACTOR_SIZE = 32; +var PLAYGROUND_WIDTH = WIDTH_TILE_COUNT * TILE_SIZE; +var PLAYGROUND_HEIGHT = HEIGHT_TILE_COUNT * TILE_SIZE; +var ACTOR_SPEED = 4; +var LOOP_COUNT_REFRESH = 66; +var loopCount = 0; +var REFRESH_RATE = 15; +//1: up, 2: left, 3:down, 4: right +var UP = 1; +var LEFT = 2; +var DOWN = 3; +var RIGHT = 4; + +var BONUS_TILE = 77; + +var eatenBonus = new Array(); + +var INFINITY = 9999999999; + +$(function(){ + + //Playground Sprites + $("#playground").playground({height: PLAYGROUND_HEIGHT, width: PLAYGROUND_WIDTH, keyTracker: true}); + + $.playground({refreshRate: 60}).addGroup("background", {posx: 0, posy: 0, width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end() + .addGroup("dots", {width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end() + .addGroup("actors", {width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end() + .addGroup( "hud", {width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end(); + + var hud = $("#hud"); + hud.append("
"); + hud.append("
"); + hud.append("
"); + hud.append("
'"); + hud.append("
'"); + hud.append("
'"); + + GUI.updateLevel( "Level" ); + + var background = $("#background"); + var dotsGroup = $("#dots"); + var maze = Game.maze.structure; + + for( var i = 0; i < maze.length; i++ ) { + var clazz = ""; + switch( maze[i]) { + case -2: + clazz = "bigDot"; + Game.dots[i] = "bigDot"; + break; + case -1: + clazz = "dot"; + Game.dots[i] = "dot"; + break; + case 1: + clazz = "corner1"; + break; + case 2: + clazz = "corner2"; + break; + case 3: + clazz = "corner3"; + break; + case 4: + clazz = "corner4"; + break; + case 5: + clazz = "squareCornerTopLeft"; + break; + case 6: + clazz = "squareCornerTopRight"; + break; + case 7: + clazz = "squareCornerBottomLeft"; + break; + case 8: + clazz = "squareCornerBottomRight"; + break; + case 9: + clazz = "horizontalMidDown"; + break; + case 10: + clazz = "verticalMidLeft"; + break; + case 11: + clazz = "verticalMidRight"; + break; + case 12: + clazz = "gate"; + break; + } + background.append('
'); + + if(i % 28 == 27 ) { + background.append('
'); + } + } + + // this is the function that control most of the game logic + $.playground().registerCallback(function(){ + if(jQuery.gameQuery.keyTracker[37]){ //this is left! (a) + Game.hero.left(); + } + if(jQuery.gameQuery.keyTracker[38]){ //this is up! (w) + Game.hero.up(); + } + if(jQuery.gameQuery.keyTracker[39]){ //this is right! (d) + Game.hero.right(); + } + if(jQuery.gameQuery.keyTracker[40]){ //this is down! (s) + Game.hero.down(); + } + + $.each(Game.actors, function(index, actor ) { + actor.move(); + }); + + for( var i = Math.max(0, eatenBonus.length - 6), j = 0; i < eatenBonus.length; i++, j++) { + $("#" +( BONUS_TILE + j)).removeClass().addClass("tile").addClass( eatenBonus[i] ); + } + + }, REFRESH_RATE); + + Sound.init(function(){ + $.playground().startGame( function() { + Game.init(); + }); + }); + +}); + +var Sound = { + soundList : [], + + init : function(callback) { + if( SOUND_ACTIVATED ) { + soundManager.setup({ + url: 'swf/' + }); + + Sound.soundList = { + opening : new $.gameQuery.SoundWrapper('sound/opening.mp3', false), + waka : new $.gameQuery.SoundWrapper('sound/wakawaka.mp3', false), + fruit : new $.gameQuery.SoundWrapper('sound/eatingfruit.mp3', false), + ghost : new $.gameQuery.SoundWrapper('sound/eatingghost.mp3', false), + dies : new $.gameQuery.SoundWrapper('sound/dies.mp3', false) + }; + soundManager.onready( callback ); + } else + callback(); + }, + + play: function( sound ) { + if( SOUND_ACTIVATED ) + Sound.soundList[sound].play(); + }, + + stop: function( sound ) { + if( SOUND_ACTIVATED ) + Sound.soundList[sound].stop(); + }, +} + +var GUI = { + updateMessage : function( message ) { + GUI.drawText( $("#message"), message, true ); + }, + + updateScoreMessage : function( message ) { + GUI.drawText( $("#scoreMessage"), message, false, "red" ); + }, + + updateLevel : function( message ) { + GUI.drawText( $("#level"), message, false ); + }, + + updateLevelNumber: function( message ) { + GUI.drawText( $("#levelNumber"), message + "", false, "", true ); + }, + + drawText : function( divHTML, message, center, customClazz, forceSmall) { + var html = ""; + var clazz = "clock"; + var letterSize = 32; + if( typeof customClazz !== "undefined" ) { + clazz = " clock " + customClazz; + } + + + var count = 0; + var width = 0; + var height = 0; + for( var i = 0; i < message.length; i++ ) { + var letter = message[i]; + var iLetter = (message.charCodeAt(i) - 97); + if( letter == " " ) { + html += "
"; + width += 16; + count++; + } else if( letter.charCodeAt(0) > 47 && letter.charCodeAt(0) < 58 ) { + var letterSize = 32; + if( forceSmall ) { + letterSize = 16; + } + html += "
"; + count++; + } else if( ( letter.charCodeAt(0) >= 'a'.charCodeAt(0) && letter.charCodeAt(0) <= 'z'.charCodeAt(0)) ) { + if( height < 16 ) + height = 16; + width += 16; + var lineSize = 20; + var x = (iLetter % lineSize) * 16; + var y = Math.floor(iLetter / lineSize) * 16 + 144; + html += "
"; + count++; + } else if( letter.charCodeAt(0) >= 'A'.charCodeAt(0) && letter.charCodeAt(0) <= 'Z'.charCodeAt(0)) { + iLetter = letter.charCodeAt(0) - 'A'.charCodeAt(0); + if( height < 32 ) + height = 32; + width += 32; + var lineSize = 10; + var x = (iLetter % lineSize) * 32; + var y = Math.floor(iLetter / lineSize) * 32 + 32; + html += "
"; + count++; + } + } + + divHTML.empty(); + divHTML.css( "width", width + "px"); + divHTML.css( "height", height + "px"); + if( center ) + divHTML.css( "margin-left", "-" + (message.length * letterSize / 2) + "px"); + divHTML.append( html ); + } +} diff --git a/js/pacman-ui.js~ b/js/pacman-ui.js~ new file mode 100644 index 0000000..f94cc88 --- /dev/null +++ b/js/pacman-ui.js~ @@ -0,0 +1,246 @@ +var SOUND_ACTIVATED = false; + +var WIDTH_TILE_COUNT = 28; +var HEIGHT_TILE_COUNT = 34; +var TILE_SIZE = 16; +var HALF_TILE_SIZE = 8; +var ACTOR_SIZE = 32; +var PLAYGROUND_WIDTH = WIDTH_TILE_COUNT * TILE_SIZE; +var PLAYGROUND_HEIGHT = HEIGHT_TILE_COUNT * TILE_SIZE; +var ACTOR_SPEED = 4; +var LOOP_COUNT_REFRESH = 66; +var loopCount = 0; +var REFRESH_RATE = 15; +//1: up, 2: left, 3:down, 4: right +var UP = 1; +var LEFT = 2; +var DOWN = 3; +var RIGHT = 4; + +var BONUS_TILE = 77; + +var eatenBonus = new Array(); + +var INFINITY = 9999999999; + +$(function(){ + + //Playground Sprites + $("#playground").playground({height: PLAYGROUND_HEIGHT, width: PLAYGROUND_WIDTH, keyTracker: true}); + + Sound.init(function(){ + $.playground().startGame( function() { + Game.init(); + }); + }); + + $.playground({refreshRate: 60}).addGroup("background", {posx: 0, posy: 0, width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end() + .addGroup("dots", {width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end() + .addGroup("actors", {width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end() + .addGroup( "hud", {width: PLAYGROUND_WIDTH, height: PLAYGROUND_HEIGHT}) + .end(); + + var hud = $("#hud"); + hud.append("
"); + hud.append("
"); + hud.append("
"); + hud.append("
'"); + hud.append("
'"); + hud.append("
'"); + + GUI.updateLevel( "Level" ); + + var background = $("#background"); + var dotsGroup = $("#dots"); + var maze = Game.maze.structure; + + for( var i = 0; i < maze.length; i++ ) { + var clazz = ""; + switch( maze[i]) { + case -2: + clazz = "bigDot"; + Game.dots[i] = "bigDot"; + break; + case -1: + clazz = "dot"; + Game.dots[i] = "dot"; + break; + case 1: + clazz = "corner1"; + break; + case 2: + clazz = "corner2"; + break; + case 3: + clazz = "corner3"; + break; + case 4: + clazz = "corner4"; + break; + case 5: + clazz = "squareCornerTopLeft"; + break; + case 6: + clazz = "squareCornerTopRight"; + break; + case 7: + clazz = "squareCornerBottomLeft"; + break; + case 8: + clazz = "squareCornerBottomRight"; + break; + case 9: + clazz = "horizontalMidDown"; + break; + case 10: + clazz = "verticalMidLeft"; + break; + case 11: + clazz = "verticalMidRight"; + break; + case 12: + clazz = "gate"; + break; + } + background.append('
'); + + if(i % 28 == 27 ) { + background.append('
'); + } + } + + // this is the function that control most of the game logic + $.playground().registerCallback(function(){ + if(jQuery.gameQuery.keyTracker[37]){ //this is left! (a) + Game.hero.left(); + } + if(jQuery.gameQuery.keyTracker[38]){ //this is up! (w) + Game.hero.up(); + } + if(jQuery.gameQuery.keyTracker[39]){ //this is right! (d) + Game.hero.right(); + } + if(jQuery.gameQuery.keyTracker[40]){ //this is down! (s) + Game.hero.down(); + } + + $.each(Game.actors, function(index, actor ) { + actor.move(); + }); + + for( var i = Math.max(0, eatenBonus.length - 6), j = 0; i < eatenBonus.length; i++, j++) { + $("#" +( BONUS_TILE + j)).removeClass().addClass("tile").addClass( eatenBonus[i] ); + } + + }, REFRESH_RATE); + +}); + +var Sound = { + soundList : [], + + init : function(callback) { + if( SOUND_ACTIVATED ) { + soundManager.setup({ + url: 'swf/' + }); + + Sound.soundList = { + opening : new $.gameQuery.SoundWrapper('sound/opening.mp3', false), + waka : new $.gameQuery.SoundWrapper('sound/wakawaka.mp3', false), + fruit : new $.gameQuery.SoundWrapper('sound/eatingfruit.mp3', false), + ghost : new $.gameQuery.SoundWrapper('sound/eatingghost.mp3', false), + dies : new $.gameQuery.SoundWrapper('sound/dies.mp3', false) + }; + soundManager.onready( callback ); + } else + callback(); + }, + + play: function( sound ) { + if( SOUND_ACTIVATED ) + Sound.soundList[sound].play(); + }, + + stop: function( sound ) { + if( SOUND_ACTIVATED ) + Sound.soundList[sound].stop(); + }, +} + +var GUI = { + updateMessage : function( message ) { + GUI.drawText( $("#message"), message, true ); + }, + + updateScoreMessage : function( message ) { + GUI.drawText( $("#scoreMessage"), message, false, "red" ); + }, + + updateLevel : function( message ) { + GUI.drawText( $("#level"), message, false ); + }, + + updateLevelNumber: function( message ) { + GUI.drawText( $("#levelNumber"), message + "", false, "", true ); + }, + + drawText : function( divHTML, message, center, customClazz, forceSmall) { + var html = ""; + var clazz = "clock"; + var letterSize = 32; + if( typeof customClazz !== "undefined" ) { + clazz = " clock " + customClazz; + } + + + var count = 0; + var width = 0; + var height = 0; + for( var i = 0; i < message.length; i++ ) { + var letter = message[i]; + var iLetter = (message.charCodeAt(i) - 97); + if( letter == " " ) { + html += "
"; + width += 16; + count++; + } else if( letter.charCodeAt(0) > 47 && letter.charCodeAt(0) < 58 ) { + var letterSize = 32; + if( forceSmall ) { + letterSize = 16; + } + html += "
"; + count++; + } else if( ( letter.charCodeAt(0) >= 'a'.charCodeAt(0) && letter.charCodeAt(0) <= 'z'.charCodeAt(0)) ) { + if( height < 16 ) + height = 16; + width += 16; + var lineSize = 20; + var x = (iLetter % lineSize) * 16; + var y = Math.floor(iLetter / lineSize) * 16 + 144; + html += "
"; + count++; + } else if( letter.charCodeAt(0) >= 'A'.charCodeAt(0) && letter.charCodeAt(0) <= 'Z'.charCodeAt(0)) { + iLetter = letter.charCodeAt(0) - 'A'.charCodeAt(0); + if( height < 32 ) + height = 32; + width += 32; + var lineSize = 10; + var x = (iLetter % lineSize) * 32; + var y = Math.floor(iLetter / lineSize) * 32 + 32; + html += "
"; + count++; + } + } + + divHTML.empty(); + divHTML.css( "width", width + "px"); + divHTML.css( "height", height + "px"); + if( center ) + divHTML.css( "margin-left", "-" + (message.length * letterSize / 2) + "px"); + divHTML.append( html ); + } +} diff --git a/js/scoreboard.js b/js/scoreboard.js new file mode 100644 index 0000000..d67e174 --- /dev/null +++ b/js/scoreboard.js @@ -0,0 +1,54 @@ +/* +Copyright (c) 2013 Fabrice ECAILLE aka Febbweiss + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var SCOREBOARD = { + score: 0, + scoreLength: 6, + + init: function(size) { + if( typeof size !== "undefined" ) + SCOREBOARD.scoreLength = size; + SCOREBOARD.score = 0; + SCOREBOARD.set_score( 0 ); + }, + + add: function(addToScore, div) { + SCOREBOARD.set_score( SCOREBOARD.score + addToScore, div); + }, + + set_score: function( score, div ) { + var currentScore = ""; + var imageScore = ""; + + SCOREBOARD.score = score; + currentScore = SCOREBOARD.pad(); + + for(i = 0; i < String(currentScore).length; i++) { + imageScore += "
"; + } + + if( typeof div === "undefined" ) + div = $(".subScoreboard"); + div.empty(); + div.append( imageScore ); + }, + + pad: function() { + var str = '' + SCOREBOARD.score; + while (str.length < SCOREBOARD.scoreLength) { + str = '0' + str; + } + return str; + }, + + callback: function() { + console.log( "SCOREBOARD.callback" ); + } +}; diff --git a/js/utils.js b/js/utils.js new file mode 100644 index 0000000..e4a903b --- /dev/null +++ b/js/utils.js @@ -0,0 +1,55 @@ +function heriter(destination, source) { + function initClassIfNecessary(obj) { + if( typeof obj["_super"] == "undefined" ) { + obj["_super"] = function() { + var methodName = arguments[0]; + var parameters = arguments[1]; + this["__parent_methods"][methodName].apply(this, parameters); + } + } + + if( typeof obj["__parent_methods"] == "undefined" ) { + obj["__parent_methods"] = {} + } + } + + for (var element in source) { + if( typeof destination[element] != "undefined" ) { + initClassIfNecessary(destination); + destination["__parent_methods"][element] = source[element]; + } else { + destination[element] = source[element]; + } + } +} + + +/** PausableTimer **/ + +function PausableTimer(func, millisec) { + this.func = func; + this.stTime = new Date().valueOf(); + this.timeout = setTimeout(func, millisec); + this.timeLeft = millisec; +} + +PausableTimer.prototype.stop = function() { + clearTimeout(this.timeout); +}; + +PausableTimer.prototype.pause = function() { + clearTimeout(this.timeout); + var timeRan = new Date().valueOf()-this.stTime; + this.timeLeft -= timeRan; +}; + +PausableTimer.prototype.resume = function() { + this.timeout = setTimeout(this.func, this.timeLeft); + this.stTime = new Date().valueOf(); +}; + +//Usage: +//var myTimer = new PausableTimer(function(){alert("It works!");}, 2000); +//myTimer.pause(); +//myTimer.unpause(); + diff --git a/lib/gamequery-0.7.0.js b/lib/gamequery-0.7.0.js new file mode 100644 index 0000000..b3e3037 --- /dev/null +++ b/lib/gamequery-0.7.0.js @@ -0,0 +1,1738 @@ +/* + * gameQuery rev. 0.7.0 + * + * Copyright (c) 2012 Selim Arsever (http://gamequeryjs.com) + * licensed under the MIT-License + */ + +// This allows use of the convenient $ notation in a plugin +(function($) { + + // This prefix can be use whenever needed to namespace CSS classes, .data() inputs aso. + var gQprefix = "gQ_"; + + // Those are the possible states of the engine + var STATE_NEW = 0; // Not yet started for the first time + var STATE_RUNNING = 1; // Started and running + var STATE_PAUSED = 2; // Paused + + /** + * Utility function that returns the radius for a geometry. + * + * @param {object} elem DOM element + * @param {float} angle the angle in degrees + * @return {object} .x, .y radius of geometry + */ + var proj = function (elem, angle) { + switch (elem.geometry){ + case $.gameQuery.GEOMETRY_RECTANGLE : + var b = angle*Math.PI*2/360; + var Rx = Math.abs(Math.cos(b)*elem.width/2*elem.factor)+Math.abs(Math.sin(b)*elem.height/2*elem.factor); + var Ry = Math.abs(Math.cos(b)*elem.height/2*elem.factor)+Math.abs(Math.sin(b)*elem.width/2*elem.factor); + + return {x: Rx, y: Ry}; + } + }; + + /** + * Utility function that checks for collision between two elements. + * + * @param {object} elem1 DOM for the first element + * @param {float} offset1 offset of the first element + * @param {object} elem2 DOM for the second element + * @param {float} offset2 offset of the second element + * @return {boolean} if the two elements collide or not + */ + var collide = function(elem1, offset1, elem2, offset2) { + // test real collision (only for two rectangles...) + if((elem1.geometry == $.gameQuery.GEOMETRY_RECTANGLE && elem2.geometry == $.gameQuery.GEOMETRY_RECTANGLE)){ + + var dx = offset2.x + elem2.boundingCircle.x - elem1.boundingCircle.x - offset1.x; + var dy = offset2.y + elem2.boundingCircle.y - elem1.boundingCircle.y - offset1.y; + var a = Math.atan(dy/dx); + + var Dx = Math.abs(Math.cos(a-elem1.angle*Math.PI*2/360)/Math.cos(a)*dx); + var Dy = Math.abs(Math.sin(a-elem1.angle*Math.PI*2/360)/Math.sin(a)*dy); + + var R = proj(elem2, elem2.angle-elem1.angle); + + if((elem1.width/2*elem1.factor+R.x <= Dx) || (elem1.height/2*elem1.factor+R.y <= Dy)) { + return false; + } else { + var Dx = Math.abs(Math.cos(a-elem2.angle*Math.PI*2/360)/Math.cos(a)*-dx); + var Dy = Math.abs(Math.sin(a-elem2.angle*Math.PI*2/360)/Math.sin(a)*-dy); + + var R = proj(elem1, elem1.angle-elem2.angle); + + if((elem2.width/2*elem2.factor+R.x <= Dx) || (elem2.height/2*elem2.factor+R.y <= Dy)) { + return false; + } else { + return true; + } + } + } else { + return false; + } + }; + + /** + * Utility function computes the offset relative to the playground of a gameQuery element without using DOM's position. + * This should be faster than the standand .offset() function. + * + * Warning: No non-gameQuery elements should be present between this element and the playground div! + * + * @param {jQuery} element the jQuery wrapped DOM element representing the gameQuery object. + * @return {object} an object {x:, y: } containing the x and y offset. (Not top and left like jQuery's .offset()) + */ + var offset = function(element) { + // Get the tileSet offset (relative to the playground) + var offset = {x: 0, y: 0}; + var parent = element[0]; + + while(parent !== $.gameQuery.playground[0] && parent.gameQuery !== undefined) { + offset.x += parent.gameQuery.posx; + offset.y += parent.gameQuery.posy; + parent = parent.parentNode; + } + + return offset + } + + /** + * Utility function computes the index range of the tiles for a tilemap. + * + * @param {jQuery} element the jQuery wrapped DOM element representing the tilemap. + * @param {object} offset an object holding the x and y offset of the tilemap, this is optional and will be computed if not provided. + * @return {object} an object {firstColumn: , lastColumn: , fristRow: , lastRow: } + */ + var visibleTilemapIndexes = function (element, elementOffset) { + if (elementOffset === undefined) { + elementOffset = offset(element); + } + + var gameQuery = element[0].gameQuery; + // Activate the visible tiles + return { + firstRow: Math.max(Math.min(Math.floor(-elementOffset.y/gameQuery.height), gameQuery.sizey), 0), + lastRow: Math.max(Math.min(Math.ceil(($.gameQuery.playground[0].height-elementOffset.y)/gameQuery.height), gameQuery.sizey), 0), + firstColumn: Math.max(Math.min(Math.floor(-elementOffset.x/gameQuery.width), gameQuery.sizex), 0), + lastColumn: Math.max(Math.min(Math.ceil(($.gameQuery.playground[0].width-elementOffset.x)/gameQuery.width), gameQuery.sizex), 0) + } + } + + /** + * Utility function thast computes the buffered zone of a tilemap + * + * @param {jQuery} element the jQuery wrapped DOM element representing the tilemap. + * @param {object} visible an object describing the visible zone + * @return {object} an object {firstColumn: , lastColumn: , fristRow: , lastRow: } + */ + var bufferedTilemapIndexes = function (element, visible) { + var gameQuery = element[0].gameQuery; + + return { + firstRow: Math.max(Math.min(visible.firstRow - gameQuery.buffer, gameQuery.sizey), 0), + lastRow: Math.max(Math.min(visible.lastRow + gameQuery.buffer, gameQuery.sizey), 0), + firstColumn: Math.max(Math.min(visible.firstColumn - gameQuery.buffer, gameQuery.sizex), 0), + lastColumn: Math.max(Math.min(visible.lastColumn + gameQuery.buffer, gameQuery.sizex), 0) + } + } + + /** + * Utility function that creates a tile in the given tilemap + * + * @param {jQuery} tileSet the jQuery element representing the tile map + * @param {integer} row the row index of the tile in the tile map + * @param {integer} column the column index of the tile in the tile map + */ + var addTile = function(tileSet, row, column) { + var gameQuery = tileSet[0].gameQuery; + var name = tileSet.attr("id"); + + var tileDescription; + if(gameQuery.func) { + tileDescription = gameQuery.tiles(row,column)-1; + } else { + tileDescription = gameQuery.tiles[row][column]-1; + } + + var animation; + if(gameQuery.multi) { + animation = gameQuery.animations; + } else { + animation = gameQuery.animations[tileDescription]; + } + + if(tileDescription >= 0){ + tileSet.addSprite($.gameQuery.tileIdPrefix+name+"_"+row+"_"+column, + {width: gameQuery.width, + height: gameQuery.height, + posx: column*gameQuery.width, + posy: row*gameQuery.height, + animation: animation}); + + var newTile = tileSet.find("#"+$.gameQuery.tileIdPrefix+name+"_"+row+"_"+column); + if (gameQuery.multi) { + newTile.setAnimation(tileDescription); + } else { + newTile[0].gameQuery.animationNumber = tileDescription; + } + newTile.removeClass($.gameQuery.spriteCssClass); + newTile.addClass($.gameQuery.tileCssClass); + newTile.addClass($.gameQuery.tileTypePrefix+tileDescription); + } + } + + // Define the list of object/function accessible through $. + $.extend({ gameQuery: { + /** + * This is the Animation Object + */ + Animation: function (options, imediateCallback) { + // private default values + var defaults = { + imageURL: "", + numberOfFrame: 1, + delta: 0, + rate: 30, + type: 0, + distance: 0, + offsetx: 0, + offsety: 0 + }; + + // options extends defaults + options = $.extend(defaults, options); + + // "public" attributes: + this.imageURL = options.imageURL; // The url of the image to be used as an animation or sprite + this.numberOfFrame = options.numberOfFrame; // The number of frames to be displayed when playing the animation + this.delta = options.delta; // The distance in pixels between two frames + this.rate = options.rate; // The rate at which the frames change in miliseconds + this.type = options.type; // The type of the animation.This is a bitwise OR of the properties. + this.distance = options.distance; // The distance in pixels between two animations + this.offsetx = options.offsetx; // The x coordinate where the first sprite begins + this.offsety = options.offsety; // The y coordinate where the first sprite begins + + // Whenever a new animation is created we add it to the ResourceManager animation list + $.gameQuery.resourceManager.addAnimation(this, imediateCallback); + + return true; + }, + + /** + * "constants" for the different types of an animation + */ + ANIMATION_VERTICAL: 1, // Generated by a vertical offset of the background + ANIMATION_HORIZONTAL: 2, // Generated by a horizontal offset of the background + ANIMATION_ONCE: 4, // Played only once (else looping indefinitely) + ANIMATION_CALLBACK: 8, // A callback is exectued at the end of a cycle + ANIMATION_MULTI: 16, // The image file contains many animations + ANIMATION_PINGPONG: 32, // At the last frame of the animation it reverses (if used in conjunction with ONCE it will have no effect) + + // "constants" for the different type of geometry for a sprite + GEOMETRY_RECTANGLE: 1, + GEOMETRY_DISC: 2, + + // basic values + refreshRate: 30, + + /** + * An object to manage resource loading + */ + resourceManager: { + animations: [], // List of animations / images used in the game + sounds: [], // List of sounds used in the game + callbacks: [], // List of the functions called at each refresh + loadedAnimationsPointer: 0, // Keep track of the last loaded animation + loadedSoundsPointer: 0, // Keep track of the last loaded sound + + /** + * Load resources before starting the game. + */ + preload: function() { + // Start loading the images + for (var i = this.animations.length-1 ; i >= this.loadedAnimationsPointer; i --){ + this.animations[i].domO = new Image(); + this.animations[i].domO.src = this.animations[i].imageURL; + } + + // Start loading the sounds + for (var i = this.sounds.length-1 ; i >= this.loadedSoundsPointer; i --){ + this.sounds[i].load(); + } + + $.gameQuery.resourceManager.waitForResources(); + }, + + /** + * Wait for all the resources called for in preload() to finish loading. + */ + waitForResources: function() { + // Check the images + var imageCount = 0; + for(var i=this.loadedAnimationsPointer; i < this.animations.length; i++){ + if(this.animations[i].domO.complete){ + imageCount++; + } + } + // Check the sounds + var soundCount = 0; + for(var i=this.loadedSoundsPointer; i < this.sounds.length; i++){ + var temp = this.sounds[i].ready(); + if(temp){ + soundCount++; + } + } + // Call the load callback with the current progress + if($.gameQuery.resourceManager.loadCallback){ + var percent = (imageCount + soundCount)/(this.animations.length + this.sounds.length - this.loadedAnimationsPointer - this.loadedSoundsPointer)*100; + $.gameQuery.resourceManager.loadCallback(percent); + } + if(imageCount + soundCount < (this.animations.length + this.sounds.length - this.loadedAnimationsPointer - this.loadedSoundsPointer)){ + imgWait=setTimeout(function () { + $.gameQuery.resourceManager.waitForResources(); + }, 100); + } else { + this.loadedAnimationsPointer = this.animations.length; + this.loadedSoundsPointer = this.sounds.length; + + // All the resources are loaded! We can now associate the animation's images to their corresponding sprites + $.gameQuery.scenegraph.children().each(function(){ + // recursive call on the children: + $(this).children().each(arguments.callee); + // add the image as a background + if(this.gameQuery && this.gameQuery.animation){ + $(this).css("background-image", "url("+this.gameQuery.animation.imageURL+")"); + // we set the correct kind of repeat + if(this.gameQuery.animation.type & $.gameQuery.ANIMATION_VERTICAL) { + $(this).css("background-repeat", "repeat-x"); + } else if(this.gameQuery.animation.type & $.gameQuery.ANIMATION_HORIZONTAL) { + $(this).css("background-repeat", "repeat-y"); + } else { + $(this).css("background-repeat", "no-repeat"); + } + } + }); + + // Launch the refresh loop + if($.gameQuery.state === STATE_NEW){ + setInterval(function () { + $.gameQuery.resourceManager.refresh(); + },($.gameQuery.refreshRate)); + } + $.gameQuery.state = STATE_RUNNING; + if($.gameQuery.startCallback){ + $.gameQuery.startCallback(); + } + // Make the scenegraph visible + $.gameQuery.scenegraph.css("visibility","visible"); + } + }, + + /** + * This function refresh a unique sprite here 'this' represent a dom object + */ + refreshSprite: function() { + // Check if 'this' is a gameQuery element + if(this.gameQuery != undefined){ + var gameQuery = this.gameQuery; + // Does 'this' has an animation ? + if(gameQuery.animation){ + // Do we have anything to do? + if ( (gameQuery.idleCounter == gameQuery.animation.rate-1) && gameQuery.playing){ + + // Does 'this' loops? + if(gameQuery.animation.type & $.gameQuery.ANIMATION_ONCE){ + if(gameQuery.currentFrame < gameQuery.animation.numberOfFrame-1){ + gameQuery.currentFrame += gameQuery.frameIncrement; + } else if(gameQuery.currentFrame == gameQuery.animation.numberOfFrame-1) { + // Does 'this' has a callback ? + if(gameQuery.animation.type & $.gameQuery.ANIMATION_CALLBACK){ + if($.isFunction(gameQuery.callback)){ + gameQuery.callback(this); + } + } + } + } else { + if(gameQuery.animation.type & $.gameQuery.ANIMATION_PINGPONG){ + if(gameQuery.currentFrame == gameQuery.animation.numberOfFrame-1 && gameQuery.frameIncrement == 1) { + gameQuery.frameIncrement = -1; + } else if (gameQuery.currentFrame == 0 && gameQuery.frameIncrement == -1) { + gameQuery.frameIncrement = 1; + } + } + + gameQuery.currentFrame = (gameQuery.currentFrame+gameQuery.frameIncrement)%gameQuery.animation.numberOfFrame; + if(gameQuery.currentFrame == 0){ + // Does 'this' has a callback ? + if(gameQuery.animation.type & $.gameQuery.ANIMATION_CALLBACK){ + if($.isFunction(gameQuery.callback)){ + gameQuery.callback(this); + } + } + } + } + // Update the background + if((gameQuery.animation.type & $.gameQuery.ANIMATION_VERTICAL) && (gameQuery.animation.numberOfFrame > 1)){ + if(gameQuery.multi){ + $(this).css("background-position",""+(-gameQuery.animation.offsetx-gameQuery.multi)+"px "+(-gameQuery.animation.offsety-gameQuery.animation.delta*gameQuery.currentFrame)+"px"); + } else { + $(this).css("background-position",""+(-gameQuery.animation.offsetx)+"px "+(-gameQuery.animation.offsety-gameQuery.animation.delta*gameQuery.currentFrame)+"px"); + } + } else if((gameQuery.animation.type & $.gameQuery.ANIMATION_HORIZONTAL) && (gameQuery.animation.numberOfFrame > 1)) { + if(gameQuery.multi){ + $(this).css("background-position",""+(-gameQuery.animation.offsetx-gameQuery.animation.delta*gameQuery.currentFrame)+"px "+(-gameQuery.animation.offsety-gameQuery.multi)+"px"); + } else { + $(this).css("background-position",""+(-gameQuery.animation.offsetx-gameQuery.animation.delta*gameQuery.currentFrame)+"px "+(-gameQuery.animation.offsety)+"px"); + } + } + } + gameQuery.idleCounter = (gameQuery.idleCounter+1)%gameQuery.animation.rate; + } + } + return true; + }, + + /** + * This function refresh a unique tile-map, here 'this' represent a dom object + */ + refreshTilemap: function() { + // Check if 'this' is a gameQuery element + if(this.gameQuery != undefined){ + var gameQuery = this.gameQuery; + if($.isArray(gameQuery.frameTracker)){ + for(var i=0; i 1)){ + $(this).css("background-position",""+(-gameQuery.animations[animationNumber].offsetx)+"px "+(-gameQuery.animations[animationNumber].offsety-gameQuery.animations[animationNumber].delta*gameQuery.frameTracker[animationNumber])+"px"); + } else if((gameQuery.animations[animationNumber].type & $.gameQuery.ANIMATION_HORIZONTAL) && (gameQuery.animations[animationNumber].numberOfFrame > 1)) { + $(this).css("background-position",""+(-gameQuery.animations[animationNumber].offsetx-gameQuery.animations[animationNumber].delta*gameQuery.frameTracker[animationNumber])+"px "+(-gameQuery.animations[animationNumber].offsety)+"px"); + } + } else { + if((gameQuery.animations.type & $.gameQuery.ANIMATION_VERTICAL) && (gameQuery.animations.numberOfFrame > 1)){ + $(this).css("background-position",""+(-gameQuery.animations.offsetx-this.gameQuery.multi)+"px "+(-gameQuery.animations.offsety-gameQuery.animations.delta*gameQuery.frameTracker)+"px"); + } else if((gameQuery.animations.type & $.gameQuery.ANIMATION_HORIZONTAL) && (gameQuery.animations.numberOfFrame > 1)) { + $(this).css("background-position",""+(-gameQuery.animations.offsetx-gameQuery.animations.delta*gameQuery.frameTracker)+"px "+(-gameQuery.animations.offsety-this.gameQuery.multi)+"px"); + } + } + }); + } + return true; + }, + + /** + * Called periodically to refresh the state of the game. + */ + refresh: function() { + if($.gameQuery.state === STATE_RUNNING) { + $.gameQuery.playground.find("."+$.gameQuery.spriteCssClass).each(this.refreshSprite); + $.gameQuery.playground.find("."+$.gameQuery.tilemapCssClass).each(this.refreshTilemap); + var deadCallback= new Array(); + for (var i = this.callbacks.length-1; i >= 0; i--){ + if(this.callbacks[i].idleCounter == this.callbacks[i].rate-1){ + var returnedValue = this.callbacks[i].fn(); + if(typeof returnedValue == 'boolean'){ + // If we have a boolean: 'true' means 'no more execution', 'false' means 'keep on executing' + if(returnedValue){ + deadCallback.push(i); + } + } else if(typeof returnedValue == 'number') { + // If we have a number it re-defines the time to the next call + this.callbacks[i].rate = Math.round(returnedValue/$.gameQuery.refreshRate); + this.callbacks[i].idleCounter = 0; + } + } + this.callbacks[i].idleCounter = (this.callbacks[i].idleCounter+1)%this.callbacks[i].rate; + } + for(var i = deadCallback.length-1; i >= 0; i--){ + this.callbacks.splice(deadCallback[i],1); + } + } + }, + + /** + * Add an animation to the resource Manager + */ + addAnimation: function(animation, callback) { + if($.inArray(animation,this.animations)<0){ + //normalize the animation rate: + animation.rate = Math.round(animation.rate/$.gameQuery.refreshRate); + if(animation.rate==0){ + animation.rate = 1; + } + this.animations.push(animation); + switch ($.gameQuery.state){ + case STATE_NEW: + case STATE_PAUSED: + // Nothing to do for now + break; + case STATE_RUNNING: + // immediatly load the animation and call the callback if any + this.animations[this.loadedAnimationsPointer].domO = new Image(); + this.animations[this.loadedAnimationsPointer].domO.src = animation.imageURL; + if (callback !== undefined){ + this.animations[this.loadedAnimationsPointer].domO.onload = callback; + } + this.loadedAnimationsPointer++; + break; + } + } + }, + + /** + * Add a sound to the resource Manager + */ + addSound: function(sound, callback){ + if($.inArray(sound,this.sounds)<0){ + this.sounds.push(sound); + switch ($.gameQuery.state){ + case STATE_NEW: + case STATE_PAUSED: + // Nothing to do for now + break; + case STATE_RUNNING: + // immediatly load the sound and call the callback if any + sound.load(); + // TODO callback.... + this.loadedSoundsPointer++; + break; + } + } + }, + + /** + * Register a callback + * + * @param {function} fn the callback + * @param {integer} rate the rate in ms at which the callback should be called (should be a multiple of the playground rate or will be rounded) + */ + registerCallback: function(fn, rate){ + rate = Math.round(rate/$.gameQuery.refreshRate); + if(rate==0){ + rate = 1; + } + this.callbacks.push({fn: fn, rate: rate, idleCounter: 0}); + }, + + /** + * Clear the animations and sounds + */ + clear: function(callbacksToo){ + this.animations = []; + this.loadedAnimationsPointer = 0; + this.sounds = []; + this.loadedSoundsPointer = 0; + if(callbacksToo) { + this.callbacks = []; + } + } + }, + + /** + * This is a single place to update the underlying data of sprites/groups/tiles after a position or dimesion modification. + */ + update: function(descriptor, transformation) { + // Did we really receive a descriptor or a jQuery object instead? + if(!$.isPlainObject(descriptor)){ + // Then we must get real descriptor + if(descriptor.length > 0){ + var gameQuery = descriptor[0].gameQuery; + } else { + var gameQuery = descriptor.gameQuery; + } + } else { + var gameQuery = descriptor; + } + // If we couldn't find one we return + if(!gameQuery) return; + if(gameQuery.tileSet === true){ + // We have a tilemap + + var visible = visibleTilemapIndexes(descriptor); + var buffered = gameQuery.buffered; + + // Test what kind of transformation we have and react accordingly + for(property in transformation){ + switch(property){ + case "x": + + if(visible.lastColumn > buffered.lastColumn) { + + // Detach the tilemap + var parent = descriptor[0].parentNode; + var tilemap = descriptor.detach(); + + var newBuffered = bufferedTilemapIndexes(descriptor, visible); + for(var i = gameQuery.buffered.firstRow; i < gameQuery.buffered.lastRow; i++){ + // Remove the newly invisible tiles + for(var j = gameQuery.buffered.firstColumn; j < Math.min(newBuffered.firstColumn, gameQuery.buffered.lastColumn); j++) { + tilemap.find("#"+$.gameQuery.tileIdPrefix+descriptor.attr("id")+"_"+i+"_"+j).remove(); + } + // And add the newly visible tiles + for(var j = Math.max(gameQuery.buffered.lastColumn,newBuffered.firstColumn); j < newBuffered.lastColumn ; j++) { + addTile(tilemap,i,j); + } + } + + gameQuery.buffered.firstColumn = newBuffered.firstColumn; + gameQuery.buffered.lastColumn = newBuffered.lastColumn; + + // Attach the tilemap back + tilemap.appendTo(parent); + + } + + if(visible.firstColumn < buffered.firstColumn) { + + // Detach the tilemap + var parent = descriptor[0].parentNode; + var tilemap = descriptor.detach(); + + var newBuffered = bufferedTilemapIndexes(descriptor, visible); + for(var i = gameQuery.buffered.firstRow; i < gameQuery.buffered.lastRow; i++){ + // Remove the newly invisible tiles + for(var j = Math.max(newBuffered.lastColumn,gameQuery.buffered.firstColumn); j < gameQuery.buffered.lastColumn ; j++) { + tilemap.find("#"+$.gameQuery.tileIdPrefix+descriptor.attr("id")+"_"+i+"_"+j).remove(); + } + // And add the newly visible tiles + for(var j = newBuffered.firstColumn; j < Math.min(gameQuery.buffered.firstColumn,newBuffered.lastColumn); j++) { + addTile(tilemap,i,j); + } + } + + gameQuery.buffered.firstColumn = newBuffered.firstColumn; + gameQuery.buffered.lastColumn = newBuffered.lastColumn; + + // Attach the tilemap back + tilemap.appendTo(parent); + } + break; + + case "y": + + if(visible.lastRow > buffered.lastRow) { + + // Detach the tilemap + var parent = descriptor[0].parentNode; + var tilemap = descriptor.detach(); + + var newBuffered = bufferedTilemapIndexes(descriptor, visible); + for(var j = gameQuery.buffered.firstColumn; j < gameQuery.buffered.lastColumn ; j++) { + // Remove the newly invisible tiles + for(var i = gameQuery.buffered.firstRow; i < Math.min(newBuffered.firstRow, gameQuery.buffered.lastRow); i++){ + tilemap.find("#"+$.gameQuery.tileIdPrefix+descriptor.attr("id")+"_"+i+"_"+j).remove(); + } + // And add the newly visible tiles + for(var i = Math.max(gameQuery.buffered.lastRow, newBuffered.firstRow); i < newBuffered.lastRow; i++){ + addTile(tilemap,i,j); + } + } + + gameQuery.buffered.firstRow = newBuffered.firstRow; + gameQuery.buffered.lastRow = newBuffered.lastRow; + + // Attach the tilemap back + tilemap.appendTo(parent); + + } + + if(visible.firstRow < buffered.firstRow) { + + // Detach the tilemap + var parent = descriptor[0].parentNode; + var tilemap = descriptor.detach(); + + var newBuffered = bufferedTilemapIndexes(descriptor, visible); + for(var j = gameQuery.buffered.firstColumn; j < gameQuery.buffered.lastColumn ; j++) { + // Remove the newly invisible tiles + for(var i = Math.max(newBuffered.lastRow, gameQuery.buffered.firstRow); i < gameQuery.buffered.lastRow; i++){ + tilemap.find("#"+$.gameQuery.tileIdPrefix+descriptor.attr("id")+"_"+i+"_"+j).remove(); + } + // And add the newly visible tiles + for(var i = newBuffered.firstRow; i < Math.min(gameQuery.buffered.firstRow, newBuffered.lastRow); i++){ + addTile(tilemap,i,j); + } + } + + gameQuery.buffered.firstRow = newBuffered.firstRow; + gameQuery.buffered.lastRow = newBuffered.lastRow; + + // Attach the tilemap back + tilemap.appendTo(parent); + } + break; + + case "angle": + //TODO + break; + + case "factor": + //TODO + break; + } + } + + } else { + var refreshBoundingCircle = $.gameQuery.playground && !$.gameQuery.playground.disableCollision; + + // Update the descriptor + for(property in transformation){ + switch(property){ + case "x": + if(refreshBoundingCircle){ + gameQuery.boundingCircle.x = gameQuery.posx+gameQuery.width/2; + } + break; + case "y": + if(refreshBoundingCircle){ + gameQuery.boundingCircle.y = gameQuery.posy+gameQuery.height/2; + } + break; + case "w": + case "h": + gameQuery.boundingCircle.originalRadius = Math.sqrt(Math.pow(gameQuery.width,2) + Math.pow(gameQuery.height,2))/2 + gameQuery.boundingCircle.radius = gameQuery.factor*gameQuery.boundingCircle.originalRadius; + break; + case "angle": //(in degrees) + gameQuery.angle = parseFloat(transformation.angle); + break; + case "factor": + gameQuery.factor = parseFloat(transformation.factor); + if(refreshBoundingCircle){ + gameQuery.boundingCircle.radius = gameQuery.factor*gameQuery.boundingCircle.originalRadius; + } + break; + } + } + } + }, + // State of the engine + state: STATE_NEW, + + // CSS classes used to mark game element + spriteCssClass: gQprefix + "sprite", + groupCssClass: gQprefix + "group", + tilemapCssClass: gQprefix + "tilemap", + tileCssClass: gQprefix + "tile", + // Prefix for CSS Ids or Classes + tileTypePrefix: gQprefix + "tileType_", + tileIdPrefix: gQprefix + "tile_" + }, + + /** + * Mute (or unmute) all the sounds. + */ + muteSound: function(muted){ + for (var i = $.gameQuery.resourceManager.sounds.length-1 ; i >= 0; i --) { + $.gameQuery.resourceManager.sounds[i].muted(muted); + } + }, + + /** + * Accessor for the currently defined playground as a jQuery object + */ + playground: function() { + return $.gameQuery.playground + }, + + /** + * Define a callback called during the loading of the game's resources. + * + * The function will recieve as unique parameter + * a number representing the progess percentage. + */ + loadCallback: function(callback){ + $.gameQuery.resourceManager.loadCallback = callback; + } + }); // end of the extensio of $ + + + // fragments used to create DOM element + var spriteFragment = $("
"); + var groupFragment = $("
"); + var tilemapFragment = $("
"); + + + // Define the list of object/function accessible through $("selector"). + $.fn.extend({ + /** + * Defines the currently selected div to which contains the game and initialize it. + * + * This is a non-destructive call + */ + playground: function(options) { + if(this.length == 1){ + if(this[0] == document){ + // Old usage detected, this is not supported anymore + throw "Old playground usage, use $.playground() to retreive the playground and $('mydiv').playground(options) to set the div!"; + } + options = $.extend({ + height: 320, + width: 480, + refreshRate: 30, + position: "absolute", + keyTracker: false, + mouseTracker: false, + disableCollision: false + }, options); + // We save the playground node and set some variable for this node: + $.gameQuery.playground = this; + $.gameQuery.refreshRate = options.refreshRate; + $.gameQuery.playground[0].height = options.height; + $.gameQuery.playground[0].width = options.width; + + // We initialize the display of the div + $.gameQuery.playground.css({ + position: options.position, + display: "block", + overflow: "hidden", + height: options.height+"px", + width: options.width+"px" + }) + .append(""+(g[0]>0&&N==g[1]-1?'
':""):""),M+=Q}K+=M}return K+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!a.inline?'':""),a._keyEvent=!1,K},_generateMonthYearHeader:function(a,b,c,d,e,f,g,h){var i=this._get(a,"changeMonth"),j=this._get(a,"changeYear"),k=this._get(a,"showMonthAfterYear"),l='
',m="";if(f||!i)m+=''+g[b]+"";else{var n=d&&d.getFullYear()==c,o=e&&e.getFullYear()==c;m+='"}k||(l+=m+(f||!i||!j?" ":""));if(!a.yearshtml){a.yearshtml="";if(f||!j)l+=''+c+"";else{var q=this._get(a,"yearRange").split(":"),r=(new Date).getFullYear(),s=function(a){var b=a.match(/c[+-].*/)?c+parseInt(a.substring(1),10):a.match(/[+-].*/)?r+parseInt(a,10):parseInt(a,10);return isNaN(b)?r:b},t=s(q[0]),u=Math.max(t,s(q[1]||""));t=d?Math.max(t,d.getFullYear()):t,u=e?Math.min(u,e.getFullYear()):u,a.yearshtml+='",l+=a.yearshtml,a.yearshtml=null}}return l+=this._get(a,"yearSuffix"),k&&(l+=(f||!i||!j?" ":"")+m),l+="
",l},_adjustInstDate:function(a,b,c){var d=a.drawYear+(c=="Y"?b:0),e=a.drawMonth+(c=="M"?b:0),f=Math.min(a.selectedDay,this._getDaysInMonth(d,e))+(c=="D"?b:0),g=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(d,e,f)));a.selectedDay=g.getDate(),a.drawMonth=a.selectedMonth=g.getMonth(),a.drawYear=a.selectedYear=g.getFullYear(),(c=="M"||c=="Y")&&this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max"),e=c&&bd?d:e,e},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");b&&b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){var b=this._get(a,"numberOfMonths");return b==null?[1,1]:typeof b=="number"?[1,b]:b},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,d){var e=this._getNumberOfMonths(a),f=this._daylightSavingAdjust(new Date(c,d+(b<0?b:e[0]*e[1]),1));return b<0&&f.setDate(this._getDaysInMonth(f.getFullYear(),f.getMonth())),this._isInRange(a,f)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min"),d=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!d||b.getTime()<=d.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");return b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10),{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,d){b||(a.currentDay=a.selectedDay,a.currentMonth=a.selectedMonth,a.currentYear=a.selectedYear);var e=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(d,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),e,this._getFormatConfig(a))}}),$.fn.datepicker=function(a){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv),$.datepicker.initialized=!0);var b=Array.prototype.slice.call(arguments,1);return typeof a!="string"||a!="isDisabled"&&a!="getDate"&&a!="widget"?a=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b)):this.each(function(){typeof a=="string"?$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this].concat(b)):$.datepicker._attachDatepicker(this,a)}):$.datepicker["_"+a+"Datepicker"].apply($.datepicker,[this[0]].concat(b))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.8.23",window["DP_jQuery_"+dpuuid]=$})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.ui.progressbar.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=a("
").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove(),a.Widget.prototype.destroy.apply(this,arguments)},value:function(a){return a===b?this._value():(this._setOption("value",a),this)},_setOption:function(b,c){b==="value"&&(this.options.value=c,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),a.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;return typeof a!="number"&&(a=0),Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var a=this.value(),b=this._percentage();this.oldValue!==a&&(this.oldValue=a,this._trigger("change")),this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(b.toFixed(0)+"%"),this.element.attr("aria-valuenow",a)}}),a.extend(a.ui.progressbar,{version:"1.8.23"})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.core.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +jQuery.effects||function(a,b){function c(b){var c;return b&&b.constructor==Array&&b.length==3?b:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))?[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)]:(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))?[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))?[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)]:(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))?[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)]:(c=/rgba\(0, 0, 0, 0\)/.exec(b))?e.transparent:e[a.trim(b).toLowerCase()]}function d(b,d){var e;do{e=(a.curCSS||a.css)(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};return a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete,[b,c,d,e]}function l(b){return!b||typeof b=="number"||a.fx.speeds[b]?!0:typeof b=="string"&&!a.effects[b]?!0:!1}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){return a.isFunction(d)&&(e=d,d=null),this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class")||"";a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.23",save:function(a,b){for(var c=0;c
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;try{e.id}catch(f){e=document.body}return b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;return b.parent().is(".ui-effects-wrapper")?(c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus(),c):b},setTransition:function(b,c,d,e){return e=e||{},a.each(c,function(a,c){var f=b.cssUnit(c);f[0]>0&&(e[c]=f[0]*d+f[1])}),e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];return a.fx.off||!i?h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)}):i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="show",this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);return b[1].mode="hide",this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);return c[1].mode="toggle",this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];return a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])}),d}});var m={};a.each(["Quad","Cubic","Quart","Quint","Expo"],function(a,b){m[b]=function(b){return Math.pow(b,a+2)}}),a.extend(m,{Sine:function(a){return 1-Math.cos(a*Math.PI/2)},Circ:function(a){return 1-Math.sqrt(1-a*a)},Elastic:function(a){return a===0||a===1?a:-Math.pow(2,8*(a-1))*Math.sin(((a-1)*80-7.5)*Math.PI/15)},Back:function(a){return a*a*(3*a-2)},Bounce:function(a){var b,c=4;while(a<((b=Math.pow(2,--c))-1)/11);return 1/Math.pow(4,3-c)-7.5625*Math.pow((b*3-2)/22-a,2)}}),a.each(m,function(b,c){a.easing["easeIn"+b]=c,a.easing["easeOut"+b]=function(a){return 1-c(1-a)},a.easing["easeInOut"+b]=function(a){return a<.5?c(a*2)/2:c(a*-2+2)/-2+1}})}(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.blind.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.blind=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.direction||"vertical";a.effects.save(c,d),c.show();var g=a.effects.createWrapper(c).css({overflow:"hidden"}),h=f=="vertical"?"height":"width",i=f=="vertical"?g.height():g.width();e=="show"&&g.css(h,0);var j={};j[h]=e=="show"?i:0,g.animate(j,b.duration,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.bounce.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.bounce=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"effect"),f=b.options.direction||"up",g=b.options.distance||20,h=b.options.times||5,i=b.duration||250;/show|hide/.test(e)&&d.push("opacity"),a.effects.save(c,d),c.show(),a.effects.createWrapper(c);var j=f=="up"||f=="down"?"top":"left",k=f=="up"||f=="left"?"pos":"neg",g=b.options.distance||(j=="top"?c.outerHeight(!0)/3:c.outerWidth(!0)/3);e=="show"&&c.css("opacity",0).css(j,k=="pos"?-g:g),e=="hide"&&(g=g/(h*2)),e!="hide"&&h--;if(e=="show"){var l={opacity:1};l[j]=(k=="pos"?"+=":"-=")+g,c.animate(l,i/2,b.options.easing),g=g/2,h--}for(var m=0;m
").css({position:"absolute",visibility:"visible",left:-j*(g/d),top:-i*(h/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/d,height:h/c,left:f.left+j*(g/d)+(b.options.mode=="show"?(j-Math.floor(d/2))*(g/d):0),top:f.top+i*(h/c)+(b.options.mode=="show"?(i-Math.floor(c/2))*(h/c):0),opacity:b.options.mode=="show"?0:1}).animate({left:f.left+j*(g/d)+(b.options.mode=="show"?0:(j-Math.floor(d/2))*(g/d)),top:f.top+i*(h/c)+(b.options.mode=="show"?0:(i-Math.floor(c/2))*(h/c)),opacity:b.options.mode=="show"?1:0},b.duration||500);setTimeout(function(){b.options.mode=="show"?e.css({visibility:"visible"}):e.css({visibility:"visible"}).hide(),b.callback&&b.callback.apply(e[0]),e.dequeue(),a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.fade.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.fade=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"hide");c.animate({opacity:d},{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.fold.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.fold=function(b){return this.queue(function(){var c=a(this),d=["position","top","bottom","left","right"],e=a.effects.setMode(c,b.options.mode||"hide"),f=b.options.size||15,g=!!b.options.horizFirst,h=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(c,d),c.show();var i=a.effects.createWrapper(c).css({overflow:"hidden"}),j=e=="show"!=g,k=j?["width","height"]:["height","width"],l=j?[i.width(),i.height()]:[i.height(),i.width()],m=/([0-9]+)%/.exec(f);m&&(f=parseInt(m[1],10)/100*l[e=="hide"?0:1]),e=="show"&&i.css(g?{height:0,width:f}:{height:f,width:0});var n={},p={};n[k[0]]=e=="show"?l[0]:f,p[k[1]]=e=="show"?l[1]:0,i.animate(n,h,b.options.easing).animate(p,h,b.options.easing,function(){e=="hide"&&c.hide(),a.effects.restore(c,d),a.effects.removeWrapper(c),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.highlight.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.highlight=function(b){return this.queue(function(){var c=a(this),d=["backgroundImage","backgroundColor","opacity"],e=a.effects.setMode(c,b.options.mode||"show"),f={backgroundColor:c.css("backgroundColor")};e=="hide"&&(f.opacity=0),a.effects.save(c,d),c.show().css({backgroundImage:"none",backgroundColor:b.options.color||"#ffff99"}).animate(f,{queue:!1,duration:b.duration,easing:b.options.easing,complete:function(){e=="hide"&&c.hide(),a.effects.restore(c,d),e=="show"&&!a.support.opacity&&this.style.removeAttribute("filter"),b.callback&&b.callback.apply(this,arguments),c.dequeue()}})})}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15 +* https://github.com/jquery/jquery-ui +* Includes: jquery.effects.pulsate.js +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ +(function(a,b){a.effects.pulsate=function(b){return this.queue(function(){var c=a(this),d=a.effects.setMode(c,b.options.mode||"show"),e=(b.options.times||5)*2-1,f=b.duration?b.duration/2:a.fx.speeds._default/2,g=c.is(":visible"),h=0;g||(c.css("opacity",0).show(),h=1),(d=="hide"&&g||d=="show"&&!g)&&e--;for(var i=0;i
').appendTo(document.body).addClass(b.options.className).css({top:g.top,left:g.left,height:c.innerHeight(),width:c.innerWidth(),position:"absolute"}).animate(f,b.duration,b.options.easing,function(){h.remove(),b.callback&&b.callback.apply(c[0],arguments),c.dequeue()})})}})(jQuery);; \ No newline at end of file diff --git a/lib/soundmanager2.min.js b/lib/soundmanager2.min.js new file mode 100644 index 0000000..c7987c1 --- /dev/null +++ b/lib/soundmanager2.min.js @@ -0,0 +1,106 @@ +/** @license + + + SoundManager 2: JavaScript Sound for the Web + ---------------------------------------------- + http://schillmania.com/projects/soundmanager2/ + + Copyright (c) 2007, Scott Schiller. All rights reserved. + Code provided under the BSD License: + http://schillmania.com/projects/soundmanager2/license.txt + + V2.97a.20130101 +*/ +(function(j,g){function aa(aa,pa){function ba(a){return c.preferFlash&&z&&!c.ignoreFlash&&c.flash[a]!==g&&c.flash[a]}function q(a){return function(d){var e=this._s;!e||!e._a?(e&&e.id?c._wD(e.id+": Ignoring "+d.type):c._wD(pb+"Ignoring "+d.type),d=null):d=a.call(this,d);return d}}this.setupOptions={url:aa||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3, +wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0,html5Test:/^(probably|maybe)$/i,preferFlash:!0,noSWFCache:!1};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1, +useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"', +"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=pa||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20130101";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1, +eqData:!1,movieStar:!1};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local+internet access)"},description:null,noRemote:null,noLocal:null};this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var Pa,c=this,Qa=null,i=null,pb="HTML5::",A,s=navigator.userAgent,R=j.location.href.toString(), +h=document,qa,Ra,ra,l,C=[],sa=!0,x,S=!1,T=!1,n=!1,r=!1,ca=!1,k,qb=0,U,v,ta,K,ua,I,L,M,Sa,va,da,F,ea,wa,N,xa,V,fa,ga,O,Ta,ya,Ua=["log","info","warn","error"],Va,za,Wa,W=null,Aa=null,p,Ba,P,Xa,ha,ia,Q,t,X=!1,Ca=!1,Ya,Za,$a,ja=0,Y=null,ka,J=[],B=null,ab,la,Z,G,Da,Ea,bb,u,cb=Array.prototype.slice,D=!1,Fa,z,Ga,db,E,eb,Ha,ma=s.match(/(ipad|iphone|ipod)/i),fb=s.match(/android/i),H=s.match(/msie/i),rb=s.match(/webkit/i),Ia=s.match(/safari/i)&&!s.match(/chrome/i),Ja=s.match(/opera/i),Ka=s.match(/(mobile|pre\/|xoom)/i)|| +ma||fb,La=!R.match(/usehtml5audio/i)&&!R.match(/sm2\-ignorebadua/i)&&Ia&&!s.match(/silk/i)&&s.match(/OS X 10_6_([3-7])/i),gb=j.console!==g&&console.log!==g,Ma=h.hasFocus!==g?h.hasFocus():null,na=Ia&&(h.hasFocus===g||!h.hasFocus()),hb=!na,ib=/(mp3|mp4|mpa|m4a|m4b)/i,$=h.location?h.location.protocol.match(/http/i):null,jb=!$?"http://":"",kb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,lb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),sb=RegExp("\\.("+ +lb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!$;var Na;try{Na=Audio!==g&&(Ja&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(ub){Na=!1}this.hasHTML5=Na;this.setup=function(a){var d=!c.url;a!==g&&(n&&B&&c.ok()&&(a.flashVersion!==g||a.url!==g||a.html5Test!==g))&&Q(p("setupLate"));ta(a);d&&(V&&a.url!==g)&&c.beginDelayedInit();!V&&(a.url!==g&&"complete"===h.readyState)&&setTimeout(N,1);return c};this.supported= +this.ok=function(){return B?n&&!r:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return A(c)||h[c]||j[c]};this.createSound=function(a,d){function e(){f=ha(f);c.sounds[f.id]=new Pa(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var b,f;b=null;b="soundManager.createSound(): "+p(!n?"notReady":"notOK");if(!n||!c.ok())return Q(b),!1;d!==g&&(a={id:a,url:d});f=v(a);f.url=ka(f.url);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+p("badID",f.id),2);c._wD("soundManager.createSound(): "+ +f.id+" ("+f.url+")",1);if(t(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];la(f)?(b=e(),c._wD(f.id+": Using HTML5"),b._setup_html5(f)):(8=a)return!1;for(a-=1;0<=a;a--)c=y[a],!c.fired&&b.position>=c.position&&(c.fired=!0,s++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(b){var a,c;a=y.length;if(!a)return!1;for(a-=1;0<=a;a--)c=y[a],c.fired&&b<=c.position&&(c.fired=!1,s--);return!0};u=function(){var a=b._iO,d=a.from,e=a.to,f,g;g=function(){c._wD(b.id+': "To" time of '+e+" reached.");b.clearOnPosition(e,g);b.stop()};f=function(){c._wD(b.id+': Playing "from" '+d);if(null!== +e&&!isNaN(e))b.onPosition(e,g)};null!==d&&!isNaN(d)&&(a.position=d,a.multiShot=!1,f());return a};n=function(){var a,c=b._iO.onposition;if(c)for(a in c)if(c.hasOwnProperty(a))b.onPosition(parseInt(a,10),c[a])};Oa=function(){var a,c=b._iO.onposition;if(c)for(a in c)c.hasOwnProperty(a)&&b.clearOnPosition(parseInt(a,10))};h=function(){b.isHTML5&&Ya(b)};m=function(){b.isHTML5&&Za(b)};f=function(a){a||(y=[],s=0);q=!1;b._hasTimer=null;b._a=null;b._html5_canplay=!1;b.bytesLoaded=null;b.bytesTotal=null;b.duration= +b._iO&&b._iO.duration?b._iO.duration:null;b.durationEstimate=null;b.buffered=[];b.eqData=[];b.eqData.left=[];b.eqData.right=[];b.failures=0;b.isBuffering=!1;b.instanceOptions={};b.instanceCount=0;b.loaded=!1;b.metadata={};b.readyState=0;b.muted=!1;b.paused=!1;b.peakData={left:0,right:0};b.waveformData={left:[],right:[]};b.playState=0;b.position=null;b.id3={}};f();this._onTimer=function(a){var c,f=!1,g={};if(b._hasTimer||a){if(b._a&&(a||(0opera.version()?new Audio(null):new Audio,d=b._a,d._called_load=!1,D&&(Qa=d);b.isHTML5=!0;b._a=d;d._s=b;j();b._apply_loop(d,a.loops);a.autoLoad||a.autoPlay?b.load():(d.autobuffer=!1,d.preload="auto");return d};j=function(){if(b._a._added_events)return!1; +var a;b._a._added_events=!0;for(a in E)E.hasOwnProperty(a)&&b._a&&b._a.addEventListener(a,E[a],!1);return!0};mb=function(){var a;c._wD(b.id+": Removing event listeners");b._a._added_events=!1;for(a in E)E.hasOwnProperty(a)&&b._a&&b._a.removeEventListener(a,E[a],!1)};this._onload=function(a){var d=!!a||!b.isHTML5&&8===l&&b.duration,a=b.id+": ";c._wD(a+(d?"onload()":"Failed to load? - "+b.url),d?1:2);!d&&!b.isHTML5&&(!0===c.sandbox.noRemote&&c._wD(a+p("noNet"),1),!0===c.sandbox.noLocal&&c._wD(a+p("noLocal"), +1));b.loaded=d;b.readyState=d?3:2;b._onbufferchange(0);b._iO.onload&&b._iO.onload.apply(b,[d]);return!0};this._onbufferchange=function(a){if(0===b.playState||a&&b.isBuffering||!a&&!b.isBuffering)return!1;b.isBuffering=1===a;b._iO.onbufferchange&&(c._wD(b.id+": Buffer state change: "+a),b._iO.onbufferchange.apply(b));return!0};this._onsuspend=function(){b._iO.onsuspend&&(c._wD(b.id+": Playback suspended"),b._iO.onsuspend.apply(b));return!0};this._onfailure=function(a,d,e){b.failures++;c._wD(b.id+": Failures = "+ +b.failures);if(b._iO.onfailure&&1===b.failures)b._iO.onfailure(b,a,d,e);else c._wD(b.id+": Ignoring failure")};this._onfinish=function(){var a=b._iO.onfinish;b._onbufferchange(0);b._resetOnPosition(0);if(b.instanceCount&&(b.instanceCount--,b.instanceCount||(Oa(),b.playState=0,b.paused=!1,b.instanceCount=0,b.instanceOptions={},b._iO={},m(),b.isHTML5&&(b.position=0)),(!b.instanceCount||b._iO.multiShotEvents)&&a))c._wD(b.id+": onfinish()"),a.apply(b)};this._whileloading=function(a,c,d,e){var f=b._iO; +b.bytesLoaded=a;b.bytesTotal=c;b.duration=Math.floor(d);b.bufferLength=e;b.durationEstimate=!b.isHTML5&&!f.isMovieStar?f.duration?b.duration>f.duration?b.duration:f.duration:parseInt(b.bytesTotal/b.bytesLoaded*b.duration,10):b.duration;b.isHTML5||(b.buffered=[{start:0,end:b.duration}]);(3!==b.readyState||b.isHTML5)&&f.whileloading&&f.whileloading.apply(b)};this._whileplaying=function(a,c,d,e,f){var m=b._iO;if(isNaN(a)||null===a)return!1;b.position=Math.max(0,a);b._processOnPosition();!b.isHTML5&& +8opera.version()?new Audio(null):new Audio:null,e,b,f={},h;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(b="audio/"+e,f[e]=a(h[e].type),f[b]=f[e],e.match(ib)?(c.flash[e]=!0,c.flash[b]=!0):(c.flash[e]=!1,c.flash[b]=!1),h[e]&&h[e].related))for(b=h[e].related.length-1;0<=b;b--)f["audio/"+h[e].related[b]]=f[e],c.html5[h[e].related[b]]=f[e],c.flash[h[e].related[b]]=f[e];f.canPlayType=d?a:null;c.html5= +v(c.html5,f);return!0};F={notReady:"Unavailable - wait until onready() has fired.",notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)",checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+h.location.protocol+ +" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s", +badID:'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?",secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html", +badRemove:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",fbLoaded:"Flash loaded",flRemoved:"soundManager: Flash movie removed.",fbHandler:"soundManager: flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.", +badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case",needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.", +policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().",noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready.",reset:"soundManager.reset(): Removing event callbacks", +mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device."};p=function(){var a=cb.call(arguments),c=a.shift(),c=F&&F[c]?F[c]:"",e,b;if(c&&a&&a.length){e=0;for(b=a.length;el)&&(c._wD(p("needfl9")),c.flashVersion=l=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===l?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(S&&T)return!1;if(c.html5Only)return va(),e(),c.oMC=A(c.movieID),ra(),T=S=!0,!1;var f=d||c.url,j=c.altURL||f,i=fa(),m=P(),l=null,l=h.getElementsByTagName("html")[0],k,q,n,l=l&&l.dir&&l.dir.match(/rtl/i),a=a===g?c.id:a;va();c.url=Wa($?f:j);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!==c.wmode&&(s.match(/msie 8/i)||!H&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))J.push(F.spcWmode),c.wmode=null;i= +{name:a,id:a,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:jb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(i.FlashVars="debug=1");c.wmode||delete i.wmode;if(H)f=h.createElement("div"),q=['', +b("movie",d),b("AllowScriptAccess",c.allowScriptAccess),b("quality",i.quality),c.wmode?b("wmode",c.wmode):"",b("bgcolor",c.bgColor),b("hasPriority","true"),c.debugFlash?b("FlashVars",i.FlashVars):"",""].join("");else for(k in f=h.createElement("embed"),i)i.hasOwnProperty(k)&&f.setAttribute(k,i[k]);ya();m=P();if(i=fa())if(c.oMC=A(c.movieID)||h.createElement("div"),c.oMC.id)n=c.oMC.className,c.oMC.className=(n?n+" ":"movieContainer")+(m?" "+m:""),c.oMC.appendChild(f),H&&(k=c.oMC.appendChild(h.createElement("div")), +k.className="sm2-object-box",k.innerHTML=q),T=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+m;k=m=null;c.useFlashBlock||(c.useHighPerformance?m={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(m={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},l&&(m.left=Math.abs(parseInt(m.left,10))+"px")));rb&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(n in m)m.hasOwnProperty(n)&&(c.oMC.style[n]=m[n]);try{H||c.oMC.appendChild(f), +i.appendChild(c.oMC),H&&(k=c.oMC.appendChild(h.createElement("div")),k.className="sm2-object-box",k.innerHTML=q),T=!0}catch(r){throw Error(p("domError")+" \n"+r.toString());}}S=!0;e();return!0};ea=function(){if(c.html5Only)return ga(),!1;if(i)return!1;if(!c.url)return k("noURL"),!1;i=c.getMovie(c.id);i||(W?(H?c.oMC.innerHTML=Aa:c.oMC.appendChild(W),W=null,S=!0):ga(c.id,c.url),i=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);Ha();return!0};M=function(){setTimeout(Sa, +1E3)};Sa=function(){var a,d=!1;if(!c.url||X)return!1;X=!0;u.remove(j,"load",M);if(na&&!Ma)return k("waitFocus"),!1;n||(a=c.getMoviePercent(),0a&&(d=!0));setTimeout(function(){a=c.getMoviePercent();if(d)return X=!1,c._wD(p("waitSWF")),j.setTimeout(M,1),!1;n||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+(0===a?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+p("checkSWF"):""),2),!$&&a&&(k("localFail",2),c.debugFlash||k("tryDebug", +2)),0===a&&c._wD(p("swf404",c.url),1),x("flashtojs",!1,": Timed out"+$?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));!n&&hb&&(null===a?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ba(),k("waitForever")):(k("waitForever"),I({type:"ontimeout",ignoreInit:!0})):0===c.flashLoadTimeout?k("waitForever"):za(!0))},c.flashLoadTimeout)};da=function(){if(Ma||!na)return u.remove(j,"focus",da),!0;Ma=hb=!0;k("gotFocus");X=!1;M();u.remove(j,"focus",da);return!0};Ha=function(){J.length&& +(c._wD("SoundManager 2: "+J.join(" "),1),J=[])};eb=function(){Ha();var a,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(a in c.audioFormats)c.audioFormats.hasOwnProperty(a)&&d.push(a+" = "+c.html5[a]+(!c.html5[a]&&z&&c.flash[a]?" (using flash)":c.preferFlash&&c.flash[a]&&z?" (preferring flash)":!c.html5[a]?" ("+(c.audioFormats[a].required?"required, ":"")+"and no flash support)":""));c._wD("SoundManager 2 HTML5 support: "+d.join(", "),1)}};U=function(a){if(n)return!1;if(c.html5Only)return k("sm2Loaded"), +n=!0,L(),x("onload",!0),!0;var d=!0,e;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())n=!0,r&&(e={type:!z&&B?"NO_FLASH":"INIT_TIMEOUT"});c._wD("SoundManager 2 "+(r?"failed to load":"loaded")+" ("+(r?"Flash security/load error":"OK")+")",r?2:1);r||a?(c.useFlashBlock&&c.oMC&&(c.oMC.className=P()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),I({type:"ontimeout",error:e,ignoreInit:!0}),x("onload",!1),O(e),d=!1):x("onload",!0);r||(c.waitForWindowLoad&&!ca?(k("waitOnload"), +u.add(j,"load",L)):(c.waitForWindowLoad&&ca&&k("docLoaded"),L()));return d};Ra=function(){var a,d=c.setupOptions;for(a in d)d.hasOwnProperty(a)&&(c[a]===g?c[a]=d[a]:c[a]!==d[a]&&(c.setupOptions[a]=c[a]))};ra=function(){if(n)return k("didInit"),!1;if(c.html5Only)return n||(u.remove(j,"load",c.beginDelayedInit),c.enabled=!0,U()),!0;ea();try{i._externalInterfaceTest(!1),Ta(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||i._disableDebug(),c.enabled=!0,x("jstoflash",!0),c.html5Only|| +u.add(j,"unload",qa)}catch(a){return c._wD("js/flash exception: "+a.toString()),x("jstoflash",!1),O({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),za(!0),U(),!1}U();u.remove(j,"load",c.beginDelayedInit);return!0};N=function(){if(V)return!1;V=!0;Ra();ya();var a=null,a=null,d=j.console!==g&&"function"===typeof console.log,e=R.toLowerCase();-1!==e.indexOf("sm2-usehtml5audio=")&&(a="1"===e.charAt(e.indexOf("sm2-usehtml5audio=")+18),d&&console.log((a?"Enabling ":"Disabling ")+"useHTML5Audio via URL parameter"), +c.setup({useHTML5Audio:a}));-1!==e.indexOf("sm2-preferflash=")&&(a="1"===e.charAt(e.indexOf("sm2-preferflash=")+16),d&&console.log((a?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.setup({preferFlash:a}));!z&&c.hasHTML5&&(c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));bb();c.html5.usingFlash=ab();B=c.html5.usingFlash;!z&&B&&(J.push(F.needFlash),c.setup({flashLoadTimeout:1}));h.removeEventListener&& +h.removeEventListener("DOMContentLoaded",N,!1);ea();return!0};Ea=function(){"complete"===h.readyState&&(N(),h.detachEvent("onreadystatechange",Ea));return!0};xa=function(){ca=!0;u.remove(j,"load",xa)};wa=function(){if(Ka&&((!c.setupOptions.useHTML5Audio||c.setupOptions.preferFlash)&&J.push(F.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,ma||fb&&!s.match(/android\s2\.3/i)))J.push(F.globalHTML5),ma&&(c.ignoreFlash=!0),D=!0};wa();Ga();u.add(j,"focus",da);u.add(j,"load",M);u.add(j, +"load",xa);h.addEventListener?h.addEventListener("DOMContentLoaded",N,!1):h.attachEvent?h.attachEvent("onreadystatechange",Ea):(x("onload",!1),O({type:"NO_DOM2_EVENTS",fatal:!0}))}var pa=null;if(void 0===j.SM2_DEFER||!SM2_DEFER)pa=new aa;j.SoundManager=aa;j.soundManager=pa})(window); \ No newline at end of file diff --git a/sound/dies.mp3 b/sound/dies.mp3 new file mode 100644 index 0000000..14c76bc Binary files /dev/null and b/sound/dies.mp3 differ diff --git a/sound/eatingfruit.mp3 b/sound/eatingfruit.mp3 new file mode 100644 index 0000000..d63cb9e Binary files /dev/null and b/sound/eatingfruit.mp3 differ diff --git a/sound/eatingghost.mp3 b/sound/eatingghost.mp3 new file mode 100644 index 0000000..13d25bb Binary files /dev/null and b/sound/eatingghost.mp3 differ diff --git a/sound/opening.mp3 b/sound/opening.mp3 new file mode 100644 index 0000000..7aac980 Binary files /dev/null and b/sound/opening.mp3 differ diff --git a/sound/siren.mp3 b/sound/siren.mp3 new file mode 100644 index 0000000..cbe9c4a Binary files /dev/null and b/sound/siren.mp3 differ diff --git a/sound/wakawaka.mp3 b/sound/wakawaka.mp3 new file mode 100644 index 0000000..69791d3 Binary files /dev/null and b/sound/wakawaka.mp3 differ diff --git a/swf/soundmanager2.swf b/swf/soundmanager2.swf new file mode 100644 index 0000000..b62fa6e Binary files /dev/null and b/swf/soundmanager2.swf differ diff --git a/swf/soundmanager2_debug.swf b/swf/soundmanager2_debug.swf new file mode 100644 index 0000000..3539251 Binary files /dev/null and b/swf/soundmanager2_debug.swf differ diff --git a/swf/soundmanager2_flash9.swf b/swf/soundmanager2_flash9.swf new file mode 100644 index 0000000..707a558 Binary files /dev/null and b/swf/soundmanager2_flash9.swf differ diff --git a/swf/soundmanager2_flash9_debug.swf b/swf/soundmanager2_flash9_debug.swf new file mode 100644 index 0000000..370ecba Binary files /dev/null and b/swf/soundmanager2_flash9_debug.swf differ