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 995891 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: 995891
  • Created:
  • Creator: chrisdavidmills
  • Is current revision? No
  • Comment Technical review completed. Editorial review completed.

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.

PlayCanvas website.

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.

A list of PlayCanvas demos: Tanx, Swooop, Star Lord, BMW i8.

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.

PlayCanvas engine repository on GitHub.

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.

PlayCanvas Editor - Login

The PlayCanvas Editor is free - all you have to do is register your account and login.

PlayCanvas Editor - Panel

Here's how the panel looks like - you can create projects and manage them, change their settings etc. To start with the brand new project click on Create a Project button.

PlayCanvas Editor - New project

It will show a modal window with a few options to choose from. There are starter kits available, but we don't want to load models or start a platformer game. We want to start small, so we will use the empty project - click on the Blank Project option and enter the name, in our case "MDN Games demo", and the optional description. The project is public by default. Click Create to have it created.

PlayCanvas Editor - Project

This is our project's page - there's not much yet. By clicking the Editor button we'll launch the online PlayCanvas editor where we'll create our scene with the shapes.

PlayCanvas Editor - Scene

Here's how the scene looks in the editor. Even though it's a blank new project we don't have to start entirely from scratch - the camera and directional light are prepared already, so you don't have to worry about them.

PlayCanvas Editor - New box

Now onto the creative part. To add an entity to the scene you have to click on the big plus button located in the top left area of the editor, next to the Hierarchy text. When hovering over that button with your mouse the label will say 'Add Entity' - that's exactly what we want to do. An Entity is an object - a box, cylinder or cone, but can also be a camera, light or sound source. After clicking the button you'll see a dropdown list containing a lot of various entities to choose from. Go ahead and click the Box - it will be added to the scene.

PlayCanvas Editor - Box

The box was created with the default values - width, height and depth are set to 1, and it is placed in the middle of the scene. You can drag it around or apply new values in the right panel.

PlayCanvas Editor - New material

To add some colors to the scene we need a new material that will be used on the newly created box. Click on the plus button next to the "Assets" text - the dropdown list will appear. Now click on the "Material" to create it.

PlayCanvas Editor - Box material

We've named it boxMaterial to remember what it's for as we plan on creating more of those materials for other shapes that we'll add to the scene in the next steps.

PlayCanvas Editor - Diffuse color

To change its color we'll use the Diffuse option in the panel on the right. Click Diffuse, then select the colored box next to the Color label - it will open a colorwheel. From here you can select desired color or enter your own as a hex value. In our case it's a blue color with a hex value of #0095DD.

PlayCanvas Editor - Box drop

After the color is confirmed by hitting the Enter key or clicking anywhere outside the colorwheel we can apply the colored material onto the shape by dragging and dropping it's icon from the bottom part of the screen onto the box on the scene.

PlayCanvas Editor - Rotate

You've created a blue box, congratulations! Remember the right sidebar with all those values to play with? Try applying the rotation from the first part of the article where we did it in the source code. Here, it's all about changing the X and Y values in the Rotation section of the selected entity. There are also options on changing the position and scale, but we'll get to them later.

PlayCanvas Editor - Launch

Click on the play arrow in the top right corner of the scene to launch and render the scene - it will be opened in a separate browser window.

PlayCanvas Editor - Boxrender

It looks perfect! Let's add more shapes to the scene to make it look more interesting.

PlayCanvas Editor - Cylinder

First, move the box to the left to make some room for the next shape. You can do it by applying the X position of the box with the value of -2. Adding other shapes is very similar to adding the box. Click on the big plus button and select cylinder from the dropdown list - it will add a new shape, cylinder, to the scene.

PlayCanvas Editor - Cylinder material

Now follow the similar steps of creating a material and make it orange, #FF9500 to be exact. By dropping the cylinderMaterial icon onto the cylinder object on the scene you'll apply that color.

PlayCanvas Editor - Cone

Follow the same approach and try adding a cone yourself, and give it a grayish #EAEFF2 color - awesome, congratulations! To make it even better let's add some animations and move the shapes around.

PlayCanvas Editor - Box animation

