This teaches a bad practice: frame-rate-dependent movement speed. Perhaps it runs fine on your 3GHz 16-thread i7 Chromebook Pixel with a single tab open that achieves a consistent 60fps, but it makes the game unplayable on machines achieving slower or less consistent framerates (like mine, which has a somewhat overburdened Firefox process on a mere 4-thread mobile i5).
If you're writing a game which, like this one, does not run at a fixed guaranteed framerate, you should vary movement speed based on the time delta between frames, i.e. instead of `x += 2.5` on every frame, do `x += (2.5 * 60) * seconds_since_last_frame`.
No, that's also a terrible idea. It makes problems like jumps that are easier, or harder (maybe impossible) to achieve based on frame rate. Games used to do this, now noone does as it leads to impossible to fix bugs and weird physics problems.
The best idea (but i don't know how to do this in is) is to run your engine at 60fps (say), then skip drawing if you are behind (but then always draw at least every third frame, if someone's computer isn't good enough to even run the engine). If you want to go above 60fps, then extrapolate between two states.
No, the usual way of achieving this is to decouple your movement (as in, physics) from rendering. Instead of having an "update" loop, have "renderUpdate" and "physicsUpdate" as separate loops, one tied to FPS, other constant.
Fully agreed. You can certainly deal with some aspects of variable framerate integration. But it's by far a better solution, more future proof even, to just have a fixed number of iterations by second and don't account for time deltas in integration.
My physics-based game is using the method argued against. Never again, integrating every behaviour over time got sometimes surprisingly hard. It also costs a lot of exp() and log() calls.
https://auburnsounds.itch.io/vibrant
(of course multiplayer is impossible now)
Some of the AI is still framerate-dependent, because:
// fixed framerate
if (randomFloat0To1() < 0.1f)
doThis();
We do also loose much accuracy/stability of physics info when varying timesteps, without adjusting velocities to the new half timestep (eg. verlet type refinement) which is a bit demanding to do most accurately.
First, even at a constant framerate, different players will have different experiences with the game due to different amounts of latency in their peripherals, weird CPU bugs, very very minor floating point behavior deviations, etc. The important part of making something framerate independent is to make the effects of framerate independence /smaller enough/ than other factors that make player experiences.
It's entirely possible to not have gameplay change at different tickrates. There are three usual types of problem that cause gameplay to change at different tickrates:
1) Events that happen at specific times
If events can only happen "in sync" with ticks, then running at different framerates will make them happen at different times. Say you have a machine gun that fires once every 1/10th of a second. If you're running at 24fps, then not only do you need to make sure that you correctly output a bullet every two-or-three frames, you also have to make it so that they /act like/ they came out at a time between frames, presumably by simulating them a little extra bit or a little less depending on what's necessary to make each bullet a fixed distance apart (for example). You could also use a continuous interaction system here but that's really hardcore and doesn't matter in 99.9%+ of cases.
2) Treating curved motions as linear motions
This isn't a problem in 99% of cases, but it ~can~ be a problem. If you can't represent your physics curves in closed form, it's effectively impossible to trace them in a framerate-independent way. The only thing you can do for these things is to "fix your timestep", but "fix your timestep" should be used with extreme caution and not be applied to action games because it adds input latency and hides frame-specific-timing information from players. Recommendation: use simpler game physics. Constant acceleration everywhere you can, special-purpose closed form functions with the right curves where you can't, and avoid tight curves. This makes it less of an issue.
You might also want a collision system that allows curved paths, but if you have enough control over your game's environments, and you don't expect people to run at SUPER low framerates, this isn't an issue.
3) Running different "integral" parts of the simulation out of sync with eachother.
This isn't literally about code order execution, it's about the behavior of different pieces of code that "add up" "over time" (if you're into calculus, think antiderivatives)
If you add n to your position every frame, that's all fine and good, as long as it always starts at exactly the right time. If you add "five pixels per second" to your position, then you need to make sure that always causes the same amount of distance travelled. Quake 3 handles this by giving subframe timings to things like pressing and releasing movement keys.
Another example is gravity. Normally, game code adds a specific amount of gravity every frame, possibly adjusted for time, either before or after motion. This isn't good enough, because if you add gravity after moving, very low framerates will have a higher initial frame of gravitational movement; essentially, low framerates will skip "outside" the ideal jump arc rather than tracing it. If you add gravity before moving, the opposite happens, low framerates trace "inside" the ideal jump arc. The correct thing to do is to calculate motion with around half the added velocity from all accelerations for that frame, which basically means the average of accelerating before or after. You can also trace a hermite spline, which is more flexible (you will have perfect framerate independence for any acceleration values that only change along line segments, i.e. "constant jerk", as long as you handle start/stop conditions for changes in acceleration with a correct continuous interaction simulation), but harder to implement.
The above is only 100% ideally possible for things you can represent closed form, and in practice, people will only implement something correctly if it's not just closed form but /simple/. Many games stop short of correct jump arcs, but it's entirely possible. Gang Garrison 2 was just changed to have a correct framerate-independent jump arc.
I don't know what kind of CPU bugs or float point behaviour deviations you think modern cpus have that will effect a game.. such things would cause most online games to immediately go out-of-sync, and in practice they don't, and while latency might effect player's enjoyment, it won't effect how fast they run / how high they jump.
The hardest part is the curved motions -- and also collision detection. Without ticks it's extremely hard to make collision detection repeatable.
I'm unaware of any recent notable multi-player game which don't run on a tick-based physics engine (I'd be interested if you could point me to some) -- that suggests to me that tick-based is necessary.
Sure, you can get things "closer" in tickless physics, but I've never seen anything non-trivial which can produce exactly the same results, for reasons of floating point: when (A+B)+C isn't the same as A+(B+C), it's very hard to make your game produce exactly the same results.
As you say, with a lot of work, you can get a 95% repeatable result with a tickless engine, but you can easily get 100% repeatable with a fixed time-step engine, and in practice it seems to make things work well enough, and is VASTLY easier.
During development of the game [Prototype] I experimented with a number of game logic update scenarios, including variable timesteps, fixed (potentially multiple per frame) and limited fixed (potentially leading to slow motion), in combination with factors like enabling and disabling vsync, taking into account camera movement (speed, mostly horizontal or mostly vertical?), amount of explosions and debris going off, etc. To try and find the best experience for the player at each moment.
But we always had physics running at a fixed update rate (always receiving a constant delta time) regardless of any of the above. Trying variable rates there will ruin the stability of your movement, collisions, platforming, etc in any system that is complex or requires precision and predictability.
Online games avoid that problem by having an authoritative networking architecture, not by avoiding minor deviations in CPU behavior between players. Games that use synchronized lockstep that use floating point math always desync, because floating point math differs slightly between different processors.
Curved motions are easy as long as you have simple polygons and only one of them is accelerating and is accelerating in a simple way. You remove the acceleration by skewing the polygon you're going to collide with and then you have a linear path of motion again. (if the acceleration is not constant for the duration of that frame, then skewing doesn't give the right result; as long as you have a closed form representation, though, it's entirely possible to get it right)
"Don't run on a tick-based physics engine" is a misconception. Interactions are the borders between ticks. It's just dynamic. As long as your tick doesn't contain interaction changes inside it, you can simulate that tick with 100% tickrate independence with 100% certainty.
Floating point differences between cpus are Much Larger, especially if your code uses hardware-accelerated trig at all. Games networking is authoritative for this reason.
You can get a 100% repeatable result with a tickless engine.
Fixed timestep doesn't solve the problem. If the user can't run the simulation at 60 ticks per second, they're still going to slow down, period. All you're doing is separating simulation from rendering, which basically every modern FPS under the sun already tries to do in a different way than fixed timestep does. If you run the simulation slow enough that nobody will have performance problems with it, you just added tons of input latency. Thanks a lot, sincerely, someone with dysgraphia.
> because floating point math differs slightly between different processors.
I don't know why you keep saying this. If I compile a program which uses floating point for (say) x64, it will produce the same results on every machine. Can you give any example where the same executable will produce different results on different machines?
Now, you may get different answers on ARM, or 32-bit, but almost no games (I'm having trouble thinking of any) try to do cross-CPU networking, so the (extremely) minor differences doesn't make any difference. Most games don't sync between users, they trust each user to run the game engine -- you can't afford to send the total state of the world to users, it would take far too much network traffic.
Can you point me to a physics engine which gives 100% repeatable results with tickless? I'm genuinely interested, I didn't know of any that claim they achieve that, the common ones (box2d, unity and havok for example) certainly don't.
Because it's true. The same operation on the same data may give different results on different CPUs, even if you're operating at the machine code level (no implementation-specific optimizations).
>Can you point me to a physics engine which gives 100% repeatable results with tickless? I'm genuinely interested, I didn't know of any that claim they achieve that, the common ones (box2d, unity and havok for example) certainly don't.
box2d is sufficiently low level that it gives programmers the tools necessary to do this.
Most notably, box2d provides the following:
>Continuous physics with time of impact solver
This directly allows developers to create a "tickless" physics simulation by breaking up the simulation into the timespans between interactions, as long as pathological situations aren't introduced (like the quake 3 ledge climbing bug). That doesn't mean that the developer will actually do so, and if the gameplay logic interacts with physics in framerate-dependent ways the result will still be wrong. It just means that the possibility is there.
Of course, this doesn't solve game logic issues with things happening only at the moment that a frame happens. That's entirely on the developer, even if they use an ideal physics engine.
At the end of this, I'll repeat that fixed timestep doesn't actually solve the problem, all it does is allow you to output higher graphical framerates than the physics simulation is running at. If the physics simulation itself can't run at full speed, you still need a way to adapt to longer frametimes, and you have to do so correctly. And if you run the physics simulation so slowly that it won't slow down on any reasonable PC, you either have a very simple game or you just added tons of input latency.
The reason why you don't see an issue while using Box2D is because its integration methods are low-error. A simple platform game using Euler style integration of the type
each step, add forces from input and gravity. add the resulting acceleration multiplied by time to my position.
will trivially produce jump heights of 50% variation when subjected to a variable timestep. On a quick search, Box2D uses semi-implicit Euler [0], which much more accurately fits the curve. It does not guarantee zero error: to do that you have to have an analytic method, which isn't applicable to a general-purpose physics simulation.
I covered integration error in my first post here, point 3. The thing I was calling Box2D out for is the fact that it doesn't use a hacky way of rectifying collisions. It seeks out the point in time that they occur.
>It does not guarantee zero error: to do that you have to have an analytic method, which isn't applicable to a general-purpose physics simulation.
If you have constant acceleration, the analytic way to get the point you want to be at at the end of the frame is simple: just pretend your current frame is using half the added speed from the acceleration that you're going to undergo this frame. Or you could use a hermite curve or something.
Those are the integration methods I was talking about. An analytic method without error is one which can describe the curve at any moment in time, not "constant acceleration per frame".
Box2d's continuous physics does not allow for a tickless simulation as I understand the term, because continuous interactions (stacking, sliding, rolling, etc.) are not reduced to discrete time-of-impact calculations. Joints are also in that category. If you run the testbed and crank the timestep way up, you'll definitely see problems with things like ragdolls.
Continuous collision detection definitely makes it easier to handle high velocities and bigger timesteps, but it's not a panacea.
By "continuous physics", it doesn't mean the "objects don't go through walls" thing (that's easy), it means that it actually finds the times that interactions happen. Box2d isn't able to use that in all cases, but it does allow it to act the same way as a tickless simulation if your game's physics is simple enough, like 2d platformers.
I think theoretically you're correct that the methods underlying Box2d could be used in such a way, but practically I don't think it's there, as that was never one of the engine's goals. Read up on the methods used (for instance, http://twvideo01.ubm-us.net/o1/vault/gdc2013/slides/824737Ca...) for some of the limitations that Erin chose to accept. In particular the fact that it misses multiple roots during the solve means that you can't use if for perfect tickless simulation; there are (were? I'm not sure to what extent they've been addressed since I was deep in that code) also issues with conservation of time that would be a problem, which are discussed elsewhere (for instance http://box2d.org/forum/viewtopic.php?t=154).
I didn't know about the innaccuracies in sin/cos, good to know, I'll remember that, but I usually wouldn't use those in a physics engine (and now I certainly won't).
The other stuff, different compiling levels, changing the floating point rounding mode, does indeed change results, but that wouldn't effect a single compile of a program running on different machines.
I maintain a javascript PRNG which relies on basic floating point math operations, addition and multiplication. Its test page here (https://strainer.github.io/Fdrandom.js/) displays a warning if it doesn't hit expected value 1 million rnds after default seeding. I've not found any computer or phone fail that basic compliance test yet.
Differences in trig functions strikes me as more matter of Math library compliance that floating point unit, im not sure but would be hopeful these are fairly well standardised across javascript engines.
To add to this statement: Input latency is a much broader issue than collision latency - a large scale of collision latency is produced simply by being an online game, regardless of how you're trying to represent the events. So the collision being subject to a tickrate is hardly a dealbreaker. Variable timesteps can be a little bit better at performance or responsiveness, but it comes at the expense of flooding additional concerns about consistency throughout the main loop. The modern fixed timestep treats a tick rate as delta times being partitioned into quantities of ticks, but also passes the time each tick represents into each update as a way to ensure that timers and time-centric physics can exhibit perceptually similar behaviors if the tickrate, and thus the duration of each tick, changes.
Input latency, OTOH, is something that has challenged developers from the earliest days since it has to do with how fast you propagate new input through the main loop to the output device, and the timestep's interaction with input is not straightforward. Arcade games could drastically improve their feel just by capturing and debouncing input multiple times a frame, even with the simple screen-refresh timesteps that were the common practice.
Variable timesteps have their own host of problems. Considering the target and scope of TFA I think best practices are beside the point, but your suggested replacement is bad practice as well.
The "right thing to do" in most games is to integrate at fixed timesteps that are decoupled from rendering. But this can be tricky to get right, and would require another article to explain [0]. Considering all that, the article's implementation is fine!
[0] Except that the definitive article has already been written, that is:
Using the delta between frames directly isn't quite right either, but it's better than writing framerate-dependent code. I think an even better way is to use an accumulator with a fixed time step, as described here: http://gafferongames.com/game-physics/fix-your-timestep/
On the other hand, beyond a certain level framerate-dependent movement speed can be enabling to the player. If there are parts in the game where the performance breaks down on certain machines, then it can be preferable to have the game go slower, i.e. still controllable, than a slide show that leaves the player no time to react.
There is no one-size-fits-all when it comes to game loops. There's various ways to approach them and which one fits your game best is determined by its gameplay.
> If there are parts in the game where the performance breaks down on certain machines, then it can be preferable to have the game go slower, i.e. still controllable, than a slide show that leaves the player no time to react.
edit: guess I spoke too quickly, that was v3. In v2 the game loop in Phaser is more aggressive detecting "spiral of death" scenarios. Still, the idea is that if your CPU just can't deal with the given number of updates per second even when skipping renders and other "optional" stuff, then there is just no way to avoid a bad experience, either very low framerate or slow motion. Variable framerate simulations can be quite dangerous and unstable, and the example doesn't even try.
I was wondering what framework they used, and am glad to see them use Phaser.
The TypeScript definitions are pretty nice (at least for the last official 2.x release), so if you're interested in learning TypeScript it's a great way to start.
Life has gotten in the way so I've slowed down, but I kept track of the Phaser tutorials I followed at https://github.com/JamesSkemp/PhaserTutorials (and converted the later tutorials to TypeScript while I was following them).
I had hopes, but then played the game. It's very basic and doesn't work on mobile browsers such as Firefox on Android and iOS, nor iOS Safari. Doesn't load in desktop IE11. No touch support.
HTML5 games seem to be stuck in a pattern of ultra-simple design, limited browser support and poor responsive characteristics - what HTML should be good at. Even a graceful degrade is absent.
Very simple games should counter-balance that simplicity with awesome cross browser and mobile support.
Not trying to discredit the educational efforts, but perhaps making a dedicated windows or native app game would have been better to teach things like animating sprites and physics, where the end result sits more comfortably on the platform it was made for.
Developing a "HTML5" game is a very great experience. The only HTML you need though is <!DOCTYPE html><meta charset="utf8"><canvas></canvas><script> ... </script> The rest is just JavaScript and interaction with the canvas. And writing a server in NodeJS is almost trivial if you already know JavaScript. I recommend not using a game engine or framework! And as a general advice, actually don't do much abstraction at all! In-line all functions within the animation/render/game loop. Your next weekend project should be a ".io" game, it's a lot of fun!
I'm going to try going through this workshop with my kids. One of the challenges of teaching my kids to program is finding interesting projects that are within their scope of interest. I've tried MindStorms, Ardrino, and various online tutorials but so far nothing has interested them for very long. Maybe making games will interest them.
If they're not interested, just keep them in the loop. Show them some of the cool stuff people build every once in a while or just tell them they can automate their math homework with a simple console app. I'm pretty sure the prospects not having to do my homework by hand would've made me sit down and code instead.
I've recently been using vim inside of tmux on a remote server to "replicate" what C9 offers. It's rather nice and I'm enjoying it a lot, but I also found C9 to be pretty awesome too.
Exactly. Thank you. I actually implemented a platform game with melonjs a long time ago (like 6+ yrs ago), before that a platform game using Flash + AS3. I have since given up game dev. I was asking hoping to solicit a response from current game devs on what's the preferred js game frameworks. But alas, Im automatically presumed to be some random lazy web guy asking on HN who doesnt know how to do these basic cybery stuff like goooogelling.
I made a game[1] as a hobby with Phaser and packaged it with NW.js. I worked on it for about six months, but not as a commercial project. I haven't done any marketing or advertising. I've made about $8 US from the game passively existing, which I'm quite happy with.
I've done a few games for a company I work for. These were developed as minisites for marketing purposes. I used Construct for the first game and that was very limiting (but very "easy" to use.), but in the end this created a lot of bugs (as you can't fully control the logic sometimes) and it's not easy to extend.
The next 3 or 4 were done in Phaser. It was very easy to setup and to code your own stuff in it. It runs very well and because you can code around it, server connections were also easy to do. The next game will be done again Phaser.js.
I haven't made a single cent off it, but my solitaire game (https://solitaire.gg) uses Phaser, I found it to be a great engine, if a bit heavy for a card game.
I haven't done any, but I know there are different publishing models where JS frameworks really shine.
It's not normally about creating a standalone game/app that you sell, but more about creating an easily accessible web game that attracts an audience and then you capitalize on tangential in-game goods like coins or abilities.
Think more Kongregate (or even the Mafia style games) rather than App Store. Those rarely need a full blown engine like Unreal or Unity.
I have just finished a game that has fun core gameplay, and Id like to continue building it out for optimization.
However, we were already running in to issues where phaser was limiting us.
Current build already has server lobbies, and after putting that into prod, I'd like yo add matchmaking and team based modes.
I work in a company that uses Cocos2d as a primary game engine (JS or C++ bindings in different projects - moving to JS lately), and we recently celebrated 100 mil installs on mobile.
at my last job, we developed games for online casinos with phaser (mostly slot machines). development started in 2014, and we looked at all the major html5 game frameworks, and phaser stood out by far for our requirements.
If you're writing a game which, like this one, does not run at a fixed guaranteed framerate, you should vary movement speed based on the time delta between frames, i.e. instead of `x += 2.5` on every frame, do `x += (2.5 * 60) * seconds_since_last_frame`.