|
17.Apr.07 Lecture 11
Camera Pathing, Camera Control
Motivate
The world will not come to you. You are your network.
28 days left. 2 weeks until screen shots and marketing
materials are due.
Camera pathing
Here is a great example of camera
pathing. This would be used for flybys in cut scenes, machinima
or anything else you might dream up. I was thinking of using some
form of it in a puzzle game and created
this sample. This is basically the tutorial.base with changes
to the server/game.cs and server/camera.cs.
This is another page on moving
dts shapes along paths.
Perfect Circle Path
That path isn't very nice as it's just a random bunch
of points. My next step for a puzzle style game is to allow a camera
to move around the board in a perfect circle. To layout the circle,
first I place 8 points at the origin. The first thing you notice about
that tutorial.base (which I started with) is that the spawn point is
not set at the origin. I then moved it to the origin.
Next is they positioning of each of the path elements
in a perfect circle around the origin. I choice a round number of 40
units in the y direction for the first point. Since I have 8 points,
4 of them will be on the axises, but 4 will be inbetween the axises.
I used basic
trigonometry (yes I'm lame and had to look it up) to find the location
of one of these points.
x = sin(45) * 40 = 28.284
y = cos(45) * 40 = 28.284
Once I know the x and y it's just a matter of futzing
with the positive or negative sign to move the corner points into the
right locations.
This is what I came up with after I had placed them
all. I had to make a couple of simple sign mistakes when I placed the
rest of the points.
| Point |
x |
y |
| p1 |
0 |
40 |
| p2 |
-28.28 |
28.28 |
| p3 |
-40 |
0 |
| p4 |
-28.28 |
-28.28 |
| p5 |
0 |
-40 |
| p6 |
28.28 |
-28.28 |
| p7 |
40 |
0 |
| p8 |
28.28 |
28.28 |
This is what the path looked like as I laid it out.
You can begin to see the formation of a perfect circle.

Once that was done, I made my camera pathing play
through the whole sequence. Notice that the camera says pointed in
the direction of the y axis and you have to rotate each axis so the
origin points at the center where the puzzle board will be. To rotate
the axis simply point at the z axis (blue vertical), hold down the
alt key and right click. For this experiment you can simply rotate
until you have it close enough, but you are welcome to calculate the
actula rotation angle and enter it into the transform. After you do
this the path will always point at the center of the circle.
Once I had the paths setup, I started working on
geting the camera to move from point to point based on the character
press. There are probably a lot of ways to do this. For me, the least
amount of code seemed like it would be to use the existing pathing
system and just give it a bunch of smaller paths. To create those paths,
I simply used the larger circular path and created a bunch of one segment
paths.
function buildMovePaths(%client,%FullPath)
{
// build a list of SimGroup move paths
// these move from one node to the next in clockwise (left)
// and counter clockwise (right) directions
// for my case %FullPath = CamPath;
// it could aslo be %FullPath = "MissionGroup/CamPath";
%group = %FullPath;
if (%group != -1)
{
// build all the move right nodes
%cur = 0;
%count = %group.getCount();
while (%cur < %count)
{
%pt = %group.getObject(%cur);
// loop around if needed for the next point
if (%cur < %count - 1)
{
%ptnext = %group.getObject(%cur+1);
}
else
{
%ptnext = %group.getObject(0);
}
// create the new path
%setTmp = new SimSet();
%setTmp.add(%pt);
%setTmp.add(%ptnext);
// add the path/set for cleanup
MissionCleanup.add(%setTmp);
// now add it to our array
%client.moveRight[%cur] = %setTmp;
//echo("created right path " @ %cur @ " pt1=" @ %pt @ " pt2=" @ %ptnext @ " set=" @%setTmp);
%cur++;
}
%client.moveRightCount = %count;
}
}
I created two paths, one for the right hand movement
and one for the left. Take the existing path an iterate through each
element creating a new path current and next node. When on the last
node, use the first node as the end of the path. With each of these
points create a SimSet and add the two points to the set. I could have
used Path, but this is just a subclass of SimSet and only includes
one element isLooping which I did not plan to use. I added the new
set to the MissionCleanup so it is removed when the mission is unloaded,
then add the set to the moveRight array. Given the current location,
it is a simple matter to tell the engine to follow the rightPath using
the current location.
function nextCameraRight()
{
// move alont the moveRight paths created in buildMovePaths
if ($conn.PathCamera.moving == false)
{
// save the location we are moving from
%fromCamera = $curCamera;
// find the next location
$curCamera++;
if ($curCamera >= $conn.moveRightCount)
{
$curCamera = 0;
}
$conn.PathCamera.moving = true;
$conn.PathCamera.followPath($conn.moveRight[%fromCamera]);
}
}
We simply tell the camera to follow the path using
the current index. We also increment the index for the next keypress.
Here is a complete
sample of the puzzle game with the rotating camera. The 'a' and
'd' keys move the camera left and right.
One complaint about my implementation might be that
I've lost the curvature of the circle and the movement is now a straight
line from one point to the next. This wasn't critical to my design
so didn't spend any time on it.
Camera Speed
After the last sample I wanted to really speed up
the camera as I'm planning a fast action puzzle game. Looking at the
camera code in camera.cs:
function PathCamera::followPath(%this,%path)
{
%this.path = %path;
if (!(%this.speed = %path.speed))
%this.speed = 10;
...
}
As you can see from this code it's expecting a speed
variable. If it doesn't find one, it uses the arbitrary value of 10
for this path. You may think this means that you have to use an official
Path instead of SimSet, but it doesn't. We can simply add the speed
variable to the SimSet on creation.
In the buildMovePaths method, simply add these two
lines after the SimSet is created
// create the new path
%setTmp = new SimSet();
%setTmp.add(%pt);
%setTmp.add(%ptnext);
// set the speed
%setTmp.speed = 40;
You have to do this in two locations for the left
and the right arrays. I used a variable for 40, but only so it is easier
to read and change later.
Mouse Cursor
Since I wanted to be able to click on things in my
puzzle game, I also wanted the cursor to show. This is an easy change.
I simply opened the playGui.gui file and changed the noCursor value.
noCursor = "0";
This tells the gui to show the cursor. In your own
future coding, try to avoid naming your variables in a negative fashion
because the double negative thing will tend to hurt your brain. This
variable should have been called showCursor and set to 1 to show it
and 0 to hide it. Or hideCursor but even that has logic problems because
1 then means it isn't show which is not intuitive. Try using names
where 1 is on and 0 is off. 'No' is just causes my brain to go into
overdrive and gets really crazy when you start using it in complex
if statements.
In Agile
programming we are focused on efficiency. Anything that slows
us down is to be avoided or refactored. This type of double negative
will slow you down and adds up over time. Don't do it.
Mouse clicking and picking
Next up on my list was to be able to select objects
in my puzzle area with the mouse and interact with the object in the
puzzle through mouse clicking while moving the viewpoint around the
field with the keyboard.
After a bunch of trying with script, it looks like
I'll have to modify
the gameTSCtrl. While I'm not looking for a complete WoW interface,
there are specific elements in here that I'll need for what I'm doing.
In looking at the default gameTSCtrl it only catch mouse move events.
Math Extension
Bill made some changes
to the engine to avoid some string to floating point number conversions.
Let's talk about these changes.
Particle Effects
I'm still having trouble with this lecture. It's coming I promise.
|