Is there any way to "clear" a surface? - python

Is there any way to clear a surface from anything that has been blitted to it?

If what you want is to make a pygame Surface object "clean", that is erase all images blited to it, to blit new images to it every game loop and keep the peer pixel alpha without creating a new surface, you can fill it, but instead of a solid color, use a transparent color
from pygame import Color, Surface
empty = Color(0,0,0,0) #The last 0 indicates 0 alpha, a transparent color
field = Surface((width, height), flags=SRCALPHA)
#Inside the game loop
field.fill(empty)
*Sorry is my english is bad, still learning

When I dont care about performance, I use:
mysurface.fill((0,0,0))
Which will draw the specified color (black in this case) across the entire surface. Is that what you meant by "clear"?
Oh, and you need, of course, to "flip" the surface after doing this for it to be visible on the screen.

I don't know what API you're using, so here's a vague answer:
In virtually all cases "clearing" a surface simply blits a coloured quad of the same size as the surface onto it. The colour used is whatever you want your clear colour to be.
If you know how do blit, just blit a white quad of the same size onto the surface.

You can't undo one graphic written over the top of another graphic any more than you can undo one chalk illustration drawn over the top of another chalk illustration on the same board.
What is typically done in graphics is what you'd do with the chalkboard - clear the whole lot, and next time only redraw what you want to keep.

I had this problem too
To create the surface:
mask=pygame.Surface((180,100),pygame.SRCALPHA)
To clear the surface:
mask.fill
mask.set_alpha(255)
Draw your lines/images etc
Then blit this surface onto your main surface using the Alpha Blend flag
screen.blit(mask,(0,0),special_flags=(pygame.BLEND_RGBA_ADD))

.fill((255,255,255,0)) appears to work for me anyway.

I used the following in a game I made:
self.image = 0 #to empty it
self.image = pygame.image.load("image")

For pygame you can use Surface.fill

If you want to clear a surface before blitting, you can first fill the surface with a unlikely random color, set the alpha (colorkey) with that color, and then blit the original sprite with the transparent background back onto the surface.
idle_image = pg.image.load("sprite.png") #sprite with transparent background
temp_color = pg.Color(132, 23, 213, 255) #random unlikely replacement color
def clear_surface(surface):
surface.fill(st.temp_color)
surface.set_colorkey(st.temp_color)
surface.blit(idle_image, (0,0))

You can clear a surface by making it transparent.
Below is how I used the empty color RGB to make text blink by setting the surface to switch to a transparent version.
from __future__ import absolute_import, division, print_function
from itertools import cycle
import pygame
VISITOR_TTF_FILENAME = 'pixelFont.ttf'
BLINK_EVENT = pygame.USEREVENT + 0
empty = (255,255,255,0)
def main():
pygame.init()
try:
screen = pygame.display.set_mode((800, 600))
screen.fill((255,255,255))
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
font = pygame.font.Font(VISITOR_TTF_FILENAME, 50)
on_text_surface = font.render(
'Press Any Key To Start', True, pygame.Color('green3')
)
blink_rect = on_text_surface.get_rect()
blink_rect.center = screen_rect.center
off_text_surface = pygame.Surface(blink_rect.size)
off_text_surface.fill(empty)
blink_surfaces = cycle([on_text_surface, off_text_surface])
blink_surface = next(blink_surfaces)
pygame.time.set_timer(BLINK_EVENT, 1000)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == BLINK_EVENT:
blink_surface = next(blink_surfaces)
screen.blit(blink_surface, blink_rect)
pygame.display.update()
clock.tick(60)
finally:
pygame.quit()
if __name__ == '__main__':
main()

When I want to get rid of something I use
screen.fill("Gray")
every time I update! So it hides it behind the gray screen.
Gray is not the only color available, so here is a list of all of the available colors you can use for pygame
Hope it helped!

Fill the surface with fill, then make it transparent with set_alpha
surface.fill
surface.set_alpha(255)

Related

How to rotate a surface in pygame, without changing its shape

I'm writing a class in pygame to create a sprite object, and I'd like to be able to rotate it. It works fine with an image, and rotates without issue. But when rotating a surface with a plain colour, the box appears to grow and shrink. I know that this is a result of the surface changing size to fit the vertices of the rectangle inside, but how do I stop it? I'd like to see a visual rotation.
I've created some sample code to show the problem that I'm facing, running it causes the box to simply change in size.
import sys, pygame
from pygame.locals import *
pygame.init()
SCREEN = pygame.display.set_mode((200, 200))
CLOCK = pygame.time.Clock()
surface = pygame.Surface((50 , 50))
surface.fill((0, 0, 0))
rotated_surface = surface
rect = surface.get_rect()
angle = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
SCREEN.fill((255, 255, 255))
angle += 5
rotated_surface = pygame.transform.rotate(surface, angle)
rect = rotated_surface.get_rect(center = (100, 100))
SCREEN.blit(rotated_surface, (rect.x, rect.y))
pygame.display.update()
CLOCK.tick(30)
How do I fix this issue, to make the surface rotate how I want?
Any help would be appreciated!
You have to create the Surface objects you create to stamp on the display surface in a way they use transparency information (That is - they have to have an alpha channel).
To do that, is just a question of passing the appropriate flag when creating your surface objects - simply replace this:
surface = pygame.Surface((50 , 50))
with:
surface = pygame.Surface((50 , 50), pygame.SRCALPHA)
and it should work.

Pygame image used as screen then final transformed to screen

