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