Crea Space Invaders con Swift y Sprite Kit implementando clases

Lo que vas a crear

En la primera parte de esta serie, exploramos los conceptos básicos del marco del Sprite Kit e implementamos la pantalla de inicio del juego. En este tutorial, implementaremos las principales clases del juego..

Swift es un lenguaje orientado a objetos y lo aprovecharemos al separar todas las entidades del juego en sus propias clases. Empezaremos por implementar el Invasor clase.

1. Implementando el Invasor Clase

Paso 1: Crea el Invasor Clase

Seleccionar Nuevo > Expediente…  de Xcode's Expediente menú, elegir Clase de Cocoa Touch desde el iOS> Fuente sección, y haga clic en Siguiente. Nombra la clase Invasor y asegúrese de que hereda de SKSpriteNode. Asegúrate de eso Idioma se establece en Rápido. Ingrese el siguiente código en Invader.swift.

importar UIKit importar SpriteKit clase Invader: SKSpriteNode var invaderRow = 0 var invaderColumn = 0 init () let texture = SKTexture (imageNamed: "invader1") super.init (textura: textura, color: SKColor.clearColor (), tamaño: texture.size ()) self.name = "invader" required init? (coder aDecoder: NSCoder) super.init (coder: aDecoder) func fireBullet (scene: SKScene) 

los Invasor clase es una subclase de la SKSpriteNodeclase. Tiene dos propiedades, invaderRow y Columna invasora. Los invasores se alinean en una cuadrícula al igual que en el juego original de Space Invaders. Las dos propiedades nos proporcionan una forma fácil de realizar un seguimiento de las filas y columnas en las que se encuentra el invasor..

En el en esoMétodo, inicializamos un SKTexture ejemplo. los init (imageNamed :) El método toma una imagen como parámetro. Luego invocamos el inicializador de la superclase, pasando en la textura, SKColor.clearColor Para el color parámetro, y para el tamaño Parámetro que pasamos en el tamaño de la textura. Finalmente, fijamos el nombre a "invasor" para que podamos identificarlo más tarde.

los en eso El método es un inicializador designado, lo que significa que debemos delegar la inicialización a un inicializador designado del Invasorla superclase. Por eso invocamos el init (textura: color: tamaño :) método.

Usted se estará preguntando por qué el requerido init (codificador :) El método está ahí también. los SKSpriteNode se ajusta a la NSCoding protocolo. los init (codificador :) El método se marca como requerido, lo que significa que cada subclase debe anular este método..

Implementaremos el FireBullet Método más adelante en este tutorial..

Paso 2: añadir invasores a la escena

En este paso, añadiremos los invasores a la GameScene. Abierto GameScene.swift y borra todo dentro de la didMoveToView (_ :) método, así como todo dentro de la TocaBegan (_: conEvento :) método. Los contenidos de GameScene.swift ahora debería verse así.

importar SpriteKit class GameScene: SKScene override func didMoveToView (ver: SKView)  override func touchesBegan (toques: Establecer, Evento withEvent: UIEvent) / * Llamado cuando comienza un toque * / anular actualización de func (currentTime: CFTimeInterval) / * Llamado antes de que se renderice cada cuadro * /

Tendremos una variable global en nuestro proyecto., invasorNum. Esta variable se utiliza para realizar un seguimiento del nivel actual del juego. Al declararlo como una variable global, tenemos acceso a invasorNum a través de escenas Para declarar la variable como una variable global, la declaramos fuera de la GameScene clase.

importar SpriteKit var invaderNum = 1 clase GameScene: SKScene … 

A continuación, agregue las siguientes propiedades a la GameScene clase.

clase GameScene: SKScene let rowsOfInvaders = 4 var invaderSpeed ​​= 2 let leftBounds = CGFloat (30) var rightBounds = CGFloat (0) var invadersWhoCanFire: [Invader] = [] override func didMoveToView (ver: SKView) 

los rowsOfInvaders propiedad es cuántas filas de invasores tendrá el juego y la invaderSpeed la propiedad es lo rápido que se moverán los invasores. los Límite izquierdo y a la derecha las propiedades se utilizan para crear un margen en el lado izquierdo y derecho de la pantalla, restringiendo el movimiento de los invasores en las direcciones izquierda y derecha. Y finalmente, el InvadersWhoCanFire La propiedad es una matriz que se utiliza para realizar un seguimiento de qué invasores pueden disparar una bala.

Añade el setupInvaders método debajo del actualizar (currentTime :) método en el GameScene clase.

