newton
Version:
A playful, particle-based physics engine designed from the ground up for JavaScript.
310 lines (286 loc) • 13.3 kB
HTML
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>Newton - guide</title>
<link href="http://fonts.googleapis.com/css?family=Poiret+One" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Roboto:400" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="styles/base.css">
<link rel="stylesheet" type="text/css" href="styles/smart-grid.css">
<link rel="stylesheet" type="text/css" href="styles/modules.css">
</head>
<body>
<div class="Header">
<div class="container">
<header class="row">
<div class="columns four"><a href="http://hunterloftis.github.io/newton/">
<h1 class="Logo">Newton</h1></a></div>
<div class="columns eight">
<div class="MainMenu"><a href="/dist/docs/guide.html" class="active">Guide</a><a href="#">API Reference</a><a href="https://github.com/hunterloftis/newton">Github</a><a href="https://github.com/hunterloftis/newton/issues?direction=desc&sort=created&state=open">Issues</a></div>
</div>
</header>
</div>
</div>
<div class="container">
<div class="row">
<nav class="columns three SideBar">
<ul>
<li><a href="#hello">Hello, World
<ul>
<li><a href="#install">Install the library</a></li>
<li><a href="#simulation">Create a simulation</a></li>
<li><a href="#particle">Add a particle</a></li>
<li><a href="#render">Render the scene</a></li>
<li><a href="#demo_hello">Demo: Hello, World</a></li>
</ul></a></li>
<li><a href="#basics">Movement
<ul>
<li><a href="#forces">Forces</a></li>
<li><a href="#constraints">Constraints</a></li>
<li><a href="#demo_basics">Demo: Rope</a></li>
</ul></a></li>
<li><a href="#bodies_group">Bodies
<ul>
<li><a href="#bodies">Create a Body</a></li>
<li><a href="#extending_body">Extending Body</a></li>
<li><a href="#demo_bodies">Demo: Rope Body</a></li>
</ul></a></li>
<li><a href="#interaction">Interaction
<ul>
<li><a href="#input">Input</a></li>
<li><a href="#removal">Removal</a></li>
<li><a href="#destruction">Destruction</a></li>
<li><a href="#demo_behavior">Demo: Interactive Rope</a></li>
</ul></a></li>
</ul>
</nav>
<main class="columns nine"><a name="hello"></a>
<h2>Hello, World</h2><a name="install"></a>
<h3>Install the library</h3>
<div class="Section-content">
<p>
<ul>
<li><a href="http://hunterloftis.github.io/newton/current/newton.js">newton.js</a></li>
<li><a href="http://hunterloftis.github.io/newton/current/newton.min.js">newton.min.js</a></li>
</ul>
</p>
<p>Or with npm:
<pre class="CodeBlock">npm install --save newton</pre>
<pre class="CodeBlock">var Newton = require('newton');</pre>
</p>
</div><a name="simulation"></a>
<h3>Create a simulation</h3>
<div class="Section-content">
<p>
The Simulator is responsible for
integrating Particles, applying Forces, and resolving Constraints.
</p>
<p>
All the high-level and advanced functionality of Newton is based on these three simple steps.
</p>
<pre class="CodeBlock">var sim = Newton.Simulator();
sim.start();</pre>
</div><a name="particle"></a>
<h3>Add a particle</h3>
<div class="Section-content">
<p>
Newton has three building blocks: Particles, Forces, and Constraints.
Particles are points in space that have X and Y coordinates as well as mass (size).
</p>
<pre class="CodeBlock">var particle = Newton.Particle(10, 20); // x, y
sim.add(particle);
</pre>
</div><a name="render"></a>
<h3>Render the scene</h3>
<div class="Section-content">
<p>
Newton ships with a WebGL-based renderer for development and debugging.
To use it, you'll need to create a canvas element on your page.
In this case, we've called our canvas `#display`.
</p>
<p>
You can render anyway you like - canvas, webgl, DOM, SVG, etc.
All renderers support a simple interface.
</p>
<pre class="CodeBlock">var display = document.getElementById('display');
var renderer = Newton.GLRenderer(display);
renderer.render(sim);
</pre>
</div><a name="demo_hello"></a>
<h3>Demo: Hello, World</h3>
<div class="Section-content">
<p>
As you can see, we're up and running -
but it's a little boring with just one Particle sitting still.
</p>
<div class="Demo-container">
<iframe src="http://jsfiddle.net/hunterloftis/yDY6r/2/embedded/js,result,html" class="Demo"></iframe>
</div>
</div><a name="basics"></a>
<h2>Movement</h2><a name="forces"></a>
<h3>Forces</h3>
<div class="Section-content">
<p>
Forces are the second basic element of Newton.
Each frame, the Simulator applies Forces to Particles in order to create movement.
</p>
<p>
Newton comes with a library of Forces, and you can easily add your own.
</p>
<pre class="CodeBlock">var gravity = Newton.LinearForce(1, Math.PI * 1.5); // strength, direction
sim.add(gravity);
</pre>
</div><a name="constraints"></a>
<h3>Constraints</h3>
<div class="Section-content">
<p>Constraints are the third basic element of Newton and are its most powerful feature.</p>
<p>
They create rules that are applied to Particles after integration, like
"All particles should stay within this rectangle," or "These two particles should be connected."
</p>
<p>
BoxConstraint is a location constraint that keeps a particle within a rectangular area.
Newton comes with a library of Constraints.
</p>
<pre class="CodeBlock">var container = Newton.BoxConstraint(0, 0, 1000, 600); // x, y, width, height
sim.add(container);
</pre>
<p>
The simulator runs constraints repeatedly to converge at an approximate solution.
Since constraints can conflict with each other, it's a good idea to give Newton
a hint about which constraints are most important. You can do this via the Simulator's
<span class='Code'>solve</span> option:
</p>
<pre class="CodeBlock">var sim = Newton.Simulator({
solve: [ Newton.PinConstraint, Newton.RopeConstraint ] // PinConstraint is more important than RopeConstraint
});
</pre>
</div><a name="demo_basics"></a>
<h3>Demo: Rope</h3>
<div class="Section-content">
<p>
Now things are getting interesting. Our little rope has come to life!
</p>
<div class="Demo-container">
<iframe src="http://jsfiddle.net/hunterloftis/a4kXG/2/embedded/js,result,html" class="Demo"></iframe>
</div>
</div><a name="bodies_group"></a>
<h2>Bodies</h2><a name="bodies"></a>
<h3>Create a Body</h3>
<div class="Section-content">
<p>
When building a simulation, you frequently want to refer to
a group of Particles, Forces, and Constraints as a single entity.
Newton uses the concept of Bodies for grouping elements.
</p>
<p>
Instead of adding Particles and Constraints directly to the Simulator,
we can instead add them as a group in a Body:
</p>
<pre class="CodeBlock">var rope = Newton.Body();
rope.add(Newton.Particle(500 + i * 20, 180));
rope.add(Newton.RopeConstraint(prev, current));
sim.add(rope);
</pre>
<p>
Keep in mind, Bodies are just for bookkeeping - logical groupings so your code can be readable.
They have no impact on the simulation.
</p>
</div><a name="extending_body"></a>
<h3>Extending Body</h3>
<div class="Section-content">
<p>
In most cases, you'll extend Newton's base Body to create reusable custom Body types.
For example, let's create a Rope Body:
</p>
<pre class="CodeBlock">function Rope(x, y, length) {
Newton.Body.call(this); // call Body's constructor
// implementation here
}
Rope.prototype = Object.create(Newton.Body.prototype); // extend Body's prototype
var rope = new Rope(225, 10, 300);
</pre>
</div><a name="demo_bodies"></a>
<h3>Demo: Rope Body</h3>
<div class="Section-content">
<p>
Reuse! We now have a drop-in Rope Body that we can use as many times as we like:
</p>
<div class="Demo-container">
<iframe src="http://jsfiddle.net/hunterloftis/6FJtv/4/embedded/js,result,html" class="Demo"></iframe>
</div>
<p>
We can also extend Rope with new data and behaviors.
We've already given it a head property - we could also add a tail property
or methods like coil() or snap()
</p>
</div><a name="interaction"></a>
<h2>Interaction</h2><a name="input"></a>
<h3>Input</h3>
<div class="Section-content">
<p>
Interacting with Newton is easy -
just inject Forces, Particles, or Constraints into the system
based on your user's behavior.
</p>
<pre class="CodeBlock">var mousePin = null;
renderer.on('pointerdown', function(point) {
var particle = sim.findNearest(point, 30);
if (particle) mousePin = sim.add(Newton.PinConstraint(particle, point));
});
</pre>
<p>
In this case, we've added a PinConstraint to represent the user.
When the user clicks on a Particle,
we bind the Particle to a new constraint, which we update to follow
wherever the user moves her mouse.
</p>
</div><a name="removal"></a>
<h3>Removal</h3>
<div class="Section-content">
<p>
Just like add() adds Particles, Forces, and Constraints to a simulation,
remove() removes them.
</p>
<p>
In this case, we want to remove the PinConstraint whenever the user releases her mouse,
so she can "let go" of the dragged Particle:
</p>
<pre class="CodeBlock">renderer.on('pointerup', function(point) {
if (!mousePin) return;
sim.remove(mousePin);
mousePin = null;
});</pre>
</div><a name="destruction"></a>
<h3>Destruction</h3>
<div class="Section-content">
<p>
Some Constraints can receive options that include some sort of strength value.
If a Simulation reaches a point where the Constraint is acting beyond its strength,
it will destroy itself to create realistic deformations and structural behavior.
</p>
<p>
RopeConstraints can have a tensile strength. Here, we specify that once the
Constraint stretches to 3x its original length, it should break:
</p>
<pre class="CodeBlock">this.add(Newton.RopeConstraint(prev, current, {
length: segmentLength,
stiffness: 0.9, // slightly springy
strength: 3 // break when stretched to 3x length
} ));</pre>
</div><a name="demo_behavior"></a>
<h3>Demo: Interactive Rope</h3>
<div class="Section-content">
<p>
Now we can drag our ropes around!
If we stretch them too far they'll even realistically break.
</p>
<div class="Demo-container">
<iframe src="http://jsfiddle.net/hunterloftis/SK6SH/1/embedded/js,result,html" class="Demo"></iframe>
</div>
</div>
</main>
</div>
</div>
</body>
</html>