i’m tring to get a rect from a mask in pygame. It works but the rect has the width of the entire png image. But I want a rect based on the mask.
enter image description here
I can draw the mask perfectly as a blue surface, check the image:
enter image description here
As you can see the mask is correct but i can’t get a rect based on this mask, only on the png image that is bigger than the sprite as you can see in gray.
Please check the def update(self) function
import pygame as pg
import pytmx
from Entities.Frame import Frame
from math import fabs
Vector2D = pg.math.Vector2
class Player(pg.sprite.Sprite):
IDLE = (0,5)
RUNNING = (6,11)
STOPPING = (12,17)
HORIZONTAL_ACCELERATION = 1
HORIZONTAL_FRICTION = .1
def __init__(self, position,spritesheet_name, size, context) -> None:
super().__init__()
self.position = position
self.spritesheet_name = spritesheet_name
self.size = size
self.context = context
self.GRAVITY = .1
self.velocity = Vector2D(0,0)
self.acceleration = Vector2D(0,self.GRAVITY)
self.animation_state = self.IDLE
self.frames = []
self.add_frames()
self.animation_velocity=.2
self.current_frame = 0
self.image = self.frames[self.animation_state[0]].convert_alpha()
self.mask = pg.mask.from_surface(self.image)
self.rect = self.mask.get_rect()
self.rect.topleft = position
def change_animation_state(self):
if self.velocity.x <self.HORIZONTAL_FRICTION and self.velocity.x > -self.HORIZONTAL_FRICTION :
self.animation_state = self.IDLE
else:
if self.velocity.x <0:
self.image = pg.transform.flip(self.image,True, False)
self.animation_state = self.RUNNING
def manage_inputs(self,keys):
self.keys = keys
if keys[pg.K_d]:
self.move_right()
elif keys[pg.K_a]:
self.move_left()
def move_right(self):
self.acceleration.x = self.HORIZONTAL_ACCELERATION
def move_left(self):
self.acceleration.x = -self.HORIZONTAL_ACCELERATION
def apply_friction(self):
self.acceleration.x -= self.velocity.x * self.HORIZONTAL_FRICTION
def get_vertical_type_collison(self):
tiles = []
for tile in self.context.tilemap.sprites():
if tile.rect.colliderect(self.top_collider):
return {'type':'Top','tile':tile}
elif tile.rect.colliderect(self.bottom_collider):
return {'type':'Bottom','tile':tile}
def get_horizontal_type_collision(self):
tiles = []
for tile in self.context.tilemap.sprites():
if tile.rect.colliderect(self.left_collider):
return {'type':'Left','tile':tile}
elif tile.rect.colliderect(self.right_collider):
return {'type':'Right','tile':tile}
def attach_colliders(self,screen):
self.left_collider = pg.Rect(self.rect.left-1, self.rect.top+ self.size[0]/5, 2, 20)
self.right_collider = pg.Rect(self.rect.right-2, self.rect.top+self.size[0]/5,2,20)
self.top_collider = pg.Rect(self.rect.right-self.size[0]/2, self.rect.top+5, 10,2)
self.bottom_collider = pg.Rect(self.rect.left + self.size[0]/3,self.rect.bottom, 10,2)
#pg.draw.rect(screen,'red', self.left_collider)
#pg.draw.rect(screen, 'red', self.right_collider)
pg.draw.rect(screen, 'red', self.top_collider)
#pg.draw.rect(screen, 'red', self.bottom_collider)
def add_frames(self):
for frame_layer in self.get_frame_layer():
for x,y,gid in frame_layer:
image = self.tmx_data.get_tile_image_by_gid(gid)
image = image.convert_alpha()
self.frames.append(image)
def get_frame_layer(self):
self.tmx_data = pytmx.load_pygame(self.spritesheet_name, pixelalpha=True)
layers = []
for layer in self.tmx_data.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
layers.append(layer)
return layers
def manage_vertical_collision(self):
collision = self.get_vertical_type_collison()
if collision:
if collision['type'] == 'Bottom':
self.velocity.y=0
self.position.y = collision['tile'].rect.top - self.rect.h
self.rect.top = self.position.y
def manage_horizontal_collision(self):
collision = self.get_horizontal_type_collision()
if collision:
if collision['type'] == 'Right':
self.velocity.x = 0
self.position.x = collision['tile'].rect.left - self.rect.w
self.rect.left = self.position.x
def update(self):
self.update_position()
self.attach_colliders(self.context.screen)
self.current_frame += self.animation_velocity
self.manage_vertical_collision()
self.manage_horizontal_collision()
self.change_animation_state()
self.acceleration = Vector2D(0,self.GRAVITY)
if int(self.current_frame) > self.animation_state[1]:
self.current_frame = self.animation_state[0]
self.image = self.frames[int(self.current_frame)]
if self.velocity.x <0:
self.image = pg.transform.flip(self.image, True,False)
self.mask = pg.mask.from_surface(self.image,100)
self.mask_surface = self.mask.to_surface(setcolor=(0,0,255,255), unsetcolor=(0,0,0,0))
self.context.screen.blit(self.mask_surface,self.rect.topleft)
self.rect = self.mask_surface.get_rect()
self.rect.topleft = self.position
#pg.draw.rect(self.context.screen, 'gray',self.rect)
def update_position(self):
self.apply_friction()
self.velocity += self.acceleration
self.position += self.velocity
I tried to get a surface without the black points (it works) but when a try to get this rect it takes the rect of the entire image
self.mask = pg.mask.from_surface(self.image)
self.mask_surface = self.mask.to_surface(setcolor=(0,0,255,255), unsetcolor=(0,0,0,0))
self.rect = self.mask_surface.get_rect()
pg.draw.rect(self.context.screen, 'gray',self.rect)
Luis Moura is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.