Wednesday, December 4, 2013

Web-Kamehameha with Beam

After receiving help on the geometry necessary to draw the beam from Dr. Remy, I was successfully able to write code to incorporate it into Web-Kamehameha. The below video shows the final product.


The solution to drawing the beam was to use the atan2 function (featured in almost every programming language) to get the angle of the center of the beam from the two given points. Then, using a factor of energy level and radians, I adjusted that angle to get the angle of the either side of the beam. From the newly computed angle, I determined which edge of the canvas the beam would hit (top, bottom, left, or right). Then, depending on the edge, I could determine the X or Y coordinate of the point to connect the base of the beam to. Given that X or Y coordinate, I could calculate it's distance from the opposite axis and use the tan() function and the basic formula tan = opposite / adjacent to find the length of the missing side, which would be directly equal to the missing coordinate. Below is my code.

function drawBeamSide(ballBase, angle) {
var adjacent = null;
var opposite = null;
var newX = ballBase[0];
var newY = ballBase[1];

// transpose the angle to the range [0, 2PI)
if (angle < 0) {
angle += 2 * Math.PI;
}

// determine which edge this beam should hit as it
// will affect the calculations
if (angle < 1 / 4 * Math.PI || angle > 7 / 4 * Math.PI) {
// Hits right edge
adjacent = ballBase[0] - 500; // distance from point to right edge
opposite = Math.tan(angle) * adjacent; // use trig to find Y coordinate
} else if (angle <= 3 / 4 * Math.PI) {
// Hits top edge
opposite = 0 - ballBase[1];
adjacent = opposite / Math.tan(angle);
} else if (angle <= 5 / 4 * Math.PI) {
// Hits left edge
adjacent = ballBase[0];
opposite = Math.tan(angle) * adjacent;
} else {
// Hits bottom edge
opposite = 500 - ballBase[1];
adjacent = opposite / Math.tan(angle);
}

newX -= adjacent;
newY += opposite;

drawLine(ballBase[0], ballBase[1], newX, newY);
}

The function's first argument is a two element array representing the X and Y coordinates of the ball's base (which is the same location for the beam's base) and then the angle (from the x-axis) of the beam to draw. Logic outside of this function already took care of changing the angle's and then calling this function to produce two sides to the beam.

The tricky thing to note is that the coordinate system for the HTML5 has a positive increasing Y value as you move down the image. The top of the image is Y = 0 while the bottom is Y = HEIGHT (or 500 in my case). The left is X = 0 and the right X = WIDTH.

Some interesting things to note about the program is that the depth appears to affect the accuracy or straightness of the beam. Tomoto's code, and what I've modified and put into my program, is simply drawinga vector along the line from the shoulder to the hand, however in the video below you will see that even when both are on the same Y level, the angle of the beam is quite off (too low). I noticed this effect increases with depth. It is not noticeable in the previous video since I crouched to increase the energy level. If I stand up straight and release a Kamehameha however you can see the problem.

In the below video I demonstrate this. I start off by showing the hand-distance threshold for ball generation. Then I release two crouched Kamehameha's for which the angle appears to be accurate. Then I release one standing and you can see that it shoots downward despite my arm being straight. I can even raise one hand to show the path of the beam, despite not having any energy, and you can see it is inaccurate.


No comments:

Post a Comment