具有碰撞对的非碰撞对象,Pymunk Pygame

Non colliding objects which has Colliding Pairs, Pymunk Pygame

我想实现一个代码,该代码具有与碰撞对象的非碰撞对。我的对是 2 个相互连接的球。我希望那些 2 对球发生碰撞。但是我不希望那两个球与其他对碰撞。

如何在 pymunk ShapeFilter 中实现包含这么多类别的蒙版?我应该使用按位运算符吗?正如你在我的形状过滤器中看到的那样,我试图忽略它们类别之外的值,除了它们的成对类别,但它不适用于 4 + 球数?

我的代码无法相互处理球的那些状态。

import pygame 
from pygame.locals import *
from pygame.color import *
import pymunk
import pymunk.pygame_util
from pymunk import Vec2d
import  sys
#import tensorflow as tf
from time import sleep
import time
import numpy as np
from math import exp
from random import seed
from random import random
import datetime
import operator


class Game:
    def __init__(self):


        # initialize game window
        pygame.init()

        self.screen_x= 1500
        self.screen_y=  200

        # Pool Hyper Parameters
        # BE CAREFULL CHANGING THESE VARIABLES

        self.pool_size = 2
        self.pool_time = 15
        #########################################################################
        # NN lists
        #Pygame fonts
        self.font = pygame.font.SysFont("Arial", 16)
        self.screen = pygame.display.set_mode((self.screen_x,self.screen_y+200)) #screen display
        self.clock = pygame.time.Clock() ## init clock
        self.running = True
        # pymunk init
        self.space = pymunk.Space()
        self.space.gravity = (0.0, -1200.0)  #gravity setup
        self.draw_options = pymunk.pygame_util.DrawOptions(self.screen)#adds add physics to the screen


    def new(self):
        # start a new game
        ## Balls
        self.balls = []

        ## creating walls
        self.static_body = self.space.static_body
        self.static_lines = [pymunk.Segment(self.static_body, (0.0,50.0), (1500.0, 50.0), 0.0) ## road
                            ,pymunk.Segment(self.static_body, (1499.0, 150.0), (1499.0, 700.0), 0.0)
                            ,pymunk.Segment(self.static_body, (1800, 50.0), (1800, 170.0), 0.0)
                           ,pymunk.Segment(self.static_body, (0.0,50.0), (0.0, 700.0), 0.0) ## wall 1
                            ]
        ## set walls
        for line in self.static_lines:
            line.elasticity = 0.95
            line.friction = 01.5
            #line.filter = pymunk.ShapeFilter(categories=np.uint8(0))

        self.space.add(self.static_lines)
        # Go to run
        self.run()

    def run(self):
        # Game Loop
        self.playing = True
        self.no_ball = True
        while self.running:
            self.events()
            if self.no_ball == True:
                self.unit(self.pool_size)

            self.update()


    def update(self):


            self.screen.fill(THECOLORS["white"])
            ### Draw stuff
            self.balls_to_remove = []
            for ball in self.balls:
                if ball.body.position.y < 0: self.balls_to_remove.append(ball)
            for ball in self.balls_to_remove:
                self.space.remove(ball, ball.body)
                self.balls.remove(ball)
            self.space.debug_draw(self.draw_options)
            ### Update physics
            self.dt = 1.0/60.0
            for k in range(1):
                self.space.step(self.dt)

            ### Flip screen
            pygame.display.flip()
            self.clock.tick(50)
            pygame.display.set_caption("fps: " + str(self.clock.get_fps()))


    def events(self):
        for event in pygame.event.get():
            if event.type == QUIT:
                self.running = False
            if event.type == KEYDOWN:
                if event.key == K_y: ## Creates a ball
                    self.running = False
                    pass

            elif event.type == pygame.MOUSEMOTION:
                (self.mouse_x,  self.mouse_y) = pymunk.pygame_util.get_mouse_pos(self.screen)



    def unit (self, number_balls=None):
        #Mass And Radius units
        self.mass = 20
        self.radius = 10

        #Mass and Radius for joint
        self.mass_joint = 2
        self.radius_joint = 2

        #for n in number_balls
        self.objs = list()
        for i in range(number_balls):

            self.objs.append(pymunk.Body())
            self.objs.append(pymunk.Body())
            self.objs.append(pymunk.Body())

            #Inertia
            self.inertia = pymunk.moment_for_circle(self.mass, 0, self.radius, (0,0))
            self.inertia_joint = pymunk.moment_for_circle(self.mass_joint , 0, self.radius_joint, (0,0))  
            #Body
            self.objs[i], self.objs[i+1] = pymunk.Body(self.mass, self.inertia), pymunk.Body(self.mass, self.inertia)
            self.objs[i+2] = pymunk.Body(self.mass_joint, self.inertia_joint)

            #Position
            x = 100
            self.objs[i].position = x   , 90
            self.objs[i+1].position = x+24, 90
            self.objs[i+2].position = x+12, 90
            #Links
            self.link_1 = pymunk.PinJoint(self.objs[i], self.objs[i+2], (0, 0), (0, 0))
            self.link_2 = pymunk.PinJoint(self.objs[i+1], self.objs[i+2], (0, 0), (0, 0))
            # Adding Body links
            self.space.add(self.link_1)
            self.space.add(self.link_2)

            #First ball shape
            self.shape_first = pymunk.Circle(self.objs[i], self.radius, (0,0))
            self.shape_first.elasticity = 0.4
            self.shape_first.friction = 0.9
            self.space.add(self.objs[i], self.shape_first)

            #Fsecond ball shape
            self.shape_second = pymunk.Circle(self.objs[i+1], self.radius, (0,0))
            self.shape_second.elasticity = 0.4
            self.shape_second.friction = 0.9
            self.space.add(self.objs[i+1], self.shape_second)

            #Joint shape        
            self.shape_joint = pymunk.Circle(self.objs[i+2], self.radius_joint, (0,0))
            self.shape_joint.elasticity = 0.4
            self.shape_joint.friction = 0.9
            #self.shape_joint.sensor == True
            self.space.add(self.objs[i+2], self.shape_joint)


            body_first_category = (i*3)+1#"{0:b}".format(int(i+1)) 
            body_second_category = (i*3)+2
            body_joint_category = (i*3)+3
            print (body_first_category )
            print(body_second_category )
            print(body_joint_category )

            #"{0:b}".format(int(i+2))
            self.shape_first.filter = pymunk.ShapeFilter(categories=body_first_category, mask=(body_joint_category and body_second_category)  )            
            self.shape_second.filter = pymunk.ShapeFilter(categories=body_second_category, mask=(body_first_category and body_joint_category)  )
            self.shape_joint.filter = pymunk.ShapeFilter(categories=body_joint_category, mask=(body_first_category and body_second_category))  

            self.balls.append(self.shape_first)
            self.balls.append(self.shape_second)
            self.balls.append(self.shape_joint)
            self.no_ball = False



g = Game()
while g.running:
    g.new()


##pg.quit()

请帮忙:)

P.S:示例库形状过滤器 class:

http://www.pymunk.org/en/latest/pymunk.html#pymunk.ShapeFilter

你可以用碰撞回调来解决这个问题,我认为 begin 回调对你来说是个不错的选择。在每对要碰撞的形状上设置一个公共标识符,然后在回调中检查它,并且 return 只有当碰撞的两个对象属于同一对时才为真。

像这样:

def only_collide_same(arbiter, space, data):
    a, b = arbiter.shapes
    return a.pair_index == b.pair_index

h = space.add_collision_handler(1,1)
h.begin = only_collide_same

for i in range(10):
    # create shapes and bodies ...
    # then for each pair of shapes:
    shape1.pair_index = i
    shape1.collision_type = 1
    shape2.pair_index = i
    shape2.collision_type = 1