Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing Sprite.width/height does not update hitbox #752

Closed
eruvanos opened this issue Sep 15, 2020 · 3 comments
Closed

Changing Sprite.width/height does not update hitbox #752

eruvanos opened this issue Sep 15, 2020 · 3 comments

Comments

@eruvanos
Copy link
Member

Bug Report

Changing Sprite.width/height does not update hitbox.

This results in wrong behaviour using:

  • Sprite.left/right/top/bottom
  • Sprite.collides_with_point
  • GUI Button clicks

Actual behavior:

Running example code fails with AssertionError

Expected behavior:

Changing properties of sprite like Sprite.width/height should update the hitbox.
Example code draws Sprite, passing the asserts

Steps to reproduce/example code:

import arcade
from arcade import Window, Sprite, get_window


class MyWindow(Window):
    def __init__(self):
        super().__init__()
        arcade.set_background_color((0, 0, 0))

        self.sprite = Sprite(":resources:images/space_shooter/playerShip1_orange.png")
        self.sprite.position = get_window().width / 2, get_window().height / 2,

        # Sprite width before : 90
        print(self.sprite.width)

        # Double sprite width: 180
        self.sprite.width = 180
        print(self.sprite.width)

        hit = self.sprite.collides_with_point((self.sprite.center_x + 80, self.sprite.center_y))
        assert hit
        assert self.sprite.right == self.sprite.center_x + 90

    def on_draw(self):
        arcade.start_render()
        self.sprite.draw()


if __name__ == '__main__':
    window = MyWindow()
    arcade.run()
@akapkotel
Copy link
Contributor

akapkotel commented Sep 20, 2020

Ok, I inspected the code and found that error comes from the self._points attribute NOT being set to None in _set_width setter in Sprite class.
In the result, get_hit_box getter returns self._points already set to the original texture dimensions instead of recalculating it.

It is now:
is

And should be:
should_be

Of course the same problem exists for _set_height setter too.

I've also found other, strange thing.In _set_width setter there is a call to spritelist.update_size() but in _set_height there is call to spritelist.update_height(). I wonder why is that so? Should not ther be a call to spritelist.update_width() ? @pvcraven ?

akapkotel pushed a commit to akapkotel/arcade that referenced this issue Sep 28, 2020
Updating sprite width/height was not changing it's hitbox. Now it is.
pvcraven pushed a commit that referenced this issue Sep 30, 2020
Updating sprite width/height was not changing it's hitbox. Now it is.

Co-authored-by: akapkotel <btcuserbtc@gmail.com>
@pvcraven
Copy link
Member

pvcraven commented Oct 3, 2020

Still seems to happen in 2.4.3:
2020-10-03_11-04-44

""" Sprite Sample Program """

import random
import arcade

# --- Constants ---
SPRITE_SCALING_PLAYER = 0.5
SPRITE_SCALING_COIN = 0.2
COIN_COUNT = 50

SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600


class MyGame(arcade.Window):
    """ Our custom Window Class"""

    def __init__(self):
        """ Initializer """
        # Call the parent class initializer
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, "Sprite Example")

        self.player_list = None
        self.coin_list = None

        self.player_sprite = None
        self.score = 0

        self.set_mouse_visible(False)
        arcade.set_background_color(arcade.color.AMAZON)

    def setup(self):

        # Sprite Lists
        self.player_list = arcade.SpriteList()
        self.coin_list = arcade.SpriteList()

        self.score = 0

        self.player_sprite = arcade.SpriteSolidColor(20, 20, arcade.color.RED)
        self.player_sprite.center_x = 400
        self.player_sprite.center_y = 300
        self.player_list.append(self.player_sprite)

        for i in range(COIN_COUNT):
            coin = arcade.SpriteSolidColor(20, 20, arcade.color.AMARANTH_PINK)
            coin.center_x = random.randrange(SCREEN_WIDTH)
            coin.center_y = random.randrange(SCREEN_HEIGHT)
            self.coin_list.append(coin)
            coin.width = 50
            coin.height = 50

    def on_draw(self):
        arcade.start_render()
        self.player_list.draw()
        self.coin_list.draw()

        self.coin_list.draw_hit_boxes(arcade.color.BLACK, 2)

        output = f"Score: {self.score}"
        arcade.draw_text(output, 10, 20, arcade.color.WHITE, 24)

    def on_mouse_motion(self, x, y, dx, dy):
        self.player_sprite.center_x = x
        self.player_sprite.center_y = y

    def on_update(self, delta_time):
        coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite,
                                                              self.coin_list)
        for coin in coins_hit_list:
            coin.remove_from_sprite_lists()
            self.score += 1


def main():
    """ Main method """
    window = MyGame()
    window.setup()
    arcade.run()


if __name__ == "__main__":
    main()

@pvcraven
Copy link
Member

I think this was fixed with that Oct 3 check-in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants