My Pages

Thursday 10 March 2011

More Javascript - Animation

Introduction
Last week we discussed Javascript in some detail were we covered some basics, history, pros and cons, applicability on the web, frameworks etc. This week we will still be dealing and discussing Javascript but as opposed to last week were we covered a range of topics, we will be talking about a specific niche of Javascript which is Animation.
Backing up a few years animation on the web mainly involved roll-over effects, animated GIFs and image maps, these techniques are nowadays being replaced by almost entirely by CSS e.g using a:hover to style an anchor tag on hover. DHTML standing for Dynamic HTML is a term that groups a number of technologies mainly HTML, Javascript, CSS and DOM (Document Object Model), these technologies together enable developers to create animations among other things. Different browsers throughout the years have created proprietary syntax to facilitate animation like filter and revealTrans, most of this syntax is getting obsolete due to the lack of syntactical and technological compatibility between browsers.
Up until recently Javascript wasn’t that popular for animating web sites. Instead proprietary software such as Adobe (back then Macromedia) Flash and Swish were used. There are several reasons why such technology was used and mostly it all boils down to practicality (it is very difficult to create complex animations and maintaining them using Javascript).
Animation development using Javacript nowadays is becoming more popular with emerging frameworks such as jQuery. These frameworks facilitate animations, tweens, transitions and allow the developer to focus on the animation by using functions such as animate() without going into the nuts and bolts of animation.
The concept behind Javascript animation is relatively simple; the manipulation of elements and their attributes e.g.  Position and width over a period of time.
This is achieved at the lowest level by using either one of these functions;
  • setTimeout()
  • setInterval()

It’s good to know that setTimeout was introduced with Javascript 1.0 by Netscape which means that the ability to create animations using javascript has been with us for quite some time.  The difference between setTimeout and setInterval is that setTimeout only calls the function once while setInterval calls the function parameterised after the time set passes. 
Differentiate between setTimeout and setInterval


Task Overview

The task assigned for this week deals with the creation of an animation using Javascript. The task is further subdivided into sub tasks each of which incrementing on the latter sub task.
  •          Implement animation using images.
  •          Allow the user to speed up or slow down the animation.
  •          Allow the user to “throw” an obstacle at the runner
  •          Adding a custom feature
Before I dove in and starting working on the tasks I tried to create a mental image of the animation I wanted to create keeping in mind the tasks mentioned above. After contemplating on what to do I decided on the actor which in my case is a stick man running with a moving forest background and a wolf moving the opposite direction as an obstacle. This scenario involves three image animations all having separate timelines.

Implementation

Implement animation using images

Each of the image based animations described in the sub task were wrapped in a container using a div tag. This allows for better management and also the creation of more than one of the same actor by using DOM’s createElement function

The Actor

The images chosen to represent the actor animation were placed in a folder and each image was named using this format actor{0}.png. {0} is an integer reflecting the sequence of the frame within the animation. This technique facilitates caching of images when the web page is loading by looping up until a specific number. In this case the number of frames making up the animation is 5 so starting from 0 to 5. By caching images into an array that array can be accessed and manipulated throughout the web page.  This technique is used for the other image based animations throughout the tasks.


Filling array with images



Once the images are stacked in memory the algorithm responsible for changing the image source over a period of time is implemented. In this function I used setTimeout and passed a global variable representing the interval. With each recursive call the image source is changed to the indexed image within the loaded array by accessing the image element using DOM’s getElementById function.


Setting image element source to indexed array

The Background

To animate the background I searched for a static image of a forest. To create the effect of the actor running through the forest I created a number of png images whereby the image was shifted to the left by 10px with each image created. Since the image chosen was pretty large in size I decided to change the quality to reduce the file size to approx. 200 kb in size. Having large sized images in an animation degrades the performance of the animation.  A separate global variable was created to handle the interval for the background. This will allow for more granular control on the animation if need be.

The Obstacle

For an obstacle as already mentioned I chose to have a wolf running opposite to the actor’s animated movement. The same techniques for caching and animation were used and a separate global variable was created to handle the time interval between each frame.

