TGB/Tutorials/Platformer/Camera

From TDN


Platformer Mechanics Tutorial

Written for TGB Version: 1.7.2


Focus on the Camera

Through the use of a behavior, a robust camera system will be created to handle different types of platformer styles.


Creating a Behavior


Create a new script file and call it platformerCamera.cs. Copy the following contents into this new file:

//-----------------------------------------------------------------------------
// Torque Game Builder
// Copyright (C) GarageGames.com, Inc.
// Behavior by Mike Lilligreen
//-----------------------------------------------------------------------------

if (!isObject(PlatformerCameraBehavior))
{
   %template = new BehaviorTemplate(PlatformerCameraBehavior);
   
   %template.friendlyName = "Platformer Camera";
   %template.behaviorType = "Camera";
   %template.description  = "Attach to a scene object for platformer camera controls";
   
   %template.addBehaviorField(target, "The object that the camera will track", object, "", t2dAnimatedSprite);
   %template.addBehaviorField(trackForce, "How the camera will follow target, 0 is rigid otherwise higher values mean less lag.", int, 0);
   %template.addBehaviorField(viewLimit, "Turn on camera view limit as defined by CLAMP world limit of object this behavior is attached to.", bool, false);
   %template.addBehaviorField(trackHeight, "Check to follow target in both X and Y, otherwise camera follows only in X.", bool, false);
   %template.addBehaviorField(facePlayer, "Camera will offset itself in direction player is facing if checked", bool, false);
   %template.addBehaviorField(xOffset, "Distance the target object should be from the center of the screen in X", int, 0);
   %template.addBehaviorField(yOffset, "Distance the target object should be from the center of the screen in Y", int, 0);
   %template.addBehaviorField(autoScroll, "Turn on auto scrolling of camera in X", bool, false);
   %template.addBehaviorField(trapObject, "Target object not allowed outside of scrolling camera view", bool, false);
   %template.addBehaviorField(scrollSpeed, "Velocity of auto scrolling", int, 5);
}

function PlatformerCameraBehavior::onAddToScene(%this, %scenegraph)
{
   // attaching the camera needs to be done via a schedule instead of directly here (TGB bug)
   %this.schedule(100, "attachCamera");
   
   // calls startAutoScroll function if box is checked in behavior
   if (%this.autoScroll)
      %this.schedule(1000, "startAutoScroll");
   
   // calls setViewLimit function if box is checked in behavior
   if (%this.viewLimit)
      %this.schedule(100, "setViewLimit");
}

function PlatformerCameraBehavior::attachCamera(%this)
{
   // mount the camera to the scene object and start the onUpdate function
   sceneWindow2D.mount(%this.owner, "0 0", %this.trackForce, true);
   %this.owner.enableUpdateCallback();
}

function PlatformerCameraBehavior::detachCamera(%this)
{
   sceneWindow2D.dismount();
   %this.owner.disableUpdateCallback();
}

function PlatformerCameraBehavior::onUpdate(%this)
{
   // if autoScroll and trapObject boxes are checked, confine the player within the camera view limits
   if (%this.autoScroll)
   {
      if (%this.trapObject)
      {
         %area = sceneWindow2D.getcurrentCameraArea();
         %this.target.setWorldLimit(CLAMP, %area);
      }
   }else
   {
      %newLoc = %this.target.getPositionX() + %this.xOffset;
      
      if (%this.trackHeight)
         %this.owner.setPositionY(%this.target.getPositionY() + %this.yOffset);

      if (%this.facePlayer)
      {
         // The $player.moveRight and moveLeft fields are taken from the playerClass.cs
         // file used in the basic platformer mechanics tutorial, you may have to change
         // this to get it to work with the PSK or your own movement code.
         %move = $player.moveRight - $player.moveLeft;
         if ((%move * %this.xOffset) < 0)
            %this.xOffset = -%this.xOffset;
            
         if (%this.xOffset > 0 || %this.xOffset < 0)
         {
            if ($player.moveRight || $player.moveLeft)
            {
               // This section creates a smooth acceleration of camera speed to prevent
               // a type of camera jitter during sudden left/right movements of the player
               $smoothCam++;
            
               if ($smoothCam > 10)
                  $smoothCam = 10;
               
               // the max %speed value should be larger than the player movement speed to
               // allow the camera to catch up to and pass the player
               %speed = $smoothCam * 5;
               %this.owner.moveTo(%newLoc, %this.owner.getPositionY(), %speed);
            }else
            {
               // if the player stops moving, so does the camera
               %this.owner.setAtRest();
               $smoothCam = 0;
            }
         }else
         {
            %this.owner.setPositionX(%this.target.getPositionX());
         }
      }else
      {
         %this.owner.setPositionX(%this.target.getPositionX() + %this.xOffset);
      }
   }
}

