As I understood pygame drawing method, the 2nd argument of the blit function (screen.blit(surface, (0,0))) tells pygame where to draw the given surface (like an offset to start drawing from, or rather a placement of the surface on the screen). Although, from recent experimenting, it seems that pygame surfaces placements are fixed, and that (0,0) is used to crop the surface before pygame blit it to the screen, for efficiency purposes.
Are surfaces placement really fixed (is my latter observation correct)? and if so, is there another way to conveniently move an already drawn surface to another position on the screen? Or should i implement my own way of moving complex "drawable" objects?
Thanks!
A pygame.Surface object has no position, it has a size only. Note, the location of the Rect object which is returned by pygame.Surface.get_rect() is always (0, 0).
When you blit a Surface on another Surface, then each pixel is copied and placed at the corresponding position of the destination Surface. Thus always a position has to be specified, when a Surface is blit on a destination Surface.
See also Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
[...] if so, is there another way to conveniently move an already drawn surface to another position [...]
You have a basic misunderstanding. A Surface cannot be "moved". A Surface is copied on the Surface object which is associated to the game window.
A Surface appears to be moving, because the entire scene is drawn in every frame. First the background is drawn, then the objects (Sprites, Surfaces) are drawn on top of the background and finally the display is updated (in every frame). If an object is placed at a slightly different position in every frame, then the object appears to be moving smoothly.
Related
It appears that in Python graphics.py, new objects are drawn behind existing objects. So if I draw a blue circle and THEN place a rectangular box over half the circle, you find the circle in on top of the rectangular box. The box, even though it was written last, is appearing behind the circle. Is there a way to control this behavior so the rectangle would appear on top of the circle and not behind it? I want to avoid having to undraw the circle, draw the rectangle, then redraw the circle, so that the rectangle is on top of the circle instead of behind it.
Certainly, this becomes more cumbersome as you have more and more overlapped objects.
Can anyone tell me the use of Pygame.Rect. I am creating a simple program to draw and display rectangle in screen and check for collision with screen. I saw a video on youtube where the Youtuber uses the following code:
moving_rect=pygame.Rect(300,300,100,100)
Now I don't know what is Pygame.Rect is used for and what the above line of code actually does.
A pygame.Rec describes a rectangular area. It can be use to define the bounding box of an object. This can be useful for a collision test. See How do I detect collision in pygame?.
Actually it is used to define the location of a pygame.sprite.Sprite object.
Notice that a pygame.Surface object has no position. It only contains the pixel information. However, a Rect and a Surface together define the position of an image (Sprite) in the window.
Like for example my game screen is 600 by 600, and my image is 600 by 1500. How can I make it so that my background moves to another part of the image when my sprite goes off screen, so it seems like I'm moving through but I'm really not?
Sorry if I seem confusing.
Thanks.
From the pygame documentation on blit, you can pass in an area of your background image that you want to draw.
My pygame is a bit rusty, but you should be able to do the following:
blit(background_image, destination_surface, ((left_x_offset, 0), (right_x_offset, 0))
The first argument is your background image (the 600 x 1500 one), the second argument is the surface you're drawing everything to, and the third argument is the area of your background image that you want to draw to the destination surface.
Since you want to move the background in relation to the character, I would set left_x_offset to the position of the character minus half the width of your screen, and right_x_offset to the position of the character plus half the screen size.
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
Although I understand that the purpose of the draw function is to draw to a certain surface, I don't understand why it doesn't simply return a pygame.Surface object that you can later blit to a surface whenever needed. So far this has been very inconvenient when I just want to create a surface and draw it to something else later.
Is there any way that you can get similar functions to return a surface object, instead of going that extra step and drawing directly to another surface?
To make a surface with the shape you want, instead of drawing to the original surface, you draw to another surface and then later you can blit it to the original one.
As to why the draw functions return a rect, it serves to later optimise your code by only updating the parts of the screen that need to be updated. The way you do this is every time you want to draw something to the screen, you append the rect that it returns to a list and when you go to update the screen you do it like so:
pygame.display.update(rect_list)