Pygame精灵表碰撞盒失效问题求助(已用Sprite Mask)
Hey there! The main issue here is that your player's collision mask is being created from the entire sprite sheet, not just the single frame you're drawing at any given time. That's why the collision box seems off—Pygame is using all 4 frames of your sprite sheet for collision detection, not just the visible one. Let's walk through the fixes step by step:
1. Correct Sprite Sheet Frame & Mask Setup
First, let's clean up your sprite sheet handling and precompute masks for each individual frame. This ensures collision detection uses only the visible frame:
class Player(pygame.sprite.Sprite): def __init__(self, x, y, py, player_img_path, veerg, rida): super(Player,self).__init__() '''Mangija huppamine''' self.x = x self.y = y self.jumping = False self.platform_y = py self.velocity_index = 0 # Jump velocity curve (moved from global to class attribute) self.velocity = [(i/1)-20 for i in range(0,60)] '''Sprite sheet''' self.player = pygame.image.load(os.path.join('Pildid', player_img_path)).convert_alpha() self.rect = self.player.get_rect() '''Sprite sheeti piltide jaotamine pikslite jargi''' self.veerg = veerg self.rida = rida self.kokku = veerg * rida # Calculate frame size correctly self.frame_width = self.rect.width // veerg self.frame_height = self.rect.height // rida # Create list of frame rects (x, y, width, height) on the sprite sheet self.frames = [ (index % veerg * self.frame_width, int(index / veerg) * self.frame_height, self.frame_width, self.frame_height) for index in range(self.kokku) ] # Precompute masks for each frame (for accurate collision detection) self.frame_masks = [] for frame_rect in self.frames: # Create a surface for the individual frame frame_surf = pygame.Surface((self.frame_width, self.frame_height), pygame.SRCALPHA) frame_surf.blit(self.player, (0, 0), frame_rect) # Generate mask for this frame self.frame_masks.append(pygame.mask.from_surface(frame_surf)) # Handle positions (unchanged, kept for drawing offsets) self.handle = [ (0, 0), (-self.frame_width//2, 0), (-self.frame_width, 0), (0, -self.frame_height//2), (-self.frame_width//2, -self.frame_height//2), (-self.frame_width, -self.frame_height//2), (0, -self.frame_height), (-self.frame_width//2, -self.frame_height), (-self.frame_width, -self.frame_height), ] # Initialize with the first frame's mask self.mask = self.frame_masks[0]
2. Update Draw Method to Sync Rect & Mask
Your draw method needs to update the player's rect to match the visible frame's position and size, and switch the mask to the current frame's mask:
def draw(self, DS, frame_index, handle=0): # Get the offset from the handle offset_x, offset_y = self.handle[handle] # Calculate where to draw the frame draw_pos = (self.x + offset_x, self.y + offset_y) # Draw the current frame DS.blit(self.player, draw_pos, self.frames[frame_index]) # Update the rect to match the drawn frame's position and size self.rect.topleft = draw_pos self.rect.width = self.frame_width self.rect.height = self.frame_height # Set the mask to the current frame's mask self.mask = self.frame_masks[frame_index]
3. Fix the do_jumpt Method (Remove Global Dependency)
Update the jump logic to use the class's velocity attribute instead of a global variable:
def do_jumpt(self): '''Huppamine: kiirus, korgus, platvorm''' if self.jumping: self.y += self.velocity[self.velocity_index] self.velocity_index += 1 if self.velocity_index >= len(self.velocity) - 1: self.velocity_index = len(self.velocity) - 1 if self.y > self.platform_y: self.y = self.platform_y self.jumping = False self.velocity_index = 0
4. Clean Up the do Method
Use the player's internal position variables instead of hardcoding values when drawing:
def do(self): '''Funktsioonide kokkupanek''' self.do_jumpt() current_frame = index % self.kokku self.draw(DS, current_frame, handle=4)
5. Minor Fixes to Initialize the Player Correctly
When creating your player instance, pass the image filename as a string (not the path fragment):
p = Player(190, 359, 359, 'karakter.png', 4, 1)
Why This Works
By precomputing masks for each frame and switching the player's mask to match the currently drawn frame, collision detection will only use the visible part of your sprite. Updating the rect to match the frame's position and size ensures the mask is perfectly aligned with what's on screen.
Testing these changes should resolve the abnormal collision box behavior you're seeing!
内容的提问来源于stack exchange,提问作者Taavi Raudkivi

