我可以使用某种容器节点而不是SKSpriteNode来表示敌人吗?

时间:2015-07-10 07:09:21

标签: sprite-kit skspritenode

我的敌人有问题。我制作了5个,每个人都独立于另一个场景。但事情是 - 除了外观,它们几乎相同。他们喜欢分组,一个在另一个,因为他们有一个随机的耳朵机制为每个人。  我试图用SKConstraint来弥补它们之间的差距,但它并不适合我。

所以我想到了不同的方法:我想使用一些东西,比如一个空节点来表示敌人在它出现在场景之前(它们就像从右侧到左侧的飞扬鸟的下部管道)。在它们出现在屏幕上之前,我希望我的游戏能够在它们的5个节点之间随机选择并执行正确的动画。因此,我的小组出现的问题将得到解决。

我怎么能这样做?

现在我使用他们的节点。如果有帮助,我会提供代码:

var robot = SKSpriteNode()
let robotAtlas = SKTextureAtlas(named: "robot")
var robotArray = [SKTexture]()

robotArray.append(robotAtlas.textureNamed("robot0"));
robotArray.append(robotAtlas.textureNamed("robot1"));

然后我将物理实体应用于他们

robot = SKSpriteNode(texture: robotArray[0]);
robot.position = CGPointMake(CGRectGetMaxX(self.frame), CGRectGetMidY(self.frame) - 138)
self.robot.name = "robot"
self.addChild(robot)

我该怎么做?或者还有其他方法可以做到这一点?

目前,这是我的计划: 这是随机函数:

func random() -> UInt32 {
var range = UInt32(60)..<UInt32(200)
return range.startIndex + arc4random_uniform(range.endIndex - range.startIndex + 1)}

我有一个外观的自定义类:

