Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 988937 of Building up a basic demo with PlayCanvas

  • Revision slug: Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_PlayCanvas
  • Revision title: Building up a basic demo with PlayCanvas
  • Revision id: 988937
  • Created:
  • Creator: end3r
  • Is current revision? No
  • Comment init commit - PlayCanvas engine demo

Revision Content

PlayCanvas is a popular 3D WebGL game engine originally created by Will Eastcott and Dave Evans. It is open sourced on GitHub, with an editor available online and good documentation. It is free for public projects and two team members, but there are also paid plans if you'd like to run a commercial, private project with more developers.

Games and demos

PlayCanvas is known for a few games showcasing its possibilities. Tanx is a multiplayer tank game where you can fight and shoot directly at other players, and Swooop let's you fly your plane around the magical island. It's not only for games - you can find demos and visualizations like the Star Lord or BMW i8 that take advantage of the engine and showcase what's possible. You can check the list of featured demos for inspiration.

Engine vs editor

The engine itself can be used as a standard library by including its file containing the source code in a project, so you can start coding right away, but PlayCanvas toolset also comes with an online editor which you can use to drag and drop components onto the scene - a great way to create games and applications if you're more of a designer than a coder. Those approaches are offering different experiences, but work equally well - after all the more tools to choose from, the better.

PlayCanvas engine

Built for modern browsers, PlayCanvas is a fully featured 3D game engine with resource loading, entity and component system, advanced graphic manipulation, collision and physics (built with ammo.js), audio and input from various devices (including gamepads). That's quite an impressive list of features - let's see some in action.

The engine demo

We can try a simple demo first - cube rendered on the screen. If you had the time to check the Building up a basic demo with Three.js article you've probably noticed that PlayCanvas have similar concepts: camera, light and objects. To play with all that though we have to organize our development environment first.

Environment setup

To start developing with PlayCanvas, you don't need much. You should:

  • Make sure you are using a modern browser with good WebGL support, such as the latest Firefox or Chrome.
  • Create a directory to store your experiments in.
  • Save a copy of the latest PlayCanvas engine inside your directory.
  • Open the PlayCanvas documentation in a separate tab — it is useful to refer to.

HTML structure

Here's the HTML structure we will use.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>MDN Games: PlayCanvas demo</title>
    <style>
        body { margin: 0; padding: 0; }
        canvas { width: 100%; height: 100%; }
    </style>
</head>
<body>
<script src="js/playcanvas-latest.js"></script>
<canvas id="application-canvas"></canvas>
<script>
    var canvas = document.getElementById("application-canvas");
    /* all our JavaScript code goes here */
</script>
</body>
</html>

It contains some basic information like the document <title>, and some CSS to set the width and height of the <canvas> element that PlayCanvas will use to 100% so that it will fill the entire available viewport space. The first <script> element includes the PlayCanvas library in the page, and we will write our example code into the second one. There is one helper variable already included, which will store the reference to the <canvas> element.

Before reading on, copy this code to a new text file, and save it in your working directory as index.html.

PlayCanvas application

To begin developing our game we have to create the PlayCanvas application first (using the given <canvas> element), and then start the update loop.

var app = new pc.Application(canvas);
app.start();

The pc object is a global handle that contains all the PlayCanvas functions available in the engine.

app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
app.setCanvasResolution(pc.RESOLUTION_AUTO);

Next, we'll set the Canvas to fill the window, and then automatically change its resolution to be the same as the Canvas size.

Camera

Now when the setup code is in place we need to think about the usual components of the scene: camera, lights and objects. Let's start with the camera - add these lines to your code, below the prevous ones.

var camera = new pc.Entity();
camera.addComponent("camera", {
    clearColor: new pc.Color(0.8, 0.8, 0.8)
});
app.root.addChild(camera);
camera.setPosition(0, 0, 7);

The code above will create a new Entity and add a camera component to it with the light gray clearColor which will be visible as the background. Then the camera object is added to the root of our application and positioned to be 7 units away from the center of the scene on the z axis, so we can make some place for the objects that we will create later on.

Note: The distance values (e.g. for the camera z position) are unitless, and can basically be anything you deem suitable for your scene — milimeters, meters, feet, or miles — it's up to you.

Try saving the file and loading it in your browser. You should now see a gray window. Congratulations!

Geometry

