Pygame Platformer: Bonus Content (Coins and Images)

In this Bonus Tutorial of our Pygame Platformer, we will mainly be focusing on adding Coins and Images into our game.

Pygame Platformer - Coins and Graphics

This will be the end result of our game, once we are done with this tutorial.


Player and Platform Interaction

The first thing we want to do is “fix” the Player and Platform interaction. Currently, what happens is that as the Player lands on a moving platform, the Player will not move along with it. This requires to constantly adjust the position of the Player as the platform moves.

So we’ll be making a few adjustments now to fix this slight issue. All we have to do is change/add a few lines in the Platform Class’s move function.

    def move(self):
        hits = self.rect.colliderect(P1.rect)
        if self.moving == True:  
            self.rect.move_ip(self.speed,0)
            if hits:
                P1.pos += (self.speed, 0)
            if self.speed > 0 and self.rect.left > WIDTH:
                self.rect.right = 0
            if self.speed < 0 and self.rect.right < 0:
                self.rect.left = WIDTH

A quick breakdown of what we did:

    def move(self):
        hits = self.rect.colliderect(P1.rect)

This line checks for collision with the player.

        if self.moving == True:  
            self.rect.move_ip(self.speed,0)
            if hits:
                P1.pos += (self.speed, 0)

Normally, we just move the platform if it’s supposed to be a moving platform. However, if it’s also colliding with the player, we change the player position by adding the platform’s speed into P1.pos. (It won’t work if you add it into the Player rect, as it’s value is being managed by the Player pos variable)

And that’s it. The rest of the code is the same as before. We just implemented a new feature.


Adding Coins

Adding Coins is a new mechanic and a way of making the game more interesting. While we do gain points for jumping on new platforms, Coins add a bonus way of earning more points.

There are two parts to creating Coins. First we make the Coin class, and then later integrate it into our Platformer Game.

This here is the Class for Coin. It’s fairly basic, with an image “Coin.png”, and a rect based off the image. It takes a parameter “pos” that sets the initial position for the Coin.

The update() method is responsible for updating the Score by 5 if the Player collides with it, and then it destroys itself.

class Coin(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()

        self.image = pygame.image.load("Coin.png")
        self.rect = self.image.get_rect()

        self.rect.topleft = pos

    def update(self):
        if self.rect.colliderect(P1.rect):
            P1.score += 5
            self.kill()

Integrating Coins

Now we need to add Coins into the Game somehow. Or more specifically, we need to manage them using a Sprite group and generate them on top of Stationary platforms.

First thing we do is create a Sprite group for coins.

all_sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()
coins = pygame.sprite.Group()

As you can see, we’ve just grouped it with all the other groups in the global namespace.

    def generateCoin(self):
        if (self.speed == 0):
            coins.add(Coin((self.rect.centerx, self.rect.centery - 50)))

Next we add a generateCoin() method for the Platform class. This is responsible for generating the Coin above the Stationary platform, and add it into the Coin group.

The next change needs to be made where the platform is generated. Platforms are generated in two separate areas (Can be further optimized to just one). As a quick revision, the plat_gen() is used to constantly generate additional platforms as the player moves up.

The second block is used to generate the initial platforms, that appear at the very start.

def plat_gen():
    while len(platforms) < 6:
        width = random.randrange(50,100)
        p  = None      
        C = True
         
        while C:
             p = platform()
             p.rect.center = (random.randrange(0, WIDTH - width),
                              random.randrange(-50, 0))
             C = check(p, platforms)

        p.generateCoin()   # <----------------
        platforms.add(p)
        all_sprites.add(p)

...
...
...
...

for x in range(random.randint(4,5)):
    C = True
    pl = platform()
    while C:
        pl = platform()
        C = check(pl, platforms)
    pl.generateCoin()    # <----------------
    platforms.add(pl)
    all_sprites.add(pl)

There are only two lines of code actually added here, marked by comments. Rest of code is provided for clarity. The two additional lines simply call generateCoin() if the platform was successfully created.

Final step is to iterate through the Coin group, and call it’s method every frame for rendering and updating.

    for coin in coins:
        displaysurface.blit(coin.image, coin.rect)
        coin.update()

This is done along with the other groups at the bottom of the game loop.


Replacing Surfaces with Actual Images

Now to actually replace the suface objects we created earlier, with actual graphics. We are going for a Winter theme, so the graphics for the Player is a snowmen, the platforms have snow on them, and the background has a starry night kind of look.

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__() 
        self.surf = pygame.image.load("snowman.png")
        self.rect = self.surf.get_rect()

Here in the Player class we simply replace our Surface code with a single line, where we load the snowman image.

class platform(pygame.sprite.Sprite):
    def __init__(self, width = 0, height = 18):
        super().__init__()

        if width == 0: width = random.randint(50, 120)

        self.image = pygame.image.load("platform.png")
        self.surf = pygame.transform.scale(self.image, (width, height))
        self.rect = self.surf.get_rect(center = (random.randint(0,WIDTH-10),
                                                 random.randint(0, HEIGHT-30)))

Next is the Platform class. Here we need to make a few modifications to the parameters, so that we can use width and height in the transform.scale() function. What is this, and why do we need it? Basically, we need platforms of many sizes. So we can’t have dozens of images for all combinations right? Hence we simply scale the image down or up, based on the size of the Platform.

background = pygame.image.load("background.png")  # <-----------------

..
..
..
..
..
..
..

while True:
     ... 
     ...
     
     displaysurface.blit(background, (0, 0))   # <------------------
     f = pygame.font.SysFont("Verdana", 20)     
     g  = f.render(str(P1.score), True, (123,255,0))   
     displaysurface.blit(g, (WIDTH/2, 10))   
     
     for entity in all_sprites:
         displaysurface.blit(entity.surf, entity.rect)
         entity.move()

     for coin in coins:
         displaysurface.blit(coin.image, coin.rect)
         coin.update()

There are two changes we need to make for the background. In the global area of the Code, we need to load an image called background.png. In the Gameloop, we then draw this background to the screen.

It is of utmost importance that the first thing that gets drawn, is the background. This is because the sequence of drawing matters, and can cause the background to be drawn “over” all of the other sprites, if not handled correctly.


Code Download + Materials

Here you can download the Pygame Platformer Code + All the materials (graphics) used in it. If you enjoyed this series, leave some feedback in the comments section below! You can also check out our Pygame RPG Series, where we build an entire RPG game.

Download “Pygame Platformer (Bonus)”

Platformer.zip – Downloaded 1468 times – 79.43 KB

With this, our tutorial on Coins and Images in our Pygame Platformer is over.

This marks the end of the Python Pygame Platformer Game series. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the article content can be asked in the comments section below.

Subscribe
Notify of
guest
6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments