Optimizing Pygame sprite images? [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 to get the scaled output with the same ratio

I'm trying to make a game using pygame but I came up with an issue of people getting annoyed of the resolution they're working with, and can't resize window without stretching it.
Here is an example picture of what I'm trying to achieve.
here's what I tried.
window.blit(pg.transform.scale(screen, (window.get_size())), (0, 0)) # The game screen stretching
PS: It's hard to explain so I had to show an image
Use the following algortihm:
Get the bounding rectangle of the image and set the center of the rectangle to the center of the destination rectangle.
Use pygame.Rect.fit() to resize and move the aspect ratio rectangle into the destination rectangle.
Use the size of the new rectangle to scale the image.
blit the image at the position of the rectangle.
def blit_fit(dest_surf, image, dest_rect):
image_rect = image.get_rect(center = dest_rect.center)
fit_rect = image_rect.fit(dest_rect)
scaled_image = pygame.transform.scale(image, fit_rect.size)
dest_surf.blit(scaled_image, fit_rect)
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
image = font.render("Screen", True, (255, 255, 0))
pygame.draw.rect(image, (255, 255, 255), image.get_rect(), 1)
def blit_fit(dest_surf, image, dest_rect):
image_rect = image.get_rect(center = dest_rect.center)
fit_rect = image_rect.fit(dest_rect)
scaled_image = pygame.transform.scale(image, fit_rect.size)
dest_surf.blit(scaled_image, fit_rect)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(0)
blit_fit(window, image, window.get_rect())
pygame.display.flip()
clock.tick(100)
pygame.quit()
exit()

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()

What can I improve considering these cProfile results? [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