Thursday, March 17, 2011

Coursework 1 - Running Man Animation

Overview

The runningMan animation, being a coursework for this module I decided to add some more features to it. I’m relatively new to the web world but despite that I still enjoyed the challenge that comes with novelty and diving into a huge and deep pool. Along the way, undoubtedly I will encounter frustration with cross-browser compatibility.


The Idea

What I intend to add is a form of “target” image that will move with the mouse pointer as a form of cross-hairs. The central animation; the runningMan is enclosed in a box (a div) that will be the area on which if the user clicked in it, a bomb will fire. A bomb image will travel from the location of the click to the runner’s head and upon arrival; the runningMan animation will simulate an explosion, by changing the animation.


Drawing the Target

The basic outline of this section was:

  • Draw the image
  • Get the mouse coordinates
  • Show the image at the coordinates

Draw the image - First off, I made the target image which is two circle outlines enclosed, one in the other.

Get the mouse coordinates - the first method I discovered to get the mouse coordinates was the “event.clientX” and “event.clientY”. This gets the user’s X,Y mouse position on the browser. I implemented the code and tried to test it with a simple alert. It worked. But when I loaded the same code in Firefox, nothing happened. IE and Chrome worked correctly. So I looked for a Firefox alternative and came across a universal method at http://forums.asp.net/p/1176241/1990722.aspx. It seems like the previous method formed part of the IE object model and was only relevant to it. The page continues to explain that there is no reliable cross-browser way of getting the coordinates, so a manual calculation has to be made using the scrolling and DOM measurements. I implemented the script found there and it worked successfully across all three browsers.

Show the image at the coordinates – the next step involved making use of the coordinates gathered and placing an image at that position. So I added the image to the HTML body and moved added lines to move the image to the mouse coordinates using the getElementById and referring to the CSS styles positioning. When testing it, I found that the image was not overlapping all the elements, and getting behind some of them. A quick search pointed me to the z-index CSS style that dictates which element overlaps which. Giving a z-index of 20 to the target image solved the issue. The next issue was that since the image is directly under the mouse, when clicking, one will click the target image. I wanted the image to be placed at the slightly offset of the pointer, so moved its position by 5 pixels each way. The resulting code is shown below.


Moving the bomb

The basic outline of this section was:

  • Find an image
  • Figure out how to identify the runningMan’s head
  • Store the position of the click
  • Generate array with X, Y coordinates for a straight line between the click and the runningMan’s head
  • Move the image according to the array of coordinates

Find an image – I found an image of a mine and resized it to appropriate proportions and added transparency to it.

Figure out how to identify the runningMan’s head – the first thing that came to mind was to always refer to a fixed position. But this is incorrect since the animation is held at the centre of the browser, and thus, its position will change if the browser is resized. After some experimentation I figured out that the Y-coordinate will always remain the same and that the runningMan’s head can be identified as always to be horizontally central. The code is shown below:

Storing the position of the click – this was simply done by getting the location of the mouse and storing it in a variable that will be used throughout the whole function.

Generate array with X, Y coordinates for a straight line between the click and the runningMan’s head – now comes the tricky bit. The target is essentially at the centre of the box so one can identify four quarters of movement. Simply changing the X or Y coordinates by 1 pixel each time until they reach the target will not make a straight line. It will be in most cases curved. The curve results from the fact that you have no guarantee that your X and Y coordinates are the same distance from the target. This required some math.

First, I decided to come up with the math myself. My approach was to identify the coordinate with the longest distance and make that distance the number of pixels I needed. Then I would fill that coordinate with all the pixels at 1-intervals while filling the other with a rounded number in ratio with the corresponding pixel. The attempt half succeed but after quite some time I realised I wasn’t going anywhere. The trial code can be seen in additionalCode.txt and is the function called firebomb.

Stuck and out of ideas, I decided to re-think my approach and recalled a friend having the same problem with drawing a straight line with pixels, defined by 2 points. He had made use of an existing algorithm. A few searches later, I found the Bresenham’s line algorithm. The illustration below perfectly illustrates the problem:

Besenham’s line algorithm general equation is shown below:

A few searches later I found some implementations of the algorithm in JavaScript. Some were plainly over-complicated until I came across a simple and clear implementation on: http://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript I adapted it to my script and voila, the arrays were generated correctly. An example is shown below:

Move the image according to the array of coordinates – the basic concept was to move the image every time a new coordinate is created, within the function. Another concept was to move the image in a separate function by looping through the arrays of coordinates. Both ideas were tried and tested but to no avail. The image would either simply be shown at its end location, or at its start location for a brief time followed by the end location. After some reading on the matter, some sources reported the same problem. Some users said that the browser will sometimes simply decide to skip the loops in between, either because it cannot keep up or because it sees the animation as being in a very short period of time so it skips it. One of the issues that I came across was that you cannot place a timer within a loop, but rather, make it loop on itself.

I am not sure whether what I had in mind is possible to implement in JavaScript or I simply wasn’t doing it correctly. Probably, the latter. Given that I couldn’t get the animation correct, I decided to compromise by showing what I had already done, from the math perspective. So, I decided to output the coordinates of the path to be taken by the animation each time a user clicks to fire. I opted for an in-page output, using the innerHTML in a div, which can take a while to render (HTML wise) when the user clicks far away from the runningMan. I also tried outputting through a message box but it was annoying, having to close it every time and if the arrays are too long, they won’t fit in the box. The code for the HTML output is shown below:

(UPDATE) - Turns out, it was the latter. I have successfully implemented the animation after having one last go. I utilised the same routine as the original example demonstrated and modified it to this purpose. The final code is shown below:


Adding the exploding animation

  • The basic outline of this section was:
  • Draw the exploding animation
  • Write a function that will input the image names in the array through a loop
  • Write the function to display the animation
  • Trigger the function if the specific box is clicked

Draw the exploding animation – I drew a series of 49 images for the exploding animation, seen below:

Write a function that will input the image names in the array through a loop – instead of having to call each image by its name in a line-by-line coding manner, I wrote a function that will fill the array for my 49 images. While I was implementing this, I decided to implement the same thing for the fall and run arrays. The code for the filling the explode array is shown below:

Write the function to display the animation – The function to display the explode animation was done like the running and falling animations

Trigger the function if the specific box is clicked – to trigger the function when the box is clicked, I implemented an onClick value to the runningField div, referring to the showExplosion function. The code is shown below:


Conclusion

Overall, at the very last minute, I achieved what I first set out to do; with loads of bumps and hiccups on the way and a last minute update. JavaScipt and web in general is vast, and it was quite a steep learning curve to get to grips with the basis of it all. The whole page might require some polishing, but the basic functionality is there.


A gallery of the page working is displayed below:

No comments:

Post a Comment