1

I have a class below that controls a small HTML5 game. You will see a few lines in to the startGame method a object is saved to a property called keys, this is an instance of the Keys class.

After this, I call another method inside of this class called setEventHandlers. This should in theory then set handlers that will invoke callbacks which will send data to the keys object (stored as a property).

Whenever this.keys.keyDown or this.keys.keyUp are called it states that 'keys' is undefined.

I can't seem to find why this is happening, it looks like something to do with order of execution. Any ideas? Thanks in advance.

function Game() {
    this.startGame();
}

Game.prototype.startGame = function () {
    this.canvasElement = document.createElement("canvas");
    this.canvasContext = this.canvasElement.getContext("2d");
    document.body.appendChild(this.canvasElement);

    this.canvasElement.width = window.innerWidth;
    this.canvasElement.height = window.innerHeight;

    this.keys = new Keys();
    this.mouse = new Mouse();
    this.player = new Player(this.randomPosition().x, this.randomPosition().y);

    this.setEventHandlers();
};

Game.prototype.setEventHandlers = function () {
    var onKeyDown = function (e) {
        this.keys.keyDown(e.keyCode);
    },
        onKeyUp = function (e) {
            this.keys.keyUp(e.keyCode);
        },
        onMouseMove = function (e) {
            // this.mouse.move(e.x, e.y);
        },
        onMouseClick = function (e) {
            // this.mouse.click(e.x, e.y);
        },
        onWindowResize = function () {
            this.canvasElement.width = window.innerWidth;
            this.canvasElement.height = window.innerHeight;
        };

    // Keyboard events
    window.addEventListener("keydown", onKeyDown, false);
    window.addEventListener("keyup", onKeyUp, false);

    // Mouse events
    window.addEventListener("mousemove", onMouseMove, false);
    window.addEventListener("click", onMouseClick, false);

    // Window events
    window.addEventListener("resize", onWindowResize, false);
};

Game.prototype.randomPosition = function () {
    var randomX = Math.round(Math.random() * this.canvasElement.width),
        randomY = Math.round(Math.random() * this.canvasElement.height);

    return { x: randomX, y: randomY };
};
jskidd3
  • 4,609
  • 15
  • 63
  • 127
  • Log `this` within one of your handlers and see what it is. – James Montagne Feb 19 '14 at 22:45
  • 1
    @jskidd3: Did I say you were? Only because you didn't find it through your search doesn't mean it isn't a duplicate. – Felix Kling Feb 19 '14 at 22:47
  • 3
    Having a question closed as a duplicate is not to be taken offensively. It is to help keep Stack Overflow organized. That's all. The link should help you with your question. – Paul Feb 19 '14 at 22:49
  • Sorry I didn't mean it to sound offensive in anyway, but I don't see how it's fair for a question to be classed as a duplicate when the titles are no where near the same. For example if one were to make a search they wouldn't search for the solution if they don't know what it is, they'd use a relative title to their problem like mine (if you know what I mean). There is no way I could have searched to find the answer to my problem if I don't know that the problem is to do with the `this` context – jskidd3 Feb 19 '14 at 22:50
  • @jskidd3 The question gets closed as a duplicate. If someone has a similar problem to yours and searches and finds your question, they will then be directed to the above duplicate with an answer that answers the question. There's no need for that same answer to exist on multiple questions. Saying it's "not fair" to close the question implies it is somehow a negative when in fact it is simply a way to direct all versions of the same question to one answer, or rather set of answers. – James Montagne Feb 19 '14 at 22:54
  • @JamesMontagne Oh oops my bad! I thought it would be removed all together. That's a pretty good system then :-) – jskidd3 Feb 19 '14 at 22:56
  • @jskidd3 Oh okay, yes it will still exist. Only the worst questions get truly deleted. – James Montagne Feb 19 '14 at 22:57

1 Answers1

3
var onKeyDown = function (e) {
    this.keys.keyDown(e.keyCode);
},

The above code creates a new function and thus "this" refers to itself rather than the game object try

var self = this;
var onKeyDown = function (e) {
    self.keys.keyDown(e.keyCode);
},
Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
clancer
  • 613
  • 4
  • 10
  • The solution is correct, but the explanation is not (completely). `this` doesn't refer to the function. – Felix Kling Feb 19 '14 at 22:46
  • 1
    He binds the function to the window: `window.addEventListener("keydown", onKeyDown, false);`. So `this` will be the `window` object. I'm not sure what you mean by it refering to `itself`. – Paul Feb 19 '14 at 22:47