Animating 3D models might be considered an advanced thing to do, but all we want to do is to control a few properties of a given object - we can use a script component for that instead. Click on the plus button next to the Assets text at the bottom of the screen, click the Script option and name the file boxAnimation.js. If you double click on it, you'll be moved to a code editor. As you can see, the file contains some boilerplate code already:

pc.script.create('boxAnimation', function (app) {
    // Creates a new BoxAnimation instance
    var BoxAnimation = function (entity) {
        this.entity = entity;
    };

    BoxAnimation.prototype = {
        // Called once after all resources are loaded and before the first update
        initialize: function () {
        },

        // Called every frame, dt is time in seconds since last update
        update: function (dt) {
        }
    };

    return BoxAnimation;
});

The most interesting part is the update function where we'll be able to affect the box's rotation on every frame. Add this line inside the function:

this.entity.rotate(dt*10, dt*20, dt*30);

In the line above this.entity refers to the object to which the script will be attached (the box) and using the dt variable which contains the delta time passed since the previous frame we can rotate the box in all three axes by a different amount. Save the changes using the Save button on the top right and return to the editor tab. Be sure you have the box selected on the scene and click on the Add script option in the right sidebar. It will show you the list of scripts available - for now there's only boxAnimation.js. Clicking it will add the animation script to the box object.

PlayCanvas Editor - Box script

Do the same steps for cylinder: create new Script asset, name it cylinderAnimation.js, and double click to launch the code editor. This time instead of rotating an object we will try to scale it. For that we'll need a timer to have the total amount of time passed since the start of the animation. Add this code to the initialize function:

this.timer = 0;

And those two lines to the update function:

this.timer += dt;
this.entity.setLocalScale(1, Math.abs(Math.sin(this.timer)), 1);

The setLocalScale method is applying the given values to the X, Y and Z axes of the object. In our case we're modifying the scale of the cylinder on the Y axis using the Math.sin on the timer and applying Math.abs to have the values always above zero (0-1), because sin wave values are normally between -1 and 1. This gives us a very nice scaling effect as a result. Remember to add the cylinderAnimation.js file to the Cylinder object to apply the given animations.

Time to play with the last object - the cone. Create the coneAnimation.js file and add this.timer = 0; to the initialize function. To move the cone up and down we will use the setPosition method - add the code below to the update function:

this.timer += dt;
this.entity.setPosition(2, Math.sin(this.timer*2), 0);

The position of the cone will be animated using the Math.sin - we can double this.timer values to have it move higher. Launch the demo to see the effects - all the shapes should animate. Congratulations, you've completed the tutorial!

PlayCanvas Editor - Shapes

It works like a charm - everything is animated exactly the same way as we did it using the engine JavaScript file, and it was easier and more fun to do with the editor.

Summary

Of course it depends on your approach - designers may favor the online editor while programmers prefer having the full control over the coding environment and will use the engine's source files. The good thing is that you have a choice and can pick whatever tools suits you best. It doesn't matter what tools you choose - you should feel comfortable with them, because every framework may be good enough for making games if you can use it to actually make games.

Revision Source

<p class="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>

<p><img alt="PlayCanvas website." src="https://mdn.mozillademos.org/files/12251/playcanvas-cover.png" style="height: 242px; width: 600px;"></p>

<h2 id="Games_and_demos">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>

<p><img alt="A list of PlayCanvas demos: Tanx, Swooop, Star Lord, BMW i8." src="https://mdn.mozillademos.org/files/12253/playcanvas-demos.png" style="height: 400px; width: 600px;"></p>

<h2 id="Engine_vs_editor">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 id="PlayCanvas_engine">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>

<p><img alt="PlayCanvas engine repository on GitHub." src="https://mdn.mozillademos.org/files/12257/playcanvas-github.png" style="height: 380px; width: 600px;"></p>

<h3 id="The_engine_demo">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 id="Environment_setup">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 id="HTML_structure">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 id="PlayCanvas_application">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 id="Camera">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 id="Geometry">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 id="Lights">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 id="Material">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 id="More_shapes">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 id="Cylinder">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 id="Cone">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 id="Animation">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 id="Rotation">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 id="Scaling">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 id="Moving">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 id="Conclusion">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 id="PlayCanvas_Editor">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.</p>

