1

I've tried to write a simple coffeescript script. It uses easeljs to spawn a small grey circle when the user clicks the mouse. Here's the code

$(window).load ->
    game.init()


game=
    init: ->
        canvas= document.getElementById("Canvas")
        alert(canvas)
        @stage= new createjs.Stage(canvas)
        alert(@stage)

        @testshape= new createjs.Shape()
        @testshape.graphics.beginFill("#555")
        @testshape.graphics.rect(50,50,500,500)

        @stage.addChild(@testshape)
        @stage.update()

        window.onmousedown= (ev)->
            alert "click"
            mx=ev.screenX
            my=ev.screenY
            @spawn({x:mx,y:my})

    spawn: (data)->
        alert("spawn")
        x=data.x
        y=data.y

        shape = new createjs.Shape()
        shape.graphics.beginFill("#555")
        shape.graphics.circle(x,y,5)
        @stage.addChild(shape)
        @stage.update()

The first two alert calls work fine. And the testshape is created correctly. The callback is also registered fine: A mouse click prompts the alert "click". But the method spawn is never called. I didn't understand why and took a look at the generated javascript:

// Generated by CoffeeScript 1.6.1
(function() {
  var game;

  $(window).load(function() {
    return game.init();
  });

  game = {
    gameObjects: [],
    init: function() {
      var canvas;
      canvas = document.getElementById("Canvas");
      alert(canvas);
      this.stage = new createjs.Stage(canvas);
      alert(this.stage);
      this.testshape = new createjs.Shape();
      this.testshape.graphics.beginFill("#555");
      this.testshape.graphics.rect(50, 50, 500, 500);
      this.stage.addChild(this.testshape);
      this.stage.update();
      return window.onmousedown = function(ev) {
        var mx, my;
        alert("click");
        mx = ev.screenX;
        my = ev.screenY;
        return this.spawn({
          x: mx,
          y: my
        });
      };
    },
    spawn: function(data) {
      var shape, x, y;
      alert("rpcspawn");
      x = data.x;
      y = data.y;
      shape = new createjs.Shape();
      shape.graphics.beginFill("#555");
      shape.graphics.circle(x, y, 5);
      this.stage.addChild(shape);
      return this.stage.update();
    }
  };

}).call(this);

The javascript seems functional. Why is spawn not called ?

UPDATE: I've changed the code to

window.onmousedown=(ev)=>

Now the method is called correctly. But inside the method other members are not available. This alert inside spawn

alert(@stage)

Returns "undefined". I've modified spawn, too. It now uses the thick arrow syntax as well. But that didn't solve the problem. Only one method remained: init . Naturally I tried to change init to thick arrow syntax. But with all three methods using thick arrows, the original problem is back: spawn is not called.

  • If only the callback and optionally spawn use thick arrows, spawn is called correctly.
  • If init uses a thick arrow, spawn can't be called.
  • In no case other members are accessible from inside of spawn.

UPDATE: I changed this to OOP programming. Game is now a class and the solution with thick arrows works

0

2 Answers 2

3

Change your code to:

window.onmousedown= (ev)=>
        alert "click"
        mx=ev.screenX
        my=ev.screenY
        @spawn({x:mx,y:my})

(Note the =).

The problem is that, when called in the context of an event handler, @ (a.k.a. this in JavaScript) is window, not game.

Using => binds the method to game.

Sign up to request clarification or add additional context in comments.

6 Comments

Minor nitpick: this is actually window in the onmousedown handler, rather than the event.
@LinusGThiel: Correct! I'll change that.
This doesn't work as expected. spawn is called correctly but inside of the method spawn, other members are not available. I'll update my question accordingly
Well, it solved your first problem. But now you have a different problem. Inside spawn, inspect this. What is it? It should be game. Is is 1) not actually game, or 2) game, but not fully initialized?
after implementing game as a class the solution works. I will gladly accept your answer. I already upvoted, so the fact that the answer is only accepted but not upvoted again does not mean that I don't appreciate your efforts
|
0

The problem here is that this, where you call this.spawn() inside your window.onmousedown callback, is actually the window object, not your game object.

You should do something like

var that = this;
return window.onmousedown = function(ev) {
    var mx, my;
    alert("click");
    mx = ev.screenX;
    my = ev.screenY;
    return that.spawn({
      x: mx,
      y: my
    });
  };

3 Comments

That's how you'd fix it in JS, but there's a much nicer solution for CoffeeScript.
I see.. sorry, I do not know much of coffeescript, only javascript, but I think I found the problem in the compiled javascript, didn't I?
Yes, that's more or less what I"d use in JS if I didn't have a bind method available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.