Now when the scene is properly rendering we can start adding 3D shapes to it. To speed up development PlayCanvas provides a bunch of predefined primitives that you can use to create shapes instantly in a single line of code. There are cubes, spheres, cylinders and more complicated shapes available. Drawing everything for given shape is taken care of by the engine, so we can focus on the high level coding. Let's start by defining the geometry for a cube shape — add the new code below your previous additions:

var box = new pc.Entity();
box.addComponent("model", { type: "box" });
app.root.addChild(box);
box.rotate(10, 15, 0);

It will create and Entity with the box model component and add it to the root of the application, our scene. We can rotate the box a bit to see it's actually a 3D cube and not a square.

As you can already see the cube is visible, but it looks black. To make it look better we have to shine some light onto it.

Lights

The basic light types in PlayCanvas are directional and ambient. The first type is a directional light placed somewhere on the scene while the scond one reflects the light from the first type, so it looks more natural, and can be set globally. Again, add the new code below your previous additions.

var light = new pc.Entity();
light.addComponent('light');
app.root.addChild(light);
light.rotate(45, 0, 0);

It will create a light Entity component and add it to the scene. We can rotate the light on the x axis to make it shine on more than one side of the cube. It's time to add the ambient light:

app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2); 

The code above assign a dark grey ambient light for the whole scene. The box look better now, but it could get some colors to look even better - for that we need to create material for it.

Material

The basic PlayCanvas material is called PhongMaterial - add those lines below the previous code.

var boxMaterial = new pc.PhongMaterial();
boxMaterial.diffuse.set(0, 0.58, 0.86);
boxMaterial.update();
box.model.model.meshInstances[0].material = boxMaterial;

By diffusing the light on the object we can set it's own color - in this case the familiar blue one.

Note: The values are given in the 0-1 float range instead of 0-255 int range for the RGB scale.

After the material is created and color is set it have to be updated so our changes are going to be applied. Then all we need is to set the box's material to the newly created boxMaterial.

Congratulations, you've created your first object in a 3D environment using PlayCanvas! It was easier than you thought, right? Here's how it should look:

Blue cube on a gray background rendered with PlayCanvas.

And here's the code we have created so far:

{{JSFiddleEmbed("https://jsfiddle.net/end3r/cqs6pg3x/","","350")}}

You can also check it out on GitHub.

More shapes

Now we will add more shapes to the scene. Let's move the cube 2 units to the left to make space for some friends — add the following line just below the previous one:

box.translate(-2, 0, 0);

Now let's add a new shape - how about a cylinder?

Cylinder

Add the following lines to your JavaScript code:

var cylinder = new pc.Entity();
cylinder.addComponent("model", { type: "cylinder" });
app.root.addChild(cylinder);
cylinder.rotate(15, 0, 0);

It looks very similar to creating a cube, but instead of the box component we are adding a cylinder. It is also rotated on the x axis to show it's actually a 3D shape. To make the cylinder have a color, let's say yellow, we need to create the material for it.

var cylinderMaterial = new pc.PhongMaterial();
cylinderMaterial.diffuse.set(1, 0.58, 0);
cylinderMaterial.update();
cylinder.model.model.meshInstances[0].material = cylinderMaterial;

It looks and works the same as the one we have created for the cube, but with a different color.

Cone

Creating a cone and its material looks almost exacly the same as the cylinder.

var cone = new pc.Entity();
cone.addComponent("model", { type: "cone" });
app.root.addChild(cone);
cone.translate(2, 0, 0);

var coneMaterial = new pc.PhongMaterial();
coneMaterial.diffuse.set(0.9, 0.9, 0.9);
coneMaterial.update();
cone.model.model.meshInstances[0].material = coneMaterial;

The code above will create a new cone, add it to the app and move it by 2 units to the right so it's not interfering with the cylinder. Then the material is created, set with the gray color which is then applied, and it is assigned to the cone Entity.

Here's how it should look right now:

Shapes: blue cube, yellow cylinder and gray cone on a light gray background rendered with PlayCanvas.

This looks a little bit boring though. In a game something is usually happening — we can see animations and such — so let's try to breathe a little life into those shapes by animating them.

Animation

We already used translate or rotate to adjust the position of the shapes; we could also change thier positions directly with setPosition, or scale them. To show actual animation, we need to make changes to these values inside the render loop, so they are updated on every frame. There's a special update event that we can use for that - add the following code just below the previous one:

