How can I load a huge image with pygame as a background? - python

I'm making a fighting game in pygame but whenever I load a background (940x680 PNG) the program starts to lag really badly, here is my code:
#import section
import os
import pygame
import time
from pygame.locals import *
#end of import section
#initiazing pygame
pygame.init()
print "Loaded Pygame 100%"
#lengths
width, height = 940,680
#opening window
screen = pygame.display.set_mode((width, height))
#position
background = [0,0]
#loading images
back = pygame.image.load("resources/image/Back.png")
print "Loaded graphics 100%"
while 1:
#clear to reload
screen.fill(0)
#drawing background
screen.blit(back, background )
#update
pygame.display.flip()
This may be a newbie question but I just started so yeah...

In pygame you need to use this code you wrote.
#clear to reload
screen.fill(0)
#drawing background
screen.blit(back, background )
#update
pygame.display.flip()
If you add a player to the screen and then move him. You will notice that unless you redraw the background, you will see the character more than once.
Pygame doesn't just let you add an image to the screen and move it around, you must redraw the background to get rid of a previous frame.
Another thing you should add to your code is a wait.
clock = pygame.time.Clock()
FPS = 30
while 1:
clock.tick(FPS)
This will set the frame rate. I'd say you would generally want this at 30 - 60 frames, depending on the game / hardware.
Your current program is probably redrawing the frame a several hundred times, so this will definately add lag.
When I checked this on my pc Ubuntu 12.04 without a background. i.e. A Black screen.
My frame rate was between 1000 - 2000 FPS.

Related

Pygame FPS is only 0.0

So, I am making a game engine in python using pygame. I am trying to get and display fps using pygame.time.Clock().get_fps(), but it is only saying 0.0 . Here is the basic code:
import pygame
from pygame.locals import *
screen = pygame.display.set_mode()
while 1:
print(pygame.time.Clock().get_fps())
pygame.time.Clock().tick(60)
I just need anything that exactly shows current fps.
See get_fps()
Compute your game's framerate (in frames per second). It is computed by averaging the last ten calls to Clock.tick().
So there are 2 reasons why your code does not work. You create a new instance of pygame.time.Clock() every time you call it, and the FPS cannot be averaged. But an even bigger problem is that you call tick from another instance.
You must create one Clock object before the application loop, but not in the application loop, and call tick and get_fps from that object. Also handle the events in the application loop (PyGame window not responding after a few seconds):
import pygame
from pygame.locals import *
screen = pygame.display.set_mode()
clock = pygame.time.Clock()
while 1:
pygame.event.pump()
print(clock.get_fps())
clock.tick(60)
A better way would be to create your clock at the top of your code. Then within the game loop at the end you can enact the .tick function.
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode()
clock = pygame.time.Clock()
while True:
pygame.display.update()
clock.tick(60)

Take screenshot then blit it

Is there a way to take a screenshot (a copy of the previous frame blitted) with pygame from the GUI, assign it to a surface variable and blit it? Without saving the screenshot to a file, then loading it, and finally blitting it,
import pygame, os
pygame.init()
screen = pygame.display.set_mode((800, 400))
def TakeScreenShot(screen):
pygame.image.save(screen, 'ScreenShot.png')
pic = pygame.image.load(os.path.join('ScreenShot.png')).convert()
return pic
pic = TakeScreenShot(screen)
screen.blit(pic, [0,0])
pygame.display.flip()
The saving screenshot then loading seems really unneccsary...is there a method to bypass this and directly blit the screenshot taken to the GUI?
I.e., something such as,
import pygame, os
pygame.init()
screen = pygame.display.set_mode((800, 400))
pic = screen.getLastFrameBlitted()
screen.blit(pic, [0,0])
pygame.display.flip()
You can take a copy of the screen anytime you want and save it in a variable.
screenshot = screen.copy()
screen is just a regular Surface object and can be treated as such. Blitting the screenshot is done as usual
screen.blit(screenshot, (0, 0))

How to use pygame.surface.scroll()?