<p><img alt="PlayCanvas Editor - Login" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-login.png"></p>

<p>The PlayCanvas Editor is free - all you have to do is <a href="https://login.playcanvas.com/signup">register</a> your account and login.</p>

<p><img alt="PlayCanvas Editor - Panel" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-panel.png"></p>

<p>Here's how the panel looks like - you can create projects and manage them, change their settings etc. To start with the brand new project click on Create a Project button.</p>

<p><img alt="PlayCanvas Editor - New project" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-newproject.png"></p>

<p>It will show a modal window with a few options to choose from. There are starter kits available, but we don't want to load models or start a platformer game. We want to start small, so we will use the empty project - click on the Blank Project option and enter the name, in our case "MDN Games demo", and the optional description. The project is public by default. Click Create to have it created.</p>

<p><img alt="PlayCanvas Editor - Project" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-project.png"></p>

<p>This is our project's page - there's not much yet. By clicking the Editor button we'll launch the online PlayCanvas editor where we'll create our scene with the shapes.</p>

<p><img alt="PlayCanvas Editor - Scene" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-scene.png"></p>

<p>Here's how the scene looks in the editor. Even though it's a blank new project we don't have to start entirely from scratch - the camera and directional light are prepared already, so you don't have to worry about them.</p>

<p><img alt="PlayCanvas Editor - New box" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-newbox.png"></p>

<p>Now onto the creative part. To add an entity to the scene you have to click on the big plus button located in the top left area of the editor, next to the Hierarchy text. When hovering over that button with your mouse the label will say 'Add Entity' - that's exactly what we want to do. An Entity is an object - a box, cylinder or cone, but can also be a camera, light or sound source. After clicking the button you'll see a dropdown list containing a lot of various entities to choose from. Go ahead and click the Box - it will be added to the scene.</p>

<p><img alt="PlayCanvas Editor - Box" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-box.png"></p>

<p>The box was created with the default values - width, height and depth are set to 1, and it is placed in the middle of the scene. You can drag it around or apply new values in the right panel.</p>

<p><img alt="PlayCanvas Editor - New material" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-newmaterial.png"></p>

<p>To add some colors to the scene we need a new material that will be used on the newly created box. Click on the plus button next to the "Assets" text - the dropdown list will appear. Now click on the "Material" to create it.</p>

<p><img alt="PlayCanvas Editor - Box material" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxmaterial.png"></p>

<p>We've named it boxMaterial to remember what it's for as we plan on creating more of those materials for other shapes that we'll add to the scene in the next steps.</p>

<p><img alt="PlayCanvas Editor - Diffuse color" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-diffusecolor.png"></p>

<p>To change its color we'll use the Diffuse option in the panel on the right. Click Diffuse, then select the colored box next to the Color label - it will open a colorwheel. From here you can select desired color or enter your own as a hex value. In our case it's a blue color with a hex value of #0095DD.</p>

<p><img alt="PlayCanvas Editor - Box drop" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxdrop.png"></p>

<p>After the color is confirmed by hitting the Enter key or clicking anywhere outside the colorwheel we can apply the colored material onto the shape by dragging and dropping it's icon from the bottom part of the screen onto the box on the scene.</p>

<p><img alt="PlayCanvas Editor - Rotate" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-rotate.png"></p>

<p>You've created a blue box, congratulations! Remember the right sidebar with all those values to play with? Try applying the rotation from the first part of the article where we did it in the source code. Here, it's all about changing the X and Y values in the Rotation section of the selected entity. There are also options on changing the position and scale, but we'll get to them later.</p>

<p><img alt="PlayCanvas Editor - Launch" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-launch.png"></p>

<p>Click on the play arrow in the top right corner of the scene to launch and render the scene - it will be opened in a separate browser window.</p>

<p><img alt="PlayCanvas Editor - Boxrender" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxrender.png"></p>

<p>It looks perfect! Let's add more shapes to the scene to make it look more interesting.</p>

<p><img alt="PlayCanvas Editor - Cylinder" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-cylinder.png"></p>

