8
\$\begingroup\$

I'm developing a 2D HTML5 Canvas Game, and I am trying to think of the most efficient way to implement a Physics Loop on the server-end of things, running NodeJS and Socket.IO.

The only method I've thought of is using setTimeout/Interval, is there any better way? Any examples would be appreciated.

EDIT: The Game is a top-down Game, like Zelda and older Pokemon Games. Most of the physics done in the loop will be simple intersects.

\$\endgroup\$
  • \$\begingroup\$ You should probably specify what type of game you are planning, specifically it is hard to say anything about server timing without knowing how time critical you game will be. \$\endgroup\$ – aaaaaaaaaaaa Sep 5 '13 at 17:53
  • \$\begingroup\$ Zelda is a lot more time critical than Pokemon. What is the multiplayer component by the way? Why does the game need to run on the server? \$\endgroup\$ – aaaaaaaaaaaa Sep 5 '13 at 19:08
  • \$\begingroup\$ @eBusiness It's Multiplayer, think MMORPG, where there are many players in different areas of Maps at any given time, updating using the server. \$\endgroup\$ – Oyed Sep 5 '13 at 19:46
  • \$\begingroup\$ I had the same issue. game loop can be implemented using the link bellow: npmjs.com/package/gameupdate-loop \$\endgroup\$ – Impractical Labs May 15 '19 at 15:32
5
\$\begingroup\$

I believe setTimeout is good enough for your needs. I am, myself, facing a similar situation and I am going with setTimeout. This awesome article on BNG helped me better understand what a I have to do (or, at least, try): Real Time Multiplayer in HTML5.

About the link: It talks mostly about the multiple game loops and networking them. It's pretty cool. Below, an excerpt.

When it comes to a real time game, we want to run the game logic itself on the server AND the client. This is due to the fact that the server needs to be the authority on the state of the game at all times, but the client needs to run the game locally too. Each frame on the server, input from the network will be processed and applied to players, and that change is sent to the other players at a fixed rate. On the client, input will be collected and sent to the server, and positions can be updated while waiting for the messages to come back from the server (client prediction).

It's a highly recommended read. At least by me. =P

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ You should add more to your answer, so that future users know what you are talking about, in case the link dies. \$\endgroup\$ – user15805 Oct 28 '13 at 21:54
  • \$\begingroup\$ @AlexM. The link is more like a complement and not immediately related to the question... But you're right. It's better summarize it anyway once I decided to put it there. =) \$\endgroup\$ – slacktracer Oct 30 '13 at 18:02
  • 1
    \$\begingroup\$ Might also be worth mentioning in the answer how the article suggests having separate loops for physics updates (~60fps) and server-->client updates (~20fps) on the server, as well as separate loops for physics (~60fps) and client-->server (fast as possible) updates on the client. The separation of the io and the physics-themed loops is the most distinctive feature of that article compared to a few others I've looked at. \$\endgroup\$ – max Aug 30 '15 at 20:14
2
\$\begingroup\$

For server-side stuff you have a couple of options. The first is to entirely extrapolate all your collisions working off of the assumption that you will have frequent-enough messages from clients, communicating all meaningful state change through the server, which then will run validation on game events only as it receives IO callbacks from the client connections.

The second way, which you seem to prefer, is to run your own loop while whilst you process IO callbacks. Although setInterval and setTimeout will accomplish this, you have a much more fine-grained set of tools to control this: setImmediate(callbacks, [[arg], ...]) and process.nextTick(callback).

Process.nextTick will run your callback before other IO events, so long as you haven't stacked up a recursively infinite stack of callbacks (if it exceeds a certain number, process.maxTickDepth, then it will yield to the IO callbacks).

SetImmediateCallback is similar to process.nextTick in that it acts every tick, but only one of the queued callbacks gets executed on every tick, rather than all queued callbacks.

Using these will look similar to setTimeout or requestAnimationFrame.

function gameLoop() {
  updateCollisions();
  process.nextTick(gameLoop);
}

process.nextTick(gameLoop);

The advantage of these is that you're not dependent on V8's implementation of setTimeout and setInterval. These are more of a direct line to Node's event loop. Just be sure you don't starve the IO if you are using process.nextTick. updateCollisions should be guaranteed to not take that long at all.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ -1 requestAnimationFrame hooks to the screen refresh rate, it is only relevant to the user computer. And for a networked game you really wouldn't want to try anything but fixed rate screen-independent physics. \$\endgroup\$ – aaaaaaaaaaaa Sep 5 '13 at 17:51
  • \$\begingroup\$ eBusiness is right, requestAnimationFrame is monitor-based whereas the Loop I'm trying to achieve is server-side in NodeJS. \$\endgroup\$ – Oyed Sep 5 '13 at 18:13
  • \$\begingroup\$ @eBusiness Looks like I misread the question, updated with material relevant to server code and nodejs. \$\endgroup\$ – michael.bartnett Sep 5 '13 at 20:55
  • \$\begingroup\$ @michael.bartnett In regards to extrapolating all collisions based on frequent packets from users, this is something I've implemented before, but on a 60FPS Machine more packets are sent, whereas 30FPS is half a many packets etc. etc. So what implementation of this would you recommend? I'm pretty open to suggestions right now. The example you provided seems pretty solid, but like you said, dependent on the Collision Checking/Other Physics being quite fast. This is fine, but if there is a better option you know of, please share! \$\endgroup\$ – Oyed Sep 5 '13 at 21:12
  • \$\begingroup\$ @ThomasMosey That's sort of a broad and difficult question to answer, and is pretty dependent on the specifics of your game. Especially the method where the server isn't running its own logic loop. A good place to start thinking is to answer: who owns each object at every point in the game, what causes those objects to change owners, and what must be objectively tracked and arbitrated--that is, owned by the server. \$\endgroup\$ – michael.bartnett Sep 5 '13 at 23:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.