Basics of a platformer

From Game Editor

Revision as of 17:18, 21 January 2011 by Dst (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Game Editor is a good program to make platform games, which is another word for a jump'n run.

What is a platformer?

A platformer is a game, where you can move to the left and right. At the bottom there is the ground and the sky is in the top. In most platformers you can jump, in the view the player moves upwards in the sky. You can find an example for Game Editor called Caveman.

How to start

First of all you need your player, who you can move to the left and right. Add a new actor. The player should have at least two walking animations, one to the left and one to the right. When player stands still, we'll simply freeze him on the first frame of one of those animations. You can add many more animations later, such as jumping or running. Now you have to add two key down events for moving left and right. When moving left, the animation should be changed to moving left. You can make the moving either with reduce the actor's x position by each frame or you change the value of xvelocity to a negative number. Do the same with the inverted direction. Don't forget to set xvelocity back to 0 when releasing the moving keys. Your player should be able to walk now.

Now your player should be able to jump. Set yvelocity to a negative number (e.g. -10) when pressing the jumping key. The yvelocity should be bigger in the draw actor event to get a quite realistic gravity effect.

Your player will either fall down infinitely or you press the jump key to let him jumping. The ground is still missing.

You should make the ground and walls with tiles. Add a new actor and give him an animation for the tiles. Add the collision event for the player with the tiles. Use the function PhysicalResponse to let him stop at the ground.

Examples

There are several ways to make anything, not just one right way.

So here is a simple example and an intermediate example.

The intermediate example is a proper way to script movement so that you can make a complete game with it. There are other proper ways, this is just one of those.

There are simpler examples, and I know many of us, when we were new to programming, just wanted a simple way to make an actor move. If that's what you want, then here's the simple method:


Simple Example

KeyDown event -> left

xvelocity = -4;
ChangeAnimation("player", "walk_left", FORWARD);

KeyDown event -> right

xvelocity = 4;
ChangeAnimation("player", "walk_right", FORWARD);

KeyUp event -> left

xvelocity = 0;
ChangeAnimation("player", "stand_left", FORWARD);

KeyUp event -> right

xvelocity = 0;
ChangeAnimation("player", "stand_right", FORWARD);

KeyDown event -> space (jump)

yvelocity = -10;

DrawActor event

yvelocity += 0.5;


This will get your character moving, but is not much easier to input, and impossible to control or adapt later in the game creation. Simple things like adding attacks and hits or invincibility to these methods are incredibly difficult.

I urge you not to take that path; YOU WILL NOT BE ABLE TO MAKE A GAME WITH THE SIMPLE METHOD. At best, you will make a 1 level demo that doesn't really do much, and YOU WILL HAVE TO UNLEARN THAT METHOD SO THAT YOU CAN LEARN THE RIGHT ONE.

The Proper Method

Using this example, you can make your character follow the basic rules of SuperMarioBrothers games.

The first thing we need is a few variables to control our player. Create the following using the variables tab:

  • speed (actor, real) //the permanent speed of our player
  • hdir (actor, int) //our players horizontal keypress
  • vdir (actor, int) //vertical keypress
  • jump (actor, int) //the power of player jump
  • canjump (actor, int)//is player allowed to jump?
  • run (actor, real) //to indicate run key is pressed
  • facing (actor, string)
  • jumping (actor, string)
  • prevdir (actor, int) //our previous direction


To keep control of your player and it's animations in C the best method is to use strings. If you are not already familiar with it, a string can be substituted for arguments in a function. For example:

 char anim[32];  //creates a string called anim, 32 characters long 
 strcpy(anim, "playerwalking"); //sets the value of anim to playerwalking
 ChangeAnimation("player", anim, FORWARD); //note that you do not use "" on     
 // a string variable.

This will call changeanimation with a value of "playerwalking".

Now lets set our variables at the start of the game:

Player>CreateActor>ScriptEditor>

speed=4; //you can adjust this anytime, player speed
hdir=0;  //horizontal dir 0 = facing right
vdir=1;  //0=duck,  1=stand, 2=jump
jump=-12;  //player's jump ability (in negative numbers)
canjump=0; //cannot jump yet
run=1;    //

Now we've set the starting variables, we'll capture the keys and output the character action based on them.

Player>Draw Actor>

char * key = GetKeyState();  // This allows you to use keys as variables 
float tspeed=0;          //tspeed is temporaryspeed.
char anim[32];          //our animation string
run=1;                  //reset run (until pressed)
if(vdir==0){vdir=1;}   //ducking(vdir0) defaults to standing each 
//frame (until pressed again).

//get keys and set the variables------------------------------------>
if(key[KEY_DOWN]==1){
 if(vdir<2){ //if we are not jumping
vdir=0;                      //duck!
strcpy(jumping, "duck");    //for our animation
tspeed=0;                  //cannot move while ducking!
}
else if(vdir==2){ //if we are already in a jump
vdir=0;                    //duck!(While jumping!)
strcpy(jumping, "duck");    //for our animation
tspeed=speed;            //speed as normal!
               } }
if(key[KEY_SPACE]==1 && vdir!=2){ //if we are not jumping already
yvelocity=jump*canjump;           //jump! (if we have canjump!)
strcpy(jumping, "jump");    //for our animation
canjump=0;                        //prevents moonwalking
}


if(key[KEY_LEFT]==1){
hdir=1;                        //1=left, 0=right
if(vdir==0){ //ducking
 tspeed*=-1; //if jumpducking, tspeed already==speed, so just set the +-.
 //if we're normal ducking, tspeed is 0, so it will stay that way.
 }
else if(vdir>0){
tspeed=-speed;  //if not ducking, we have normal speed (left is-)
               }
 strcpy(anim, "LEFT");//our direction for animation
                     }


if(key[KEY_RIGHT]==1){
hdir=0;
if(vdir>0){      //for normal speed
 tspeed=speed;
 }
strcpy(facing, "right"); //our direction for animation
}


if(key[KEY_RSHIFT]==1){ //run button
run=2;
tspeed*=run;        //make us go faster!
} 


We now have all the variables we need to control the player! After this script runs in draw actor, we can look a the variables it output, and determine exactly what animation to depict for our player. We have 3 strings to assemble this animation from. anim - will store the entire animation name jumping - stores duck/jump/standing facing - stores left/right

So after this script, we're going to join them together, and process player movement.

Now we can use sprintf to join multiple strings and integers together. In this case, we only have strings.

 sprintf(anim, "%s%s%s", "player", jumping, facing);

We made a string that will result in words like: playerduckleft or playerjumpright. You will need to name your players animations to match this word scheme.

Now we use our new anim string on changeanimation.

Now the only issue to be found here is that unfortunately, we cannot use a string to control the final argument of changeanimation, that is FORWARD, STOPPED, NO_CHANGE. We will have to make a case switch for these.

However, it's quite simple really: Note that we haven't added our x and y movement to player yet; this is important. We must distinguish between standing and moving, because they will both use the walking animation, but when standing, it's stopped on the first frame. In addition, once we have started moving, we must use 'NO_CHANGE' to keep the animation cycling properly (we don't want to reset it each frame), but we also much start it at forward if it was stopped previously.

 if(vdir==1 && tspeed!=0){  //we only animate forward when walking running,
 //and a tspeed != 0 means we have pressed a key...
 if(xvelocity==0 || prevdir!=hdir){
 /*if we have a tspeed but our xvelocity is 0, then we WERE standing 
 but are now moving. If we have a tspeed and our hdir != prevdir, then
 the player has just changed direction. Either way, it's a new animation.
 */    
 ChangeAnimation("player", anim, FORWARD); 
 }
 else {  //if we haven't changed direction and are just moving forward
 ChangeAnimation("player", anim, NO_CHANGE);
 }
 }
 //
 else{  //if we are jumping, standing still, or jumping
 ChangeAnimation("player", anim, STOPPED);
 animpos=0;  //we will stay on frame 0 
 }
 
 //now apply all movement to the player.                   
 x+=tspeed;  //move the player if right/left was pressed
 yvelocity+=1; //gravity
 
 // and set our prevdir for the next frame
 prevdir=hdir;


