CorEngine RSS
NAVIGATION >>
HOME TUTORIAL API TOOLS FORUM REPORT BUGS
:. Tutorial : Moving the camera

In this tutorial you will learn how to make a simple fly through camera

Step 1: W S A D


First we will modify the init.lua script file main loop. Here is how the init.lua script should look now:

  scene1 = Engine.LoadScene( "level1.pak" )

  while ( Engine.Run() == true ) do
  end

Hey! Whats that 'scene1' variable there before Engine.LoadScene? I didn't see it in the first tutorial!

Yeah, we didn't need it in the first tutorial. In addition to loading the scene, Engine.LoadScene also returns a handle to the loaded scene so that we can access the objects in the scene with it.

So the first thing we have to do is to gain access to the currently active camera. Lets write a line that does that for us.

  scene1  = Engine.LoadScene( "level1.pak" )
  camera1 = Scene.GetActiveCamera( scene1 )

  while ( Engine.Run() == true ) do
  end

We pass the 'scene1' variable we just got from Engine.LoadScene to Scene.GetActiveCamera to get the active camera in that particular scene.

So now we have our camera stored in the 'camera1' variable, what then? Well, now we will check on each frame (inside our while loop) if the user is pressing a certain button, and if he/she is, we will move the camera accordingly. Lets check for the W (we go forward with W) button first.

  scene1  = Engine.LoadScene( "level1.pak" )
  camera1 = Scene.GetActiveCamera( scene1 )

  while ( Engine.Run() == true ) do

    if ( Context.GetKeyState(KEY_W) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, -12.0 )
    end

  end

The Context.GetKeyState function returns the current state of the key passed to it. In this case we pass KEY_W, meaning the W key, to it. Here is a overview of the possible button states that Context.GetKeyState returns:

    * UP - the button is up
    * PRESSED - the button has been pressed on the current frame
    * DOWN - the buttons is being pressed but wasn't just pressed on the current frame
    * RELEASED - the buttons has been released on the current frame

So why do we have two states for a pressed button, PRESSED and DOWN? Basically when you press a button, its state changes to PRESSED for the current frame. After that, if the button is still pressed, the state changes to DOWN. The PRESSED is useful if you want to, for example shoot a gun a single time. If you used DOWN for that, you would be firing a bullet on every frame assuming that the button is still pressed. The DOWN is useful for continuous movement. If you would use PRESSED for that, your actor would move just for the instant the button is pressed and not when its down.

We use Actor.MoveLocal to move our camera. The actor functions can be performed on any actor. That is cameras, entities, lights and particles. And what does Local stand for in Actor.MoveLocal? That means that you are moving the actor according to its local orientation. For example, if you would use just Actor.Move, it would move according to the global x/y/z axises instead of moving according to the models local x/y/z axises. Yes, the three floating point values we pass to Actor.MoveLocal represent the amount of movement in 3D space during one second. Since we are moving a camera, we want to move it locally every time we are moving it front, back, left or right. That being said, there are many situations where you will want to move an actor according to the global axises, and you will most likely know when to do that.

Hey! Why are we moving the camera -12.0 to the Z direction, is that really moving to the front?

Yes it is. Why is that? Well the camera coordinate system is different from the coordinate systems of other actors. For a camera, negative Z is front, positive Y is up and positive X is right. Just remember that and you are good to go ;). Also remember that this only applies when moving the camera locally. When you are moving the camera with Actor.Move or any other globally moving function, it works just like with other actors.

Try out the code so far, if it works right, it should make the camera go forward when you press W. If it doesn't work, please check the console or CorEngine.log for errors.

Now, lets add the code for S, A and D.

  scene1  = Engine.LoadScene( "level1.pak" )
  camera1 = Scene.GetActiveCamera( scene1 )

  while ( Engine.Run() == true ) do

    if ( Context.GetKeyState(KEY_W) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, -12.0 )
    end

    if ( Context.GetKeyState(KEY_S) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, 12.0 )
    end

    if ( Context.GetKeyState(KEY_A) == DOWN ) then
      Actor.MoveLocal( camera1, -12.0, 0.0, 0.0 )
    end

    if ( Context.GetKeyState(KEY_D) == DOWN ) then
      Actor.MoveLocal( camera1, 12.0, 0.0, 0.0 )
    end

  end

