How to make a scrolling platform game with pygame

This code is a good example of a plaform scrolling game.

The code

#! /usr/bin/python

import pygame
from pygame import *
import time
# import random

WIN_WIDTH = 800
WIN_HEIGHT = 640
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30
cameraY = 30
cameraX = 30
red = (225, 0, 0)
blue = (53, 115, 255)
black = (0, 0, 0)
clock = pygame.time.Clock()

gameDisplay = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))


def text_objects(text, font, color):
	textSurface = font.render(text, True, color)
	return textSurface, textSurface.get_rect()


def switch_fun(text):
	largeText = pygame.font.Font('freesansbold.ttf', 80)
	TextSurf, TextRect = text_objects(text, largeText, red)
	TextRect.center = (HALF_WIDTH, HALF_HEIGHT)
	gameDisplay.blit(TextSurf, TextRect)
	time.sleep(0.05)
	pygame.display.update()
	largeText = pygame.font.Font('freesansbold.ttf', 80)
	TextSurf, TextRect = text_objects(text, largeText, blue)
	TextRect.center = (HALF_WIDTH, HALF_HEIGHT)
	gameDisplay.blit(TextSurf, TextRect)
	time.sleep(0.05)
	pygame.display.update()


def message_display(text):
	switch_fun(text)
	switch_fun(text)
	switch_fun(text)
	switch_fun(text)
	switch_fun(text)
	switch_fun(text)
	switch_fun(text)
	switch_fun(text)


def main():
	global cameraX, cameraY
	pygame.init()
	screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
	pygame.display.set_caption("Use arrows to move!")
	timer = pygame.time.Clock()

	up = down = left = right = running = False
	bg = Surface((32, 32))
	bg.convert()
	bg.fill(Color("#000000"))
	entities = pygame.sprite.Group()
	player = Player(32, 32)

	platforms = []

	x = y = 0
	level = [
		"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
		"P                                                E  P",
		"P                                                   P",
		"P         RRRRRRR                                   P",
		"P                             PPPPPPPPPPP           P",
		"P                                                   P",
		"P                                                   P",
		"P                                                   P",
		"P             PPPPPPPP                              P",
		"P                                                   P",
		"P                                    PPPPPPP        P",
		"P                          PPPPPP                   P",
		"P                                                   P",
		"P                 PPPPPPP                           P",
		"P                                                   P",
		"P                              PPPPPP               P",
		"P                                                   P",
		"P           PPPPPPPPPPP                             P",
		"P                                                   P",
		"P                          P PPPPPPP P              P",
		"P                         P           P             P",
		"P                        P             P            P",
		"P                       P               P           P",
		"P                      P                 P          P",
		"P                     P                   P         P",
		"P                    PRRRRRRRRRRRRRRRRRRRRRP        P",
		"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",]

	# build the level
	for row in level:
		for col in row:
			if col == "R":
				r = Death(x, y)
				platforms.append(r)
				entities.add(r)
			if col == "P":
				p = Platform(x, y)
				platforms.append(p)
				entities.add(p)
			if col == "E":
				e = ExitBlock(x, y)
				platforms.append(e)
				entities.add(e)
			x += 32
		y += 32
		x = 0

	total_level_width = len(level[0])*32
	total_level_height = len(level)*32
	camera = Camera(complex_camera, total_level_width, total_level_height)
	entities.add(player)

	while 1:
		timer.tick(60)

		for e in pygame.event.get():
			if e.type == QUIT: raise SystemExit(QUIT)
			if e.type == KEYDOWN and e.key == K_ESCAPE:
				raise SystemExit(ESCAPE)
			if e.type == KEYDOWN and e.key == K_UP:
				up = True
			if e.type == KEYDOWN and e.key == K_DOWN:
				down = True
			if e.type == KEYDOWN and e.key == K_LEFT:
				left = True
			if e.type == KEYDOWN and e.key == K_RIGHT:
				right = True
			if e.type == KEYDOWN and e.key == K_SPACE:
				running = True

			if e.type == KEYUP and e.key == K_UP:
				up = False
			if e.type == KEYUP and e.key == K_DOWN:
				down = False
			if e.type == KEYUP and e.key == K_LEFT:
				left = False
			if e.type == KEYUP and e.key == K_RIGHT:
				right = False

		# draw backround
		for y in range(32):
			for x in range(32):
				screen.blit(bg, (x * 32, y * 32))

		camera.update(player)

		# update player, draw everything else
		player.update(up, down, left, right, running, platforms)
		for e in entities:
			screen.blit(e.image, camera.apply(e))

		pygame.display.update()