Then on Player>Collision>TopSide>Block>RepeatYes>Script Editor>

PhysicalResponse(MOVE_EVENT_ACTOR_ONLY, USE_CALCULATED_MASS, 1,1,0,1);
canjump=1;      //we can now jump again!
if(vdir==2){ //if we were jumping
vdir=1;      //we are now standing/running (or ducking if you want)
}

And when player falls off a cliff, we need to turn off the canjump. Player>DrawActor>ScriptEditor (the same one we used above, not a new one):

if(yvelocity>2 && canjump==1){   //if player falls off a cliff and is 
//moving downward and has not jumped since leaving the cliff
canjump=0;       //player cannot jump now
vdir=2;        //falling is the same as jumping
}

Notice that you don't need any KeyDown or KeyUP events for this script to work!

The next step would be to create another variable to explain the user mode: normal, hurt, attack, invincible, and die, as a string. This would output a new string to add to our animation string.

Note that you can add infinite strings together using sprintf; The proper usage is

 sprintf(nameofstringtowriteto, "%s%s%s", string1, string2, string3);
 sprintf will always overwrite anything previously in the string. 

You can also add ints to the string using "%i" instead of %s.

If you do not wish to overwrite the string, but add more onto it, use strcat instead:

 strcat(nameofstringtoaddonto, nameofstringtoadd);

If you want to create different sets of player animations, i.e. big mario, raccoon mario, then simply add a new word to all of your animations, and insert that as another string into the sprintf. Only this one is a constant string, based on what powerup(s) the player has.

So playerjumpright would become playernormaljumpright, and player big would be playerbigjumpright;

Now we've got a complete interaction system going here already, which cannot be made from the simpler examples. Adding attacks to the simple methods and trying to synchronize them with jumping and running...is much harder than this method. In this method, it's just a matter of adding new words to the string, and setting the appropriate animation direction.

If you have another example, please add it to this page as its own example.