如何在复杂的SpriteKit模拟中解决不必要的碰撞?

时间:2015-08-13 08:03:01

标签: ios swift sprite-kit skphysicsbody

(如果你想切入追逐,请转到粗体部分。)

我的模拟中发生了不必要的碰撞。我的模拟有以下几组:

TeethTop(这是一组对象)
TeethBottom(这是一组对象)
球(在游戏中移动的主要对象)
线(偶尔绘制的一条线仅用于检测用户是否刷到牙齿)
边界(屏幕边界)

以下是我需要的规则

  • 我需要生成SKcontacts
    • 球击中任何牙齿(顶部或底部)
    • TeethTop击中任何牙齿
    • 线击中任何牙齿
  • 至于身体接触和反应(谁可以击中谁并进行物理模拟)
    • 该线不能妨碍移动或击球
    • 球必须落在牙齿上,但不要移动牙齿
    • 由于物理原因,任何牙齿都不能移动身体
    • 没有牙齿必须对与另一颗牙齿的接触做出反应
    • 球不需要穿过边界
  • 生病引力
    • 球是唯一对重力作出反应的球
  • 动态的东西(不是代码)
    • 球是动态的,因为它会对重力产生反应并击中其他牙齿
    • 无论如何,其他所有内容都会保持不变(但是我必须告诉它们它们是动态的,所以当顶部击中底部时我可以拥有SKPhysicsContacts)

基本上发生的是它们是两排牙齿,顶部和底部。他们做自己的事情,成为一个舞台。墙壁是一样的。球在嘴里移动就像一个撞击并咬住牙齿的平台。

在滑动时,在滑动后创建SKPhysicsNode线,并检测用户向哪个牙齿滑动(****可能是更好的方式,然后为滑动线制作SKPhyiscsNode ...我仍然需要检测是否用户在牙齿方向上滑动)。一切都是花花公子一段时间,然后当顶部的牙齿从底部撞到牙齿时,嘴巴闭合并停止。

我把所有东西都设置得很好,因为

BottomTeethGroup = 10
TopTeethGroup = 31
playergroup = 2
wallgroup = 1
lineleart = 99
  • 顶尖的牙齿
    • affectedbygravity = false
    • collisionbitmask = 0
    • categorybitmask = BottomTeethGroup
    • contacttTest = TopTeethGroup
    • dynamic = false
  • 牙齿底部
    • affectedbygravity = false
    • collisionbitmask = 0
    • categorybitmask = TopTeethGroup
    • contacttTest = BottomTeethGroup
    • dynamic = false
    • affectedbygravity = false
    • 永远不会设置碰撞位掩码,因此它会与所有内容发生碰撞
    • categorybitmask = playergroup
    • contacttTest = playergroup
    • 动态= true
  • 边界
    • categorybitmask = wallgroup
    • dynamic = false
  • 线
    • collisionbitmask = 0
    • categorybitmask = lineleart
    • 我尝试将物理属性设置为疯狂值,但我不能让球通过

我添加该行时会出现问题。检测到的所有内容都可以正常工作,直到您添加该行。不幸的是,球与线路相撞产生了一种物理反应,这并不是一件好事!球不应该与线发生碰撞!

我认为他们的方式是一些选择:

  • 让球穿过线,或忽略两个之间的碰撞
  • 找到一种不同的方法来检测玩家在哪个牙齿上滑动(目前的方法仍有缺陷,因为该线会探测到多个牙齿,因为它有一个斜坡,一旦碰到第一个牙齿就不会停止)。如果有人有更好的方法,我有开始和结束的坐标以及方向。
  • 或许如果我们能够做到这一点,那么上牙和下牙只与另一侧的牙齿有物理接触,那么事情会变得更容易。
  • 让球看起来像是在穿过线

