Advertisement
  1. Code
  2. SpriteKit
Code

Bases de SpriteKit: Nodos

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called SpriteKit Basics.
Introducing SpriteKit
SpriteKit Basics: Sprites

Spanish (Español) translation by Javier Salesi (you can also view the original English article)

SpriteKit es el motor de juegos 2D de Apple-un motor de renderizado construído teniendo como base OpenGL. Fue introducido con iOS 7, y cada liberación subsecuente ha traído magníficas adiciones al framework. Con el uso de sprites texturizados, una motor de física integrado, y la muy poderosa clase SKAction, puedes construir muy rápidamente juegos 2D funcionales.

SpriteKit tiene editores integrados para escenas y partículas, un nodo de cámara desde la liberación de iOS9, y soporte integrado para conjunto de azulejos desde la liberación de iOS10. Con éstas nuevas adiciones, SpriteKit rápidamente se está convirtiendo en una potencia para crear juegos 2D.

Para seguir éste tutorial, solo descarga el complementario repositorio en Github. Tiene un directorio llamado ExampleProject Starter. Abre el proyecto en ese directorio en Xcode, y ¡estás listo para empezar!

Nodos

Los nodos son los bloques de construcción fundamentales de SpriteKit, y SKNode es la clase base de todos los nodos. Todos los recursos en pantalla serán un SKNode o una subclase de ello. Sin embargo, SKNodes por sí mismos no proporcionan ningún contenido visual. Todo el contenido visual es dibujado usando una de un número predefinido de subclases SKNode. SKNodes y sus subclases comparten varias propiedades que puedes alterar. Algunas de las más importantes son las siguientes.

  • position (CGPoint): la posición del nodo dentro del sistema de coordenadas de su padre
  • XScale (CGFloat): escala la anchura de un nodo por un multiplicador
  • yScale (CGFloat): escala la altura de un nodo por un multiplicador
  • alpha (CGFloat): la transparencia del nodo
  • zRotation (CGFloat): la rotación de Euler sobre el eje z (en radianes)

Uno de los más importantes SKNodes es el SKScene. Éste es el nodo raíz al cual otros nodos son añadidos. Por sí mismo, SKScene no proporciona ningún elemento visual, pero muestra los nodos que son añadidos a él.

Nodos de Escena

SKScenes son los nodos raíz a los cuales otros nodos son agregados. La escena anima y renderiza el contenido de sus nodos hijo. Para visualizar una escena, la agregas a un SKView (que es una subclase de UIView y por lo tanto tiene muchas de las mismas propiedades que UIView).

En el proyecto inicial de SpriteKit, la escena inicial está mostrando cuando el proyecto se carga. Por ahora, ésta es solo una pantalla negra. Es mostrada cuando el GameViewController invoca presentScene(_:) en la instancia de la vista, pasando la escena como parámetro:

No te preocupes por las otras opciones por ahora; las explicaré más adelante en ésta serie.

Creando una Escena

Muchos juegos tienen más de una pantalla o escena, así que crearemos una nueva escena desde cero y luego las mostramos desde nuestra escena inicial.

Selecciona File > New > File del menú de Xcode, y elige Cocoa Touch Class.

Choose the Cocoa Touch Class template

Asegúrate de que Class esté establecida en NewScene y que Subclass of esté establecido en SKScene. Presiona Next y luego Create, asegurándote de que esté marcado el objetivo principal. Abajo está el código para NewScene.swift.

Ahora tenemos dos escenas en nuestro proyecto, y ninguna tiene algún contenido visual. Agreguemos un SKLabelNode (como todos los nodos, ésta es una subclase de SKNode). El único propósito de SKLabelNode es desplegar una etiqueta de texto.

Nodos de Etiqueta

Nodos de etiqueta, implementados en la clase SKLabelNode, son usados para mostrar texto dentro de tu juego. Puedes usar fuentes personalizadas si quieres, pero para nuestros propósitos solo nos apegaremos a lo predeterminado, que muestra texto blanco y está establecido en Helvetica Neue Ultra Light, 32 point.

Agrega lo siguiente dentro del método didMove(to:) dentro de GameScene.swift. Éste método es llamado inmediatamente después de que una escena es presentada por una vista. Generalmente, aquí es donde establecerías cualquiera de los recursos de tu juego y los agregarías a la escena.

Aquí creamos un SKLabelNode usando el inicializador de conveniencia init(text:), que toma como parámetro una cadena de texto.

Agregando y Eliminando Nodos

Solo inicializando nodos no los mostrará en la escena. Para que se muestren los nodos, tienes que invocar el método addChild(_:) en el nodo receptor, pasando el SKNode que quieres agregar como parámetro.

