嵌套在此if语句中时,为什么requestAnimationFrame()不起作用?

时间:2019-08-07 00:34:54

标签: javascript html css

我正在制作一个俄罗斯方块游戏,现在我正在编写一个函数,该函数每1s(在这种情况下,每800ms)丢掉一块。我的功能看起来像这样

function drop() {
    //grab the current time
    let now = Date.now();
    //create a var to hold the difference of the current time
    let delta = now - dropStart; //------Why can't these be switched
    if(delta > 800) {
        dropStart = Date.now();
        drawPiece(p.activeTetromino, vacant);
        p.y++;
        drawPiece(p.activeTetromino, p.color);
    }
    requestAnimationFrame(drop);
}

drop();

这可以很好地完成工作。但是我还是一个新手,由于我是从教程中复制此代码的,所以我希望从函数的顶部到底部读取逻辑,然后重新排列某些行。例如,我移动了requestAnimationFrame(drop);并将其放在if语句中。看起来像这样

 function drop() {
    //grab the current time
    let now = Date.now();
    //create a var to hold the difference of the current time
    let delta = now - dropStart; //------Why can't these be switched
    if(delta > 800) {
        dropStart = Date.now();
        drawPiece(p.activeTetromino, vacant);
        p.y++;
        drawPiece(p.activeTetromino, p.color);
        requestAnimationFrame(drop);
    }
}

drop();

这将使功能失效,并且不会看到tetromino每隔800ms掉落一次。我看着dubugger,看着函数执行。我看到它碰到了第一个drawpiece()函数,该函数应该删除当前块(在其上涂上黑色)。然后增加其位置,然后在其新位置绘制新零件。但问题是它不会移除零件或在其新位置上绘制新零件。但是,当requestAnimationFrame(drop);时所有这些都是固定的。被感动了吗?为什么?

// //create your globals
// const canvas = document.querySelector('#canvas');
// const ctx = canvas.getContext('2d');
// const row = 20;
// const col = 10;
// const sq = 40;
// const vacant = 'black';

// //-----------------------Why can't I initialize the tetrominos??

// //create and draw board
// let board = [];
// for(let r = 0; r < row; r++) {
// 	board[r] = [];
// 	for(let c = 0; c < col; c++) {
// 		board[r][c] = vacant;
// 		draw(c, r, board[r][c]);
// 	}
// }

// //define a function to draw to the canvas
// function draw(x, y, color) {
// 	ctx.fillStyle = color;
// 	ctx.fillRect(x * sq, y * sq, sq, sq);
// 	ctx.strokeStyle = 'white';
// 	ctx.strokeRect(x * sq, y * sq, sq, sq);
// }

// //create an object for the tetrominos 
// function Tetromino(tetromino, color) {
// 	this.tetromino = tetromino;
// 	this.color = color;
// 	this.tetrominoN = 0;
// 	this.activeTetromino = this.tetromino[this.tetrominoN];
// 	this.x = 0;
// 	this.y = 0;
// }

// //create an array for the pieces
// const pieces = [
// 	[Z, 'red'],
// 	[S, 'limegreen'],
// 	[T, 'yellow'],
// 	[O, 'blue'],
// 	[L, '#b938ff'],
// 	[I, 'cyan'],
// 	[J, 'orange']
// ]

// //create a new instance of Tetromino
// function randomPiece() {
// 	let r = Math.floor(Math.random() * pieces.length);
// 	return new Tetromino(pieces[r][0], pieces[r][1]);
// }
// let p = randomPiece();

// //draw the piece
// function drawPiece(piece) {
// 	//loop through the tetromino
// 	for(let r = 0; r < piece.length; r++) {
// 		for(let c = 0; c < piece.length; c++) {
// 			//if the tetromino index is zero skip it
// 			if(!piece[r][c]) continue;
// 			//else draw it
// 			else draw(p.x + c, p.y + r, p.color);
// 		}
// 	}
// }

// //undrawdraw the piece
// function undrawPiece(piece) {
// 	//loop through the tetromino
// 	for(let r = 0; r < piece.length; r++) {
// 		for(let c = 0; c < piece.length; c++) {
// 			//if the tetromino index is zero skip it
// 			if(!piece[r][c]) continue;
// 			//else draw it
// 			else draw(p.x + c, p.y + r, vacant);
// 		}
// 	}
// }

// drawPiece(p.activeTetromino);

// //control the piece 
// document.addEventListener('keydown', (event) => {
// 	if(event.keyCode === 37) p.moveLeft();

// 	else if (event.keyCode === 38) p.rotate();

//     else if (event.keyCode === 39) p.moveRight();

// 	else if (event.keyCode === 40) p.moveDown();

// });

// Tetromino.prototype.moveDown = function() {
// 	if(!this.collision(0, 1, this.activeTetromino)) {
// 		undrawPiece(this.activeTetromino);
// 		this.y++;
// 		drawPiece(this.activeTetromino);
// 	} else {
// 		//lock piece and generate a new one
// 		this.lock();
// 		p = randomPiece();
// 	}
// }

