Aracılığıyla paylaş


Xamarin.iOS'ta iOS Oyun API'leri

Bu makale, iOS 9 tarafından sağlanan ve Xamarin.iOS oyununuzun grafiklerini ve ses özelliklerini geliştirmek için kullanılabilecek yeni oyun geliştirmelerini kapsar.

Apple, bir Xamarin.iOS uygulamasında oyun grafiklerini ve seslerini uygulamayı kolaylaştıran iOS 9'daki oyun API'lerinde çeşitli teknolojik geliştirmeler yaptı. Bunlar hem üst düzey çerçeveler aracılığıyla geliştirme kolaylığı hem de gelişmiş hız ve grafik becerileri için iOS cihazının GPU'sunun gücünden yararlanmayı içerir.

Sürü oluşturma çalıştıran bir uygulama örneği

Buna GameplayKit, ReplayKit, Model G/Ç, MetalKit ve Metal Performans Gölgelendiricilerinin yanı sıra Metal, SceneKit ve SpriteKit'in yeni, gelişmiş özellikleri dahildir.

Bu makalede, iOS 9'un yeni oyun geliştirmeleriyle Xamarin.iOS oyununuzu geliştirmenin tüm yolları tanıtılacaktır:

GameplayKit tanıtımı

Apple'ın yeni GameplayKit çerçevesi, uygulama için gereken yinelenen ve ortak kod miktarını azaltarak iOS cihazları için oyun oluşturmayı kolaylaştıran bir dizi teknoloji sağlar. GameplayKit, oyun mekaniği geliştirmek için bir grafik motoruyla (SceneKit veya SpriteKit gibi) kolayca birleştirilebilen araçlar seçerek tamamlanmış bir oyunu hızlı bir şekilde sunar.

GameplayKit aşağıdakiler gibi çeşitli, yaygın oyun oynama algoritmaları içerir:

  • Yapay zekanın otomatik olarak takip edeceği hareketleri ve hedefleri tanımlamanızı sağlayan davranış tabanlı, aracı simülasyonu.
  • Sıra tabanlı oyun için minmax yapay zeka.
  • Yeni bir davranış sağlamak için belirsiz mantık içeren veri odaklı oyun mantığına yönelik bir kural sistemi.

Ayrıca, GameplayKit aşağıdaki özellikleri sağlayan modüler bir mimari kullanarak oyun geliştirmeye yönelik bir yapı taşı yaklaşımı benimser:

  • Oyun oynarken karmaşık, yordamsal kod tabanlı sistemleri işlemeye yönelik durum makinesi.
  • Hata ayıklama sorunlarına neden olmadan rastgele oyun oynama ve öngörülemezlik sağlama araçları.
  • Yeniden kullanılabilir, bileşenli varlık tabanlı bir mimari.

GameplayKit hakkında daha fazla bilgi edinmek için lütfen Apple'ın Oyun Seti Programlama Kılavuzu ve GameplayKit Framework Başvurusu'na bakın.

GameplayKit Örnekleri

Şimdi oyun setini kullanarak Xamarin.iOS uygulamasında bazı basit oyun mekaniği uygulamaya göz atalım.

Yol Bağlama

Pathfinding, bir oyunun yapay zeka öğesinin oyun panosunda yolunu bulmasıdır. Örneğin, bir 2B düşman, birinci şahıs-atıcı dünya arazisinde bir labirent veya 3B karakter aracılığıyla yolunu bulur.

Aşağıdaki haritayı göz önünde bulundurun:

Örnek yol bağlama eşlemesi

Bu C# kodunun yol bağlamasını kullanarak haritada bir yol bulabilirsiniz:

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

Klasik Uzman Sistemi

C# kodunun aşağıdaki parçacığında, Klasik bir uzman sistemi uygulamak için GameplayKit'in nasıl kullanılabileceğini gösterilmektedir:

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;
}

Belirli bir kural kümesine (GKRule) ve bilinen bir giriş kümesine bağlı olarak, uzman sistem (GKRuleSystem) tahmin edilebilir çıkış oluşturur (fizzbuzz yukarıdaki örneğimiz için).

Akın

Sürü oluşturma, bir grup yapay zeka kontrollü oyun varlığının bir sürü gibi davranmasına olanak tanır. Burada grup, uçuşta kuş sürüleri veya balık yüzme okulu gibi bir kurşun varlığın hareketlerine ve eylemlerine yanıt verir.

Aşağıdaki C# kodu parçacığı, grafik görüntüsü için GameplayKit ve SpriteKit kullanarak sürü oluşturma davranışı uygular:

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}");
        }
    }
}

Ardından, bu sahneyi bir görünüm denetleyicisinde uygulayın:

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

Çalıştırıldığında, küçük animasyonlu "Boids" parmak dokunuşlarımızın etrafında akın edecektir:

