Python Platform Game 2

Python and Pygame to make a platform game, second part… collitions, physics, maps.

In the second part of this tutorial to make a platform based on the dafluffypotato work, we will do this:

The video explanation

 

The initializing and the variables for movements

pygame.init()

clock = pygame.time.Clock()

pygame.display.set_caption('Game')

WINDOW_SIZE = (600, 400)
# This will be the Surface where we will blit everything
display = pygame.Surface((300, 200))
# Then we will scale (every frame) the display onto the screen
screen = pygame.display.set_mode(WINDOW_SIZE, 0, 32)

moving_right = False
moving_left = False
# For the pygame.transform.flip(player_img, 1, 0)
stay_right = True
momentum = 0
air_timer = 0

The variables holding the map and its tiles

game_map1 = """
<---->xxxx<----xxxx
ox<----ooo-------oo
o------ooo--------o
o--->xxoo-----xxxxo
o------ooxxx<-----o
oxx<---oo-------xxo
o------oo---------o
o--->xxooxxxxxxx<-o
o------oo---------o
oxxxxxxoo-xxxxxxxxo
ooooooooo----------
ooooooooooooooooooo
""".splitlines()

game_map = [list(lst) for lst in game_map1]

tl = {}
tl["o"] = dirt_img = pygame.image.load('dirt.png')
tl["x"] = grass_img = pygame.image.load('grass.png')
tl["<"] = grassr = pygame.image.load('grassr.png')
tl[">"] = grassr = pygame.image.load('grassl.png')

The player image converted to transparent and its rect object

player_img = pygame.image.load('player.png').convert()
player_img.set_colorkey((255, 255, 255))
player_rect = pygame.Rect(100, 100, 5, 13)

This returns a list of the tiles colliding with the player

def collision_test(rect, tiles):
    "Returns the Rect of the tile with which the player collides"
    hit_list = []
    for tile in tiles:
        if rect.colliderect(tile):
            hit_list.append(tile)
    return hit_list

This returns the player rect and where the collision is (up, left…)

def move(rect, movement, tiles):
    collision_types = {
        'top': False, 'bottom': False, 'right': False, 'left': False}
    rect.x += movement[0]
    hit_list = collision_test(rect, tiles)
    for tile in hit_list:
        if movement[0] > 0:
            rect.right = tile.left
            collision_types['right'] = True
        elif movement[0] < 0:
            rect.left = tile.right
            collision_types['left'] = True
    rect.y += movement[1]
    hit_list = collision_test(rect, tiles)
    for tile in hit_list:
        if movement[1] > 0:
            rect.bottom = tile.top
            collision_types['bottom'] = True
        elif movement[1] < 0:
            rect.top = tile.bottom
            collision_types['top'] = True
    return rect, collision_types

The while loop that draw the map of tiles

loop = 1
while loop:
    # CLEAR THE SCREEN
    display.fill((146, 244, 255))

    # Tiles are blitted  ==========================
    tile_rects = []
    y = 0
    for line_of_symbols in game_map:
        x = 0
        for symbol in line_of_symbols:
            if symbol in tl:
                # draw the symbol for image
                display.blit(
                    tl[symbol], (x * 16, y * 16))
            # draw a rectangle for every symbol except for the empty one
            if symbol != "-":
                tile_rects.append(pygame.Rect(x * 16, y * 16, 16, 16))
            x += 1
        y += 1
    # ================================================

The movement detection to draw the player (in the while loop)

    # MOVEMENT OF THE PLAYER
    player_movement = [0, 0]
    if moving_right:
        player_movement[0] += 2
    if moving_left:
        player_movement[0] -= 2
    player_movement[1] += momentum
    momentum += 0.3
    if momentum > 3:
        momentum = 3

    player_rect, collisions = move(player_rect, player_movement, tile_rects)

    if collisions['bottom']:
        air_timer = 0
        momentum = 0
    else:
        air_timer += 1

    # Flip the player image when goes to the left
    if stay_right:
        display.blit(
            player_img, (player_rect.x, player_rect.y))
    else:
        display.blit(
            pygame.transform.flip(player_img, 1, 0),
            (player_rect.x, player_rect.y))

The key command to move the player

    for event in pygame.event.get():
        if event.type == QUIT:
            loop = 0
        if event.type == KEYDOWN:
            if event.key == K_RIGHT:
                moving_right = True
                stay_right = True
            if event.key == K_LEFT:
                moving_left = True
                stay_right = False
            if event.key == K_SPACE:
                if air_timer < 6:
                    momentum = -5
        if event.type == KEYUP:
            if event.key == K_RIGHT:
                moving_right = False
            if event.key == K_LEFT:
                moving_left = False

