Maze Wall Detection

Ok I did the Coding Challenge #10.1 - 10.4: Maze Generator with p5.js at , but now I want to move an object (pacman) through the maze. I have created the object(pacman) and it can move using the keyPressed function, but I want the object (pacman) to first check if there are walls blocking its movement. Something like if(!cell.walls(top) && keyCode === UP_ARROW) { move up. The issue I think i'm having is I do not understand how I can refer to the specific grid[] that my object is in and then have it check that specific grid for walls. My code so far is as follows:

    var pacman;
    var w = 40;
    var cols, rows;
    //width of each square is 40
    var grid = [];
    var current;
    //the current cell being visited
    var stack = [];



    function setup() {
      createCanvas(400, 400);
      cols = floor(width / w);
      rows = floor(height / w);
      pacman = new Pacman(0, 0);
      for (var j = 0; j < rows; j++) {
        for (var i = 0; i < cols; i++) {
          var cell = new Cell(i, j);
          grid.push(cell);
        }
      }
      current = grid[0];

    }

    function draw() {
      background(0);
      pacman.show();
      pacman.borders();
      for (var i = 0; i < grid.length; i++) {
        grid[i].show();
      }
      current.visited = true;
      var next = current.checkNeighbours();
      if (next) {
        next.visited = true;

        stack.push(current);

        removeWalls(current, next);

        current = next;
      } else if (stack.length > 0) {
        current = stack.pop();
      }
    }

        function keyPressed() {
      if (keyCode === RIGHT_ARROW) {
        pacman.moveh(1);
      }
      if (keyCode === LEFT_ARROW) {
        pacman.moveh(-1);
      }
      if (keyCode === UP_ARROW) {
        pacman.movev(-1);
      }
      if (keyCode === DOWN_ARROW) {
        pacman.movev(1);
      }
    }


    function Pacman(x, y) {
      this.x = x + 20;
      this.y = y + 20;
      this.toDelete = false;
      this.r = w;
      this.top = false;


      this.show = function() {
        noStroke();
        fill(255, 146, 0);
        ellipseMode(CENTER);
        ellipse(this.x, this.y, this.r, this.r);
      }

      this.moveh = function(dir) {
        this.x += dir * w;
      }
      this.movev = function(dir) {
        this.y += dir * w;
      }
      this.borders = function() {
        if (this.x > width - 1) {
          this.x = x + 20;
        }
        if (this.x < 0) {
          this.x = width - 20;
        }

        if (this.y > height - 1) {
          this.y = y + 20;
        }
        if (this.y < 0) {
          this.y = height - 20;
        }
      }
    }

    function index(i, j) {
      if (i < 0 || j < 0 || i > cols - 1 || j > rows - 1) {
        return -1;
      }
      return i + j * cols;
    }

    function Cell(i, j) {
      this.i = i;
      this.j = j;
      //i = column number
      //j = row number
      this.walls = [true, true, true, true];
      //top, right, bottom, left
      //if true you see that side of the wall of each cell, if false you do not see the wall
      this.visited = false;


      this.checkNeighbours = function() {
        var neighbours = [];
  `  //top = walls[0]`
        var top = grid[index(i, j - 1)];
        var right = grid[index(i + 1, j)];
        var bottom = grid[index(i, j + 1)];
        var left = grid[index(i - 1, j)];

        if (top && !top.visited) {
          neighbours.push(top);
        }
        if (right && !right.visited) {
          neighbours.push(right);
        }
        if (bottom && !bottom.visited) {
          neighbours.push(bottom);
        }
        if (left && !left.visited) {
          neighbours.push(left);
        }
        if (neighbours.length > 0) {
          var r = floor(random(0, neighbours.length));
          return neighbours[r];
        } else {
          return undefined;
        }

      }



      this.show = function() {
        var x = this.i * w;
        var y = this.j * w;
        stroke(255);
        if (this.walls[0]) {
          line(x, y, x + w, y);
        }
        if (this.walls[1]) {
          line(x + w, y, x + w, y + w);
        }
        if (this.walls[2]) {
          line(x + w, y + w, x, y + w);
        }
        if (this.walls[3]) {
          line(x, y + w, x, y);
        }

      }
    }

    function removeWalls(a, b) {
      var x = a.i - b.i;
      if (x === 1) {
        a.walls[3] = false;
        b.walls[1] = false;
      } else if (x === -1) {
        a.walls[1] = false;
        b.walls[3] = false;
      }
      var y = a.j - b.j;
      if (y === 1) {
        a.walls[0] = false;
        b.walls[2] = false;
      } else if (y === -1) {
        a.walls[2] = false;
        b.walls[0] = false;
      }
    }