编辑:也许我对事物的定义是有缺陷的,所以这就是我认为联系人的工作方式:

  • collisionbitmask:仅与具有您指定的数字的其他对象发生碰撞。如果为0则它与没有对象发生碰撞,如果没有设置则会与所有
  • 发生冲突
  • categorybitmask:定义什么类别,如果一个对象有一个具有此值的类别测试位掩码,那么将创建一个SKPhysics联系人,但它们可能不一定是物理反应
  • contactTest:如果它命中并且另一个对象与此处设置的对象具有相同的categorybitmask,则将进行SKphysics联系
  • 动态对象在遇到其他动态对象或非动态对象时会产生物理反应。为所有碰撞编写SKPhysicsContacts
  • 非动态对象不会在任何碰撞中移动,并且只有在另一个对象是静态时才会写入SKPhysics接触。预计两个非动态对象不会发生碰撞。

我尝试过的解决方案列表:

  • 未设置线条碰撞比特(相同问题)
  • Cavities collisionbitmask设置为0(通过随机牙齿落下但是它不会与线路发生碰撞,但仍会生成SKPhysicsContact)
  • 所有的牙齿'碰撞位掩码设置为4(A BIIG MESS)
  • 顶齿碰撞钻头面罩设置为2,底部设置为4(较少混乱,当腔体碰到牙齿时,它会像0 g一样漂移(0 g))

编辑:

我一直在尝试一堆东西,但没有一个能奏效。我厌倦了,创造了一个有四个球的新项目。基本上,您将每个球设置为特定的组类型并运行模拟。我有它所以它们是所有类别的顶部变量。如果模拟设置正确(我相信它是),程序WI模拟如果顶部的所有值都正确将会发生什么。

您还可以找到以下代码

//

//  GameScene.swift

//  CollisionTesting

//

//  Created on 8/13/15.

//  Copyright (c) 2015 BroccoliPresentations. All rights reserved.

//

 

import SpriteKit

enum type

{

    case _toptooth

    case _bottomtooth

    case _ball

    case _line

    case _boundary

