MainLoop.js provides a well-constructed main loop useful for JavaScript games and other animated or time-dependent applications.
The main loop is a core part of any application in which state changes over time. In games, it is typically responsible for computing physics and AI as well as drawing the result on the screen.
Main loops are difficult to write correctly due to timing issues. The vast majority of main loops found online are written incorrectly, resulting in applications that speed up or slow down depending on the frame rate. This can cause unfortunate behavior like characters running through walls or being unable to jump over obstacles. These main loops can also result in applications that are non-deterministic. This project solves these problems.
- Example (source code)
- API documentation
- MainLoop.js source code (heavily documented to explain how it works - the source is about 75% docs)
- How it works and a detailed walkthrough of what problems this project solves
You can download the script normally, install it with npm
(npm install mainloop.js
), or install it with Bower
(bower install mainloop
). To include it on a page client-side without a
module loader:
<!-- from a direct download or git clone -->
<script src="build/mainloop.min.js"></script>
<!-- from npm -->
<script src="node_modules/mainloop.js/build/mainloop.min.js"></script>
<!-- from Bower -->
<script src="bower_components/mainloop.js/build/mainloop.min.js"></script>
<!-- via CDN -->
<script src="https://cdn.jsdelivr.net/npm/mainloop.js@latest/build/mainloop.min.js"></script>
You then have access to the MainLoop
global.
MainLoop.js is also compatible with CommonJS (e.g. with node.js or
browserify) and AMD (e.g. with RequireJS). This means that if you are using
a module loader or want to use MainLoop server-side you can call
require('mainloop.js')
to get the MainLoop
object or include 'mainloop.js'
in
the dependencies you pass to a define()
call.
For TypeScript users, there are
typings
available. Install them with npm install --save-dev @types/mainloop.js
.
MainLoop
works by running functions you define every time the browser is
ready to update the screen (up to about 60 times per second on most monitors).
There are four such functions, all of which are optional. You can set them
using the following methods:
MainLoop.setBegin()
: thebegin
function runs at the beginning of each frame and is typically used to process input.MainLoop.setUpdate()
: theupdate
function runs zero or more times per frame depending on the frame rate. It is used to compute anything affected by time - typically physics and AI movements.MainLoop.setDraw()
: thedraw
function should update the screen, usually by changing the DOM or painting a canvas.MainLoop.setEnd()
: theend
function runs at the end of each frame and is typically used for cleanup tasks such as adjusting the visual quality based on the frame rate.
The update
function receives a delta
parameter which holds the amount of
time in milliseconds that should be simulated. This should be used to calculate
movement. For example, if an object obj
has an x-axis velocity of 100 units
per second (0.1 units per millisecond), the update
function might look like
this:
function update(delta) {
obj.x += 0.1 * delta;
}
This structure will ensure that your application behaves regardless of the frame rate.
To start the application, simply call MainLoop.start()
. For example, to start
the application for the first time, you might write:
MainLoop.setUpdate(update).setDraw(draw).start();
You can call MainLoop.stop()
to stop the application.
For more detail about the API, check out the documentation. You can also check out a usage example (source code).
This project is MIT-licensed.
Compatible with all modern browsers (IE9+) including mobile browsers, as well as node.js. There are no dependencies.
Contributions are welcome. To get started contributing, run npm install
in
the project's directory, then run grunt
before submitting a pull request to
update the minified script and the docs as well as to perform a style check.
The library is < 1KB minified and gzipped.
Isaac Sukin (@IceCreamYou) is the author of this project. I'd love to hear about what you make! Special thanks to Ian Langworth for reviewing a version of this I wrote for my book about making 3D browser games and for some tips about web workers.