Answers

  • edited January 2017

    The issue I think i'm having is I do not understand how I can refer to the specific grid[] that my object is in

    this is doing it, line 124.

    var top = grid[index(i, j - 1)];
    

    that's using i and j-1, calculating the index into the grid for that square and returning the value of the grid at that point.

  • yes, but I don't know how to reference or to say:

        if (grid[0] !grid[index(i + 1, j)] && keyCode === RIGHT_ARROW) {
            pacman.moveh(1);
        }
    
    // if grid[0] has no right wall and right arrow is pressed.
    
  • The walls object within the grid says whether there's a wall in the given direction.

    See line 156 etc

  • Something like if(!cell.walls(top) && keyCode === UP_ARROW)

    Yes, just like this, where cell is the grid item that you've looked up using the index.

  • Lines 115 and 116 are relevant here, you'll need to know which element of the array is which direction.

  • edited January 2017

    gives me this error

    Uncaught TypeError: object is not a function

    referring to the line:

    if(!cell.walls(top) && keyCode === UP_ARROW)

  • That's because the object is not a function, it's an array. Which is where line 116 comes into it...

  • edited January 2017

    Uncaught TypeError: object is not a function

    • When we access any variable or property suffixing it w/ (), it means we're using it as a function.
    • Obviously, if property walls doesn't refer to a function, JS is gonna throw that exception message.
    • And indeed, your class Cell doesn't have any method called walls().
    • Instead, it's gotta an array property called walls: this.walls = [true, true, true, true];
    • Therefore, we should use operator [] instead of () in order to access an indexed element from walls!
  • Ok cool I get that... I think hah. so I've changed my line to:

    if(!cell.walls[top] && keyCode === UP_ARROW)

    I receive no error, but now I am unable to move up at all.

  • Three =

    Use two

  • Still doesn't move at all.

  • What is 'top'?

  • Line 156...

  • top is the first object of the array walls, walls[0] walls [true, true, true, true] = walls [top, right, bottom, left]

  • Is top defined in your code? What value does it have?

  • My point being that

    cell.walls[top]
    

    Isn't defined if top isn't defined. And if top isn't 0 then it'll return the wrong thing.

    The rest of the code uses

    cell.walls[0]
    

    directly. It's not great from a clarity point of view but you can always add a comment.

  • edited January 2017

    Define some kinda enumerable object at the top of the sketch:

    const Wall = {
      TOP: 0, RIGHT: 1, BOTTOM: 2, LEFT: 3
    }
    

    Now, instead of cell.walls[0], re-write it as cell.walls[Wall.TOP].
    For cell.walls[3], go w/ cell.walls[Wall.LEFT], and so on for the rest of the index constants. *-:)

  • I did what you suggested

    const Wall = {
      TOP: 0, RIGHT: 1, BOTTOM: 2, LEFT: 3
    }
    
      this.show = function() {
        var x = this.i * w;
        var y = this.j * w;
        var x2 = (this.i * w) + w;
        var y2 = (this.j * w) + w;
    
        stroke(255);
        if (this.walls[Wall.TOP]) {
          line(x, y, x2, y);
        }
        if (this.walls[Wall.RIGHT]) {
          line(x + w, y, x2, y2);
        }
        if (this.walls[Wall.BOTTOM]) {
          line(x + w, y + w, x, y2);
        }
        if (this.walls[Wall.LEFT]) {
          line(x, y + w, x, y);
        }
    
      }
    }
    

    But I this line still has no affect:

      if (!cell.walls[Wall.TOP] && keyCode === UP_ARROW) {
      }
    
  • edited January 2017

    Accordingly to your 1st posted sketch, cell is a setup()'s local variable.
    It doesn't exist anywhere else within your sketch! @-)
    Perhaps you've meant grid[] instead? :-??

  • you are correct, if I use

      if (!grid.walls[Wall.TOP] && keyCode === UP_ARROW) {
      }
    

    I get an error "Uncaught TypeError: Cannot read property '0' of undefined"

    If I use

      if (!grid[0].walls[Wall.TOP] && keyCode === UP_ARROW) {
      }
    

    or run a loop and do grid[i], then I cannot move up.

  • then I cannot move up.

    You mean you cannot move up even though it shoulda been allowed? :-/

  • Yes sorry, that is what I meant. Perhaps, not that it shoulda been allowed, but I don't know where the error is that is not allowing it

  • edited January 2017

    Problem is you've carried on coding the original based sketch w/o checking out whether it was still working correctly. It'd help a lil' if you posted the code you're basing yours from. 8->

  • why === instead of ==

    ?

  • grid[] holds the entire grid, cell is a local variable (type Cell) holding the grid element at (x, y)

    jan 19th

    Yes, just like this, where cell is the grid item that you've looked up using the index.

  • two steps:

    i) look up the grid element according to the position

    ii) check the walls for this grid element

Sign In or Register to comment.