LESSON 20 - June 2, 2013

HTML5 GAME DEVELOPMENT

(Game Dev. Tools) LESSON # 20

Ben W. Savage

So as promised (with a bit of delay) here's lesson #20! Last time we got our feet wet with Math.sin and Math.cos. Now it's time to move things forward a bit and see what other cool things we can do with them. The world of trigonometry in the world of games, however, is vast and sometimes frightening and to cover it all would take a gazillion tutorials! But we'll take everything slowly, piece by piece until we get there.

Now in lesson 19 we saw how to move our objects around the screen at a specific angle using raidans. That's pretty neat to look at, and certainly useful, but what else can we do with these mathy built-in functions?

Well....

How about moving things in a circular pattern? I guess you're probably sick of moving things in straight lines, right? Remember that you can apply velocity, friction, acceleration and the like to ANY sort of movement. You're certainly not limited to circular stuff! So let's see our circle in action...

MOVING IN A CIRCLE

Now before I show you the code, I think it's useful to consider what we'll need first.

Pretend, for example, that you want to move your phone around in a circular pattern on your desk. Also pretend that I'm trying to recreate this effect, but have no way of seeing what it is you're doing. I'd therefore need to ask you some questions to get a precise mental picture in my mind, namely:

How fast is it moving?
What's the radius/diameter of this circular pattern?
What is the exact location of the center point of this circle on the desk?

These are important questions and require that we make variables to specify them in our circle!

Therefore we're going to be adding these values:

centerPointX <--- The x value of the center point of our circle.
centerPointY <---- The y value of the center point of our circle.
radius <-----The radius of the circle we're going to be generating.
speed <-------How fast our circle will be moving.

also

angle <-------our angle (in radians) which will be increased by a specific amount with each iteration of the drawRectangle function.

So before I show you the code, just keep this simple idea in mind:

ALL moving in a circle means is constantly increasing the angle value.

