Pygame need to build sprite from a rotating and non rotating image [duplicate] - pygame

This question already has answers here:
How to set the pivot point (center of rotation) for pygame.transform.rotate()?
(5 answers)
How can you rotate an image around an off center pivot in Pygame
(1 answer)
How do I rotate an image around its center using Pygame?
(6 answers)
Closed 22 days ago.
I have an interesting problem with sprits in pygame.
Essentially, I am trying to create an archer sprite which will follow a target.
To do so, I need it to rotate. Naturally, I don't want the whole archer to rotate - just his shoulders/head etc. To do so I have create two separate spritesheets (for the top and bottom)
I can then create the sprite image using:
class Archer(pygame.sprite.Sprite):
def __init__(self, group, pos, size):
super().__init__(group)
self.pos = pos
self.assets_legs = GetAssets('../graphics/archer_fixed.png', size)
self.frames_legs = self.assets_legs.sprite_images
self.assets_body = GetAssets('../graphics/archer_rotate.png', size)
self.frames_body = self.assets_body.sprite_images
self.frame_index = 0
self.angle = 0
self.archer = [self.frames_legs[round(self.frame_index)], self.frames_body[round(self.frame_index)]]
self.image = pygame.Surface((size), pygame.SRCALPHA)
for image in self.archer:
self.image.blit(image, (0,0))
This is fine and works well. However, when I want to rotate the top half and blit this to the self.image, as in:
def rotate(self):
self.rot_img = self.archer[1]
self.rot_img = pygame.transform.rotate(self.rot_img, 1)
self.image = pygame.Surface((75,75), pygame.SRCALPHA)
self.archer = [self.frames_legs[round(self.frame_index)], self.rot_img]
for image in self.archer:
self.image.blit(image, (0,0))
self.rect = self.image.get_rect(center = self.pos)
I get strange artifacts. I suspect because I am trying to blit a surface with a rotated dimension to a self.image. The only work around I can think of is to create two separate sprites and then have them track each other, but the must be a way to do this in one class.
Any ideas?
Cheers

Related

