I'm trying to capture a video of my game by saving each frame as an image than stitching them together using ffmpeg. I followed the example of these scripts:
http://www.pygame.org/wiki/DummyVideoDriver
http://www.pygame.org/wiki/HeadlessNoWindowsNeeded
Here's the basic logic of my code:
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.init()
pygame.display.set_mode((1,1))
screen = pygame.Surface((400, 400)).convert()
# screen becomes attribute of game object: game.screen
game = MyGame(screen)
while game.running:
game.update() # <--- updates game.screen
pygame.display.flip()
pygame.image.save(game.screen, 'frame-%03d.png' % (game.frame_num))
create_video_using_ffmpeg()
If I comment out the first line setting video driver to 'dummy', the images turn out as expected. But it opens a (small) window, so the script fails when run as a cronjob. With the line uncommented, I just get a series of blank black images.
Any idea what's going wrong?
I was able to work around this by drawing a rectangle to the base image surface serving as my screen:
os.environ['SDL_VIDEODRIVER'] = 'dummy'
pygame.init()
pygame.display.set_mode((1,1))
# surface alone wouldn't work so I needed to add a rectangle
screen = pygame.Surface((400, 400), pygame.SRCALPHA, 32)
pygame.draw.rect(screen, (0,0,0), (0, 0, 400, 400), 0)
# screen becomes attribute of game object: game.screen
game = MyGame(screen)
while game.running:
game.update() # <--- updates game.screen
pygame.display.flip()
pygame.image.save(game.screen, 'frame-%03d.png' % (game.frame_num))
create_video_using_ffmpeg()
Perhaps someone else can explain why this makes a difference. (Was I using the wrong surface parameters originally?)
This worked successfully as a cronjob.
Related
I want to learn pygame and code small fun games with it. So I have started learning this library.
After running this code;
import pygame
from sys import exit
pygame.init()
display_surface = pygame.display.set_mode((800, 400))
pygame.display.set_caption("My Game")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# draw all our elements
# update everything
pygame.display.update()
I see a black screen but there are some artefacts in the screen, like this;
The screen I am talking about
In the Youtube tutorial I am following, the screen is solid black. I don't understand why my screen is different and has some green points in it. My computer works normally and if I restart the program or the computer nothing changes. The pattern is always the same. I can of course fill the display surface black with extra code, and then it works.
My question is, why do I have these points on the display surface in the first place? If someone is knowledgeable about the topic; what do these green lines mean?
I am just curious : )
MacOS Mojave 10.14.6
You must clear the screen with display_surface.fill(0):
run = True
while run :
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
display_surface.fill(0)
# draw all our elements
# update everything
pygame.display.update()
pygame.quit()
exit()
I would like to know how to draw images using pygame. I know how to load them.
I have made a blank window.
When I use screen.blit(blank, (10,10)), it does not draw the image and instead leaves the screen blank.
This is a typical layout:
myimage = pygame.image.load("myimage.bmp")
imagerect = myimage.get_rect()
while 1:
your_code_here
screen.fill(black)
screen.blit(myimage, imagerect)
pygame.display.flip()
import pygame, sys, os
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((100, 100))
player = pygame.image.load(os.path.join("player.png"))
player.convert()
while True:
screen.blit(player, (10, 10))
pygame.display.flip()
pygame.quit()
Loads the file player.png.
Run this and it works perfectly. So hopefully you learn something.
Images are represented by "pygame.Surface" objects. A Surface can be created from an image with pygame.image.load:
my_image_surface = pygame.load.image('my_image.jpg')
However, the pygame documentation notes that:
The returned Surface will contain the same color format, colorkey and alpha transparency as the file it came from. You will often want to call convert() with no arguments, to create a copy that will draw more quickly on the screen.
For alpha transparency, like in .png images, use the convert_alpha() method after loading so that the image has per pixel transparency.
Use the appropriate conversion method for best performance:
image_surface = pygame.load.image('my_image.jpg').convert()
alpha_image_surface = pygame.load.image('my_icon.png').convert_alpha()
A Surface can be drawn on or blended with another Surface using the blit method. The first argument to blit is the Surface that should be drawn. The second argument is either a tuple (x, y) representing the upper left corner or a rectangle. With a rectangle, only the upper left corner of the rectangle is taken into account. It should be mentioned that the window respectively display is also represented by a Surface. Therefore, drawing a Surface in the window is the same as drawing a Surface on a Surface:
window_surface.blit(image_surface, (x, y))
window_surface.blit(image_surface,
image_surface.get_rect(center = window_surface.get_rect().center))
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
pygameSurface = pygame.image.load('apple.png').convert_alpha()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill((127, 127, 127))
window.blit(pygameSurface, pygameSurface.get_rect(center = window.get_rect().center))
pygame.display.flip()
pygame.quit()
exit()
pygame.image.load is bale to load most images. According to the documentation the following formats are supported: JPG, PNG, GIF (non-animated), BMP, PCX, TGA (uncompressed), TIF, LBM (and PBM), PBM (and PGM, PPM), XPM.
If you want to use images in PyGame that are loaded with other libraries, see:
PIL and pygame.image
How do I convert an OpenCV (cv2) image (BGR and BGRA) to a pygame.Surface object
For information on loading Scalable Vector Graphics (SVG) files, see:
SVG rendering in a PyGame application
Loading animated GIF files is presented at:
How can I load an animated GIF and get all of the individual frames in PyGame?
How do I make a sprite as a gif in pygame?
Or see how to load NumPy frames:
Pygame and Numpy Animations
After using blit or any other update on your drawing surface, you have to call pygame.display.flip() to actually update what is displayed.
I am trying to make a pygame window that can be resized but after resizing it just deletes everything on it. So I thought of a solution on my own.
pygame.init()
screen=pygame.display.set_mode((640,360),pygame.RESIZABLE)
clock=pygame.time.Clock()
screen.blit(somesurface,(0,0))
pygame.display.flip()
while True:
clock.tick(100)
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()
if event.type==pygame.VIDEORESIZE:
old=screen
screen=pygame.display.set_mode(event.size,pygame.RESIZABLE)
screen.blit(old,(0,0))
del old
pygame.display.flip()
But this doesnt work. The blitted surface just disappears after resizing.
I'm using python 3.8.5 and pygame 1.9.6
The main issue is that pygame.display.set_mode does not create a new surface object. It just resets the existing one. When you're 'saving' the old surface, you're just creating another reference to the same object. If you want to save the current screen surface, use surface.copy().
I updated your code to copy the screen then redraw the saved screen surface centered on the new screen. I also print the screen memory address before and after set_mode. You can see the screen address doesn't change.
import pygame
pygame.init()
screen=pygame.display.set_mode((640,360),pygame.RESIZABLE)
clock=pygame.time.Clock()
somesurface = pygame.Surface((640,360)) # new surface
somesurface.fill((255,255,255)) # fill white
pygame.draw.circle(somesurface,(100,100,255),(320,190),50) # draw blue circle
screen.blit(somesurface,(0,0)) # draw surface onto screen
pygame.display.flip()
while True:
clock.tick(100)
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
exit()
if event.type==pygame.VIDEORESIZE:
print(id(screen)) # memory address of screen object
old=screen.copy() # copy current screen to temp surface
screen=pygame.display.set_mode(event.size,pygame.RESIZABLE) # reset screen
print(id(screen)) # memory address of 'new' screen object, same address :(
screen.blit(old,((event.w-old.get_width())//2,(event.h-old.get_height())//2)) # draw back temp surface centered
del old # delete temp surface
pygame.display.flip()
I wanted a background picture for my game that would always be behind the player character and enemies. I just typed in:
background = pygame.image.load("mypicture")
at the top of my code, before my running loop. I then blit the image by typing:
screen.blit(background, (0, 0))
if I blit the image BEFORE the running loop, the game is not laggy at all, but everywhere the player character moves, it leaves an outline that never goes way, as shown
However, if I blit the image DURING the running loop, the previously mentioned tracer effect doesn't happen, but instead, the gamer runs insanely slow.
It's worth mentioning some of the code for my player character:
def Player(x, y):
screen.blit(PlayerImg, (x, y))
I call the function at the end of the running loop, right before
pygame.display.update
. The player is placed at coordinates x, y, which are decided based on input from the keyboard.
Try adding convert method: background = pygame.image.load("mypicture").convert(). This will improve performance. More info here [https://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert]
And if you want your background to refresh you must call it inside the loop.
I am new to the sikuli , while running my script i found an error "[error] Region(-32000,-32000,160,27) outside any screen - subsequent actions might not work as expected" .
Please someone help me out how to over come from this issue.
My script as follows : Open an Window App if the App is not opened and if is already opened then focus on App
from __future__ import with_statement
from sikuli.Sikuli import *
class LaunchClient(object):
def __init__(self):
self.appCoordinates = (0, 0, 1024, 768)
def startApp(self):
clientApp = App("XYZ")
if not clientApp.window():
App.open(r"C:\\Program Files (x86)\\ABC \\XYZ.exe"); wait(2)
clientApp.focus(); wait(1)
def runTest(self):
self.startApp()
if __name__ == "__main__":
client = LaunchClient()
client.runTest()
The Error message "[error] Region(-32000,-32000,160,27) outside any screen - subsequent actions might not work as expected" display when the window app is already opened . Error not observed while opening the App .
It means your app is reacing the borders of your screen. For example, you can open "Notepad" and drag it off the screen so you can only see half of it. Then there is a part outside the screen.
That is what this error means.
It will also give this message when a few pixels (for the app) are outside the screen.
It is just a way from Sikuli telling you it can only click on the things that are on the screen not outside it. If you make the app full screen it mostly disapears. (Or you app is opening while touching an edge of the screen.)