Think it over: I've told you twice already that radians are nothing more than the subdivisions of 6.28 (2 PI/360 degrees). All we'll be doing is spinning our object around and around like hands on a clock moving around a fixed center point. It will start off at 0 radians (3 o'clock), then move around the circumference until it reaches 6.28 radians, at which point it will start over again at 0 radians. That's all there is to moving in a circle!

No let's take a peek at the code. Copy this and run it. Note that I've added a second little rectangle to illustrate where the center point is. Also note that the first fillRect is a little cluttered. We've had to add quite a few things in there, but this is only phase 1. Just wait until we get into objects and how they can help you in you gamedev pursuits!

So here it is:

<!doctype html>
<title>CIRCULAR MOTION</title>
<canvas id = "canvas" width = "550" height = "400"></canvas>
<style>
canvas
{
background-color: #dddddd;
}
</style>

<script>

var theCanvas = document.getElementById("canvas");
var context = theCanvas.getContext("2d");

var rectWidth = 50;
var rectHeight = 50;

var angle = 0;
var centerPointX = canvas.width / 2;
var centerPointY = canvas.height / 2;
var radius = 50;
var speed = .3;


window.setInterval(drawRectangle,30);

function drawRectangle()
{

context.clearRect(0,0,canvas.width,canvas.height);
context.fillStyle = "#44ff11";
context.fillRect(centerPointX - rectWidth / 2 + Math.cos(angle) * radius,centerPointY - rectHeight / 2 + Math.sin(angle) * radius,rectWidth,rectHeight);
context.fillStyle = "#ff0000";
context.fillRect(centerPointX, centerPointY, 3,3);
angle += speed;
}

</script>

Our rectangle is now spinning nicely around its two center points located at the exact center of our canvas.

If we analyze this we see the following:

Here are our variables. Pretty straightforward, just everything we described earlier.

var rectWidth = 50;
var rectHeight = 50;

var angle = 0;
var centerPointX = canvas.width / 2;
var centerPointY = canvas.height / 2;
var radius = 50;
var speed = .3;

Then in our fillRect() function we have this bad guy:

context.fillRect(centerPointX - rectWidth / 2 + Math.cos(angle) * radius,centerPointY - rectHeight / 2 + Math.sin(angle) * radius,rectWidth,rectHeight);

Lengthy, yes, but not all that complicated. All we're doing is defining the four standard elements of any old fillRect.

The first is our X value: If we chop up the first part we have:

centerPointX - rectWidth / 2 + Math.cos(angle) * radius

Which chopped up again gives us:

The x value of the center point of our rectangle MINUS the half the width of our rectangle PLUS the cosine value of our angle TIMES the radius of our circle.

A real mouthful, huh?

The second section is almost the same, except it deals with the Y value of our center point:

centerPointY - rectHeight / 2 + Math.sin(angle) * radius

Hence:

The y value of the center point of our rectangle MINUS half the height of our rectangle PLUS the sine value of our angle TIMES the raidus of our circle.

Got it?

And the last two values are just the run-of-the-mill width and height of our rectangle.

So why is the speed value so SMALL? We've usually used values like 3 or so for our VX and VY values. Why the small value here?

Well, that's because, as I explained above, we're increasing the angle for each iteration. Since we start off with an inital angle value of 0, then continuously add .3 to it every iteration, we'll eventually end up at a value of 6.28, which is essentially the same thing as 0, right? From there we continue on our way until we reach 0 again, then again and again and again creating the circular effect.

And that's all there is to say about circular motion! Next on our list: making oval-shaped patterns (ellipses) with our rectangle!

OVAL PATTERNS

The only real important point to consider when making ellipses is that you don't have a single radius anymore, but you need to consider how tall or how wide your ellpise will be. A circle, of course, doesn't need to bother with that stuff!

So instead of a radius variable, we'll add the following instead:

var ellipseWidth = 300; var ellipseHeight = 100;

And we'll replace the value of radius with these two guys once again, making our first fillRect():

context.fillRect(centerPointX - rectWidth / 2 + Math.cos(angle) * ellipseWidth,centerPointY - rectHeight / 2 + Math.sin(angle) * ellipseHeight,rectWidth,rectHeight);

Again, it's a mouthful, I know. But be patient until we get to objects, which are basically prefabricated things which have these values already inherent to them. It'll make your game dev. life a LOT easier, but I've held off on them for now because we have to first understand the principles behind these guys! Can't run until ya walk!

So here's the complete code:


<!doctype html>
<title>ELLIPTICAL MOTION</title>
<canvas id = "canvas" width = "550" height = "400"></canvas>
<style>
canvas
{
background-color: #dddddd;
}
</style>

<script>

var theCanvas = document.getElementById("canvas");
var context = theCanvas.getContext("2d");

var rectWidth = 50;
var rectHeight = 50;

var angle = 0;
var centerPointX = canvas.width / 2;
var centerPointY = canvas.height / 2;
var ellipseWidth = 300;
var ellipseHeight = 100;
var speed = .3;


window.setInterval(drawRectangle,30);

function drawRectangle()
{

context.clearRect(0,0,canvas.width,canvas.height);
context.fillStyle = "#44ff11";
context.fillRect(centerPointX - rectWidth / 2 + Math.cos(angle) * ellipseWidth,centerPointY - rectHeight / 2 + Math.sin(angle) * ellipseHeight,rectWidth,rectHeight);
context.fillStyle = "#ff0000";
context.fillRect(centerPointX, centerPointY, 3,3);
angle += speed;
}

</script>

And we now have or rectangle moving in a short/far elliptical pattern. Want tall/thin? Change your ellipseWidth and ellipseHeight to 100 and 300 respectively. And now we've covered two very important trigonomical concepts. These can be used ALL OVER THE PLACE! Ever played a game in which you have something hovering around your character like a force field or a weapon? That's trig! Ever seen games where you shoot stuff that flies off in a circular pattern? That's trig! Get the hang of this stuff, it's really quite useful!

To reinforce this, and to make a sort of mini review (next lesson is the big kahuna in which we'll make some mini games), let's add some bounce to the walls of our canvas, create a spinning object, and have it bounce all over the screen! Sound fun?

So here's the code. Take a gander, then we'll pick it apart like a buzzard!

<!doctype html>
<title>BOUNCING A SPINNING OBJECT</title>
<canvas id = "canvas" width = "550" height = "400"></canvas>
<style>
canvas
{
background-color: #dddddd;
}
</style>

<script>

var theCanvas = document.getElementById("canvas");
var context = theCanvas.getContext("2d");

var rectWidth = 50;
var rectHeight = 50;

var VX = 3;
var VY = 3;

var angle = 0;
var centerPointX = canvas.width / 2;
var centerPointY = canvas.height / 2;
var ellipseWidth = 60;
var ellipseHeight = 50;
var speed = .3;


window.setInterval(drawRectangle,30);

function drawRectangle()
{

context.clearRect(0,0,canvas.width,canvas.height);
context.fillStyle = "#44ff11";
context.fillRect(centerPointX - rectWidth / 2 + Math.cos(angle) * ellipseWidth,centerPointY - rectHeight / 2 + Math.sin(angle) * ellipseHeight,rectWidth,rectHeight);
context.fillStyle = "#ff0000";
context.fillRect(centerPointX, centerPointY, 3,3);
angle += speed;

centerPointX += VX;
centerPointY += VY;

if (centerPointX > canvas.width)
{
VX *= -1;
}
else if (centerPointX < 0 - rectWidth)
{
VX *= -1;
}

if (centerPointY < 0)
{
VY *= -1;
}
else if (centerPointY > canvas.height)
{
VY *= -1;
}

}

</script>

Now to be honest, there's NOT MUCH that was manipulated in these lines. The most significant verbage I made was to add the 4 if statements. What's at the heart of this, however, is the fact that we've used VX an VY in association NOT with rectX and rectY like we usually do, but with the centerPointX and centerPointY values. As you can see, under the line angle += speed, I've added these lines:

centerPointX += VX;
centerPointY += VY;

Finished! Piece of cake!

You can mess around with these values all you want and in fact, I recommend you DO! Try changing the speed to lightning fast or turtle slow! Make some really crazy elliptical shapes! Heck, what happens if you have THREE ellipse values - maybe two centerPointX values or something. What would happen then? Why not throw in another fillRect(), start it off at 3.14 radians and see what happens?

You've learned some really great tools today, so pat yourself on the back. Next week we'll make a couple cool mini games with the stuff we've covered since lesson 15. Gonna be a blast! Don't miss it! As always, you'll find me on Twitter @benwhi.

So stay tuned and I hope you enjoyed! As always, thanks for following along! Code didn't work for you? Hate me? Are you my illegitimate child? Send input anytime!

Until next time!

-Ben
@benwhi
Onward to Lesson Twenty One!
Back to Lesson Nineteen!
Back to Index