People who have visited this shit

GMS Tutorial - Platformer System


So now Michael Grubbs Asked me on twitter about the code i use for character of my GM48 Game, i always use the same code for my platformer games changing, and improving some features everytime, right now i think i got to a point where the player feels pretty good, here’s a little gif of my current Player control

image

(I’ll not include the sword attack on this “tutorial”)


So let’s start with some coding!

First of all we initialize the variables for our player object in the Create Event

/// Initialize Variables

horSpeed  = 0.0;               // Current horizontal speed
verSpeed  = 0.0;               // Current vertical speed
jmpSpeed  = 4.0;               // Max jump height
maxSpeed  = 3.0;              // Max horizontal speed
runSpeed  = 5.0;               // Speed when running

mainAccel  = 0.1;              // The speed our player will accelerate
mainFric    = 0.2;               // The speed our player will stop moving
mainGrav  = 0.2;               // The gravity for our player to fall
mainDir      = 1.0;              // Keep track of where our player is looking

slideGrav = 0.15;              // The gravity for our player when sliding on a wall

tempSpeed = 0.0;             // This will keep track of what our horSpeed is (if we are running or not)
tempGrav  = mainGrav;    // This will keep track of our current Gravity (if we are sliding or not)
tempState = 'idle';             // This keeps track of our current action (useful for changing sprites)

jmpCount  = 2.0;              // The ammount of jumps we can make (double or triple jumps or more)
colLeft   = place_meeting(x - 1, y, parentSolid);   // Used for wall jump
colRight  = place_meeting(x + 1, y, parentSolid); // Used for wall jump


Now that we have declared our variables we can start to work on the step event so our player actually moves, i’ll mark with bold italics  what you can just delete and the code will keep working perfectly, things as the wall jumping, sliding, wall jumping

before starting i fogot to say something, you’ll need this script

///approach( var, target, shift)
return (argument1 - argument 0) * argument2


This is a pretty simple script the argument0 (var) is the variable we want to get changed, argument1 (target) is the value we want to set that variable and the argument2 (shift) is the... “velocity“ we are going to approach that variable to it’s target, something like 0.1 (this would be something like approach the 10% each time of the difference between the variable and it’s target)

/// Control of the player
// Set the keys
var keyLeft, keyRight, keyJump, keyJumpHold, keyDrift, keyRun, keyUp;
   keyLeft           = keyboard_check(ord('A'));
   keyRight         = keyboard_check(ord('D'));
   keyUp             = keyboard_check(ord('W'));
   keyRun          = keyboard_check(vk_shift);
   keySlide         = keyboard_check(ord('P'));

   keyJumpHold = keyboard_check(vk_space);
   keyJump        = keyboard_check_pressed(vk_space);

   /// Update variables
   /// Here we update the wall checks for our wall jumps
   colLeft   = place_meeting(x - 1, y, parentSolid);
   colRight  = place_meeting(x + 1, y, parentSolid);

// React to the input
// Sliding, this is just optional
if (keySlide&& abs(horSpeed) > 0.1 && tempState != 'Slide') {
   horSpeed += approach(horSpeed, 0.0, mainFric * 0.1);
   tempState = 'Slide';
} else {

   if (place_meeting(x, y-1, parentSolid)) {
       // This is so our player wont get stuck while sliding
       horSpeed += approach(horSpeed, 0.5 * mainDir, mainAccel);
   } else {
   
       // Run Action (This is used to make our player run
       // also dont really need this depending on your game
       // but i recommend using it)
       if (keyRun) {
           tempSpeed += approach(tempSpeed, runSpeed, mainAccel);
       } else {
           tempSpeed += approach(tempSpeed, maxSpeed, mainAccel);
       }

       // Move Horizontally
       if (keyLeft && !keyRight) {
           horSpeed += approach(horSpeed, -tempSpeed, mainAccel);
           mainDir = -1.0;
           tempState = 'Walk';
       } else if (keyRight && !keyLeft) {
           horSpeed += approach(horSpeed, tempSpeed, mainAccel);
           mainDir = 1.0;
           tempState = 'Walk';
       } else {
           horSpeed += approach(horSpeed, 0.0, mainFric);
           tempState = 'Idle';
       }
   }
}