Scaling the display on the screen (and quitting)

    screen.blit(pygame.transform.scale(display, (600, 400)), (0, 0))
    pygame.display.update()
    clock.tick(60)

pygame.quit()

and now …

The whole code

import pygame
import sys
from pygame.locals import *


pygame.init()

clock = pygame.time.Clock()

pygame.display.set_caption('Game')

WINDOW_SIZE = (600, 400)
# This will be the Surface where we will blit everything
display = pygame.Surface((300, 200))
# Then we will scale (every frame) the display onto the screen
screen = pygame.display.set_mode(WINDOW_SIZE, 0, 32)

moving_right = False
moving_left = False
# For the pygame.transform.flip(player_img, 1, 0)
stay_right = True
momentum = 0
air_timer = 0

game_map1 = """
<---->xxxx<----xxxx
ox<----ooo-------oo
o------ooo--------o
o--->xxoo-----xxxxo
o------ooxxx<-----o
oxx<---oo-------xxo
o------oo---------o
o--->xxooxxxxxxx<-o
o------oo---------o
oxxxxxxoo-xxxxxxxxo
ooooooooo----------
ooooooooooooooooooo
""".splitlines()

game_map = [list(lst) for lst in game_map1]

tl = {}
tl["o"] = dirt_img = pygame.image.load('dirt.png')
tl["x"] = grass_img = pygame.image.load('grass.png')
tl["<"] = grassr = pygame.image.load('grassr.png')
tl[">"] = grassr = pygame.image.load('grassl.png')

player_img = pygame.image.load('player.png').convert()
player_img.set_colorkey((255, 255, 255))
player_rect = pygame.Rect(100, 100, 5, 13)


def collision_test(rect, tiles):
    "Returns the Rect of the tile with which the player collides"
    hit_list = []
    for tile in tiles:
        if rect.colliderect(tile):
            hit_list.append(tile)
    return hit_list


def move(rect, movement, tiles):
    collision_types = {
        'top': False, 'bottom': False, 'right': False, 'left': False}
    rect.x += movement[0]
    hit_list = collision_test(rect, tiles)
    for tile in hit_list:
        if movement[0] > 0:
            rect.right = tile.left
            collision_types['right'] = True
        elif movement[0] < 0:
            rect.left = tile.right
            collision_types['left'] = True
    rect.y += movement[1]
    hit_list = collision_test(rect, tiles)
    for tile in hit_list:
        if movement[1] > 0:
            rect.bottom = tile.top
            collision_types['bottom'] = True
        elif movement[1] < 0:
            rect.top = tile.bottom
            collision_types['top'] = True
    return rect, collision_types


loop = 1
while loop:
    # CLEAR THE SCREEN
    display.fill((146, 244, 255))

    # Tiles are blitted  ==========================
    tile_rects = []
    y = 0
    for line_of_symbols in game_map:
        x = 0
        for symbol in line_of_symbols:
            if symbol in tl:
                # draw the symbol for image
                display.blit(
                    tl[symbol], (x * 16, y * 16))
            # draw a rectangle for every symbol except for the empty one
            if symbol != "-":
                tile_rects.append(pygame.Rect(x * 16, y * 16, 16, 16))
            x += 1
        y += 1
    # ================================================

    # MOVEMENT OF THE PLAYER
    player_movement = [0, 0]
    if moving_right:
        player_movement[0] += 2
    if moving_left:
        player_movement[0] -= 2
    player_movement[1] += momentum
    momentum += 0.3
    if momentum > 3:
        momentum = 3

    player_rect, collisions = move(player_rect, player_movement, tile_rects)

    if collisions['bottom']:
        air_timer = 0
        momentum = 0
    else:
        air_timer += 1

    # Flip the player image when goes to the left
    if stay_right:
        display.blit(
            player_img, (player_rect.x, player_rect.y))
    else:
        display.blit(
            pygame.transform.flip(player_img, 1, 0),
            (player_rect.x, player_rect.y))

    for event in pygame.event.get():
        if event.type == QUIT:
            loop = 0
        if event.type == KEYDOWN:
            if event.key == K_RIGHT:
                moving_right = True
                stay_right = True
            if event.key == K_LEFT:
                moving_left = True
                stay_right = False
            if event.key == K_SPACE:
                if air_timer < 6:
                    momentum = -5
        if event.type == KEYUP:
            if event.key == K_RIGHT:
                moving_right = False
            if event.key == K_LEFT:
                moving_left = False

    screen.blit(pygame.transform.scale(display, (600, 400)), (0, 0))
    pygame.display.update()
    clock.tick(60)

pygame.quit()

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.