stackHD
stackHD

Reputation: 1

javascript tile map collision optimization

I am rather new to programming in general, but I have managed to make a tile map system with collisions. I am looking for tips on optimization, or if the way I am doing this is completely stupid please let me know of a better way.

https://jsfiddle.net/19ed4sm0/

Basically I made a function that loops through the map array, and is called whenever a movement key is down. The system works with 8 directional movement, that is something I would like to keep.

  //Collision with map tiles
  function checkMove(px, py, pw, ph, pd) {
      for(var y=0; y < map.length; y+=1) {
        for(var x=0; x <map[y].length; x+=1) {

          var tileX = x * 32;
          var tileY = y * 32;

          if (map[y][x] === 1) {
            if (px < tileX+32 && px + pw > tileX && py < tileY+32 && py + ph > tileY) {
              if (pd === 'right' && px+pw > tileX) {
                _player.x = tileX - pw - _player.speed;
              }
              if (pd === 'left' && px < tileX+32) {
                _player.x = tileX+32 + _player.speed;
              }
              if (pd === 'up' && py+ph > tileY) {
                _player.y = tileY + ph + _player.speed;
              }
              if (pd === 'down' && py < tileY+32) {
                _player.y = tileY-32 - _player.speed;
              }
            }

          }
        }
      }
  }

  function playerInit() {
    this.width = 32;
    this.height = 32;
    this.x = cWidth/2-16;
    this.y = cHeight-96;
    this.speed = 4;
    this.gravity = 6;
    this.color = '#ffb5e2'

    this.update = function() {

      //movement
      if (keydown.up === true) {
        checkMove(this.x, this.y - this.speed, tileSize, tileSize, 'up');
        this.y -= this.speed;
      }
      if (keydown.left === true) {
        checkMove(this.x-this.speed, this.y, tileSize, tileSize, 'left');
        this.x -= this.speed;
      }
      if (keydown.right === true) {
        checkMove(this.x+this.speed, this.y, tileSize, tileSize, 'right');
        this.x += this.speed;
      }
      if (keydown.down === true) {
        checkMove(this.x, this.y+this.speed, tileSize, tileSize, 'down');
        this.y += this.speed;
      }

      //canvas border collision
      if (this.x < 0) {
          this.x = 0;
      }
      if (this.y < 0) {
          this.y = 0;
      }
      if (this.x > cWidth - this.width) {
          this.x = cWidth - this.width;
      }
      if (this.y > cHeight - this.height) {
          this.y = cHeight - this.height;
      }
    }

    this.render = function() {
      c.fillStyle = this.color;
      c.fillRect(this.x, this.y, this.width, this.height);
    }
  }

Upvotes: 0

Views: 239

Answers (2)

Calvinxiao
Calvinxiao

Reputation: 116

Actually you just need to check the 8 tiles around your current position.

To calculate the next position you can store their offsets in an array:

var deltaX = [-1, -1, -1, 0, 0, 1, 1, 1];
var deltaX = [-1, 0, 1, -1, 1, -1, 0, 1];
for (var i = 0; i < deltaX.length; i++) {
    var nextX = tileX + deltaX[i];
    var nextY = tileY + deltaY[i];
    // check collisions here
}

So instead of checking 20 * 20 = 400 tiles now you just need to check 8 tiles for collisions.

Upvotes: 1

Red Mercury
Red Mercury

Reputation: 4310

By measuring execution time:

//Collision with map tiles
function checkMove(px, py, pw, ph, pd) {
  console.time("checkMove execution")
  ... // Rest of function
  console.timeEnd("checkMove execution")
}

it can be seen that checkMove only takes a fraction of a millisecond to execute.

enter image description here

So on the performance side, you are covered. This is not surprising even thought there are nested loops, since your map is small. Computers can calculate really fast. Probably faster than you think they can. I remember how grossly I underestimated the speed of computers when I started programming.

Upvotes: 0

Related Questions