0

I'm working on my pygame project and now I want to make collision rectangle smaller than the whole sprite image. But the problem is image.get_rect() put the collide rectangle in the topleft position regardless using center or midbottom or anything else. I don't know what to do with this, I think the solution is very simple, but pygame documentation is unreadable at all.

The problem place:

class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        # pos is the (x,y) coordinates of player starting position on the map

        # [...]

        self.status = "idle"
        self.image = self.animations[self.status][self.frame_index]
        self.rect = self.image.get_rect(
            center=pos,
            w=TILESIZE,
            h=TILESIZE
        )

        # THIS DOESN'T HELP:
        # self.rect.center = self.image.get_rect().center
        
        # [...]

Showing the Player.rect I get this: screen1

The rect part is definitely in the topleft position... As I think I should do something with an image, not with rect, because the rect itself behaves exactly as intended

This is my full player.py file:

import pygame

from ..importer import import_folder
from ..settings import (
    DASH_COOLDOWN,
    DASH_POWER,
    ENERGY,
    HEALTH,
    JUMPS,
    SPEED,
    TILESIZE,
    WEAPON_DATA,
)

__all__ = ["Player"]


class Player(pygame.sprite.Sprite):
    def __init__(self, pos, player_attack):
        super().__init__()

        # set animation
        self.type = "Player Sword"
        self.assets()
        self.frame_index = 0
        # ! don't do animation speed aliquot to 1
        self.animation_speed = 0.3
        self.status = "idle"
        self.image = self.animations[self.status][self.frame_index]
        self.rect = self.image.get_rect(
            center=pos,
            w=TILESIZE,
            h=TILESIZE,
        )
        # THIS DOESN'T HELP:
        # self.rect.center = self.image.get_rect().center

        # player status
        self.exp = 123
        self.health = HEALTH
        self.energy = ENERGY
        self.facing = True
        self.space_pressed = False
        self.on_ground = False
        self.on_ceiling = False
        self.on_left = False
        self.on_right = False
        self.can_jump = JUMPS
        self.wearpon = WEAPON_DATA[self.type]

        # player actions status
        self.shift_pressed = False
        self.attacking = False
        self.attack_time = None
        self.dashing = False
        self.can_attack_1 = True
        self.can_attack_2 = True
        self.can_attack_3 = True
        self.can_dash = True
        self.attack_type = "attack_1"

        # cooldowns
        self.dash_cooldown = DASH_COOLDOWN

        # movement params
        self.direction = pygame.math.Vector2(0, 0)
        self.speed = SPEED
        self.gravity_v = SPEED / 10
        self.jump_speed = -SPEED * 2
        self.player_attack = player_attack[0]
        self.destroy_damageboxes = player_attack[1]
        self.dash_power = DASH_POWER

    def update_settings(self):
        from ..settings import (
            DASH_COOLDOWN,
            DASH_POWER,
            HEALTH,
            JUMPS,
            SPEED,
            WEAPON_DATA,
        )

        self.health = HEALTH
        self.can_jump = JUMPS
        self.wearpon = WEAPON_DATA[self.type]
        self.speed = SPEED
        self.gravity_v = SPEED / 10
        self.jump_speed = -SPEED * 2
        self.dash_cooldown = DASH_COOLDOWN
        self.dash_power = DASH_POWER

    def assets(self):
        c_path = f"src/Assets/Sprites/Main_Character/{self.type}/"
        self.animations = {
            "climb": [],
            "dash": [],
            "die": [],
            "fall": [],
            "idle": [],
            "jump": [],
            "run": [],
        }
        if self.type != "Player":
            self.animations["attack_1"] = []
            self.animations["attack_2"] = []
            self.animations["attack_3"] = []

        for animation in self.animations:
            path = c_path + animation
            self.animations[animation] = import_folder(path)

    def animate(self, status):
        animation = self.animations[status]
        self.frame_index += self.animation_speed

        if self.frame_index > len(animation) - 1:
            if self.attacking == True:
                self.attacking = False
            elif self.dashing == True:
                self.dashing = False
            self.frame_index = 0

        if self.facing:
            self.image = animation[int(self.frame_index)]
        else:
            self.image = pygame.transform.flip(
                animation[int(self.frame_index)], True, False
            )

        # if self.on_ground and self.on_right:
        #     self.rect = self.image.get_rect(bottomright=self.rect.bottomright)
        # elif self.on_ground and self.on_left:
        #     self.rect = self.image.get_rect(bottomleft=self.rect.bottomleft)
        # elif self.on_ground:
        #     self.rect = self.image.get_rect(midbottom=self.rect.midbottom)
        # elif self.on_ceiling and self.on_right:
        #     self.rect = self.image.get_rect(topright=self.rect.topright)
        # elif self.on_ceiling and self.on_left:
        #     self.rect = self.image.get_rect(topleft=self.rect.topleft)
        # elif self.on_ceiling:
        #     self.rect = self.image.get_rect(midtop=self.rect.midtop)

    def get_status(self):
        if self.health <= 0:
            self.status = "die"
        else:
            if self.dashing:
                self.status = "dash"
                self.animation_speed = 0.4
            elif self.attacking:
                self.animation_speed = self.wearpon[self.attack_type]["speed"]
                self.status = self.attack_type
            else:
                self.animation_speed = 0.3
                if self.direction.y < 0:
                    self.status = "jump"
                elif self.direction.y > 1:
                    self.status = "fall"
                else:
                    if self.direction.x != 0:
                        self.status = "run"
                    else:
                        self.status = "idle"

    def input(self):
        # self.joystick = pygame.joystick.Joystick(0)
        # self.joystick.init()
        keys = pygame.key.get_pressed()
        mouses = pygame.mouse.get_pressed()

        # attack input
        if self.type != "Player":
            if not self.attacking:
                if mouses[0] and self.can_attack_1:
                    self.attacking = True
                    self.attack_type = "attack_1"
                    self.attack_time = pygame.time.get_ticks()
                    self.direction.x = 0
                    self.frame_index = 0
                    self.can_attack_1 = False
                    self.player_attack()

                elif mouses[2] and self.can_attack_2:
                    self.attacking = True
                    self.attack_type = "attack_2"
                    self.attack_time = pygame.time.get_ticks()
                    self.frame_index = 0
                    self.direction.x = 0
                    self.can_attack_2 = False
                    self.player_attack()

                elif mouses[1] and self.can_attack_3:
                    self.attacking = True
                    self.attack_type = "attack_3"
                    self.attack_time = pygame.time.get_ticks()
                    self.frame_index = 0
                    self.direction.x = 0
                    self.can_attack_3 = False
                    self.player_attack()

        # movement input
        if not self.dashing and not self.attacking:
            #  or (self.joystick.get_axis(0) > 0)
            if keys[pygame.K_d]:
                self.direction.x = 1
                self.facing = True
            elif keys[pygame.K_a]:
                self.direction.x = -1
                self.facing = False
            else:
                self.direction.x = 0

        if self.can_dash and not self.attacking:
            if keys[pygame.K_LSHIFT] and self.direction.x == 1:
                self.dashing = True
                self.facing = True
                self.can_dash = False
                self.dash_time = pygame.time.get_ticks()
                self.direction.x = self.dash_power
                self.frame_index = 0
            elif keys[pygame.K_LSHIFT] and self.direction.x == -1:
                self.dashing = True
                self.can_dash = False
                self.facing = False
                self.dash_time = pygame.time.get_ticks()
                self.direction.x = -self.dash_power
                self.frame_index = 0

        # jump input

        if keys[pygame.K_SPACE]:
            if self.space_pressed == False:
                if self.can_jump > 0:
                    self.jump()
                self.space_pressed = True
        else:
            self.space_pressed = False

    def cooldowns(self):
        current_time = pygame.time.get_ticks()

        if not self.can_attack_1:
            if current_time - self.attack_time <= self.wearpon["attack_1"]["cooldown"]:
                self.can_attack_1 = False
            else:
                self.can_attack_1 = True
                self.destroy_damageboxes()

        if not self.can_attack_2:
            if current_time - self.attack_time >= self.wearpon["attack_1"]["cooldown"]:
                self.can_attack_2 = False
            else:
                self.can_attack_2 = True
                self.destroy_damageboxes()

        if not self.can_attack_3:
            if current_time - self.attack_time >= self.wearpon["attack_1"]["cooldown"]:
                self.can_attack_3 = False
            else:
                self.can_attack_3 = True
                self.destroy_damageboxes()

        if not self.can_dash:
            if current_time - self.dash_time >= self.dash_cooldown:
                self.can_dash = True

    def gravity(self):
        self.direction.y += self.gravity_v
        self.rect.y += self.direction.y

    def jump(self):
        self.direction.y = self.jump_speed
        self.can_jump -= 1

    def update(self):
        self.input()
        self.cooldowns()
        self.rect.x += self.direction.x * self.speed
        self.get_status()
        self.animate(self.status)
zer0deck
  • 1
  • 1
  • Actually you need 2 rectangles. One for drawing and one for the collision. Or just get a subsurface from the image [How to get the correct dimensions for a pygame rectangle created from an image](https://stackoverflow.com/questions/65361582/how-to-get-the-correct-dimensions-for-a-pygame-rectangle-created-from-an-image/65361896#65361896) – Rabbid76 Apr 15 '22 at 11:56

0 Answers0