Advertisement
Guest User

Untitled

a guest
Aug 19th, 2016
339
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Full game code
  2.  
  3. index.html
  4.  
  5. <!DOCTYPE html>
  6. <html>
  7. <head>
  8.   <meta charset="UTF-8">
  9.   <title>LE JEU DES MANDARINES 0.90</title>
  10.   <link rel="stylesheet" href="ljdm.css" type="text/css" media="screen">
  11.   <script type="text/javascript" src="jquery.2.1.1.min.js"></script>
  12. </head>
  13. <body>
  14.   <div class="wrapper">
  15.     <div class="sound sound-off"></div>
  16.     <div id="menu">
  17.       <div id="progress">
  18.         <div id="percent">Téléchargement: <span id="p"></span></div>
  19.         <progress id="progress-bar" value="0"></progress>
  20.       </div>
  21.       <div id="main">
  22.         <h1>LE JEU DES MANDARINES</h1>
  23.         <ul>
  24.           <li><a href="javascript:void(0)" class="button play">JOUER</a></li>
  25.           <li><a href="javascript:void(0)" class="button credits">Les Credits</a></li>
  26.           <li><a href="javascript:void(0)" class="button howto">Comment Jouer</a></li>
  27.         </ul>
  28.       </div>
  29.       <div id="credits">
  30.         <ul>
  31.         <li class="maincredits">Inspiration Première/Vidéo des Mandarines/Notre Maître a tous : <a href="https://www.youtube.com/user/legrandjd" target="_blank">LeGrandJD</a></li>
  32.         <li class="maincredits">Chef de projet/Idée du Jeu : <a href="https://twitter.com/k0spwn/" target="_blank">k0spwn</a></li>
  33.         <li class="maincredits">Graphiste : Seveko00</li>
  34.         </ul>
  35.         <ul>
  36.           <li class="artwork">Inspiration Première/Vidéo des Mandarines/Notre Maître a tous : <a href="https://www.youtube.com/user/legrandjd" target="_blank">LeGrandJD</a></li>
  37.           <li class="artwork">Character design and art: <a href="https://www.youtube.com/user/legrandjd">LeGrandJD ( Julien Donzé )</a></li>
  38.           <li class="artwork">Animation du personnage : Seveko00</li>
  39.           <li class="artwork">Les Plateformes: Seveko00</li>
  40.         </ul>
  41.         <ul>
  42.           <li class="music">La Musique: <a href="https://www.youtube.com/watch?v=aHrc_F8xMXE" target="_blank">LeGrandJD ( Julien Donzé )</a></li>
  43.           <li class="music">Jump sound effect: <a href="http://opengameart.org/content/platformer-jumping-sounds" target="_blank">dklon</a></li>
  44.           <li class="music">Game over music: <a href="https://twitter.com/k0spwn/" target="_blank">k0spwn</a></li>
  45.         </ul>
  46.         <ul>
  47.           <li class="developer">Developeurs : <a href="https://twitter.com/k0spwn/" target="_blank">k0spwn</a> et Seko00</li>
  48.           <li class="developer">Developeur de la base Javascript/CSS : <a href="http://blog.sklambert.com/" target="_blank">Steven Lambert</a></li>
  49.         </ul>
  50.           <li class="addcredits">Remerciements : <br>- EtGamerz <br>- BurnHunterz <br>- PaoloLucky13 <br>- LeGrandJD ( Evidemment ) </li>
  51.         <ul>
  52.         </ul>
  53.         <a href="javascript:void(0)" class="button back">Retour au jeu</a>
  54.       </div>
  55.       <div id="howto">
  56.          <ul>
  57.             <h2><font color="blue">Réfere toi a ce magnifique dessin pour apprendre a jouer:</font><h2>
  58.          </ul>  
  59.         <a href="javascript:void(0)" class="button back">Retour au jeu</a>
  60.       </div>
  61.     </div>
  62.     <canvas id="canvas" width="800" height="480">
  63.       <p>Ton naviguateur Internet n'a pas les fonctionnalitée requise pour jouer a ce jeu</p>
  64.      <p>Veuillez télécharger un naviguateur plus récent comme <a href="www.google.com/chrome/‎">Google Chrome</a> pour pouvoir jouer</p>
  65.    </canvas>
  66.    <div id="game-over">
  67.      <h3><font color="orange">Tu as courus <span id="score"></span> mètres, tu peux faire mieux (ou pas)</font></h3>
  68.      <a href="javascript:void(0)" class="button restart">Ressayer ?</a>
  69.       <button class="button back"><a href="javascript:location.reload(true)">Retour au menu</a></button>
  70.    </div>
  71.  </div>
  72.  <script type="text/javascript" src="ljdm.js"></script>
  73. </body>
  74. </html>
  75.  
  76.  
  77. JAVASCRIPT CODE HERE \|/
  78. ljdm.js
  79.  
  80. (function ($) {
  81. // define variables
  82. var canvas = document.getElementById('canvas');
  83. var ctx = canvas.getContext('2d');
  84. var player, score, stop, ticker;
  85. var ground = [], water = [], enemies = [], environment = [];
  86.  
  87. // platform variables
  88. var platformHeight, platformLength, gapLength;
  89. var platformWidth = 32;
  90. var platformBase = canvas.height - platformWidth;  // bottom row of the game
  91. var platformSpacer = 64;
  92.  
  93. var canUseLocalStorage = 'localStorage' in window && window.localStorage !== null;
  94. var playSound;
  95.  
  96. // set the sound preference
  97. if (canUseLocalStorage) {
  98.  playSound = (localStorage.getItem('kandi.playSound') === "true")
  99.  
  100.  if (playSound) {
  101.    $('.sound').addClass('sound-on').removeClass('sound-off');
  102.  }
  103.  else {
  104.    $('.sound').addClass('sound-off').removeClass('sound-on');
  105.  }
  106. }
  107.  
  108. /**
  109. * Get a random number between range
  110. * @param {integer}
  111. * @param {integer}
  112. */
  113. function rand(low, high) {
  114.  return Math.floor( Math.random() * (high - low + 1) + low );
  115. }
  116.  
  117. /**
  118. * Bound a number between range
  119. * @param {integer} num - Number to bound
  120. * @param {integer}
  121. * @param {integer}
  122. */
  123. function bound(num, low, high) {
  124.  return Math.max( Math.min(num, high), low);
  125. }
  126.  
  127. /**
  128. * Asset pre-loader object. Loads all images
  129. */
  130. var assetLoader = (function() {
  131.  // images dictionary
  132.  this.imgs        = {
  133.    'bg'            : 'imgs/bg.png',
  134.    'sky'           : 'imgs/sky.png',
  135.    'backdrop'      : 'imgs/backdrop.png',
  136.    'backdrop2'     : 'imgs/backdrop_ground.png',
  137.    'grass'         : 'imgs/grass.png',
  138.    'avatar_normal' : 'imgs/normal_walk.png',
  139.    'water'         : 'imgs/water.png',
  140.    'grass1'        : 'imgs/grassMid1.png',
  141.    'grass2'        : 'imgs/grassMid2.png',
  142.    'bridge'        : 'imgs/bridge.png',
  143.    'plant'         : 'imgs/plant.png',
  144.    'bush1'         : 'imgs/bush1.png',
  145.    'bush2'         : 'imgs/bush2.png',
  146.    'cliff'         : 'imgs/grassCliffRight.png',
  147.    'spikes'        : 'imgs/spikes.png',
  148.    'box'           : 'imgs/boxCoin.png',
  149.    'slime'         : 'imgs/slime.png'
  150.  };
  151.  
  152.  // sounds dictionary
  153.  this.sounds      = {
  154.    'bg'            : 'sounds/bg.mp3',
  155.    'jump'          : 'sounds/jump.mp3',
  156.    'gameOver'      : 'sounds/gameOver.mp3'
  157.  };
  158.  
  159.  var assetsLoaded = 0;                                // how many assets have been loaded
  160.  var numImgs      = Object.keys(this.imgs).length;    // total number of image assets
  161.  var numSounds    = Object.keys(this.sounds).length;  // total number of sound assets
  162.  this.totalAssest = numImgs;                          // total number of assets
  163.  
  164.  /**
  165.   * Ensure all assets are loaded before using them
  166.   * @param {number} dic  - Dictionary name ('imgs', 'sounds', 'fonts')
  167.   * @param {number} name - Asset name in the dictionary
  168.   */
  169.  function assetLoaded(dic, name) {
  170.    // don't count assets that have already loaded
  171.     if (this[dic][name].status !== 'loading') {
  172.       return;
  173.     }
  174.  
  175.     this[dic][name].status = 'loaded';
  176.     assetsLoaded++;
  177.  
  178.     // progress callback
  179.     if (typeof this.progress === 'function') {
  180.       this.progress(assetsLoaded, this.totalAssest);
  181.     }
  182.  
  183.     // finished callback
  184.     if (assetsLoaded === this.totalAssest && typeof this.finished === 'function') {
  185.       this.finished();
  186.     }
  187.   }
  188.  
  189.   /**
  190.    * Check the ready state of an Audio file.
  191.    * @param {object} sound - Name of the audio asset that was loaded.
  192.    */
  193.   function _checkAudioState(sound) {
  194.     if (this.sounds[sound].status === 'loading' && this.sounds[sound].readyState === 4) {
  195.       assetLoaded.call(this, 'sounds', sound);
  196.     }
  197.   }
  198.  
  199.   /**
  200.    * Create assets, set callback for asset loading, set asset source
  201.    */
  202.   this.downloadAll = function() {
  203.     var _this = this;
  204.     var src;
  205.  
  206.     // load images
  207.     for (var img in this.imgs) {
  208.       if (this.imgs.hasOwnProperty(img)) {
  209.         src = this.imgs[img];
  210.  
  211.         // create a closure for event binding
  212.         (function(_this, img) {
  213.           _this.imgs[img] = new Image();
  214.           _this.imgs[img].status = 'loading';
  215.           _this.imgs[img].name = img;
  216.           _this.imgs[img].onload = function() { assetLoaded.call(_this, 'imgs', img) };
  217.           _this.imgs[img].src = src;
  218.         })(_this, img);
  219.       }
  220.     }
  221.  
  222.     // load sounds
  223.     for (var sound in this.sounds) {
  224.       if (this.sounds.hasOwnProperty(sound)) {
  225.         src = this.sounds[sound];
  226.  
  227.         // create a closure for event binding
  228.         (function(_this, sound) {
  229.           _this.sounds[sound] = new Audio();
  230.           _this.sounds[sound].status = 'loading';
  231.           _this.sounds[sound].name = sound;
  232.           _this.sounds[sound].addEventListener('canplay', function() {
  233.             _checkAudioState.call(_this, sound);
  234.           });
  235.           _this.sounds[sound].src = src;
  236.           _this.sounds[sound].preload = 'auto';
  237.           _this.sounds[sound].load();
  238.         })(_this, sound);
  239.       }
  240.     }
  241.   }
  242.  
  243.   return {
  244.     imgs: this.imgs,
  245.     sounds: this.sounds,
  246.     totalAssest: this.totalAssest,
  247.     downloadAll: this.downloadAll
  248.   };
  249. })();
  250.  
  251. /**
  252.  * Show asset loading progress
  253.  * @param {integer} progress - Number of assets loaded
  254.  * @param {integer} total - Total number of assets
  255.  */
  256. assetLoader.progress = function(progress, total) {
  257.   var pBar = document.getElementById('progress-bar');
  258.   pBar.value = progress / total;
  259.   document.getElementById('p').innerHTML = Math.round(pBar.value * 100) + "%";
  260. }
  261.  
  262. /**
  263.  * Load the main menu
  264.  */
  265. assetLoader.finished = function() {
  266.   mainMenu();
  267. }
  268.  
  269. /**
  270.  * Creates a Spritesheet
  271.  * @param {string} - Path to the image.
  272.  * @param {number} - Width (in px) of each frame.
  273.  * @param {number} - Height (in px) of each frame.
  274.  */
  275. function SpriteSheet(path, frameWidth, frameHeight) {
  276.   this.image = new Image();
  277.   this.frameWidth = frameWidth;
  278.   this.frameHeight = frameHeight;
  279.  
  280.   // calculate the number of frames in a row after the image loads
  281.   var self = this;
  282.   this.image.onload = function() {
  283.     self.framesPerRow = Math.floor(self.image.width / self.frameWidth);
  284.   };
  285.  
  286.   this.image.src = path;
  287. }
  288.  
  289. /**
  290.  * Creates an animation from a spritesheet.
  291.  * @param {SpriteSheet} - The spritesheet used to create the animation.
  292.  * @param {number}      - Number of frames to wait for before transitioning the animation.
  293.  * @param {array}       - Range or sequence of frame numbers for the animation.
  294.  * @param {boolean}     - Repeat the animation once completed.
  295.  */
  296. function Animation(spritesheet, frameSpeed, startFrame, endFrame) {
  297.  
  298.   var animationSequence = [];  // array holding the order of the animation
  299.   var currentFrame = 0;        // the current frame to draw
  300.   var counter = 0;             // keep track of frame rate
  301.  
  302.   // start and end range for frames
  303.   for (var frameNumber = startFrame; frameNumber <= endFrame; frameNumber++)
  304.     animationSequence.push(frameNumber);
  305.  
  306.   /**
  307.    * Update the animation
  308.    */
  309.   this.update = function() {
  310.  
  311.     // update to the next frame if it is time
  312.     if (counter == (frameSpeed - 1))
  313.       currentFrame = (currentFrame + 1) % animationSequence.length;
  314.  
  315.     // update the counter
  316.     counter = (counter + 1) % frameSpeed;
  317.   };
  318.  
  319.   /**
  320.    * Draw the current frame
  321.    * @param {integer} x - X position to draw
  322.    * @param {integer} y - Y position to draw
  323.    */
  324.   this.draw = function(x, y) {
  325.     // get the row and col of the frame
  326.     var row = Math.floor(animationSequence[currentFrame] / spritesheet.framesPerRow);
  327.     var col = Math.floor(animationSequence[currentFrame] % spritesheet.framesPerRow);
  328.  
  329.     ctx.drawImage(
  330.       spritesheet.image,
  331.       col * spritesheet.frameWidth, row * spritesheet.frameHeight,
  332.       spritesheet.frameWidth, spritesheet.frameHeight,
  333.       x, y,
  334.       spritesheet.frameWidth, spritesheet.frameHeight);
  335.   };
  336. }
  337.  
  338. /**
  339.  * Create a parallax background
  340.  */
  341. var background = (function() {
  342.   var sky   = {};
  343.   var backdrop = {};
  344.   var backdrop2 = {};
  345.  
  346.   /**
  347.    * Draw the backgrounds to the screen at different speeds
  348.    */
  349.   this.draw = function() {
  350.     ctx.drawImage(assetLoader.imgs.bg, 0, 0);
  351.  
  352.     // Pan background
  353.     sky.x -= sky.speed;
  354.     backdrop.x -= backdrop.speed;
  355.     backdrop2.x -= backdrop2.speed;
  356.  
  357.     // draw images side by side to loop
  358.     ctx.drawImage(assetLoader.imgs.sky, sky.x, sky.y);
  359.     ctx.drawImage(assetLoader.imgs.sky, sky.x + canvas.width, sky.y);
  360.  
  361.     ctx.drawImage(assetLoader.imgs.backdrop, backdrop.x, backdrop.y);
  362.     ctx.drawImage(assetLoader.imgs.backdrop, backdrop.x + canvas.width, backdrop.y);
  363.  
  364.     ctx.drawImage(assetLoader.imgs.backdrop2, backdrop2.x, backdrop2.y);
  365.     ctx.drawImage(assetLoader.imgs.backdrop2, backdrop2.x + canvas.width, backdrop2.y);
  366.  
  367.     // If the image scrolled off the screen,
  368.     if (sky.x + assetLoader.imgs.sky.width <= 0)
  369.       sky.x = 0;
  370.     if (backdrop.x + assetLoader.imgs.backdrop.width <= 0)
  371.       backdrop.x = 0;
  372.     if (backdrop2.x + assetLoader.imgs.backdrop2.width <= 0)
  373.       backdrop2.x = 0;
  374.   };
  375.  
  376.   /**
  377.    * Reset background to zero
  378.    */
  379.   this.reset = function()  {
  380.     sky.x = 0;
  381.     sky.y = 0;
  382.     sky.speed = 0.2;
  383.  
  384.     backdrop.x = 0;
  385.     backdrop.y = 0;
  386.     backdrop.speed = 0.4;
  387.  
  388.     backdrop2.x = 0;
  389.     backdrop2.y = 0;
  390.     backdrop2.speed = 0.6;
  391.   }
  392.  
  393.   return {
  394.     draw: this.draw,
  395.     reset: this.reset
  396.   };
  397. })();
  398.  
  399. /**
  400.  * A vector for 2d space.
  401.  * @param {integer} x - Center x coordinate.
  402.  * @param {integer} y - Center y coordinate.
  403.  * @param {integer} dx - Change in x.
  404.  * @param {integer} dy - Change in y.
  405.  */
  406. function Vector(x, y, dx, dy) {
  407.   // position
  408.   this.x = x || 0;
  409.   this.y = y || 0;
  410.   // direction
  411.   this.dx = dx || 0;
  412.   this.dy = dy || 0;
  413. }
  414.  
  415. /**
  416.  * Advance the vectors position by dx,dy
  417.  */
  418. Vector.prototype.advance = function() {
  419.   this.x += this.dx;
  420.   this.y += this.dy;
  421. };
  422.  
  423. /**
  424.  * Get the minimum distance between two vectors
  425.  * @param {Vector}
  426.  * @return minDist
  427.  */
  428. Vector.prototype.minDist = function(vec) {
  429.   var minDist = Infinity;
  430.   var max     = Math.max( Math.abs(this.dx), Math.abs(this.dy),
  431.                           Math.abs(vec.dx ), Math.abs(vec.dy ) );
  432.   var slice   = 1 / max;
  433.  
  434.   var x, y, distSquared;
  435.  
  436.   // get the middle of each vector
  437.   var vec1 = {}, vec2 = {};
  438.   vec1.x = this.x + this.width/2;
  439.   vec1.y = this.y + this.height/2;
  440.   vec2.x = vec.x + vec.width/2;
  441.   vec2.y = vec.y + vec.height/2;
  442.   for (var percent = 0; percent < 1; percent += slice) {
  443.     x = (vec1.x + this.dx * percent) - (vec2.x + vec.dx * percent);
  444.     y = (vec1.y + this.dy * percent) - (vec2.y + vec.dy * percent);
  445.     distSquared = x * x + y * y;
  446.  
  447.     minDist = Math.min(minDist, distSquared);
  448.   }
  449.  
  450.   return Math.sqrt(minDist);
  451. };
  452.  
  453. /**
  454.  * The player object
  455.  */
  456. var player = (function(player) {
  457.   // add properties directly to the player imported object
  458.   player.width     = 60;
  459.   player.height    = 96;
  460.   player.speed     = 6;
  461.  
  462.   // jumping
  463.   player.gravity   = 1;
  464.   player.dy        = 0;
  465.   player.jumpDy    = -10;
  466.   player.isFalling = false;
  467.   player.isJumping = false;
  468.  
  469.   // spritesheets
  470.   player.sheet     = new SpriteSheet('imgs/normal_walk.png', player.width, player.height);
  471.   player.walkAnim  = new Animation(player.sheet, 4, 0, 15);
  472.   player.jumpAnim  = new Animation(player.sheet, 4, 15, 15);
  473.   player.fallAnim  = new Animation(player.sheet, 4, 11, 11);
  474.   player.anim      = player.walkAnim;
  475.  
  476.   Vector.call(player, 0, 0, 0, player.dy);
  477.  
  478.   var jumpCounter = 0;  // how long the jump button can be pressed down
  479.  
  480.   /**
  481.    * Update the player's position and animation
  482.    */
  483.   player.update = function() {
  484.  
  485.     // jump if not currently jumping or falling
  486.     if (KEY_STATUS.space && player.dy === 0 && !player.isJumping) {
  487.       player.isJumping = true;
  488.       player.dy = player.jumpDy;
  489.       jumpCounter = 12;
  490.       assetLoader.sounds.jump.play();
  491.     }
  492.  
  493.     // jump higher if the space bar is continually pressed
  494.     if (KEY_STATUS.space && jumpCounter) {
  495.       player.dy = player.jumpDy;
  496.     }
  497.  
  498.     jumpCounter = Math.max(jumpCounter-1, 0);
  499.  
  500.     this.advance();
  501.  
  502.     // add gravity
  503.     if (player.isFalling || player.isJumping) {
  504.       player.dy += player.gravity;
  505.     }
  506.  
  507.     // change animation if falling
  508.     if (player.dy > 0) {
  509.       player.anim = player.fallAnim;
  510.     }
  511.     // change animation is jumping
  512.     else if (player.dy < 0) {
  513.       player.anim = player.jumpAnim;
  514.     }
  515.     else {
  516.       player.anim = player.walkAnim;
  517.     }
  518.  
  519.     player.anim.update();
  520.   };
  521.  
  522.   /**
  523.    * Draw the player at it's current position
  524.    */
  525.   player.draw = function() {
  526.     player.anim.draw(player.x, player.y);
  527.   };
  528.  
  529.   /**
  530.    * Reset the player's position
  531.    */
  532.   player.reset = function() {
  533.     player.x = 64;
  534.     player.y = 250;
  535.   };
  536.  
  537.   return player;
  538. })(Object.create(Vector.prototype));
  539.  
  540. /**
  541.  * Sprites are anything drawn to the screen (ground, enemies, etc.)
  542.  * @param {integer} x - Starting x position of the player
  543.  * @param {integer} y - Starting y position of the player
  544.  * @param {string} type - Type of sprite
  545.  */
  546. function Sprite(x, y, type) {
  547.   this.x      = x;
  548.   this.y      = y;
  549.   this.width  = platformWidth;
  550.   this.height = platformWidth;
  551.   this.type   = type;
  552.   Vector.call(this, x, y, 0, 0);
  553.  
  554.   /**
  555.    * Update the Sprite's position by the player's speed
  556.    */
  557.   this.update = function() {
  558.     this.dx = -player.speed;
  559.     this.advance();
  560.   };
  561.  
  562.   /**
  563.    * Draw the sprite at it's current position
  564.    */
  565.   this.draw = function() {
  566.     ctx.save();
  567.     ctx.translate(0.5,0.5);
  568.     ctx.drawImage(assetLoader.imgs[this.type], this.x, this.y);
  569.     ctx.restore();
  570.   };
  571. }
  572. Sprite.prototype = Object.create(Vector.prototype);
  573.  
  574. /**
  575.  * Get the type of a platform based on platform height
  576.  * @return Type of platform
  577.  */
  578. function getType() {
  579.   var type;
  580.   switch (platformHeight) {
  581.     case 0:
  582.     case 1:
  583.       type = Math.random() > 0.5 ? 'grass1' : 'grass2';
  584.       break;
  585.     case 2:
  586.       type = 'grass';
  587.       break;
  588.     case 3:
  589.       type = 'bridge';
  590.       break;
  591.     case 4:
  592.       type = 'box';
  593.       break;
  594.   }
  595.   if (platformLength === 1 && platformHeight < 3 && rand(0, 3) === 0) {
  596.     type = 'cliff';
  597.   }
  598.  
  599.   return type;
  600. }
  601.  
  602. /**
  603.  * Update all ground position and draw. Also check for collision against the player.
  604.  */
  605. function updateGround() {
  606.   // animate ground
  607.   player.isFalling = true;
  608.   for (var i = 0; i < ground.length; i++) {
  609.     ground[i].update();
  610.     ground[i].draw();
  611.  
  612.     // stop the player from falling when landing on a platform
  613.     var angle;
  614.     if (player.minDist(ground[i]) <= player.height/2 + platformWidth/2 &&
  615.         (angle = Math.atan2(player.y - ground[i].y, player.x - ground[i].x) * 180/Math.PI) > -130 &&
  616.         angle < -50) {
  617.       player.isJumping = false;
  618.       player.isFalling = false;
  619.       player.y = ground[i].y - player.height + 5;
  620.       player.dy = 0;
  621.     }
  622.   }
  623.  
  624.   // remove ground that have gone off screen
  625.   if (ground[0] && ground[0].x < -platformWidth) {
  626.     ground.splice(0, 1);
  627.   }
  628. }
  629.  
  630. /**
  631.  * Update all water position and draw.
  632.  */
  633. function updateWater() {
  634.   // animate water
  635.   for (var i = 0; i < water.length; i++) {
  636.     water[i].update();
  637.     water[i].draw();
  638.   }
  639.  
  640.   // remove water that has gone off screen
  641.   if (water[0] && water[0].x < -platformWidth) {
  642.     var w = water.splice(0, 1)[0];
  643.     w.x = water[water.length-1].x + platformWidth;
  644.     water.push(w);
  645.   }
  646. }
  647.  
  648. /**
  649.  * Update all environment position and draw.
  650.  */
  651. function updateEnvironment() {
  652.   // animate environment
  653.   for (var i = 0; i < environment.length; i++) {
  654.     environment[i].update();
  655.     environment[i].draw();
  656.   }
  657.  
  658.   // remove environment that have gone off screen
  659.   if (environment[0] && environment[0].x < -platformWidth) {
  660.     environment.splice(0, 1);
  661.   }
  662. }
  663.  
  664. /**
  665.  * Update all enemies position and draw. Also check for collision against the player.
  666.  */
  667. function updateEnemies() {
  668.   // animate enemies
  669.   for (var i = 0; i < enemies.length; i++) {
  670.     enemies[i].update();
  671.     enemies[i].draw();
  672.  
  673.     // player ran into enemy
  674.     if (player.minDist(enemies[i]) <= player.width - platformWidth/2) {
  675.       gameOver();
  676.     }
  677.   }
  678.  
  679.   // remove enemies that have gone off screen
  680.   if (enemies[0] && enemies[0].x < -platformWidth) {
  681.     enemies.splice(0, 1);
  682.   }
  683. }
  684.  
  685. /**
  686.  * Update the players position and draw
  687.  */
  688. function updatePlayer() {
  689.   player.update();
  690.   player.draw();
  691.  
  692.   // game over
  693.   if (player.y + player.height >= canvas.height) {
  694.     gameOver();
  695.   }
  696. }
  697.  
  698. /**
  699.  * Spawn new sprites off screen
  700.  */
  701. function spawnSprites() {
  702.   // increase score
  703.   score++;
  704.  
  705.   // first create a gap
  706.   if (gapLength > 0) {
  707.     gapLength--;
  708.   }
  709.   // then create ground
  710.   else if (platformLength > 0) {
  711.     var type = getType();
  712.  
  713.     ground.push(new Sprite(
  714.       canvas.width + platformWidth % player.speed,
  715.       platformBase - platformHeight * platformSpacer,
  716.       type
  717.     ));
  718.     platformLength--;
  719.  
  720.     // add random environment sprites
  721.     spawnEnvironmentSprites();
  722.  
  723.     // add random enemies
  724.     spawnEnemySprites();
  725.   }
  726.   // start over
  727.   else {
  728.     // increase gap length every speed increase of 4
  729.     gapLength = rand(player.speed - 2, player.speed);
  730.     // only allow a ground to increase by 1
  731.     platformHeight = bound(rand(0, platformHeight + rand(0, 2)), 0, 4);
  732.     platformLength = rand(Math.floor(player.speed/2), player.speed * 4);
  733.   }
  734. }
  735.  
  736. /**
  737.  * Spawn new environment sprites off screen
  738.  */
  739. function spawnEnvironmentSprites() {
  740.   if (score > 40 && rand(0, 20) === 0 && platformHeight < 3) {
  741.     if (Math.random() > 0.5) {
  742.       environment.push(new Sprite(
  743.         canvas.width + platformWidth % player.speed,
  744.         platformBase - platformHeight * platformSpacer - platformWidth,
  745.         'plant'
  746.       ));
  747.     }
  748.     else if (platformLength > 2) {
  749.       environment.push(new Sprite(
  750.         canvas.width + platformWidth % player.speed,
  751.         platformBase - platformHeight * platformSpacer - platformWidth,
  752.         'bush1'
  753.       ));
  754.       environment.push(new Sprite(
  755.         canvas.width + platformWidth % player.speed + platformWidth,
  756.         platformBase - platformHeight * platformSpacer - platformWidth,
  757.         'bush2'
  758.       ));
  759.     }
  760.   }
  761. }
  762.  
  763. /**
  764.  * Spawn new enemy sprites off screen
  765.  */
  766. function spawnEnemySprites() {
  767.   if (score > 100 && Math.random() > 0.96 && enemies.length < 3 && platformLength > 5 &&
  768.       (enemies.length ? canvas.width - enemies[enemies.length-1].x >= platformWidth * 3 ||
  769.        canvas.width - enemies[enemies.length-1].x < platformWidth : true)) {
  770.     enemies.push(new Sprite(
  771.       canvas.width + platformWidth % player.speed,
  772.       platformBase - platformHeight * platformSpacer - platformWidth,
  773.       Math.random() > 0.5 ? 'spikes' : 'slime'
  774.     ));
  775.   }
  776. }
  777.  
  778. /**
  779.  * Game loop
  780.  */
  781. function animate() {
  782.   if (!stop) {
  783.     requestAnimFrame( animate );
  784.     ctx.clearRect(0, 0, canvas.width, canvas.height);
  785.  
  786.     background.draw();
  787.  
  788.     // update entities
  789.     updateWater();
  790.     updateEnvironment();
  791.     updatePlayer();
  792.     updateGround();
  793.     updateEnemies();
  794.  
  795.     // draw the
  796.     ctx.font = '15pt Calibri';
  797.     ctx.fillStyle = 'red';
  798.     ctx.fillText('Score: ' + score + 'm', canvas.width - 450, 50);
  799.  
  800.     // spawn a new Sprite
  801.     if (ticker % Math.floor(platformWidth / player.speed) === 0) {
  802.       spawnSprites();
  803.     }
  804.  
  805.     // increase player speed only when player is jumping
  806.     if (ticker > (Math.floor(platformWidth / player.speed) * player.speed * 20) && player.dy !== 0) {
  807.       player.speed = bound(++player.speed, 0, 15);
  808.       player.walkAnim.frameSpeed = Math.floor(platformWidth / player.speed) - 1;
  809.  
  810.       // reset ticker
  811.       ticker = 0;
  812.  
  813.       // spawn a platform to fill in gap created by increasing player speed
  814.       if (gapLength === 0) {
  815.         var type = getType();
  816.         ground.push(new Sprite(
  817.           canvas.width + platformWidth % player.speed,
  818.           platformBase - platformHeight * platformSpacer,
  819.           type
  820.         ));
  821.         platformLength--;
  822.       }
  823.     }
  824.  
  825.     ticker++;
  826.   }
  827. }
  828.  
  829. /**
  830.  * Keep track of the spacebar events
  831.  */
  832. var KEY_CODES = {
  833.   32: 'space'
  834. };
  835. var KEY_STATUS = {};
  836. for (var code in KEY_CODES) {
  837.   if (KEY_CODES.hasOwnProperty(code)) {
  838.      KEY_STATUS[KEY_CODES[code]] = false;
  839.   }
  840. }
  841. document.onkeydown = function(e) {
  842.   var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
  843.   if (KEY_CODES[keyCode]) {
  844.     e.preventDefault();
  845.     KEY_STATUS[KEY_CODES[keyCode]] = true;
  846.   }
  847. };
  848. document.onkeyup = function(e) {
  849.   var keyCode = (e.keyCode) ? e.keyCode : e.charCode;
  850.   if (KEY_CODES[keyCode]) {
  851.     e.preventDefault();
  852.     KEY_STATUS[KEY_CODES[keyCode]] = false;
  853.   }
  854. };
  855. document.addEventListener("touchstart", function(e) {
  856.   document.onkeydown({ keyCode: 32 });
  857. });
  858. document.addEventListener("touchend", function(e) {
  859.   document.onkeyup({ keyCode: 32 });
  860. });
  861.  
  862. /**
  863.  * Request Animation Polyfill
  864.  */
  865. var requestAnimFrame = (function(){
  866.   return  window.requestAnimationFrame       ||
  867.           window.webkitRequestAnimationFrame ||
  868.           window.mozRequestAnimationFrame    ||
  869.           window.oRequestAnimationFrame      ||
  870.           window.msRequestAnimationFrame     ||
  871.           function(callback, element){
  872.             window.setTimeout(callback, 1000 / 60);
  873.           };
  874. })();
  875.  
  876. /**
  877.  * Show the main menu after loading all assets
  878.  */
  879. function mainMenu() {
  880.   for (var sound in assetLoader.sounds) {
  881.     if (assetLoader.sounds.hasOwnProperty(sound)) {
  882.       assetLoader.sounds[sound].muted = !playSound;
  883.     }
  884.   }
  885.  
  886.   $('#progress').hide();
  887.   $('#main').show();
  888.   $('#menu').addClass('main');
  889.   $('.sound').show();
  890. }
  891.  
  892. /**
  893.  * Start the game - reset all variables and entities, spawn ground and water.
  894.  */
  895. function startGame() {
  896.   document.getElementById('game-over').style.display = 'none';
  897.   ground = [];
  898.   water = [];
  899.   environment = [];
  900.   enemies = [];
  901.   player.reset();
  902.   ticker = 0;
  903.   stop = false;
  904.   score = 0;
  905.   platformHeight = 2;
  906.   platformLength = 15;
  907.   gapLength = 0;
  908.   player.speed = 6;
  909.  
  910.   ctx.font = '16px arial, sans-serif';
  911.  
  912.   for (var i = 0; i < 30; i++) {
  913.     ground.push(new Sprite(i * (platformWidth-3), platformBase - platformHeight * platformSpacer, 'grass'));
  914.   }
  915.  
  916.   for (i = 0; i < canvas.width / 32 + 2; i++) {
  917.     water.push(new Sprite(i * platformWidth, platformBase, 'water'));
  918.   }
  919.  
  920.   background.reset();
  921.  
  922.   animate();
  923.  
  924.   assetLoader.sounds.gameOver.pause();
  925.   assetLoader.sounds.bg.currentTime = 0;
  926.   assetLoader.sounds.bg.loop = true;
  927.   assetLoader.sounds.bg.play();
  928. }
  929.  
  930. /**
  931.  * End the game and restart
  932.  */
  933. function gameOver() {
  934.   stop = true;
  935.   $('#score').html(score);
  936.   $('#game-over').show();
  937.   assetLoader.sounds.bg.pause();
  938.   assetLoader.sounds.gameOver.currentTime = 0;
  939.   assetLoader.sounds.gameOver.play();
  940. }
  941.  
  942. /**
  943.  * Click handlers for the different menu screens
  944.  */
  945.  $('.howto').click(function() {
  946.   $('#main').hide();
  947.   $('#howto').show();
  948.   $('#menu').addClass('howto');
  949. });
  950. $('.back').click(function() {
  951.   $('#howto').hide();
  952.   $('#main').show();
  953.   $('#menu').removeClass('howto');
  954. });
  955. $('.credits').click(function() {
  956.   $('#main').hide();
  957.   $('#credits').show();
  958.   $('#menu').addClass('credits');
  959. });
  960. $('.back').click(function() {
  961.   $('#credits').hide();
  962.   $('#main').show();
  963.   $('#menu').removeClass('credits');
  964. });
  965. $('.sound').click(function() {
  966.   var $this = $(this);
  967.   // sound off
  968.   if ($this.hasClass('sound-on')) {
  969.     $this.removeClass('sound-on').addClass('sound-off');
  970.     playSound = false;
  971.   }
  972.   // sound on
  973.   else {
  974.     $this.removeClass('sound-off').addClass('sound-on');
  975.     playSound = true;
  976.   }
  977.  
  978.   if (canUseLocalStorage) {
  979.     localStorage.setItem('kandi.playSound', playSound);
  980.   }
  981.  
  982.   // mute or unmute all sounds
  983.   for (var sound in assetLoader.sounds) {
  984.     if (assetLoader.sounds.hasOwnProperty(sound)) {
  985.       assetLoader.sounds[sound].muted = !playSound;
  986.     }
  987.   }
  988. });
  989. $('.play').click(function() {
  990.   $('#menu').hide();
  991.   startGame();
  992. });
  993. $('.restart').click(function() {
  994.   $('#game-over').hide();
  995.   startGame();
  996. });
  997.  
  998. assetLoader.downloadAll();
  999. })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement