What can I improve considering these cProfile results? [duplicate] - python

I'm having trouble with the framerate in my game. I've set it to 60 but it only goes to ~25fps. This was not an issue before displaying the background (was fine with only win.fill(WHITE)). Here is enough of the code to reproduce:
import os, pygame
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50, 50)
pygame.init()
bg = pygame.image.load('images/bg.jpg')
FPS = pygame.time.Clock()
fps = 60
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
winW = 1227
winH = 700
win = pygame.display.set_mode((winW, winH))
win.fill(WHITE)
pygame.display.set_icon(win)
def redraw_window():
#win.fill(WHITE)
win.blit(bg, (0, 0))
win.blit(text_to_screen('FPS: {}'.format(FPS.get_fps()), BLUE), (25, 50))
pygame.display.update()
def text_to_screen(txt, col):
font = pygame.font.SysFont('Comic Sans MS', 25, True)
text = font.render(str(txt), True, col)
return text
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
redraw_window()
FPS.tick(fps)
pygame.quit()

Ensure that the background Surface has the same format as the display Surface. Use convert() to create a Surface that has the same pixel format. That should improve the performance, when the background is blit to the display, because the formats are compatible and blit do not have to do an implicit transformation.
bg = pygame.image.load('images/bg.jpg').convert()
Furthermore, it is sufficient to create the font once, rather than every time when a text is drawn. Move font = pygame.font.SysFont('Comic Sans MS', 25, True) to the begin of the application (somewhere after pygame.init() and before the main application loop)

Instead use screen.blit(pygame.image.load(picture.png))
Just image = pygame.image.load(picture.png) then screen.blit(image)
( if you keep loading your pictures continuously it will get lag )

Related

How can I make my code more optimised by not drawing a rect on each pixel?

I am using the cv2.imread() function to make a a level editor in pygame that works with images, the only problem is that cv2.imread() gives me information on pixels thus I can only display one rect per pixel.This makes the code really slow and makes it impossible to work with it. I have tried storing all the values in a list but the problem is in the pygame rect function because it foes not have the ability to display all the pixels with collisions and all.
code:
import sys
import pygame
from pygame import *
import cv2
pygame.init()
screen = pygame.display.set_mode((388, 404))
lib = ['Map1.png']
Read = list(cv2.imread(lib[0]))
clock = pygame.time.Clock()
while True:
screen.fill((15, 15, 15))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
for i in range(len(Read)):#y coords
for j in range(len(Read[i])):#x coords
blue = list(Read[i][j])[0]
green = list(Read[i][j])[0]
red = list(Read[i][j])[0]
if blue > 240 and green > 240 and red > 240:
pygame.draw.rect(screen, (255,255,255), pygame.Rect(j, i, 32,32))
else:
pygame.draw.rect(screen, (0), pygame.Rect(j, i, 32, 32))
pygame.display.update()
clock.tick(120)
map1:
I recommend to use pygame.image.load and a pygame.mask.Mask:
Create a mask form the surface (pygame.mask.from_surface)
Invert the mask (invert())
Create a black and whit Surfcae from the mask (to_surface())
Scale up the black and white Surface (pygame.transform.scale)
import sys
import pygame
from pygame import *
pygame.init()
screen = pygame.display.set_mode((388, 404))
read_surf = pygame.image.load("Map1.png")
w, h = read_surf.get_size()
mask = pygame.mask.from_surface(read_surf)
# mask.invert() # optional
mask_surf = pygame.transform.scale(mask.to_surface(), (w*32, h*32))
clock = pygame.time.Clock()
while True:
screen.fill((15, 15, 15))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(mask_surf, (0, 0))
pygame.display.update()
clock.tick(120)

PyGame won't load the images on window and crashes immediately