var timer = 0;
app.on("update", function (deltaTime) {
    timer += deltaTime;
    // code executed on every frame
});

It takes the deltaTime as the parameter, so we have the relative time that has passed since the previous invocation of this update. For time based animations we'll use a timer variable that will store the time that has passed since the start of the app by adding the deltaTime to it on every update.

Rotation

Rotating is quite easy — all you need to do is to add a defined value to the given direction of the rotation on each frame. Add this line of code inside the app.on("update") function right after the addition of the deltaTime to the timer variable:

box.rotate(deltaTime*10, deltaTime*20, deltaTime*3);

It will rotate the box by deltaTime*10 on the x axis, deltaTime*20 on the y axis and deltaTime*30 on the z axis respectively - by doing so it will look like a smooth animation.

Scaling

We can also scale a given object - there's a function for that called setLocalScale.

cylinder.setLocalScale(1, Math.abs(Math.sin(timer)), 1);

This way we'll be able to use Math.sin and end up with quite an interesting result: this will scale the cylinder and repeat the whole process, as sin is a periodic function. We're wrapping the y scale value in Math.abs to pass the absolute values (greater or equal to 0), because sin is between -1 and 0, and for negative values the cylinder might render unexpectedly (in this case it looks black half the time).

Now onto the movement part.

Moving

Beside rotation and scaling we can also move objects around the scene. Add the following code to achieve that.

cone.setPosition(2, Math.sin(timer*2), 0);

This will move the cone up and down by applying the sin value to the y axis on each frame, with a little bit of adjustment to make it look cooler. Try changing the value to see how it affects the animations.

Conclusion

Here's the final piece of the code:

{{JSFiddleEmbed("https://jsfiddle.net/end3r/auvcLoc4/","","350")}}

You can also see it on GitHub and fork the repository if you want to play with it yourself locally. Now you know the basics of PlayCanvas engine, congatulations!

PlayCanvas Editor

Instead of coding everything from scratch you can also use the online editor. It might be a lot easier for you if you don't like to code. The PlayCanvas Editor is free - all you have to do is register your account and login.

TODO: EDITOR INSTRUCTIONS, SUMMARY

Revision Source

<p clas="summary"><span class="seoSummary">PlayCanvas is a popular 3D WebGL game engine originally created by Will Eastcott and Dave Evans. It is <a href="https://github.com/playcanvas/engine">open sourced on GitHub</a>, with an <a href="https://developer.playcanvas.com/en/user-manual/designer/">editor</a> available <a href="https://login.playcanvas.com/">online</a> and good <a href="https://developer.playcanvas.com/en/">documentation</a>.</span> It is free for public projects and two team members, but there are also <a href="https://playcanvas.com/plans">paid plans</a> if you'd like to run a commercial, private project with more developers.</p>

<h2>Games and demos</h2>

<p>PlayCanvas is known for a few games showcasing its possibilities. <a href="https://playcanv.as/p/aP0oxhUr">Tanx</a> is a multiplayer tank game where you can fight and shoot directly at other players, and <a href="https://playcanv.as/p/JtL2iqIH">Swooop</a> let's you fly your plane around the magical island. It's not only for games - you can find demos and visualizations like the <a href="https://playcanv.as/b/FQbBsJTd">Star Lord</a> or <a href="https://playcanv.as/p/RqJJ9oU9">BMW i8</a> that take advantage of the engine and showcase what's possible. You can check the list of <a href="https://playcanvas.com/explore">featured demos</a> for inspiration.</p>

<h2>Engine vs editor</h2>

<p>The engine itself can be used as a standard library by including its file containing the source code in a project, so you can start coding right away, but PlayCanvas toolset also comes with an online editor which you can use to drag and drop components onto the scene - a great way to create games and applications if you're more of a designer than a coder. Those approaches are offering different experiences, but work equally well - after all the more tools to choose from, the better.</p>

<h2>PlayCanvas engine</h2>

<p>Built for modern browsers, PlayCanvas is a fully featured 3D game engine with resource loading, entity and component system, advanced graphic manipulation, collision and physics (built with <a href="https://github.com/kripken/ammo.js/">ammo.js</a>), audio and input from various devices (including gamepads). That's quite an impressive list of features - let's see some in action.</p>