Draw detection radius around square sprite [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Pygame collision with masks
(1 answer)
Closed 6 months ago.
I would like to draw sprites with 2 features: a base image (let's say a square image that I pass as argument) and a togglable view of their circular detection radius, for debug purposes and checking that collisions with a circular mask actually work.
Note: the main question is not about to detect collisions as in How do I detect collision in pygame?, but rather can a sprite have several surfaces attached to it and why is my draw_mask_outline function returning croppped circles? (see attached screenshots)
Here's an example of my class:
class Robot(pygame.sprite.Sprite):
def __init__(self, x, y, image, detection_radius, mouse_group, *groups):
super().__init__(*groups)
# extra image added for changing color if mouse is detected within
# detection radius
# I have used the mouse as a debug tool but in the end the Robot
# should have no knowledge of the other groups positions (and should
# not be able to compute a euclidean distance from a sprite group) but
# simply detect if a sprite of a certain sprite group has entered its
# radius
other_img = pygame.Surface((30, 30))
other_img.fill('black')
self.img_idx = 0
self.images = [image, other_img]
self.image = self.images[self.img_idx]
self.pos = pygame.Vector2(x, y)
self.rect = image.get_rect(center=self.pos)
self.detection_radius = detection_radius
self.mask_surface = pygame.Surface((detection_radius * 2, detection_radius * 2), pygame.SRCALPHA)
self.detection_mask = self.make_circle(self.notice_radius)
self.mask = pygame.mask.from_surface(
self.make_circle_surface(detection_radius))
sekf.mouse_group = mouse_group
def draw_mask_outline(self):
# this function should draw the outline of the circular detection mask
display_surf = pygame.display.get_surface()
pts = self.mask.outline()
for pt in pts:
x = pt[0] + self.rect.centerx
y = pt[1] + self.rect.centery
pygame.draw.circle(display_surf, 'black', (x, y), 1)
def make_circle_surface(self, radius):
# I used this function to generate the circular surface
mask_surf = pygame.Surface((radius * 2, radius * 2), pygame.SRCALPHA)
pygame.draw.circle(mask_surf, (0, 0, 0), (self.rect.centerx, self.rect.centery), radius)
return mask_surf
def collision(self):
# collision detection function, if mouse inside detection radius do something
if pygame.sprite.spritecollide(self, self.mouse_group, False, pygame.sprite.collide_mask):
pygame.draw.circle(pygame.display.get_surface(), (0, 0, 0), (self.rect.centerx, self.rect.centery), self.notice_radius, 1)
self.img_idx = 1
self.image = self.images[self.img_idx]
else:
self.img_idx = 0
self.image = self.images[self.img_idx]
def update(self):
# the overall update function where all the robot logic will happen
self.draw_mask_outline()
As fas as I've understood how the lib works, I should create a surface around the original image, big enough to fit the circle but this does not seem compatible with already having a self.image. Then I should draw a circle on that new surface.
Will this new surface follow the sprite when it moves too?
I managed to draw the circle inside the original image but this is not what is expected since the starting is smaller than the circle. In some cases, I also managed to generate surfaces, transform them to mask, then using the mask to generate an outline (hence the self.mask) but these outlines are always drawn far away from the sprite positions, are incomplete or completely missing...
Here are some screenshots of the current version and what I could achieve.
When the mouse is outside the detection ring, outlines are drawn with a severe offset, are sometimes incomplete and some robots have no outline.
Displaced and incomplete outlines
When the mouse is inside, the collision function draws the correct circle (but this is not the mask).
Collisions debug ring
Here are links to some solutions that I have tested and that did not work (if I've understood them correctly that is...):
pygame: mask non-image type surfaces
Pygame: Why i can't draw a circle sprite
how to create a circular sprite in pygame
OOP Pygame Circle
Ultimately the goal is to have the robots roam around and detect sprites from another group of robots that enter their detection radius.
Any help would be very much appreciated!

I'm trying to make my bullet look at my cursor [duplicate]

This question already has answers here:
How do you point the barrel towards mouse in pygame?
(1 answer)
calculating direction of the player to shoot pygame
(1 answer)
How to move a sprite according to an angle in Pygame
(3 answers)
Closed 7 months ago.
I've got my player in the center of my screen and I want a bullet at a fixed distance from the player pointing at my cursor. I've got the fixed distance down and the angle in degrees, but the bullet spins around violently when I move my cursor. What am I doing wrong?
radius = 100
mouse = pg.mouse.get_pos()
delta_x = mouse[0] - (Width/2)
delta_y = -(mouse[1] - (Height/2))
Rotation = math.degrees(math.atan2(delta_y, delta_x))
if Rotation > 0:
angle = (360 - Rotation)
elif Rotation < 0:
angle = -(Rotation)
x, y = (radius*(math.sin(angle))), (radius*(math.cos(angle)))
Bullet_x = (Width/2 + x)
Bullet_y = (Height/2 + y)
screen.blit(Bullet, (Bullet_x, Bullet_y))

How to attribute rect to sprite

When I run this code it does not display the sprite on the screen . just a blank screen I have tried everything I can think of to get this to work .Some help would be much appreciated.
I have tried everything I can think of to get this to work. what I'm trying to do is create my sprites with a rect attribute.
import pygame
pygame.display.init()
pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
x = 300
y = 500
x1 = 100
y1 = 200
image1 = pygame.sprite.Sprite()
image1.image = pygame.image.load("picy.png").convert_alpha()
image2 = pygame.sprite.Sprite()
image2.image = pygame.image.load("picy1.png").convert_alpha()
image1_rect = image1.image.get_rect(topleft=(x,y))
image2_rect = image2.image.get_rect(topleft=(x1,y1))
screen.blit(image2_rect,(x1,y1))
screen.blit(image1_rect,(x,y))
pygame.display.update()
I expect it to put my two sprites on the screen and when they touch for them to register a hit.
From the docs:
blit()
draw one image onto another
blit(source, dest, area=None, special_flags = 0) -> Rect
Draws a source Surface onto this Surface. The draw can be positioned with the dest argument. Dest can either be pair of coordinates representing the upper left corner of the source. A Rect can also be passed as the destination and the topleft corner of the rectangle will be used as the position for the blit. The size of the destination rectangle does not effect the blit.
The blit method takes as first argument a Surface, not a Rect. The Surface is your image.
Try with:
screen.blit(image2.image, dest=image2_rect)
screen.blit(image1.image, dest=image1_rect)
By the way, you may also wish to make the rectangles attributes of the Sprite instances, instead of separate instances:
image1.rect = image1.image.get_rect(topleft=(x,y))
image2.rect = image2.image.get_rect(topleft=(x1,y1))

Image rotation in pygame [duplicate]

This question already has answers here:
How do I rotate an image around its center using Pygame?
(6 answers)
How can you rotate an image around an off center pivot in Pygame
(1 answer)
Closed 2 years ago.
I've got a little problem that I can't seem to solve. I can't find it on stackoverflow yet.
It's about rotating an image. I've got two 'gamepieces' in the example here, where I can show the problem. If I click on one line, it rotates 90 degrees. But after it rotated 180 degrees (which is precise, because I made sure it ends on exactly 90, 180, 270 etc degrees) the images don't connect well anymore. if I rotate it another 180 degrees, then it's fine again..
Screen 1, nothing bad here:
Screen 2, here you see the two lines don't connect well.
I tried changing the resolution to different pixel sizes (64, 64) and (81, 81) for example. But this does not cure the problem.
And here is part of the code:
class Piece:
def __init__(self, piece, x, y):
self.image = pygame.image.load(piece)
self.rotated_image = self.image
self.rect = self.rotated_image.get_rect()
self.rect.center = x, y
self.current_degrees = 0
self.degrees = 0
self.values = [0, 1, 0, 1]
def rotate_piece(self):
self.rotated_image = pygame.transform.rotozoom(self.image, lerp(self.current_degrees, self.degrees, 0.3), 1)
self.rect = self.rotated_image.get_rect(center=self.rect.center)
self.current_degrees = lerp(self.current_degrees, self.degrees, 0.3)
def rotate_values(self):
temp = self.values[0]
for i in range(len(self.values) - 1):
self.values[i] = self.values[i+1]
self.values[3] = temp
print(self.values)
pieces = []
piece1 = Piece(images['line'], 32, 32)
piece2 = Piece(images['line'], 96, 32)
pieces.append(piece1)
pieces.append(piece2)

How can I make my sprite move accross the screen? [duplicate]

This question already has answers here:
How to make a circle move diagonally from corner to corner in pygame
(1 answer)
How to make smooth movement in pygame
(2 answers)
Closed 2 years ago.
When a certain value is met I want my enemy sprite to return to his intial position,but now hes just disappearing and reappearing in that position.
I'm only changing the Y position
def update(self):
self.count += 1
x_component = self.ship.rect.centerx-self.enemy2X
y_component = self.ship.rect.centery-self.enemy2Y
distance = math.hypot(x_component, y_component)
if distance < 200:
self.currentState = 1
print distance
elif distance > 200:
self.currentState = 0
self.enemy2Y=68
print self.enemy2Y