So I was making a game in python with pygame and I had some assets as characters. I coded everything correctly. But when I run the program none of the images show up and the window crashes immediately.
import pygame
import os
import random
WIDTH, HEIGHT = 900, 500
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Fly game")
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
FPS = 60
VEL = 5
BORDER = pygame.Rect(WIDTH//2 - 5, 0, 10, HEIGHT)
PLAYER_WIDTH, PLAYER_HEIGHT = 55, 40
SKY = pygame.image.load(
os.path.join('C:\\Users\\Kostadin Klemov\\Desktop\\Programms\\Python\\projects\\Fly game\\Assets\\SKY.jpg')), (WIDTH, HEIGHT)
JETPACK_MAN_IMAGE = pygame.image.load(
os.path.join('C:\\Users\\Kostadin Klemov\\Desktop\\Programms\\Python\\projects\\Fly game\\Assets\\JETPACK_MAN.jpg'))
JETPACK_MAN = pygame.transform.scale(
JETPACK_MAN_IMAGE, (PLAYER_WIDTH, PLAYER_HEIGHT))
FLY_IMAGE = pygame.image.load(
os.path.join('C:\\Users\\Kostadin Klemov\\Desktop\\Programms\\Python\\projects\\Fly game\\Assets\\FLY.png'))
FLY = pygame.transform.scale(
FLY_IMAGE, (PLAYER_WIDTH, PLAYER_HEIGHT))
def draw_window(jetpack, fly):
WIN.blit(SKY, (0, 0))
pygame.draw.rect(WIN, BLACK, BORDER)
WIN.blit(JETPACK_MAN, (jetpack.x, jetpack.y))
WIN.blit(FLY, (fly.x, fly.y))
pygame.display.update()
def main():
jetpack = pygame.Rect(225, 250, PLAYER_WIDTH, PLAYER_HEIGHT)
fly = pygame.Rect(675, 250, PLAYER_WIDTH, PLAYER_HEIGHT)
clock = pygame.time.Clock()
run = True
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
draw_window(jetpack, fly)
main()
if __name__ == "__main__":
main
No error showed up so I didn't know what was wrong.
If you can, please check out the code and try to fix it!
This is an indentation error.
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
# <---- INDENTATION
# this should be in the while loop, the "game loop", not in the quit condition
draw_window(jetpack, fly)
Also, you probably don't want to call main() after you program terminates. (Assuming you want people to be able to exit your game easily.
if __name__ == "__main__":
main
This main does nothing, it needs to be called, like main(). With the parentheses. It's not "crashing instantly," it's just not running anything.
SKY = pygame.image.load(
os.path.join('C:\\Users\\Kostadin Klemov\\Desktop\\Programms\\Python\\projects\\Fly game\\Assets\\SKY.jpg')), (WIDTH, HEIGHT)
That (WIDTH, HEIGHT) at the end is very suspicious. Presumably you just want the image put in the SKY variable, not another random tuple.
On another note, os.path.join() does nothing if you give it the full path as an argument.

"Spin" coin image in python, pygame clicker game

So I'm currently making a clicker game, and I already have some pretty good looking stuff. But since I want to polish the game, I would like to add a spinning coin animation to the coin that's in the center of the screen.
I have a coin.py file and this is how it looks like:
import pygame
class Coin():
def __init__(self, screen):
self.screen = screen
self.image = pygame.image.load('pyfiles/images/click_button.png')
self.image_x = 230
self.image_y = 130
self.scale_change_x = 10
self.scale_change_y = 10
def blitme(self):
self.screen.blit(self.image, (self.image_x, self.image_y))
And the current gameplay looks like:
As you can see, when my cursor goes on the coin image, it turns yellow. But now, I want it to not only turn yellow but to spin like this image ( that I found on google ):
What code should I add to my coin.py file to make it do this when my cursor goes on ( collides with ) the coin?
If you have an animated GIF, see Animated sprite from few images.
If you don't have an animated GIF or sprite sheet of a coin, you can achieve a similar effect by squeezing and flipping the coin along the y-axis.
Use pygame.transform.scale() to scale an image and pygame.transform.flip() to flip it. The following code snippet creates a spin effect of a coin Surface that depends on a specific angel:
new_width = round(math.sin(math.radians(angle)) * coin_rect.width)
rot_coin = coin if new_width >= 0 else pygame.transform.flip(coin, True, False)
rot_coin = pygame.transform.scale(rot_coin, (abs(new_width), coin_rect.height))
window.blit(rot_coin, rot_coin.get_rect(center = coin_rect.center))
Minimal example:
import pygame
import math
pygame.init()
window = pygame.display.set_mode((400, 400))
font = pygame.font.SysFont(None, 40)
clock = pygame.time.Clock()
coin = pygame.Surface((160, 160), pygame.SRCALPHA)
pygame.draw.circle(coin, (255, 255, 0), (80, 80), 80, 10)
pygame.draw.circle(coin, (128, 128, 0), (80, 80), 75)
cointext = pygame.font.SysFont(None, 80).render("10", True, (255, 255, 0))
coin.blit(cointext, cointext.get_rect(center = coin.get_rect().center))
coin_rect = coin.get_rect(center = window.get_rect().center)
angle = 0
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
new_width = round(math.sin(math.radians(angle)) * coin_rect.width)
angle += 2
rot_coin = coin if new_width >= 0 else pygame.transform.flip(coin, True, False)
rot_coin = pygame.transform.scale(rot_coin, (abs(new_width), coin_rect.height))
window.blit(rot_coin, rot_coin.get_rect(center = coin_rect.center))
pygame.display.flip()
pygame.quit()
exit()

Optimizing Pygame sprite images? [duplicate]

I'm having trouble with the framerate in my game. I've set it to 60 but it only goes to ~25fps. This was not an issue before displaying the background (was fine with only win.fill(WHITE)). Here is enough of the code to reproduce:
import os, pygame
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50, 50)
pygame.init()
bg = pygame.image.load('images/bg.jpg')
FPS = pygame.time.Clock()
fps = 60
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
winW = 1227
winH = 700
win = pygame.display.set_mode((winW, winH))
win.fill(WHITE)
pygame.display.set_icon(win)
def redraw_window():
#win.fill(WHITE)
win.blit(bg, (0, 0))
win.blit(text_to_screen('FPS: {}'.format(FPS.get_fps()), BLUE), (25, 50))
pygame.display.update()
def text_to_screen(txt, col):
font = pygame.font.SysFont('Comic Sans MS', 25, True)
text = font.render(str(txt), True, col)
return text
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
redraw_window()
FPS.tick(fps)
pygame.quit()
Ensure that the background Surface has the same format as the display Surface. Use convert() to create a Surface that has the same pixel format. That should improve the performance, when the background is blit to the display, because the formats are compatible and blit do not have to do an implicit transformation.
bg = pygame.image.load('images/bg.jpg').convert()
Furthermore, it is sufficient to create the font once, rather than every time when a text is drawn. Move font = pygame.font.SysFont('Comic Sans MS', 25, True) to the begin of the application (somewhere after pygame.init() and before the main application loop)
Instead use screen.blit(pygame.image.load(picture.png))
Just image = pygame.image.load(picture.png) then screen.blit(image)
( if you keep loading your pictures continuously it will get lag )