<h3>The engine demo</h3>

<p>We can try a simple demo first - cube rendered on the screen. If you had the time to check the <a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/Building_up_a_basic_demo_with_Three.js">Building up a basic demo with Three.js</a> article you've probably noticed that PlayCanvas have similar concepts: camera, light and objects. To play with all that though we have to organize our development environment first.</p>

<h3>Environment setup</h3>

<p>To start developing with PlayCanvas, you don't need much. You should:</p>

<ul>
 <li>Make sure you are using a modern browser with good <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API">WebGL</a> support, such as the latest Firefox or Chrome.</li>
 <li>Create a directory to store your experiments in.</li>
 <li>Save a copy of the <a href="https://code.playcanvas.com/playcanvas-latest.js">latest PlayCanvas engine</a> inside your directory.</li>
 <li>Open the <a href="https://developer.playcanvas.com/en/user-manual/">PlayCanvas documentation</a> in a separate tab — it is useful to refer to.</li>
</ul>

<h3>HTML structure</h3>

<p>Here's the HTML structure we will use.</p>

<pre class="brush: html">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;title&gt;MDN Games: PlayCanvas demo&lt;/title&gt;
    &lt;style&gt;
        body { margin: 0; padding: 0; }
        canvas { width: 100%; height: 100%; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script src="js/playcanvas-latest.js"&gt;&lt;/script&gt;
&lt;canvas id="application-canvas"&gt;&lt;/canvas&gt;
&lt;script&gt;
    var canvas = document.getElementById("application-canvas");
    /* all our JavaScript code goes here */
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>

<p>It contains some basic information like the document <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/title">&lt;title&gt;</a>, and some CSS to set the width and height of the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas">&lt;canvas&gt;</a> element that PlayCanvas will use to 100% so that it will fill the entire available viewport space. The first <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script">&lt;script&gt;</a> element includes the PlayCanvas library in the page, and we will write our example code into the second one. There is one helper variable already included, which will store the reference to the &lt;canvas&gt; element.</p>

<p>Before reading on, copy this code to a new text file, and save it in your working directory as <code>index.html</code>.</p>

<h3>PlayCanvas application</h3>

<p>To begin developing our game we have to create the PlayCanvas application first (using the given &lt;canvas&gt; element), and then start the update loop.</p>

<pre class="brush: js">
var app = new pc.Application(canvas);
app.start();
</pre>

<p>The <code>pc</code> object is a global handle that contains all the PlayCanvas functions available in the engine.</p>

<pre class="brush: js">
app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
app.setCanvasResolution(pc.RESOLUTION_AUTO);
</pre>

<p>Next, we'll set the Canvas to fill the window, and then automatically change its resolution to be the same as the Canvas size.</p>

<h3>Camera</h3>

<p>Now when the setup code is in place we need to think about the usual components of the scene: camera, lights and objects. Let's start with the camera - add these lines to your code, below the prevous ones.</p>

<pre class="brush: js">
var camera = new pc.Entity();
camera.addComponent("camera", {
    clearColor: new pc.Color(0.8, 0.8, 0.8)
});
app.root.addChild(camera);
camera.setPosition(0, 0, 7);
</pre>

<p>The code above will create a new <code>Entity</code> and add a <code>camera</code> component to it with the light gray <code>clearColor</code> which will be visible as the background. Then the <code>camera</code> object is added to the root of our application and positioned to be 7 units away from the center of the scene on the <code>z</code> axis, so we can make some place for the objects that we will create later on.</p>

<div class="note">
<p><strong>Note</strong>: The distance values (e.g. for the camera z position) are unitless, and can basically be anything you deem suitable for your scene — milimeters, meters, feet, or miles — it's up to you.</p>
</div>

<p>Try saving the file and loading it in your browser. You should now see a gray window. Congratulations!</p>

<h3>Geometry</h3>

<p>Now when the scene is properly rendering we can start adding 3D shapes to it. To speed up development PlayCanvas provides a bunch of predefined primitives that you can use to create shapes instantly in a single line of code. There are cubes, spheres, cylinders and more complicated shapes available. Drawing everything for given shape is taken care of by the engine, so we can focus on the high level coding. Let's start by defining the geometry for a cube shape — add the new code below your previous additions:</p>

<pre class="brush: js">
var box = new pc.Entity();
box.addComponent("model", { type: "box" });
app.root.addChild(box);
box.rotate(10, 15, 0);
</pre>

<p>It will create and <code>Entity</code> with the <code>box</code> model component and add it to the root of the application, our scene. We can rotate the box a bit to see it's actually a 3D cube and not a square.</p>

<p>As you can already see the cube is visible, but it looks black. To make it look better we have to shine some light onto it.</p>

<h3>Lights</h3>

<p>The basic light types in PlayCanvas are directional and ambient. The first type is a directional light placed somewhere on the scene while the scond one reflects the light from the first type, so it looks more natural, and can be set globally. Again, add the new code below your previous additions.</p>

<pre class="brush: js">
var light = new pc.Entity();
light.addComponent('light');
app.root.addChild(light);
light.rotate(45, 0, 0);
</pre>

<p>It will create a light <code>Entity</code> component and add it to the scene. We can rotate the light on the <code>x</code> axis to make it shine on more than one side of the cube. It's time to add the ambient light:</p>

<pre class="brush: js">
app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2); 
</pre>

