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 996069 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: 996069
  • Created:
  • Creator: chrisdavidmills
  • Is current revision? No
  • Comment

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 with up to 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 has a few well-known demos published that showcase its possibilities.

  • Tanx is a multiplayer tank game where you can drive your tank around, shooting at other players as you go.
  • Swooop is a flying game where you pilot your plane around a magical island, collecting jewels and fuel as you go.
  • Visualizations like the Star Lord and BMW i8 also take advantage of the engine and showcase what's possible.

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

Note: Check out the list of featured demos to find more examples.

Engine vs editor

The engine itself can be used as a standard library by including its JavaScript file directly in your HTML, so you can start coding right away; in addition the PlayCanvas toolset comes with an online editor that you can use to drag and drop components onto the scene — a great way to create games and other apps requiring scenes if you're more of a designer than a coder. Those approaches are different, but work equally well in terms of achieving end goals.

PlayCanvas engine

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

PlayCanvas engine repository on GitHub.

We will try putting together a simple demo first — a cube rendered on the screen. If you have already worked through our Building up a basic demo with Three.js article (or you are familiar with other 3D libraries) you'll notice that PlayCanvas works on similar concepts: camera, light and objects.

Environment setup

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

  • Making sure you are using a modern browser with good WebGL support, such as the latest Firefox or Chrome.
  • Creating a directory to store your experiments in.
  • Saving a copy of the latest PlayCanvas engine inside your directory.
  • Opening 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="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 {{htmlelement("title")}}, and some CSS to set the width and height of the {{htmlelement("canvas")}} element that PlayCanvas will use to 100% so that it will fill the entire available viewport space. The first {{htmlelement("script")}} element includes the PlayCanvas library in the page; we will write our example code in the second one. There is one helper variable already included, which will store a reference to the {{htmlelement("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 {{htmlelement("canvas")}} element), and then start the update loop. Add the following code to the bottom of your second {{htmlelement("script")}} element:

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

The pc global object contains all the PlayCanvas functions available in the engine.

Next, we'll set the Canvas to fill the window, and automatically change its resolution to be the same as the Canvas size. Again, add the following lines at the bottom of your script.

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

Camera

Now when the setup code is in place we need to think about implementing the standard scene components: camera, lights and objects. Let's start with the camera — add these lines to your code, below the previous 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 — the color will be visible as the background. Next, 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. This allows us to make some space to visualize 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 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 following 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 an Entity with the box model component and add it to the root of the application, our scene. We also rotate the box a bit to show that it's actually a 3D cube and not a square.

The cube is visible, but it is completely. To make it look better we need 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; this 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 the following 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 give it it's own color —we'll choose a nice familiar blue.

Note: In PlayCanvas, the color channel values are provided as floats in the range 0-1, instead of integers of 0-255 as you might be used to using on the Web.

After the material is created and its color is set, it has to be updated so our changes are going to be applied. Then all we need to do is 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 code:

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

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

Cylinder

Add the following lines at the bottom of your JavaScript code:

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

This looks very similar to the code we used for creating a cube, but instead of the box component we are adding a cylinder. It is also rotated around 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, as before. Add the following lines:

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

Cone

Creating a cone and its material is done in almost exacly the same way as we did for the cylinder. Add the following code, again, at the bottom of your script:

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 overlapping the cylinder. Then the material is created, given a gray color, and 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 works, but it is a bit boring. 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 their positions directly with setPosition, or scale them. To show actual animation, we need to make changes to these values inside the rendering 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 additions:

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

The callback 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 rotation on each frame. Add this line of code inside the app.on("update") callback function, right after the addition of the deltaTime to the timer variable:

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

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, on very frame — giving us a smooth animation.

Scaling

We can also scale a given object — there's a function for that called setLocalScale. Add the following, again into the callback:

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

Here we are using Math.sin to scale the cylinder in a cycle, bigger and smaller again. We're wrapping the y scale value in Math.abs to pass the absolute values (greater or equal to 0); sin varies between -1 and 0, and for negative values the cylinder scaling can 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 animation.

Conclusion

Here's the final code listing, along with a viewable live example:

{{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; happy experimentation!

The PlayCanvas editor

Instead of coding everything from scratch you can also use the online editor. This can be a more pleasent working environment if you are not someone who likes to code.

Creating an account

The PlayCanvas Editor is free — all you have to do to begin with is register your account and login:

PlayCanvas Editor - Login

When you first sign up, you are taken straight into the editor and given a simple starter tutorial involving editing a 3D rolling ball game. You can finish this before you continue our tutorial if you like. When you are ready to continue with our tutorial, go to your canvas homepage — for example mine is https://playcanvas.com/end3r. Here's what the page looks like — you can create projects and manage them, change their settings etc.

Creating a new project

Start a brand new project by clicking on the New button:

PlayCanvas Editor - Panel

The resulting dialog box will show a few different options. There are starter kits available, but we don't want to load models or start a platform game.

  1. We want to start small, so we will use the empty project — click on the Blank Project option and enter a name for it (we are using "MDN Games demo".)
  2. Enter a description if you want — it is optional.
  3. Click Create to have it created.

PlayCanvas Editor - New project

Next you'll see your 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. Do this now.

PlayCanvas Editor - Project

Creating the scene

Here's how the scene looks initially 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 - Scene

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 any object used in the scene — it cna be an object like a box, cylinder or cone, but it 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 Box — it will be added to the scene.

PlayCanvas Editor - New box

The box is 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 - Box

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 in the Assets tab, and click on the Material option in the dropdown list that appears to create a new material.

PlayCanvas Editor - New material

Click on your new material in the assets tab and its entity inspector will appear on the right hand side of the display. Now edit the Name text field to give it a unique name (we've chosen boxMaterial). A unique name will help us remember what this material is for — we will add more later!

PlayCanvas Editor - Box material

To change its color we'll use the Diffuse option in the entity inspector. Click Diffuse, then select the colored box next to the Color label — it will open a color wheel. From here you can click your desired color or enter it in the bottom text field as a hex value. We've chosen a blue color with a hex value of 0095DD — enter this code in the text field and press return for it to be accepted.

Note: Yes, you read that right — you need to enter the hex value without the hash/pound symbol.

PlayCanvas Editor - Diffuse color

Now we can apply the colored material to the shape by clicking and dragging its icon from the bottom part of the screen (the little dot on the left hand side of the material's name — it can be a bit fiddly to select; just persevere) onto the box on the scene.

PlayCanvas Editor - Box drop

So, at this point we've created a blue box. Click on the box to bring up its entity sidebar — you'll see options for changing its position, rotation, and scale. Try applying the rotation values X: 10 and Y: 20.

PlayCanvas Editor - Rotate

Now 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 tab.

PlayCanvas Editor - Launch

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

PlayCanvas Editor - Boxrender

Adding more shapes

To make way for more shapes, move the box to the left to make some room for the next shape. You can do this by giving it an X position value of -2.

Adding other shapes involves a very similar process to adding the box. Click on the Root folder in the hierarchy panel (to make sure that the new shape appears in the root, and not as a child of the Box) then Click on the big Add Entity (plus) button and select cylinder from the dropdown list — it will add a new cylinder shape to the scene.

PlayCanvas Editor - CylinderNow follow the same steps as we did before when coloring the cube:

  • Create a new material using the Add Asset (plus) button.
  • Make sure the New Material in the Assets panel is selected, to bring up the entity inspector.
  • Give the material a new name, along the lines of cylinderMaterial.
  • Click diffuse, then click the color picker — give it an orange color (we used FF9500.)
  • Drag and drop the cylinderMaterial icon onto the cylinder object on the sceene to apply that color.

PlayCanvas Editor - Cylinder material

Follow the same approach again to add a cone to the scene, giving it a grayish color (we used EAEFF2.) You should now have three shapes on your scene, something like the below screenshot.

PlayCanvas Editor - Cone

Animating our scene

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 to do that. Click on the plus button in the Assets panel, select the Script option, and name your new script file boxAnimation.js.

PlayCanvas Editor - Box animation

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, which is where we can put any code that we want repeated on every frame. Add the following line inside this function, to rotate the cube on every frame:

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); using the dt variable, which contains the delta time passed since the previous frame, we can rotate the box by a different amount around all three axes.

  1. Save the changes using the Save button in the top right of the code editor, then return to the main editor tab. Here, follow these steps:
  2. Be sure you have the box selected on the scene.
  3. Click on Add component, then Script in the entity inspector.
  4. At the bottom of the screen you can see 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

The cylinder

Now we'll do the same steps for cylinder. First:

  1. Create a new Script asset.
  2. Name it cylinderAnimation.js.
  3. Double click the script icon to launch the code editor.

This time instead of rotating the object we will try to scale it. For that we'll need a timer to store 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 applies 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, giving it as a value the Math.sin() of the timer, with Math.abs() applied to the result of that to have the values always above zero (0-1; sin values are normally between -1 and 1.) This gives us a nice scaling effect as a result.

Remember to add the cylinderAnimation.js file to the Cylinder object to apply the given animations.

The cone

Time to play with the last object — the cone. Create a coneAnimation.js file and double click it to open it in the editor.

Next, add the following line to the initialize() function:

this.timer = 0;

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 on each frame by being passed the Math.sin() value of the timer at each point in time — we have doubled the this.timer value to make it move higher.

Add the coneAnimation.js script to the cone object, as before.

Test the demo out

Launch the demo to see the effects — all the shapes should animate. Congratulations, you've completed the tutorial!

PlayCanvas Editor - Shapes

Summary

Of course it depends on your approach — designers may favor the online editor while programmers will prefer having the full control over the coding environment and will probably use the engine's source files. The good thing is that you have a choice and can pick whatever tools suits you best.

Revision Source

<p class="summary"><span class="seoSummary"><strong>PlayCanvas</strong> 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 online and good <a href="https://developer.playcanvas.com/en/">documentation</a>.</span> It is free for public projects with up to 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="display:block; height:242px; margin:0px auto; width:600px" /></p>

<h2 id="Games_and_demos">Games and demos</h2>

<p>PlayCanvas has a few well-known demos published that showcase its possibilities.</p>

<ul>
 <li><a href="https://playcanv.as/p/aP0oxhUr">Tanx</a> is a multiplayer tank game where you can drive your tank around, shooting at other players as you go.</li>
 <li><a href="https://playcanv.as/p/JtL2iqIH">Swooop</a> is a flying game where you pilot your plane around a magical island, collecting jewels and fuel as you go.</li>
 <li>Visualizations like the <a href="https://playcanv.as/b/FQbBsJTd">Star Lord</a> and <a href="https://playcanv.as/p/RqJJ9oU9">BMW i8</a> also take advantage of the engine and showcase what's possible.</li>
</ul>

<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="display:block; height:400px; margin:0px auto; width:600px" /></p>

<div class="note">
<p><strong>Note</strong>: Check out the list of <a href="https://playcanvas.com/explore">featured demos</a> to find more examples.</p>
</div>

<h2 id="Engine_vs_editor">Engine vs editor</h2>

<p>The engine itself can be used as a standard library by including its JavaScript file directly in your HTML, so you can start coding right away; in addition the PlayCanvas toolset comes with an online editor that you can use to drag and drop components onto the scene — a great way to create games and other apps requiring scenes if you're more of a designer than a coder. Those approaches are different, but work equally well in terms of achieving end goals.</p>

<h2 id="PlayCanvas_engine">PlayCanvas engine</h2>

<p>Built for modern browsers, PlayCanvas is a fully-featured 3D game engine with resource loading, an entity and component system, advanced graphics manipulation, collision and physics engine (built with <a href="https://github.com/kripken/ammo.js/">ammo.js</a>), audio, and facilities to handle control inputs 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="display:block; height:380px; margin:0px auto; width:600px" /></p>

<p>We will try putting together a simple demo first — a cube rendered on the screen. If you have already worked through our <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 (or you are familiar with other 3D libraries) you'll notice that PlayCanvas works on similar concepts: camera, light and objects.</p>

<h3 id="Environment_setup">Environment setup</h3>

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

<ul>
 <li>Making 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>Creating a directory to store your experiments in.</li>
 <li>Saving a copy of the <a href="https://code.playcanvas.com/playcanvas-latest.js">latest PlayCanvas engine</a> inside your directory.</li>
 <li>Opening 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="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 {{htmlelement("title")}}, and some CSS to set the width and height of the {{htmlelement("canvas")}} element that PlayCanvas will use to 100% so that it will fill the entire available viewport space. The first {{htmlelement("script")}} element includes the PlayCanvas library in the page; we will write our example code in the second one. There is one helper variable already included, which will store a reference to the {{htmlelement("canvas")}} 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 {{htmlelement("canvas")}} element), and then start the update loop. Add the following code to the bottom of your second {{htmlelement("script")}} element:</p>

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

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

<p>Next, we'll set the Canvas to fill the window, and automatically change its resolution to be the same as the Canvas size. Again, add the following lines at the bottom of your script.</p>

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

<h3 id="Camera">Camera</h3>

<p>Now when the setup code is in place we need to think about implementing the standard scene components: camera, lights and objects. Let's start with the camera — add these lines to your code, below the previous 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> — the color will be visible as the background. Next, 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. This allows us to make some space to visualize 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 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 following 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 an <code>Entity</code> with the <code>box</code> model component and add it to the root of the application, our scene. We also rotate the box a bit to show that it's actually a 3D cube and not a square.</p>

<p>The cube is visible, but it is completely. To make it look better we need 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; this 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 the following 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 give it it's own color —we'll choose a nice familiar blue.</p>

<div class="note">
<p><strong>Note</strong>: In PlayCanvas, the color channel values are provided as floats in the range <code>0-1</code>, instead of integers of <code>0-255</code> as you might be used to using on the Web.</p>
</div>

<p>After the material is created and its color is set, it has to be updated so our changes are going to be applied. Then all we need to do is 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="display:block; height:430px; margin:0px auto; 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 code:</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 at the bottom of 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>This looks very similar to the code we used for creating a cube, but instead of the <code>box</code> component we are adding a <code>cylinder</code>. It is also rotated around 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, as before. Add the following lines:</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>

<h4 id="Cone">Cone</h4>

<p>Creating a cone and its material is done in almost exacly the same way as we did for the cylinder. Add the following code, again, at the bottom of your script:</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 overlapping the cylinder. Then the material is created, given a gray color, and 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="display:block; height:220px; margin:0px auto; width:600px" /></p>

<p>This works, but it is a bit boring. 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 their positions directly with <code>setPosition</code>, or scale them. To show actual animation, we need to make changes to these values inside the rendering 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 additions:</p>

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

<p>The callback 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 rotation on each frame. Add this line of code inside the <code>app.on("update")</code> callback 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*30);
</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, on very frame — giving us 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>. Add the following, again into the callback:</p>

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

<p>Here we are using <code>Math.sin</code> to scale the cylinder in a cycle, bigger and smaller again. We're wrapping the <code>y</code> scale value in <code>Math.abs</code> to pass the absolute values (greater or equal to 0); <code>sin</code> varies between -1 and 0, and for negative values the cylinder scaling can 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 animation.</p>

<h3 id="Conclusion">Conclusion</h3>

<p>Here's the final code listing, along with a viewable live example:</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; happy experimentation!</p>

<h2 id="PlayCanvas_Editor">The PlayCanvas editor</h2>

<p>Instead of coding everything from scratch you can also use the online editor. This can be a more pleasent working environment if you are not someone who likes to code.</p>

<h3>Creating an account</h3>

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

<p><img alt="PlayCanvas Editor - Login" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-login.png" style="display:block; margin:0px auto" /></p>

<p>When you first sign up, you are taken straight into the editor and given a simple starter tutorial involving editing a 3D rolling ball game. You can finish this before you continue our tutorial if you like. When you are ready to continue with our tutorial, go to your canvas homepage — for example mine is <code>https://playcanvas.com/end3r</code>. Here's what the page looks like — you can create projects and manage them, change their settings etc.</p>

<h3>Creating a new project</h3>

<p>Start a brand new project by clicking on the <em>New</em> button:</p>

<p><img alt="PlayCanvas Editor - Panel" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-panel.png" style="display:block; margin:0px auto" /></p>

<p>The resulting dialog box will show a few different options. There are starter kits available, but we don't want to load models or start a platform game.</p>

<ol>
 <li>We want to start small, so we will use the empty project — click on the Blank Project option and enter a name for it (we are using "MDN Games demo".)</li>
 <li>Enter a description if you want — it is optional.</li>
 <li>Click <em>Create</em> to have it created.</li>
</ol>

<p><img alt="PlayCanvas Editor - New project" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-newproject.png" style="display:block; margin:0px auto" /></p>

<p>Next you'll see your project's page — there's not much yet. By clicking the <em>Editor</em> button we'll launch the online PlayCanvas editor where we'll create our scene with the shapes. Do this now.</p>

<p><img alt="PlayCanvas Editor - Project" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-project.png" style="display:block; margin:0px auto" /></p>

<h3>Creating the scene</h3>

<p>Here's how the scene looks initially 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 - Scene" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-scene.png" style="display:block; margin:0px auto" /></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 any object used in the scene — it cna be an object like a box, cylinder or cone, but it 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 <em>Box</em> — it will be added to the scene.</p>

<p><img alt="PlayCanvas Editor - New box" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-newbox.png" style="display:block; margin:0px auto" /></p>

<p>The box is 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 - Box" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-box.png" style="display:block; margin:0px auto" /></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 in the <em>Assets</em> tab, and click on the <em>Material</em> option in the dropdown list that appears to create a new material.</p>

<p><img alt="PlayCanvas Editor - New material" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-newmaterial.png" style="display:block; margin:0px auto" /></p>

<p>Click on your new material in the assets tab and its entity inspector will appear on the right hand side of the display. Now edit the <em>Name</em> text field to give it a unique name (we've chosen <em>boxMaterial</em>). A unique name will help us remember what this material is for — we will add more later!</p>

<p><img alt="PlayCanvas Editor - Box material" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxmaterial.png" style="display:block; margin:0px auto" /></p>

<p>To change its color we'll use the <em>Diffuse</em> option in the entity inspector. Click <em>Diffuse</em>, then select the colored box next to the Color label — it will open a color wheel. From here you can click your desired color or enter it in the bottom text field as a hex value. We've chosen a blue color with a hex value of <code>0095DD</code> — enter this code in the text field and press return for it to be accepted.</p>

<div class="note">
<p><strong>Note</strong>: Yes, you read that right — you need to enter the hex value without the hash/pound symbol.</p>
</div>

<p><img alt="PlayCanvas Editor - Diffuse color" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-diffusecolor.png" style="display:block; margin:0px auto" /></p>

<p>Now we can apply the colored material to the shape by clicking and dragging its icon from the bottom part of the screen (the little dot on the left hand side of the material's name — it can be a bit fiddly to select; just persevere) onto the box on the scene.</p>

<p><img alt="PlayCanvas Editor - Box drop" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxdrop.png" style="display:block; margin:0px auto" /></p>

<p>So, at this point we've created a blue box. Click on the box to bring up its entity sidebar — you'll see options for changing its position, rotation, and scale. Try applying the rotation values X: 10 and Y: 20.</p>

<p><img alt="PlayCanvas Editor - Rotate" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-rotate.png" style="display:block; margin:0px auto" /></p>

<p>Now 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 tab.</p>

<p><img alt="PlayCanvas Editor - Launch" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-launch.png" style="display:block; margin:0px auto" /></p>

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

<p><img alt="PlayCanvas Editor - Boxrender" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxrender.png" style="display:block; margin:0px auto" /></p>

<h3>Adding more shapes</h3>

<p>To make way for more shapes, move the box to the left to make some room for the next shape. You can do this by giving it an X position value of -2.</p>

<p>Adding other shapes involves a very similar process to adding the box. Click on the Root folder in the hierarchy panel (to make sure that the new shape appears in the root, and not as a child of the Box) then Click on the big <em>Add Entity</em> (plus) button and select cylinder from the dropdown list — it will add a new cylinder shape to the scene.</p>

<p><img alt="PlayCanvas Editor - Cylinder" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-cylinder.png" style="display:block; margin:0px auto" />Now follow the same steps as we did before when coloring the cube:</p>

<ul>
 <li>Create a new material using the <em>Add Asset</em> (plus) button.</li>
 <li>Make sure the New Material in the Assets panel is selected, to bring up the entity inspector.</li>
 <li>Give the material a new name, along the lines of <code>cylinderMaterial</code>.</li>
 <li>Click diffuse, then click the color picker — give it an orange color (we used FF9500.)</li>
 <li>Drag and drop the <code>cylinderMaterial</code> icon onto the cylinder object on the sceene to apply that color.</li>
</ul>

<p><img alt="PlayCanvas Editor - Cylinder material" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-cylindermaterial.png" style="display:block; margin:0px auto" /></p>

<p>Follow the same approach again to add a cone to the scene, giving it a grayish color (we used EAEFF2.) You should now have three shapes on your scene, something like the below screenshot.</p>

<p><img alt="PlayCanvas Editor - Cone" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-cone.png" style="display:block; margin:0px auto" /></p>

<h3>Animating our scene</h3>

<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 to do that. Click on the plus button in the Assets panel, select the Script option, and name your new script file <code>boxAnimation.js</code>.</p>

<p><img alt="PlayCanvas Editor - Box animation" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxanimation.png" style="display:block; margin:0px auto" /></p>

<p>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 <code>update()</code> function, which is where we can put any code that we want repeated on every frame. Add the following line inside this function, to rotate the cube on every frame:</p>

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

<p>In the line above <code>this.entity</code> refers to the object to which the script will be attached (the box); using the <code>dt</code> variable, which contains the delta time passed since the previous frame, we can rotate the box by a different amount around all three axes.</p>

<ol>
 <li>Save the changes using the Save button in the top right of the code editor, then return to the main editor tab. Here, follow these steps:</li>
 <li>Be sure you have the box selected on the scene.</li>
 <li>Click on <em>Add component</em>, then <em>Script</em> in the entity inspector.</li>
 <li>At the bottom of the screen you can see the list of scripts available — for now there's only <code>boxAnimation.js</code> — clicking it will add the animation script to the box object.</li>
</ol>

<p><img alt="PlayCanvas Editor - Box script" src="https://enclavegames.com/_tmp/pc-mdn/playcanvas-editor-boxscript.png" style="display:block; margin:0px auto" /></p>

<h4>The cylinder</h4>

<p>Now we'll do the same steps for cylinder. First:</p>

<ol>
 <li>Create a new Script asset.</li>
 <li>Name it <code>cylinderAnimation.js</code>.</li>
 <li>Double click the script icon to launch the code editor.</li>
</ol>

<p>This time instead of rotating the object we will try to scale it. For that we'll need a timer to store the total amount of time passed since the start of the animation. Add this code to the <code>initialize()</code> function:</p>

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

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

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

<p>The <code>setLocalScale()</code> method applies 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, giving it as a value the <code>Math.sin()</code> of the timer, with <code>Math.abs()</code> applied to the result of that to have the values always above zero (0-1; sin values are normally between -1 and 1.) This gives us a nice scaling effect as a result.</p>

<p>Remember to add the <code>cylinderAnimation.js</code> file to the Cylinder object to apply the given animations.</p>

<h4>The cone</h4>

<p>Time to play with the last object — the cone. Create a <code>coneAnimation.js</code> file and double click it to open it in the editor.</p>

<p>Next, add the following line to the <code>initialize()</code> function:</p>

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

<p>To move the cone up and down we will use the <code>setPosition()</code> method — add the code below to the <code>update()</code> 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 on each frame by being passed the <code>Math.sin()</code> value of the <code>timer</code> at each point in time — we have doubled the <code>this.timer</code> value to make it move higher.</p>

<p>Add the <code>coneAnimation.js</code> script to the cone object, as before.</p>

<h3>Test the demo out</h3>

<p>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" style="display:block; margin:0px auto" /></p>

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

<p>Of course it depends on your approach — designers may favor the online editor while programmers will prefer having the full control over the coding environment and will probably use the engine's source files. The good thing is that you have a choice and can pick whatever tools suits you best.</p>
Revert to this revision