Game Development Community

Move the camera

by Gavin Beard · in Torque Game Builder · 03/20/2008 (1:43 pm) · 14 replies

Hi all,

Just trying to get a simple system to move the camera in accordence to the mouse movement whilst the right mouse buttom is being held on a tile map. I have it working but is very jumpy and not like how the tgb editor window works.

here is my code:
$MyGame::rMouseDown=0;
$MyGame::mapX=0;
$MyGame::mapY=0;
$MyGame::MouseX=0;
$MyGame::MouseY=0;

function startGame(%level)
{
   Canvas.setContent(mainScreenGui);
   Canvas.setCursor(DefaultCursor);
   
   new ActionMap(moveMap);   
   moveMap.bind(keyboard,"u",moveUp);
   moveMap.push();

   sceneWindow2D.setUseObjectMouseEvents( true );
   sceneWindow2D.setUseWindowMouseEvents( true );

   $enableDirectInput = true;
   activateDirectInput();
   //enableJoystick();
   
   sceneWindow2D.loadLevel(%level);
}
function mBaselyr::onRightMouseDown(%this, %modifier, %worldPosition, %mouseClicks)
{
   $MyGame::rMouseDown =1;
   $MyGame::mapX=sceneWindow2d.getCurrentCameraPosition.x;
   $MyGame::mapY=sceneWindow2d.getCurrentCameraPosition.y;
   $MyGame::MouseX = sceneWindow2d.getMousePosition().x;
   $MyGame::MouseY = sceneWindow2d.getMousePosition().y;
}
function mBaselyr::onRightMouseUp(%this, %modifier, %worldPosition, %mouseClicks)
{
   $MyGame::rMouseDown=0;

}
function mBaselyr::onRightMouseDragged(%this, %modifier, %worldPosition, %mouseClicks)
{
   if ($MyGame::rMouseDown)
   {
      sceneWindow2D.setCurrentCameraPosition($MyGame::mapX+($MyGame::MouseX-sceneWindow2d.getMousePosition().x),$MyGame::mapY+($MyGame::MouseY-sceneWindow2d.getMousePosition().y));
      //sceneWindow2D.startCameraMove(0);
   }
}

this is located within my game.cs file, and as i say, when i drag the window it is very jittery
is the anything i can do to make this work better?

many thanks

#1
03/20/2008 (2:54 pm)
Not having tried this mind you, but how about setting a tolerance threshold before moving the camera?
ie only move the camera after the mouse has dragged +/- n units.
#2
03/20/2008 (3:07 pm)
Isn't the reason for the jittery camera because you're just setting the camera position by hand? You're going to need to find some way of moving it properly, not just changing its position.
#3
03/20/2008 (3:18 pm)
@Simon

Thanks, i shall look at this.

@Phillip
Sorry not sure i understand? surely setting the position by hand is moving it properly? or am i missing something, sorry to sound stupid?
#4
03/20/2008 (4:01 pm)
The engine will render the screen more frequently than it processes scripts. So when an object moves from A to B, the engine renders A, (A + B) / 2 and then B so it appears nice and smooth (a process called interpolation). When you just set the position of an object it will not render the middle frame making it appear choppy.

To avoid this, you must let the engine interpolate between points. To do this you must apply velocities and not position updates.

I have never been able to get the move camera methods working, so I always mount the camera to an object and then move the object (either by changing its linear velocity or using the moveTo function).

Hope that cleared a few things up for you.
#5
03/21/2008 (4:08 am)
@Phillip

many thanks, i shall look into this a bit further then

Update
Changed the move code to:
sceneWindow2D.setTargetCameraPosition($MyGame::mapX+($MyGame::MouseX-sceneWindow2d.getMousePosition().x),$MyGame::mapY+($MyGame::MouseY-sceneWindow2d.getMousePosition().y));
      sceneWindow2D.startCameraMove(0.5);
Which stops jitter but, the direction seems to vary :-)
#6
03/21/2008 (6:15 am)
With 1.1.3, I know that the camera moves started off slow, then gradually increased to a peak speed in the middle between the starting position and target position, then they slowed down again.

I would suggest doing what Phillip says. That way you can apply forces to a scene object that are linear.

Here's some code that I wrote for an RTS style camera a couple weeks ago:

function sceneWindow2D::onMouseMove(%this, %modifier, %worldPosition, %clicks)
{
    %windowCoordinates = sceneWindow2D.getWindowPoint(%worldPosition);
    %x = getWord(%windowCoordinates, 0);
    %y = getWord(%windowCoordinates, 1);
    %worldX = getWord(%worldPosition, 0);
    %worldY = getWord(%worldPosition, 1);
    
    if(%x <= 50 || %x >= 750 || %y <= 50 || %y >= 550) 
    {
        %vec = t2dVectorSub(%worldPosition, cameraHolder.getPosition());
        %angle = -mRadToDeg(mATan(getWord(%vec,0),getWord(%vec,1)));
        cameraHolder.setLinearVelocityPolar(%angle, -30);
    }
    
    else
        cameraHolder.setLinearVelocityPolar(cameraHolder.getRotation(), 0);
}

What it should do: when you move the mouse to the edge of the screen, the camera will move in an angle between the center of the screen and the mouse cursor.

Given: that cameraHolder is an object that has the camera mounted to it.

Note: the first five lines are converting the parameters to coordinates you can use with the action window. If you have only one window, this is probably unnecessary. Also, this code accounts for a 800 by 600 resolution. Change the if statements as necessary. You could even replace that if statement with something like:

Pseudo code:
if(%x <= 50 || %x >= (getWord(getResolution(), 0) - 50) || %y <= 50 || %y >= (getWord(getResolution(), 1) - 50))
#7
03/21/2008 (7:14 am)
I've become a proponent of mounting the camera to something and indirectly controlling it through that object to which it is mounted.
#8
03/21/2008 (9:48 am)
I definitely agree with Jason. When I want to do anything complex with the camera I often find it valuable to mount it to an object and control it that way.
#9
03/22/2008 (3:18 pm)
Many thanks to all for the help

i shall play a little more with the examples and code given and report back
#10
03/23/2008 (4:26 am)
@Kevin

Your code and method work great, have changed it to only move when right move button is down, cant seem to do this without using a global variable which is changed when the mouse button is pressed on the map.

but it works

many thanks
#11
03/23/2008 (5:13 am)
I'm glad that chunk of code could be of use to you. I'll probably be doing something similar to what you did pretty soon. (Making the camera move only when a mouse button is pressed.)

Doesn't seem like a global variable should be necessary, but it doesn't really matter. You'll probably come back to this code in a couple months and know how to fix it without using global variables. ;)
#12
03/23/2008 (3:52 pm)
Lol, would hope so, just cant see any other way to check if mouse buton is down lol
#13
03/16/2012 (5:50 am)
The way I got mine to work with a right click was using orbit. Now I need to change it from right click to left drag. Can anyone give me an idea on how I can use the scenewindow2d function or how can i implement left drag using this function.

Thank you.

function Orbit()
{
   //Orbit point is the center of the arrows with a z-axis of +1
   %rot = $Camera.getRotation();
   $Camera.setOrbitMode(0, $Position @ " 0 0 1 0", 2, 3, 3, true, "0 0 1", false);
   $Camera.setRotation(%rot);
}
#14
12/23/2012 (9:02 am)
This thread helped me devise a nice click and pan system. Thanks!