    case _none

}

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {

        

        //The physics categories for each of them

        var topteethcategory:UInt32 = (0x01 << 1)

        var bottomteethcategory:UInt32 = (0x01 << 2)

        var ballcategory:UInt32 = (0x01 << 3)

        var boundriesgroup:UInt32 = (0x01 << 4)

        var linegroup:UInt32 = (0x01 << 5)

        

        //When collision reports should be written up

        var topteethcolisionreport:UInt32 = bottomteethcategory

        var bottomteethcollisionreport:UInt32 = topteethcategory

        var ballcollisionreport:UInt32 = bottomteethcategory | topteethcategory

        var boundriescollisionreport:UInt32 = 0

        var linecollisionreport:UInt32 = topteethcategory | bottomteethcategory

        

        //When they should bounce off of eachother

        var topteethphysics:UInt32 = bottomteethcategory

        var bottomteethphysics:UInt32 = topteethcategory

        var ballphysics:UInt32 = bottomteethcategory | topteethcategory | boundriesgroup

        var boundriesphysics:UInt32 = boundriesgroup

        var linecollisionphysics:UInt32 = linegroup

        

        

        //Here you can set what tope of object each color is

        var blue:type = type._toptooth

        var red:type = type._bottomtooth

        var yellow:type = type._ball

        var green:type = type._none

        

        

        var xy = CGRectGetMidX(self.frame) * 1.5

        var ball1 = SKSpriteNode(texture: SKTexture(imageNamed: "Blue"))

        ball1.position = CGPoint(x: xy, y:CGRectGetMidY(self.frame));

        ball1.size = CGSizeMake(100, 100)

        ball1.physicsBody?.affectedByGravity = false

        ball1.physicsBody = SKPhysicsBody(circleOfRadius: 50)

        ball1.physicsBody?.velocity = CGVector(dx: -100, dy: 0)

        

        var ball2 = SKSpriteNode(texture: SKTexture(imageNamed: "Red"))

        ball2.position = CGPoint(x:xy / 2, y:CGRectGetMidY(self.frame));

        ball2.size = CGSizeMake(100, 100)

        ball2.physicsBody?.affectedByGravity = false

        ball2.physicsBody = SKPhysicsBody(circleOfRadius: 50)

        ball2.physicsBody?.velocity = CGVector(dx: 100, dy: 0)

        

        var ball3 = SKSpriteNode(texture: SKTexture(imageNamed: "Yellow"))

        ball3.position = CGPoint(x:((xy / 4) + xy) / 2, y:CGRectGetMidY(self.frame) / 2);

        ball3.size = CGSizeMake(100, 100)

        ball3.physicsBody?.affectedByGravity = false

        ball3.physicsBody = SKPhysicsBody(circleOfRadius: 50)

        ball3.physicsBody?.velocity = CGVector(dx: 0, dy: 100)

        

        var ball4 = SKSpriteNode(texture: SKTexture(imageNamed: "Green"))

        ball4.position = CGPoint(x:((xy / 4) + xy) / 2, y:CGRectGetMidY(self.frame) * 1.5);

        ball4.size = CGSizeMake(100, 100)

        ball4.physicsBody?.affectedByGravity = false

        ball4.physicsBody = SKPhysicsBody(circleOfRadius: 50)

        ball4.physicsBody?.velocity = CGVector(dx: 0, dy: -100)

        self.addChild(ball1)

        self.addChild(ball2)

        self.addChild(ball3)

        self.addChild(ball4)

        

        

        switch (blue)

        {

        case type._toptooth:

                ball1.physicsBody?.categoryBitMask = topteethcategory

                ball1.physicsBody?.collisionBitMask = topteethphysics

                ball1.physicsBody?.contactTestBitMask = topteethcolisionreport

        case type._bottomtooth:

            ball1.physicsBody?.categoryBitMask = bottomteethcategory

            ball1.physicsBody?.collisionBitMask = bottomteethphysics

            ball1.physicsBody?.contactTestBitMask = bottomteethcollisionreport

        case type._ball:

            ball1.physicsBody?.categoryBitMask = ballcategory

            ball1.physicsBody?.collisionBitMask = ballphysics

            ball1.physicsBody?.contactTestBitMask = ballcollisionreport

        case type._boundary:

            ball1.physicsBody?.categoryBitMask = boundriesgroup

            ball1.physicsBody?.collisionBitMask = boundriesphysics

            ball1.physicsBody?.contactTestBitMask = boundriescollisionreport

        case type._line:

            ball1.physicsBody?.categoryBitMask = linegroup

            ball1.physicsBody?.collisionBitMask = linecollisionphysics

            ball1.physicsBody?.contactTestBitMask = linecollisionreport

        case type._none:

            ball1.position = CGPointMake(100000, 10000)

        }

        

        switch (red)

        {

        case type._toptooth:

            ball2.physicsBody?.categoryBitMask = topteethcategory

            ball2.physicsBody?.collisionBitMask = topteethphysics

            ball2.physicsBody?.contactTestBitMask = topteethcolisionreport

        case type._bottomtooth:

            ball2.physicsBody?.categoryBitMask = bottomteethcategory

            ball2.physicsBody?.collisionBitMask = bottomteethphysics

            ball2.physicsBody?.contactTestBitMask = bottomteethcollisionreport

        case type._ball:

            ball2.physicsBody?.categoryBitMask = ballcategory

            ball2.physicsBody?.collisionBitMask = ballphysics

            ball2.physicsBody?.contactTestBitMask = ballcollisionreport

        case type._boundary:

            ball2.physicsBody?.categoryBitMask = boundriesgroup

            ball2.physicsBody?.collisionBitMask = boundriesphysics

            ball2.physicsBody?.contactTestBitMask = boundriescollisionreport

        case type._line:

            ball2.physicsBody?.categoryBitMask = linegroup

            ball2.physicsBody?.collisionBitMask = linecollisionphysics

            ball2.physicsBody?.contactTestBitMask = linecollisionreport

        case type._none:

            ball2.position = CGPointMake(100000, 10000)

        }

        

        switch (blue)

        {

        case type._toptooth:

            ball3.physicsBody?.categoryBitMask = topteethcategory

            ball3.physicsBody?.collisionBitMask = topteethphysics

            ball3.physicsBody?.contactTestBitMask = topteethcolisionreport

        case type._bottomtooth:

            ball3.physicsBody?.categoryBitMask = bottomteethcategory

            ball3.physicsBody?.collisionBitMask = bottomteethphysics

            ball3.physicsBody?.contactTestBitMask = bottomteethcollisionreport

        case type._ball:

            ball3.physicsBody?.categoryBitMask = ballcategory

            ball3.physicsBody?.collisionBitMask = ballphysics

            ball3.physicsBody?.contactTestBitMask = ballcollisionreport

        case type._boundary:

            ball3.physicsBody?.categoryBitMask = boundriesgroup

            ball3.physicsBody?.collisionBitMask = boundriesphysics

            ball3.physicsBody?.contactTestBitMask = boundriescollisionreport

        case type._line:

            ball3.physicsBody?.categoryBitMask = linegroup

            ball3.physicsBody?.collisionBitMask = linecollisionphysics

            ball3.physicsBody?.contactTestBitMask = linecollisionreport

        case type._none:

            ball3.position = CGPointMake(100000, 10000)

        }

        

        switch (green)

        {

        case type._toptooth:

            ball4.physicsBody?.categoryBitMask = topteethcategory

            ball4.physicsBody?.collisionBitMask = topteethphysics

            ball4.physicsBody?.contactTestBitMask = topteethcolisionreport

        case type._bottomtooth:

            ball4.physicsBody?.categoryBitMask = bottomteethcategory

            ball4.physicsBody?.collisionBitMask = bottomteethphysics

            ball4.physicsBody?.contactTestBitMask = bottomteethcollisionreport

        case type._ball:

            ball4.physicsBody?.categoryBitMask = ballcategory

            ball4.physicsBody?.collisionBitMask = ballphysics

            ball4.physicsBody?.contactTestBitMask = ballcollisionreport

        case type._boundary:

            ball4.physicsBody?.categoryBitMask = boundriesgroup

            ball4.physicsBody?.collisionBitMask = boundriesphysics

            ball4.physicsBody?.contactTestBitMask = boundriescollisionreport

        case type._line:

            ball4.physicsBody?.categoryBitMask = linegroup

            ball4.physicsBody?.collisionBitMask = linecollisionphysics

            ball4.physicsBody?.contactTestBitMask = linecollisionreport

        case type._none:

            ball4.position = CGPointMake(100000, 10000)

        }

        

        

        

        physicsWorld.gravity = CGVector(dx: 0, dy: 0)

    }

    

 

    override func update(currentTime: CFTimeInterval) {

        /* Called before each frame is rendered */

    }

}

 

