This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.
Now that you know about spinning and changing camera view, wouldn't it be nice to move forward and backward based on this view? Doesn't seem too hard right? After all, we did both movement and panning individually; how hard could it be to put them together? Not toooo much, but it's enough. There's that added complication of direction of movement. Before, with camera movement, we were always facing the same direction. Now, however, the camera is facing other directions so no longer would forward movement be associated with just the z value. It will include z and x. How much depends on the rotation of the camera, and getting how much involves...you guessed it, more trig.
If you think back to the triangle and rotating an object based on sine and cosine, what you are basically doing is moving an object from the origin and placing it cosine of angle times radius spaces along the x and sine of angle times radius spaces along the y, ultimately moving it all in that instance in a diagonal.
What if you repeat that process without rotating the line any further and just kept moving the shape by that x movement and that y movement? What you would get is motion in the direction of that angle! As the angle changes, so would the movement, but based on that shape's current position as long as those values kept getting added on to its current.
clip._x
+= Math.cos(angle)*radius;
clip._y +=
Math.sin(angle)*radius;
Compounding the new movement onto the present location sets it off to move based on the rotation or direction or positioning:
[ movement based on rotation ]
Now, just picture instead of that shape, you have an overhead view of the camera in its 3D environment. Since the angle represents the direction its facing, moving in that angle would mean moving camera forward in the direction of the view. Reverse that direction and you're going backwards. Easy, right?
The only thing is, since you've completely moved all the objects in the scene in respect to the camera, new radius values would have to be determined for each of those movieclips. With the trig functions learned earlier, this won't be a problem.
We'll go back to our figures from before and put a few in some simple stationary positions within the 3D space. Then, using what was described above, allow the user to move through the space using the arrow keys. Left and Right will turn left and right respectively and Up and Down will move forward and back.
[ moving and panning the camera ]
this.createEmptyMovieClip("theScene", 1);
theScene._x = 150;
theScene._y = 150;
objectsInScene = new Array();
cameraView = new Object();
cameraView.x = 0;
cameraView.y = 0;
cameraView.z = 0;
cameraView.rotation = 0;
focalLength = 300;
displayFigure = function(){
var x = this.x - cameraView.x;
var z = this.z - cameraView.z;
var y = this.y;
var angle = Math.atan2(z,x);
var radius = Math.sqrt(x*x + z*z);
x = Math.cos(angle + cameraView.rotation) * radius;
z = Math.sin(angle + cameraView.rotation) * radius;
if (z > 0){
if (!this._visible) this._visible = true;
var scaleRatio = focalLength/(focalLength + z);
this._x = x * scaleRatio;
this._y = y * scaleRatio;
this._xscale = this._yscale = 100 * scaleRatio;
this.swapDepths(Math.round(-z));
}else{
this._visible = false;
}
};
for (i=0; i<8; i++){
attachedObj = theScene.attachMovie("figure", "figure"+i, i);
if (i < 4){
attachedObj.x = -200
attachedObj.z = 50 + i*150
attachedObj.y = 0;
}else{
attachedObj.x = 200
attachedObj.z = 50 + (i-4)*150
attachedObj.y = 0;
}
attachedObj.display = displayFigure;
objectsInScene.push(attachedObj);
}
clip._x
+= Math.cos(angle)*radius;
clip._y +=
Math.sin(angle)*radius; walkAround = function(){
if (Key.isDown(Key.RIGHT)) cameraView.rotation += .05;
if (Key.isDown(Key.LEFT)) cameraView.rotation -= .05;
var movement = 0;
if (Key.isDown(Key.UP)) movement += 10;
if (Key.isDown(Key.DOWN)) movement -= 10;
cameraView.x += Math.sin(cameraView.rotation)*movement;
cameraView.z += Math.cos(cameraView.rotation)*movement;
for (var i=0; i < objectsInScene.length; i++){
objectsInScene[i].display();
}
};
theScene.onEnterFrame = walkAround;
|
|
WARNING! Reminder: Conflicting Depths |
|
With this last example you are able to see, before
panning, that there are a few figures in the back that overlap
incorrectly. This is due to the previously mentioned issue of
conflicting depths where if one object tries to share the depth of
another, those depths will actually swap. Because the figures are lined
up the way they are with 2 rows of figures each sharing a similar z with
the figure across from them, each of those figures will therefore also
try to share the same depth. In doing this, the figures swapped last end
up swapping depths with the opposing figure currently at the depth it's
trying to occupy. That being the case, some figures will end up being
swapped back to their originally attached depth thereby causing them to
be above other correctly swapped clips.
To prevent this, you can just lay out such clips not to share the same z to start, or just attach each clip at an appropriate depth relating to where they might be when displayed on the screen. You may, however, never have this problem and wouldn't then need to worry about it in the first place. If it does happen, though, it may need to be addressed. |
|
That wraps up this tutorial. A huge thank you to all of you who buy kirupa's books, became a paid subscriber, watch the videos, and/or interact on the forums. Your support is what keeps writing like this online! 😇
This tutorial was written by senocular, also known as Trevor McCauley. He has been one of this community's most generous teachers since the early Flash days, and he is still around: find him on senocular.com and on the forums.
:: Copyright KIRUPA 2026 //--