Reputation: 563
I'm building a Snake-like game with two modules. The first (let's call it "Main") handles the game's mechanics and the second ("MainUI") builds the UI and display based on the board state it receives from the mechanics module.
Main handles setInterval for both itself and for MainUI and sets the tick rate thus:
var startGame = Main.startGame = function (displayCallback) {
board.initialize();
var container = function () {
gameTick(displayCallback);
}; // displayCallback is a function passed from the UI to visually render the board
root.gameLoop = Main.gameLoop = window.setInterval(container, 200);
};
So the game, and its display, is intended to update five times a second. It executes this code on every update:
var gameTick = Main.gameTick = function (displayCallback) { // same callback
if (isGameOver()) {
gameOver();
}
player.update(); //update an array of the coordinates the player occupies
board.update(); //recreate board state based on position of player
board.display(displayCallback); //Board.display runs the externally-passed callback
};
But the game seems to run far slower than it should. In fact, no amount of adjusting the setInterval time seems to make it faster beyond a certain point, say, half a second. I'm not sure if the problem is in inefficient mechanics code, if passing the display callback function around is causing problems, or if I'm using setInterval improperly, or if somehow the UI code is slowing it down.
The UI starts the mechanics module like this:
var beginUpdates = MainUI.beginUpdates = function () {
Main.startGame(updateBoard);
};
And it updates the displayed board, an HTML table with unique CSS formatting for elements with specific classes, using jQuery like so:
var updateBoard = MainUI.updateBoard = function (board) {
for (var y = 0; y < board.length; y++) {
for(var x = 0; x < board[0].length; x++) {
var currentElement = $("td[data-y=" + y + "][data-x=" + x + "]")
switch(board[y][x]) {
case 0:
currentElement.removeClass("snake");
currentElement.removeClass("apple");
break;
case 1:
currentElement.addClass("snake");
currentElement.removeClass("apple");
break;
case 2:
currentElement.removeClass("snake");
currentElement.addClass("apple");
break;
}
}
}
};
This function is from the UI module and is the callback that is passed into the mechanics module, where it is given the "board" object.
Can you guys tell me what might be going wrong here? I'll be happy to post more code. I apologize for the long post and for my cluelessness :\
Upvotes: 1
Views: 94
Reputation: 353
You should first try profiling your code and HTML updates. In Chrome this can be done using the Developer Tools.
JS Profiling
In the Profiles tab choose "Collect JavaScript CPU Profile" and click start. Start your game and play it for a 10 seconds or so. Again go to the Profiles tab and click stop. You will now be able to see if your code is taking longer than it should, although I suspect this is not the problem.
A way to speed this up may be to cache the jQuery elements themselves in an array instead of selecting them each time which will be slow. I would also give the TDs an ID instead of using data elements such as:
<table id="game">
<tr>
<td id="cell-0-0"></td>
<td id="cell-1-0"></td>
</tr>
<tr>
<td id="cell-0-1"></td>
<td id="cell-1-1"></td>
</tr>
</table>
And use a selector that is only selecting on IDs as these a very quick.
$('#cell-' + x + '-' + y);
HTML Profiling
This is more likely the problem. Depending on what you are doing with the CSS it may be causing reflows on the page. To test for this, and your general HTML paint speed, open the developer tools and click the "Settings" (gear) icon. Here you can enable:
Upvotes: 1