Pages

Sunday 20 March 2011

JavaScript - running man animation

The following blog post is intended to log my experience with implementing the “Running man” JavaScript application.

At its core the “running man” task involved the implementation of a JavaScript animation depicting a running man by stringing together a sequence of slightly different images. This task also involved the implementation of various features such as allowing the user to slow down or increase the speed of the animation and also the ability for the user to “throw” an obstacle at the running man.

Implementation

I have split up the project into 3 parts namely, HTML, CSS and JavaScript.

HTML

The HTML part of the project contains just the bare elements required for the JavaScript application.

container div – This is a global wrapper around all elements required for this task. I find it to be good practice to use a global container div whenever possible, this allows for more flexibility with styling especially with positioning as any internal elements even if positioned absolutely are still relative to this parent container div.

runningArea div – This div represents the area inside which the running man is actually running, by having this area explicitly dedicated for the running man I was able to detect boundaries inside which the animation has to take place, it also proved very handy for the onclick throwObstace() function which will be explained later when dealing with javascript.
This div also contains some other inner elements mainly the running man div “divMan” and the obstacle div “divObstacle”

controlPanel div – this div contains all the action buttons available for the user, the start, stop, slow, fast, jump and clear obstacle buttons, as you can se from the code below all buttons with the exception of the start button are disabled by default, these buttons will be enabled through JavaScript when their functionality is available.


CSS

Since the layout for this page is very simple I primarily made use of CSS id selectors to style it’s content, most styling attributes have been defaulted to represent the initial state of the page, these will obviously be altered during execution to output the illusion of a running man.

Below I have extracted some CSS from the project


The above CSS code effectively sets all elements on screen to the default position and font-family attributes shown above unless otherwise overridden.

The running Area has been styled with a background image, a specific height and a width of 100% (this is obviously 100% of the parent container and not of the page).


 The imgMan element simply positions the element absolutely aligning the element with the bottom of it’s parent div “runningArea”


 The divObstacle element represents the obstacle (soccer ball) on the screen, even though it’s positioned absolutely it’s position is still relative to it’s parent div and not to the page, initially the margin-top attribute is set to -1000 which would move the obstacle out of the viewable area of the screen, the z-index attribute is set to 2 which means that this element will be stacked on top of anything on the screen with a lower z-index.

 The above image shown the work done so far

JavaScript

The JavaScript section is the more complex section and where most of the work had to take place, I will split up the core functionality of the application into various segments to make this blog post more structured.

Main variables




Start animation - btnStartClick()



This function is the event handler for the Start button on the HTML page, it will first load all required images into the arrays defined in the previous section by executing a simple function loadImages() which populates the image arrays with the image URLs. It will then execute the animate() function which will call itself recursively to animate the application until terminated.


The animate function can be considered as the main “game loop” which will call itself recursively with a timed delay as defined by the speed variable to project the animation. The first portion of the code takes care of the sequencing of the image used to animate the “running man” as well as handle the direction. The “running man” will effectively change direction whenever either the left or right boundary of the running area is reached. The second portion of the code handles the horizontal positioning of the animation.


Stop/Pause animation - btnStopClick()


 The above code is fired whenever the stop button is clicked, it effectively stops the animation by calling the clearTimeout() function on the reference generated with the setTimeout() function in the animate() function, it also handled the enabling/disabling of on screen buttons as expected.


Slow down animation - btnSlowClick()


 The above code sets the speed (delay) value to 50 which will make the animation run in slow mode.


Speed up animation - btnFastClick()


 The above code sets the speed (delay) value to 50 which will make the animation run in fast mode.


Throw obstacle – throwObstacle(event)

 This function is fired whenever a mouse click event takes place on the runningArea div, the event object contains the x & y co-ordinates of where the actual mouse click took place, unfortunately this is relative to the browser window an not the runningArea div so some simple computation had to be done to compute this value using the .offsetLeft attribute of the container element. This function then calls the animateObstacle() function which will handle the animation (dropping effect of the obstacle).


 The above function will call itself recursively until the obstacle lands on the ground, the horizontal positioning of the obstacle depends on where the user clicks on the screen.


Jump - btnJumpClick()


 This function allows the user to make the running man Jump over the obstacle, the above code will disable the jump button while a jump is in progress.


 The animateJump() function will take care of the jumping animation by keeping track of the direction (up or down) as well as the vertical positioning of the “running man” animation.

The above image shows the "running man" jumping over an obstacle, notice how all the buttons are enabled/disabled depending on the state of the page.

 Clear obstacle - btnClearObstacleClick()



The clear obstacle function just clears the obstacle off the screen.


Collision detection

I haven’t yet managed to implement the collision detection between the running man and the soccer ball. My idea would be to compare the current position of the running man to that of the obstacle to after every animate() execution only when the obstacle is placed on the ground by comparing the margins of both elements and if they overlap I could simply call the btnStopClick() function which would pause the animation and take care of all other functionality such as enabling/disabling of buttons just as if a user had clicked the stop button


Conclusion

Overall I believe the project turned out ok, considering I had never before worked with JavaScript before, it did take me significantly longer than I anticipated to complete mainly because I am used to statically typed languages such as Java. I’m sure you have noticed some tricks in JavaScript code above especially the *1 arithmetic operation to “trick” JavaScript to treat the value as a number and also the .replace(/px,*\)*/g,"") function which I used to remove the px characters to be able to treat such values as numbers.


Resources

Images

Running man image sequence –  The running man animation is made up of a total of 60 images, 30 going in each direction. I downloaded the original sprite sheet from http://www.thebest3d.com/pda/tutorials/array2animation/index2.html adter which I sliced it into individual images and flipped each image to go in the opposite direction.


Soccer ball – the soccer ball used as an obstacle was downloaded from http://www.iconarchive.com/show/sport-icons-by-icons-land/Soccer-Ball-icon.html


JavaScript references

w3schools.com – I mainly used this site as a reference to the core JavaScript functions and also for guidance when parsing the DOM.

0 comments:

Post a Comment