[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Bitmask Collision Response



One way to go is to use simple "two sphere" collision equations.
Here is a snippet of code I wrote for an elastic ball collision
demo when learning pygame.  I think I used this page for reference:

http://stackoverflow.com/questions/345838/ball-to-ball-collision-detection-and-handling

This code is "elastic" (conserves energy) and takes the masses
of both objects into consideration.

For a character against a non-movable heightfield set the
heightfield's mass to infinity and don't bother computing its
final speed.

For friction and non-elastic collisions just do the same thing but
multiply the resulting speed changes by some factor less than 1.0 but
more than 0.0 (like 0.98).  Applying such loss to the velocity
component  parallel to the collision normal makes for inelastic
collisions, and applying it to the component perpendicular to the
collision normal makes for surface friction.

I can send you the entire pygame demo if you're interested.

    def collide(self):
        # this N^2 algorithm does not scale well
        i = 0
        j = 0
        MINIMUM_SEPARATION_SPEED = 1.0
        object_count = len(self.objects)
        while i < object_count:
            j = i + 1
            while j < object_count:
                approach = self.objects[i].get_closest_approach(self.objects[j])
                if approach < 0.0:
                    # negative approach means objects overlap
                    relative_position = self.objects[j].position - self.objects[i].position
                    relative_velocity = self.objects[j].linear_velocity - self.objects[i].linear_velocity

                    if relative_velocity.dot(relative_position) < 0.0:
                        # objects are moving toward each other
                        # use solution to two-body collision
                        total_mass = self.objects[i].linear_mass + self.objects[j].linear_mass
                        axis = relative_position
                        axis.normalize()
                        axial_velocity = axis * axis.dot(relative_velocity)
                        self.objects[i].linear_velocity = self.objects[i].linear_velocity + axial_velocity * (2.0 * (self.objects[j].linear_mass / total_mass))
                        self.objects[j].linear_velocity = self.objects[j].linear_velocity - axial_velocity * (2.0 * (self.objects[i].linear_mass / total_mass))
                        self.objects[i].shift_color(-0.05)
                        self.objects[j].shift_color(-0.05)

                    else:
                        # objects are already moving away
                        speed = relative_velocity.length()
                        if speed < MINIMUM_SEPARATION_SPEED:
                            # objects overlap, but aren't separating fast enough
                            # so we'll give them a little push
                            # NOTE this pumps energy into the system
                            relative_position.normalize()
                            self.objects[i].linear_velocity = self.objects[i].linear_velocity - relative_position * (0.5 * MINIMUM_SEPARATION_SPEED)
                            self.objects[j].linear_velocity = self.objects[j].linear_velocity + relative_position * (0.5 * MINIMUM_SEPARATION_SPEED)
                j = j + 1
            i = i + 1

- Andrew

Tyler Laing wrote:
Then its a solid-on-solid collision, really quite simple. Looking for
collision "handling".

On Fri, Jun 5, 2009 at 2:26 PM, pymike <pymike93@xxxxxxxxx> wrote:

The player needs to move out of a static bitmask. I's a platformer. :)
Concept Art: http://pymike.pynguins.com/downloads/ambito-concept-art.png