-
-
Notifications
You must be signed in to change notification settings - Fork 176
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
What about geometry multi-collision and collision? #2792
Comments
I know two approaches: double dispatch and lookup. I'm no expert but my experience in implementing collision detection in python has shown me these two approaches. These methods are good for the narrow phase of collision detection where the primitive collision happen. Broad phase is probably a topic of itself. double dispatchI have implemented it once I think.
But this leads to many methods to be implemented. Each shape will have to implement a method for each other shape and itself, e.g.
When adding a new shape then all classes need to be changed/updated. lookupI have used this many times now, My preferred way.
The challenges here are: the lookup key and the order of the arguments Lookupkey: in python I use tuples, but here other ideas could be used like bit masks to combine the values into some value. Also for the lookup table it does not have to be a dict (might be slow), but maybe it could be a simple array (if the number of collision functions is fixed but then the key has to be an index). order of arguments: the code can be written such that always the correct order is used. For convenience a re-ordering method could be registered, e.g.:
The lookup table has the advantage that adding a new collision function is pretty easy and could even be done at runtime. NotesOverall I would recommend to write the collision methods to process lists of objects at once for performance and loop within the function instead of calling a collision method for each pair, e.g.:
If there is still the need for a collision function for single objects then call the one taking lists from within the single object function. |
Context
Following our discussion in #2208 regarding multi-draw functions, it's evident that having numerous APIs for multi-operation tasks doesn't align with our goal of optimizing performance. This was particularly apparent with drawing functions, where faster looping couldn't compensate for the computational time required to render large shapes covering much of the screen.
Now, with the upcoming addition of numerous shapes and corresponding collision methods in the geometry module (#2267), we face a similar challenge. Unlike multi-draw functions, these collision methods' runtime isn't solely determined by pixel count but rather by the complexity of involved shapes. Thus, optimizing runtime and ensuring stability with longer collision sequences becomes more feasible.
The current plan
The current plan entails:
Calculating for the 3 shapes, we'll have a total of: 6 * 3 + 6 * 3 + 3 = 39 functions. This presents a considerable number of collision methods, which could pose usability challenges.
It's worth noting that single collision functions like colliderect() also allow passing a quick tuple to represent the shape, although this doesn't provide a speed benefit. Additionally, with the introduction of shapes like Line, passing a tuple like (10, 10, 20, 10) to a general .collide() method would cause ambiguity between a line and a rectangle.
My alternative
PS. These ideas could also be expaded to the Rect class for pygame 3.0 in #2760.
The alternative proposal is based on two main ideas:
Generalize the Collision Interface
This involves two sub-ideas:
Implementing both of these ideas would reduce the total number of collision functions from 48 (considering every collision function) to 4 + 24 = 28. This approach simplifies maintenance and testing, although it would require some programs to be rewritten, hence the proposal for pygame 3.0.
Accept a Variety of Input Types (Single and Sequence)
This idea stems from our earlier discussion and suggests retaining single collision functions while allowing them to accept sequences of shapes (both classes and tuples) as input and return a sequence of booleans.
This implementation would be relatively straightforward and would spare us from creating specific multi-collision functions for each shape. Moreover, given the nature of collision calculations compared to pixel drawing, performance improvements are predictable. For instance, testing one implementation for Circle.collidepoint yielded a consistent 3X performance improvement, which can be expected for other collision methods as well.
The text was updated successfully, but these errors were encountered: