View on GitHub

JS1 Help

How-To's from Mr. Hinkle's Intro to JavaScript Class

Using Objects to Track Movement

JavaScript objects are a great way to track objects in games.

You create an object in JavaScript like this:

let thing = {
  property : value,
  otherProperty : otherValue,
}

Filling in to represent an item in a game with a position, we might have something like this:

let rocket = {
  x : 100,
  y : 100,
}

Properties can be anything you want. Values can be any valid value in JavaScript (numbers, strings, arrays, other objects, etc).

When we think about movement, we’re really just updating our x and y coordinates on a regular basis. A simple way to do this is to track the movement in each direction with a separate property, like so (the rocket below is moving slowly to the right and quickly up)

let rocket = {
  x :  100,
  y : 100,
  vx : 5,
  vy : -20,
}

JavaScript even lets us add methods to objects, which are functions that update the object. We could do something like this:

let rocket = {
  x : 100,
  y : 100,
  vx : 5,
  vy : -20,
  move : function (timeUnit = 1) {
    /* The special word "this" represents the current object */
    this.x += this.vx * timeUnit;
    this.y += this.vy * timeUnit;
  }  
}

It’s important to realize that this object is abstract and has nothing to do with what’s being drawn on your game. What you’re actually doing is simply updating numbers in an object.

Here’s an example of the code above implemented with pure HTML animation:

See the Pen Squares by Tom Hinkle (IACS) (@thinkle-iacs) on CodePen.

Constructors

You’ll notice above I used the special keyword this to refer to the rocket within the method of rocket (the function attached to the object).

JavaScript also has a special way to create objects with a new constructor which is designed for this purpose. In that case, we call a function with the new keyword and then within the function we attach whatever methods we want to the this object.

By convention, functions which should be called with the new keyword are capitalized to indicate that they are constructors.

function Rocket () {
  this.x = 100;
  this.y = 100;
  this.vx = 5;
  this.vy = -20;
  this.move = function (timeUnit = 1) {    
    this.x += this.vx * timeUnit;
    this.y += this.vy * timeUnit;
  }  
}

let rocket = new Rocket();

Note, in this case, we can then create many moving objects with the same function.

For example, I might do something like this:


function Rocket (element, x=0, y=0, vx=5, vy=-20) {
  this.x = x;
  this.y = y;
  this.vx = vx;
  this.vy = vy;
  this.move = function (timeUnit = 1) {    
    this.x += this.vx * timeUnit;
    this.y += this.vy * timeUnit;
  }
  this.element = element;
  this.draw = function () {
    this.element.style.position = 'absolute';
    this.element.style.left = `${x}px`;
    this.element.style.top = `${y}px`;
  }
}

let newRocketEl = document.createElement('div');
document.body.appendChild(newRocketEl);
let rocket = new Rocket(newRocketEl);

Note: JavaScript also supports the class keyword familiar from other programming languages to do the equivalent of the above. Here’s a translation of the above using the class keyword (which is basically just syntactic sugar for standard JavaScript constructor behavior):

// This is typescript, with JavaScript classes
// AND typescript type annotations

class Rocket {
  x : number;
  y : number;
  vx : number;
  vy : number;
  element : HTMLElement
  constructor (element, x=0, y=0, vx=5, vy=-20) {
    this.x = x;
    this.y = y;
    this.vx = vx;
    this.vy = vy;
    this.element = element;
  }

  move (timeUnit = 1) {    
    this.x += this.vx * timeUnit;
    this.y += this.vy * timeUnit;
  }
  
  this.draw = function () {
    this.element.style.position = 'absolute';
    this.element.style.left = `${x}px`;
    this.element.style.top = `${y}px`;
  }
}

let newRocketEl = document.createElement('div');
document.body.appendChild(newRocketEl);
let rocket = new Rocket(newRocketEl);