非碰撞物体具有碰撞对,Pymunk Pygame。

3
我想实现一个代码,其中有非冲突对和碰撞物体。 我的配对对象是两个相互连接的球。我希望这两个配对的球发生碰撞。但是我不希望这两个球与其他配对对象发生碰撞。
如何在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:示例库形状过滤器类:

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


请不要在Stack Overflow上发布太多的代码。这会花费很多时间来分析和调试它,所以请尽量将其减少到绝对最小限度。参考链接 - skrx
我想要与一个类别碰撞并忽略所有其他类别。请检查我的unit()函数下的代码。我的代码可以编译。我使用了XOR和NOT操作数。为了与一个碰撞,忽略其他所有。然而这可能不是一个好主意。我知道你之前问题中的代码是有效的。但这是一个新问题,有点独特@skrx - Meric Ozcan
这些球对中会有多少对同时存在? - skrx
最少50个球,但我相信你的方法可以适用于32个不同的类别,因为ALLMASK 2^32。如果你能帮忙,我会非常感激@skrx。你觉得还有其他方法吗? - Meric Ozcan
让我们在聊天中继续这个讨论 - skrx
显示剩余3条评论
1个回答

2

你可以通过碰撞回调来解决这个问题,我认为begin回调是一个不错的选择。对于每一对你想要发生碰撞的形状,你需要设置一个共同的标识符,然后在回调中进行检查,只有当两个发生碰撞的对象属于同一对时才返回True。

像这样:

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

不错的解决方案。顺便问一下,能否增加ShapeFilter类别的数量? - skrx
2
是的,但需要进行一些更改。Chipmunk有一个名为cpBitmask的typedef,用于类别和掩码。可以通过在(chipmunk)编译时定义所需类型的CP_BITMASK_TYPE来覆盖它。然后,需要更新pymunk,以便_chipmunk_cffi_abi中的cpBitmask类型与定义的任何内容匹配。 - viblo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接