Swift Jump方法碰撞物体和地面

Posted

技术标签:

【中文标题】Swift Jump方法碰撞物体和地面【英文标题】:Swift Jump Method Collision object and ground 【发布时间】:2015-09-02 13:12:43 【问题描述】:

我正在开发一款 iPhone 游戏。基本上如果英雄遇到障碍就放弃了。现在我想为我的英雄添加跳跃能力。但是当我使用“physicsBody = SKPhysicsBody(rectangleOfSize: size)”作为地面时,一旦游戏开始并且英雄出现在地面上“func didBeginContact(contact:SKPhysicsContact) 游戏结束() " 方法使游戏结束。这是我对英雄、地面和游戏场景的实现。你们能帮我让英雄跳跃并降落在地面上吗。提前谢谢。

//  AKHero.swift
//  Run Hero

  import Foundation
  import SpriteKit
  class AKHero: SKSpriteNode

var body:SKSpriteNode!
var arm: SKSpriteNode!
var leftFoot: SKSpriteNode!
var rightFoot: SKSpriteNode!
var leftpupil: SKSpriteNode!
var rightpupil: SKSpriteNode!

var isUpsideDown = false

init()
    let size = CGSizeMake(35, 45)
    super.init(texture: nil, color: UIColor.clearColor(), size: size)

    loadAppearance()
    loadPhysicsBoadyWithsize(size)



   func loadPhysicsBoadyWithsize(size: CGSize)

    physicsBody = SKPhysicsBody(rectangleOfSize: size)

    physicsBody?.categoryBitMask = heroCategory
    physicsBody?.contactTestBitMask = obstacleCategory
    physicsBody?.usesPreciseCollisionDetection = true
    physicsBody?.affectedByGravity = false



   func jump()

    self.physicsBody?.applyImpulse(CGVectorMake(0, 15))
    physicsBody?.affectedByGravity = true



//  GameScene.swift
//  Run Hero

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate 

var movingGround: AKMovingGround!
var hero: AKHero!
var cloudGenerator: AKCloudGenerator!
var obstacleGenerator: AKObstacleGenerator!
var coinGenerator: AKCoinGenerator!
var isStarted = false
var isGameOver = false

override func didMoveToView(view: SKView) 
    backgroundColor = UIColor(red: 159.0/255.0, green: 201.0/255.0 ,       blue: 244.0/255.0 , alpha: 1.0)

 func addMovingGround()
     movingGround = AKMovingGround(size: CGSizeMake(view!.frame.width, kAKGroundHeight))
    movingGround.position = CGPointMake(0, view!.frame.size.height/2)
    addChild(movingGround)



//add hero
func addHero()
    hero = AKHero()
    hero.position = CGPointMake(70, movingGround.position.y + movingGround.frame.size.height/2 + hero.frame.size.height/2)
    addChild(hero)
    hero.breathe()

func addPhysicsWorld() 
    physicsWorld.contactDelegate = self


override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 

    if isGameOver 

        restart()
    

    else if !isStarted 

        start()

    
    else
       hero.flipHero()
      //hero.jump()

    



// MARK: - SKPhysicsContactDelegate
func didBeginContact(contact: SKPhysicsContact) 

    if !isGameOver
    println("didBeginContact")
    gameOver()
    

//
//  AKMovingGround.swift
//  Run Hero
//
//  Created by Alican Karamil on 24/08/15.
//  Copyright (c) 2015 Alican Karamil. All rights reserved.
//

import Foundation
import SpriteKit
class AKMovingGround: SKSpriteNode

    let NUMBER_OF_SEGMENTS = 20
    let COLOR_ONE = UIColor(red: 88.0/255.0, green: 148.0/255, blue: 87.0/255.0, alpha: 1.0)
    let COLOR_TWO = UIColor(red: 120.0/255.0, green:195.0/255.0, blue: 118.0/255.0, alpha: 1.0)

    init (size: CGSize)
        super.init(texture: nil, color: UIColor.brownColor(), size: CGSizeMake(size.width*2, size.height))
        anchorPoint = CGPointMake(0, 1.5)
        //anchorPoint = CGPointMake(0, 0.5)

        for var i = 0; i < NUMBER_OF_SEGMENTS; i++ 
            var segmentColor: UIColor!
            if i % 2 == 0
            segmentColor=COLOR_ONE
            else
            segmentColor=COLOR_TWO
            
            let segment = SKSpriteNode(color: segmentColor, size: CGSizeMake(self.size.width/CGFloat(NUMBER_OF_SEGMENTS), self.size.height))
            segment.anchorPoint = CGPointMake(0.0, 0.5)
            segment.position = CGPointMake(CGFloat(i)*segment.size.width, 0)
            addChild(segment)
        

    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    


    func start()
        let moveleft = SKAction.moveByX(-frame.size.width/2, y: 0, duration: 1.0)
        let resetPosition = SKAction.moveToX(0, duration: 0.0)
        let moveSequence = SKAction.sequence([moveleft, resetPosition])
        //runAction(moveSequence, completion: nil)
        runAction(SKAction.repeatActionForever(moveSequence))

    

    func stop()

    removeAllActions()
   


 

【问题讨论】:

你应该在 didBeginContact 中加入一些条件逻辑。现在,如果游戏开始,您的英雄会触及场景边界,并且会调用 didBeginContact 并导致游戏结束。在 didBeginContact 中,您应该定义触摸什么结束了游戏,什么没有结束。 【参考方案1】:

您的问题是 didBeginContact() 尚未分配特定联系人,因此任何联系人都会被渲染到该函数中,包括玩家和地面之间的联系人。

要解决此问题,您必须创建特定的 categoryBitMask。有关这方面的更多信息,请查看Apple Docs。完成后,您需要在播放器上指定要检测碰撞的 categoryBitMask。这样,如果它撞到地面,什么都不会发生,但如果它撞到障碍物,游戏就结束了。为此,您必须指定玩家的physicsBody?.categoryBitMask,然后设置其physicsBody?.contactTestBitMaskphysicsBody?.collisionBitMask

didBeginContact() 中,使用 if 语句指定要查找的联系人。试试看this Youtube video 是否对您有帮助。或者this one。

【讨论】:

以上是关于Swift Jump方法碰撞物体和地面的主要内容,如果未能解决你的问题,请参考以下文章

unity3D中,给物体添加刚体后,为啥不是掉在地面上,而是穿过地形一直往下落呢?

unity - 两个具有刚体的物体如何相互穿过?

unity3d中如何检测车轮是不是接触地面?

unity3d 中的模型加了重力之后就会穿过地面往下掉,我模型和地面都加了碰撞啊,没有选择trigger

为啥用unity 3d做的物体添加Rigidbody属性,并设置重力运行后直接穿过地面,而不是停在地面上?

unity3d怎么添加碰撞体