func setupInvaders () var invaderRow = 0; var invaderColumn = 0; deje numberOfInvaders = invaderNum * 2 + 1 para var i = 1; yo <= rowsOfInvaders; i++  invaderRow = i for var j = 1; j <= numberOfInvaders; j++  invaderColumn = j let tempInvader:Invader = Invader() let invaderHalfWidth:CGFloat = tempInvader.size.width/2 let xPositionStart:CGFloat = size.width/2 - invaderHalfWidth - (CGFloat(invaderNum) * tempInvader.size.width) + CGFloat(10) tempInvader.position = CGPoint(x:xPositionStart + ((tempInvader.size.width+CGFloat(10))*(CGFloat(j-1))), y:CGFloat(self.size.height - CGFloat(i) * 46)) tempInvader.invaderRow = invaderRow tempInvader.invaderColumn = invaderColumn addChild(tempInvader) if(i == rowsOfInvaders) invadersWhoCanFire.append(tempInvader)     

Tenemos el invaderRow y Columna invasora variables que se utilizarán para establecer las propiedades del mismo nombre en el invasor. A continuación, utilizamos un doble. para bucle para disponer los invasores en la pantalla. Hay una gran cantidad de conversión de tipo numérico en marcha, porque swift no convierte números implícitamente al tipo apropiado. Debemos hacerlo nosotros mismos.

Primero instanciamos un nuevo InvasortempInvader, y luego declarar una constante InvaderHalfWidth eso es la mitad del tamaño de tempInvader.

A continuación, calculamos la xPositionStart para que los invasores siempre estén alineados en el medio de la escena. Obtenemos la mitad del ancho de la escena y restamos la mitad del ancho del invasor ya que el punto de registro predeterminado es el centro (0.5, 0.5) del sprite. Entonces debemos restar el ancho de los tiempos de invasor sin embargo mucho invasorNum es igual a, y agrega 10 a ese valor, ya que hay 10 puntos de espacio entre los invasores. Esto puede ser un poco difícil de comprender al principio, así que tómate tu tiempo para entenderlo.

Luego fijamos el invasores posición propiedad, que es un GGPoint. Usamos un poco más de matemáticas para asegurarnos de que cada invasor tenga 10 puntos de espacio entre ellos y que cada fila tenga 46 puntos de espacio entre ellos..

Asignamos el invaderRow y Columna invasora propiedades, y agregar el tempInvader a la escena con el addChild (_ :) método. Si esta es la última fila de invasores, ponemos la tempInvader en el InvadersWhoCanFire formación.

los setupInvaders método se invoca en el didMoveToView (_ :) método. En este método, también establecemos la color de fondo propiedad a SKColor.blackColor.

 función de reemplazo didMoveToView (ver: SKView) backgroundColor = SKColor.blackColor () setupInvaders ()

Si prueba la aplicación, debería ver 4 filas de 3 invasores. Si te pones invasorNum a 2deberías ver 4 filas de 5 invasores alineados en el medio de la escena.

2. Implementando el Jugador Clase

Paso 1: Crea el Jugador Clase

Crear un nuevo Clase de Cocoa Touch llamado Jugadoreso es una subclase de SKSpriteNode. Agregue la siguiente implementación a Jugador..

importar UIKit importar clase SpriteKit Player: SKSpriteNode init () let texture = SKTexture (imageNamed: "player1") super.init (texture: texture, color: SKColor.clearColor (), tamaño: texture.size ()) animate ( ) required init? (coder aDecoder: NSCoder) super.init (coder: aDecoder) private func animate () var playerTextures: [SKTexture] = [] para i en 1 ... 2 playerTextures.append (SKTexture (imageNamed : "player \ (i)")) let playerAnimation = SKAction.repeatActionForever (SKAction.animateWithTextures (playerTextures, timePerFrame: 0.1)) self.runAction (playerAnimation) func die ()  func kill () ) func respawn ()  func fireBullet (scene: SKScene)  

los en eso El método debe parecer familiar. La única diferencia es que estamos usando una imagen diferente para la configuración inicial. Hay dos imágenes nombradas Jugador 1 y jugador2 en la carpeta de imágenes, uno tiene el propulsor activado y el otro tiene el propulsor apagado. Cambiaremos constantemente entre estas dos imágenes, creando la ilusión de que un propulsor dispara y apaga. Esto es lo que el animar método hace.

En el animar método, tenemos una matriz PlayerTextures Eso contendrá las texturas para la animación. Añadimos el SKTexture objetos a esta matriz mediante el uso de una para-enbucle y un rango cerrado utilizando el operador de rango cerrado. Utilizamos la interpolación de cadenas para obtener la imagen correcta e inicializar una SKTexture ejemplo.