// Tetromino.prototype.moveLeft = function() {
// 	if(!this.collision(-1, 0, this.activeTetromino)) {
// 		undrawPiece(this.activeTetromino);
// 		this.x--;
// 		drawPiece(this.activeTetromino);
// 	}
// }

// Tetromino.prototype.moveRight = function() {
// 	if(!this.collision(1, 0, this.activeTetromino)) {
// 		undrawPiece(this.activeTetromino);
// 		this.x++;
// 		drawPiece(this.activeTetromino);
// 	}
// }

// Tetromino.prototype.rotate = function() {
// 	let nextPattern = this.tetromino[(this.tetrominoN + 1) % 4];
// 	if(!this.collision(0, 0, nextPattern)) {
// 		if(this.tetromino.length > 1) {
// 			undrawPiece(this.activeTetromino);
// 			this.tetrominoN = (this.tetrominoN + 1) % 4; // take paranthesis off
// 			this.activeTetromino = this.tetromino[this.tetrominoN];
// 			drawPiece(this.activeTetromino);
// 		}
// 	}
// }

// //create a function to check for collisions
// Tetromino.prototype.collision = function(x, y, piece) {
// 	for(let r = 0; r < piece.length; r++) {
// 		for(let c = 0; c < piece.length; c++) {
// 			//skip index if it is 0
// 			if(!piece[r][c]) continue;
// 			//create vars for the future piece position
// 			let newX = this.x + c + x;
// 			let newY = this.y + r + y;
// 			//see if new position collides with border
// 			if(newX < 0 || newX >= col || newY >= row) return true;
// 			//see if there's a locked piece on the board
// 			if(board[newY][newX] !== vacant) return true;
// 		}
// 	}
// 	return false;
// }

// Tetromino.prototype.lock = function() {
// 	for(let r = 0; r < this.activeTetromino.length; r++) {
// 		for(let c = 0; c < this.activeTetromino.length; c++) {
// 			if(!this.activeTetromino[r][c]) continue;
// 			//if piece reaches the top its gameover
// 			if(this.y + r < 0) {
// 				gameover = true;
// 				alert('Game Over!');
// 			}
// 			//lock the piece by updating the board
// 			board[this.y + r][this.x + c] = this.color;
// 		}
// 	}
// }

// let dropStart = Date.now();
// //drop the piece every 1s
// function drop() {
// 	let now = Date.now();
// 	let delta = now - dropStart;
// 	//if delta is greater than 1s drop the piece
// 	if(delta > 800) {
// 		p.moveDown();
// 		dropStart = Date.now();
// 	}
// 	requestAnimationFrame(drop);
// }

// drop();

//declare globals
const col = 10;
const row = 20;
const sq = 40;
const vacant = 'black';
const cvs = document.querySelector('#canvas');
const ctx = cvs.getContext('2d');

//create and draw the board
let board = [];
for(let r = 0; r < row; r++) {
	board[r] = [];
	for(let c = 0; c < col; c++) {
		board[r][c] = vacant;
		draw(c, r, board[r][c]);
	}
}

//create a blueprint function to draw to the board
function draw(x, y, color) {
	//set the drawing specifications
	ctx.fillStyle = color;
	ctx.fillRect(x * sq, y * sq, sq, sq);
	ctx.strokeStyle = 'white';
	ctx.strokeRect(x * sq, y * sq, sq, sq);
}

//create a blueprint object for the tetrominos
function Piece(tetromino, color) {
	//create the properties
	this.tetromino = tetromino;
	this.color = color;
	this.tetrominoN = 0;
	this.activeTetromino = this.tetromino[this.tetrominoN];
	this.x = 0;
	this.y = 0;
}

//create an array to hold all of the tetrominos
const pieces = [
	[Z, 'red'],
	[S, 'limegreen'],
	[T, 'yellow'],
	[O, 'blue'],
	[L, '#b938ff'],
	[I, 'cyan'],
	[J, 'orange']
]

//grab a piece
let p = new Piece(pieces[2][0], pieces[2][1]);

//create a blueprint function to draw tetrominos to the board
function drawPiece(piece, color) {
	for(let r = 0; r < piece.length; r++) {
		for(let c = 0; c < piece.length; c++) {
			if (!piece[r][c]) continue;
			draw(c + p.x, r + p.y, color);
		}
	}
}

//draw a piece to the board
drawPiece(p.activeTetromino, p.color);

//start a time to set as a refrence for the dropstart
let dropStart = Date.now();
//create a blueprint function to drop the piece
function drop() {
	//grab the current time
	let now = Date.now();
	//create a var to hold the difference of the current time
	let delta = now - dropStart; //------Why can't these be switched
	if(delta > 800) {
		dropStart = Date.now();
		drawPiece(p.activeTetromino, vacant);
		p.y++;
		drawPiece(p.activeTetromino, p.color);
		requestAnimationFrame(drop);
	}
}

