How to make a platformer
So some of you might be wondering how to make a platformer...
Although this tutorial is more over the methods of how I do it, it will use pygame as an example.
You want to make sure that you use some lang with oop to make this a lot easier. Your player should have a defined size (although it can change later, its just easier to have width/height vars) and you should know how to do rect collisions given your language/framework.
Basic horizontal movement
in your lang/framework you should have a way to get the keys pressed. in pygame the method I use and recommend is
keys = pygame.key.get_pressed().
The best way I found to handle movement is make a variable called
move and assign it to rightKey-leftKey. in pygame (using the previously mention method) you can use
move = keys[K_d]-keys[K_a] (ofc the things inside the square brackets depends on what keys you want the player to use). this is a really simple way of handling which direction the player is going. It can return 1, -1, or 0. It acts as a xor gate (exclusive or, this or that but not both). if right is held, 1 is returned, left = -1, and both/nothing = 0.
its good practice to have some sort of walkSpeed variable, however not technically needed, if you ever need to change it especially in code with a powerup or something, its way easier if you have some walk speed variable in the init of the object (or however you language defines object variables).
to move the player simply modify the players x by move*walkSpeed... but wait! that doesn't collide with any walls!
to collide with walls you need to setup another variable
hsp (Horizontal Speed). this lets us predict where the player is going so we can keep them from going inside of a block. this also lets us add acceleration, but lets not get ahead of ourselves, thats coming in a bit.
something in pygame you also must do is make a list of wall rects (one could also make a list of wall objects and use them in a for statement but pygame.Rect.collidelist is more optimized) this way the player can check collision for all the walls
this is the code I use for collision (in pygame):
if pygame.Rect(self.x+self.hsp,self.y,self.w,self.h).collidelist(wallRects) != -1: while pygame.Rect(self.x+sign(self.hsp),self.y,self.w,self.h).collidelist(wallRects) == -1: self.x += sign(self.hsp) self.hsp = 0 self.x += self.hsp
something I must clarify before explaining the code is what sign is. sign is not in python by default I define the functions as this:
def sign(x): if x > 0: return 1 elif x < 0: return -1 return 0
what that does is returns the sign (positive or negative) in the form of 1,0, or -1.
back to the code earlier.
if pygame.Rect(self.x+self.hsp,self.y,self.w,self.h).collidelist(wallRects) != -1
this checks to see if your x + horizontal speed is in a wall.
while pygame.Rect(self.x+sign(self.hsp),self.y,self.w,self.h).collidelist(wallRects) == -1: self.x += sign(self.hsp) self.hsp = 0
when we decide we are about to collide, we don't want to stop short of the obstacle. This loop lets use move the player to the obstacle before resetting the speed
self.x += self.hsp
this moves the player by our horizontal speed.
the same can be done for vertical movement (using vsp instead).
keep in mind that in pygame y = 0 is the top and positive y is down, so you need to do self.y -= self.vsp instead of +
to add jumping we need to do two things: add gravity and check if the player is on the ground.
to add the ground check, simply check for a ground peice directly below the player
if pygame.Rect(self.x,self.y,self.w,self.h).collidelist(wallRects) != -1:
that will check one pixel below the player for any ground.
if pygame.Rect(self.x,self.y,self.w,self.h).collidelist(wallRects) != -1: if key[K_SPACE] #or key[K_w] or whatever you want to be the jump key: self.vsp = jump
so if your on the ground and holding a jump key, make our vsp some jump value.
but we want gravity so we add this:
else: self.vsp -= grav
so we are not on the ground we want to make our vsp go down by a gravity value.
using this function you can make smooth acceleration:
def approach(val,goal,amm): if val < goal: val += amm if (val > goal): return goal else: val -= amm; if val < goal: return goal return val
this function goes toward goal by amm without going over
to use this just edit
self.hsp = self.move*walkSpeed to `self.hsp += approach(self.hsp,self.walksp*move,accel)
this lets us approach our walk speed in increments of accel
and there you have it! basic platformer movement! do what you want with it. Hope to see more people make things like this!
hope this helped you, have a nice day