这只是一个示例,让您了解如何在随机位置生成敌人并沿随机方向移动它们。我没有广泛使用 Swift,这更像是向您展示您可以往哪个方向发展,以及如何解决问题。我留给你关心 Swift 2 语法 :D 另外,我目前使用的是过时的 Swift 版本,所以不确定什么对我有用,对你有用,但逻辑是一样的。
在这里您将看到如何做:
- 生成一个节点并将其移动到屏幕的另一侧
- 将节点移动到屏幕另一侧的随机点
- 随机生成持续时间
- 沿屏幕边框之一创建一个随机点
- 在两个数字之间创建一个随机数
- 使用 SKAction 完成所有这些操作
这里重要的一件事是如何在闭包中使用对 self 的强引用。因为我的 Swift 版本,正如我所说,对我有用的,可能对你不起作用,但逻辑是一样的。如果有兴趣,请在此处阅读有关强参考周期的更多信息:
这是一个代码示例:
import SpriteKit
class GameScene:SKScene, SKPhysicsContactDelegate{
override func didMoveToView(view: SKView) {
self.physicsWorld.contactDelegate = self
createEnemies()
}
deinit{
print("deinit called")
}
func randomBetweenNumbers(firstNum: CGFloat, secondNum: CGFloat) -> CGFloat{
return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(firstNum - secondNum) + min(firstNum, secondNum)
}
//Helper method for spawning a point along the screen borders. This will not work for diagonal lines.
func randomPointBetween(start:CGPoint, end:CGPoint)->CGPoint{
return CGPoint(x: randomBetweenNumbers(start.x, secondNum: end.x), y: randomBetweenNumbers(start.y, secondNum: end.y))
}
func createEnemies(){
//Randomize spawning time.
//This will create a node every 0.5 +/- 0.1 seconds, means between 0.4 and 0.6 sec
let wait = SKAction .waitForDuration(0.5, withRange: 0.2)
weak var weakSelf = self //Use weakSelf to break a possible strong reference cycle
let spawn = SKAction.runBlock({
var random = arc4random() % 4 + 1
var position = CGPoint()
var moveTo = CGPoint()
var offset:CGFloat = 40
println(random)
switch random {
//Top
case 1:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: weakSelf!.frame.height), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x:weakSelf!.frame.width, y:0))
break
//Bottom
case 2:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x: weakSelf!.frame.width, y: 0))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: weakSelf!.frame.height), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
break
//Left
case 3:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: weakSelf!.frame.width, y: 0), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
break
//Right
case 4:
position = weakSelf!.randomPointBetween(CGPoint(x: weakSelf!.frame.width, y: 0), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: weakSelf!.frame.height))
break
default:
break
}
weakSelf!.spawnEnemyAtPosition(position, moveTo: moveTo)
})
let spawning = SKAction.sequence([wait,spawn])
self.runAction(SKAction.repeatActionForever(spawning), withKey:"spawning")
}
func spawnEnemyAtPosition(position:CGPoint, moveTo:CGPoint){
let enemy = SKSpriteNode(color: SKColor.brownColor(), size: CGSize(width: 40, height: 40))
enemy.position = position
enemy.physicsBody = SKPhysicsBody(rectangleOfSize: enemy.size)
enemy.physicsBody?.affectedByGravity = false
enemy.physicsBody?.dynamic = true
enemy.physicsBody?.collisionBitMask = 0 // no collisions
//Here you can randomize the value of duration parameter to change the speed of a node
let move = SKAction.moveTo(moveTo,duration: 2.5)
let remove = SKAction.removeFromParent()
enemy.runAction(SKAction.sequence([move, remove]))
self.addChild(enemy)
}
func didBeginContact(contact: SKPhysicsContact) {
}
/*
Added for debugging purposes
override func touchesBegan(touches: NSSet, withEvent event: UIEvent?) {
//Just make a transition to the other scene, in order to check if deinit is called
//You have to make a new scene ... I named it WelcomeScene
var scene:WelcomeScene = WelcomeScene(fileNamed: "WelcomeScene.sks")
scene.scaleMode = .AspectFill
self.view?.presentScene(scene )
}
*/
}
结果如下:
重要部分位于createEnemies()方法中:
//Top
case 1:
position = weakSelf!.randomPointBetween(CGPoint(x: 0, y: weakSelf!.frame.height), end: CGPoint(x: weakSelf!.frame.width, y: weakSelf!.frame.height))
//Move to opposite side
moveTo = weakSelf!.randomPointBetween(CGPoint(x: 0, y: 0), end: CGPoint(x:weakSelf!.frame.width, y:0))
break
您可以在此处定义生成位置,该位置可以是顶部边框上的任何点。或者更准确地说,在顶部边界上方一点点。节点在屏幕外生成。接下来,您创建(随机化)一个您想要移动节点的点,与生成位置相比,这是相反的一侧。因此,这可以是底部边界上的任何随机点。
如果你想停止产卵,你会这样做:
if(self.actionForKey("spawning") != nil){
self.removeActionForKey("spawning")
}
关于您的物理体设置...请注意,我已将节点的 collisionBitMask 设置为 0。
enemy.physicsBody?.collisionBitMask = 0 // no collisions
在 SpriteKit 中通过动作移动节点时,您会将它们从物理模拟中拉出来,如果您希望看到逼真的物理模拟,您可能会得到意想不到的行为。因此,仅当您对碰撞(或其他类型的物理模拟)不感兴趣时才使用动作,而只是对接触检测感兴趣。如果您还需要碰撞,请使用物理引擎并通过施加脉冲或力来移动节点。
希望这会有所帮助!