API de juegos de iOS en Xamarin.iOS
En este artículo se tratan las nuevas mejoras de juegos proporcionadas por iOS 9 que se pueden usar para mejorar las características de audio y gráficos del juego de Xamarin.iOS.
Apple ha realizado varias mejoras tecnológicas en las API de juegos en iOS 9 que facilitan la implementación de gráficos y audio de juegos en una aplicación xamarin.iOS. Entre ellas se incluye la facilidad de desarrollo a través de marcos de alto nivel y el aprovechamiento de la potencia de la GPU del dispositivo iOS para mejorar la velocidad y las capacidades gráficas.
Esto incluye Los sombreadores de rendimiento de MetalKit, ReplayKit, E/S de modelos, MetalKit y Metal, junto con características nuevas y mejoradas de Metal, SceneKit y SpriteKit.
En este artículo se presentan todas las formas de mejorar el juego de Xamarin.iOS con las nuevas mejoras de juegos de iOS 9:
Introducción aKit de juego
El nuevo marco DeiKit de Apple proporciona un conjunto de tecnologías que facilita la creación de juegos para dispositivos iOS mediante la reducción de la cantidad de código repetitivo y común necesario para la implementación. GameKit proporciona herramientas para desarrollar la mecánica del juego que luego se puede combinar fácilmente con un motor gráfico (como SceneKit o SpriteKit) para entregar rápidamente un juego completado.
GameKit incluye varios algoritmos de juego comunes, como:
- Una simulación de agente basada en el comportamiento que le permite definir movimientos y objetivos que la inteligencia artificial alcanzará automáticamente.
- Inteligencia artificial minmax para el juego basado en turnos.
- Un sistema de reglas para la lógica de juego controlada por datos con razonamientos aproximadas para proporcionar un comportamiento emergente.
Además, GameKit adopta un enfoque de bloque de creación para el desarrollo de juegos mediante una arquitectura modular que proporciona las siguientes características:
- Máquina de estados para controlar sistemas complejos basados en código de procedimientos en el juego.
- Herramientas para proporcionar juegos aleatorios e imprevisibilidad sin causar problemas de depuración.
- Arquitectura basada en entidades reutilizable y con componentes.
Para obtener más información sobre ElKit de juego, consulte guía de programación deKit de Juego de Apple y Referencia del marco de Trabajo deKit de Apple.
Ejemplos deKit de juego
Echemos un vistazo rápido a la implementación de algunos mecanismos de juego sencillos en una aplicación xamarin.iOS mediante el kit de juego.
Búsqueda de rutas de acceso
Pathfinding es la capacidad de que un elemento de inteligencia artificial de un juego se encuentre en el tablero de juego. Por ejemplo, un adversario en 2D que se encuentra a través de un mágico o un carácter 3D a través de un terreno del mundo en primera persona.
Tenga en cuenta el siguiente mapa:
El uso de pathfinding a este código de C# puede encontrar una manera a través del mapa:
var a = GKGraphNode2D.FromPoint (new Vector2 (0, 5));
var b = GKGraphNode2D.FromPoint (new Vector2 (3, 0));
var c = GKGraphNode2D.FromPoint (new Vector2 (2, 6));
var d = GKGraphNode2D.FromPoint (new Vector2 (4, 6));
var e = GKGraphNode2D.FromPoint (new Vector2 (6, 5));
var f = GKGraphNode2D.FromPoint (new Vector2 (6, 0));
a.AddConnections (new [] { b, c }, false);
b.AddConnections (new [] { e, f }, false);
c.AddConnections (new [] { d }, false);
d.AddConnections (new [] { e, f }, false);
var graph = GKGraph.FromNodes(new [] { a, b, c, d, e, f });
var a2e = graph.FindPath (a, e); // [ a, c, d, e ]
var a2f = graph.FindPath (a, f); // [ a, b, f ]
Console.WriteLine(String.Join ("->", (object[]) a2e));
Console.WriteLine(String.Join ("->", (object[]) a2f));
Sistema experto clásico
El siguiente fragmento de código de C# muestra cómo se puede usar ElKit de juego para implementar un sistema experto clásico:
string output = "";
bool reset = false;
int input = 15;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
/*
If reset is true, clear the output and set reset to false
*/
var clearRule = GKRule.FromPredicate ((rules) => reset, rules => {
output = "";
reset = false;
});
clearRule.Salience = 1;
var fizzRule = GKRule.FromPredicate (mod (3), rules => {
output += "fizz";
});
fizzRule.Salience = 2;
var buzzRule = GKRule.FromPredicate (mod (5), rules => {
output += "buzz";
});
buzzRule.Salience = 2;
/*
This *always* evaluates to true, but is higher Salience, so evaluates after lower-salience items
(which is counter-intuitive). Print the output, and reset (thus triggering "ResetRule" next time)
*/
var outputRule = GKRule.FromPredicate (rules => true, rules => {
System.Console.WriteLine(output == "" ? input.ToString() : output);
reset = true;
});
outputRule.Salience = 3;
var rs = new GKRuleSystem ();
rs.AddRules (new [] {
clearRule,
fizzRule,
buzzRule,
outputRule
});
for (input = 1; input < 16; input++) {
rs.Evaluate ();
rs.Reset ();
}
}
protected Func<GKRuleSystem, bool> mod(int m)
{
Func<GKRuleSystem,bool> partiallyApplied = (rs) => input % m == 0;
return partiallyApplied;
}
En función de un conjunto determinado de reglas ( ) y un conjunto conocido de entradas, el sistema experto ( ) creará una salida predecible GKRule ( para nuestro ejemplo GKRuleSystemfizzbuzz anterior).
Reuniéndose
La agrupación permite que un grupo de entidades de juego controladas por inteligencia artificial se comporte como un grupo, donde el grupo responde a los movimientos y acciones de una entidad principal, como un grupo de animales en vuelo o una escuela de piscándose.
El siguiente fragmento de código de C# implementa el comportamiento de la bandada mediante ElKit de juego y SpriteKit para la presentación de gráficos:
using System;
using SpriteKit;
using CoreGraphics;
using UIKit;
using GameplayKit;
using Foundation;
using System.Collections.Generic;
using System.Linq;
using OpenTK;
namespace FieldBehaviorExplorer
{
public static class FlockRandom
{
private static GKARC4RandomSource rand = new GKARC4RandomSource ();
static FlockRandom ()
{
rand.DropValues (769);
}
public static float NextUniform ()
{
return rand.GetNextUniform ();
}
}
public class FlockingScene : SKScene
{
List<Boid> boids = new List<Boid> ();
GKComponentSystem componentSystem;
GKAgent2D trackingAgent; //Tracks finger on screen
double lastUpdateTime = Double.NaN;
//Hold on to behavior so it doesn't get GC'ed
static GKBehavior flockingBehavior;
static GKGoal seekGoal;
public FlockingScene (CGSize size) : base (size)
{
AddRandomBoids (20);
var scale = 0.4f;
//Flocking system
componentSystem = new GKComponentSystem (typeof(GKAgent2D));
var behavior = DefineFlockingBehavior (boids.Select (boid => boid.Agent).ToArray<GKAgent2D>(), scale);
boids.ForEach (boid => {
boid.Agent.Behavior = behavior;
componentSystem.AddComponent(boid.Agent);
});
trackingAgent = new GKAgent2D ();
trackingAgent.Position = new Vector2 ((float) size.Width / 2.0f, (float) size.Height / 2.0f);
seekGoal = GKGoal.GetGoalToSeekAgent (trackingAgent);
}
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
boids.ForEach(boid => boid.Agent.Behavior.SetWeight(1.0f, seekGoal));
}
public override void TouchesEnded (NSSet touches, UIEvent evt)
{
boids.ForEach (boid => boid.Agent.Behavior.SetWeight (0.0f, seekGoal));
}
public override void TouchesMoved (NSSet touches, UIEvent evt)
{
var touch = (UITouch) touches.First();
var loc = touch.LocationInNode (this);
trackingAgent.Position = new Vector2((float) loc.X, (float) loc.Y);
}
private void AddRandomBoids (int count)
{
var scale = 0.4f;
for (var i = 0; i < count; i++) {
var b = new Boid (UIColor.Red, this.Size, scale);
boids.Add (b);
this.AddChild (b);
}
}
internal static GKBehavior DefineFlockingBehavior(GKAgent2D[] boidBrains, float scale)
{
if (flockingBehavior == null) {
var flockingGoals = new GKGoal[3];
flockingGoals [0] = GKGoal.GetGoalToSeparate (boidBrains, 100.0f * scale, (float)Math.PI * 8.0f);
flockingGoals [1] = GKGoal.GetGoalToAlign (boidBrains, 40.0f * scale, (float)Math.PI * 8.0f);
flockingGoals [2] = GKGoal.GetGoalToCohere (boidBrains, 40.0f * scale, (float)Math.PI * 8.0f);
flockingBehavior = new GKBehavior ();
flockingBehavior.SetWeight (25.0f, flockingGoals [0]);
flockingBehavior.SetWeight (10.0f, flockingGoals [1]);
flockingBehavior.SetWeight (10.0f, flockingGoals [2]);
}
return flockingBehavior;
}
public override void Update (double currentTime)
{
base.Update (currentTime);
if (Double.IsNaN(lastUpdateTime)) {
lastUpdateTime = currentTime;
}
var delta = currentTime - lastUpdateTime;
componentSystem.Update (delta);
}
}
public class Boid : SKNode, IGKAgentDelegate
{
public GKAgent2D Agent { get { return brains; } }
public SKShapeNode Sprite { get { return sprite; } }
class BoidSprite : SKShapeNode
{
public BoidSprite (UIColor color, float scale)
{
var rot = CGAffineTransform.MakeRotation((float) (Math.PI / 2.0f));
var path = new CGPath ();
path.MoveToPoint (rot, new CGPoint (10.0, 0.0));
path.AddLineToPoint (rot, new CGPoint (0.0, 30.0));
path.AddLineToPoint (rot, new CGPoint (10.0, 20.0));
path.AddLineToPoint (rot, new CGPoint (20.0, 30.0));
path.AddLineToPoint (rot, new CGPoint (10.0, 0.0));
path.CloseSubpath ();
this.SetScale (scale);
this.Path = path;
this.FillColor = color;
this.StrokeColor = UIColor.White;
}
}
private GKAgent2D brains;
private BoidSprite sprite;
private static int boidId = 0;
public Boid (UIColor color, CGSize size, float scale)
{
brains = BoidBrains (size, scale);
sprite = new BoidSprite (color, scale);
sprite.Position = new CGPoint(brains.Position.X, brains.Position.Y);
sprite.ZRotation = brains.Rotation;
sprite.Name = boidId++.ToString ();
brains.Delegate = this;
this.AddChild (sprite);
}
private GKAgent2D BoidBrains(CGSize size, float scale)
{
var brains = new GKAgent2D ();
var x = (float) (FlockRandom.NextUniform () * size.Width);
var y = (float) (FlockRandom.NextUniform () * size.Height);
brains.Position = new Vector2 (x, y);
brains.Rotation = (float)(FlockRandom.NextUniform () * Math.PI * 2.0);
brains.Radius = 30.0f * scale;
brains.MaxSpeed = 0.5f;
return brains;
}
[Export ("agentDidUpdate:")]
public void AgentDidUpdate (GameplayKit.GKAgent agent)
{
}
[Export ("agentWillUpdate:")]
public void AgentWillUpdate (GameplayKit.GKAgent agent)
{
var brainsIn = (GKAgent2D) agent;
sprite.Position = new CGPoint(brainsIn.Position.X, brainsIn.Position.Y);
sprite.ZRotation = brainsIn.Rotation;
Console.WriteLine ($"{sprite.Name} -> [{sprite.Position}], {sprite.ZRotation}");
}
}
}
A continuación, implemente esta escena en un controlador de vista:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
this.View = new SKView {
ShowsFPS = true,
ShowsNodeCount = true,
ShowsDrawCount = true
};
}
public override void ViewWillLayoutSubviews ()
{
base.ViewWillLayoutSubviews ();
var v = (SKView)View;
if (v.Scene == null) {
var scene = new FlockingScene (View.Bounds.Size);
scene.ScaleMode = SKSceneScaleMode.AspectFill;
v.PresentScene (scene);
}
}
Cuando se ejecuten, los pequeños "Boids" animados aparecerán alrededor de las pulsaciones de los dedos:
Otros ejemplos de Apple
Además de los ejemplos presentados anteriormente, Apple ha proporcionado las siguientes aplicaciones de ejemplo que se pueden transcodificar a C# y Xamarin.iOS:
- FourInARow: Uso del estratega Dekit Minmax para la inteligencia artificial fetichista
- AgentsCatalog: Uso del sistema de agentes enKit de juego
- DemoBots: Creación de un juego multiplataforma con SpriteKit y GameKit
Metal
En iOS 9, Apple ha realizado varios cambios y adiciones a Metal para proporcionar acceso de baja sobrecarga a la GPU. Con Metal puede maximizar el potencial de gráficos y computación de las aplicaciones iOS.
El marco metal incluye las siguientes características nuevas:
- Nuevas texturas de galería de símbolos privadas y de profundidad para OS X.
- Se ha mejorado la calidad de la sombra con fijación de profundidad y se han separado los valores de galería de símbolos frontal y posterior.
- Mejoras en el lenguaje de sombreado de metal y la biblioteca estándar de metal.
- Los sombreadores computacionales admiten una gama más amplia de formatos de píxel.
El marco metalkit
El marco MetalKit proporciona un conjunto de clases y características de utilidad que reducen la cantidad de trabajo necesario para usar Metal en una aplicación de iOS. MetalKit proporciona compatibilidad en tres áreas clave:
- Carga asincrónica de texturas desde diversos orígenes, incluidos formatos comunes como PNG, JPEG, KTX y PVR.
- Fácil acceso a los recursos basados en E/S del modelo para el control de modelos específicos de Metal. Estas características se han optimizado altamente para proporcionar una transferencia de datos eficaz entre mallas de E/S de modelo y búferes de metal.
- Vistas de metal predefinidas y administración de vistas que reducen en gran medida la cantidad de código necesario para mostrar representaciones gráficas dentro de una aplicación de iOS.
Para obtener más información sobre MetalKit, vea Referencia de MetalKit Frameworkde Apple, Guía de programación de metal,Referencia de Metal Framework y Guía del lenguaje de sombreado de metal de Apple.
Marco de sombreadores de rendimiento de metal
El marco de sombreador de rendimiento de metal proporciona un conjunto altamente optimizado de gráficos y sombreadores basados en cálculos para su uso en aplicaciones iOS basadas en Metal. Cada sombreador del marco de sombreador de rendimiento de metal se ha optimizado específicamente para proporcionar un alto rendimiento en GPU iOS compatibles con Metal.
Mediante el uso de clases de sombreador de rendimiento de metal, puede lograr el máximo rendimiento posible en cada GPU de iOS específica sin tener que tener como destino y mantener bases de código individuales. Los sombreadores de rendimiento de metal se pueden usar con cualquier recurso metal, como texturas y búferes.
El marco de sombreador de rendimiento de metal proporciona un conjunto de sombreadores comunes, como:
- Desenfoque gausiano ( )
- Detección de Sobel Edge ( )
- Histograma de imagen ( )
Para más información, consulte la Guía del lenguaje de sombreado de metal deApple.
Introducción a la E/S del modelo
El marco de E/S de modelos de Apple proporciona un conocimiento profundo de los recursos 3D (como modelos y sus recursos relacionados). La E/S de modelo proporciona a los juegos de iOS materiales físicos, modelos e iluminación que se pueden usar conKit de juego, metal y SceneKit.
Con E/S de modelo, puede admitir los siguientes tipos de tareas:
- Importe la iluminación, los materiales, los datos de malla, la configuración de la cámara y otra información basada en la escena de una variedad de formatos populares de software y motor de juegos.
- Procese o genere información basada en escena, como la creación de domos de cielo con textura de procedimientos o la iluminación de bake en una malla.
- Funciona con MetalKit, SceneKit y GLKit para cargar eficazmente los recursos del juego en búferes de GPU para su representación.
- Exportar información basada en escena a una variedad de formatos populares de software y motor de juegos.
Para más información sobre la E/S del modelo, consulte Referencia del marco de E/S de modelos de Apple.
Introducción a ReplayKit
El nuevo marco ReplayKit de Apple le permite agregar fácilmente la grabación del juego al juego de iOS y permitir al usuario editar y compartir este vídeo de forma rápida y sencilla desde la aplicación.
Para obtener más información, vea el vídeo going social de Apple con ReplayKit y Game Center y sus DemoBots: Building a Cross Platform Game with SpriteKit and GameKit sample app (DemostraBots: creación de un juego multiplataforma con SpriteKit y la aplicación de ejemplo DesenlazadorKit).
SceneKit
Scene Kit es una API de grafo de escena 3D que simplifica el trabajo con gráficos 3D. Se introdujo por primera vez en OS X 10.8 y ahora ha llegado a iOS 8. Con Scene Kit, crear visualizaciones 3D envolventes y juegos 3D ocasionales no requiere experiencia en OpenGL. A partir de los conceptos comunes del grafo de escena, Scene Kit abstrae las complejidades de OpenGL y OpenGL ES, lo que facilita mucho la adición de contenido 3D a una aplicación. Sin embargo, si es un experto en OpenGL, Scene Kit también tiene una gran compatibilidad para conectarse directamente con OpenGL. También incluye numerosas características que complementan gráficos 3D, como la física, y se integra muy bien con otros marcos de Apple, como Core Animation, Core Image y Sprite Kit.
Para más información, consulte nuestra documentación de SceneKit.
Cambios de SceneKit
Apple ha agregado las siguientes características nuevas a SceneKit para iOS 9:
- Xcode ahora proporciona un editor de escenas que permite crear rápidamente juegos y aplicaciones 3D interactivas mediante la edición de escenas directamente desde Xcode.
- Las
SCNViewclases y se pueden usar para habilitar la representación de MetalSCNSceneRenderer(en dispositivos iOS compatibles). - Las clases y se pueden usar para agregar efectos de audio espaciales que realicen un seguimiento automático de la posición
SCNAudioPlayerde un reproductor en una aplicaciónSCNNodeiOS.
Para obtener más información, consulte nuestra documentación de SceneKit y referencia del marco SceneKit de Apple y Fox: Building a SceneKit Game with the Xcode Scene Editor sample project (Fox: Building a SceneKit Game with the Xcode Scene Editor sample project).
SpriteKit
Sprite Kit, el marco de juego en 2D de Apple, tiene algunas características nuevas interesantes en iOS 8 y OS X Yosemite. Entre ellas se incluyen la integración con Scene Kit, la compatibilidad con sombreadores, la iluminación, las sombras, las restricciones, la generación normal de mapas y las mejoras físicas. En concreto, las nuevas características físicas hacen que sea muy fácil agregar efectos realistas a un juego.
Para más información, consulte nuestra documentación de SpriteKit.
Cambios de SpriteKit
Apple ha agregado las siguientes características nuevas a SpriteKit para iOS 9:
- Efecto de audio espacial que realiza un seguimiento automático de la posición del reproductor con la
SKAudioNodeclase . - Xcode ahora incluye un Editor de escenas y un Editor de acciones para facilitar la creación de juegos y aplicaciones en 2D.
- Compatibilidad sencilla con juegos de desplazamiento con nuevos objetos nodos de cámara
SKCameraNode(). - En dispositivos iOS que admiten Metal, SpriteKit lo usará automáticamente para la representación, incluso si ya estaba usando sombreadores OpenGL ES personalizados.
Para obtener más información, consulte nuestra referencia del marco SpriteKit de la documentación de SpriteKit de Apple y sus DemoBots: Building a Cross Platform Game with SpriteKit andKit sample app (Demostraciones: creación de un juego multiplataforma con SpriteKit y la aplicación de ejemplo DesenlazadorKit).
Resumen
En este artículo se han abordado las nuevas características de juegos que proporciona iOS 9 para las aplicaciones de Xamarin.iOS. Introdujo ElKit de juego y la E/S del modelo; las principales mejoras de Metal; y las nuevas características de SceneKit y SpriteKit.

