Creating Interactive WebGL Content with Adobe Animate CC
Learn how to build interactive WebGL content using Adobe Animate CC without any prior programming knowledge.
What you will learn…
- How to publish for WebGL from Adobe Animate CC
- How to write simple timeline scripts
- How to add interactivity using code snippets
With Adobe Animate CC, designers can create content that runs seamlessly across both desktop and mobile web browsers. But what about adding interactivity to a project? Isn’t a developer required for such tasks? Not necessarily.
This tutorial will take you through Adobe Animate CC’s deisgner-developer workflow and show you how easy it is to add interactivity to your project without any prior programming knowledge.
We’ll create a prototype beat ‘em up game where our hero can perform either an attacking or blocking move. By doing so you’ll learn how to work with movie-clips and how to handle and respond to simple user interactions. Before we continue, let’s first take a look at what we’ll be building. You can see the final result here.
What you are looking at here is rich interactive vector content running in your web browser without the need for a plugin. By publishing to WebGL you are utilising modern web standards and increasing the potential reach of your content to include mobile as well as modern desktop browsers.
Getting Started
You’ll need Adobe Animate CC to work through this tutorial. A trial version can be downloaded from www.adobe.com/products/animate.html.
A web browser is required to test your work. Any WebGL-enabled browser will do. I’ll be using Google Chrome.
Finally, a WebGL document file has been prepared for you to work from and can be downloaded from github.com/ccaleb/bunny-animate-webgl-tutorial. You can find the document within the repository at: start/bunny.fla. The complete source code for this tutorial can be found within the repository’s final/ folder.
Creating a WebGL Document
If you plan to target WebGL then you’ll need to create and work with a WebGL document within Animate CC. To do this select File | New (Cmd + N | Ctrl + N) from Animate’s drop-down menu then select the WebGL (Preview) document type from the New Document panel. This is shown in Figure 1 below.
Figure 1. Selecting the WebGL (Preview) document type.
You now know how to create a WebGL document but for this tutorial there’s no need to directly create one. Instead, one has been provided for you, complete with its own graphics resources. Open bunny-animate-webgl-tutorial/start/bunny.fla within Adobe Animate CC.
Exploring the WebGL Document
Take a look at the bunny.fla file provided. On the stage you’ll find a background movie-clip containing trees and mountains (Figure 2). Within the Library panel you’ll find a few more items that we’ll make use of. Specifically you’ll find movie-clip representations for our game’s hero and two buttons.
Our hero is a kick-ass blue bunny. Its movie-clip is appropriately named Bunny. The user will control the bunny by pressing one of two buttons. The first button is used to trigger an attacking move, while the second button forces the bunny to jump out of harms way. The buttons are named Button Attack and Button Defend respectively within the library.
Figure 2. A view of the stage and the Library panel.
Let’s take a look at the Bunny movie-clip in more detail. Double-click on it to move to its timeline. The timeline contains three distinct animations (idle, punch, and jump), which are clearly marked by the following frame labels:
- idle (frame 1)
- punch (frame 64)
- jump (frame 120)
The idle animation will be used when the bunny is awaiting instructions from the users. We’ll trigger the punch animation when the user presses the attack button, and the jump animation when the defend button is pressed.
Now we’ll take a quick look at the attack button. Double-click on the Button Attack clip within the library.
As you can see, the clip spans two frames. On the first layer is the text ATTACK, which spans both frames. On the layer below is a red spot, which represents the actual button. If you move to the second frame of the timeline, you’ll see that the red spot is reduced in size on this frame. The user will be moved to this frame when they press the button, giving them valuable feedback that their interaction was detected and acted upon.
Feel free to examine the library’s Button Defend movie-clip. You’ll find it follows an identical structure to the attack button.
Adding Clips to the Stage
We’ll be making use of the Bunny, Button Attack, and Button Defend movie-clips. However, none of them are actually sitting on the stage. So let’s go ahead and put them there.
Begin by dragging the Bunny clip from Library panel onto the stage.
Use the Properties Inspector panel to precisely position the bunny. Set its X position to 123 and its Y position to 293. While you’re at it, use the Properties Inspector again to give your movie-clip an instance name of bunny. Providing an instance name will allow you to target and manipulate the bunny using JavaScript a little later on.
The bunny should now be standing roughly in the centre of the stage and your Properties Inspector panel should look like the one shown in Figure 3 below.
Figure 3. The Properties Inspector with the bunny’s position and instance name set.
Now let’s do the same for the Button Attack and Button Defend movie-clips. Position the attack button on the stage at (434, 340) and the defend button at (128, 340). Give the attack button an instance name of attack and the defend button an instance name of defend. Your stage should now look like the screenshot shown in Figure 4.
Figure 4. The bunny and buttons positioned on stage.
Save your FLA.
Publishing for WebGL
Now that we’ve set up our FLA, we can go ahead and publish it and see how things currently look in the browser.
From Adobe Animate CC’s drop-down menu, select Control | Test (Cmd + Enter | Shift + Enter). This will export your FLA for WebGL and launch the published scene within your default browser. The screenshot in Figure 5 below shows our scene being rendered within Chrome.
Figure 5. The FLA exported to WebGL and running in Chrome.
Remember, you’ll need to use a WebGL-enabled browser. Most modern browsers have WebGL enabled by default.
If you take a look at your browser’s address bar, you should notice that your content is running in a local web server, which is required in order to run WebGL content. Adobe Animate CC has a built-in web server that is run whenever you publish your content.
Your browser’s address bar should show a URL of 127.0.0.1:8090/bunny.html. The 127.0.0.1 part is an address that is often known as localhost and is used to establish a connection to a web server running locally on your computer. In our case, localhost is serving your browser with the WebGL content that you just published from Adobe Animate CC.
You should see our hero bunny standing on the screen and looping through all three of its timeline animations. Both buttons will also be looping through their timeline frames. However, we only really want the user to see the bunny’s idle animation at the moment, and we want both buttons to be stopped on their first frame.
Timeline Scripts
We can control the playhead within the timeline of any of our movie-clips by adding frame scripts. A frame script can contain one or more actions that can be used to perform tasks, such as stopping the playhead or moving it to a different frame. Frame scripts are written in JavaScript, which is easy to learn and use.
Let’s write a simple script that will loop the bunny on its idle animation.
Start by double-clicking on the Bunny movie-clip on the stage to move to its timeline. We’ll create a new timeline layer that will be used to store our bunny’s scripts. Do that by selecting Insert | Timeline | Layer from the drop-down menu. Position the new layer directly below the Labels layer and name it Actions. Figure 6 below illustrates this.
Figure 6. Creating an Actions layer within the timeline.
Now move to frame 63 within your Actions layer and insert a keyframe by selecting Insert | Timeline | Keyframe (F6) from the drop-down menu. We can now add a script to that keyframe. The Actions panel is used to add scripts. First, click on the keyframe if it’s not already selected, then open the Actions panel by selecting Window | Actions (F9) from the drop-down menu (Figure 7).
Figure 7. The Actions Panel.
With the Actions panel open, we can write a simple script that will move the timeline’s playhead back to the first frame. Type the following into the Actions panel:
this.gotoAndPlay(“idle”);
The line above uses the gotoAndPlay action to instruct the playhead to go to the frame labelled idle (frame 1) and start playing again from that point. This single line of code allows our bunny to continuously loop on its idle animation.
Let’s go ahead and add a frame script at the end of the bunny’s punch and jump animations.
Move to frame 101 and insert a new keyframe (Insert | Timeline | Keyframe). Now add the following script:
this.gotoAndPlay(“idle”);
The script is the same as before and will ensure that the bunny returns to its idle animation immediately after its punch animation has finished playing.
Finally, move to the last frame in the timeline, create a keyframe, and type the exact same script again:
this.gotoAndPlay(“idle”);
And again, this has the same effect as before. When the bunny’s jump animation ends its idle animation will start playing again.
The this Keyword
Before we continue you may have noticed the use of a property named this within each of your scripts:
this.gotoAndPlay(“idle”);
When calling certain actions, JavaScript needs some context or it won’t know what exactly you want to apply the action to. When adding scripts to a movie-clip’s timeline, the this property refers to the movie-clip instance itself. In other words, the following script:
this.gotoAndPlay(“idle”);
basically translates as:
for this instance of the bunny movie-clip, go to its idle frame and continue playing from that point onwards.
Testing Your Latest Changes
Okay, let’s see how our latest changes look when running in the browser.
Move back to the stage and double-click on the Button Attack movie-clip instance. Within it’s timeline, add a new layer and name it Actions. Remember, you can add a layer by selecting Insert | Timeline | Layer from Animate CC’s drop-down menu.
Now create a keyframe on frame 1 of the Actions layer by selecting Insert | Timeline | Keyframe (F6).
If the Actions panel isn’t visible then select Window | Actions (F9) from the drop-down menu.
Now type the following script into the Actions panel:
this.stop();
The line of JavaScript above will stop the button’s playhead from running. In other words, the attack button will be frozen on its first frame.
Stopping Playback on the Defend Button
Let’s go ahead and make exactly the same changes to the defend button.
From the stage, double-click on the Button Defend movie-clip instance.
Add a new layer to its timeline and name it Actions.
Create a keyframe on frame 1 of the Actions layer.
Finally, add the following script to that keyframe:
this.stop();
Save and re-publishing the scene. Check the latest version in your browser. You should see that both buttons are now stopped on their first frame. The bunny should continue to loop on its idle animation.
Taking Advantage of Code Snippets
We’ve made some real progress. All that’s left to do now is add some interactivity by having our bunny respond to button presses.
This however will require more involved JavaScript than the single line scripts we’ve been writing so far. Fear not though. Adobe Animate CC makes our lives easy by providing a comprehensive set of code snippets that we can simply tailor to achieve our goal.
These snippets can be found in the Code Snippets panel. Let’s take a look at it.
First, close your Actions panel if it’s currently visible to make some space. Now, select Window | Code Snippets from Animate CC’s drop-down menu.
The Code Snippets panel provides a comprehensive set of snippets across Animate CC’s three main publish targets: ActionScript, HTML5 Canvas, and WebGL. Since we’re targeting WebGL, expand the WebGL folder. The snippets have been grouped into the following sub folders that best describe their general uses:
- Timeline Navigation: Code to control movie playback
- Actions: Code for common interactions
- Event Handlers: Code to handle basic user input
- Animation: Code to change an object’s properties over time
Expand each of the sub folders and take a look around. Each will contain a collection of scripts that you can easily add to your project by double-clicking on it. You can see the Code Snippets panel in Figure 8 below.
Figure 8. The Code Snippets panel.
If you expand the Event Handlers sub-folder, you’ll notice there’s a code snippet named Mouse Click Event. You can use that to detect when the user presses on one of the buttons.
Adding a Code Snippet
We’ll add the Mouse Click Event code snippet to the stage. If you’re currently in edit mode within one of the movie-clips, return to the stage first.
The code snippet requires a target object to be selected on the stage. We’ll start by wiring-up our defend button to the code snippet. Do this by selecting the Button Defend instance on the stage then double-clicking Mouse Click Event within the Code Snippets panel.
A new layer named Actions will automatically be added to the stage’s timeline and it will contain a chunk of JavaScript. You should be able to see that JavaScript from the Actions Panel, which has also automatically been opened for you.
Understanding your Code Snippet
Although the code may look intimidating, you really don’t need to understand that much of it. You can see the code listed below. The main points of interest have been highlighted in bold for you.
/* Mouse Click Event
Clicking on the specified symbol instance executes a function in which
you can add your own custom code.
Instructions:
- Add your custom code on a new line after the line that says
“// Start your custom code” below. The code will execute when the
symbol instance is clicked.
*/
//Get a reference to the Symbol on Stage using its Instance Name
this.defend = this.getChildByName(“defend”);
canvas.onclick = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
// Start your custom code
// This example code shows an alert with words “Mouse clicked”.
alert(“Mouse clicked”);
// End your custom code
}
}.bind(this);
//Function to check whether the specified point lies within the rect.
function isMouseOverSymbol(pointX, pointY, rect) {
if(rect.left getChildByName which asks for a reference to the child object with an instance name of defend. That reference gets stored in a property named this.defend, which provides a convenient way to work with our instance without having to repeatedly call getChildByName everything time we want to do something with it.
Next we have the following two lines:
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect) {
The first simply gets the bounding area that our defend button occupies on the stage. The second line checks to see if the user pressed anywhere within that region. If so then we know that the user touched the button and our final line of highlighted code gets executed:
alert(“Mouse clicked”);
This line simply shows an alert box in the browser and displays Mouse clicked as the alert’s text.
This is an ideal place to add our own custom code for when the button is pressed. After all, we want our bunny to actually perform its jump animation at this point rather than show an alert.
First let’s just save what we have and test our current code in the browser. As usual, select Control | Test (Cmd + Enter | Shift + Enter) from the drop-down menu. Your default browser will open and you will see the scene, complete with our bunny.
Test everything is working by clicking the defend button. An alert box should appear (Figure 9) containing the text Mouse clicked.
Figure 9. An alert box in response to a user event.
Congratulations, you’ve added some limited interaction to your content. Now let’s add some custom code to trigger the bunny’s jump animation.
Defend Button Interaction
Move back to Adobe Animate CC and add the following line of code to the Actions panel:
//Get a reference to the Symbol on Stage using its Instance Name
this.defend = this.getChildByName(“defend”);
this.bunny = this.getChildByName(“bunny”);
This will obtain a reference to our bunny instance on the stage and assign it to a property named this.bunny for easy access.
Now that we have a reference to our bunny, we can use it to trigger the bunny’s jump animation. Remove the original line of code that displayed the alert and replace it with the following:
alert(“Mouse clicked”);
this.bunny.gotoAndPlay(“jump”);
Here we simply call the gotoAndPlay action upon our this.bunny reference. The gotoAndPlay action instructs the bunny’s playhead to go to the frame labelled jump and start playing again from that point.
Once again, save your changes and republish your content to the browser.
This time when you test it, clicking on the defend button will actually trigger the bunny’s jump animation. When the jump animation ends, the bunny will return to its idle animation. Give it a try.
Attack Button Interaction
Now let’s do the same for the attack button. Move back to Animate CC and add the following line to the Actions panel:
//Get a reference to the Symbol on Stage using its Instance Name
this.defend = this.getChildByName(“defend”);
this.attack = this.getChildByName(“attack”);
this.bunny = this.getChildByName(“bunny”);
We now have a reference to the attack button and have that reference stored in a property named this.attack.
Now we need to add some code that checks to see if the user has pressed the button. We can copy-and-paste the code that already exists for the defend button and make a few slight adjustments.
Let’s begin by doing the copy-and-paste:
canvas.onclick = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
// Start your custom code
// This example code shows an alert with words “Mouse clicked”.
this.bunny.gotoAndPlay(“jump”);
// End your custom code
}
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
// Start your custom code
// This example code shows an alert with words “Mouse clicked”.
this.bunny.gotoAndPlay(“jump”);
// End your custom code
}
}.bind(this);
Now we’ll make two small changes. The first will be to ensure we actually check that the attack button is being pressed rather than the defend button. The second is to trigger the bunny’s punch animation rather than the jump animation when the attack button is pressed.
You can see the two changes below in bold:
canvas.onclick = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
// Start your custom code
// This example code shows an alert with words “Mouse clicked”.
this.bunny.gotoAndPlay(“jump”);
// End your custom code
}
var boundingRect = this.attack.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
// Start your custom code
// This example code shows an alert with words “Mouse clicked”.
this.bunny.gotoAndPlay(“punch“);
// End your custom code
}
}.bind(this);
Once again save your changes and re-publish.
Now you should be able to press both buttons to see the bunny perform its jump and punch animations.
Button Feedback
Congratulations! You now have an interactive WebGL project, but we can take things a little further and add a little more sophistication to proceedings.
Our bunny only responds to a button press when the mouse button is released. To improve the user experience, we’ll add some visual feedback to our two buttons. We’ll show the button’s second frame when the mouse is held down over it, and we’ll move back to the first frame when the mouse button is released.
To achieve this we’ll need to listen and respond to the following two events:
- onmousedown: occurs when a user presses a mouse button over an element
- onmouseup: occurs when a user releases a mouse button over an element
Much of what we’re about to write is borrowed from our existing code snippet but with a few slight modifications. Let’s begin by writing some JavaScript to update the visual state of each button when being pressed. Add the following code at the end of your existing code snippet within the Actions Panel:
canvas.onmousedown = function(e) {
// We’ll add some code in here in a moment
}.bind(this);
The code above simply listens and responds to an onmousedown event. In other words, any code we write within this block will get executed when the user holds the mouse button down over the screen.
Now let’s add some more code to check if the defend button is being pressed. If so, we’ll move it to the second frame in its timeline:
canvas.onmousedown = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.defend.gotoAndStop(2);
}
}.bind(this);
Everything above should look fairly familiar to you. We get the bounding area of the defend button, then check to see if the user clicked within that region. If so, we use the gotoAndStop action to move the defend button’s timeline to frame 2.
Now let’s do the same for the attack button. Add the following:
canvas.onmousedown = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.defend.gotoAndStop(2);
}
var boundingRect = this.attack.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.attack.gotoAndStop(2);
}
}.bind(this);
As you can see, the code is almost identical. The only difference is that we are working with the this.attack property this time rather than the this.defend property.
Save your work then re-publish it to your browser.
Now when you click either of the two buttons, their state should change to indicate that they are being pressed down by the user. However, when we release the mouse button, the button does not return to its original state. Let’s add the code for that.
Move back to Animate CC and add the following code to the end of your timeline script:
canvas.onmousedown = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.defend.gotoAndStop(2);
}
var boundingRect = this.attack.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.attack.gotoAndStop(2);
}
}.bind(this);
canvas.onmouseup = function(e) {
var boundingRect = this.defend.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.defend.gotoAndStop(1);
}
var boundingRect = this.attack.getBounds(this);
if(isMouseOverSymbol(e.offsetX, e.offsetY, boundingRect)) {
this.attack.gotoAndStop(1);
}
}.bind(this);
As you can see, it’s an almost carbon copy of the code that deals with the onmousedown event. The only differences being that it listens for the onmouseup event instead, and sends the playhead of each button back to the first frame.
Save your changes and re-publish. This time when you run your scene in the browser you’ll see that the buttons return to their original state after being pressed.
And that’s us finished! You’ve successfully built your first piece of interactive WebGL content without needing any prior programming knowledge. Well done!
Summary
Adobe Animate CC’s WebGL export feature facilitates the creation of visually rich and highly interactive web projects. It also provides an avenue for those wishing to deliver that content across desktop and mobile browsers without the need for a plugin. And as you’ve seen from this tutorial, adding interactivity to your work is relatively easy. The code snippets panel is a great place to start and writing your own basic timeline scripts is relatively easy too, even for those without any prior programming experience.