简体   繁体   中英

Colliding shapes in python

My plan is to create a "simple" 2-player minigame game (for ex. sumo and race).

My goal would be to efficiently implement collisions (my current code can deal only with simple wall physics and movement of the objects) with square, circle (and triangle?) shaped objects that can be either part of the environment (for ex. "rocks" or immovable obstacles) or part of the user controlled items (for ex. "cars" or pushable obstacles). It would be also nice to know how mass could also be accounted for in the collisions.

There are two aspects I need help with:

  1. Different types of dynamic collisions between two moving objects (that have a mass and 2D vector) (the physics part not the detection).

  2. Making sure everything that needs to collide, collides fast enough (so that my slow computer could still render more than 40-60 frames per second) , and according to the specific rules (or if it would be possible then according to one rule?). So that it would not also be hard to manage the objects that need to be collided (add, remove, modify and so on).

Or should I just implement two types of collision for ex. static + dynamic circle and dynamic + dynamic circle?

def checkcollisions(object1, object2):
    # x is the current x position
    # y is the current y position
    # angle is the current vector angle (calculated from x and y with pythagoros
    # speed is the length of the vector
    dx = object1.x - object2.x
    dy = object1.y - object2.y

    dist = hypot(dx, dy)
    if dist < object1.radius + object2.radius:
        angle = atan2(dy, dx) + 0.5 * pi
        total_mass = object1.mass + object2.mass
        '''''http://www.petercollingridge.co.uk/pygame-physics-simulation/mass'''''
        if (0.79 <= object1.angle < 2.36 or 0.79-2*pi <= object1.angle < 2.36-2*pi) or (3.93 <= object1.angle < 5.5 or 3.93-2*pi <= object1.angle < 5.5-2*pi) and ((0.79 <= object2.angle < 2.36 or 0.79-2*pi <= object2.angle < 2.36-2*pi) or (3.93 <= object2.angle < 5.5 or 3.93-2*pi <= object2.angle < 5.5-2*pi)):
            (object2angle, object2speed) = vectorsum((object2.angle, object2.speed*(object2.mass-object1.mass)/total_mass), (angle+pi, 2*object1.speed*object1.mass/total_mass))
            (object1angle, object1speed) = vectorsum((object1.angle, object1.speed*(object1.mass-object2.mass)/total_mass), (angle, 2*object2.speed*object2.mass/total_mass))
        else:
            '''''https://en.wikipedia.org/wiki/Elastic_collision'''''
            CONTACT_ANGLE = angle
            x = (((object1.speed * cos(object1.angle - CONTACT_ANGLE) * (object1.mass-object2.mass)+ 2*object2.mass*object2.speed*cos(object2.angle - CONTACT_ANGLE))/total_mass)*cos(CONTACT_ANGLE))+object1.speed*sin(object1.angle - CONTACT_ANGLE)*cos(CONTACT_ANGLE + 0.5 * pi)
            y = (((object1.speed * cos(object1.angle - CONTACT_ANGLE) * (object1.mass-object2.mass)+ 2*object2.mass*object2.speed*cos(object2.angle - CONTACT_ANGLE))/total_mass)*cos(CONTACT_ANGLE))+object1.speed*sin(object1.angle - CONTACT_ANGLE)*sin(CONTACT_ANGLE + 0.5 * pi)
            object1angle = pi/2 - atan2(y, x)
            object1speed = hypot(x, y)

            x = (((object2.speed * cos(object2.angle - CONTACT_ANGLE)*(object2.mass-object1.mass)+2*object1.mass*object1.speed*cos(object1.angle - CONTACT_ANGLE))/total_mass)*cos(CONTACT_ANGLE))+object2.speed*sin(object2.angle - CONTACT_ANGLE)*cos(CONTACT_ANGLE + 0.5 * pi)
            y = (((object2.speed * cos(object2.angle - CONTACT_ANGLE)*(object2.mass-object1.mass)+2*object1.mass*object1.speed*cos(object1.angle - CONTACT_ANGLE))/total_mass)*cos(CONTACT_ANGLE))+object2.speed*sin(object2.angle - CONTACT_ANGLE)*sin(CONTACT_ANGLE + 0.5 * pi)
            object2angle = pi/2 - atan2(y, x)
            object2speed = hypot(x, y)

        (object2.angle, object2.speed) = (object2angle, object2speed)
        (object1.angle, object1.speed) = (object1angle, object1speed)
        object1.speed *= 0.999
        object2.speed *= 0.999

        overlap = 0.5*(object1.radius + object2.radius - dist+1)
        object1.x += sin(angle)*overlap
        object1.y -= cos(angle)*overlap
        object2.x -= sin(angle)*overlap
        object2.y += cos(angle)*overlap

'''''http://www.petercollingridge.co.uk/pygame-physics-simulation/mass'''''


def vectorsum(vectorx, vectory):  # Every array's first number is the degree from 0, the second is speed
    x = sin(vectory[0]) * vectory[1] + sin(vectorx[0]) * vectorx[1]
    y = cos(vectory[0]) * vectory[1] + cos(vectorx[0]) * vectorx[1]  # Calculating new vectors from anle and lenght
    angle = pi / 2 - atan2(y, x)  # Calculating the degree
    speed = hypot(x, y)  # Calculating the speed
    return angle, speed

(I'm just a beginner with Python (or English) so keep that in mind please.)

  1. Collision detection is very easy in pygame. Take a look at using pygame.sprite . They have several functions to detect collisions. ( spritecollide , groupcollide , etc) If you have some complex collision interaction generally you use the rect or circle to see if they collide, then only do your complex calculations on those. Though for most games you do not need to have the cost of perfect collision detection, close enough is good enough.
  2. As far was what happens when you collide, that is more physics then programming. Some concepts to keep in mind are: momentum conservation, elastic vs inelastic collisions, deflection angle. "How to building a 2D physics engine" is a bit too broad for SO question. Maybe look at how-to-create-a-custom-2d-physics-engine-oriented-rigid-bodies

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM