block by joyrexus 11219270

Lunar-lander

Full Screen

Use the left and right arrow keys to rotate the ship. Press the up arrow key to turn on the engine.

Try to land the ship safely on the ground. You must land gently or the ship will explode!

Notes

This is an example of Asteroids-style motion. The ship moves in straight lines until the engine is turned on and accelerates. When the ship reaches any of the stage boundaries it is repositioned to the opposite side. The ship rotates at ROTATION_SPEED degrees/second.

This example introduces a function getExplosion() which either creates a new explosion object or re-uses one that was created earlier. This approach allows the number of explosion sprites to increase dynamically but never creates more than are needed to display on screen at any one time.

All code here is taken straight from the Game Mechanic Explorer, a collection of concrete examples for various game mechanics, algorithms, and effects. The examples are all implemented in JavaScript using the Phaser game framework, but the concepts and methods are general and can be adapted to any engine.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<script src="//cdnjs.cloudflare.com/ajax/libs/phaser/2.0.3/phaser.min.js"></script>
<body>
  <div id="game" style="overflow: hidden;"></div>
<script>
  /* 
   A GAME MECHANIC EXPLORER DEMO
   //gamemechanicexplorer.com/#thrust-4
   */

  var GameState = function(game) {
  };

  // Load images and sounds
  GameState.prototype.preload = function() {
      this.game.load.spritesheet('ship', 'ship.png', 32, 32);
      this.game.load.image('ground', 'ground.png');
      this.game.load.spritesheet('explosion', 'explosion.png', 128, 128);
  };

  // Setup the example
  GameState.prototype.create = function() {
      // Set stage background color
      this.game.stage.backgroundColor = 0x333333;

      // Define motion constants
      this.ROTATION_SPEED = 180; // degrees/second
      this.ACCELERATION = 200; // pixels/second/second
      this.MAX_SPEED = 250; // pixels/second
      this.DRAG = 0; // pixels/second
      this.GRAVITY = 50; // pixels/second/second

      // Add the ship to the stage
      this.ship = this.game.add.sprite(0, 0, 'ship');
      this.ship.anchor.setTo(0.5, 0.5);
      this.ship.angle = -90; // Point the ship up

      // Enable physics on the ship
      this.game.physics.enable(this.ship, Phaser.Physics.ARCADE);

      // Set maximum velocity
      this.ship.body.maxVelocity.setTo(this.MAX_SPEED, this.MAX_SPEED); // x, y

      // Add drag to the ship that slows it down when it is not accelerating
      this.ship.body.drag.setTo(this.DRAG, this.DRAG); // x, y

      // Choose a random starting angle and velocity for the ship
      this.resetShip();

      // Turn on gravity
      game.physics.arcade.gravity.y = this.GRAVITY;

      // Make ship bounce a little
      this.ship.body.bounce.setTo(0.25, 0.25);

      // Create some ground for the ship to land on
      this.ground = this.game.add.group();
      for(var x = 0; x < this.game.width; x += 32) {
          // Add the ground blocks, enable physics on each, make them immovable
          var groundBlock = this.game.add.sprite(x, this.game.height - 32, 'ground');
          this.game.physics.enable(groundBlock, Phaser.Physics.ARCADE);
          groundBlock.body.immovable = true;
          groundBlock.body.allowGravity = false;
          this.ground.add(groundBlock);
      }

      // Create a group for explosions
      this.explosionGroup = this.game.add.group();

      // Capture certain keys to prevent their default actions in the browser.
      // This is only necessary because this is an HTML5 game. Games on other
      // platforms may not need code like this.
      this.game.input.keyboard.addKeyCapture([
          Phaser.Keyboard.LEFT,
          Phaser.Keyboard.RIGHT,
          Phaser.Keyboard.UP,
          Phaser.Keyboard.DOWN
      ]);

      // Show FPS
      this.game.time.advancedTiming = true;
      this.fpsText = this.game.add.text(
          20, 20, '', { font: '16px Arial', fill: '#ffffff' }
      );
  };

  // Try to get a used explosion from the explosionGroup.
  // If an explosion isn't available, create a new one and add it to the group.
  // Setup new explosions so that they animate and kill themselves when the
  // animation is complete.
  GameState.prototype.getExplosion = function(x, y) {
      // Get the first dead explosion from the explosionGroup
      var explosion = this.explosionGroup.getFirstDead();

      // If there aren't any available, create a new one
      if (explosion === null) {
          explosion = this.game.add.sprite(0, 0, 'explosion');
          explosion.anchor.setTo(0.5, 0.5);

          // Add an animation for the explosion that kills the sprite when the
          // animation is complete
          var animation = explosion.animations.add('boom', [0,1,2,3], 60, false);
          animation.killOnComplete = true;

          // Add the explosion sprite to the group
          this.explosionGroup.add(explosion);
      }

      // Revive the explosion (set it's alive property to true)
      // You can also define a onRevived event handler in your explosion objects
      // to do stuff when they are revived.
      explosion.revive();

      // Move the explosion to the given coordinates
      explosion.x = x;
      explosion.y = y;

      // Set rotation of the explosion at random for a little variety
      explosion.angle = this.game.rnd.integerInRange(0, 360);

      // Play the animation
      explosion.animations.play('boom');

      // Return the explosion itself in case we want to do anything else with it
      return explosion;
  };

  GameState.prototype.resetShip = function() {
      // Move the ship back to the top of the stage
      this.ship.x = 32;
      this.ship.y = 32;
      this.ship.body.acceleration.setTo(0, 0);

      // Select a random starting angle and velocity
      this.ship.angle = this.game.rnd.integerInRange(-180, 180);
      this.ship.body.velocity.setTo(this.game.rnd.integerInRange(100, 200), 0);
  };

  // The update() method is called every frame
  GameState.prototype.update = function() {
      if (this.game.time.fps !== 0) {
          this.fpsText.setText(this.game.time.fps + ' FPS');
      }

      // Collide the ship with the ground
      this.game.physics.arcade.collide(this.ship, this.ground);

      // Keep the ship on the screen
      if (this.ship.x > this.game.width) this.ship.x = 0;
      if (this.ship.x < 0) this.ship.x = this.game.width;

      if (this.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
          // If the LEFT key is down, rotate left
          this.ship.body.angularVelocity = -this.ROTATION_SPEED;
      } else if (this.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
          // If the RIGHT key is down, rotate right
          this.ship.body.angularVelocity = this.ROTATION_SPEED;
      } else {
          // Stop rotating
          this.ship.body.angularVelocity = 0;
      }

      // Set a variable that is true when the ship is touching the ground
      var onTheGround = this.ship.body.touching.down;

      if (onTheGround) {
          if (Math.abs(this.ship.body.velocity.y) > 20 || Math.abs(this.ship.body.velocity.x) > 30) {
              // The ship hit the ground too hard.
              // Blow it up and start the game over.
              this.getExplosion(this.ship.x, this.ship.y);
              this.resetShip();
          } else {
              // We've landed!
              // Stop rotating and moving and aim the ship up.
              this.ship.body.angularVelocity = 0;
              this.ship.body.velocity.setTo(0, 0);
              this.ship.angle = -90;
          }

      }

      if (this.input.keyboard.isDown(Phaser.Keyboard.UP)) {
          // If the UP key is down, thrust
          // Calculate acceleration vector based on this.angle and this.ACCELERATION
          this.ship.body.acceleration.x = Math.cos(this.ship.rotation) * this.ACCELERATION;
          this.ship.body.acceleration.y = Math.sin(this.ship.rotation) * this.ACCELERATION;

          // Show the frame from the spritesheet with the engine on
          this.ship.frame = 1;
      } else {
          // Otherwise, stop thrusting
          this.ship.body.acceleration.setTo(0, 0);

          // Show the frame from the spritesheet with the engine off
          this.ship.frame = 0;
      }
  };

  var game = new Phaser.Game(960, 500, Phaser.AUTO, 'game');
  game.state.add('game', GameState, true);

  window.focus();
</script>