Displaying a high resolution .png image with pygame - python

I am currently trying to develop a computer game with pygame - and I'd like to display a background image for the game (2D-jump-and-run).
However I noticed a significant frame-rate drop when displaying a full-screen background image, above a certain window-size:
Windowsize | Time to blit the image | (~ FPS)
1280x720: 0.029s (~32 FPS)
1366x768: 0.031s (~29 FPS)
1600x900: 0.042s (~22 FPS)
1920x1080: 0.062s (~15 FPS)
Is there a different, more effective way of blitting the image? I wouldn't want to restrict the game to such small window sizes as 1366x768 and lower...
I tried using an image which was smaller concerning the KB-size, as well as trying to blit 4 images with 1/4 the size to cover the screen, but the times remains the same.
The game runs on the pygame screen, so I can't use any functions of e.g. Tkinter (as they would need a Tkinter surface).
Currently im using the following function of pygame:
# Once at the beginning
screen = pygame.display.set_mode((screenWidth_X, screenHeight_Y))
# Every frame
screen.blit(background_Image, (0,0))
Any help/suggestions would be greatly appreciated!

Per Ted Klein Bergman's comment, using .convert() and .convert_alphais a huuuuge performance boost.
# From originally:
1920x1080: 0.062s (~15 FPS)
# To:
1920x1080: 0.002s (~140 FPS)

Related

Pygame zooming screen

im writing a game right now with 32x32 textures, i have a problem because my screen window is too small, is there any solution? Can i "zoom" my whole game?
Now it looks like this and exactly what i want is to make whole screen bigger and zoom to see only like 5% of map.
Of course, if i make my screen bigger it not gonna fix my problem.
Maybe i should add another camera or something?
I think I made myself quite clear.
Thanks!
First, you can definitely zoom as you are saying.
screen.blit(pygame.transform.scale(display, (int(width), int(height)))
You can resize the screen:
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT),pygame.RESIZABLE)
def resize(event):
global WINDOWWIDTH, WINDOWHEIGHT
if event.type == pygame.VIDEORESIZE:
WINDOWWIDTH = event.size[0]
WINDOWHEIGHT = event.size[1]
return pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), pygame.RESIZABLE)
And have the display the actual size you want to draw to:
display = pygame.Surface((300,200))
However, scaling surfaces is really bad as pixel art isn't great at scaling. An alternative would be a camera or switching off of pygame which would make everything you are trying to do way less complicated. I would recommend rubato for a start. It will do all this work for you, and you can decide how big you want your actual grid (display) to be with one variable.
Good luck! Feel free to comment if you want any extra help.
One way you can fix this is by shrinking the size of the screen itself:
#you can adjust the width and height in game until it seems the right fit
screen=pygame.display.set_mode((WIDTH,HEIGHT))
And if you want, you can set the window to Fullscreen:
screen=pygame.display.set_mode((WIDTH,HEIGHT),pygame.FULLSCREEN)

Pygame/MoviePy - The video displays with a terrible framerate and the window size is bigger than my screen [duplicate]