Agrega lo siguiente dentro del método didMove(to:).

El método addChild(_:) no es exclusivo a SKScene, pero es un método de SKNode. Ésto te permite construir una compleja jerarquía de nodos-conocida como el "arbol de nodos". Por ejemplo, supongamos que tienes un personaje de juego y querías mover sus brazos y piernas por separado. Podrías crear una instancia de SKNode y luego agragar cada parte individual como un hijo de ese SKNode (el nodo contenedor también se conoce como el nodo padre). Ésto te daría el beneficio de poder mover el personaje como una unidad completa al mover el SKNode padre, pero también te permite mover individualmente cada parte individual.

Otro método importante para añadir nodos es el método insertChild(_:at:), que inserta un hijo en una posición específica dentro de la lista de hijos del nodo receptor. Cuando agregas un hijo a un nodo, el nodo mantiene una lista ordenada de hijos que es referenciada al leer la propiedad children del nodo. Es importante cuando se agrega múltiples nodos a un nodo padre tomar ésto en consideración, pues el orden en el que agregas los nodos afecta a algunos de los aspectos del procesamiento de la escena, incluyendo pruebas de golpe y renderizado.

Para eliminar un nodo, invocas el método removeFromParent() en el nodo que quieres eliminar.

Ahora que hemos cubierto agregar y eliminar nodos, podemos concentrarnos de nuevo en el proyecto de ejemplo. Si recuerdas, acababamos de agregar un SKLabelNode a GameScene. Si pruebas ahora, verás solo la mitad del texto en la parte inferior izquierda de la pantalla.

Test showing blank screen with text half off to the bottom left of the screen

¿Por qué solo se muestra la mitad del texto? Ahora sería un buen momento para hablar sobre el sistema de coordenadas y posiconamiento de SpriteKit.

Posicionamiento y Coordenadas

Por defecto, el sistema de coordenadas de SpriteKit coloca (0,0) en la parte inferior de la pantalla. También por defecto, SpriteKit coloca nodos para que estén posicionados en (0,0). Aunque, todavía... ¿por qué solo vemos la mitad del texto? Ésto es porque por defecto la etiqueta de texto es centrada horizontalmente en el origen del nodo de la etiqueta, que es (0,0). Abajo está una imagen que muestra cómo funciona el sistema de coordenadas del nodo.

A nodes x and y coordinates

Los orígenes del nodo están en (0,0), y una coordenada x positiva se mueve hacia la derecha y una coordinada y positiva se va arriba en la pantalla. Recuerda que un SKScene es un nodo, y por lo tanto su origen también es (0,0).

Estableciendo la Posición de un Nodo

Ahora que hemos aprendido como funciona el sistema de coordenadas de SpriteKit y cómo coloca nodos, podemos mover el SKLabelNode hacia una posición diferente para que podamos ver todo el texto. Agrega lo siguiente al método didMove(to:) dentro de GameScene.swift.

Aquí colocamos la etiqueta en el centro de la escena. La propiedad position es de tipo CGPoint, que tiene valores x y y que representan un solo punto dentro de la escena.

Si pruebas ahora, deberías ver que la etiqueta ha sido colocada en el centro de la escena.

Test with label positioned in centre of screen

Cambiando Entre Escenas

Como actualmente está, NewScene es solo una escena en blanco. Agreguemos también una etiqueta a ella, y luego podemos aprender cómo cambiar entre escenas. Aquí está un desafío: antes de que continúes leyendo, trata de agregar una etiqueta a NewScene que diga, "Go Back" (Regresa). Mi solución está abajo.

Lo primero que necesitamos hacer es agregar el método didMove(to:). Agrega lo siguiente a NewScene.swift.

A continuación, necesitamos agregar la etiqueta. Agrega lo siguiente dentro del método didMove(to:) que agregaste arriba.

Ésto agrega una etiqueta a NewScene con el texto "Go Back". En seguida, implementaremos la funcionalidad que ésta etiqueta sugiere-responderemos a eventos táctiles al cambiar escenas.

Respondiendo a Eventos Táctiles

Casi todos los juegos de móviles tendrán interacción con el uso de eventos táctiles. En éste paso, aprenderás cómo responder a eventos táctiles dentro de tu juego.

Para registrar manejadores de evento táctil dentro de tu juego, debes implementar el método touchesBegan(_:with:) de la vista. Agrega lo siguiente a GameScene.swift:

Si quieres probar ésto ahora, verás YOU TOUCHED impreso en la consola cuando tocas la pantalla. Sin embargo, lo que generalmente necesitamos, es poder decir cuando un nodo específico ha sido tocado. Para hacer ésto, necesitamos alguna manera de encontra e identificar los nodos. Aprenderemos cómo lograr ésto, y luego regresa y termina el método touchesBegan(_:with:).

