Pygame / 2D Platformer

I have no idea how to make some basic mechanics for a 2D Platformer.
In terms of mechanics, I’m regarding:

  • Moving an Image (the player)
  • Adding a ground for the player to move on
  • Adding Collisions
  • Adding Gravity
    Basically, if you think of Mario’s mechanics, I’m kind of going with that.

I’ve tried looking through the Pygame docs, but I have had trouble really comprehending what I was reading.
I also looked through other sources, but I didn’t really get much from it.
I need help with achieving this, and I have no idea how to start. I need help.

Here is my code so far, and after is the link to my Pygame Repl:

import pygame, sys
from pygame.locals import QUIT
pygame.init()

DISPLAYSURF = pygame.display.set_mode((500, 500))

#background
background = pygame.transform.scale(pygame.image.load("GRID.png"), (500, 500))

# caption and icon
pygame.display.set_caption(' achromatic {TEST}')
icon = pygame.image.load("Image/char.png")
pygame.display.set_icon(icon)
# Displays it?
pygame.display.flip()

runing = True
while runing:
    # displays the bg
    DISPLAYSURF.blit(background, (0,0))
    for event in pygame.event.get():
        if event.type == QUIT:
            runing = False
    pygame.display.update()
pygame.quit()

Repl:
https://replit.com/@sKVZZ-STG1/what?v=1

I know that pygame is difficult to learn. I had trouble when I first started using it too, and it took me a long time before I understood it well. I can try and give you some explainations to your problems, but it is best learned by experience. Rects also have values like .bottom, .top, .left, and .right which help you position it.

The Pygame Canvas and Rects
One important thing you should learn about before using pygame, is how drawing is done. The screen acts like a coordinate plane where top left is (0, 0). A pygame Rect is used to define an area inside of the screen. It takes in four values, and X, Y, WIDTH, and HEIGHT, which are shown in the picture. Rects can also be used to detect collisions, and if you have an image, you can call image.get_rect() to return a pygame rect of the image.

The black is the pygame window, the red is an example rect with values x, y, w, and h

Drawing the Ground
There are two ways to do this. Either, you can create an entire new image for the ground, or you can create a pygame Rect object and fill that area with a solid color for the ground. You can call surface.fill("green", ground_rect) to fill a rect with color. In this case, green is the color and ground_rect is a pygame rect object that defines the area where the ground is.

Making a Player
Players can be done simply by drawing a player image, or filling a rect with a color. You may also want to create variables for the player’s x and y positions. Another useful thing to do is to make an Player class. You can create a class like this.

class Player:
    def __init__(self, image, pos):
        # save the pygame image
        self.image = image
        # create the rect, sized to the image
        self.rect = image.get_rect()
        # set the rect's x and y to the tuple pos
        self.rect.pos = pos

    def draw(self):
        DISPLAYSURF.blit(self.image, self.rect)

And now you can create a new player like this player1 = Player(player_img, (100, 0)) and then call player1.draw() to draw it, and change the position like this player1.rect.x += 5 By using classes, it also allows for more customization later on. You don’t have to use classes, but they are worth learning and make code cleaner.

Gravity and Movement
So there are soooo many different ways to make gravity, but a really simple one is just to keep adding to the player’s y value like this player1.rect.y += 2 (adding because bigger y values mean lower down the screen), but the problem is that you fall at the same constant speed. If you want more realistic looking gravity, then you need to fall faster every frame. So maybe you fall 1 pixel the first, then 2 pixels, then 3, then 4, and so on. So how can you do this? With momentum.

fall_speed = 1
while True:
    # do other stuff...
    player1.rect.y += fall_speed
    fall_speed += 1

Or an even better way to do it within your class is like this.

class Player:
    def __init__(self, image, pos):
        # ...
        self.fall_speed = 0

    def draw(self):
        # ...

    def apply_gravity(self):
        self.fall_speed += 1
        self.rect.y += self.fall_speed

        #if you hit the ground
        if self.rect.bottom > GROUND_HEIGHT:
            self.fall_speed = 0
            self.rect.bottom = GROUND_HEIGHT

    def jump(self):
        self.fall_speed = -10

As for movement, you need to detect keypresses and I really don’t feel like saying how to do that AGAIN so here is a link to the post. Check the keypress section How do you make text appear when you click a key in pygame - #44 by SharkCoding

Collisions
So actually detecting collisions is really easy with pygame Rects, you just need to do this.

# rect at (50, 50) with size (100, 100)
myRandomRect = pygame.Rect(50, 50, 100, 100)

# check for collision with point
if myRandomRect.collidePoint((100, 100)):
    # do stuff

#check for collision with another rect
if myRandomRect.collideRect(otherRect):
    # do stuff

Hopefully this helps. Also I think I am going to make a pygame tutorial because there aren’t a whole lot of good ones out there and pygame is fun to learn and easy once you know it.

3 Likes

WOW, I REALLY REALLY APPRECIATE THIS.
This is insanely helpful and literally is way better than the sources I have found.

Thank you, and I would look forward to seeing a tutorial on pygame.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.