This question already has answers here:
How to load and play a video in pygame
(3 answers)
Closed last year.
I've been looking around for a while trying to find a way to display videos in Pygame because of a new story video-game project. I finally stumbled across Moviepy which works alright...except that the video displays showing only one of the 24 frames each second and the window it displays in is bigger than by screen.
(on a Windows 10 laptop with an 11inch(I think) screen)
The sound is alright but the video also goes too fast so is out of sync.
I've tried the resize function as said on the docs but it gives no effect.
And I can't find anything to do with the framerate.
So I need a way to make the window smaller and correct the framerate.
This is the code I used:
from moviepy.editor import VideoFileClip
from moviepy.video.fx.resize import resize
import pygame
pygame.display.set_caption('My video!')
clip = VideoFileClip('Eleeza Crafter And The Cloud Colours Trailer.mp4')
clip.fx(resize, width=240)
clip.preview(fps=24)
pygame.quit()
Any help would be appreciated. Thanks :)
EDIT: I tested a different video at the same framerate and it works perfectly?
Then again it was just a simple line flying around the screen.
A 2 seconds google gave me this link.
It states :
A clip can be previewed as follows
my_clip.preview() # preview with default fps=15
my_clip.preview(fps=25)
my_clip.preview(fps=15, audio=False) # don't generate/play the audio.
my_audio_clip.preview(fps=22000)
Also (depending of your import method:
This way you can use clip.resize(width=240) instead of the longer clip.fx( resize, width=240).
Still from the documentation:
For advanced image processing you will need one or several of these packages. For instance using the method clip.resize requires that at least one of Scipy, PIL, Pillow or OpenCV are installed.
I don't know if this is the problem, but for screen size you should use pygame.display.set_mode((WIDTH, HEIGHT)) (change the WIDTH value to your desired width and the HEIGHT value to your desired height. Also, something I have noticed with pygame is that the big windows have lots of lag, so maybe a smaller window size would be recommended. I find that 500x500 is the maximum size for no lag (at least on my laptop)

Pygame : Getting rid of strange gradient effect on displayed image

Hello fellow programmers,
I wrote a little python program which is use to launch random games on a retrograming distribution, and I use pygame to display the image of the game before launching it
I use a background and my issue is that the background image is clean but when displaying it and the cover of the game over it, it appears with a strange ugly gradient effect as you can see there : https://imgur.com/a/BnNdoqn
It appears mostly in the corner and the cover itself is entirely unaffected.
Here is my pygame code displaying both images :
log('showPic %s' %file)
# INITS
pygame.init()
pygame.mouse.set_visible(0)
backgroundPicture = pygame.image.load(backgroundFile)
picture = pygame.image.load(file)
# # CREATE FULLSCREEN DISPLAY. X = 1920- Y = 1080
fullscreen = pygame.display.set_mode((1920,1080), FULLSCREEN)
fullscreen.blit(backgroundPicture, (0,0))
# # PASTE PICTURE ON FULLSCREEN
x = (1920 - picture.get_width()) /2
y = (1080 - picture.get_height()) /2
fullscreen.blit(picture, (x,y))
# # SHOW FULLSCREEN
pygame.display.flip()
# # WAIT 5 SECONDS (need import time)
time.sleep(5)
# # EXIT PYGAME (Not needed but recommanded)
pygame.display.quit()
pygame.quit()
backgroundPicture is the background image and picture is the cover of the game, I combined the too like it appears in second capture.
So mainly I don't know much at all about display, images, graphical libraries and all that.
I think that this might be related to transparency or alpha layer or compression format of the image but I have no knowledge at all about that either.
The code is launched on a raspberry pi with a linux distribution, don't know much more about it.
Also strangely, one of my users said the strange gradient effect seems to disappear after ten or so launches of the script, but I couldn't reproduce that.
So what am I missing to get rid of that ugly effect ?
Here is the background image here if its characteristic might be related to the problem :
Thank you for your help !
The effect you are seeing is called "banding", see Wikipedia article. It is caused by not having enough bit-depth to represent fine gradations of colour and is most noticeable in large, untextured areas.
There are not many things you can do about it. Your options are basically:
to go to a 16-bit setup instead of 8-bit, if pygame can do that, or
add a small amount of random noise, or dithering to break it up.

pygame.error No video mode large enough

I have been working on a game using the pygame module for python and am having an issue getting it to display properly on other computers. When I first starting writing I chose a resolution of (1400,1000). There was no real reason for this choice, I was/am new to programming and it seemed like a nice round number. The issue I am having is that on many laptops the screen is bigger than the max resolution. I can run it in windowed mode but then the screen runs off to the right and the bottom and there are things that the user cannot see. I then tried to run it in full screen mode, but then I get the error message "pygame.error No video mode large enough for 1400 , 1000"
The most obvious solution is to reduce my screen resolution I suppose, but all my GUI menu buttons are blitted to the screen assumming a resolution of (1400,1000) and changing everything would be extremely tedious.
The most curious thing happens when I connect a USB moniter with a resolution high enough to display it properly; The game will display properly on the connected moniter, and will also resize itself to display properly on the laptop moniter as well!. I can then disconnect the other moniter and go about playing the game no problem!
If I could somehow "trick" the computer into thinking there is a moniter connected with a proper resolution everything would work perfect. Not a perfect or elegant solution I admit, but I loathe having to go back and redo my entire GUI...
size = (1400, 1000)
screen = pygame.display.set_mode(size,pygame.FULLSCREEN)
Read up on pygame.org/docs
pygame.display.set_mode() will use your current screen resolution automatically, no matter what computer you are on as long as you don't pass in any parameters.
As to why 1400 by 1000 wasn't working for you, that is not a common screen resolution (not even sure if it exists). Some common ones include:
1280 by 720
1600 by 900
1920 by 1200
"The most obvious solution is to reduce my screen resolution I suppose, but all my GUI menu buttons are blitted to the screen assumming a resolution of (1400,1000) and changing everything would be extremely tedious."
A way to avoid this issue is to work in terms of your screen area. For example, lets say I work in a resultion of 1280 by 800.
width = 1280
height = 800
screen = pygame.display.set_mode([width, height])
I want my position to be in the middle of the screen. Instead of saying
position = 1280 / 2 # Hardcoded
do
position = width/2
Now no matter what you change your screen width to, your position will be preserved. I recommend looking into http://www.pygame.org/docs/ref/rect.html for information about how to track locations in pygame in a nice way.
About the flags: I don't know much about these so I won't say much, other than that I never use them and don't have any issues doing anything.
I hope this helps
```
from win32api import GetSystemMetrics
width = GetSystemMetrics(0)
height = GetSystemMetrics(1)
size = (width, height)
```
I would try to incorporate this into into your code

Pygame bliting scaled image

When i try to blit an image in pygame the image blits smaller than the actual image, my simplified code is
import pygame
pygame.init()
screen = pygame.display.set_mode((1176,674),0,32)
background = pygame.image.load("picture.jpg").convert()
while True:
screen.blit(background, (0,0))
pygame.display.flip()
The resulting image is about half the size it should be
It is entirely possible that when you view it you have zoomed in. Or there could be formatting irregularities. Either way, there are two simple solutions. Solution number 1 is to just scale up the image in an image editor, if you don't have one, GIMP is free online. A better way is to scale it in the code. You can just double the size of an image you loaded with this modification to your code, solving your problem. Use pygame.transform:
import pygame
pygame.init()
screen = pygame.display.set_mode((1176,674),0,32)
background = pygame.image.load("start_screen.jpg").convert()
background = pygame.transform.scale(background, (1176,674))
while True:
screen.blit(background, (0,0))
pygame.display.flip()
this should work
I found that the issue came from my MacBooks retina screen resolution, once i downloaded a program to adjust the resolution the program worked properly

Categories

Resources