Küçük animasyonlu Boid'ler parmak dokunuşlarının etrafında akın edecek

Diğer Apple Örnekleri

Yukarıda sunulan örneklere ek olarak, Apple C# ve Xamarin.iOS'a çevrilebilen aşağıdaki örnek uygulamaları sağlamıştır:

Metal

iOS 9'da Apple, GPU'ya düşük ek yük erişimi sağlamak için Metal'e çeşitli değişiklikler ve eklemeler yaptı. Metal kullanarak iOS uygulamalarınızın grafik ve işlem potansiyelini en üst düzeye çıkarabilirsiniz.

Metal çerçevesi aşağıdaki yeni özellikleri içerir:

  • OS X için yeni özel ve derinlik kalıbı dokuları.
  • Derinlik sıkıştırma ve ayrı ön ve arka kalıp değerleri ile geliştirilmiş gölge kalitesi.
  • Metal Gölgelendirme Dili ve Metal Standart Kitaplığı geliştirmeleri.
  • Hesaplama gölgelendiricileri daha geniş bir piksel biçimi yelpazesini destekler.

The MetalKit Framework

MetalKit çerçevesi, bir iOS uygulamasında Metal'i kullanmak için gereken çalışma miktarını azaltan bir dizi yardımcı program sınıfı ve özelliği sağlar. MetalKit üç önemli alanda destek sağlar:

  1. PNG, JPEG, KTX ve PVR gibi yaygın biçimler de dahil olmak üzere çeşitli kaynaklardan zaman uyumsuz doku yükleme.
  2. Metale özgü model işleme için Model G/Ç tabanlı varlıklara kolay erişim. Bu özellikler, Model G/Ç kafesleri ile Metal arabellekler arasında verimli veri aktarımı sağlamak için yüksek oranda iyileştirilmiştir.
  3. iOS uygulamasında grafik işlemeleri görüntülemek için gereken kod miktarını büyük ölçüde azaltan önceden tanımlanmış Metal görünümler ve görünüm yönetimi.

MetalKit hakkında daha fazla bilgi edinmek için lütfen Apple'ın MetalKit Framework Başvurusu, Metal Programlama Kılavuzu, Metal Çerçeve Başvurusu ve Metal Gölgelendirme Dil Kılavuzu'na bakın.

Metal Performans Gölgelendiricileri Çerçevesi

Metal Performans Gölgelendiricisi çerçevesi, Metal tabanlı iOS uygulamalarınızda kullanmak için yüksek oranda iyileştirilmiş bir grafik ve hesaplama tabanlı gölgelendirici kümesi sağlar. Metal Performans Gölgelendiricisi çerçevesindeki her gölgelendirici, Metal tarafından desteklenen iOS GPU'larında yüksek performans sağlayacak şekilde özel olarak ayarlanmıştır.

Metal Performans Gölgelendiricisi sınıflarını kullanarak, tek tek kod tabanlarını hedeflemek ve korumak zorunda kalmadan her bir iOS GPU'da mümkün olan en yüksek performansı elde edebilirsiniz. Metal Performans Gölgelendiricileri dokular ve arabellekler gibi herhangi bir Metal kaynağı ile kullanılabilir.

Metal Performans Gölgelendiricisi çerçevesi aşağıdakiler gibi bir dizi ortak gölgelendirici sağlar:

  • Gauss Bulanıklığı (MPSImageGaussianBlur)
  • Sobel Edge Algılama (MPSImageSobel)
  • Görüntü Histogramı (MPSImageHistogram)

Daha fazla bilgi için lütfen Apple'ın Metal Gölgelendirme Dil Kılavuzu'na bakın.

Model G/Ç'ye giriş

Apple'ın Model G/Ç çerçevesi, 3B varlıkları (modeller ve bunların ilgili kaynakları gibi) ayrıntılı bir şekilde anlamanızı sağlar. Model G/Ç, iOS oyunlarınıza GameplayKit, Metal ve SceneKit ile kullanılabilecek fiziksel tabanlı malzemeler, modeller ve aydınlatma sağlar.

Model G/Ç ile aşağıdaki görev türlerini destekleyebilirsiniz:

  • Çeşitli popüler yazılım ve oyun motoru biçimlerinden aydınlatma, malzeme, örgü verileri, kamera ayarları ve diğer sahne tabanlı bilgileri içeri aktarın.
  • Yordamsal dokulu gökyüzü kubbeleri oluşturma veya ağ içinde aydınlatma pişirme gibi sahne tabanlı bilgileri işleyin veya oluşturun.
  • İşleme için oyun varlıklarını GPU arabelleklerine verimli bir şekilde yüklemek için MetalKit, SceneKit ve GLKit ile çalışır.
  • Sahne tabanlı bilgileri çeşitli popüler yazılım ve oyun motoru biçimlerine aktarın.

