I was working with some projectiles with pygame and found out that even with just 200 lines of code, the game ran with under 50 fps. (There isn't a big loop, except the running loop, and my PC is fairly new)
So, is this because pygame uses SDL?
If so, would using GPU like OpenGL improve the performance?
Main.py
#Eemport
import pygame as pyg,sys,background, player, wall
from pygame.locals import *
#Screen
screen_size_width = 1280
screen_size_height = 720
screen_size = (screen_size_width,screen_size_height)
#Initialization
pyg.init()
screen = pyg.display.set_mode(screen_size)
pyg.display.set_caption("Collision and better physics")
#Set clock
Clock = pyg.time.Clock()
#Set Background
Background = background.background("beach.jpg",screen_size)
#Set Player
player_size_width = 128
player_size_height = 128
player_location_x = 640
player_location_y = 360
player_size = (player_size_width,player_size_height)
player_location = (player_location_x,player_location_y)
player_speed = 5
Player = player.player("crab.png",player_size,player_location)
#Set input
keys = {'right': False, 'left': False, 'up': False, 'down': False}
nextlocation = [0,0]
#make wall
walls = []
walls.append(wall.wall((600,100),(340,600)))
#Running loop
running = True
while running:
#Read input
for event in pyg.event.get():
if event.type == QUIT:
pyg.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pyg.quit()
sys.exit()
if event.key == K_UP:
keys['up'] = True
if event.key == K_DOWN:
keys['down'] = True
if event.key == K_LEFT:
keys['left'] = True
if event.key == K_RIGHT:
keys['right'] = True
if event.type == KEYUP:
if event.key == K_UP:
keys['up'] = False
if event.key == K_DOWN:
keys['down'] = False
if event.key == K_LEFT:
keys['left'] = False
if event.key == K_RIGHT:
keys['right'] = False
#Update values
#1. Player Value
if keys['right']:
Player.move(player_speed,0,walls)
if keys['left']:
Player.move(-player_speed,0,walls)
if keys['up']:
Player.move(0,player_speed,walls)
if keys['down']:
Player.move(0,-player_speed,walls)
#Draw on screen Be aware of priority!!!
Background.draw_image(screen)
for wall in walls:
pyg.draw.rect(screen, (255,255,255),wall.rect)
Player.draw_image(screen)
Clock.tick()
print(Clock.get_fps(),Player.rect.x,Player.rect.y)
#Update display
pyg.display.update()
Wall.py
import pygame as pyg
from pygame.locals import *
class wall(object):
"""
This class represents walls
No action
"""
def __init__(self,size,location):
self.width = size[0]
self.height = size[1]
self.locationx = location[0]
self.locationy = location[1]
self.rect = pyg.Rect(self.locationx,self.locationy,self.width,self.height)
background.py
import pygame as pyg
from pygame.locals import *
class background(object):
"""
This class represents the background
action - draw
"""
def __init__(self,image_file,screen_size):
self.screen_size = screen_size
self.image = pyg.image.load(image_file)
self.image = pyg.transform.scale(self.image,self.screen_size)
self.rect = pyg.Rect((0,0),self.screen_size)
def draw_image(self,screen):
screen.blit(self.image,self.rect)
def load_new_image(self,image_file):
self.image = pyg.image.load(image_file)
player.py
import pygame as pyg
from pygame.locals import *
class player(object):
"""
This class represents the player
contains actions for the player
"""
def __init__(self,image_file,image_size,location):
#image
self.image = pyg.image.load(image_file)
self.image = pyg.transform.scale(self.image,image_size)
self.image_size = image_size
#Rect
self.rect = pyg.Rect(location,image_size)
def move(self, dx, dy,walls):
self.rect.x += dx
collide_wall = self.rect.collidelist(walls)
if collide_wall != -1:
if dx > 0:
self.rect.right = walls[collide_wall].rect.left
else:
self.rect.left = walls[collide_wall].rect.right
self.rect.y -= dy
collide_wall = self.rect.collidelist(walls)
if collide_wall != -1:
if dy > 0:
self.rect.bottom = walls[collide_wall].rect.top
else:
self.rect.top = walls[collide_wall].rect.bottom
def draw_image(self,screen): #Draw image on screen
screen.blit(self.image,self.rect)
def load_new_image(self,image_file): #loads new image
self.image = pyg.image.load(image_file)
self.image = pyg.transform.scale(self.image, self.image_size)
def current_location(self):
return (self.rect.x , self.rect.y)
display. flip() for software displays. It allows only a portion of the screen to updated, instead of the entire area. If no argument is passed it updates the entire Surface area like pygame.
Images/pygame.Surfaces should usually be converted with the convert
or convert_alpha
methods of the pygame.Surface
class. This will improve the performance dramatically.
IMAGE = pygame.image.load('an_image.png').convert()
IMAGE2 = pygame.image.load('an_image_with_transparency.png').convert_alpha()
Also, load your images only once when the program starts and reuse them in your program. Loading them from the hard disk with pygame.image.load
again is slow and should be avoided.
If you need even more speed, you can use OpenGL in conjunction with pygame, but that means rewriting your rendering code and of course you would have to learn OpenGL first.
Alternatively, you could check out some of the other game frameworks for Python.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With