Reputation: 340
I'm playing with redux-saga to create a version of the snake game in react native, and I'm not sure how to go about the game loop implementation. So far I have a working version, but it feels clunky.. the snake moves at different speeds and the game is not very smooth.
Here is what I've got so far:
function *tickSaga() {
while (true) {
yield call(updateGameSaga)
const game = yield select(getGame)
if (game.crashed)
break
yield delay(1000)
}
}
The updateGameSaga basically gets the state from the store, process some logic (finds out if the snake next move will be a crash, move to an empty tile or move to a food tile and grow) and dispatches the corresponding action for it.
I'm slightly aware of things like requestAnimationFrame which I know I should be using, but I'm not sure how to make it work within the saga (maybe I don't need too do it in the saga, hence this question).
Any ideas on how to improve the smoothness of the game loop would be welcome.
I've included redux-saga-ticker, which internally uses setInterval
(code here) to periodically send updates to the channel.
function *tickSaga() {
const channel = Ticker(1000); // game tick every 1000ms
while (true) {
yield take(channel);
yield call(updateGameSaga);
const game = yield select(getGame)
if (game.crashed)
break
}
}
It works better now and I like the channel aproach, but I still feel requestAnimationFrame
is the way to go, although I'm not yet sure on how to implement it.
Upvotes: 2
Views: 805
Reputation: 2709
How about this.
let lastTime = 0;
function *tickSaga() {
while (true) {
var time = +new Date();
var delayTime = Math.max(0, 1000 - (time - lastTime));
lastTime = time + delayTime;
yield call(updateGameSaga)
const game = yield select(getGame)
if (game.crashed)
break
yield delay(delayTime)
}
}
If you need 60 fps, replace 1000 to 16 (1000/60). For each tick you have a correction of the interval (time - lastTime) so the ticker interval should be uniform.
Upvotes: 2