I'm making my own game on Pygame, and I want to add images to rects instead of having a coloured rectangle.
I know how to add an image to pygame, but I want to know if there's some way to add the image and use the Pygame.rect properties such us rect.centerY and rect.centerX.
Does anyone know how?
Load your image, call its get_rect method to get a rect with the size of the image, then set the coordinates of the rect (there are several attributes like x, y, topleft, center, etc.) ...
IMAGE = pg.image.load('an_image.png').convert() # or .convert_alpha()
# Create a rect with the size of the image.
rect = IMAGE.get_rect()
rect.center = (200, 300)
... and pass the rect as the dest argument to pygame.Surface.blit to blit the image at the rect.topleft coordinates.
screen.blit(IMAGE, rect)
Related
I am trying to calculate the middle of the screen for image pygame.Surface object. I've tried to do the simple screen.blit(my_image, (0, 0))
but that won't do it. Is there a way I can calculate where to blit an image, so it's in the middle? Each of my images have different sizes etc.
Edit:
I've figured it out! I've made a function:
screenw = 500
screenh = 500
# true_coords(pygame.Surface(...), (250, 250))
def true_coords(obj, coords):
objw = obj.get_width()
objh = obj.get_height()
true_coords = coords[0] - (objw / 2), coords[1] - (objh /2)
return(true_coords)
Use the Rect class to do all the calculation for you.
Given a Surface called surf and the display Surface called screen, you could do something like this:
screen = pygame.display.set_mode(...)
screen_rect = screen.get_rect()
surf = pygame.Surface(...)
# set the center of the new Rect to the center of the screen
surf_rect = surf.get_rect(center=screen_rect.center)
screen.blit(surf, surf_rect)
The Rect class has a number of useful virtual attributes, like center, topleft, bottomright etc which you can use to easily position a Surface. Usually you use a Surface and a Rect together wrapped in a Sprite.
I have a sprite in Pygame that is a blue circle. I want this image to be drawn to the screen "faded", e.g. translucent. However, I don't want a translucent rectangle to be drawn over it; instead, I want the actual image to be modified and made translucent. Any help is greatly appreciated!
Right now I have:
Class Circle(pygame.sprite.Sprite):
self.image = self.image = pygame.image.load("circle.png")
circle = Circle()
and eventually...
window.blit(pygame.transform.scale(circle.image, (zoom, zoom)), (100, 100))
How the circle.png looks:
How I want the image to look after making it transparent:
I am blitting the image onto the window, which is a white background.
First, your image/surface needs to use per-pixel alpha, therefore call the convert_alpha() method when you load it. If you want to create a new surface (as in the example), you can also pass pygame.SRCALPHA to pygame.Surface.
The second step is to create another surface (called alpha_surface here) which you fill with white and the desired alpha value (the fourth element of the color tuple).
Finally, you have to blit the alpha_surface onto your image and pass pygame.BLEND_RGBA_MULT as the special_flags argument. That will make
the opaque parts of the image translucent.
import pygame as pg
pg.init()
screen = pg.display.set_mode((800, 600))
clock = pg.time.Clock()
BLUE = pg.Color('dodgerblue2')
BLACK = pg.Color('black')
# Load your image and use the convert_alpha method to use
# per-pixel alpha.
# IMAGE = pygame.image.load('circle.png').convert_alpha()
# A surface with per-pixel alpha for demonstration purposes.
IMAGE = pg.Surface((300, 300), pg.SRCALPHA)
pg.draw.circle(IMAGE, BLACK, (150, 150), 150)
pg.draw.circle(IMAGE, BLUE, (150, 150), 130)
alpha_surface = pg.Surface(IMAGE.get_size(), pg.SRCALPHA)
# Fill the surface with white and use the desired alpha value
# here (the fourth element).
alpha_surface.fill((255, 255, 255, 90))
# Now blit the transparent surface onto your image and pass
# BLEND_RGBA_MULT as the special_flags argument.
IMAGE.blit(alpha_surface, (0, 0), special_flags=pg.BLEND_RGBA_MULT)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
screen.fill((50, 50, 50))
pg.draw.rect(screen, (250, 120, 0), (100, 300, 200, 100))
screen.blit(IMAGE, (150, 150))
pg.display.flip()
clock.tick(60)
pg.quit()
Create a new Surface with per-pixel alpha.
surf = pygame.Surface((circle_width, circle_height), pygame.SRCALPHA)
Make the surface transparent
surf.set_alpha(128) # alpha value
Draw the circle to that surface at (x=0, y=0)
surf.blit(pygame.transform.scale(circle.image, (zoom, zoom)), (0, 0))
Draw the surface to the window
window.blit(surf, (circle_x, circle_y))
As the Surface.set_alpha() documentation says, you can have surfaces with "homogeneous alpha" or per pixel alpha, but not both, wich I believe is what you want. It might work with colorkey transparency, but I'm not sure (I didn't tested that yet). Any non RGBA (without active alpha channel) pixel format might work if you use set_colorkey() and set_alpha() before blitting.
So, the code might look like:
class Circle(pygame.sprite.Sprite):
def __init__(self)
self.image = pygame.image.load("circle.png")
# get the surface's top-left pixel color and use it as colorkey
colorkey = self.image.get_at((0, 0))
self.image.set_colorkey(colorkey)
At some point in your code (immediately before rendering) you might want to set the transparency by calling:
circle.image.set_alpha(some_int_val)
And then you can scale and blit it as intended.
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode((width_display,height_display))
pygame.display.set_caption("Ballzy")
ballImg = pygame.draw.circle(screen,(255,0,0),(250,250),36)
def ball(x,y):
screen.blit(ballImg,(x,y))
I got an error which said
TypeError: argument 1 must be pygame.Surface, not pygame.Rect
inside the ball function. This would work if the ball was an actual image but I need it to be a shape drawn in pygame.
The Pygame documentation says this about pygame.draw.circle:
pygame.draw.circle()
draw a circle around a point
circle(Surface, color, pos, radius, width=0) -> Rect
This means that this function returns a pygame rectangle. Pygame rectangles simply store a x and y coordinate and a width and height. This means that ballImg is a rectangle, not an image. It does not store any image data but rather just an area.
Your function ball blits ballImg to the screen.
def ball(x,y):
screen.blit(ballImg,(x,y))
The pygame documentation says this about blit:
blit()
draw one image onto another
blit(source, dest, area=None, special_flags = 0) -> Rect
Source should be a surface and dest should be a position where the image is blit on to.
In your code, however, you try and blit a rectangle to the screen, which does not work. In fact, when you call pygame.draw.circle(), you have already drawn the circle to the screen. You do not need to blit any images to the screen at all.
If instead of blitting ballImg to the screen in ball(), you simply draw a circle at the x and y coordinates as so, your problem should be fixed:
def ball(x,y):
pygame.draw.circle(screen, (255,0,0), (x, y), 36)
I have a class in my pygame program that extends sprite, and effectively gives collision and whatnot to a rectangle. The __init__ of the class is as follows:
def __init__(self,topleft,size,label):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface(size)
self.rect = self.image.get_rect()
self.rect.topleft = topleft
self.image.fill([128,128,128])
pygame.draw.rect(self.image, [200,200,200], self.rect, 5)
And this works great... for one rectangle. Problem is, after that rectangle, any others are solidly colored rectangles set to the fill color (128,128,128) instead of being a filled rectangle with a differently colored (200,200,200) border. I'm expecting this is some sort of issue with class variables as opposed to instance variables, but I'm unsure where the problem lies.
Okay, I figured it out. The Rect argument in the draw function is relative to the position of the image. Since I had set its rect to its location on the screen, it was drawing the rectangle way offset from the corner. It worked on my first one only because it happened to start at [0,0]. Here is the fixed draw code:
pygame.draw.rect(self.image, [200,200,200],pygame.Rect([0,0],size), 5)
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()