现在,我正在用JavaScript编写Conway的生活游戏,而我遇到的问题是使用requestAnimationFrame()进行动画处理。当我在浏览器中加载游戏时,动画在一瞬间就运行得太快了。我想知道是否有人可以提供有关如何减慢动画速度以便可以看到动画正常运行的建议?
JavaScript代码如下:
$(function(event) {
var GRIDWIDTH = 400;
var GRIDHEIGHT = 400;
var gameGrid = createGrid(GRIDWIDTH); //Grid used to display the grid
var newGameGrid = createGrid(GRIDWIDTH); //Grid used to update game state
//creates the grid for the game, using an array of empty arrays
function createGrid(rows) {
var gridArray = []; //is the game grid
//for loop that creates the grid array, each element is an empty array to create the multi-dimensional array
for (var i = 0; i < rows; i++) {
gridArray[i] = [];
}
return gridArray;
}
//will populate the grid randomly with alive and dead cells
function populateGrid() {
for (var rows = 0; rows < GRIDHEIGHT; rows++) { //goes across the rows within the grid
for (var cols = 0; cols < GRIDWIDTH; cols++) { //goes across the columns within the grid
var cell = Math.floor(Math.random() * 2 ); //the cells of the grid is either a 1 or 0 (alive or dead), chosen at random
if (cell === 1) { //if the cell variable is the same as the integer value 1 and same type int then the element at gameGrid[rows][cols] is set to a 1 else a 0, this is done randomly.
gameGrid[rows][cols] = 1;
}
else {
gameGrid[rows][cols] = 0;
}
}
}
}
//Will draw the game grid on the screen including cells
function drawGrid() {
// var gameCanvas = $("#gameCanvas"); //gets the gameCanvas element
var ctx = $("#gameCanvas")[0].getContext("2d");
ctx.clearRect(0, 0, 400, 400);
//both loops go through the rows and columns respectively and draws the pixel in the grid in the specified colour
for (var rows = 1; rows < GRIDHEIGHT; rows++) {
for (var cols = 1; cols < GRIDWIDTH; cols++) {
if (gameGrid[rows][cols] === 1) { //if the element is a 1 the pixel is coloured (red) to represent it is alive
ctx.fillStyle = "#FF0000";
ctx.fillRect(rows, cols, 1, 1);
}
}
}
}
//this function will update the grid to show the new position of the pixels
function updateGrid() {
for (var rows = 1; rows < GRIDHEIGHT - 1; rows++) {
for (var cols = 1; cols < GRIDWIDTH - 1; cols++) {
var totalNeighbours = 0; //holds the total neighbours a cell has
//calculations to add the neighbours
totalNeighbours += gameGrid[rows-1][cols-1]; //top left
totalNeighbours += gameGrid[rows-1][cols]; //top center
totalNeighbours += gameGrid[rows-1][cols+1] //top right
totalNeighbours += gameGrid[rows][cols-1] //middle left
totalNeighbours += gameGrid[rows][cols+1] //middle right
totalNeighbours += gameGrid[rows+1][cols-1] //bottom left
totalNeighbours += gameGrid[rows+1][cols] //bottom center
totalNeighbours += gameGrid[rows+1][cols+1] //bottom right
//Game of life rules:
//alive cell rules
if (gameGrid[rows][cols] === 1) {
switch(totalNeighbours) {
//rule 1 any live cell with fewer than two live neighbours dies, as if by underpopulation
case totalNeighbours < 2:
newGameGrid[rows][cols] = 0;
break;
//rule 2 any live cell with two or three live neighbours lives on to the next generation
case totalNeighbours == 2:
case totalNeighbours == 3:
newGameGrid[rows][cols] = 1;
break;
//rule 3 any live cell with more than three live neighbours dies, as if by overpopulation
case totalNeighbours > 3:
newGameGrid[rows][cols] = 0;
break;
}
}
//dead cell rule 4 any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
else if (gameGrid[rows][cols] === 0) {
if (totalNeighbours == 3) {
newGameGrid[rows][cols] = 1;
}
}
}
}
//iterate through the rows and columns and gameGrid is set to the newGameGrid with the updated cells in the grid
for (var rows = 0; rows < GRIDWIDTH; rows++) {
for (var cols = 0; cols < GRIDHEIGHT; cols++) {
gameGrid[rows][cols] = newGameGrid[rows][cols];
}
}
}
populateGrid();
start();
function start() {
drawGrid();
updateGrid();
requestAnimationFrame(start);
}
})
The html is simple as follows:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Conway's Game Of Life</title>
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="text/javascript" src="../js/index.js"></script>
<link rel="stylesheet" href="../css/index.css">
<link href="https://fonts.googleapis.com/css?family=Anton" rel="stylesheet">
</head>
<body>
<div class="gameScreen">
<div class="title">John Conway's Game Of Life</div>
<canvas id="gameCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
</div>
</body>
</html>
答案 0 :(得分:0)
另请参见
我认为您应该将两次渲染之间经过的时间与速度因子结合起来使用。
例如,您可以定义希望主角在一秒钟内移动200px。然后-使用渲染之间的经过时间,您可以计算出要将他移动多远(模型代码):
var distance_to_move = 200px * time_since_last_render / 1000;
setNewPosition();
render();
因此,如果自上次渲染以来经过的时间是500毫秒,那么在此渲染中,您会将他移动100像素。
答案 1 :(得分:0)
这是使用requestAnimationFrame
的方式:传递给它的函数接受一个参数,即时间戳。您可以使用它来计算经过的时间。在此示例中,该步长设置为2s(2000ms)。请注意,您需要以requestAnimationFrame(start);
而不是start();
开头:
$(function(event) {
var GRIDWIDTH = 400;
var GRIDHEIGHT = 400;
var gameGrid = createGrid(GRIDWIDTH); //Grid used to display the grid
var newGameGrid = createGrid(GRIDWIDTH); //Grid used to update game state
//creates the grid for the game, using an array of empty arrays
function createGrid(rows) {
var gridArray = []; //is the game grid
//for loop that creates the grid array, each element is an empty array to create the multi-dimensional array
for (var i = 0; i < rows; i++) {
gridArray[i] = [];
}
return gridArray;
}
//will populate the grid randomly with alive and dead cells
function populateGrid() {
for (var rows = 0; rows < GRIDHEIGHT; rows++) { //goes across the rows within the grid
for (var cols = 0; cols < GRIDWIDTH; cols++) { //goes across the columns within the grid
var cell = Math.floor(Math.random() * 2 ); //the cells of the grid is either a 1 or 0 (alive or dead), chosen at random
if (cell === 1) { //if the cell variable is the same as the integer value 1 and same type int then the element at gameGrid[rows][cols] is set to a 1 else a 0, this is done randomly.
gameGrid[rows][cols] = 1;
}
else {
gameGrid[rows][cols] = 0;
}
}
}
}
//Will draw the game grid on the screen including cells
function drawGrid() {
// var gameCanvas = $("#gameCanvas"); //gets the gameCanvas element
var ctx = $("#gameCanvas")[0].getContext("2d");
ctx.clearRect(0, 0, 400, 400);
//both loops go through the rows and columns respectively and draws the pixel in the grid in the specified colour
for (var rows = 1; rows < GRIDHEIGHT; rows++) {
for (var cols = 1; cols < GRIDWIDTH; cols++) {
if (gameGrid[rows][cols] === 1) { //if the element is a 1 the pixel is coloured (red) to represent it is alive
ctx.fillStyle = "#FF0000";
ctx.fillRect(rows, cols, 1, 1);
}
}
}
}
//this function will update the grid to show the new position of the pixels
function updateGrid() {
for (var rows = 1; rows < GRIDHEIGHT - 1; rows++) {
for (var cols = 1; cols < GRIDWIDTH - 1; cols++) {
var totalNeighbours = 0; //holds the total neighbours a cell has
//calculations to add the neighbours
totalNeighbours += gameGrid[rows-1][cols-1]; //top left
totalNeighbours += gameGrid[rows-1][cols]; //top center
totalNeighbours += gameGrid[rows-1][cols+1] //top right
totalNeighbours += gameGrid[rows][cols-1] //middle left
totalNeighbours += gameGrid[rows][cols+1] //middle right
totalNeighbours += gameGrid[rows+1][cols-1] //bottom left
totalNeighbours += gameGrid[rows+1][cols] //bottom center
totalNeighbours += gameGrid[rows+1][cols+1] //bottom right
//Game of life rules:
//alive cell rules
if (gameGrid[rows][cols] === 1) {
switch(totalNeighbours) {
//rule 1 any live cell with fewer than two live neighbours dies, as if by underpopulation
case totalNeighbours < 2:
newGameGrid[rows][cols] = 0;
break;
//rule 2 any live cell with two or three live neighbours lives on to the next generation
case totalNeighbours == 2:
case totalNeighbours == 3:
newGameGrid[rows][cols] = 1;
break;
//rule 3 any live cell with more than three live neighbours dies, as if by overpopulation
case totalNeighbours > 3:
newGameGrid[rows][cols] = 0;
break;
}
}
//dead cell rule 4 any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
else if (gameGrid[rows][cols] === 0) {
if (totalNeighbours == 3) {
newGameGrid[rows][cols] = 1;
}
}
}
}
//iterate through the rows and columns and gameGrid is set to the newGameGrid with the updated cells in the grid
for (var rows = 0; rows < GRIDWIDTH; rows++) {
for (var cols = 0; cols < GRIDHEIGHT; cols++) {
gameGrid[rows][cols] = newGameGrid[rows][cols];
}
}
}
populateGrid();
requestAnimationFrame(start);
var startTime = null, stepInMs = 2000, drawCount = 0;
function start(timestamp) {
var progress;
if (startTime === null){
startTime = timestamp;
}
progress = timestamp - startTime;
if (progress > stepInMs) {
drawCount++;
document.getElementById('drawCount').innerHTML = drawCount;
startTime = timestamp;
drawGrid();
updateGrid();
}
requestAnimationFrame(start);
}
})
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Conway's Game Of Life</title>
<script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script type="text/javascript" src="../js/index.js"></script>
<link rel="stylesheet" href="../css/index.css">
<link href="https://fonts.googleapis.com/css?family=Anton" rel="stylesheet">
</head>
<body>
<div class="gameScreen">
<div class="title">John Conway's Game Of Life - count: <span id="drawCount">0</span></div>
<canvas id="gameCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
</div>
</body>
</html>
编辑:添加了一个跨度以显示重新绘制,并带有一个计数来演示,您的代码中可能存在错误,因为它在重新绘制时仅更改了2次。.