//nothing set they collide to eachother

//contactTestbitmask has nothing to do with bumping against eachother

//Category is the most important it gives it a type

//The other two decide when reactions happen, either physical or in code

//Collision bitmask is a list of groups that it actually should collide with

//Contacttestbitmask is list of groups that can trigger the code

1 个答案:

答案 0 :(得分:0)

我已经弄明白了!我的问题是我把事情弄得太复杂了。我实际上并不需要所有这些组!这就是我做的!

var stage:UInt32 = (0x1 << 1)
var player:UInt32 = (0x1 << 2)
var sensors:UInt32 = (0x1 << 3)

//Physics collision bitmask
var p_stage:UInt32 = 0
var p_player:UInt32 = 0 | stage
var p_sensors:UInt32 = 0

//Test bitmask
var t_stage:UInt32 = stage
var t_player:UInt32 = stage
var t_sensors:UInt32 = stage

我实际上并不需要像我想的那样多的团队!但是我确实必须在节点名称中存储一些数据,以便告诉它是从顶部还是底部或哪一行,但总体来说它工作得很棒!

谢谢那些看过一切的人,这真的意味着很多!

我发现奇怪的是做了

(0x1 << 1)
(0x1 << 2)
(0x1 << 3)

更好
1
2
3

我想我真的不知道我在做什么(0x1&lt;&lt; 1),但是我在其他地方看到并复制了它!