<p>The code above assign a dark grey ambient light for the whole scene. The box look better now, but it could get some colors to look even better - for that we need to create material for it.</p>

<h3>Material</h3>

<p>The basic PlayCanvas material is called <a href="https://developer.playcanvas.com/en/api/pc.PhongMaterial.html">PhongMaterial</a> - add those lines below the previous code.</p>

<pre class="brush: js">
var boxMaterial = new pc.PhongMaterial();
boxMaterial.diffuse.set(0, 0.58, 0.86);
boxMaterial.update();
box.model.model.meshInstances[0].material = boxMaterial;
</pre>

<p>By diffusing the light on the object we can set it's own color - in this case the familiar blue one.</p>

<div class="note">
<p><strong>Note</strong>: The values are given in the <code>0-1</code> <code>float</code> range instead of <code>0-255</code> <code>int</code> range for the RGB scale.</p>
</div>

<p>After the material is created and color is set it have to be updated so our changes are going to be applied. Then all we need is to set the <code>box</code>'s material to the newly created <code>boxMaterial</code>.</p>

<p>Congratulations, you've created your first object in a 3D environment using PlayCanvas! It was easier than you thought, right? Here's how it should look:</p>

<p><img alt="Blue cube on a gray background rendered with PlayCanvas." src="https://mdn.mozillademos.org/files/12247/cube-playcanvas.png" style="height:430px; width:600px" /></p>

<p>And here's the code we have created so far:</p>

<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/cqs6pg3x/","","350")}}</p>

<p>You can also <a href="https://github.com/end3r/MDN-Games-3D/blob/gh-pages/PlayCanvas/cube.html">check it out on GitHub</a>.</p>

<h3>More shapes</h3>

<p>Now we will add more shapes to the scene. Let's move the cube 2 units to the left to make space for some friends — add the following line just below the previous one:</p>

<pre class="brush: js">
box.translate(-2, 0, 0);
</pre>

<p>Now let's add a new shape - how about a cylinder?</p>

<h4>Cylinder</h4>

<p>Add the following lines to your JavaScript code:</p>

<pre class="brush: js">
var cylinder = new pc.Entity();
cylinder.addComponent("model", { type: "cylinder" });
app.root.addChild(cylinder);
cylinder.rotate(15, 0, 0);
</pre>

<p>It looks very similar to creating a cube, but instead of the <code>box</code> component we are adding a <code>cylinder</code>. It is also rotated on the <code>x</code> axis to show it's actually a 3D shape. To make the cylinder have a color, let's say yellow, we need to create the material for it.</p>

<pre class="brush: js">
var cylinderMaterial = new pc.PhongMaterial();
cylinderMaterial.diffuse.set(1, 0.58, 0);
cylinderMaterial.update();
cylinder.model.model.meshInstances[0].material = cylinderMaterial;
</pre>

<p>It looks and works the same as the one we have created for the cube, but with a different color.</p>

<h4>Cone</h4>

<p>Creating a cone and its material looks almost exacly the same as the cylinder.</p>

<pre class="brush: js">
var cone = new pc.Entity();
cone.addComponent("model", { type: "cone" });
app.root.addChild(cone);
cone.translate(2, 0, 0);

