【问题标题】:SpriteKit - Border on all sides except bottom and topSpriteKit - 除底部和顶部外的所有边的边框
【发布时间】:2017-12-05 14:18:27
【问题描述】:

我有一个主玩家节点和随机下来的敌人,但他们中的一部分在框架之外,我想让他们(和玩家)无法离开框架、左右边界。我怎样才能做到这一点?

感谢您的时间和精力:)

这是我的敌对线,不知道这有什么帮助,但它就在这里,所以我不会因为“太宽泛”而被举报

 func launchEnemy() {

    let randomX = arc4random_uniform( UInt32(screenWidth))

    EnemyMissile.position = CGPoint(  x: CGFloat(randomX)  - (screenWidth / 2), y: screenHeight + 50)


    let action = SKAction.move(by: CGVector(dx: 0, dy: -400 + speedScore), duration: 5.0)


   EnemyMissile.run(SKAction.repeatForever(action))        

     increaseSpeed()


    self.run(action, withKey:"LaunchEnemyAction")
}  

这是我的EnemyClass

     import Foundation
     import SpriteKit

class EnemyClass: SKNode {

var EnemyNode:SKSpriteNode = SKSpriteNode()

var hitsToKill:Int = 2
var hitCount:Int = 0
var damagePoints: Int = 2

//var missileAnimation:SKAction?

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) had not been implemented")

}

override init () {

    super.init()

}



    func createEnemy ( _ theImage:String) {


EnemyNode = SKSpriteNode(imageNamed: theImage)
self.addChild(EnemyNode)

let body:SKPhysicsBody = SKPhysicsBody(circleOfRadius: EnemyNode.size.width / 2.25, center:CGPoint(x: 0,y: 0))
body.isDynamic = true
body.affectedByGravity = false
body.allowsRotation = false


  body.categoryBitMask = BodyType.enemy.rawValue
  body.contactTestBitMask =  BodyType.bullet.rawValue |              BodyType.player.rawValue


self.physicsBody = body

self.name = "EnemyClass"

}

func destroy() {
   self.removeFromParent()
   self.name = "removeNode"
}
func hit() -> Bool {

    hitCount += 1

    if ( hitCount == hitsToKill) {

        destroy()
        return true

    } else {
        damagePoints = 4

        EnemyNode.removeAction(forKey: "animation")
        return false
    }

}

}

【问题讨论】:

  • 您需要在这个问题上做更多的工作,尝试在可以获得特定答案的地方创建它。解释你做了什么并展示了一些工作,问题越彻底和简洁,答案就越好。在我投票决定关闭之前,我会给你一些时间来重做这个。
  • @Knight0fDragon 你是什么意思?没有要解决的特定“问题”,所以我不确定如何为我的问题提供更多信息或“工作”,而不是发布我的整个 GameScene,这在这种情况下是完全没有必要的。
  • 那你来错地方了。请参阅stackoverflow.com/tour 了解如何提出适合这种格式的问题。也许您的广泛问题最好在developer.apple.com/devforums 提出。
  • @Knight0fDragon 我知道我没有找错地方,因为我在这里问了一段时间的问题,我已经看到很多类似的问题,被“广泛”回答。所以先生,请原谅我,我正在等待有人可以帮助我解决我的无知。谢谢。
  • 这对我来说似乎不是一个 -2 问题@-@()

标签: swift sprite-kit 2d-games


【解决方案1】:

基本上你有两个问题:

  1. 你的生成点搞砸了
  2. 你没有边界

您有几个设置边界的选项,一个是physicsBody,另一个是keepInBounds() 方法等。下面我应该一个简单的保持边界方法:

class GameScene: SKScene {

  func spawnEnemy() {
    let offset = CGFloat(5) // pixels, so enemy will have some spacing between borders.

    let enemy = SKSpriteNode(color: .blue, size: CGSize(width: 50, height: 100))
    enemy.name = "enemy"
    addChild(enemy)

    var randomX = CGFloat(arc4random_uniform(UInt32(self.size.width))) // This is not a perfect rando algo.

    // Because our random x was from 0 through screenwidth, but .position works
    // on -halfWidth through +halfWidth
    randomX -= (self.frame.size.width / 2)

    // Because spawning on the border will mean that the enemy is HALF out of view:
    /*

     right border:       |
     enemy @ frame.maxX: x
     - offset:          x|
     - size.w/2        x |
     */
    if randomX > self.frame.maxX - offset - (enemy.size.width / 2) {
       randomX = self.frame.maxX - offset - (enemy.size.width / 2)
    }
    else if randomX < self.frame.minX + offset + (enemy.size.width / 2) {
            randomX = self.frame.minX + offset + (enemy.size.width / 2)
    }

    enemy.position.x = randomX
  }

  func keepEnemyInBounds() {
    // A better way to do this would be to have a dictionary of enemies:
    for node in self.children {
      guard node.name == "enemy" else { continue }
      let enemy = node as! SKSpriteNode

      if enemy.position.x > frame.maxX - (enemy.size.width / 2) {
        enemy.position.x = frame.maxX - (enemy.size.width / 2)
      }
      else if enemy.position.x < frame.minX + (enemy.size.width / 2) {
        enemy.position.x = frame.minX + (enemy.size.width / 2)
      }
    }
  }


  override func update(_ currentTime: TimeInterval) {
    spawnEnemy()
  }
  override func didFinishUpdate() {
    keepEnemyInBounds()
  }
}

【讨论】:

  • 感谢您的回复。这段代码对我不起作用,因为我的敌人被称为 EnemyMissile,它来自另一个名为 EnemyClass 的类,因此,当我插入“if randomX > self.frame.maxX - offset - (EnemyMissile. size.width / 2)..." 等等,它说'EnemyClass'类型的值没有成员'size'。我尝试在 EnemyClass 中引用 EnemyNode,但它不起作用。我怎样才能解决这个问题?
  • @GabrielsGalaxy 你必须使用敌人 spritenode 实例的任何属性。如果 EnemyMissile 是一个精灵,它应该可以工作。也许发布你的课程,让我看看?
  • @GabrielsGalaxy 哦等等,我的代码在你的 GameScene 中工作,而不是你的敌人类
  • @GabrielsGalaxy 好的,使用标准的 swift 命名,实例是 camelCase,你想要在我的代码中做的是'让敌人 =enemyMissile.enemyNode',它会工作
  • 太棒了!所以敌人现在正在边境上下来,但是有一个问题。太多了(十个和十个,而不是每隔几秒一两个)并且它们都没有像以前那样与播放器节点有任何联系,它们只是通过播放器。有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-13
  • 2023-02-21
  • 2019-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多