I just found out about pygame.surface.scroll() and what I understand from the pygame documents that scroll() is for moving surface without the need to rebuild the background again to cover the old surface, just like pygame.rect.move_ip() but for surfaces.
Anyway, I don't know how to use it and the examples in the pygame documents are hard to me to understand as long as I am beginner and, after searching for long time, I couldn't found anything useful to understand how to use it.
Here is my code.
import pygame
from pygame.locals import*
screen=pygame.display.set_mode((1250,720))
pygame.init()
clock=pygame.time.Clock()
boxx=200
boxy=200
image = pygame.Surface([20,20]).convert_alpha()
image.fill((255,255,255))
while True :
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT :
pygame.quit()
quit()
image.scroll(10,10)
screen.blit(image,(boxx,boxy))
pygame.display.update()
clock.tick(60)
EDIT: Your image and screen variables are backwards. That is also causing you some confusion I'm sure..
Your problem may is that you are trying to scroll an all black background. It is probably scrolling, and you just don't know it because the white box you used blit() to draw on the screen is stationary.
Try using something you can see scroll, like an image file. If you wanna move the white box, you can add a counter as a speed variable. Read this, then run it.
import pygame
from pygame.locals import*
screen=pygame.display.set_mode((1250,720))
pygame.init()
clock=pygame.time.Clock()
boxx=200
boxy=200
image = pygame.Surface([20,20]).convert_alpha()
image.fill((255,255,255))
speed = 5 # larger values will move objects faster
while True :
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT :
pygame.quit()
quit()
image.scroll(10,10)
# I did modulus 720, the surface width, so it doesn't go off screen
screen.blit(image,((boxx + speed) % 720, (boxy + speed) % 720))
pygame.display.update()
clock.tick(60)
I can't say for sure the scroll function is working or not, learn to use an image as your background so you can see it moving first.

Don't clear the framebuffer when exiting pygame

I've written a small script to display album art on USB display (on Raspberry Pi) by writing to the framebuffer with pygame. The script is working perfectly and the album art is displayed on the screen for 3 seconds:
def set_image(image):
""" Set the USB display image using pygame (320px x 240px) """
pygame.display.init()
size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
black = 0, 0, 0
screen = pygame.display.set_mode(size)
pygame.mouse.set_visible(False)
pygame_image = pygame.image.fromstring(image.tobytes(), image.size, image.mode)
pygame_image_rect = pygame_image.get_rect()
screen.fill(black)
screen.blit(pygame_image, (40, 0))
pygame.font.init()
pygame.display.update()
time.sleep(3)
The problem is that when the script finishes, pygame (correctly) clears the framebuffer and my image disappears. Is there any way to tell it to leave the contents of the framebuffer when quitting?
Are you calling pygame.quit?
Generally:
- don't run window server (run from console)
- use flip to flip to a different surface
- don't call pygame.quit when exiting.
It is hard to guarantee what happens after that, but flip should flip the screen buffer to a different part of memory than the shell uses, so it won't get overwritten, and if you don't call pygame.quit, it should leave it in the (bad) state. Although there are scenarios this is useful.

Pygame display.info giving wrong resolution size

I'm building a small game with pygame. I want the window of the game to be size of the monitors resolution. My computers screen's resolution is 1920x1080 and display.info says the window size is also 1920x1080 but when I run it, it creates a window roughly one and half times the size of my screen.
import pygame, sys
def main():
#set up pygame, main clock
pygame.init()
clock = pygame.time.Clock()
#creates an object with the computers display information
#current_h, current_w gives the monitors height and width
displayInfo = pygame.display.Info()
#set up the window
windowWidth = displayInfo.current_w
windowHeight = displayInfo.current_h
window = pygame.display.set_mode ((windowWidth, windowHeight), 0, 32)
pygame.display.set_caption('game')
#gameLoop
while True:
window.fill((0,0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#draw the window onto the screen
pygame.display.flip()
clock.tick(60)
main()
I've been having the same problem, and I managed to find the answer and posted it here. The answer I found is as follows:
I managed to find a commit on the Pygame BitBucket page here that explains the issue and gives an example on how to fix it.
What is happening is that some display environments can be configured to stretch windows so they don't look small on high PPI (Pixels Per Inch) displays. This stretching is what causes displays on larger resolutions to display larger than they actually are.
They provide an example code on the page I linked to showing how to fix this issue.
They fix the issue by importing ctypes and calling this:
ctypes.windll.user32.SetProcessDPIAware()
They also express that this is a Windows only solution and is available within base Python since Python 2.4. Before that it will need to be installed.
With that said, to make this work, put this bit of code anywhere before pygame.display.set_mode()
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
#
# # # Anywhere Before
#
pygame.display.set_mode(resolution)
I hope this helps you and anyone else who finds they have this same issue.

Categories