I want to be able to stretch a screen without needing to stretch each image individually.
I have a image I use as the screen, then when I have the final product I transform the image to the size of the screen and blit it to the screen.
But the images blit onto the main image do not transform with the main image, and comes out as its first size.
You can find the current version here:
https://gist.github.com/gideonjvisser/eca7506f483c51edf93c/
Here's the script:
import pygame
from pygame.locals import Color
chosen_resolution = (400,200)
screen = pygame.display.set_mode(chosen_resolution)
screen_rect = screen.get_rect()
in_game_resolution = (800,600)
screen_image = pygame.Surface(in_game_resolution)
screen_image_rect = screen_image.get_rect()
image_on_in_game = pygame.image.load("image.png").convert_alpha()
image_on_in_game = pygame.transform.scale(image_on_in_game, (469,669)) #to fit on in_game_resolution
print screen_rect
print screen_image_rect
while(True):
screen_image.fill(Color('white'))
screen_image.blit(image_on_in_game, (0,0))
screen_image = pygame.transform.scale(screen_image, chosen_resolution)
screen.blit(screen_image, (0,0))
pygame.display.flip()
This code almost works. The issue is that, in your while loop, you overwrite your static resolution intermediate surface with the scaled version. Try replacing the while loop with this:
while True:
screen_image.fill(Color('white'))
screen_image.blit(image_on_in_game, (0,0))
screen.blit(pygame.transform.scale(screen_image, chosen_resolution), (0,0))
pygame.display.flip()
Now the pre-scaled buffer should remain the right size and actually be scaled to fit the real screen's size.

Set constant translucency for background

I am trying to put in a background image for my game and I need that at certain opacity. I have used the method set_alpha() of surface to control its translucency. However, this is creating a fade-in effect with the initial background at the set opacity turning to its full brightness eventually. Is there any way I can set the translucency of the background to a constant value?
My code is
self.bg = pygame.image.load("../game_images/background.png")
self.bg_size = self.bg.get_size()
self.bg_rect = self.bg.get_rect()
self.bg.set_alpha(5)
self.screen = pygame.display.set_mode(self.bg_size,pygame.FULLSCREEN)
self.screen.blit(self.bg, self.bg_rect)
pygame.display.update()
Any hints on how to do this?
It would help to see game loop.
Your image probably is getting bright because you not clearing the screen before it redrawn.
screen.fill((0,0,0))
screen.blit(self.bg, self.bg_rect)
pygame.display.update()
if you decide to do a self.bg.convert_alpha(). Then you need to use pygame.surfarray.pixels_alpha() and this require numpy to be install.
# value is a float .01 to .99
def set_alpha(image, value):
array = pygame.surfarray.pixels_alpha(image)
for x in xrange(array.shape[0]):
for y in xrange(array.shape[1]):
array[x][y] = int(array[x][y] * value)

Creating a permanent background in pygame

I have a program where I am using mouse controls to move objects. When the objects move, the program resets the screen to solid white so that there are no trails of the object using:
screen.fill(255,255,255)
What I am trying to do now is have the background a created background I made in a method.
black = (0,0,0)
brown = (218,134,10)
white = (255,255,255)
pygame.draw.rect(screen,white,(0,0,1000,600))
first =pygame.draw.rect(screen,brown,(150,150,50,400),0)
second = pygame.draw.rect(screen,brown,(450,150,50,400),0)
third = pygame.draw.rect(screen,brown,(750,150,50,400),0)
first_out = pygame.draw.rect(screen,black,(150,150,50,400),2)
second_out = pygame.draw.rect(screen,black,(450,150,50,400),2)
third_out= pygame.draw.rect(screen,black,(750,150,50,400),2)
How can I make my background the background that refreshes every time an object is moved?
Rather than drawing directly on the screen surface, you should create a new surface, let's call it background_surface.
By doing so, you will only have to draw the background once (at the very beginning of your application) and any blitting afterwards will be done a lot quicker, since no pygame.draw.xxx is being done.
To fill the screen surface with background_surface, you'll just use screen.blit().
A quick snippet:
WIDTH, HEIGHT = 800, 600
background_surface = pygame.Surface((WIDTH, HEIGHT))
# do all the drawings on the background surface
background_surface.fill((255, 255, 255))
while application_running:
# processinput
# update objects
# draw everything
screen.blit(background_surface, (0, 0))
pygame.display.update()

Drawn surface transparency in pygame?

I'm writing a predator-prey simulation using python and pygame for the graphical representation. I'm making it so you can actually "interact" with a creature (kill it, select it and follow it arround the world, etc). Right now, when you click a creature, a thick circle(made of various anti-aliased circles from the gfxdraw class) sorrounds it, meaning that you have succesfully selected it.
My goal is to make that circle transparent, but according to the documentation you can't set an alpha value for drawn surface. I have seen solutions for rectangles (by creating a separate semitransparent surface, blitting it, and then drawing the rectangle on it), but not for a semi-filled circle.
What do you suggest? Thank's :)
Have a look at the following example code:
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 300))
ck = (127, 33, 33)
size = 25
while True:
if pygame.event.get(pygame.MOUSEBUTTONDOWN):
s = pygame.Surface((50, 50))
# first, "erase" the surface by filling it with a color and
# setting this color as colorkey, so the surface is empty
s.fill(ck)
s.set_colorkey(ck)
pygame.draw.circle(s, (255, 0, 0), (size, size), size, 2)
# after drawing the circle, we can set the
# alpha value (transparency) of the surface
s.set_alpha(75)
x, y = pygame.mouse.get_pos()
screen.blit(s, (x-size, y-size))
pygame.event.poll()
pygame.display.flip()

Categories