【发布时间】:2019-08-07 12:41:43
【问题描述】:
我正在制作俄罗斯方块游戏,现在我正在编写每 1 秒(在本例中为每 800 毫秒)丢块的函数。我的函数是这样的
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 棋子每 800 毫秒掉落一次。我查看了调试器并观察了函数的执行。我看着它击中了第一个 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>
【问题讨论】:
-
如果
delta <= 800则不会再调用它,因此 delta 永远不会变为 > 800,因为代码永远不会再次调用... requestAnimationFrame 只调用一次给定函数...要再次调用它,您必须再次 requestAnimationFrame ...因为您不这样做,所以什么也没有发生
标签: javascript html css