Declaramos una constante, jugadorAnimacion, que invoca al repetir acción para siempre método de la SKAcción clase. En esa acción, invocamos. animateWithTextures (_: timePerFrame :). los animateWithTextures (_: timePerFrame :) El método toma como parámetros una matriz de texturas y la cantidad de tiempo que se muestra cada textura. Por último, invocamos runAction (_ :) y pasar en el jugadorAnimacion.

Los otros métodos se implementarán más adelante en este tutorial..

Paso 2: Agregar el jugador a la escena

Declara una propiedad constante llamada jugador al GameScene clase.

clase GameScene: SKScene … var invadersWhoCanFire: [Invader] = [Invader] () dejar jugador: Player = Player ()

A continuación, agregue el setupPlayer método debajo del setupInvaders método.

func setupPlayer () player.position = CGPoint (x: CGRectGetMidX (self.frame), y: player.size.height / 2 + 10) addChild (player)

Debe estar familiarizado con la implementación de la setupPlayer método. Establecemos el jugadores posición Y añádelo a la escena. Sin embargo, estamos utilizando una nueva función., CGRectGetMidX (_ :), que devuelve el centro de un rectángulo a lo largo del eje x. Aquí usamos el escenamarco de.

Ahora puedes invocar el setupPlayer método en el didMoveToView (_ :) método.

 anular func didMoveToView (ver: SKView) backgroundColor = SKColor.blackColor () setupInvaders () setupPlayer () 

Si prueba la aplicación, debería ver el jugador agregado a la parte inferior de la pantalla con los propulsores activados y disparando.

3. Implementando el Bala Las clases

Paso 1: Crea el Bala clase

Crear un nuevo Clase de Cocoa Touch llamado Bala eso es una subclase de la SKSpriteNode clase.

importar UIKit importar clase SpriteKit Bullet: SKSpriteNode init (imageName: String, bulletSound: String?) let texture = SKTexture (imageNamed: imageName) super.init (texture: texture, color: SKColor.clearColor (), size: texture. size ()) if (bulletSound! = nil) runAction (SKAction.playSoundFileNamed (bulletSound!, waitForCompletion: false)) requerido init? (codificador aDecoder: NSCoder) super.init (coder: aDecoder)

los en eso método toma dos parámetros, Nombre de la imágen y bulletSound. El segundo parámetro es opcional. El jugador reproducirá un sonido láser cada vez que se dispare una bala. No tengo a los invasores haciendo eso en este juego, aunque ciertamente podrías. Esa es también la razón por la que el sonido de bala es un parámetro opcional. Incluso podrías usar un sonido diferente para cada uno..

La primera parte debe ser familiar, aunque ahora estamos creando el textura Con cualquier imagen que se haya pasado como primer argumento. Esto te permitirá usar diferentes imágenes para el jugador y las balas de los invasores si quisieras.

Si bulletSound no es nulo, corremos un SKAcción método playSoundFileNamed (_: waitForCompletion :). Este método toma como parámetros una Cuerda, que es el nombre del archivo de sonido que incluye la extensión, y una BoolwaitForCompletion. los waitForCompletion El parámetro no es importante para nosotros. Si estuviera configurado para cierto, entonces la acción duraría por mucho tiempo el archivo de sonido es.

Paso 2: Crea el InvaderBullet Clase

Crear un nuevo Clase de Cocoa Touch llamado InvaderBullet eso es una subclase de la Bala clase.

importar UIKit importar clase SpriteKit InvaderBullet: Bullet override init (imageName: String, bulletSound: String?) super.init (imageName: imageName, bulletSound: bulletSound) requerido init? (codificador aDecoder: NSCoder) super.init (codificador) : aDecoder)

La implementación de la InvaderBullet La clase puede no tener mucho sentido, porque solo llamamos al init (imageName: bulletSound :) Método de la superclase en el init (imageName: bulletSound :) inicializador Sin embargo, tendrá mucho más sentido por qué se configura de esta manera cuando agregamos código para la detección de colisiones..

Paso 3: Crea el PlayerBullet Clase

Crear un nuevo Clase de Cocoa Touch llamado PlayerBullet que también es una subclase de la Bala clase. Como se puede ver, la implementación de la PlayerBullet clase es idéntica a la de la InvaderBullet clase.

importar UIKit importar clase SpriteKit PlayerBullet: Bullet override init (imageName: String, bulletSound: String?) super.init (imageName: imageName, bulletSound: bulletSound) required init? (coder aDecoder: NSCoder) super.init (coder : aDecoder)

Conclusión

En este tutorial, creamos e implementamos algunas de las clases clave del juego. Agregamos una cuadrícula de invasores a la escena y la nave espacial que el jugador controlará. Continuaremos trabajando con estas clases en la siguiente parte de esta serie en la que implementamos el juego..