class EnemyAppear {
var nowAppear = false
var waitToAppear = UInt32(0)
var currentInterval = UInt32(0)
init(nowAppear:Bool, waitToAppear:UInt32, currentInterval:UInt32) {
self.nowAppear = nowAppear
self.waitToAppear = waitToAppear
self.currentInterval = currentInterval  }


func shouldRun() -> Bool {
return self.appearInterval > self.waitToAppear  }

然后我有一个跟踪敌人的状态:

var enemyStatus:Dictionary<String,EnemyAppear> = [:]


enemyStatus["robot"] = EnemyAppear(nowAppear: false, waitToAppear: random(), currentInterval: UInt32(0))
enemyStatus["drone"] = EnemyAppear(nowAppear: false, waitToAppear: random(), currentInterval: UInt32(0))

在Update函数中,我有移动它们的函数:

func enemyRun() {
    for(enemy, enemyAppear) in self.enemyStatus {
    var thisPet = self.childNodeWithName(enemy)!
        if enemyAppear.shouldRun() {
            enemyAppear.waitToAppear = random()
            enemyAppear.currentInterval = 0
            enemyAppear.nowAppear = true
        }

        if enemyAppear.nowAppear {
            if thisPet.position.x > petMaxX {
                thisPet.position.x -= CGFloat(self.groundSpeed)
            }else {
                thisPet.position.x = self.originalPetPositionX
                enemyAppear.nowAppear = false
                self.score++
                self.scoreText.text = String(self.score)
            }
        }
    }

我只需要设定敌人之间的距离。

1 个答案:

答案 0 :(得分:2)

我认为你使事情变得复杂化或者我仍然误解你:(但这里有一些建议。如果你只是需要产生随机敌人,你可以选择以下几种方式:

<强> 1。制作自定义机器人类

您可以创建一个名为Robot的类,并随机选择不同的纹理。要完成随机化纹理(从纹理图集或纹理数组),您可以使用arc4random()方法。

使用示例(伪代码):

Robot.init(texture:someRandomTexture) //note that texture is a type of SKTexture, it's not a string

在这种情况下,Robot类是SKSpriteNode的子类,您可以通过构造函数(如上面的示例)使用纹理对其进行初始化,或者您可以在构造函数(init方法)中移动所有纹理选择逻辑。这取决于你。

使用示例:

Robot.init()

整个逻辑在init方法中调用,该方法调用SKSpriteNode的initWithTexture方法

如果你真的需要你的机器人有一个骨架和一个皮肤,你不能为每种类型的机器人使用单一纹理,那么你可以制作Robot类,它是SKNode的子类(空容器)。

在这种情况下,Robot类应该有两个变量,SKSpriteNode骨架和SKSpriteNode皮肤。在这种情况下,皮肤变量将随机选择。应该将骷髅和皮肤节点作为子项添加到self(在这种情况下,self是Robot类,即SKNode)。 SKNode没有可视化表示,但它具有位置属性,因此当您移动SKNode时,您也会移动其子项。

<强> 2。使用SKSpriteNode

如果您决定不使用Robot类,并且只使用SKSpriteNode,那么故事就是一样的。我会为每种类型的敌人使用不同的纹理,但如果这不可管理,你可以为每个机器人使用多个SKSpriteNodes。

所以,你应该制作一个返回敌人的方法,即SKSpriteNode。在该方法中,您将创建具有骨架纹理的SKSpriteNode,之后您将添加皮肤作为子项,将皮肤的zPosition设置为高于骨架的zPosition,创建物理体并返回该节点。

一个有用的东西(如果你只需要更改精灵的颜色)是你可以轻松地colorize nodes programatically(着色纹理)

修改

使用动作序列在随机持续时间后产生敌人的简单示例:

import SpriteKit

class GameScene: SKScene {

    var enemies: NSMutableArray = []
    var textures = [SKTexture]()

    let debugLabel = SKLabelNode(fontNamed: "Arial-BoldMT")

    override func didMoveToView(view: SKView) {

        /* Setup your scene here */

        debugLabel.fontColor = SKColor.purpleColor()
        debugLabel.fontSize = 20.0
        debugLabel.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(debugLabel)


        let atlas = SKTextureAtlas(named: "enemies")

        //Fill the array with textures to use them later
        //Not needed IMO, but suitable to show you how to pick a random element from an array
        for var i = 1; i<=atlas.textureNames.count; i++ {

            textures.append(atlas.textureNamed( "enemy\(i)"))

        }


         debugLabel.text = "Enemies count : \(enemies.count), Nodes count : \(self.children.count)"

        spawnEnemiesWithDelay(3)

    }


    //This method is just for creating a sprite
    func createRandomEnemy() ->SKSpriteNode{

        let rand = Int(arc4random_uniform(UInt32(textures.count)))

        let enemy =  SKSpriteNode(texture: textures[rand])

        //setup here enemy physics body

        return enemy

    }

    //This method spawns enemies after random period of time. You can stop this by removing an action key
    func spawnEnemiesWithDelay(delay: NSTimeInterval){



        let delay = SKAction.waitForDuration(delay, withRange:3) //The duration may vary in either direction by up to half of the value of the durationRange parameter. Which means duration can vary either plus or minus 1.5 sec



        let block = SKAction.runBlock({

            let enemy = self.createRandomEnemy()

            enemy.position = CGPoint(x: self.frame.size.width+enemy.size.width/2, y:100)

            self.addChild(enemy)

            self.enemies.addObject(enemy) // Store reference to enemy if needed

            let move = SKAction.moveTo(CGPoint(x: -enemy.size.width/2, y: 100), duration: 5)

            let moveAndRemove = SKAction.sequence([move, SKAction.runBlock({
                enemy.removeFromParent()


                self.enemies.removeObjectIdenticalTo(enemy as AnyObject)

            })]) //remove enemy when offscreen



            enemy.runAction(moveAndRemove, withKey: "moving")

        })

        let sequence = SKAction.sequence([delay,block])

        self.runAction(SKAction.repeatActionForever( sequence), withKey: "spawning")

    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */

       debugLabel.text = "Enemies count : \(enemies.count), Nodes count : \(self.children.count)"

    }
}

如果您的场景和视图已正确初始化,您可以制作具有少量不同纹理的enemies.atlas文件夹,并复制并粘贴此代码以进行尝试。希望这有点帮助。