0

I'm new to javascript (third day!) but i've been a programmer for a long time. I have the following problem when using the setInterval function of javascript:

<script>
  var canvasObj, canvasContext;
  var tetrisObj;

  main();

  function main() {
    log("call init");
    init();
    tetrisObj.startGame(canvasContext)
    log("finished");
  }

  function init() {
    canvasObj = document.getElementById("Tetris");
    canvasContext = canvasObj.getContext("2d");
    tetrisObj = new tetris(canvasObj.width, canvasObj.height);
  }

  function log(string) {
    var p = document.createElement("p");
    var text = document.createTextNode(string);
    p.appendChild(text);
    document.getElementById("logs").appendChild(p);
  }

  function tetris(width, height) {
    this.width = width;
    this.height = height;

    this.b_width = width * 0.1;
    this.b_height = width * 0.1;

    this.block_container = new Array();

    this.tetris_context;

    this.startGame = function(canvasContext) {
      this.tetris_context = canvasContext;
      this.addBlock();
      this.gameLoop();
      setInterval(this.gameLoop, 500);
    }

    this.gameLoop = function() {
      this.updateBlocks();
      this.drawBlocks();
    }

    this.updateBlocks = function() {
      var i = 0;
      log(this.block_container.length);
      for (i = 0; i < this.block_container.length; i++) {
        if (this.block_container[i].y >= 20 * this.b_height) {
          continue;
        } else {
          this.block_container[i].y += this.b_height;
          log(this.block_container[i].y);
        }
      }
    }

    this.addBlock = function() {
      var new_block = new s_block(0, 0, "black", this.b_width, this.b_height);
      this.block_container.push(new_block);
    }

    this.drawBlocks = function() {
      var i = 0;
      for (i = 0; i < this.block_container.length; i++) {
        this.block_container[i].drawBlock(this.tetris_context);
      }
    }

  }

  function s_block(x, y, color, width, height) {
    this.x = x;
    this.y = y;
    this.color = color;
    this.width = width;
    this.height = height;

    this.drawBlock = function(context) {
      context.save();
      context.fillStyle = color;
      context.fillRect(this.x, this.y, this.width, this.height);
      context.restore();
    }

  }
</script>

The problem I have is that when running the "startGame()" function of the code snippet above, the direct call to this.gameLoop is found, but the indirect call to this.gameLoop via setInterval fails. I think this might be because it gets executed in the global context which messes with the "this" object. However I don't quite see how to fix it elegantly!

Praveen Kumar Purushothaman
  • 154,660
  • 22
  • 177
  • 226
Don
  • 1,358
  • 2
  • 13
  • 29
  • Alternative duplicate: [How to access the correct `this` / context inside a callback?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback) – James Thorpe Dec 22 '15 at 10:11
  • write `setInterval(function(){},500);` like this. – Shubham Dec 22 '15 at 10:12
  • should be `setInterval(function() {that.gameLoop();}, 500)`, with a line `var that = this;` right before it. Since `setInterval` is on the `window` object, `this` refers to the `window` instead of your `tetris` object. – JosephGarrone Dec 22 '15 at 10:12
  • The shortest way here is explained in [that answer](http://stackoverflow.com/a/20279485/2666289) and is to use `this.gameLoop.bind(this)` instead of simply `this.gameLoop`. – Holt Dec 22 '15 at 10:19

0 Answers0