Pygame pygame.Rect.clamp - pygame

I can't get clamp to work. I thought clamp is to keep a rect inside of another, however the following try doesn't put the blue ball inside the red rect. Where is the problem?
import pygame
from pygame.locals import *
pygame.init()
TV=pygame.display.set_mode((400,400))
pygame.display.set_caption("Rect")
c=pygame.draw.circle(TV,(0,100,0),(150,100),100,1)
c1=pygame.draw.circle(TV,(0,0,200),(250,250),20,1)
r=pygame.draw.rect(TV,(100,0,0),c,1)
c1.clamp(r)
pygame.display.flip()
while True:
for e in pygame.event.get():
if e.type==QUIT:
pygame.quit()

clamp returns a new Rect without changing the source Rect itself.
If you want to change the source Rect, you'll have to use clamp_ip.
But this is not enough for you, because you draw the circle directly on the screen surface, and changing the resultung Rect does nothing:
You have to create a new Surface, draw your circle onto it and get a Rect from that Surface (or any other Rect you're going to use for drawing, but it's easiest to just use the get_rect() function).
Then do whatever you want with that Rect, e.g. use clamp_ip or get a new one with clamp, then use that Rect (or the new one) together with the blit function, e.g. TV.blit(the_new_surface, the_rect).

Related

Can't draw RECT on pygame ffs

this is the code:
this is the pygame output
I have not been able to create a very simple shape/sprite.
The problem is that the code you are using to draw the red rectangle is after the while loop. Your program is stalling in the while loop and never reaches the drawing line.
Try moving:
pygame.draw.rect(stage, red, (x,y,width,height))
pygame.display.update()
to before the while running: statement
or if you want it to draw the rectangle every tick include that statement directly under the while running: statement
Indent the lines:
pygame.draw.rect(stage, red, (x,y,width,height))
pygame.display.update()
four spaces to the right. This will put them inside the for loop, and so will redraw the rectangle on every iteration of the loop.

PyGame Moving Animation and issue with background

here is my code:
import pygame
import sys
pygame.init()
FPS=30
clock=pygame.time.Clock()
white=(255,255,255) #background
screen=pygame.display.set_mode((480,320)) #screen size
pygame.display.set_caption("Zombie Game!")
mainsheet=pygame.image.load("C:\Python34\MyMan.png") #load image
sheet_size=mainsheet.get_size() #get size of img
steps_right=8 #first 8 pictures is moving to the right
jump=16 #next 8 (actually 5) is jumping
steps_left=24 #next 8 is moving to the left
cell_width=int(sheet_size[0]/8) #width of the one animation
cell_height=int(sheet_size[1]/4) #height of the one animation
cell_list=[]
for y in range(0,sheet_size[1],int(cell_height)): #looping through image
for x in range(0,sheet_size[0],int(cell_width)):
surface=pygame.Surface((cell_width,cell_height))
surface.blit(mainsheet,(0,0),(x,y,cell_width,cell_height))
cell_list.append(surface) #adding images to list
cell_position=0
running=True
pygame.key.set_repeat(50, 50) #if they hold the key
while running:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_RIGHT: #if to the right..
if cell_position <steps_right-1:
cell_position+=1
else:
cell_position=0
if event.key==pygame.K_LEFT:
if cell_position<steps_left-1 and cell_position>jump:
cell_position+=1
else:
cell_position=jump+1
if event.key==pygame.K_UP:
if cell_position<12 and cell_position>7:
cell_position+=1
else:
cell_position=8
screen.fill(white)
screen.blit(cell_list[cell_position],(100,10))
clock.tick(FPS)
pygame.display.update()
I know that maybe it isn't the best way to do it but it's my first try. But there are 2 problems(at least): 1)"Character" is moving(animated) but of course he doesn't move and I dont have any idea how to do that ,if it was only simple rectangle then I would,but this is a little bit complicated ..and 2) when I try to change the background to white instead of black,my character is in the small black square but background is white..thanks for help!!!! :-))
Notes:
"C:\Python34\MyMan.png": please start this with r"" or use double slashes. Otherwise, if you put this in a directory starting with n or something, things will break.
Background color is caused (presumably) by using a non-transparent image. png supports transparency. I think there might be a flag to send to Pygame to mark it as transparent, but I don't remember what it is.
For movement, look at the line screen.blit(cell_list[cell_position],(100,10)). That's an xy coordinate pair; change those from constants to variables, and change them in the event loop.

Pygame: Sprite placement and black rectangle border

