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))
Related
I'm trying to make a chess opening trainer with Pygame. Graphically, it's incredibly simple; it works like a slideshow, I am only blitting a single image to the screen at a time which updates when I press the return key. I am using chess.svg to generate an SVG of the current game state. Not being able to use SVGs natively with pygame means that I have been converting the SVG to a PNG.
Viewing the PNG on my computer, it's very clear.
However when pygame displays the image, it's very blurry.
Ideally I would like pygame to display the SVG so I don't have to worry about the resolution at all. All I found on pygame and SVGs was this link from 12 years ago. In 2018, an answer was posted stating that the original methods no longer worked. However, now, in 2021 the methods given in 2018 no longer work either; I tried, and one comment also confirms this.
If using SVGs is not possible, that's fine, provided I can get pygame to display the PNG at a greater definition than it currently does.
Even if I make screen = pygame.display.set_mode((width, height)) fullscreen, it's still blurry. I can't seem to find anything on that, so I'm not sure that's the issue here.
Here's a simplified version of my code to demonstrate the graphical part:
import pygame
from pygame.locals import *
import chess
import cairosvg
import chess.svg
import chess.pgn
##Setup Pygame:
pygame.init()
width, height = 640, 640
screen = pygame.display.set_mode((width, height))
## MAIN ##
board = chess.Board()
#Step 1: Create image
boardsvg = chess.svg.board(board=board)
f = open("image.SVG", "w")
f.write(boardsvg)
f.close()
#scale
cairosvg.svg2png(url="image.svg", write_to="image_scaled.png", scale=3.0)
#Step2: Blit the image
image = pygame.image.load('image_scaled.png')
image = pygame.transform.scale(image, (640, 640))
screen.blit(image,(0,0))
pygame.display.flip()
Does anyone one know what I need to try?
Cheers.
I found that using smoothscale like so image = pygame.transform.smoothscale(image, (width, height)) helped a little, but it still wasn't perfect. In the end I decided to rewrite it in javascript using cm-chessboard.
chess.svg.board has a size keyword argument:
size – The size of the image in pixels (e.g., 400 for a 400 by 400 board), or None (the default) for no size limit.
e.g.
boardsvg = chess.svg.board(board=board, size=1024)
Setting this to your output size should fix the blurryness.
In 2021 you can use Pygame 2 + SDL2, which loads SVG images directly, no need of cairo or any other lib:
import io
import pygame
from pygame.locals import *
import chess
import chess.svg
##Setup Pygame:
pygame.init()
width, height = 640, 640
screen = pygame.display.set_mode((width, height))
## MAIN ##
board = chess.Board()
#Step 1: Create image
boardsvg = io.BytesIO(chess.svg.board(board=board).encode())
#Step 2: Blit the image
image = pygame.image.load(boardsvg)
image = pygame.transform.scale(image, (640, 640))
screen.blit(image,(0,0))
pygame.display.flip()
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.
I am trying to make the background of an image transparent in a Pygame script. Now the background in my game is black, instead of transparent. I read somewhere else that I could use convert_alpha, but it doesn't seem to work.
Here is (the relevant part of) my code:
import PIL
gameDisplay = pygame.display.set_mode((display_width, display_height))
img = pygame.image.load('snakehead1.bmp').convert_alpha(gameDisplay)
What am I doing wrong? Thanks in advance!
To make an image transparent you first need an image with alpha values. Be sure that it meets this criteria! I noticed that my images doesn't save the alpha values when saving as bmp. Apparently, the bmp format do not have native transparency support.
If it does contain alpha you should be able to use the method convert_alpha() to return a Surface with per-pixel alpha. You don't need to pass anything to this method; if no arguments are given the new surface will be optimized for blitting to the current display.
Here's an example code demonstrating this:
import pygame
pygame.init()
screen = pygame.display.set_mode((100, 100))
image = pygame.image.load("temp.png").convert_alpha()
while True:
screen.fill((255, 255, 255))
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
screen.blit(image, (0, 0))
pygame.display.update()
And my image ("temp.png"):
If it doesn't contain alpha there are two easy fixes.
Save the image with a different file format, like png.
Use colorkeys. This works if you only need to remove the background. It is as easy as putting the line of code image.set_colorkey((0, 0, 0)), which will make all black colors transparent.
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.
I want to make a game using pygames in python and I have a background which I want to load only at the beginning of the game not at every frame and the background should still appear.
I load the background like this in a init function:
self.window = pygame.display.set_mode((self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
self.screen = pygame.display.get_surface()
self.rasp = "../images/image.jpg"
self.rasp_surface = pygame.image.load(self.rasp)
self.rasp_surface = pygame.transform.scale(self.rasp_surface, (self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
self.screen.blit(self.rasp_surface, (0,0))
and in a run function I do this :
while True:
...
self.screen.blit(self.rasp_surface, (0,0))
pygame.display.update()
If you have a while loop with pygame.display.update() in it, you are constantly doing this. This is unnecessary. However, it is likely you are moving sprites or images over the background, so just make sure to fill in the portion of the image that the sprite is moving over as it moves. You can make a move function to do that for you.