Jump to content

Isometric collision


Recommended Posts

I am trying to make an isometric game from scratch and I'm stuck on collision. I want the pyramid character to stay in the same place if the tile is trying to move on is water. Here's what I have

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<canvas id="view" width="256" height="256"></canvas>
<script src="game.js"></script>
(function(isometric) {

    var map = [
    var playerX = 1;
    var playerY = 1;
    var tileGraphics = [];
    function loadImg() {
        var tgToLoad = ['http://jsiso.com/tutorials/images/water.png', 'http://jsiso.com/tutorials/images/land.png', 'http://jsiso.com/tutorials/img/ralph.png'];
        var tgLoaded = 0;
        for(var i = 0; i < tgToLoad.length; i++) {
            tileGraphics[i] = new Image();
            tileGraphics[i].src = tgToLoad[i];
            tileGraphics[i].onload = function() {
                if(tgLoaded === tgToLoad.length) {
    function drawMap(keyPressed) {
        var ctx = document.getElementById('view').getContext('2d');
        var tileH = 25;
        var tileW = 52;
        var mapX = 76;
        var mapY = 52;

        var drawTile;

        ctx.clearRect(0, 0, 500, 500);

        for(var i = 0; i < map.length; i++) {
            for(var j = 0; j < map[i].length; j++) {
                drawTile = map[i][j];
                ctx.drawImage(tileGraphics[drawTile], (i - j) * tileH + mapX, (i + j) * tileH / 2 + mapY);
                if (playerX === i && playerY === j) {
                    // check if next tile is water
                    if(map[i][j] == 0) {
                        // keep player in same position
                        /* this make boy go up!
                        ctx.drawImage(tileGraphics[2], i * tileH + mapX, j * tileH / 2 + mapY - tileH);
                       ctx.drawImage(tileGraphics[2], (i - j) * tileH + mapX, (i + j) * tileH / 2 + mapY - tileH);

                    } else {
                        // draw player in new position
                        ctx.drawImage(tileGraphics[2], (i - j) * tileH + mapX, (i + j) * tileH / 2 + mapY - tileH);

    function init() {
        isometric.removeEventListener('load', init);
        isometric.addEventListener("keyup", function(e) {
            switch(e.keyCode) {
              case 65: // A
              case 68: // D
              case 87: // W
              case 83: // S
    isometric.addEventListener('load', init, false);


Link to comment
Share on other sites

  • 3 weeks later...

Isometric collision is nothing special, I'm not sure you're suggesting it is but this is just (I think) a generic question on handling collisions, more specifically, in a 2D world.

You need a couple of things to things to be able to do collision detection:

* A map representing the state of entities in your world. This includes actors/entities and the map itself.

* A representation of the desired 'next step' for an entity.

You can separate your code more, but, the crux of your current problem looks like it probably lies in a few places:

* In your 'keyup' (i.e. user input handler) function you manually mutate the position of your Player Character

* You pass `keypressed` into your render function, although doesn't look like you use it, which is good, don't use it there. You look like you're trying to put collision handling code in your render method, don't do this either, keep your render method just 'dumbly' rendering the current state of the game

* You have no concept of an update function, you almost certainly want to create this concept.

* You treat your Player Character as a special case, this isn't wrong per se, but it is better to treat it as 'just another' entity/actor in your world.

So, this leaves you with 3 distinct pieces (you currently only have 2)

* Handling user input

* Handling world updates

* Rendering the world

A super simplistic game loop would be:

while (gameRunning) {

In the beginning, this is how they worked.

You don't want to block on waiting for user input, and you aren't by using an asynchronous keypress handler. This is good.

When you handle user input related to moving the PC (Player Character) you need to define a 'desired' location to move, i.e. turn that keypress into an action (a movement action) associated with the PC entity.

In the update function (which you will create) you want to handle all the desired actions on entities in your world, for the sake of simplicity, this is going to handle the movement action for your PC. So, you see the PC has a movement action and where it wants to move to, this triggers your Collision code i.e. you query the map to see if the PC can move, if so, update their position, if not, do _something_ based on the type of collision (i.e. in to a wall, do not update position, in to a monster, add a 'battle' action to the queue of the PC). When you have handled this action you remove it from the PC action queue.

The update function loops over all entities and drains their action queues, it then exits.

Now you render the world. As you have already updated the player position (or not, depending on the outcome of a possible collision) you just render the world as it is and your users will see their beloved PC moving around, bashing in to things, starting fights, casting spells, shooting guns, picking up items, communicating, transmutating, defecating, whatever it is that they can do in your game.

The above isn't the only way of doing things, but it is probably the most common. http://journal.stuffwithstuff.com/2014/07/15/a-turn-based-game-loop/ this is nice additional reading, most of the above is covered there in more depth, and with working code examples too, its a superb article (the author is also great, I highly recommend following his writings).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...