Having an issue with blitting order (I think) and transparent bounding boxes showing up during collisions.
Link to the code and the issue is here: https://github.com/CastleSeven/flappy-balloon/issues/1
Basically, whenever a collision is about to occur, the player model is occluded by a transparent bounding box around the obstacle. I'm not sure what I need to change so that JUST the non-transparent pixels are reblitted for the background on every loop.
If I change the code so that the balloon blit comes AFTER the obstacle blit, I get the inverse effect, the balloon's bounding box occludes the obstacle.
Try using a colorkey, make the background of the textures something ugly like (255, 0, 255) and set the colorkey of the textures the same color. https://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_colorkey
Related
This question already has answers here:
How do I blit a PNG with some transparency onto a surface in Pygame?
(4 answers)
How to fade in a text or an image with PyGame
(2 answers)
Closed 2 years ago.
I'm trying to blit some fog into a game, but I've run into a problem where I've realized that the fog is too thick/opacity to high. I want to blit it with an even lower opacity, but I'm not too sure how and the tutorials I've found online don't work/already expect you to know how to.
Just in case you're wondering how the code is written:
screen.blit(fog, (0, 0))
EDIT: I'm using Python 3.8, just in case that matters
EDIT EDIT: I'm using Pygame 2.0.0, just in case that also matters
You don't blit at lower opacity, you blit a surface that has a lower opacity.
Use surface.set_alpha() to change the opacity of the fog before you blit it.
Docs: https://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha
Also, if you're loading in your fog from an image, be sure to use surface.convert_alpha() on it, or else it will not register the transparency in the image format.
blit() actually blends a Surface onto the target Surface, dependent on the alpha channel of the Surface. All you have to do is change the alpha channel of the fog. Use set_alpha() to set the alpha value for the full Surface image:
Set the current alpha value for the Surface. When blitting this Surface onto a destination, the pixels will be drawn slightly transparent. The alpha value is an integer from 0 to 255, 0 is fully transparent and 255 is fully opaque.
If you want to apply a 50% transparent fog:
fog.set_alpha(127)
screen.blit(fog, (0, 0))
This question already has an answer here:
How do I focus light or how do I only draw certain circular parts of the window in pygame?
(1 answer)
Closed 2 years ago.
That question wasn't very clear.
Essentially, I am trying to make a multi-player Pac-Man game whereby the players (when playing as ghosts) can only see a certain radius around them. My best guess for going about this is to have a rectangle which covers the whole maze and then somehow cut out a circle which will be centred on the ghost's rect. However, I am not sure how to do this last part in pygame.
I'd just like to add if it's even possible in pygame, it would be ideal for the circle to be pixelated and not a smooth circle, but this is not essential.
Any suggestions? Cheers.
The best I can think of is kind of a hack. Build an image outside pygame that is mostly black with a circle of zero-alpha in the center, then blit that object on top of your ghost character to only see a circle around it. I hope there is a better way but I do not know what that is.
If you only want to show the scene inside a circular area, then you can do the following:
Clear the display.
Limit the drawing region to a square area around the circular area
Draw the scene
Draw a transparent circle surface on top of the square area
The circle surface can be created with ease on runtime. Define the radius of the circular area (areaRadius). Create a square pygame.Surface with the doubled radius of the circular area. Fill it with opaque black and draw a transparent circle in the middle:
circularArea = pygame.Surface((areaRadius*2, areaRadius*2), pygame.SRCALPHA)
circularArea.fill((0, 0, 0, 255))
pygame.draw.circle(circularArea, (0,0,0,0), (areaRadius, areaRadius), areaRadius)
The drawing region of a surface can be limited by .set_clip(). Calling the function with the parameter None removes the clipping area. In the following screen is the surface which represents the window and areaCenter is the center of the circular area on the screen:
while run:
# [...]
# remove clipping region and clear the entire screen
screen.set_clip(None)
screen.fill(0)
# set the clipping region to square around the circular area
areaTopleft = (areaCenter[0]-areaRadius, areaCenter[1]-areaRadius)
clipRect = pygame.Rect(areaTopleft, (areaRadius*2, areaRadius*2))
screen.set_clip(clipRect)
# draw the scene
# [...]
# draw the transparent circle on top of the rectangular clipping region
screen.blit(circularArea, areaTopleft)
# clear the dripping region and draw all the things which should be visible in any case
screen.set_clip(None)
# [...]
pygame.display.flip()
I want to darken current screen a bit before poping up a new surface. I know there is no function in pygame to do this and that I will have to process the image to darken it. But as long as I know the only way to get current displaying surface in pygame is by saving it to disk as a file which slows down the game. Is there any other way to do this with pygame? Like saving the image to a value in memory so that I can process it without saving it somewhere.
Thanks in advance,
Stam
You don't need to save anything to a file.
When you read an image to a file, it is a Surface object. You them blit this object to the screen. But these Surface objects have the same methods and properties than the object working as the screen - (which is also a Surface): you can draw primitives, and blit other images to them - all in memory.
So, once you read your image, just make a copy of it, draw a filled rectangle with a solid transparent color on it to darken it, and then blit it to the screen. Repeat the process increasing the transparency level and pasting it on the screen again if you want a fade in effect.
import pygame
screen = pygame.display.set_mode((640,480))
img = pygame.image.load("MYIMAGE.PNG")
for opacity in range(255, 0, -15):
work_img = img.copy()
pygame.draw.rect(work_img, (255,0, 0, opacity), (0,0, 640,480))
screen.blit(work_img, (0,0))
pygame.display.flip()
pygame.time.delay(100)
I have got some surfaces in Pygame with a transparent background. They're all the same size. But there's a different sized circle drawn on each of them, so the circle doesn't exactly fit the image.
Here are some example images (I took a screenshot in Photoshop so you can clearly see the transparency and the size of the images):
Now I want to remove the transparent border around the image so the circle exactly fits into the image. I don't want the surface to be circle shaped, I don't think that's possible, but I want that the surface doesn't have blank columns on the left and right and that it doesn't have any blank rows on the top and the bottom. The wanted results:
The circle on the surfaces changes size every frame so I have to recalculate the new surfaces every frame.
I already Googled it, but I haven't found anything for Pygame surfaces yet. I also tried making my own function but it looks ugly and much worse: the framerate drops from 50 (if I don't call the function) to 30 fps (if I do call the function). I tested it a little bit and I found out that smaller circles take longer to process than bigger circles. How can I do this, but faster. If you want I can show the function I made.
The surface object has a method called get_bounding_rect which is where we will start. The function returns the smallest rect possible which contains all of the non-transparent pixels on the surface.
pixel_rect = image.get_bounding_rect()
With the size of this rect, we can create a new surface:
trimmed_surface = pygame.Surface(pixel_rect.size)
Now blit the portion of image contained within pixel_rect onto trimmed_surface:
trimmed_surface.blit(image, (0,0), pixel_rect)
At this point, trimmed_surface should be a surface the same size as pixel_rect, with the unwanted transparent rows and columns "trimmed" off of the original surface.
Documentation for Surface.get_bounding_rect: http://www.pygame.org/docs/ref/surface.html#Surface.get_bounding_rect
I have a pygame surface (some text created by font.render) that is mostly transparent except some pixels are white. I'd like to change half of these white pixels black. I know I could iterate through each pixel, checking whether it is white by get_at() and changing its color using set_at(), but it strikes me that there must be a faster way of telling pygame to grab all the white pixels and change a random half of them to black. Any ideas?
I think you'll need to iterate through all the pixels to check if they're white. Once you have the list of whites, do something like:
for px in random.sample(whites,len(whites)/2):
Surface.set_at((px.x,px.y),'black')
Python Documentation - random