<p>First, move the box to the left to make some room for the next shape. You can do it by applying the X position of the box with the value of -2. Adding other shapes is very similar to adding the box. Click on the big plus button and select cylinder from the dropdown list - it will add a new shape, cylinder, to the scene.</p>

<p><img alt="PlayCanvas Editor - Cylinder material" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-cylindermaterial.png"></p>

<p>Now follow the similar steps of creating a material and make it orange, #FF9500 to be exact. By dropping the cylinderMaterial icon onto the cylinder object on the scene you'll apply that color.</p>

<p><img alt="PlayCanvas Editor - Cone" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-cone.png"></p>

<p>Follow the same approach and try adding a cone yourself, and give it a grayish #EAEFF2 color - awesome, congratulations! To make it even better let's add some animations and move the shapes around.</p>

<p><img alt="PlayCanvas Editor - Box animation" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxanimation.png"></p>

<p>Animating 3D models might be considered an <a href="https://developer.playcanvas.com/en/tutorials/intermediate/animation-blending/">advanced</a> thing to do, but all we want to do is to control a few properties of a given object - we can use a script component for that instead. Click on the plus button next to the Assets text at the bottom of the screen, click the Script option and name the file boxAnimation.js. If you double click on it, you'll be moved to a code editor. As you can see, the file contains some boilerplate code already:</p>

<pre class="brush: js">pc.script.create('boxAnimation', function (app) {
    // Creates a new BoxAnimation instance
    var BoxAnimation = function (entity) {
        this.entity = entity;
    };

    BoxAnimation.prototype = {
        // Called once after all resources are loaded and before the first update
        initialize: function () {
        },

        // Called every frame, dt is time in seconds since last update
        update: function (dt) {
        }
    };

    return BoxAnimation;
});</pre>

<p>The most interesting part is the update function where we'll be able to affect the box's rotation on every frame. Add this line inside the function:</p>

<pre class="brush: js">this.entity.rotate(dt*10, dt*20, dt*30);</pre>

<p>In the line above this.entity refers to the object to which the script will be attached (the box) and using the dt variable which contains the delta time passed since the previous frame we can rotate the box in all three axes by a different amount. Save the changes using the Save button on the top right and return to the editor tab. Be sure you have the box selected on the scene and click on the Add script option in the right sidebar. It will show you the list of scripts available - for now there's only boxAnimation.js. Clicking it will add the animation script to the box object.</p>

<p><img alt="PlayCanvas Editor - Box script" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxscript.png"></p>

<p>Do the same steps for cylinder: create new Script asset, name it cylinderAnimation.js, and double click to launch the code editor. This time instead of rotating an object we will try to scale it. For that we'll need a timer to have the total amount of time passed since the start of the animation. Add this code to the initialize function:</p>

<pre class="brush: js">this.timer = 0;</pre>

<p>And those two lines to the update function:</p>

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

<p>The setLocalScale method is applying the given values to the X, Y and Z axes of the object. In our case we're modifying the scale of the cylinder on the Y axis using the Math.sin on the timer and applying Math.abs to have the values always above zero (0-1), because sin wave values are normally between -1 and 1. This gives us a very nice scaling effect as a result. Remember to add the cylinderAnimation.js file to the Cylinder object to apply the given animations.</p>

<p>Time to play with the last object - the cone. Create the coneAnimation.js file and add this.timer = 0; to the initialize function. To move the cone up and down we will use the setPosition method - add the code below to the update function:</p>

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

<p>The position of the cone will be animated using the Math.sin - we can double this.timer values to have it move higher. Launch the demo to see the effects - all the shapes should animate. Congratulations, you've completed the tutorial!</p>

<p><img alt="PlayCanvas Editor - Shapes" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-shapes.png"></p>

<p>It works like a charm - everything is animated exactly the same way as we did it using the engine JavaScript file, and it was easier and more fun to do with the editor.</p>

<h2 id="Summary">Summary</h2>

<p>Of course it depends on your approach - designers may favor the online editor while programmers prefer having the full control over the coding environment and will use the engine's source files. The good thing is that you have a choice and can pick whatever tools suits you best. It doesn't matter what tools you choose - you should feel comfortable with them, because every framework may be good enough for making games if you can use it to actually make games.</p>
Revert to this revision