How efficient is blitting a surface with a colorkey in pygame? [duplicate]

I'm having trouble with the framerate in my game. I've set it to 60 but it only goes to ~25fps. This was not an issue before displaying the background (was fine with only win.fill(WHITE)). Here is enough of the code to reproduce:
import os, pygame
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50, 50)
pygame.init()
bg = pygame.image.load('images/bg.jpg')
FPS = pygame.time.Clock()
fps = 60
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
winW = 1227
winH = 700
win = pygame.display.set_mode((winW, winH))
win.fill(WHITE)
pygame.display.set_icon(win)
def redraw_window():
#win.fill(WHITE)
win.blit(bg, (0, 0))
win.blit(text_to_screen('FPS: {}'.format(FPS.get_fps()), BLUE), (25, 50))
pygame.display.update()
def text_to_screen(txt, col):
font = pygame.font.SysFont('Comic Sans MS', 25, True)
text = font.render(str(txt), True, col)
return text
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
redraw_window()
FPS.tick(fps)
pygame.quit()
Ensure that the background Surface has the same format as the display Surface. Use convert() to create a Surface that has the same pixel format. That should improve the performance, when the background is blit to the display, because the formats are compatible and blit do not have to do an implicit transformation.
bg = pygame.image.load('images/bg.jpg').convert()
Furthermore, it is sufficient to create the font once, rather than every time when a text is drawn. Move font = pygame.font.SysFont('Comic Sans MS', 25, True) to the begin of the application (somewhere after pygame.init() and before the main application loop)
Instead use screen.blit(pygame.image.load(picture.png))
Just image = pygame.image.load(picture.png) then screen.blit(image)
( if you keep loading your pictures continuously it will get lag )

Categories

Resources