Again, go ahead and test your code. Be sure to test your code a lot and often. If it works, you should be able to move the camera forward, back, left and right. If the code doesn't work, check the console or CorEngine.log for errors.

Step 2: Rotating the camera with the mouse


Now we are ready to code the rotation for the camera. We are going for a classic flythrough camera, so you will be able to rotate the camera with the mouse.

But wait, what is needed for that? First we need to make sure that the mouse is inside the window all the time so that we don't get weird jumps in rotation while the mouse enters the window and goes out. We can do this by passing true to function Context.HideMouse. Also since now we can't close the window by clicking the X symbol in the top right corner of the window like you usually do to windows, we need an alternate way to close the window. Lets do that with the ESC key. You can also shut down CorEngine with the F10 button on your keyboard, but it is nice to have some backup for it. Great! Lets add the code for this:

  Context.HideMouse( true )
  scene1  = Engine.LoadScene( "level1.pak" )
  camera1 = Scene.GetActiveCamera( scene1 )

  while ( Engine.Run() == true ) do

    if ( Context.GetKeyState(KEY_W) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, -12.0 )
    end

    if ( Context.GetKeyState(KEY_S) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, 12.0 )
    end

    if ( Context.GetKeyState(KEY_A) == DOWN ) then
      Actor.MoveLocal( camera1, -12.0, 0.0, 0.0 )
    end

    if ( Context.GetKeyState(KEY_D) == DOWN ) then
      Actor.MoveLocal( camera1, 12.0, 0.0, 0.0 )
    end

    if ( Context.GetKeyState(KEY_ESC) == PRESSED ) then
      Engine.Quit()
    end

  end

For clarification, the new lines of code are marked in RED. Now try to run the code and see if the mouse disappears and if the ESC button works. If not, don't worry, you can still close the window with F10 or ALT + F4 so that you can come back to fix your code.

So now we can move to camera rotation. For this, we need to know how much the mouse has moved during the current and the last frame. You could store the previous frames mouse position and calculate the differece between it and the current frames mouse position, but CorEngine already does this. You can access the difference with Context.GetMouseForce. The rest is just using the values we get from that:

  Context.HideMouse( true )
  scene1  = Engine.LoadScene( "level1.pak" )
  camera1 = Scene.GetActiveCamera( scene1 )

  while ( Engine.Run() == true ) do

    if ( Context.GetKeyState(KEY_W) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, -12.0 )
    end

    if ( Context.GetKeyState(KEY_S) == DOWN ) then
      Actor.MoveLocal( camera1, 0.0, 0.0, 12.0 )
    end

    if ( Context.GetKeyState(KEY_A) == DOWN ) then
      Actor.MoveLocal( camera1, -12.0, 0.0, 0.0 )
    end

    if ( Context.GetKeyState(KEY_D) == DOWN ) then
      Actor.MoveLocal( camera1, 12.0, 0.0, 0.0 )
    end

    mf = Context.GetMouseForce()
    Actor.Rotate( camera1, 0.0, 0.0, -mf.x * 10.0 )
    Actor.RotateLocal( camera1, -mf.y * 10.0, 0.0, 0.0 )

    if ( Context.GetKeyState(KEY_ESC) == PRESSED ) then
      Engine.Quit()
    end

  end

Because the mouse and 3d space coordinate systems are different, we use the negatives of the force as you can see. Also you can notice that we used just Actor.Rotate for the Z rotation instead of Actor.RotateLocal. That is because unless you are writing a flight simulator, you don't want the camera to turn around Z according to its own orientation. That would make the user "stand tilted". You can try Actor.RotateLocal on the Z rotation if you want to see the effect. Also keep in mind that the rotations we input are in degrees, not radians. Pretty much all rotation related functions in CorEngine use degrees.

Thats it! I hope you enjoyed the tutorial, and if you have any comments about it, please post to the forums.

SourceForge.net
CorEngine.sf.net Except where otherwise noted, content on this site is
licensed under a Creative Commons Attribution 3.0 License.