Spawn Balls随机摆脱屏幕

时间:2015-10-19 15:50:04

标签: swift sprite-kit swift2

我想从屏幕外面调出敌人(var enemis),无论是屏幕的顶部,底部,左侧还是右侧。而这些敌人在屏幕上有一个随机方向。目前,我的代码会在屏幕顶部,底部,左侧和右侧产生敌人,但只有一个方向,我想做一个随机的方向

var hasMatch = arr2.some(function (item) {
  return arr1.indexOf(item.id) > -1;
});

if (hasMatch) {
  doSomething();
}

对不起我的英语我是法国人

3 个答案:

答案 0 :(得分:2)

这只是一个例子,让您了解如何在随机位置产生敌人并随机移动它们。我没有广泛使用Swift,这更像是向您展示您可以走向哪个方向,以及如何解决问题。我留给你关心Swift 2语法:D另外,我目前正在使用过时的Swift版本,所以不确定什么对我有用,对你有用,但逻辑​​是一样的。

在这里,您将了解如何:

  • 生成一个节点并将其移动到屏幕的另一侧
  • 将节点移动到屏幕另一侧的随机点
  • 随机化产卵持续时间
  • 沿着其中一个屏幕的边框创建一个随机点
  • 在两个数字之间创建一个随机数
  • 使用SKAction完成所有这些

这里重要的一件事是如何在封闭中使用强引用自我。因为我的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 )


    }
    */

}

结果如下:

spawning nodes

重要部分位于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中的动作移动节点时,您将它们从物理模拟中拉出来,如果您希望看到真实的物理模拟,则可能会出现意外行为。因此,只有在您对碰撞(或其他类型的物理模拟)不感兴趣时​​才使用动作,而只是在接触检测中。如果您还需要碰撞,请使用物理引擎并通过施加脉冲或力来移动节点。

希望这有帮助!

答案 1 :(得分:0)

非常感谢! 我制作了不同版本的代码,因为我在回答之前找到了解决方案

func CreationMeteorites(){

        let Meteorites = SKSpriteNode(imageNamed: "Meteroites.png")
        let choixDeCote = arc4random() % 4 + 1

        switch choixDeCote {

        case 1 : //Haut
            let MinValue = self.size.width / 8
            let MaxValue = self.size.width - 200
            SpawnX = UInt32(MaxValue - MinValue)
            SpawnX = arc4random_uniform(SpawnX)
            SpawnY = UInt32(self.size.height)
            directionX = Int(arc4random()) % Int(self.frame.size.width)
            directionY = 0
            action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 4)
            break

        case 2 ://Bas
            let MinValue = self.size.width / 8
            let MaxValue = self.size.width - 200
            SpawnX = UInt32(MaxValue - MinValue)
            SpawnX = arc4random_uniform(SpawnX)
            SpawnY = 0
            directionX = Int(arc4random()) % Int(self.frame.size.width)
            directionY = Int(self.frame.size.height)
            action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 4)
            break

        case 3 : //Gauche
            let MinValue = self.size.height / 8
            let MaxValue = self.size.height - 200
            SpawnX = 0
            SpawnY = UInt32(MaxValue - MinValue)
            SpawnY = arc4random_uniform(SpawnY)
            directionY = Int(arc4random()) % Int(self.frame.size.height)
            directionX = Int(self.frame.size.width)
            action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 3)
            break

        case 4 ://Droite
            let MinValue = self.size.height / 8
            let MaxValue = self.size.height - 200
            SpawnX = UInt32(self.size.width)
            SpawnY = UInt32(MaxValue - MinValue)
            SpawnY = arc4random_uniform(SpawnY)
            directionY = Int(arc4random()) % Int(self.frame.size.height)
            directionX = 0
            action = SKAction.moveTo(CGPoint(x: CGFloat(directionX),y: CGFloat(directionY)),duration: 3)
            break

        default :
            break
        }

        //Positioner les météorites

        Meteorites.position = CGPoint(x: CGFloat(SpawnX), y: CGFloat(SpawnY))
        Meteorites.setScale(4)
        Meteorites.physicsBody = SKPhysicsBody(circleOfRadius: 30)
        Meteorites.physicsBody?.affectedByGravity = false
        Meteorites.physicsBody?.dynamic = true
        Meteorites.physicsBody?.categoryBitMask = PhysicsCategories.Meteorites
        Meteorites.physicsBody?.contactTestBitMask = PhysicsCategories.Meteorites

        let actionFini = SKAction.removeFromParent()

        Meteorites.runAction(SKAction.sequence([action, actionFini]))
        Meteorites.runAction(SKAction.repeatActionForever(action))

        self.addChild(Meteorites)
    }

关于碰撞,你知道一个有很好解释的教程,因为我不了解如何进行碰撞。

答案 2 :(得分:0)

对于有兴趣在GameScene内部的目标C中执行此操作的任何人:

-(void) randomSpawnPosition{
    NSUInteger randPos = arc4random_uniform(4);
    CGPoint spawnPosition;
    CGFloat randFloatX = arc4random_uniform(self.frame.size.width + 10);
    CGFloat randFloatY = arc4random_uniform(self.frame.size.height + 10);

    switch (randPos) {
            //top
        case 1:
            spawnPosition = CGPointMake(randFloatX, self.frame.size.height+10);
            break;
            //bottom
        case 2:
            spawnPosition = CGPointMake(randFloatX, 0-10);
            break;
            //left
        case 3:
            spawnPosition = CGPointMake(0 - 10, randFloatY);
            break;
            //right
        case 4:
            spawnPosition = CGPointMake(self.frame.size.width + 10, randFloatY);
            break;
    }
    [self addEnemy:spawnPosition];
}