Before I start, let me say that I'm a complete beginner at Pygame.
Here's my current program:
import pygame, sys, random
pygame.init()
white = ((255,255,255))
display_width = 800
display_height = 600
FPS = 15
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Francis')
gameExit = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
clock = pygame.time.Clock()
while not gameExit:
for event in pygame.event.get():
if event.type== pygame.QUIT:
gameExit = True
francis = pygame.sprite.Sprite() #create sprite
francis.image = pygame.image.load("francis.png").convert() #load francis image
francis.rect = francis.image.get_rect() # use image extent values
francis.rect.center = [lead_x,lead_y]
gameDisplay.fill(white)
gameDisplay.blit(francis.image, francis.rect)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
What I plan to do with this program is load in my sprite (francis) and use the arrow keys to move him across the screen. I plan to create that motion by having each arrow key pressed add or subtract 10 pixels from lead_x, which should be the sprite's x location. I'm not sure whether the code I used to load in the sprite is correct. I used "francis.rect.center" then gave the coordinates to that. Is there a better way to load and position a sprite?
Also, my sprite has a black rectangle around it whenever I load it. The sprite itself is a 30x70 picture. Where there is not a pixel of the actual person, I just have transparency. The transparency works fine, but whenever I load in the image, there's a black rectangle around the border of the sprite. I have a feeling this has to do with the way I loaded in the sprite, but I'd appreciate if you'd let me know. (I've tried converting it to png, bmp, and jpg. png and bmp both have black borders, and jpg has black background instead of transparency)
Any and all help is appreciated!
When you do your image load with
francis.image = pygame.image.load("francis.png").convert() #load francis image
you should do
francis.image = pygame.image.load("francis.png").convert_alpha() #load francis image
as png images have an alpha channel which is the transparent part of the image. If you don't know what this means load your image into an image editor and remove the part you do not need by selecting the and deleting them. Now these parts will contain no colour information and therefor will be the alpha channel for the image.
You can also set the colour key of the image by
francis.image.set_colorkey(0, RLEACCEL) # the colour key is set to 0
A key colour is also transparent. (That's how they shoot movies like spiderman, fantastic four etc. :-))
read this too
https://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha.
hope this helps.
Regarding how you position sprites, I believe the norm is to go by the top-left, but I don't think it matters much.
Try opening the picture in paint and saving it as a gif. Note of course that changing the file extension doesn't make a difference by renaming it, it is actually still the same file type. So to change a file type, you have to use the "save as" option and select a file type. Try using a gif or a png using this method assuming you haven't so far.
francis.rect.center = [lead_x,lead_y]
You set it as a list. I'm pretty sure it's meant to be a tuple i.e.
francis.rect.center = (lead_x,lead_y)
What does the ".convert" part do in "francis.image = pygame.image.load("francis.png").convert()"
I'm pretty sure it's not meant to be there, try removing it unless you specifically know you need it.
You forgot a crucial line in your code. On the end of the mainloop you should be saying the following line;
pygame.display.flip()
This has something to do with how it loads the pixels from top to bottom or something, I honestly don't know, but I'm pretty sure you need it otherwise the program wont work. I think it replaces pygame.display.update()

Is there a way in pygame to detect if a rect is fully inside a mask?

Is there a way in pygame to detect if a rect is fully inside a mask?
I know that there is rect in rect collision and collidepoint (point in rect collision) but is there any way to detect if a rect is inside a mask?
Thanks
I don't believe there is any function supplied by pygame to do that. It would definitely be somewhat challenging, because of the "shapeless" possibilities of a mask. One possibility which might work for you would be to first get a list of the bounding rects of the mask (a list of rects which together "contain" all of the points of the mask) and check if your rect is inside any of these rects:
bounding_rects = mask.get_bounding_rects()
for b_rect in bounding_rects:
if b_rect.contains(test_rect):
print "Rect is inside mask"
Of course with this solution, if the rect is inside the mask, but not inside any one particular bounding rect, the test will fail. Here's an idea of how you might handle that, with the tradeoff of a little bit of lost precision:
bounding_rects = mask.get_bounding_rects()
mask_rect = bounding_rects[0].unionall(bounding_rects)
if mask_rect.contains(test_rect):
print "Rect is inside mask"
This solution unions all of the bounding rects of the mask into one rect, which has the possibility of covering area that none of the bounding rects covered (if two rects have a gap of 10 pixels between each other and are unioned together, the new rect will contain that gap)

Pygame how to change size of a surface?

How do you change the size of a surface in pygame that has an image (not scaling). When I load an image in pygame the surface becomes the size of the image. I need to change the size of the surface to be the size of a frame (sprite sheet).
Here is code I used to solve issue (thanks to Chris Dennett):
self.surface = pygame.Surface((20, 20))
self.surface.blit(pygame.image.load(imageName).convert_alpha(), (0,0), (0, 0, frameWidth, frameHeight))
For sprite sheets, you have 2 good options.
1) Load spritesheet as one Surface.
When blitting, use the source rect argument. This will blit just one frame, from the sheet.
2) Use subsurfaces.
Load spritesheet as one Surface.
Load a subsurface, of each frame you want : http://www.pygame.org/docs/ref/surface.html#Surface.subsurface
As far as you are concerned, the subsurface is a 'new' surface, with the width and height of the cell. But, it's not duplicate memory. It's linked.
From the docs:
Returns a new Surface that shares its pixels with its new parent. The
new Surface is considered a child of the original. Modifications to
either Surface pixels will effect each other. Surface information like
clipping area and color keys are unique to each Surface.
Create a new surface, passing in the desired width and height as arguments (i.e., how big the sprite is). Then use newsurf.blit(spritesheet, (0, 0), (posX, posY, newsurf.getWidth(), newsurf.getHeight())). Should work. Then you can use newsurf as your sprite. posX and posY should be the x and y you want to blit from in your sprite sheet respectively.