Obstacle and actor image animations
Allow the user to speed up or slow down the animation

In the previous section it was mentioned that a separate global variable was set to handle the interval of each object. Changing the global interval variable changes the refresh rate of each animation taking place and two events triggered by buttons in the control panel were created. Within the event an argument with the amount of time to be either subtracted or added to the existing intervals was specified.

Attaching modifySpeed function to the onClick events
The function called will add or subtract the value passed to the global variables holding the interval time for each animation, resulting in a faster or slower animation. Since not all animations have the same number of frames, speed is relative to the number of images making up the animation.


Speed adjustment algorithm for the actor interval


Allow the user to throw an obstacle to the runner

To achieve this effect the following tasks had to be developed, some of which we already discussed and implemented.
  •        Animated running actor
  •        Animated running obstacle
  •        Actor motion tween
  •        Obstacle motion tween
  •        Collision detection when the two objects meet


The first two items in this list were already in place as discussed in previous sections.  The term tween signifies the creation of movement between two points.
To achieve the actor motion tween a function was created which incrementally moves the actor container until the specified relative position is reached. The function makes use of the setTimeout function as to make the actor movement visible. Each event triggered by the user moves the actor by 50px and this distance is moved incrementally by 10px at the specified interval for a smoother transition. To achieve both left and right movement a variable specifing the direction was added as an argument and according to this value the movement was either negated when the user clicks left and set as positive when moved right.

Actor movement to the left
The left and right movement events were attached to two buttons and to the left and right arrow keys by using this snippet : document.onkeydown = actorMoveKeys. The actorMoveKeys event gets the event object by determining which event object is available (depends on the browser being used to view the web page). The event object contains information on the key that is being pressed by the user. The respective function is triggered (actorMove(“LEFT”), actorMove(“RIGHT”)). We will talk about the jump function later.

Actor Controls
The obstacle uses the same logic with the difference of being set to visibility:hidden up until the canvas area is reached. Also the obstacle only moves from right to left.

Changing obstacle visibility when entering canvas area
 Now we will be going through the collision detection algorithm Part 1. For the purpose of this section we will only be taking into consideration the x-axis collisions since for the time being the actor has no upward motion. The function checking for collisions is triggered whenever an obstacle animation is initiated. The algorithm has its separate global interval variable which allows for faster collision detection if need be.

The algorithm subtracts the actor offset width divided by two from the actor offset left to get the far left edge of the actor container. To get the actor far right edge the actor offset width is divided by two and added instead of subtracted. The same calculation is done on the obstacle and when that is done the far edges are compared to see if one of the edges is within the range of the edges of the other object. 

X-Axis collision detection
Actor and obstacle left and right offsets
When a collision occurs the function is stopped as only one collision is registered. Whenever a collision occurs points are reduced from a global variable and displayed in a div on top of the animation.

A typical x-axis collision decrementing points on collision
Adding a custom feature

As described in the previous section the collision algorithm only checks for x-axis collisions since the actor can only do left and right movements. So to include y-axis collisions the actor has to be able to do some upward movements like jump. The jump function can be triggered either by the jump button on the form or by the up arrow key. When the function is called the actor is moved upwards by incrementing pixels to the bottom attribute over a period of time until the allocated coordinate is reached. Once the y coordinate is reached the same function handles the subtraction of pixels from the bottom attribute until 
the actor reaches the ground.

Demonstration of the actor jump function
Once on top the actor image animation is stopped as to show the actor jumping. With this added functionality now we can check for y-axis collisions. To check for y-axis collisions the top offset of the actor is added to the width offset to get the bottom edge of the actor container. If the bottom edge is greater than the obstacle top edge then a y-axis collision is registered.

y-axis collision detection
Final result

When the actor jumps the obstacle and no x or y collision take place one point is added to the variable holding the points.

Conclusion

This web page can be found at the following URL http://www.gregdevelopment.com

No comments:

Post a Comment