3

我想实现一个与碰撞对象具有非碰撞对的代码。我的配对是 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()

请帮忙 :)

PS:示例库形状过滤器类:

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

4

1 回答 1

2

你可以通过碰撞回调来解决这个问题,我认为开始回调对你来说是一个不错的选择。在要碰撞的每一对形状上设置一个公共标识符,然后在回调中检查它,并且仅当碰撞的两个对象属于同一对时才返回 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
于 2018-06-13T20:33:15.197 回答