英雄在与他们相撞后跳过墙壁

Hero jumps over walls after colliding with them

在下面的代码中,'hero' 从关卡内部开始。当它在地图上移动时,地图外的黑色区域变得可见。当英雄走到墙边时,他停了下来。但是,如果我触摸关卡外的黑色区域,英雄就会跳过墙进入关卡外区域。此外,有时当英雄接触墙壁时,他会朝相反的方向反弹。 (我不太确定是什么原因造成的。)我想做的是让英雄保持在关卡内,并停止有时会发生的反弹。

我不确定问题是我没有正确进行碰撞,还是我需要以某种方式阻止黑色区域完全可见。我认为阻止关卡外的区域显示是我需要的,但是玩 let scene = GameScene(size: view.bounds.size) 并将其更改为 let scene = GameScene(size: tileMap.frame.size) 没有用。这是我的代码:

import SpriteKit

let tileMap = JSTileMap(named: "level2.tmx")
let hero = SKSpriteNode(imageNamed: "hero")
let theCamera: SKCameraNode = SKCameraNode()

class GameScene: SKScene, SKPhysicsContactDelegate {

    enum ColliderType: UInt32 {

        case Hero = 1
        case Wall = 2

    }


    override func didMoveToView(view: SKView) {

        self.physicsWorld.contactDelegate = self

       self.anchorPoint = CGPoint(x: 0, y: 0)
       self.position = CGPoint(x: 0, y: 0)

        hero.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))

        hero.xScale = 0.5
        hero.yScale = 0.5
        hero.zPosition = 2

        hero.physicsBody = SKPhysicsBody(circleOfRadius: hero.size.height / 2)
        hero.physicsBody?.affectedByGravity = false
        hero.physicsBody!.dynamic = true
        hero.physicsBody!.categoryBitMask = ColliderType.Hero.rawValue
        hero.physicsBody!.contactTestBitMask = ColliderType.Wall.rawValue
        hero.physicsBody!.collisionBitMask = ColliderType.Wall.rawValue


        tileMap.zPosition = 1


        tileMap.position = CGPoint(x: 0, y: 0)
        self.addChild(tileMap)
        self.addChild(hero)
        self.addChild(theCamera)

        self.camera = theCamera

        camera?.position = hero.position

        addWalls()


    }

    func didBeginContact(contact: SKPhysicsContact) {

        print("Hero made contact with a wall")

    }


    func addWalls() {
        //Go through every point up the tile map
        for var a = 0; a < Int(tileMap.mapSize.width); a++ {
            //Go through every point across the tile map
            for var b = 0; b < Int(tileMap.mapSize.height); b++ {
                //Get the first layer (you may want to pick another layer if you don't want to use the first one on the tile map)
                let layerInfo:TMXLayerInfo = tileMap.layers[1] as! TMXLayerInfo
                //Create a point with a and b
                let point = CGPoint(x: a, y: b)
                //The gID is the ID of the tile. They start at 1 up the the amount of tiles in your tile set.
                let gid = layerInfo.layer.tileGidAt(layerInfo.layer.pointForCoord(point))

                //My gIDs for the floor were 2, 9 and 8 so I checked for those values
                if gid == 1 {
                    //I fetched a node at that point created by JSTileMap
                    let node = layerInfo.layer.tileAtCoord(point)
                    //I added a physics body
                    node.physicsBody = SKPhysicsBody(rectangleOfSize: node.frame.size)
                    node.physicsBody?.dynamic = false

                    node.physicsBody!.categoryBitMask = ColliderType.Wall.rawValue
                    node.physicsBody!.contactTestBitMask = ColliderType.Hero.rawValue
                    node.physicsBody!.collisionBitMask = ColliderType.Wall.rawValue

                }
            }
        }
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
       /* Called when a touch begins */

        for touch in touches {

            let location = touch.locationInNode(self)

            let action = SKAction.moveTo(location, duration: 1)

            hero.runAction(action)


        }

            }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */


        let action = SKAction.moveTo(hero.position, duration: 0.25)
        theCamera.runAction(action)
    }
}

我的 TMX 文件:

<?xml version="1.0" encoding="UTF-8"?>
<map version="1.0" orientation="orthogonal" renderorder="right-down" width="24" height="42" tilewidth="32" tileheight="32" nextobjectid="13">
 <tileset firstgid="1" name="grass-tiles-2-small" tilewidth="32" tileheight="32" tilecount="72">
  <image source="grass-tiles-2-small.png" trans="ff00ff" width="384" height="192"/>
 </tileset>
 <layer name="Tile Layer 1" width="24" height="42">
  <data encoding="base64" compression="zlib">
   eJztzLEJAAAMw7Bs/f/jXhHIIINXJf2uNJ/P5/P5fD6fz+fz+Ut+swfI8xgR
  </data>
 </layer>
 <layer name="Walls" width="24" height="42">
  <data encoding="base64" compression="zlib">
   eJztzLEJAAAMw7Dk/6d7RaCDDF7VJB2/is/n8/l8Pp/P5/P5/E/+8gMA/ACB
  </data>
 </layer>
</map>

这里有英雄触墙弹跳和翻墙的视频Video of app sim

当节点和物理体之间发生接触时,SpriteKit 只会检测到接触,而不会像我们在日常生活中遇到障碍物那样负责停止节点的动作。所以你需要手动停止它。

让我们为 heroSKAction 添加一个键值,以区分移动动作与将来可能添加的其他动作:

hero.runAction(action, withKey: "move")

然后,修改didBeginContact方法,去掉接触发生时的动作,希望这会如你所愿:

func didBeginContact(contact: SKPhysicsContact) {
    print("Hero made contact with a wall")
    // Stop your hero
    hero.removeActionForKey("move")
}