Fork me on GitHub

A Joyful HTML5 2D Game Engine

Platformer prototype

Source code

var engine = new Joy.Engine(document.getElementById('example'));
engine.createScene(function(scene) {
  var background = new Joy.Rect({
    position: scene.viewport.position,
    width: engine.width,
    height: engine.height
  });
  background.colorize("#BFE5E5");
  scene.addChild(background);

  // Player Behaviour
  Joy.Behaviour.define('player', {

    // When this behaviour is attached to a DisplayObject...
    INIT: function() {
      this.maxVelocity = new Joy.Vector2d(2, 2);
      this.friction.x = 0.1;
      this.maxVelocity.y = 10;
      this.grounded = false;
    },

    // UPDATE is called every frame
    UPDATE: function() {
      // Play idle animation
      if (this.grounded && Math.abs(this.velocity.x) < 1) {
        this.play("idle");
      }

      if (!this.grounded) {
        this.acceleration.y = 0.5;
      }
    },

    // On key up
    KEY_UP: function(evt) {
      this.acceleration.x = 0;
    },

    // On key down
    KEY_DOWN: function(evt) {
      if (evt.keyCode == Joy.Keyboard.SPACE && this.direction.y === 0) {
        this.play("jumping");
        this.grounded = false;
        this.acceleration.y = -10;
        this.position.y -= 1;
      }
    },

    // On collision stay
    COLLISION: function (other) {
      if (other instanceof Joy.Tilemap &&
          this.willCollideAt(new Joy.Vector2d(this.collider.width / 2, this.collider.height)) &&
            this.direction.y > 0) {
        this.grounded = true;
      this.acceleration.y = 0;
      this.velocity.y = 0;
      }
    },

    // On collision exit
    COLLISION_EXIT: function (other) {
      if (other instanceof Joy.Tilemap) {
        this.grounded = false;
      }
    },

    // Custom method: moveLeft
    moveLeft: function () {
      if (!this.willCollideAt(new Joy.Vector2d(0, this.collider.height / 2))) {
        this.acceleration.x = -2;
        this.flipX = false;
        if (this.grounded) {
          this.play("walking");
        }
      } else {
        this.acceleration.x = 0;
        this.velocity.x = 0;
      }
    },

    // Custom method: moveRight
    moveRight: function () {
      if (!this.willCollideAt(new Joy.Vector2d(this.collider.width, this.collider.height / 2))) {
        this.acceleration.x = 2;
        this.flipX = true;
        if (this.grounded) {
          this.play("walking");
        }
      } else {
        this.acceleration.x = 0;
        this.velocity.x = 0;
      }
    },

    // On key press, called every frame
    KEY_PRESS: function(evt) {
      if (evt.keyCode == Joy.Keyboard.LEFT) {
        this.moveLeft();

      } else if (evt.keyCode == Joy.Keyboard.RIGHT) {
        this.moveRight();
      }
    }
  });


  // Player sprite sheet
  var player = new Joy.SpriteSheet({
    x: engine.width / 2 + 520,
    y: engine.height / 2 - 200,
    src: "/assets/examples/rufus/spritesheets/rufus.png",

    // Setup sprite sheet size
    width: 120,
    height: 120,

    // Setup sprite sheet animation frames
    animations: {
      "walking": [0, 30],
      "idle": [31, 39],
      "jumping": [40, 59],
      "falling": [60, 67],
    }
  }).behave('movimentation, player');

  // Background parallax
  var backgroundParallax = new Joy.Parallax({
    id: "Parallax",
    distance: 1.5,
    velocity: 3,
    children: [
      new Joy.Sprite("/assets/examples/rufus/background/parallax-3.png"),
      new Joy.Sprite("/assets/examples/rufus/background/parallax-2.png")
    ]
  });

  // Collision mask
  player.collider = new Joy.RectCollider(new Joy.Vector2d(30, 40), 60, 45);

  // This map data was generated by Tiled - http://www.mapeditor.org/
  var map = [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, 0, 0, 0, 13, 17, 14, 17, 14, 14, 17, 14, 14, 14, 17, 17, 17, 17, 14, 14, 14, 14, 14, 14, 14, 17, 17, 18, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 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, 2, 31, 5, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 14, 17, 18, 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, 20, 8, 9, 11, 11, 10, 19, 6, 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, 4, 5, 4, 4, 4, 20, 10, 10, 10, 8, 11, 9, 9, 19, 6, 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, 2, 5, 2, 5, 4, 5, 5, 2, 2, 20, 8, 10, 11, 8, 10, 10, 11, 10, 8, 8, 9, 8, 8, 8, 19, 2, 2, 3, 3, 3, 2, 2, 3, 3, 5, 4, 4, 3, 3, 3, 3, 2, 5, 4, 4, 4, 3, 5, 2, 2, 5, 5, 2, 0, 0, 0, 0, 0, 1, 20, 9, 10, 10, 9, 10, 8, 9, 10, 11, 8, 8, 9, 11, 10, 8, 8, 8, 8, 10, 11, 11, 8, 9, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 8, 11, 8, 11, 11, 11, 10, 10, 10, 8, 8, 8, 10, 8, 8, 11, 11, 8, 11, 10, 3, 5, 3, 5, 2, 20, 8, 9, 11, 8, 8, 8, 11, 10, 11, 10, 10, 8, 11, 10, 9, 11, 10, 8, 10, 11, 8, 8, 8, 8, 8, 11, 9, 8, 11, 11, 8, 10, 8, 8, 9, 11, 8, 8, 8, 10, 10, 11, 10, 11, 8, 8, 11, 11, 11, 11, 11, 11, 11, 10];

  var tilemap = new Joy.Tilemap({
    tileset: new Joy.Tileset({
      src: "/assets/examples/rufus/tilesets/bright.png",
      width: 64,
      height: 64
    }),
    columns: 60,
    lines: 10,
    data: map
  });

  // Allow collisions from TilemapCollider
  player.allowCollisionFrom(tilemap);

  // Add DisplayObjects into the Scene.
  scene.addChild(backgroundParallax);
  scene.addChild(tilemap);
  scene.addChild(player);

  // Setup viewport
  scene.viewport.setup({
    follow: player,
    width: engine.width / 1.5,
    height: engine.height / 1.5
  });
});