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

时间:2015-09-21 21:51:15

标签: sprite-kit swift2 xcode7

在下面的代码中,'英雄'从关卡开始。当它在地图上移动时,地图外部的黑色区域变得可见。当英雄走到墙上他停下来。但是,如果我触摸水平线以外的黑色区域,英雄会跳过墙壁并进入水平区域外。此外,有时当英雄接触墙壁时,他会以相反的方向反弹。 (我并不确定是什么导致了这一点。)我想要做的就是将英雄保持在关卡中,并停止有时发生的反弹。

我不确定问题是否我没有正确地进行碰撞,或者我是否需要以某种方式阻止黑色区域完全可见。我认为停止展示级别之外的区域是我需要的,但是使用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

1 个答案:

答案 0 :(得分:1)

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

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

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

然后,修改didBeginContact方法以在发生联系时删除操作,我希望这会成为您想要的:

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