Создание проекта MonoGame для Visual Studio под платформу iOS

У всех разработчиков на MonoGame одна из главных целей — выпустить свою игру на максимальном количестве платформ. При этом затратить меньшее количество ресурсов, как на само разработку, так и поддержку игры в дальнейшем.

Использование при разработке на все платформы одних и тех же инструментов, несомненно позволяет сэкономить не мало времени. А такая мощная среда, как Visual Studio, позволяет не только в одном месте вести разработку, но и в один клик переключаться между платформами.

Но в текущей версии MonoGame официально поддержка Visual Studio при разработке под iOS не заявлено. А при установке библиотеки убеждаемся, что для Visual Studio нету шаблона MonoGame под iOS.

Но это недоразумение легко разрешается. Так как MonoGame — это всего лишь библиотека для Xamarin.iOS, с которой можно работать в Visual Studio.

Сборка библиотеки MonoGame

Этот этап к сожалению нельзя провести в самой Visual Studio. Но так как для разработки под iOS у нас должна быть машина на Mas OS с установленной Xamarin.iOS это не составит проблемы. Как настроить машину на Mac OS для работы с Visual Studio, я уже ранее писал.

Что нужно сделать на машине с Mac OS:

  1. Скачиваем исходный код библиотеки MonoGame
  2. Запускаем в Xamarin Studio решение MonoGame.Framework.iOS.sln
  3. Собираем решение.
  4. После чего в папке MonoGame.Framework/bin находим собранные библиотеки: Lidgren.Network.dll и MonoGame.Framework.dll.
  5. Переносим эти файлы на машину с Visual Studio.

Также уже собранные библиотеки, которые получились у меня можно просто скачать. Но они могут устареть к моменту, когда вы это читаете.

Создание базового проекта

Библиотеки мы получили, а вот шаблона для проекта у нас так и нет. Так как все игры на MonoGame, это всего лишь производные от проектов Xamarin.iOS, то просто создаем пустой проект для iOS, как показано ниже.

Empty Xamarin.iOS project

Дальнейшие действия:

  1. Убираем из проекта файл AppDelegate.cs.
  2. Подключаем к нашему проектeу библиотеки MonoGame, которые мы собрали до этого. Правой кнопкой по проекту -> Add reference… -> Browse -> находим библиотеки и выбираем их.
  3. Создаем в проекте папку Content, в которую будем складывать ресурсы для игры.
  4. Создаем файл для класса игры Game1.cs и наполняем следующим:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    
        /// <summary>
        /// Default Project Template
        /// </summary>
        public class Game1 : Game
        {
     
            #region Fields
            readonly GraphicsDeviceManager graphics;
            SpriteBatch _spriteBatch;
            #endregion
     
            #region Initialization
     
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
     
                Content.RootDirectory = "Content";
     
                graphics.IsFullScreen = true;
     
                graphics.SupportedOrientations = DisplayOrientation.Portrait;
            }
     
            /// <summary>
            /// Overridden from the base Game.Initialize. Once the GraphicsDevice is setup,
            /// we'll use the viewport to initialize some values.
            /// </summary>
            protected override void Initialize()
            {
                base.Initialize();
            }
     
            /// <summary>
            /// Load your graphics content.
            /// </summary>
            protected override void LoadContent()
            {
                // Create a new SpriteBatch, which can be use to draw textures.
                _spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
     
                // TODO: use this.Content to load your game content here eg.
            }
            #endregion
     
            #region Update and Draw
     
            /// <summary>
            /// Allows the game to run logic such as updating the world,
            /// checking for collisions, gathering input, and playing audio.
            /// </summary>
            /// <param name="gameTime">Provides a snapshot of timing values.</param>
            protected override void Update(GameTime gameTime)
            {
                // TODO: Add your update logic here         
     
                base.Update(gameTime);
            }
            /// <summary>
            /// This is called when the game should draw itself. 
            /// </summary>
            /// <param name="gameTime">Provides a snapshot of timing values.</param>
            protected override void Draw(GameTime gameTime)
            {
                // Clear the backbuffer
                graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
     
                //TODO: Add your drawing code here
                base.Draw(gameTime);
            }
            #endregion
        }
        /// <summary>
        /// Default Project Template
        /// </summary>
        public class Game1 : Game
        {
    
            #region Fields
            readonly GraphicsDeviceManager graphics;
            SpriteBatch _spriteBatch;
            #endregion
    
            #region Initialization
    
            public Game1()
            {
                graphics = new GraphicsDeviceManager(this);
    
                Content.RootDirectory = "Content";
    
                graphics.IsFullScreen = true;
    
                graphics.SupportedOrientations = DisplayOrientation.Portrait;
            }
    
            /// <summary>
            /// Overridden from the base Game.Initialize. Once the GraphicsDevice is setup,
            /// we'll use the viewport to initialize some values.
            /// </summary>
            protected override void Initialize()
            {
                base.Initialize();
            }
    
            /// <summary>
            /// Load your graphics content.
            /// </summary>
            protected override void LoadContent()
            {
                // Create a new SpriteBatch, which can be use to draw textures.
                _spriteBatch = new SpriteBatch(graphics.GraphicsDevice);
    
                // TODO: use this.Content to load your game content here eg.
            }
            #endregion
    
            #region Update and Draw
    
            /// <summary>
            /// Allows the game to run logic such as updating the world,
            /// checking for collisions, gathering input, and playing audio.
            /// </summary>
            /// <param name="gameTime">Provides a snapshot of timing values.</param>
            protected override void Update(GameTime gameTime)
            {
                // TODO: Add your update logic here			
    
                base.Update(gameTime);
            }
            /// <summary>
            /// This is called when the game should draw itself. 
            /// </summary>
            /// <param name="gameTime">Provides a snapshot of timing values.</param>
            protected override void Draw(GameTime gameTime)
            {
                // Clear the backbuffer
                graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
    
                //TODO: Add your drawing code here
                base.Draw(gameTime);
            }
            #endregion
        }
  5. Теперь изменим содержимое файла Main.cs на:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
        [Register("AppDelegate")]
        class Program : UIApplicationDelegate
        {
            Game1 game;
     
            public override void FinishedLaunching (UIApplication app)
            {
                // Fun begins..
                game = new Game1 ();
                game.Run ();
            }
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static void Main (string[] args)
            {
                UIApplication.Main (args, null, "AppDelegate");
            }
        }
        [Register("AppDelegate")]
        class Program : UIApplicationDelegate
    	{
    		Game1 game;
    
    		public override void FinishedLaunching (UIApplication app)
    		{
    			// Fun begins..
    			game = new Game1 ();
    			game.Run ();
    		}
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
    		static void Main (string[] args)
    		{
    			UIApplication.Main (args, null, "AppDelegate");
    		}
    	}
  6. Также нужно не забыть в свойствах проекта выставить такие пункты как Application nameIdentifierVersion. Без них игра на эмуляторе и устройстве не запустится.
  7. Запускаем приложение в сборке iPhoneSimulator и видим следующее:

MonoGame iOS project in Visual Studio

Так мы создали базовый проект игры на MonoGame для Visual Studio под платформу iOS.

Скачать пример

  • Интересный блог. Я был бы очень благодарен автору, если бы он осветил вопрос как лучше организовать работу приложения с удаленным сервером,
    выделить отдельный поток или через Service? Как правильно и какие
    преимущества у каждого подхода?