// Move Vertically, add gravity if we are not in the ground
// parentSolid is just our solid object, obj_solid, or however you’ve
// called your block object
if (!place_meeting(x, y + 1, parentSolid)) {
   if (verSpeed < 10) {
       verSpeed += tempGrav;
   }

   tempState = 'Jump';

   // Slide through the wall (for walljumping)
   if ((colLeft || colRight)) {
       horSpeed = 0.0;
       tempGrav = slideGrav;

       tempState = 'Slide';
       mainDir   = (-colLeft) + colRight;

       jmpCount = 2.0;
   } else {
       tempGrav = mainGrav;
   }

} else {
   jmpCount = 2.0;
}

/// JUMPING
if (keyJump && jmpCount >= 1.0 && tempState != 'Slide') {
   // (1.0 + (jmpCount == 1.0)) is used so our second jump is less
   // high than our first jump, this is completely optional and if you have
   // set jmpCount to 1.0 (no double jumps) you shouldn’t write that

   verSpeed = -jmpSpeed / (1.0 + (jmpCount == 1.0));
   jmpCount--;
   tempState = 'Jump';
}

// Variable Jump height
// I really, really recommend this, it just make your player fell a lot better
// this gives the player a lot more of control to the player, it is optional,
// but i really recommend you adding it
if (!keyJumpHold && verSpeed < 0.0) verSpeed = max(verSpeed, -jmpSpeed / 3.0);

// Wall Jump
// Right Wall Jump
if (keyJump && colLeft && !place_meeting(x, y + 1, parentSolid)) {
   if (keyLeft) {
       verSpeed = -jmpSpeed * 1.1;
       horSpeed =  maxSpeed;
   } else {
       verSpeed = -jmpSpeed * 1.1;
       horSpeed =  maxSpeed * 1.1;
   }
}

// Left Wall Jump
if (keyJump && colRight && !place_meeting(x, y + 1, parentSolid)) {
   if (keyRight) {
       verSpeed = -jmpSpeed * 1.1;
       horSpeed = -maxSpeed;
   } else {
       verSpeed = -jmpSpeed * 1.1;
       horSpeed = -maxSpeed * 1.1;
  }

}

/// Collisions
// Horizontal Collisions
if (place_meeting(x + horSpeed, y, parentSolid)) {
   while (!place_meeting(x + sign(horSpeed), y, parentSolid)) {
       x += sign(horSpeed);
      
       // Here i check if the player has gone inside a solid object, fix
       // it’s position and also exiting the while loop so the game doesn’t
       // get stuck into a while loop if this happens and so the player
       // won’t also get stuck
       if (place_meeting(x, y, parentSolid)) {
           x = xprevious;
           exit;
       }
   }
   horSpeed = 0.0;
}

x += horSpeed;

// Vertical Collisions
if (place_meeting(x, y + verSpeed, parentSolid)) {
   while (!place_meeting(x, y + sign(verSpeed), parentSolid)) {
       y += sign(verSpeed);

       // Here i check if the player has gone inside a solid object, fix
       // it’s position and also exiting the while loop so the game doesn’t
       // get stuck into a while loop if this happens and so the player
      // won’t also get stuck
       if (place_meeting(x, y, parentSolid)) {
           y = yprevious;
           exit;
       }
   }
   verSpeed = 0.0;
}

y += verSpeed;


I’ve commented the piece of code as best as i could since it was quite a lot of code and it would be pretty hard for me to explain you everything, even though i hope you’ve undestood how my code basically works, what i think gives the player more gamefeel on my system is the horizontal smooth movement using the approach script and also the variable jump height i just think that two thinks give the player a lot of gamefeel and good control, hope this have helped you and feel completely free to use it on your projects!

- GC

Comentarios

Entradas populares