Buscando el Árbol de los Nodos

Para poder identificar un nodo, usa la propiedad name del nodo y la búsqueda de un nodo en el árbol de los nodos con ese nombre. La propiedad name del nodo toma una cadena alfanumérica sin ninguna puntuación.

Hay un par de métodos para buscar un nodo por la propiedad de su name. Si ya tienes una referencia para el nodo, puedes solo verificar directamente su propiedad name, que es lo que haremos en el método touchesBegan(_:with:). Sin embargo, es importante saber cómo buscar un particular nodo por nombre en el árbol de los nodos, o buscar un grupo de nodos con el mismo nombre.

El método childNode(withName:) busca los hijos de un nodo por el nombre específico pasado como un parámetro.

El método enumerateChildNodes(withName:using:) busca los hijos de un nodo y llama al bloque una vez por cada nodo coincidente que encuentra. Usa éste método cuando quieras encontrar todos los nodos que comparten el mismo nombre.

El método subscript(_:) regresa un arreglo de nodos que coinciden con el parámetro del nombre.

También puedes buscar nodos usando una sintaxis de búsqueda avanzada que te permite buscar por todo el árbol de la escena, o buscar un patrón más bien que un nombre exacto, por ejemplo. Ésta capacidad de búsqueda avanzada está más allá del alcance de éste tutorial. Sin embargo, si quieres aprender más, puedes leer sobre ello en la referencia de programación SKNode.

Ahora que sabemos cómo buscar nodos dentro del árbol de nodos, demos a nuestras etiquetas un nombre.

Agrega lo siguiente dentro del método didMove(to:) dentro de GameScene.swift.

Aquí, establecemos la propiedad del nombre de startGameLabel en startgame.

También necesitamos establecer el nombre de la etiqueta dentro de NewScene. Agrega lo siguiente con el método didMove(to:) dentro de NewScene.swift.

Establecemos la propiedad name en goback.

Detectando Cuál Nodo Es Tocado

Agrega lo siguiente dentro del método touchesBegan(_:with:) dentro de GameScene.swift.

La propiedad multiTouchEnable de la vista de la escena es establecida en false por defecto, lo que significa que la vista únicamente recibe el primer toque de una secuencia multitoque. Con ésta propiedad deshabilitada, puedes recuperar el toque al usar la propiedad computada first del conjunto de toques, ya que hay sólamente un objeto en el conjunto.

Podemos obtener la touchLocation dentro de la escena de la propiedad location del toque. Podemos luega descubrir cuál nodo fue tocado al invocar atPoint(_:) y pasar la touchLocation.

Verificamos si la propiedad del nombre de tocheNode es igual a "startgame", y si lo es, sabemos que el usuario ha tocado la etiqueta. Luego creamos una instancia de NewScene y establecemos su propiedad scalemode para que sea igual a la escena actual-ésto asegura que la escena actúe igual en diferentes dispositivos. Finalmente, creamos un SKTransition e invocamos el método presentScene(_:transition:), que presentará la escena junto con la transición.

La clase SKTransition tiene muchos métodos de clase que puedes invocar para mostrar diferentes transiciones entre escenas en lugar de mostrar inmediatamente la escena. Ésto proporciona un poco de "placer visual" para el usuario final, y hace que parezca menos abrupto el mostrar una nueva escena. Para ver todos los tipos de transición disponibles, consuta la clase SKTransition en la guía de referencia.

No voy a implementar el método touchesBegan(_:with:) en NewScene. ¿Por qué no tratas de hacer eso por tí mismo y regresas la transición de la etiqueta a GameScene usando un tipo de transición diferente? El código se asemejará mucho a lo que tenemos arriba, únicamente recuerda nombrar el SKLabelNode "goback".

Conclusión

Hemos aprendido un poco de nodos hasta ahora usando escenas, y has visto cómo usar un nodo de una etiqueta como un ejemplo genérico para aprender algunas de las características de nodos. Hemos estudiado sus sistemas de coordenadas, cómo localizarlas dentro del árbol de nodos, cómo colocarlas, y cómo responder a eventos táctiles.

Hay otras clases de nodos disponibles, y las veremos en el próximo tutorial-¡comenzando con SKSpriteNode!

Para aprender más sobre cómo comenzar con SpriteKit, deberías también consultar el artículo de Davis Allie aquí en Envato Tuts+.

También, ¡consulta nuestros cursos de SpriteKit! Éstos te guiarán por todos los pasos para crear tu primer juego SpriteKit para iOS, aún si nunca has programado antes con SpriteKit.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.