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.
Invasor
ClaseInvasor
ClaseSeleccionar 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 SKSpriteNode
clase. 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 eso
Mé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 Invasor
la 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..
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 Invasor
, tempInvader
, 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 invasor
es 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 2, deberías ver 4 filas de 5 invasores alineados en el medio de la escena.
Jugador
ClaseJugador
ClaseCrear un nuevo Clase de Cocoa Touch llamado Jugador
eso 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-en
bucle 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..
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 jugador
es 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 escena
marco 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.
Bala
Las clasesBala
claseCrear 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 Bool
, waitForCompletion
. 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.
InvaderBullet
ClaseCrear 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..
PlayerBullet
ClaseCrear 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)
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..