Game Development Community

dev|Pro Game Development Curriculum

Platforms...a simple start to a 3D side-scrolling platformer

by Bryan Sawler · 03/07/2011 (11:07 am) · 22 comments

Platforms...
A simple 3D side-scrolling platformer sample in a step-by-step format.

Step 1: Creating the project.
Go ahead and make a new project, using the Full template. Learning from my previous (Das Swarmy) resource I've decided since I'm keeping this fully script I'm not going to waste 5 minutes building. Current time is 10:35am.

Step 2: Setting the camera.
We're going to pull the camera back from the side. In game/scripts/server/gameCore at the bottom of the function GameCore::onClientEnterGame(%game, %client), just UNDER %game.preparePlayer(%client); we're going to add:
// Make the camera side-facing
%client.setCameraObject(%client.camera);
%client.camera.setOrbitObject(%client.player, "0 0 " @ -mDegToRad(90), 15, 25, 25, false, "0 2 1", true);
%client.setFirstPerson(false);

So we're aiming the camera at a -90 degree rotation, setting the camera 25 units away from the player, and actually aiming the camera 2 units in front of the player, and 1 unit up (we want to aim at the chest, not the feet).

Step 3: Controls
We're going to set REALLY simple controls. The right key will make me face (and move) to the right. The left key will make me face (and move) to the left. Mouse will do NOTHING, and up/down will (currently) do nothing. So, open up game/scripts/client/default.bind.cs and move down to the // Movement Keys section. Just under $movementSpeed = 1; we're going to add:
$facingDirection = 0; // right = 0, left = 1
A direction of 0 will be right, a direction of 1 will be left. Continuing down, the function moveleft and moveright will become:
function moveleft(%val)
{
	if(%val > 0 && $facingDirection == 0)
	{
		$mvYaw = mDegToRad(180);
		$facingDirection = 1;
	}
	$mvForwardAction = %val * $movementSpeed;
}
function moveright(%val)
{
	if(%val > 0 && $facingDirection == 1)
	{
		$mvYaw = mDegToRad(180);
		$facingDirection = 0;
	}
	$mvForwardAction = %val * $movementSpeed;
}
Now we're going to remove the lines in moveforward and movebackward so they become:
function moveforward(%val)
{
}

function movebackward(%val)
{
}
We'll leave the functions there and bound so that we can use them later. Lastly, we kill mouse turning / suppose so search for the line moveMap.bind( mouse, xaxis, yaw ); and comment it AND the yaxis line out. Save the file, and while you're in game/scripts/client delete config.cs and prefs.cs if they exist. The time is now 10:45