drop();
<!-- <!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Tetris</title>
	<link href="https://fonts.googleapis.com/css?family=Orbitron&display=swap" rel="stylesheet">
</head>
<style>
	body {
		background-color: #595959;
		display: flex;
		justify-content: center;
		align-items: center;
		min-height: 100vh;
		overflow-y: hidden;
	}
	canvas {
		outline: 1px solid white;
	}
	.canvas-wrap {
		padding-left: 50px;
		padding-top: 50px;
		position: relative;
	}
	.num-top, .num-bottom {
		position: absolute;
		top: -1px;
		left: 0;
	}

	.num-top {
		width: 100%;
		height: 50px;
	}

	.num-bottom {
		height: 100%;
		width: 50px;
	}
	.nb {
		font-family: 'Orbitron';
		color: white;
	}
	.num-wrap-t {
		display: flex;
		justify-content: space-around;
		margin-left: 50px;
		width: 400px;
	}
	.num-wrap-b {
		display: flex;
		flex-direction: column;
		justify-content: space-around;
		margin-top: 50px;
		height: 800px;
	}
	.num-wrap-b .nb {
		text-align: right;
		margin-right: 3px;
	}

	.num-wrap-t .nb {
		position: relative;
		top: 31px;
	}
</style>
<body>
	<div class="canvas-wrap">
		<div class="num-top">
			<div class="num-wrap-t">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
			</div>
		</div>
		<canvas id="canvas" width="400" height="800"></canvas>
		<div class="num-bottom">
			<div class="num-wrap-b">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
				<div class="nb">10</div>
				<div class="nb">11</div>
				<div class="nb">12</div>
				<div class="nb">13</div>
				<div class="nb">14</div>
				<div class="nb">15</div>
				<div class="nb">16</div>
				<div class="nb">17</div>
				<div class="nb">18</div>
				<div class="nb">19</div>
			</div>
		</div>
    </div>		
	<script src="tetrominos.js"></script>
	<script src="tetris.js"></script>
</body>
</html> -->
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Tetris</title>
	<link href="https://fonts.googleapis.com/css?family=Orbitron&display=swap" rel="stylesheet">
</head>
<style>
	body, html {
		padding: 0;
		margin: 0;
	}

	body {
		background-color: #595959;
		min-height: 100vh;
		display: flex;
		justify-content: center;
		align-items: center;
	}

	canvas {
		outline: 1px solid white;
	}
	.canvas-wrap {
		padding-left: 50px;
		padding-top: 50px;
		position: relative;
	}
	.num-top, .num-bottom {
		position: absolute;
		top: -1px;
		left: 0;
	}

	.num-top {
		width: 100%;
		height: 50px;
	}

	.num-bottom {
		height: 100%;
		width: 50px;
	}
	.nb {
		font-family: 'Orbitron';
		color: white;
	}
	.num-wrap-t {
		display: flex;
		justify-content: space-around;
		margin-left: 50px;
		width: 400px;
	}
	.num-wrap-b {
		display: flex;
		flex-direction: column;
		justify-content: space-around;
		margin-top: 50px;
		height: 800px;
	}
	.num-wrap-b .nb {
		text-align: right;
		margin-right: 3px;
	}

	.num-wrap-t .nb {
		position: relative;
		top: 31px;
	}
</style>
<body>
	<div class="canvas-wrap">
		<div class="num-top">
			<div class="num-wrap-t">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
			</div>
		</div>
		<canvas id="canvas" width="400" height="800"></canvas>
		<div class="num-bottom">
			<div class="num-wrap-b">
				<div class="nb">0</div>
				<div class="nb">1</div>
				<div class="nb">2</div>
				<div class="nb">3</div>
				<div class="nb">4</div>
				<div class="nb">5</div>
				<div class="nb">6</div>
				<div class="nb">7</div>
				<div class="nb">8</div>
				<div class="nb">9</div>
				<div class="nb">10</div>
				<div class="nb">11</div>
				<div class="nb">12</div>
				<div class="nb">13</div>
				<div class="nb">14</div>
				<div class="nb">15</div>
				<div class="nb">16</div>
				<div class="nb">17</div>
				<div class="nb">18</div>
				<div class="nb">19</div>
			</div>
		</div>
	</div>
	<script src="tetrominos.js"></script>		
	<script src="tetris.js"></script>
</body>
</html>

1 个答案:

答案 0 :(得分:1)

要简单地回答问题:在requestAnimationFrame(drop)嵌套在if语句内的示例中,if条件永远不会满足。

该函数依赖于动画循环的发生,否则整个drop()函数将只运行一次,看到增量不为800,忽略其块内的代码,并且不再运行。

当requestAnimationFrame()在if语句之外时,它将始终运行并创建一个drop()的无休止循环,并且每次运行时,nowdelta都会增加函数运行所需的毫秒数,最终比dropStart大800毫秒,最终满足该语句,然后将时间变量设置为基本相同,然后为俄罗斯方块制作动画件移动一个空间。