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

标签 python pygame collision pymunk

我想实现一个代码,它具有与碰撞对象的非碰撞对。我的对是 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:示例库形状过滤器类:

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

最佳答案

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

关于python - 具有碰撞对的非碰撞对象,Pymunk Pygame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50815789/

相关文章:

javascript - ActionScript ExternalInterface 命名空间冲突

python - Masonite 中的 login_required() 相当于什么?

python - 本地图在pygame中移动时用鼠标找到一个项目

python - 为什么这个 Python 代码在 Ubuntu 上会出现段错误,但在 Windows 上却没有?

pygame - 使用 psychopy 时如何在不更改窗口类型的情况下克服 "RuntimeError: Gamma ramp size is reported as 0."?

Swift:物理 body 碰撞错误指令错误

python - 抓取过程中返回"None"

python - 如何在 Flask 中并行化任务?

python - Django/Python requirements.txt 总是获取最近的包

libgdx - 使用 box2d 检测碰撞,但忽略力