Step 4: Facing direction
We're going to make the camera bias to the direction we're facing. This will be a 2-step process so first, we need to setup a server command, and then we'll make the client call that comment. So, open up game/scripts/server/commands.cs and at the bottom of the file we'll add:
// Platformer support
function serverCmdsetCameraDirection(%client, %direction)
{
        %camera = %client.camera;
        %client.camera.setOrbitObject(%client.player, "0 0 " @ -mDegToRad(90), 15, 25, 25, false, %direction, true);
}
Now head back to that lovely game/scripts/client/default.bind.cs and we'll be adding the following:
Under $facingDirection we're going to add
$lookingOffset = 0;     // 0 = center, 1 = up, -1 = down
This will allow us to look up / down (told you we'd do something with them)
We'll be further modifying moveleft and moveright, to add a call to that serverCmd we just specified. So, edit them so they look like:
function moveleft(%val)
{
        if(%val > 0 && $facingDirection == 0)
        {
                $mvYaw = mDegToRad(180);
                $facingDirection = 1;
		commandToServer('setCameraDirection', "0 -3 " @ $lookingOffset); // ADDED
        }
        $mvForwardAction = %val * $movementSpeed;
}
function moveright(%val)
{
        if(%val > 0 && $facingDirection == 1)
        {
                $mvYaw = mDegToRad(180);
                $facingDirection = 0;
		commandToServer('setCameraDirection', "0 3 " @ $lookingOffset); // ADDED
        }
        $mvForwardAction = %val * $movementSpeed;
}
The added lines are noted there. This will tell the server when we've changed directions, and update the camera. Next up we're going to make moveforward and movebackward actually DO something. These will actually be our look up / look down functions (you can rename them if you like, which means also editing the moveMap.bind calls below them).
function moveforward(%val)
{
	if(%val > 0)
	{
		$lookingOffset = 1;
	}
	else
	{
		$lookingOffset = 0;
	}

	if($facingDirection == 0)
	{
		commandToServer('setCameraDirection', "0 3 " @ $lookingOffset); // ADDED
	}
	else
	{
		commandToServer('setCameraDirection', "0 -3 " @ $lookingOffset); // ADDED
	}
}

function movebackward(%val)
{
	if(%val > 0)
	{
		$lookingOffset = -1;
	}
	else
	{
		$lookingOffset = 0;
	}

	if($facingDirection == 0)
	{
		commandToServer('setCameraDirection', "0 3 " @ $lookingOffset); // ADDED
	}
	else
	{
		commandToServer('setCameraDirection', "0 -3 " @ $lookingOffset); // ADDED
	}
	doCrouch(%val);
}
Now we can look up/down as we go. Down will ALSO make us crouch

So here we go. It's now 11am. We have the VERY simple start of a platformer game. If there are specific requests for additions to this, please just ask, or if there are any other game "starting points" (similar to this / the 8-directional shooter Das Swarmy I posted) please ask! I have a few ideas for a part 2 if people seem interested.

About the author

President and Founder of The Muteki Corporation Makers of such fine iPhone games as MazeFinger, Topple 2, and The Battle of Pirate Bay!

Page «Previous 1 2
#1
03/07/2011 (11:24 am)
Very nice Bryan! Exactly such resources are needed for beginners. Would be cool if your resources, maybe a little fleshed out, would be part of standard torque doc.
#2
03/07/2011 (2:25 pm)
Very nice resource,Bryan!
This is a great start for Crash Bandicoot style games.
#3
03/07/2011 (3:48 pm)
Currently planned for the follow-up resource are:
1) Having the camera ANIMATE to the new position instead of snap
2) Some kind of "pickup" that you can collect
3) A hud that shows how many of those pickups you have, as well as some kind of score (which for now will just be pickups * 100 or so)

Anything else people could see as "necessary" in this style of game?
#4
03/07/2011 (4:44 pm)
Hi Bryan... I am definately interested... Thanks! Just last night I've been burning brain cells in default.bind.cs The problem? The camera followed the character in 2D style, but when i pressed left or right he started moving sideways... I was like NNNNNOOOOOoooooo! Thanks so much!
#5
03/08/2011 (4:56 am)
maybe a checkpoint system...make it possible for the player to die, and then respawn him at the last checkpoint?
Anyways Bryan, really nice tuts you are doing!
#6
03/08/2011 (6:27 am)
This is nifty. Keep up the good work!
#7
03/08/2011 (11:06 am)
I don't know if you published this resource because of that but I posted a similar request a few days ago (on the dedicated thread), so it's really great. I'll play with it a bit and post any feature that I think would make it more complete. Thanks a lot already! (I am already thinking about a "ledge grab" feature that most platformers have, but that's probably too much for a "getting started" resource)
#8
03/08/2011 (11:22 am)
amir, for the ledge grab, probably looking into the 3DAAK makes sense.
#9
03/08/2011 (3:21 pm)
What would be useful is the ability to retain keyboard and mouse controls when editing in the "World Editor" and when "game play" automatically swaping back to side scrolling controls.
#10
03/09/2011 (8:32 am)
Bryan, I would just like to THANK YOU for this! I've been reading through the documentation and searching the forums for THIS EXACT THING. You've rescued me from quite a few frustrated afternoons :D
#11
03/09/2011 (9:25 am)
@Ebonixs - working on that exact thing now (it's a problem that's plagued a few of my projects...keeping the editor controls sane while modifying game controls)

Hopefully I'll have that figured out soon and will include it in the follow-up post. Sadly "real work" has kept me from digging around / solving that yet this week.
#12
03/10/2011 (12:11 am)
No problem, just by sharing your info, you're inspiring and rejuvinating minds to be creative beyond being artist. Others are stepping back into coding just to see this work. Thanks again...
#13
03/22/2011 (3:01 pm)
Amazing, thank you. Im not trying to make this style of games but over the past 2 days I have been using your tutorials to help me learn the engine. This stuff is gold for people like me, I like the way you explain things. Thanks so much
#14
03/23/2011 (9:07 am)
Bryan, do oyu have an idea already on how to make sure that the controls act normal in the editor?
#15
03/23/2011 (3:03 pm)
This is a great great tutorial, thanks. As for other starting points I would love to see a 3D platformer with moving platforms or a double jump.

