So, after some thinking, I came up with the following solution: Instead of checking the y-value of the drop once a collision is detected, only check for collisions against rain drops that are within the acceptable range. It works great, and it's pretty slick if I do say so myself.
First, I store the heights of all beakers in the current level. Currently, each level has at least 1 beaker, no more than 2, the beakers exist for the duration of the level, and they are all of the same height. However, in the future this may change, and beakers may even be destroyed as the level plays on, so I had to ensure that I was able to keep track of the beakers that were currently on the screen: having a static list of the beakers that the level started with wouldn't have been sufficient. Then, I sort the list of beaker heights. This ensures the smallest beaker height will be in the front of the list. This is crucial because I need to use the y-value of the *smallest* beaker as my baseline for accepting collisions because even if I have taller beakers, a y-value of <= the smallest one will also suffice for any beakers taller (remember, y gets larger as it approaches the bottom of the screen). Now that I have the y-value of the shortest beaker, I check against this value when a collision is detected. If the rain drop's y-value is <= this number, I know it is within the area of the opening of the beaker, and I can consider that a collision, and thus a "caught" rain drop.
This also has a nice benefit in that it eliminates a number of otherwise useless and costly collision comparisons. Before, every drop on the screen was being checked for a collision. Now, any drop that is below the shortest beaker is ignored entirely. With enough drops on the screen, this can be a big savings in performance.
The code for this is as follows:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Find the shortest beaker so we know which drops to check for collisions | |
# against | |
beakerHeights = [] | |
shortest = 0 | |
for beaker in level.beakers: beakerHeights.append(beaker.rect.y) | |
beakerHeights.sort() | |
if (beakerHeights): shortest = beakerHeights[0] | |
# Get the current drops to test for collisions | |
drops=pygame.sprite.Group() | |
for cloud in level.clouds: | |
for drop in cloud.drops: | |
# Only check for collisions with drops that are above or = to the top | |
# of the shortest beaker | |
if (drop.rect.y <= shortest): | |
drops.add(drop) | |
for beaker in pygame.sprite.groupcollide(level.beakers, drops, False, True).keys(): | |
beaker.takeDrop() |
No comments:
Post a Comment