简体   繁体   中英

context.clearRect() doesn't work as expected

So I have a maze here and the problem arises when user changes rowNum/colNum in the maze. When user changes either of them, it calls

ctx.clearRect(0, 0, canvas.width, canvas.height) .

This clears up the whole canvas but when user again starts moving the player, the player from previously cleared up canvas appears up in the this canvas. see here .

clearRect() clears up the canvas but I don't know why the player is still left there to interact with.

codesandbox link

Here's a shortened description of what my code does to draw the player -

main.js

let customGrid = document.querySelector("#rows,#columns");

customGrid.forEach(elem =>  elem.addEventListener("change", e => {

    // detect changed element
    if (e.target.id === "row")
        customGrid[0].value = parseInt(e.target.value);
    else
        customGrid[1].value = parseInt(e.target.value);

    ctx.clearRect(0, 0, canvas.width, canvas.width);

    // setting myMaze to new instance of Maze
    myMaze = new Maze(ctx, 600, customGrid[0].value, customGrid[1].value);
    myMaze.setup();
    myMaze.drawMap();
    })
);

Next, myMaze.drawMap() contains-

//set player
this.player = new Player(this.ctx, this.goal, this.cellWidth, this.cellHeight);
this.player.setPlayer(this);

From here setPlayer calls-

setPlayer(myMaze) {
    ....
    this.drawPlayer();
    this.listenMoves(myMaze);
}
listenMoves(myMaze) {
    window.addEventListener("keydown", function handler(e) {
        myMaze.player.move(e.keyCode, myMaze);

        let reachedCol = myMaze.player.colNum === myMaze.goal.colNum ? true : false;
        let reachedRow = myMaze.player.rowNum === myMaze.goal.rowNum ? true : false;

        if (reachedRow && reachedCol) {
            alert("reached!");
            window.removeEventListener("keydown", handler);
        }
    });
}
move(input, myMaze) {

    let current = myMaze.grid[this.rowNum][this.colNum];
    let walls = current.walls;

    switch(input) {

        case 37:
            if(!walls.leftWall) {
                this.colNum -= 1;  
            } break;

        case 38:
            if(!walls.topWall)  {
                this.rowNum -= 1;  
            } break;
            
        case 39:
            if(!walls.rightWall)  {
                this.colNum += 1;  
            } break;

        case 40:
            if(!walls.bottomWall)   {
                this.rowNum += 1;
            }
    }
        
    this.ctx.clearRect(current.xCord, current.yCord, current.width, current.height);
    current.drawCell();
    this.drawPlayer();
}

I would move the event listener up to main.js . Since Maze has the reference to Player, it should be possible. I am assuming you have a global variable of Maze ( myMaze ).

let myMaze;
let reched = false;

window.addEventListener("keydown", function handler(e) {
  if (!myMaze || reched) {
    return;
  }

  myMaze.player.move(e.keyCode, myMaze);
  myMaze.player.handleMove();

  let reachedCol = myMaze.player.colNum === myMaze.goal.colNum ? true : false;
  let reachedRow = myMaze.player.rowNum === myMaze.goal.rowNum ? true : false;

  if (reachedRow && reachedCol) {
    alert("reached!");
    reched = true;
  }
});

If you want to keep the event handler as Player's method, you could do something like below. And call unListenMoves() when the grid size changes.

class Player {
  constructor(ctx, goal, cellWidth, cellHeight, myMaze) {
    // keep the Maze instance as a Player's prop for the later use
    this.myMaze = myMaze;

    // we need to bind this here, not in listenMoves
    this.handleMove = this.handleMove.bind(this);
  }

  listenMoves() {
    window.addEventListener("keydown", this.handleMove);
  }

  unListenMoves() {
    window.removeEventListener("keydown", this.handleMove);
  }

  handleMove(e) {
    const myMaze = this.myMaze;
    myMaze.player.move(e.keyCode, myMaze);

    let reachedCol = myMaze.player.colNum === myMaze.goal.colNum ? true : false;
    let reachedRow = myMaze.player.rowNum === myMaze.goal.rowNum ? true : false;

    if (reachedRow && reachedCol) {
      alert("reached!");
      window.removeEventListener("keydown", this.handleMove);
    }
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM