我正在制作一个俄罗斯方块游戏,现在我正在编写一个函数,该函数每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>
答案 0 :(得分:1)
要简单地回答问题:在requestAnimationFrame(drop)
嵌套在if语句内的示例中,if条件永远不会满足。
该函数依赖于动画循环的发生,否则整个drop()
函数将只运行一次,看到增量不为800,忽略其块内的代码,并且不再运行。
当requestAnimationFrame()在if语句之外时,它将始终运行并创建一个drop()
的无休止循环,并且每次运行时,now
和delta
都会增加函数运行所需的毫秒数,最终比dropStart
大800毫秒,最终满足该语句,然后将时间变量设置为基本相同,然后为俄罗斯方块制作动画件移动一个空间。