GameDev1:Session 6
Contents
Learning Objectives
- Know how to use Math.PI when rotating an object
- Understand the purpose of a Tween
- Know how a ray is used to detect collisions
Preparation
- If you have a laser pointer handy, it could serve as a useful (and fun!) visual aid when discussing rays . Just don't point the thing in anyone's eyes, and don't let the students play with it.
Lesson Overview
This lesson is divided into three parts, each with a quick discussion and coding time. Be sure to keep track of timing, as each section will have a hard stop to allow students to keep pace.
Today we're going to learn how to turn our avatar to face the right direction (as well as animate the turning). We're also going to learn how to keep the avatar from walking right through the trees, so let's jump right to it!
Turning the avatar
Discussion: Rotation and Math.PI [5-10 minutes]
Ask for a volunteer student to stand at the front of the room, and tell the class that this person will be our Avatar. Ask the student to turn in different directions using degrees as directions.
I'm going to tell you to face different directions, but instead of North, South, East, and West, I'm going to use degrees.
0° is facing forward. When I tell you to turn to a certain number of degrees, I want you to turn counter-clockwise (or to your left) to face that point.
- Turn to 90° (should be facing their left)
- Turn to 180° (should be turned back facing class)
- Turn to negative 90° (should be facing their right)
- Turn to 0° (should be facing forward)
Now explain how we use radians when coding, not degrees, and that we can easily convert using PI.
- Turn a quarter turn to the left. (ask the class: how many degrees is that?)
- Face forward again.
- Now turn a half turn (how many degrees was that?)
We know that a quarter turn is 90°, and a half turn is 180°. But how many radians is that?
Did you know, 180° is equal to 3.14 radians? Does that number sound familiar? Can anyone tell me what 3.14 is?
That's all you have to remember -- π (radians) is 180 degrees!
When we're coding, we can use
Math.PI
to represent the exact value of π.
Now see if you can get the student to turn to face a direction by speaking only in terms of π .
Note: student should always be turning counter-clockwise (or left) to mimic how the avatar will turn
- Turn to π (should be facing backward, or 180°)
- Now turn to 0 (should be facing forward)
- Turn to half of π (should be facing left)
- How many degrees is that?
- How would I tell you to face right, or -90°?
Coding: Face the right direction [10-15 minutes]
Have students turn to chapter 8, and start at section 8.2 - Facing the proper direction .
Step 1
: Add
turn();
inside our
animate()
function.
Step 2
: Define the turn function in which we rotate our avatar. We can add our new function definition below the
walk()
function:
function turn() {
var direction = 0;
if (is_moving_forward) direction = Math.PI;
if (is_moving_back) direction = 0;
if (is_moving_right) direction = Math.PI / 2; // player's right, avatar's left
if (is_moving_left) direction = -Math.PI / 2; // player's left, avatar's right
avatar.rotation.y = direction;
}
Have students test out their code.
Discussion: What is Tweening [5 minutes]
Tweening allows us to smoothly animate a change from one state to another. For example, instead of instantly "jumping" from facing forward to facing left, we want the avatar to smoothly rotate over a small period of time.
Ask another volunteer to the front of the class to demonstrate (this will be quicker than the last demonstration):
When you turn your avatars 180°, what happens?
- Go ahead and face 180° (or π radians).
- Now, do it again, but more slowly.
That doesn't look quite like how our avatar does it. Our avatar just magically teleports from facing one direction to another.
I could tell (student name) to turn to 1°, then 2°, then 3°, then 4°, over and over until we get to 90°, but that would be a lot of work. We can make this easier using what's called a "TWEEN" to have the computer automatically do the in-be TWEEN stages of the turn.
Ask the student to be seated, and have students look at the bottom of page 83
We do this by creating a special new TWEEN object.
- We give a starting point, which is the avatar's current rotation (
avatar.rotation.y
)- In the
to()
part, also tell it the place where we want it to end up (the new direction), and how long we want the animation to take (100 milliseconds).- The
onUpdate()
part runs every frame (remember, we have about 30-60 frame every second).this.y
is the direction we want to be facing in that particular frame.That code that starts with
new TWEEN
could all be on one line, but we break it up over multiple lines to make it easier to read.
Coding: Animate the turn [15-20 minutes]
IMPORTANT
: Before beginning this section students will need to add the
Tween.js
file to their workspace (see steps 1 & 2 below).
|
Step 1 : Enter http://gamingjs.com/Tween.js in the browser, then click File -> Save As to download the file.
Step 2 : In Cloud 9, click on the Workspace tab on the left to view your project files. Click the js folder, then select File -> Upload File to upload Tween.js (Note: it must be uploaded to the js folder):
Step 3
: Add
TWEEN.update()
to the
animate()
function.
Step 4
: In your
turn()
function, change the last line (
avatar.rotation.y = direction
) to
spinAvatar(direction)
.
Step 5
: Add the
spinAvatar()
function definition below the
turn()
definition:
function spinAvatar(direction) {
new TWEEN
.Tween({y: avatar.rotation.y})
.to({y: direction}, 100)
.onUpdate(function() {
avatar.rotation.y = this.y;
})
.start();
}
Have the student see what happens when you change the
100
to
1000
.
1000
milliseconds is one second, so it takes a whole second for the tween to complete.
Break [10 minutes]
Collision detection
Discussion [10-15 minutes]
Explain why collision detection is a challenge in 3D games:
- We take a lot for granted when we play 3D games. The fact that your character doesn't walk through walls or fall straight through the ground is due to some careful programming by the game developer.
- This is a common problem to solve in game development, and is called "Collision Detection". We need to detect when two objects collide, and perform some action when they touch.
- We need to write code that detects when our avatar is near the tree, and stop him from moving
- It would take a lot of computing power to check every point on your avatar and every point of the tree, and then check if any of those points overlap. That would really slow our game down because the computer would have to check this dozens of times per second.
Ask for another student volunteer to play the Avatar. Hand them a pencil, pen, or something representing the ray. If you have a laser pointer or flashlight handy, use that.
Place a flat object like a piece of paper on the ground, a few feet in front of the student. We're going to use this as the "boundary" that we collide with.
Instead we're going to take a shortcut. We're going to use what's called a ray . Think of a ray as a beam from a laser pointer. It has a starting point, and then points in a certain direction. It's very simple and much easier for the computer to work with.
(student name) here is going to hold the "ray" pointing down toward the ground. We're going to use that "ray" to detect if they've crossed a boundary.
This piece of paper is our boundary, and we want to check to see if they touch the boundary. But all we have to do is check to see if the ray is pointing to the piece of paper:
I'm going to ask (student name) to walk forward a little bit at a time. Think of this as one frame in our game (remember, we can have 30-60 frames in a second).
- Ok, (student name) , step forward 6 inches.
- Is the ray pointing at the paper? No?
- Ok, step forward 6 more inches
- Is the ray pointing at the paper?
Keep repeating until the "ray" is over the piece of paper.
Now the ray is over the piece of paper, so we need to undo that last move!
- Ok, step 6 inches backward.
This is how we can keep our avatar from crossing over into the tree's boundary!
Have the student take a seat, and briefly explain how we're going to do solve this problem. It may help to outline the major steps on the whiteboard:
To detect collision with trees, we're going to do the following:
- Create a circular boundary around our trees that acts like a "fence"
- Store these boundaries in a list so we can check them later
- Create a function called detectCollisions(). Inside this function we'll do the following:
- Create a ray pointing down from the center of the avatar
- Check to see if that ray intersects with any of our boundaries
- If it does, we're going to return "false" if it's not colliding, and a "true" value if it is colliding.
- We'll then use this function in our keyDown listener, which is where we have the code that moves the avatar.
- If we detect a collision, we have to move the avatar back outside the boundary so it doesn't get stuck forever.
- So if we're moving left, we need to move the avatar right a few pixels. If it's moving forward, we need to move the avatar back a few pixels. (We're basically "undoing" the last movement).
Let's get to coding!
Coding [20-30 minutes]
Have students start at the top of page 96 . The steps are as follows:
Step 1
: Declare a list variable called not_allowed to keep track of our boundaries:
var not_allowed = [];
We haven't learned the Javascript concept behind
[]
yet, but you can tell students this is called an
Array
, and we use it to keep things in a list. We'll learn more about these in a later session.
|
Step 2
: In your
makeTree()
function, create the boundary object as a flat circle at the base of the tree:
// This goes just after: trunk.add(top);
var boundary = new THREE.Mesh(
new THREE.CircleGeometry(300),
new THREE.MeshNormalMaterial()
);
boundary.position.y = -100;
boundary.rotation.x = -Math.PI/2;
trunk.add(boundary);
not_allowed.push(boundary);
Step 3
: write the
detectCollisions()
function. You can put this at the very bottom of your code.
function detectCollisions() {
var vector = new THREE.Vector3(0, -1, 0);
var ray = new THREE.Ray(marker.position, vector);
var intersects = ray.intersectObjects(not_allowed);
if (intersects.length > 0) return true;
return false;
}
Step 3: Add the following at the end of the
keydown
event listener (before the closing brace):
encourage copy/paste here, just make sure and read closely to change what needs to be changed. |
if (detectCollisions()) {
if (is_moving_left) marker.position.x = marker.position.x + 5;
if (is_moving_right) marker.position.x = marker.position.x - 5;
if (is_moving_forward) marker.position.x = marker.position.z + 5;
if (is_moving_back) marker.position.x = marker.position.z - 5;
}
Have students test their code.
Exit Tickets [10 minutes]
Have students complete today's exit ticket .