var coneMaterial = new pc.PhongMaterial();
coneMaterial.diffuse.set(0.9, 0.9, 0.9);
coneMaterial.update();
cone.model.model.meshInstances[0].material = coneMaterial;
</pre>

<p>The code above will create a new <code>cone</code>, add it to the <code>app</code> and move it by 2 units to the right so it's not interfering with the cylinder. Then the material is created, set with the gray color which is then applied, and it is assigned to the cone <code>Entity</code>.</p>

<p>Here's how it should look right now:</p>

<p><img alt="Shapes: blue cube, yellow cylinder and gray cone on a light gray background rendered with PlayCanvas." src="https://mdn.mozillademos.org/files/12249/shapes-playcanvas.png" style="height:220px; width:600px" /></p>

<p>This looks a little bit boring though. In a game something is usually happening — we can see animations and such — so let's try to breathe a little life into those shapes by animating them.</p>

<h3>Animation</h3>

<p>We already used <code>translate</code> or <code>rotate</code> to adjust the position of the shapes; we could also change thier positions directly with <code>setPosition</code>, or scale them. To show actual animation, we need to make changes to these values inside the render loop, so they are updated on every frame. There's a special <code>update</code> event that we can use for that - add the following code just below the previous one:</p>

<pre class="brush: js">
var timer = 0;
app.on("update", function (deltaTime) {
    timer += deltaTime;
    // code executed on every frame
});
</pre>

<p>It takes the <code>deltaTime</code> as the parameter, so we have the relative time that has passed since the previous invocation of this update. For time based animations we'll use a <code>timer</code> variable that will store the time that has passed since the start of the app by adding the <code>deltaTime</code> to it on every update.</p>

<h4>Rotation</h4>

<p>Rotating is quite easy — all you need to do is to add a defined value to the given direction of the rotation on each frame. Add this line of code inside the <code>app.on("update")</code> function right after the addition of the <code>deltaTime</code> to the <code>timer</code> variable:</p>

<pre class="brush: js">
box.rotate(deltaTime*10, deltaTime*20, deltaTime*3);
</pre>

<p>It will rotate the <code>box</code> by <code>deltaTime*10</code> on the <code>x</code> axis, <code>deltaTime*20</code> on the <code>y</code> axis and <code>deltaTime*30</code> on the <code>z</code> axis respectively - by doing so it will look like a smooth animation.</p>

<h4>Scaling</h4>

<p>We can also scale a given object - there's a function for that called <code>setLocalScale</code>.</p>

<pre class="brush: js">
cylinder.setLocalScale(1, Math.abs(Math.sin(timer)), 1);
</pre>

<p>This way we'll be able to use <code>Math.sin</code> and end up with quite an interesting result: this will scale the cylinder and repeat the whole process, as <code>sin</code> is a periodic function. We're wrapping the <code>y</code> scale value in <code>Math.abs</code> to pass the absolute values (greater or equal to 0), because <code>sin</code> is between -1 and 0, and for negative values the cylinder might render unexpectedly (in this case it looks black half the time).</p>

<p>Now onto the movement part.</p>

<h4>Moving</h4>

<p>Beside rotation and scaling we can also move objects around the scene. Add the following code to achieve that.</p>

<pre class="brush: js">
cone.setPosition(2, Math.sin(timer*2), 0);
</pre>

<p>This will move the <code>cone</code> up and down by applying the <code>sin</code> value to the <code>y</code> axis on each frame, with a little bit of adjustment to make it look cooler. Try changing the value to see how it affects the animations.</p>

<h3>Conclusion</h3>

<p>Here's the final piece of the code:</p>

<p>{{JSFiddleEmbed("https://jsfiddle.net/end3r/auvcLoc4/","","350")}}</p>

<p>You can also <a href="https://github.com/end3r/MDN-Games-3D/blob/gh-pages/PlayCanvas/shapes.html">see it on GitHub</a> and <a href="https://github.com/end3r/MDN-Games-3D/">fork the repository</a> if you want to play with it yourself locally. Now you know the basics of PlayCanvas engine, congatulations!</p>

<h2>PlayCanvas Editor</h2>

<p>Instead of coding everything from scratch you can also use the online editor. It might be a lot easier for you if you don't like to code. The PlayCanvas Editor is free - all you have to do is register your account and login.</p>

<p>TODO: EDITOR INSTRUCTIONS, SUMMARY</p>
Revert to this revision