I am making a 'code your own adventure' type game, and I have a module set up so then I can do things like character.move()
to move a character forward, but the problem is, is that if I have multiple of these set up, ie
character.move()
character.move()
character.turnLeft()
character.move()
It will immediately go through every single one, and appear all the way at the end, though I want it to go line by line, a little bit slower.
If I do
setInterval(() => {character.move()}, 400)
It gets an effect similar to what I want, but if I add anything else it still just goes through it instantly.
I just want to know if there is anything similar to a draw()
function, that goes line by line, instead of just immedeately, or if there are any work arounds.
FWI, the snippet below is the exact code, so no other text entry other than in javascript underneath bob.initiate()
class HTMLGrid {
constructor(w, h) {
this.w = w;
this.h = h;
this.gridArray = this.create();
this.painterPosition = null;
this.obstacleArray = [];
}
create() {
let tempArr = []
for (let i = 0; i < this.w; i ) {
for (let j = 0; j < this.h; j ) {
tempArr.push([i, j]);
}
}
return tempArr;
} //Creates an array that contains coordinates in the form [[x1, y2], [x2, y2],...]
initiate() {
for (let i = 0; i < this.gridArray.length; i ) {
if (!document.getElementById(this.gridArray[i][0])) {
let row = document.createElement('tr');
row.id = 'row' this.gridArray[i][0];
document.getElementById('holder').appendChild(row);
}
let cell = document.createElement('td');
cell.id = 'cell' this.gridArray[i];
document.getElementById('row' this.gridArray[i][0]).appendChild(cell);
}
}
/* Uses the created array from create() to make HTML Elements for each square
creates a row with the id of 'row0' 'row1' ..., and cells with the id of
'cell x1y1, cell x2y2'*/
changeColorAtIndex(x, y, color) {
document.getElementById('cell' [x, y]).style.backgroundColor = color;
if (color == 'black') {
document.getElementById('cell' [x, y]).style.color = 'white';
} else document.getElementById('cell' [x, y]).style.color = 'black';
} //Changes the color at specified index
returnColorIndex(x, y) {
return document.getElementById('cell' [x, y]).style.backgroundColor;
} //return the color of the index
placePainter(x, y, sprite) {
if (!document.getElementById('cell' [x, y])) {
console.log('Painter Cannot Move Out of Bounds');
} else if (this.painterPosition === null) {
document.getElementById('cell' [x, y]).innerHTML = sprite;
this.painterPosition = [x, y];
} else {
document.getElementById('cell' this.painterPosition).innerText = '';
document.getElementById('cell' [x, y]).innerHTML = sprite;
this.painterPosition = [x, y];
}
} //places the painter and removes the other one
returnPainterPosition() {
return this.painterPosition;
} //gives you the painters xy
changeSprite(x, y, sprite) {
document.getElementById('cell' [x, y]).innerHTML = sprite;
} //changes the sprites allowing for rotation
isValidSquare(x, y) {
if (this.obstacleArray.length === 0)
return this.gridArray.flat().includes(x, y)
else {
if (this.gridArray.join('|').indexOf([x, y] '|') == -1) {
return this.gridArray.join('|').indexOf([x, y] '|') !== -1
} else {
return !this.obstacleArray.flat().includes(x, y)
}
}
} //lets you see if a square is valid to move onto
createObstacle(x, y) {
document.getElementById('cell' [x, y]).innerHTML = '⃤';
this.obstacleArray.push([x, y])
} //creates an obstacle that can prevent movement
}
/* create with new HTMLGrid(int width, int height) as the dimensiosn of the grid
use HTMLGrid.initiate() to place the grid on the screen*/
class Painter {
constructor(gridToPlaceOn) {
this.x = 0;
this.y = 0;
this.grid = gridToPlaceOn;
this.direction = null;
this.sprite = '→';
this.spriteArr = {
0: '↑',
1: '→',
2: '↓',
3: '←'
};
}
initiate() {
this.grid.placePainter(this.x, this.y, this.sprite);
this.direction = 1;
this.sprite = '→';
} //places the sprite on 0,0 with the rotation to the right\
directionToMove() {
let tempX = this.x,
tempY = this.y;
if (this.direction == 0) tempX -= 1;
else if (this.direction == 1) tempY = 1;
else if (this.direction == 2) tempX = 1;
else tempY -= 1;
return [tempX, tempY]
} //Uses direction to set x and y values to desired location
move() {
let moveTo = this.directionToMove();
this.grid.placePainter(moveTo[0], moveTo[1], this.sprite);
this.x = moveTo[0];
this.y = moveTo[1];
} //Allows a piece to move forward
canMove() {
let direction = this.directionToMove()
return this.grid.isValidSquare(direction[0], direction[1])
} //Checks if you can move in desired location, returns false if cannot including for obstacles
turnRight() {
this.direction = 1;
if (this.direction == 4) this.direction = 0;
this.sprite = this.spriteArr[this.direction];
this.grid.changeSprite(this.x, this.y, this.sprite);
} //Iterates on direction, loopin if at end of the loop, then changes the sprite
turnLeft() {
this.turnRight();
this.turnRight();
this.turnRight();
}
turnAround() {
this.turnRight();
this.turnRight();
}
paint(color) {
this.grid.changeColorAtIndex(this.x, this.y, color);
}
scrapePaint() {
this.grid.changeColorAtIndex(this.x, this.y, '#808080');
}
isOnPaint() {
return this.grid.returnColorIndex(this.x, this.y) != '#808080';
}
getColor() {
return this.grid.returnColorIndex(this.x, this.y) == '' ? '#808080' : this.grid.returnColorIndex(this.x, this.y);
}
getX() {
return this.x;
}
getY() {
return this.y;
}
isFacingNorth() {
return this.direction == 0;
}
isFacingSouth() {
return this.direction == 2;
}
isFacingEast() {
return this.direction == 1;
}
isFacingWest() {
return this.direction == 3;
}
getDirection() {
if (this.isFacingNorth()) return 'north';
else if (this.isFacingSouth()) return 'south';
else if (this.isFacingEast()) return 'east';
else return 'west';
} // returns direction as a cardinal direction string
} /* create with new Painter(gridToPlaceOn) as the grid that will be changing
use Painter.initiate() to place it on the grid*/
let grid = new HTMLGrid(8, 8);
let bob = new Painter(grid);
grid.initiate();
bob.initiate();
bob.move();
bob.move();
bob.move(); // This is where the problem is, instantly jumping through everything
table {
border-collapse: collapse;
}
td {
height: 40px;
width: 40px;
text-align: center;
border: 1px solid white;
border-radius: 5px;
border-color: white;
background-color: #808080;
}
<table id = 'holder'></table>
CodePudding user response:
Here is how to implement async/await in your code. I only edited the move()
function as an example.
First write a delay function
function delay(millis) {
return new Promise((resolve, reject) => setTimeout(resolve, millis));
}
Then make the move()
function async and put a delay in it
async move() {
await delay(400);
let moveTo = this.directionToMove();
this.grid.placePainter(moveTo[0], moveTo[1], this.sprite);
this.x = moveTo[0];
this.y = moveTo[1];
} //Allows a piece to move forward
Finally, call the move function and await for it, within an async function
(async () => {
await bob.move();
await bob.move();
await bob.move();
})();
function delay(millis) {
return new Promise((resolve, reject) => setTimeout(resolve, millis));
}
class HTMLGrid {
constructor(w, h) {
this.w = w;
this.h = h;
this.gridArray = this.create();
this.painterPosition = null;
this.obstacleArray = [];
}
create() {
let tempArr = []
for (let i = 0; i < this.w; i ) {
for (let j = 0; j < this.h; j ) {
tempArr.push([i, j]);
}
}
return tempArr;
} //Creates an array that contains coordinates in the form [[x1, y2], [x2, y2],...]
initiate() {
for (let i = 0; i < this.gridArray.length; i ) {
if (!document.getElementById(this.gridArray[i][0])) {
let row = document.createElement('tr');
row.id = 'row' this.gridArray[i][0];
document.getElementById('holder').appendChild(row);
}
let cell = document.createElement('td');
cell.id = 'cell' this.gridArray[i];
document.getElementById('row' this.gridArray[i][0]).appendChild(cell);
}
}
/* Uses the created array from create() to make HTML Elements for each square
creates a row with the id of 'row0' 'row1' ..., and cells with the id of
'cell x1y1, cell x2y2'*/
changeColorAtIndex(x, y, color) {
document.getElementById('cell' [x, y]).style.backgroundColor = color;
if (color == 'black') {
document.getElementById('cell' [x, y]).style.color = 'white';
} else document.getElementById('cell' [x, y]).style.color = 'black';
} //Changes the color at specified index
returnColorIndex(x, y) {
return document.getElementById('cell' [x, y]).style.backgroundColor;
} //return the color of the index
placePainter(x, y, sprite) {
if (!document.getElementById('cell' [x, y])) {
console.log('Painter Cannot Move Out of Bounds');
} else if (this.painterPosition === null) {
document.getElementById('cell' [x, y]).innerHTML = sprite;
this.painterPosition = [x, y];
} else {
document.getElementById('cell' this.painterPosition).innerText = '';
document.getElementById('cell' [x, y]).innerHTML = sprite;
this.painterPosition = [x, y];
}
} //places the painter and removes the other one
returnPainterPosition() {
return this.painterPosition;
} //gives you the painters xy
changeSprite(x, y, sprite) {
document.getElementById('cell' [x, y]).innerHTML = sprite;
} //changes the sprites allowing for rotation
isValidSquare(x, y) {
if (this.obstacleArray.length === 0)
return this.gridArray.flat().includes(x, y)
else {
if (this.gridArray.join('|').indexOf([x, y] '|') == -1) {
return this.gridArray.join('|').indexOf([x, y] '|') !== -1
} else {
return !this.obstacleArray.flat().includes(x, y)
}
}
} //lets you see if a square is valid to move onto
createObstacle(x, y) {
document.getElementById('cell' [x, y]).innerHTML = '⃤';
this.obstacleArray.push([x, y])
} //creates an obstacle that can prevent movement
}
/* create with new HTMLGrid(int width, int height) as the dimensiosn of the grid
use HTMLGrid.initiate() to place the grid on the screen*/
class Painter {
constructor(gridToPlaceOn) {
this.x = 0;
this.y = 0;
this.grid = gridToPlaceOn;
this.direction = null;
this.sprite = '→';
this.spriteArr = {
0: '↑',
1: '→',
2: '↓',
3: '←'
};
}
initiate() {
this.grid.placePainter(this.x, this.y, this.sprite);
this.direction = 1;
this.sprite = '→';
} //places the sprite on 0,0 with the rotation to the right\
directionToMove() {
let tempX = this.x,
tempY = this.y;
if (this.direction == 0) tempX -= 1;
else if (this.direction == 1) tempY = 1;
else if (this.direction == 2) tempX = 1;
else tempY -= 1;
return [tempX, tempY]
} //Uses direction to set x and y values to desired location
async move() {
await delay(400);
let moveTo = this.directionToMove();
this.grid.placePainter(moveTo[0], moveTo[1], this.sprite);
this.x = moveTo[0];
this.y = moveTo[1];
} //Allows a piece to move forward
canMove() {
let direction = this.directionToMove()
return this.grid.isValidSquare(direction[0], direction[1])
} //Checks if you can move in desired location, returns false if cannot including for obstacles
turnRight() {
this.direction = 1;
if (this.direction == 4) this.direction = 0;
this.sprite = this.spriteArr[this.direction];
this.grid.changeSprite(this.x, this.y, this.sprite);
} //Iterates on direction, loopin if at end of the loop, then changes the sprite
turnLeft() {
this.turnRight();
this.turnRight();
this.turnRight();
}
turnAround() {
this.turnRight();
this.turnRight();
}
paint(color) {
this.grid.changeColorAtIndex(this.x, this.y, color);
}
scrapePaint() {
this.grid.changeColorAtIndex(this.x, this.y, '#808080');
}
isOnPaint() {
return this.grid.returnColorIndex(this.x, this.y) != '#808080';
}
getColor() {
return this.grid.returnColorIndex(this.x, this.y) == '' ? '#808080' : this.grid.returnColorIndex(this.x, this.y);
}
getX() {
return this.x;
}
getY() {
return this.y;
}
isFacingNorth() {
return this.direction == 0;
}
isFacingSouth() {
return this.direction == 2;
}
isFacingEast() {
return this.direction == 1;
}
isFacingWest() {
return this.direction == 3;
}
getDirection() {
if (this.isFacingNorth()) return 'north';
else if (this.isFacingSouth()) return 'south';
else if (this.isFacingEast()) return 'east';
else return 'west';
} // returns direction as a cardinal direction string
} /* create with new Painter(gridToPlaceOn) as the grid that will be changing
use Painter.initiate() to place it on the grid*/
let grid = new HTMLGrid(8, 8);
let bob = new Painter(grid);
grid.initiate();
bob.initiate();
(async () => {
await bob.move();
await bob.move();
await bob.move();
})();
table {
border-collapse: collapse;
}
td {
height: 40px;
width: 40px;
text-align: center;
border: 1px solid white;
border-radius: 5px;
border-color: white;
background-color: #808080;
}
<table id = 'holder'></table>
Another approach so that no await is needed by user: Use an array to queue up the operation. Use a timer to dequeue one operation in regular interval.
let operations = [];
setInterval(()=>{
if(operations.length > 0)
{
operations.shift()();
}
},400);
move() {
operations.push(()=>{
let moveTo = this.directionToMove();
this.grid.placePainter(moveTo[0], moveTo[1], this.sprite);
this.x = moveTo[0];
this.y = moveTo[1];
});
} //Allows a piece to move forward
let operations = [];
setInterval(()=>{
if(operations.length > 0)
{
operations.shift()();
}
},400);
class HTMLGrid {
constructor(w, h) {
this.w = w;
this.h = h;
this.gridArray = this.create();
this.painterPosition = null;
this.obstacleArray = [];
}
create() {
let tempArr = []
for (let i = 0; i < this.w; i ) {
for (let j = 0; j < this.h; j ) {
tempArr.push([i, j]);
}
}
return tempArr;
} //Creates an array that contains coordinates in the form [[x1, y2], [x2, y2],...]
initiate() {
for (let i = 0; i < this.gridArray.length; i ) {
if (!document.getElementById(this.gridArray[i][0])) {
let row = document.createElement('tr');
row.id = 'row' this.gridArray[i][0];
document.getElementById('holder').appendChild(row);
}
let cell = document.createElement('td');
cell.id = 'cell' this.gridArray[i];
document.getElementById('row' this.gridArray[i][0]).appendChild(cell);
}
}
/* Uses the created array from create() to make HTML Elements for each square
creates a row with the id of 'row0' 'row1' ..., and cells with the id of
'cell x1y1, cell x2y2'*/
changeColorAtIndex(x, y, color) {
document.getElementById('cell' [x, y]).style.backgroundColor = color;
if (color == 'black') {
document.getElementById('cell' [x, y]).style.color = 'white';
} else document.getElementById('cell' [x, y]).style.color = 'black';
} //Changes the color at specified index
returnColorIndex(x, y) {
return document.getElementById('cell' [x, y]).style.backgroundColor;
} //return the color of the index
placePainter(x, y, sprite) {
if (!document.getElementById('cell' [x, y])) {
console.log('Painter Cannot Move Out of Bounds');
} else if (this.painterPosition === null) {
document.getElementById('cell' [x, y]).innerHTML = sprite;
this.painterPosition = [x, y];
} else {
document.getElementById('cell' this.painterPosition).innerText = '';
document.getElementById('cell' [x, y]).innerHTML = sprite;
this.painterPosition = [x, y];
}
} //places the painter and removes the other one
returnPainterPosition() {
return this.painterPosition;
} //gives you the painters xy
changeSprite(x, y, sprite) {
document.getElementById('cell' [x, y]).innerHTML = sprite;
} //changes the sprites allowing for rotation
isValidSquare(x, y) {
if (this.obstacleArray.length === 0)
return this.gridArray.flat().includes(x, y)
else {
if (this.gridArray.join('|').indexOf([x, y] '|') == -1) {
return this.gridArray.join('|').indexOf([x, y] '|') !== -1
} else {
return !this.obstacleArray.flat().includes(x, y)
}
}
} //lets you see if a square is valid to move onto
createObstacle(x, y) {
document.getElementById('cell' [x, y]).innerHTML = '⃤';
this.obstacleArray.push([x, y])
} //creates an obstacle that can prevent movement
}
/* create with new HTMLGrid(int width, int height) as the dimensiosn of the grid
use HTMLGrid.initiate() to place the grid on the screen*/
class Painter {
constructor(gridToPlaceOn) {
this.x = 0;
this.y = 0;
this.grid = gridToPlaceOn;
this.direction = null;
this.sprite = '→';
this.spriteArr = {
0: '↑',
1: '→',
2: '↓',
3: '←'
};
}
initiate() {
this.grid.placePainter(this.x, this.y, this.sprite);
this.direction = 1;
this.sprite = '→';
} //places the sprite on 0,0 with the rotation to the right\
directionToMove() {
let tempX = this.x,
tempY = this.y;
if (this.direction == 0) tempX -= 1;
else if (this.direction == 1) tempY = 1;
else if (this.direction == 2) tempX = 1;
else tempY -= 1;
return [tempX, tempY]
} //Uses direction to set x and y values to desired location
move() {
operations.push(()=>{
let moveTo = this.directionToMove();
this.grid.placePainter(moveTo[0], moveTo[1], this.sprite);
this.x = moveTo[0];
this.y = moveTo[1];
});
} //Allows a piece to move forward
canMove() {
let direction = this.directionToMove()
return this.grid.isValidSquare(direction[0], direction[1])
} //Checks if you can move in desired location, returns false if cannot including for obstacles
turnRight() {
this.direction = 1;
if (this.direction == 4) this.direction = 0;
this.sprite = this.spriteArr[this.direction];
this.grid.changeSprite(this.x, this.y, this.sprite);
} //Iterates on direction, loopin if at end of the loop, then changes the sprite
turnLeft() {
this.turnRight();
this.turnRight();
this.turnRight();
}
turnAround() {
this.turnRight();
this.turnRight();
}
paint(color) {
this.grid.changeColorAtIndex(this.x, this.y, color);
}
scrapePaint() {
this.grid.changeColorAtIndex(this.x, this.y, '#808080');
}
isOnPaint() {
return this.grid.returnColorIndex(this.x, this.y) != '#808080';
}
getColor() {
return this.grid.returnColorIndex(this.x, this.y) == '' ? '#808080' : this.grid.returnColorIndex(this.x, this.y);
}
getX() {
return this.x;
}
getY() {
return this.y;
}
isFacingNorth() {
return this.direction == 0;
}
isFacingSouth() {
return this.direction == 2;
}
isFacingEast() {
return this.direction == 1;
}
isFacingWest() {
return this.direction == 3;
}
getDirection() {
if (this.isFacingNorth()) return 'north';
else if (this.isFacingSouth()) return 'south';
else if (this.isFacingEast()) return 'east';
else return 'west';
} // returns direction as a cardinal direction string
} /* create with new Painter(gridToPlaceOn) as the grid that will be changing
use Painter.initiate() to place it on the grid*/
let grid = new HTMLGrid(8, 8);
let bob = new Painter(grid);
grid.initiate();
bob.initiate();
bob.move();
bob.move();
bob.move();
table {
border-collapse: collapse;
}
td {
height: 40px;
width: 40px;
text-align: center;
border: 1px solid white;
border-radius: 5px;
border-color: white;
background-color: #808080;
}
<table id = 'holder'></table>