I was wondering if anyone out there would be able to help me with my problem. Currently I want to display a pause screen everytime a certain key is pressed, which it does however the resulting screen is always either fully transparent or non-transparent and was wondering if there was any way that I would be able to adjust the following code in order to make that dream a reality.
Here's where the Pause Screen is called:
if event.key == pygame.K_p:
notPaused = False
#print("Obtained")
pause = Pause(self.pauseScreen)
while notPaused == False:
#print("Received")
notPaused = pause.processEvents()
print(str(notPaused))
pause.displayFrame(self.pauseScreen)
clock = pygame.time.Clock()
clock.tick(60)
And here's how the pause screen displays itself:
screen.fill(constants.BLACK)
font = pygame.font.SysFont("serif", 25)
for counter in range(1,5):
text = font.render(self.options[counter-1], True, constants.WHITE)
center_x = 150
center_y = (counter * 120) - (text.get_height() // 2) + (self.pointer.image.get_height() // 2)
screen.blit(text, [center_x, center_y])
self.active_sprite_list.draw(screen)
pygame.display.flip()
And for anyone wondering I sometimes try to sub out BLACK for ABLACK using the RGBA values of: (0,0,0,125)
Finally this is where the screen is initialized for the pause screen:
self.size = [constants.SCREEN_WIDTH, constants.SCREEN_HEIGHT]
self.pauseScreen = pygame.Surface(self.size,pygame.SRCALPHA,32)
Any and all help is appreciated.
You should build up your pause screen as a separate surface. This command: screen.fill(constants.BLACK) all but ensures you will never get 50% transparency (since everything that was on your screen before has been painted over with black).
Build a new surface for your pause screen, fill it black, add your text; then use something like my_pause_surface.set_alpha(128) to make that whole surface 50% transparent, then blit it on top of the rest of your game.
Here is some useful information in another question: Draw a transparent rectangle in pygame
Related
I am trying do end credits like animation the code above for Title crawl, I am trying to make the following changes to it:- 1) The text should begin at the bottom of screen at certain location, such that no other text from the string should be displayed below that location on the screen. 2) The text should stop at certain location on top of screen such that the line at the top should be deleted as soon as it reaches that location making room for other lines in the string.
I am a python newbie, I am just experimenting with things, the following code doesn't belong to me either.
import pygame
from pygame.locals import *
pygame.init()
pygame.display.set_caption('Title Crawl')
screen = pygame.display.set_mode((1000, 800))
screen_r = screen.get_rect()
font = pygame.font.SysFont("franklingothicdemibold", 40)
clock = pygame.time.Clock()
def main():
crawl = ["Star Wars - The Wilds"," ","It is a dark time for the Galaxy. The evil Dark","Lord, Vitiate is rising to power. Alone, a single", "spec is on a trip, a trip that will ultimately", "rectify the wrongs of the galaxy. The keepers ", "of peace are dying out and the DARK SIDE is", "lurking, a conniving force determined to", "become the omniarch."]
texts = []
# we render the text once, since it's easier to work with surfaces
# also, font rendering is a performance killer
for i, line in enumerate(crawl):
s = font.render(line, 1, (229, 177, 58))
# we also create a Rect for each Surface.
# whenever you use rects with surfaces, it may be a good idea to use sprites instead
# we give each rect the correct starting position
r = s.get_rect(centerx=screen_r.centerx, y=screen_r.bottom + i * 45)
texts.append((r, s))
while True:
for e in pygame.event.get():
if e.type == QUIT or e.type == KEYDOWN and e.key == pygame.K_ESCAPE:
return
screen.fill((0, 0, 0))
for r, s in texts:
# now we just move each rect by one pixel each frame
r.move_ip(0, -1)
# and drawing is as simple as this
screen.blit(s, r)
# if all rects have left the screen, we exit
if not screen_r.collidelistall([r for (r, _) in texts]):
return
# only call this once so the screen does not flicker
pygame.display.flip()
# cap framerate at 60 FPS
clock.tick(60)
if __name__ == '__main__':
main()
Use set_clip() to set the clipping region of the display surface.
e.g. Clip 100 rows at the top and the bottom:
# set clipping rectangle
clip_rect = (0, 100, screen.get_width(), screen.get_height()-200)
screen.set_clip(clip_rect)
for r, s in texts:
# now we just move each rect by one pixel each frame
r.move_ip(0, -1)
# and drawing is as simple as this
screen.blit(s, r)
# cancel clipping for further drawing
screen.set_clip(None)
UPDATED ISSUE
I have discovered the issue appears to be with the fact that I am using the FULLSCREEN display flag to create the window. I added a rectangle to be drawn in the top left of the scree (0, 0), but when I run the program, It is mostly off the screen. Then, when I Alt-Tab away and back, the rectangle is appropriately placed at 0,0 and the turret is off center.
So basically, when the program starts, the game screen is larger than my actual screen, but centered. Then after Alt-Tab, the game screen is lined up with 0,0 but since the game screen is larger than my screen, the turret looks off center, but is actually centered relative to the game.
So the real question is why does using the FULLSCREEN display flag make a screen larger than my computer screen?
ORIGINAL ISSUE
I am building a simple demonstration of a turret in the center of the screen which follows the location of the cursor as if to fire where it is. Everything works perfectly until I Alt-Tab away from the screen, and then Alt-Tab back. At this point to turret is now off center (down and to the right)
import pygame, math
pygame.init()
image_library = {}
screen_dimen = pygame.display.Info()
print("Screen Dimensions ", screen_dimen)
def get_image(name):
if name not in image_library:
image = pygame.image.load(name)
image_library[name] = image
else:
image = image_library[name]
return image
robot_turret_image = get_image('robot_turret.png')
screen = pygame.display.set_mode((0, 0), pygame.`FULLSCREEN`)
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEMOTION:
print(event.pos)
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
done = True
screen.fill((0, 0, 0))
pos = pygame.mouse.get_pos()
angle = 360 - math.atan2(pos[1] - (screen_dimen.current_h / 2),
pos[0] - (screen_dimen.current_w / 2)) * 180 / math.pi
rot_image = pygame.transform.rotate(robot_turret_image, angle)
rect = rot_image.get_rect(center=(screen_dimen.current_w / 2, screen_dimen.current_h / 2))
screen.blit(rot_image, rect)
color = (0, 128, 255)
pygame.draw.rect(screen, color, pygame.Rect(0, 0, 200, 200))
pygame.display.update()
clock.tick(60)
It seems that the center is now off. I have printed out the screen dimensions before and after the Alt-Tab and they are the same, so I can't figure out why the image moves. I believe I am missing something regarding state changes with Pygame, but can't figure out what. If it is relevant, I am on Windows 10.
Alright, I discovered a solution from gamedev.stackexchange
And I will re-hash it here. The issue was that Using the fullscreen tag was making a screen larger than my computer screen. The following code solves this
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
true_res = (ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1))
pygame.display.set_mode(true_res,pygame.FULLSCREEN)
It is important to note that this is potentially just a windows fix, but I do not have another system with which to test it on. But It works on Windows 10 with python 3.5.1 and pygame 1.9.2a0
UPDATED ISSUE
I have discovered the issue appears to be with the fact that I am using the FULLSCREEN display flag to create the window. I added a rectangle to be drawn in the top left of the scree (0, 0), but when I run the program, It is mostly off the screen. Then, when I Alt-Tab away and back, the rectangle is appropriately placed at 0,0 and the turret is off center.
So basically, when the program starts, the game screen is larger than my actual screen, but centered. Then after Alt-Tab, the game screen is lined up with 0,0 but since the game screen is larger than my screen, the turret looks off center, but is actually centered relative to the game.
So the real question is why does using the FULLSCREEN display flag make a screen larger than my computer screen?
ORIGINAL ISSUE
I am building a simple demonstration of a turret in the center of the screen which follows the location of the cursor as if to fire where it is. Everything works perfectly until I Alt-Tab away from the screen, and then Alt-Tab back. At this point to turret is now off center (down and to the right)
import pygame, math
pygame.init()
image_library = {}
screen_dimen = pygame.display.Info()
print("Screen Dimensions ", screen_dimen)
def get_image(name):
if name not in image_library:
image = pygame.image.load(name)
image_library[name] = image
else:
image = image_library[name]
return image
robot_turret_image = get_image('robot_turret.png')
screen = pygame.display.set_mode((0, 0), pygame.`FULLSCREEN`)
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEMOTION:
print(event.pos)
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
done = True
screen.fill((0, 0, 0))
pos = pygame.mouse.get_pos()
angle = 360 - math.atan2(pos[1] - (screen_dimen.current_h / 2),
pos[0] - (screen_dimen.current_w / 2)) * 180 / math.pi
rot_image = pygame.transform.rotate(robot_turret_image, angle)
rect = rot_image.get_rect(center=(screen_dimen.current_w / 2, screen_dimen.current_h / 2))
screen.blit(rot_image, rect)
color = (0, 128, 255)
pygame.draw.rect(screen, color, pygame.Rect(0, 0, 200, 200))
pygame.display.update()
clock.tick(60)
It seems that the center is now off. I have printed out the screen dimensions before and after the Alt-Tab and they are the same, so I can't figure out why the image moves. I believe I am missing something regarding state changes with Pygame, but can't figure out what. If it is relevant, I am on Windows 10.
Alright, I discovered a solution from gamedev.stackexchange
And I will re-hash it here. The issue was that Using the fullscreen tag was making a screen larger than my computer screen. The following code solves this
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
true_res = (ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1))
pygame.display.set_mode(true_res,pygame.FULLSCREEN)
It is important to note that this is potentially just a windows fix, but I do not have another system with which to test it on. But It works on Windows 10 with python 3.5.1 and pygame 1.9.2a0
If I set a pygame window to resizable and then click and drag on the border of the window the window will get larger but nothing blit onto the surface will get larger with it. (Which is understandable) How would I make it so that when I resize a window all blit objects resize with it and fill the window properly?
For example: Say I have a window of 200 x 200 and I blit a button at window_width/2 and window_height/2. The button would be in the center of the window at 100 x 100. Now if I resize the window to 300 x 300 the button stays at 100 x 100 instead of 150 x 150.
I tried messing around with pygame.Surface.get_width ect, but had no luck.
Basically I'm trying to resize a program's window and have all blit images stay proportionate.
Don't draw on the screen directly, but on another surface. Then scale that other surface to size of the screen and blit it on the screen.
Here's a simple example:
import pygame
from pygame.locals import *
def main():
pygame.init()
screen = pygame.display.set_mode((200, 200),HWSURFACE|DOUBLEBUF|RESIZABLE)
fake_screen = screen.copy()
pic = pygame.surface.Surface((50, 50))
pic.fill((255, 100, 200))
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.display.quit()
elif event.type == VIDEORESIZE:
screen = pygame.display.set_mode(event.size, HWSURFACE|DOUBLEBUF|RESIZABLE)
fake_screen.fill('black')
fake_screen.blit(pic, (100, 100))
screen.blit(pygame.transform.scale(fake_screen, screen.get_rect().size), (0, 0))
pygame.display.flip()
main()
so without the gui initialization (pygame init, and setmode comands ) in the section where you have existing pygame event get()(which your only allowed one time (or just put in ''for inkey in pygame.event.get(VIDEORESIZE):''(
if you want to be redundant))(note you can only use ''for inkey in pygame.event.get(VIDEORESIZE):'' one time per loop because it is really a stack that unstacks when you read the event list so you should really use ''for inkey in pygame.event.get():'' snd put all your key recognission statements after this one occurrance of ''for inkey in pygame.event.get():'':
for inkey in pygame.event.get(VIDEORESIZE)
if inkey.type == pygame.VIDEORESIZE:
winwidth,winhight = inkey.size # or event.w, event.h
Window1copy = Window1.copy()# make copy of existing window
Window1=pygame.display.set_mode((winwidth,winhight),pygame.RESIZABLE)
Window1.blit(Window1copy, (0, 0))
pygame.display.update()
Recently with pygame2.0 You can use the SCALED flag
Is it possible to stretch an image in pygame using an event to trigger it?
Like say I have a person and I want his eyes to popout like this
when I press a button and I am using surface.blit(eyes=pygame.image.load('eyes')) for the eyes.
Can i stretch the eye image like the picture in this link?
There is a solution to this problem that allows you to stretch the eyes to the exact width you want, but it may make the eyes very deformed... (nevermind, the original image has pretty deformed eyes anyway.)
From the Pygame doc on pygame.transform.scale:
scale(Surface, (width, height), DestSurface = None) -> Surface
We also use image.get_height() so the user does not have to get the height themselves.
So you would do something like this (wrapped in a function):
def stretchEyes(image, newWidth):
return pygame.transform.scale(image, (image.get_height(), newWidth))
eyes = stretchEyes(eyes, image.get_width()*3) # Stretch to three times width
# Blitting takes in the top left position, so we don't need to do any maths here!
screen.blit(eyes, (x,y))
A better approach would be to have two images one for the actual image and one where the eyes are stretched. Draw the second image whenever you need instead of the first image.
import pygame
from pygame.locals import *
screen = pygame.display.set_mode((540, 480))
runner1 = pygame.image.load('./runner1.jpg').convert()
runner1_rect = runner1.get_rect(center=(270, 240))
runner2 = pygame.image.load('./runner2.jpg').convert()
runner2_rect = runner2.get_rect(center=(270, 240))
screen.fill((0, 0, 0))
change = True
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == MOUSEBUTTONDOWN:
screen.blit(runner2, runner2_rect)
pygame.display.update()
if event.type == KEYDOWN:
screen.blit(runner1, runner1_rect)
pygame.display.update()
As shown in the above example, we get images(sprites) of different postures and play them as and when we need to get the motion.
To begin and understand the pygame start from PUMMEL THE CHIMP and there are good API to handle sprites and their behavior through pygame.