renpy / pygame_sdl2

Reimplementation of portions of the pygame API using SDL2.
GNU Lesser General Public License v2.1
326 stars 64 forks source link

Rect.__init__ does not support argument with rect attribute, LayeredUpdates.get_sprites_at fails #67

Closed hsandt closed 3 months ago

hsandt commented 7 years ago

Unlike the original pygame, Rect cannot be constructed from a sprite. In pygame, Rects are basically constructed with the GameRect_FromObject function in rect.c, which supports passing another Rect, (x, y), (x, y, w, h) or [(x, y), (w, h)], but also an object with a rect attribute matching one of the previous cases (or even a rect() method that returns one of the previous cases) through recursion.

a. pygame_sdl2 should add an equivalent check in Rect.init (rect.pyx). In particular, this behaviour is used by LayeredUpdates.get_sprites_at(pos) which calls in order Rect.collidelistall(_sprites) > Rect.colliderect(other) > Rect(other). Because it passes the sprites directly to Rect.collidelistall, they need to be converted to Rect later.

b. An alternative would be to modify get_sprites_at in sprite.py to pass rects to Rect.colliderlistall instead of sprites, with something like

colliding_idx = rect.collidelistall([sprite.rect for sprite in _sprites])

If you don't like the fact that you can pass anything with a rect attribute to the Rect constructor, or want to avoid possible recursion on the rect attribute, you'll prefer method b.

An example of error when calling get_sprites_at with the current code (I am using subclasses of DirtySprite for the visible objects in my game):

File ".../myscript.py", line 112, in update_on_mouse_button sprites = self.view.get_sprites_at(mouse_pos) File ".../Python/VirtualEnvs/myenv/lib/python2.7/site-packages/pygame_sdl2/sprite.py", line 788, in get_sprites_at colliding_idx = rect.collidelistall(_sprites) File "pygame_sdl2/rect.pyx", line 362, in pygame_sdl2.rect.Rect.collidelistall (gen/pygame_sdl2.rect.c:9198) File "pygame_sdl2/rect.pyx", line 348, in pygame_sdl2.rect.Rect.colliderect (gen/pygame_sdl2.rect.c:8630) File "pygame_sdl2/rect.pyx", line 45, in pygame_sdl2.rect.Rect.init (gen/pygame_sdl2.rect.c:1146) TypeError: object of type 'MySpriteSubClass' has no len()

I'll try method b. on my fork soon.