function PlatformerCameraBehavior::startAutoScroll(%this)
{
   // scrolling will start as soon as the player moves
   if ($player.moveRight || $player.moveLeft)
   {
      %this.owner.setLinearVelocityX(%this.scrollSpeed);
   }else
   {
      %this.schedule(100, "startAutoScroll");
   }
}

function PlatformerCameraBehavior::stopAutoScroll(%this)
{
   %this.owner.setAtRest();
}

function PlatformerCameraBehavior::setViewLimit(%this)
{
   // check the world limit mode of this object
   %limit = %this.owner.getWorldLimit();
   %mode = getWord(%limit, 0);
   
   // if CLAMP then set the camera view limit with the same values
   if (%mode $= "CLAMP")
   {
      %minX = getWord(%limit, 1);
      %minY = getWord(%limit, 2);
      %maxX = getWord(%limit, 3);
      %maxY = getWord(%limit, 4);
      
      sceneWindow2D.setViewLimitOn(%minX SPC %minY SPC %maxX SPC %maxY);
   }else
   {
      error("Wrong Limit Mode set - needs to be CLAMP");
   }
}


Remember to save the file in your project's behaviors folder. To have it display in the behavior drop down menu in TGB, either quit and reopen TGB or from the Project menu, choose Reload Project.

The Camera's Instruction Manual


To use this new behavior, first drag a Scene Object into your level (Figure 3.1). Then on this scene object's edit tab, give it the Platformer Camera behavior. While the size of the scene object doesn't matter, the position of the scene object does matter depending on whether you are tracking the Y direction movement of the player. Easiest is to place the object at the exact same coordinates as the player sprite. If you wish that the player is located a bit lower on the screen when playing the game, drag the scene object so its location is a bit higher than the player (Figure 3.2).

Figure 3.1
Figure 3.1
Figure 3.2
Figure 3.2


Although there is a tool tip that displays what each option does in this behavior, let's go over all the options available:

Figure 3.3
Figure 3.3


Target: This should be the object that you want the camera to follow. For the MiniPlatformer, it's obviously the player which also has the script name of "player". The behavior as it is set up now lets you select t2dAnimatedSprites only. If you want you can change the list of selectable objects by changing the t2dAnimatedSprite in this line:

   %template.addBehaviorField(target, "The object that the camera will track", object, "", t2dAnimatedSprite);


to either t2dStaticSprite or t2dSceneObject, for example.

Track Force: This value determines with how much lag the camera follows the player's movements. 0 is rigid (player and camera move in parallel), otherwise increasingly higher values also decrease the amount of lag seen.

View Limit: This check box turns on or off the camera's view limit. Similar to an object's world limit, the view limit traps the camera within a certain area of your level. This can be helpful to make sure the player doesn't see blank areas outside the tile layers or background sprites. To set this up, hover the mouse over the scene object and click on the far right tooltip icon for changing the object's world limits (Figure 3.4). Have the world limit box cover the entire area of your level (Figure 3.5). Hit enter to leave the world limit setup mode and now you can have the view limit box checked.

Figure 3.4
Figure 3.4
Figure 3.5
Figure 3.5


Track Height: If you want the camera to follow player movements in the Y direction, check this box. Otherwise it will only follow the player in the X (horizontal) direction. If this box is NOT checked, the position of the scene object this behavior is attached to does matter in relation to the player.

Face Player: This box is used in combination with the next field for setting the X directional offset. If you want the camera to always be 10 units in front of the player, set the xOffset value to 10 and check the facePlayer box. If this box is not checked and you have an offset, in one direction the camera will be ahead of the player and if the player moves in the opposite direction it will stay behind the player.

X Offset, Y Offset: The values you put in these fields will alter the position of the camera in relation to the player. 0, 0 will always keep the player in the center of the screen. The Y Offset value only works if you have the trackHeight box checked.

Auto Scroll: Like certain levels in the Super Mario Bros. games, checking this box will have the camera move at a constant speed defined by the scrollSpeed field and does not follow the player. Currently auto scrolling is only enabled for the X direction.

Trap Object: Traps the object defined in the target field within the current area of the camera.

Scroll Speed: How fast the camera scrolls in Auto Scroll mode is defined by this field.


As a final note, this behavior has been set up to work based on the movements defined in the Platformer Mechanics tutorial. If you wish to use this with the Platformer Starter Kit or your own movement code, certain sections of the behavior will have to be rewritten.


Return to Platformer Mechanics Tutorial Hub