PASTE NAVIGATION MENU CODE

Saturday 24 March 2012

Phase 3: Making the Ball Move

| | with 0 comments |

Ball Movement Logic

Having all elements set up and user values stored in variables, it was then time to act upon these results. The user is required to select an angle of projection together with the speed of ball movement. The angle of projection determines the direction of the ball. The speed chosen will determine both the speed of the ball movement together with the distance to be covered by the ball.

How are we going to figure out these elements? We'll start tackling each of these variables one by one starting with the speed of the ball. The vertical slider will be giving a value ranging from one to twenty-six (1-26), with twenty-six being the lowest speed value. I hear you asking, how is he going to translate this value in relation to the size of the canvas?

Here it goes..

After some on-line research to figure out how to translate a range into another range, I managed to find a very interesting formula which does this job smoothly. The workings performed can be shown below.

The formulas

I need to transform Q = [OldMin , OldMax] to Q' = [NewMin , NewMax], where f(OldMin) = NewMin and f(OldMax) = NewMax, then an arbitrary X in space [OldMin , OldMax] will have for [NewMin , NewMax] the following value:

NewValue = OldValue * k + d;

where

k = (NewMin - NewMax) / (OldMin - OldMax);
d = NewMax - OldMax * k;

So we have OldMin = 26, OldMax = 1 and NewMin = 30, NewMax = 430, resulting:

k = (30 - 430) / (26 - 1) = -16
d = 430 - 1 * -16 = 446

 an arbitrary value x from [1 , 26] space is translated as follow:

NewValue = (OldValue * -16) + 446  

So let's try it out..

NewValue = (OldValue * -16) + 446
NewValue = (1 * -16) + 446
NewValue  = -16 + 446 = 430 (value obtained is equivalent to the NewMax)

At this point, we know that when the user moves the vertical slider, the above formula will translate the value to a new value which can be used to calculate the distance moved by the ball which will be later called radius.

The next thing that I was required to figure out was the method to be used to calculate the next ball position according to the chosen angle of projection by the player. In order to produce a smooth ball movement, I decided to move the ball in steps of 1 pixel. Having the original x and y coordinates of the ball and knowing that I was going to move the ball in steps of 1 pixel at a time, I chose the Pythagoras Theorem to calculate the new x and y coordinates of the ball at each stage of the whole path covered.



Figure 3.1

The Figure shown above is showing the values which are known in black whilst the values which need to be calculated are shown in blue. The values which are known are: 

  • the angle of projection
  • the distance to be covered by the ball - radius
Therefore, in order to obtain the new x and y coordinates, we would need to perform the following Trigonometric calculations:

Sin(Angle) = Opposite / Hypotenuse
Sin(Angle) = y / radius
Sin(Angle) * radius = y

Cos(Angle) = Adjacent / Hypotenuse
Cos(Angle) = x / radius
Cos(Angle) * radius = x

Having both calculations sorted out, the next step was to implement these calculations to produce a moving ball. A loop will need to be implemented with the radius being incremented by 1 pixel each time until reaching the distance chosen by the player.

Implementing the Logic

After figuring out the logic of how the ball will start moving on the canvas using the values adjusted by the player, it was then time for the implementation towards seeing the ball moving for the first time.

Calculating the distance to be covered by the ball:

//Function used to update ball speed  
function updateDelay(sliderValue) {
delay = sliderValue;
}

This function is used to assign the value of the vertical slider to the variable called delay.

//getting the value from the vertical slider -- delay -- and changing it to scale
function calcRadius(){
radius = ((delay*(-16))+446);
}

This function is used to calculate the radius to be covered by the ball. As it can be clearly seen, the formula used is equivalent to the formula used to convert the range from that of the vertical slider, which ranges from 1 to 26 and the range needed to move the ball across the canvas which ranges from 30 to 430.

Calculating the new x and y coordinates:


//giving the function the radius and returning the new x position
  function getX(r) {
   var radAngle = angle * (Math.PI / 180);
   var result = Math.cos(radAngle) * r;
   return result;
  }
//giving the function the radius and returning the new y position
  function getY(r) {
   var radAngle = angle * (Math.PI / 180);
   var result = Math.sin(radAngle) * r;
   return result;
  }

As shown in the code snippets above, the functions will calculate the new x and y coordinates given both the current radius (r) and the angle. The current radius is an incremental variable which will later on be compared with the total radius until both becoming equal in value. This would mean that the circle has moved the full radius in steps of 1 pixel. The next step was to convert the angle of projection into radians since the method Math.cos / Math.sin work only with angles in radians. The last step included the implementation of the trigonometric calculation discussed earlier which obtained the new x and y coordinates of the ball.


Getting it all to work together:

function startMovement() {
   hslider.disable(1);
   vslider.disable(1);
   document.getElementById("start").style.visibility="hidden";
   document.getElementById("main").style.visibility="hidden";
   
   document.getElementById('aimer').style.visibility = 'hidden';
   calcRadius(); 
   if (currentRadius < radius) {    
    ballNewX = 150 - getX(currentRadius);
    ballNewY = 420 - getY(currentRadius);
    
    currentRadius++;
    setTimeout("updateCanvas();startMovement();", delay);  
  }

The function startMovement() is initialized when the user clicks on the play button. On click, the function will first disable both sliders and hide the return to Main and Play buttons and then the loop to finally animate the ball will commence. The function call the calcRadius() functions, where it will get the value from the vertical slider and return the distance to be covered by the ball. Then, the function will check if the currentRadius (which initially is set to 0) if smaller then radius. This check is performed so as the ball will not exceed the distance imposed by the player. Therefore, if this check is valid, the new x and y coordinates of the ball are obtained. The currentRadius variable in then incremented by 1 and the setTimeout method is called. The setTimeout method is used to redraw the circle with the new axis using the function updateCanvas() shown below and re-enter the startMovement() function which will loop until the currentRadius is equal to the radius; meaning that the ball has moved the full distance / radius. The delay is used to determine the movement speed of the ball.

function updateCanvas(){
    context.clearRect(0,0, 320,480); 
       context= ballCanvas.getContext('2d');
       context.beginPath();
       context.fillStyle="#3e3e3e";
       context.arc(ballNewX,ballNewY,10,0,Math.PI*2,true); 
       context.closePath();
       context.fill();   
     }

The function updateCanvas() is used to clear the canvas from any drawn objects and redraw the circle in the new x and y coordinates.

Post a Comment

Please enter your comments here..

0 comments: