Программируем на Monogame без XNA. Делаем интерфейс с Neoforce

В этой статье, по просьбе читателя, мы попробуем воспользоваться Neoforce Controls, известной XNA библиотекой для создания пользовательского интерфейса, в MonoGame проекте.

Для начала вот несколько ссылок на исходники Neoforce:

http://neoforce.codeplex.com/

https://github.com/NeoforceControls/Neoforce-Mono

По второй ссылке можно скачать исходники двухгодичной давности, которые почти работают с MonoGame 3.5.

Небольшое отступление, neoforce на сегодняшний день не поддерживается, что так я бы рекомендовал сразу искать какую-то другую библиотеку. Вот несколько примеров:

https://github.com/DigitalRune

https://bitbucket.org/sparklinlabs/nuclearwinter/

У меня исходники просто так не собрались, пришлось удалять некоторые куски, так что, на всякий случай, я приложу библиотеку в формате dll к этой статье.

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

Можно начинать. Создадим новый MonoGame Windows Project.

Теперь нужно подключить библиотеку контролов. Для этого в контекстном меню References жмем Add Reference и выбираем TomShane.Neoforce.Controls.dll

Теперь нужно добавить скины в проект, для этого добавим папку Skins в папку Content в нашем проекте, а для всех файлов установим Copy To Output Directory = Copy always

Теперь можно добавлять элементы управления

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using TomShane.Neoforce.Controls;

namespace nftest2
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Manager neoManager;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            neoManager = new Manager(this, "Default");
            neoManager.AutoCreateRenderTarget = true;
            neoManager.TargetFrames = 60;
            neoManager.LogUnhandledExceptions = false;
            neoManager.ShowSoftwareCursor = true;

            IsMouseVisible = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            neoManager.Initialize();
            // TODO: use this.Content to load your game content here
            var tb = new TextBox(neoManager)
            {
                Left = 300,
                Top = 10,
                Height = 100,
                Width = 100,
                Mode = TextBoxMode.Multiline,
                WordWrap = true,
                Enabled = false,
                AutoSelection = false,
                Text = "Hello world! This is multiline textbox with word wrap"
            };
            neoManager.Add(tb);
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// game-specific content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <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)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            // TODO: Add your update logic here
            neoManager.Update(gameTime);

            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)
        {
            neoManager.BeginDraw(gameTime);
            GraphicsDevice.Clear(Color.CornflowerBlue);
            // TODO: Add your drawing code here
            neoManager.EndDraw();

            base.Draw(gameTime);
        }
    }
}

Вот так выглядит исходных код более сложного примера

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using TomShane.Neoforce.Controls;

namespace nftest2
{
    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Manager neoManager;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            neoManager = new Manager(this, "Default");
            neoManager.AutoCreateRenderTarget = true;
            neoManager.TargetFrames = 60;
            neoManager.LogUnhandledExceptions = false;
            neoManager.ShowSoftwareCursor = true;

            IsMouseVisible = true;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            neoManager.Initialize();
            // TODO: use this.Content to load your game content here
           
            var window = new Window(neoManager)
            {
                Width = 160,
                Height = 160,
                Text = "Hello World!",
            };
            window.Init();
            window.Center();



            // Create Button control and set the previous window as its parent.
            var button = new TomShane.Neoforce.Controls.Button(neoManager);
            button.Init();
            button.Text = "OK";
            button.Width = 100;
            button.Height = 24;
            button.Left = 0;
            button.Top = 100;
            button.Parent = window;

            var textbox = new TomShane.Neoforce.Controls.TextBox(neoManager);
            textbox.Init();
            textbox.Text = "Example";
            textbox.Width = 100;
            textbox.Height = 100;
            textbox.Top = 0;
            textbox.Left = 0;
            textbox.BackColor = Color.Transparent;
            textbox.Parent = window;

            // Add the window control to the manager processing queue.
            neoManager.Add(window);

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// game-specific content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <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)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            // TODO: Add your update logic here
            neoManager.Update(gameTime);

            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)
        {
            neoManager.BeginDraw(gameTime);
            GraphicsDevice.Clear(Color.CornflowerBlue);
            // TODO: Add your drawing code here
            neoManager.EndDraw();

            base.Draw(gameTime);
        }
    }
}

neoforce-zip (переименовать в .zip)

Реклама
Запись опубликована в рубрике Компьютерная графика, MonoGame с метками , , , , , . Добавьте в закладки постоянную ссылку.

12 комментариев на «Программируем на Monogame без XNA. Делаем интерфейс с Neoforce»

  1. Ched:

    Спасибо! Только как добраться до .dll в .pdb? Пошаговая инструкцию Add Reference-TomShane.Neoforce.Controls.dll невыполнима) В папке TomShane.Neoforce.Controls.pdb.

  2. Ched:

    Не получается у меня с Monogame. Поставил 3.4, выскочило исключение:
    Не удается загрузить DLL «d3d11.dll». Нужен DirectX 11. У меня XP, 32-bit, DirectX 9.0, OpenGL 2.1. Дошел до MonoGame 3.0. Там «Не удается найти точку входа «glBindFramebuffer» в DLL «opengl32.dll». С такой машиной никак с Monogame не сдружиться?)

  3. Ched:

    Вернулся к XNA) Делал первую .dll, узнал, что в VS есть кнопочка Показать все — при компиляции видно где создается .dll. Заглянул в такую же папку обновленной Neoforce с исходниками, версия для XNA, и обнаружил там заветный dll) WordWrap в этой версии работает, но по минимуму, при вставке текста все работает, при вводе — ужас. До версии TextBox 1.0 далековато. Не хотелось бы показаться навязчивым) Не могли бы вы сделать урок по созданию .dll из исходников Neoforce или здесь проинструктировать. Я бы попробовал допилить TextBox)

  4. Ched:

    Мне бы с первых шагов) Потому что захожу в папку XNA-master, там Neoforce.sln(unrecognized version). У меня не открывается. Проекты Controls, Importers, Scins для VS 2010, они по отдельности открываются. А как их собрать все вместе я не знаю.

  5. Ched:

    Это понятно) А что делать, если Neoforce.sln не открывается в VS 2010? Как мне создать новый проект и включить в него Controls, Importers, Scins

  6. У меня открылся и в 2010 после открытия в 2012 ). Можно создать новый solution и в него добавить все проекта (Add -> Existing Project), но тогда нужно будет правильно проставить ссылки в проектах друг не друга

  7. Ched:

    Обнадежило, что у вас открылся в 2010. Снова попытался открыть — не получилось. А потом что-то подтолкнуло попробовать через контекстное меню, там две строки:
    o Microsoft Visual Studio Version Selector
    o Microsoft Visual C# 2010 Express
    Кликнул на вторую — и проект открылся) Хотя двойным кликом так и не открывается. Откомпилировать получилось. В класс текстбокса добавил строку Text = «My text» при MouseDown, перекинул полученный .dll. И строка вывелась успешно. Можно допиливать)

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s