1

I have a simple javascript program.

You can move a square in it.

If the square conflicts with an object, a pixel will jump back.

It works. But it will not work if two objects are next to each other. Example for this code. if the square y coordinate is 200 and is close to silver then it does not collide.

How can I solve it?

How can I solve it? If someone could have a simpler solution, then thank you.

<body onload="Start()">
  <script>
    function Start() {
      myAvatar = new component("black", 30, 30, 50, 50);
      components = {
        silverMine: new component("grey", 30, 30, 300, 170),
        forest: new component("green", 30, 30, 300, 200),
      }
      Field.start();
    }

    var Field = {
      field: document.createElement("canvas"),
      start: function() {
        this.field.height = 800;
        this.field.width = 800;
        this.context = this.field.getContext("2d");
        document.body.insertBefore(this.field, document.body.childNodes[0]);
        this.interval = setInterval(fieldUpdate, 10);

        window.addEventListener('keydown', function(e) {
          Field.keys = Field.keys || [];
          Field.keys[e.keyCode] = (e.type == "keydown");
        })

        window.addEventListener('keyup', function(e) {
          Field.keys[e.keyCode] = (e.type == "keydown");
        })
      },

      clear: function() {
        this.context.clearRect(0, 0, this.field.width, this.field.height);
      }
    }

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

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

    function collision(a) {
      for (var prop in components) {
        c = components[prop];
        com = prop;

        if ((a.x == c.x - c.width) && (a.y >= c.y - c.width && a.y <= c.y - c.width + 60)) {
          console.log("balról");
          return true;
        }
        if ((a.x == c.x + c.width) && (a.y >= c.y - c.width && a.y <= c.y - c.width + 60)) {
          console.log("jobbrol");
          return true;
        }
        if ((a.y == c.y - c.width) && (a.x >= c.x - c.width && a.x <= c.x - c.width + 60)) {
          console.log("felülröl");
          return true;
        }
        if ((a.y == c.y + c.width) && (a.x >= c.x - c.width && a.x <= c.x - c.width + 60)) {
          console.log("alulrol");
          return true;
        }

        if ((a.x == c.x - c.width + 1) && (a.y >= c.y - c.width && a.y <= c.y - c.width + 60)) {
          a.x = c.x - c.width;
          console.log("5");
          return true;
        }
        if ((a.x == c.x + c.width - 1) && (a.y >= c.y - c.width && a.y <= c.y - c.width + 60)) {
          a.x = c.x + c.width;
          console.log("6");
          return true;
        }
        if ((a.y == c.y - c.width + 1) && (a.x >= c.x - c.width && a.x <= c.x - c.width + 60)) {
          a.y = c.y - c.width;
          console.log("7");
          return true;
        }
        if ((a.y == c.y + c.width - 1) && (a.x >= c.x - c.width && a.x <= c.x - c.width + 60)) {
          a.y = c.y + c.width;
          console.log("8");
          return true;
        }

      }

      return false;
    }

    function fieldUpdate() {
      Field.clear();
      if (Field.keys && Field.keys[37]) {
        myAvatar.x--;
      }
      if (Field.keys && Field.keys[38]) {
        myAvatar.y--;
      }
      if (Field.keys && Field.keys[39]) {
        myAvatar.x++;
      }
      if (Field.keys && Field.keys[40]) {
        myAvatar.y++;
      }
      collision(myAvatar);
      myAvatar.componentUpdate();
      for (var prop in components) {
        components[prop].componentUpdate();
      }
    }
  </script>
</body>

</html>

2 Answers 2

2

The main problem is that you are able to move in the x and y direction at the same time as you have an off by 1 type of error with some of the detection. Therefore, when you are one pixel below the bottom of the top square it actually detects a collision in the y direction with that square and only stops y from moving but allows the x move.

Here is a change that doesn't allow collisions although it does get "stuck" in places:

function fieldUpdate() {
  Field.clear();
  var oldX = myAvatar.x;
  var oldY = myAvatar.y;
  if (Field.keys && Field.keys[37]) {
    myAvatar.x--;
  }

  if (Field.keys && Field.keys[39]) {
    myAvatar.x++;
  }

  if (collision(myAvatar)) {
    myAvatar.x = oldX;
    myAvatar.y = oldY;
  }

  var oldX = myAvatar.x;
  var oldY = myAvatar.y;

  if (Field.keys && Field.keys[40]) {
    myAvatar.y++;
  }      

  if (Field.keys && Field.keys[38]) {
    myAvatar.y--;
  }

  if (collision(myAvatar)) {
    myAvatar.x = oldX;
    myAvatar.y = oldY;
  }

  myAvatar.componentUpdate();
  for (var prop in components) {
    components[prop].componentUpdate();
  }
}

If you fix your off by 1 errors, it should also not get stuck.

Also another issue is that you have c.y - c.width in a couple of places. These should likely by c.y - c.height. This is going to be a problem if you ever make non-square shapes.

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

2 Comments

Thanks, but it will never be true the collision(myAvatar).
So as long as it is in collision, it's true.
0

The problem is that you return in the collision loop, resulting that only one object gets detected per movement. That would be fine if all movements were stopped / reversed but reversing only one direction allows the other to roam freely through anything else.

A way to fix that would be to remove all returns in that function. Additionally watch that video "Bounding Box Collision Detection" to fix your algorithm because currently it ignores the width and height of your own avatar.

Comments

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.