Model G/Ç hakkında daha fazla bilgi edinmek için bkz. Apple'ın Model G/Ç Çerçevesi Başvurusu

ReplayKit tanıtımı

Apple'ın yeni ReplayKit çerçevesi, iOS oyununuza oyun kaydını kolayca eklemenize ve kullanıcının bu videoyu uygulama içinden hızlı ve kolay bir şekilde düzenlemesine ve paylaşmasına olanak tanır.

Daha fazla bilgi için lütfen ReplayKit ve Game Center ile Apple'ın Going Social videosuna ve onların DemoBots: SpriteKit ve GameplayKit ile Platformlar Arası Oyun Oluşturma örnek uygulamasına bakın.

SceneKit

Sahne Seti, 3B grafiklerle çalışmayı kolaylaştıran bir 3B sahne grafı API'sidir. İlk olarak OS X 10.8'de tanıtıldı ve şimdi iOS 8'e geldi. Sahne Seti, çevreleyici 3B görselleştirmeler ve gündelik 3B oyunlar oluştururken OpenGL'de uzmanlık gerektirmez. Ortak sahne grafı kavramlarını temel alan Scene Kit, OpenGL ve OpenGL ES'nin karmaşıklıklarını soyutlayarak uygulamaya 3B içerik eklemeyi çok kolaylaştırır. Ancak, bir OpenGL uzmanıysanız, Sahne Seti doğrudan OpenGL ile bağlama için de büyük desteğe sahiptir. Ayrıca fizik gibi 3B grafikleri tamamlayan ve Core Animation, Core Image ve Sprite Kit gibi diğer birçok Apple çerçevesiyle çok iyi bir şekilde tümleşen çok sayıda özellik içerir.

Daha fazla bilgi için lütfen SceneKit belgelerimize bakın.

SceneKit Değişiklikleri

Apple, iOS 9 için SceneKit'e aşağıdaki yeni özellikleri eklemiştir:

  • Xcode artık doğrudan Xcode'un içinden sahneleri düzenleyerek hızlı bir şekilde oyun ve etkileşimli 3B uygulamalar oluşturmanıza olanak tanıyan bir Sahne Düzenleyicisi sağlar.
  • SCNView ve SCNSceneRenderer sınıfları Metal işlemeyi etkinleştirmek için kullanılabilir (desteklenen iOS cihazlarında).
  • SCNAudioPlayer ve SCNNode sınıfları, iOS uygulamasına bir oynatıcı konumunu otomatik olarak izleyen uzamsal ses efektleri eklemek için kullanılabilir.

Daha fazla bilgi için lütfen SceneKit Belgelerimize ve Apple'ın SceneKit Framework Başvurusu ve Fox: Xcode Sahne Düzenleyicisi örnek projesiyle Bir SceneKit Oyunu Oluşturma bölümüne bakın.

SpriteKit

Apple'ın 2B oyun çerçevesi Sprite Kit, iOS 8 ve OS X Yosemite'da bazı ilginç yeni özelliklere sahiptir. Bunlar Arasında Scene Kit ile tümleştirme, gölgelendirici desteği, aydınlatma, gölgeler, kısıtlamalar, normal harita oluşturma ve fizik geliştirmeleri yer alır. Özellikle, yeni fizik özellikleri bir oyuna gerçekçi efektler eklemeyi çok kolaylaştırır.

Daha fazla bilgi için lütfen SpriteKit belgelerimize bakın.

SpriteKit Değişiklikleri

Apple, iOS 9 için SpriteKit'e aşağıdaki yeni özellikleri ekledi:

  • Oyuncunun sınıfındaki SKAudioNode konumunu otomatik olarak izleyen uzamsal ses efekti.
  • Xcode artık kolay 2B oyun ve uygulama oluşturma için bir Sahne Düzenleyicisi ve Eylem Düzenleyicisi'ne sahip.
  • Yeni Kamera Düğümleri (SKCameraNode) nesneleriyle kolay kaydırma oyunu desteği.
  • Metal'i destekleyen iOS cihazlarda SpriteKit, özel OpenGL ES gölgelendiricileri kullanıyor olsanız bile işleme için otomatik olarak kullanır.

Daha fazla bilgi için lütfen SpriteKit Belgelerimize bakın Apple'ın SpriteKit Framework Başvurusu ve demobotları: SpriteKit ve GameplayKit ile Platformlar Arası Oyun Oluşturma örnek uygulaması.

Özet

Bu makalede, iOS 9'un Xamarin.iOS uygulamalarınız için sağladığı yeni Oyun özellikleri ele alınmıştır. GameplayKit ve Model G/Ç'sini tanıttı; Metal'de yapılan önemli geliştirmeler; ve SceneKit ve SpriteKit'in yeni özellikleri.