def things_dodged(count):
	font = pygame.font.SysFont(None, 25)
	text = font.render("Dodged: "+str(count), True, black)
	gameDisplay.blit(text, (0, 0))


def things(thingx, thingy, thingw, thingh, color):
	pygame.draw.rect(gameDisplay, color, [400, 400, thingw, thingh])


class Camera(object):
	def __init__(self, camera_func, width, height):
		self.camera_func = camera_func
		self.state = Rect(0, 0, width, height)

	def apply(self, target):
		return target.rect.move(self.state.topleft)

	def update(self, target):
		self.state = self.camera_func(self.state, target.rect)


def simple_camera(camera, target_rect):
	l, t, _, _ = target_rect
	_, _, w, h = camera
	return Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)


def complex_camera(camera, target_rect):
	l, t, _, _ = target_rect
	_, _, w, h = camera
	l, t, _, _ = -l + HALF_WIDTH, -t + HALF_HEIGHT, w, h
	l = min(0, l) 								# stop scrolling at the left edge
	l = max(-(camera.width - WIN_WIDTH), l)		# stop scrolling at the right edge
	t = max(-(camera.height - WIN_HEIGHT), t)	# stop scrolling at the bottom
	t = min(0, t)								# stop scrolling at the top
	return Rect(l, t, w, h)


class Entity(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)


class Player(Entity):
	def __init__(self, x, y):
		Entity.__init__(self)
		self.xvel = 0
		self.yvel = 0
		self.onGround = False
		self.image = Surface((32, 32))
		self.image.fill(Color("#0000FF"))
		self.image.convert()
		self.rect = Rect(x, y, 32, 32)

	def update(self, up, down, left, right, running, platforms):
		if up:
			# only jump if on the ground
			if self.onGround: self.yvel -= 10
		if down:
			pass
		if running:
			self.xvel = 12
		if left:
			self.xvel = -8
		if right:
			self.xvel = 8
		if not self.onGround:
			# only accelerate with gravity if in the air
			self.yvel += 0.3
			# max falling speed
			if self.yvel > 100: self.yvel = 100
		if not(left or right):
			self.xvel = 0
		# increment in x direction
		self.rect.left += self.xvel
		# do x-axis collisions
		self.collide(self.xvel, 0, platforms)
		# increment in y direction
		self.rect.top += self.yvel
		# assuming we're in the air
		self.onGround = False
		# do y-axis collisions
		self.collide(0, self.yvel, platforms)

	def collide(self, xvel, yvel, platforms):
		for p in platforms:
			if pygame.sprite.collide_rect(self, p):
				if isinstance(p, ExitBlock):
					event.type = pygame.QUIT
					message_display('Winner')
					pygame.quit()
					quit()
				if isinstance(p, Death):
					event.type = pygame.QUIT
					message_display('Loser')
					pygame.quit()
					quit()
				if xvel > 0:
					self.rect.right = p.rect.left
					print("collide right")
				if xvel < 0:
					self.rect.left = p.rect.right
					print("collide left")
				if yvel > 0:
					self.rect.bottom = p.rect.top
					self.onGround = True
					self.yvel = 0
				if yvel < 0:
					self.rect.top = p.rect.bottom


class Platform(Entity):
	def __init__(self, x, y):
		Entity.__init__(self)
		self.image = Surface((32, 32))
		self.image.convert()
		self.image.fill(Color("#DDDDDD"))
		self.rect = Rect(x, y, 32, 32)

	def update(self):
		pass


class ExitBlock(Platform):
	def __init__(self, x, y):
		Platform.__init__(self, x, y)
		self.image.fill(Color("#0033FF"))


class Death(Platform):
	def __init__(self, x, y):
		Platform.__init__(self, x, y)
		self.image.fill(Color("#DDDDDD"))
		

if __name__ == "__main__":
	main()


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Similar code

2D game platform


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

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.