2015-07-10 1 views
1

У меня проблема с моими врагами. Я сделал 5 из них, и каждый из них выходит на сцену независимо друг от друга. Но дело в том, что они почти одинаковы, кроме взглядов. Им нравится появляться в группах, один на другой, потому что у них есть один случайный механизм для каждого. Я попытался использовать SKConstraint, чтобы сделать промежуток между ними, но он не работает для меня.Можно ли использовать какой-то контейнерный узел вместо SKSpriteNode для обозначения врагов?

Итак, я подумал о другом подходе: я хочу использовать что-то, как пустой узел, чтобы представлять врага, прежде чем он появится на сцене (они похожи на нижние трубы в птице птицы, идущей с правой стороны влево). И прежде чем они появятся на экране, я хочу, чтобы моя игра случайным образом выбирала между 5 узлами и выполняла правильную анимацию. Из-за этого моя групповая проблема будет решена.

Как я мог это сделать?

Теперь я использую их узел. Я предоставить код, если это поможет:

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

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

тогда я применяю physicBodies им

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)) 

И в функции обновления У меня есть функция, которая перемещает их:

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

Я дважды читал ваш вопрос и до сих пор не знаю, чего вы пытаетесь достичь. Вы пытаетесь перемещать врагов в формации или создавать их случайно на экране и перемещать их по отдельности? – Whirlwind

+0

Создайте пустой/прозрачный SKSpriteNode. – sangony

+0

@Whirlwind К настоящему моменту моя программа порождает 5 разных врагов, 5 разных узлов. Я хочу, чтобы он породил только 1 врага, вы знаете, как скелет. И я хочу, чтобы он выбирал из 5 узлов, например, из пяти скинов, и клал один на этот скелет. Например, подумайте о автозаводе. Сначала автомобиль не имеет цвета. И есть пять разных цветов, чтобы нарисовать этот автомобиль. Я хочу, чтобы он случайным образом выбирал этот цвет и рисовал его. Имеет ли это смысл? – TimurTest

ответ

2

Я думаю, что вы усложнять ненужными или я до сих пор недоразумений вам :(но вот некоторые предложения Если вам просто нужно порождать случайных врагов, вы можете выбрать между несколькими способами:.

1. Создание пользовательских класс Robot

вы можете сделать класс под названием Robot и выбрать другую текстуру случайным образом. Для достижения рандомизации текстуры (от текстуры атласа или массив текстур), вы можете использовать arc4random() метод.

Пример использования (псевдо Колорадо де): класс

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

робота в этом случае будет подкласс SKSpriteNode и вы можете инициализировать его с текстурой через конструктор (как в примере выше), или вы можете переместить все, что текстуру выбора логики внутри конструктора (INIT метод). Тебе решать.

Пример использования:

Robot.init()

Вся логика называется внутри метода инициализации, который вызывает initWithTexture метод SKSpriteNode в

Если вам действительно нужно, что робот имеет скелет и кожу, и вы можете Не используйте единую текстуру для каждого типа робота, тогда вы можете сделать класс Robot, который является подклассом SKNode (пустой контейнер).

В этом случае класс робота должен иметь две переменные: скелет SKSpriteNode и скин SKSpriteNode. В этом случае переменная кожи будет выбрана случайным образом. Скелет и узлы кожи должны быть добавлены как дети к себе (я в этом случае - класс роботов, который является SKNode). SKNode не имеет визуального представления, но имеет свойство position, поэтому, когда вы перемещаете SKNode, вы также перемещаете его детей.

2. Использование SKSpriteNode

Если вы решили не иметь класс роботов, и просто использовать SKSpriteNode, история та же. Я бы пошел с другой текстурой для каждого типа врагов, но если это невозможно, вы можете использовать несколько SKSpriteNodes для каждого робота.

Итак, вы должны сделать метод, который вернет врага, который является SKSpriteNode. Внутри этого метода вы создадите SKSpriteNode с текстурой скелета, а после этого вы добавите скин в качестве дочернего элемента, установите zPosition для слоя выше, чем zPosition скелета, создайте физический объект и верните этот узел.

одна полезная вещь (если вам просто нужно изменить цвет спрайта) является то, что вы можете легко colorize nodes programatically (раскрасить текстуры)

EDIT:

Простой пример использования последовательности действий по икре враги после случайного периода времени:

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 папку с несколькими различными текстурами и скопировать & вставьте этот код, чтобы попробовать. Надеюсь это немного поможет.

+0

Человек, вот такие большие советы! Спасибо за вашу работу, я бы хотел отметить это как лучший ответ несколько раз! Я думаю, что я поеду с вашим вторым предложением на данный момент, но благодаря этому ответу у меня всегда есть план резервного копирования сейчас :) – TimurTest

+0

Прошу просить вас снова, но, возможно, вы знаете ответ.Что, если я буду использовать обычные SKSpriteNodes, как вы сказали? Все, что я хочу, это оставить пространство между моими врагами. Но моя случайная функция решает, должен ли он запускать другого врага на сцену по времени, прошедшего с момента запуска этого противника в прошлый раз. И я думаю, было бы лучше, если бы это решило это со временем, которое прошло с запуска ЛЮБОГО врага. Я обновил свой вопрос, может быть, это можно сделать так? – TimurTest

+0

@TimurTest Вы пытались породить врагов с помощью последовательности действий, как предложено (один за другим)? Вместо вашего класса вы можете начинать нерестовую последовательность с помощью ключа, удаляя его, когда это необходимо. Я не могу помочь вам с вашим быстрым кодом, потому что сейчас я использую только Obj-C. – Whirlwind

Смежные вопросы