In my last post I wrote about how:
- I made my object move upwards, reach a certain point and then back down.
- Disable and re-enable HTML elements when a particular event gets triggered.
Today I will explain how I managed to implement collision detection and how I provided the user with a way to alter the throwing angle of my paper ball.
Changing the angle with user input
For this web application to become a game, it must have some sort of user input, therefore I decided to give the user two options to change to course of the paper ball; The angle which the object will be thrown and the force, but in this post I will only explain how to change the angle and will talk about the force in my next post.
As I pointed out in my first post, It's best to start out simple and then elaborate, so as an input method for the angle I used a simple drop down list with pre-defined angles from which the user can choose one. To implement this drop down list in HTML I used the standard <SELECT> element tag and inserted <OPTION> elements between its open and close tags like so:
Angle:<select id="angleSelector" title="Angle">
<option value="-250">80 deg</option>
<option value="-200">70 deg</option>
<option value="-150">60 deg</option>
<option value="-100">50 deg</option>
<option value="0">45 deg</option>
<option value="100">40 deg</option>
<option value="150">30 deg</option>
<option value="200">20 deg</option>
<option value="250">10 deg</option>
<select>
In the above HTML code I am declaring a Select element and assigning its unique identification attribute to "angleSelector" in-order to be able to reference it through JavaScript later on and its title attribute to "Angle", this value will display in a tool-tip box when the mouse pointer hovers over this drop down list.
Between the Select element's open and close tags, I inserted an Option element for every angle value I wanted to be in the list. As you may have noticed I assigned each Option element a positive or negative number in their value attribute. I will explain the purpose of this value attribute soon enough.
So now I have an input method for the shooting angle, but I still have to connect this control to my JavaScript code. To do so I first had to decide where and when I should retrieve the selected value and how to use it in-order to alter the angle of my paper.
The obvious choice of when to retrieve the selected angle is when the Throw button is pressed and that event calls my 'throwPaper()' function which I mentioned in my previous posts.
But what to do with the selected angle?
In-order for the angle to change I decided that the easiest way was to tweak the 'middleX' value, thus effecting the 'yPaces' calculation I mentioned in my previous blog, therefore altering the upwards movement of the paper ball.
 |
| How altering the 'middleX' value effects the shooting angle. |
In the above image, the dotted lines represent the 'middleX' value and the straight lines represent the respective course of the paper ball. Notice how the angle of the red lines is much higher than the angle of the blue lines, because the 'middleX' value is closer to the left.
This is where the Option element's value attribute comes in! I add or reduce this value from the 'middleX' value and thus replicating what is illustrated in the image above.
N.B. - This method has a serious drawback though, because the 'middleX'
value is dynamically calculated according to the user's screen width,
while the values retrieved from the <SELECT> element are static. This
means that the angles will vary according to the user's screen width.
To solve this issue, you could calculate the ratio of the user's screen
width against a predefined amount, say 100 pixels, and use this ratio
on the retrieved value from the <SELECT> element. This way you would
dynamically calculate the amount of pixels to deduct or add to the
'middleX' value as well.
Collision Detection
So, up to now its been interesting making my object move on screen and changing the shooting angle, but what is the point of being able to throw a paper ball in different angles, when there is noting to aim at?
Therefore I added another object on screen, this time a paper basket, called it 'bin' and gave it a width of 100 pixels and a height of 150 pixels.
<img id="bin" src="bin.jpg" alt="Image Not Found" style="width: 100px;height: 150px"/>
In the 'start()' function I reference this object and place it at the furthest corner on the right. Keeping in mind that each user might have different screen widths, I also dynamically calculated this position by using the retrieved screen width stored in 'screenW'.
//calculate and store the position of the bin
binXLocation = ((screenW-40)-140);
//gets the bin image and stores it as an object in myBin
myBin=document.getElementById('bin');
myBin.style.position='relative';
myBin.style.left=binXLocation+'px';
myBin.style.top='0px';
Now that my bin is in place, the next step was to implement collision detection and to do that I started out by defining the possible collision points and differentiating them from each other, like the image below illustrates:
 |
| Different Collision Points |
After defining the collision points, I altered my 'move()' function to detect where the paper ball is, every time the function is called.
//gets the paper location on the x-axis
var paperXLocation = parseInt(myPaper.style.left);
//gets the paper location on the y-axis
var paperYLocation = parseInt(myPaper.style.top);
Then I used a combination of conditions to determine whether the paper ball touches any of the collision points I had defined and if so, displays a message box with a respective message to the touched area.
Below is the code containing these conditions:
//still have moves available
if(availableMoves > 0){
if(paperYLocation>=-20){
clearInterval(motion);
alert("Not far enough!");
}else if(paperYLocation>=-125 && paperXLocation>((screenW-40)/2) &&
paperXLocation>=binXLocation){
clearInterval(motion);
alert("So close...yet so FAR!!")
}else if(paperYLocation>=-150 && paperXLocation>binXLocation){
clearInterval(motion);
alert("Dunk! YOU WIN!!!");
}else{
if(paperXLocation<middleX){//paper goes up
//move paper up
myPaper.style.top = parseInt(myPaper.style.top) - yPaces+'px';
}else{//paper goes down
//move paper down
myPaper.style.top = parseInt(myPaper.style.top) + yPaces+'px';
}
//move paper right
myPaper.style.left = parseInt(myPaper.style.left) + xPaces + 'px';
}
availableMoves--;
}else{//no more moves left
clearInterval(motion);
if(paperYLocation<-20 && paperXLocation<binXLocation){//the paper is still in mid-air
//available moves ran out and the paper is still in mid-air,
//therefore get it to the ground!
//Set a new interval which calls the landPaper() function every 40 milliseconds
landMotion = setInterval(landPaper,40);
}else if(paperYLocation>=-150 && paperXLocation>binXLocation){//dunk
alert("Dunk! YOU WIN!!!");
}else if(paperYLocation<-150 && paperXLocation>binXLocation){//overshoot
alert("Over Shoot!");
}else if(paperYLocation>=-20){//not far enough
alert("Not far enough!");
}
}
That's it for today's post, hope you found it interesting and helpful. If you have any questions or suggestions, please leave them in the comments section and I will do my best to respond.
In my next post I will discuss how to provide the user with control of the shooting power and make the paper ball roll while moving in the air.