Thanks again.
#16
06/04/2011 (10:01 pm)
For what it's worth, people looking to keep the original WASD controls for the editor can just replace the original move functions with these:

function moveleft(%val)  
{  
   if(isObject( Editor ) && Editor.isEditorEnabled())
      $mvLeftAction = %val * $movementSpeed;
   else
   {
     if(%val > 0 && $facingDirection == 0)  
     {  
             $mvYaw = mDegToRad(180);  
             $facingDirection = 1;  
     commandToServer('setCameraDirection', "0 -3 " @ $lookingOffset); // ADDED  
     }  
     $mvForwardAction = %val * $movementSpeed;  
   }
}  
function moveright(%val)  
{  
   if(isObject( Editor ) && Editor.isEditorEnabled())
      $mvRightAction = %val * $movementSpeed;
   else
   {
     if(%val > 0 && $facingDirection == 1)  
     {  
             $mvYaw = mDegToRad(180);  
             $facingDirection = 0;  
     commandToServer('setCameraDirection', "0 3 " @ $lookingOffset); // ADDED  
     }  
     $mvForwardAction = %val * $movementSpeed;  
   }
}  
function moveforward(%val)  
{  
    if(isObject( Editor ) && Editor.isEditorEnabled())
      $mvForwardAction = %val * $movementSpeed;
    else
    {
       if(%val > 0)  
       {  
           $lookingOffset = 1;  
       }  
       else  
       {  
           $lookingOffset = 0;  
       }  
     
       if($facingDirection == 0)  
       {  
           commandToServer('setCameraDirection', "0 3 " @ $lookingOffset); // ADDED  
       }  
       else  
       {  
           commandToServer('setCameraDirection', "0 -3 " @ $lookingOffset); // ADDED  
       }  
    }
}  
  
function movebackward(%val)  
{  
   if(isObject( Editor ) && Editor.isEditorEnabled())
      $mvBackwardAction = %val * $movementSpeed;
   else
   {
       if(%val > 0)  
       {  
           $lookingOffset = -1;  
       }  
       else  
       {  
           $lookingOffset = 0;  
       }  
     
       if($facingDirection == 0)  
       {  
           commandToServer('setCameraDirection', "0 3 " @ $lookingOffset); // ADDED  
       }  
       else  
       {  
           commandToServer('setCameraDirection', "0 -3 " @ $lookingOffset); // ADDED  
       }  
       doCrouch(%val);  
   }
}

This will check when pressing the button if we're in the editor. If we are, we do the normal WASD, if not, our platforming controls.
Good resource, by the way!
#17
06/22/2011 (1:19 am)
Hi Bryan.
First of all i want to thank you for posting this superior guide which couldn't have been written in a more easy-to-understand English...
but i'm have some problems because i have tried to use this code and edit it to make the player able to go forward and backwards instead of looking up and down because i want to create a 2.5D side scrolling platformer in Torque 3D ....
Is there anyone who can fulfill this dream of mine???

But indeed the best guide/tutorial for platforming games in Torque3D!!!
#18
06/22/2011 (3:15 am)
@ David Mortensen

So... you mean like the classic arcade beat-em-ups? (TMNT, etc.)

I guess you'd just need to use this guide, and have your "up" and "down" movements be life FPS strafing.
#19
06/22/2011 (7:19 am)
@ Shaolin Dave

i think that is right what you're saying there but the thing is i'm a newbie to torque script so i don't understand how the language works... if you could tell me how to make this work i would be very grateful.
#20
07/08/2011 (2:53 pm)
Excellent resource, thank you. I was wondering what causes the pop when the player flips directions? Is it a problem with the mount the camera orbits on the character? I've gone through the offset settings and had no luck. It becomes much more noticeable when I shortened the distance from player to camera. Is there a way to fix this?

*When I offset the view in gameCore/commands and spawn in the game the view reflects the scripts settings, when I move the view snaps away and doesn't return the scripted values.
Page «Previous 1 2