Пару недель назад мы опубликовали наш первый материал "Колобок в гостях у Windows 8: дневники разработки (введение)", сегодня мы продолжаем эту тему и рассказываем более детально структуру абстрактного уровня нашей архитектуры, в том виде как мы ее на сегодня организовали.
Недавно мы получили первые картинки от художника. Вот такой концепт на данный момент:

Этот класс берет на себя обязанности по управлению основным жизненным циклом игры, а также включает в себя логику и физику игры.
Жизненный цикл можно представить так:

Визуализация на верхнем уровне не привязана к игре. Связь с рендерингом происходит только в конкретной реализации игры.
За визуализацию отвечает интерфейс IRenderer, который обеспечивает реализацию трех методов:
Цикл визуализации:

IRenderer также наследует интерфейс IDisposable, что обеспечивает реализацию комплектом методов по детерминированному уничтожению объектов. В нашей реализации объекты по рисованию также наследуются от класса Component из библиотеки SharpDX, у которого можно использовать методы связанные с помещением ресурсов в список удаления, по которому проходит объект перед уничтожением, и мы получаем готовую реализацию IDisposable.
В нашей игре представлена интерфейсом ILogic
При возникновении игрового события логика обрабатывает набор правил, проверяет условия и возможность их выполнения, и потом инициирует события Win, Lose или Game Over, которые передаются в игру.
Рабочий цикл логики игры:

Интерфейс для физики предоставляет методы для добавления, удаления физических объектов,
симуляции мира на определенное время, получение фабрики объектов и слушателя событий
передвижения объектов. Интерфейс физического объекта представлен ниже
С помощью данного интерфейс можно задать и получить начальные координаты объекта, а также
матрицу преобразования в результате симуляции мира.
Хотим сказать, что знакомство с DirectX и самой разработкой игр — это очень интересная и новая для нас сфера.
По C# 5.0 и разработке под Windows Store хотим выделить такие вот особенности:
Первые эскизы
Недавно мы получили первые картинки от художника. Вот такой концепт на данный момент:

Абстрактный класс BaseGame
Этот класс берет на себя обязанности по управлению основным жизненным циклом игры, а также включает в себя логику и физику игры.
public abstract class BaseGame:DisposeSupport
/// <summary>
/// Describes an abstract game
/// </summary>
public abstract class BaseGame:DisposeSupport
{
/// <summary>
/// The game Logic
/// </summary>
protected abstract ILogic Logic { get; }
/// <summary>
/// The game Physics
/// </summary>
protected abstract IPhysics Physics { get; }
/// <summary>
/// Initialize the game
/// </summary>
public void Initialize(){}
/// <summary>
/// Start the new game
/// </summary>
public void StartNewGame(){}
/// <summary>
/// Activate the game
/// </summary>
public void ActivateGame(){}
/// <summary>
/// Pause on game
/// </summary>
public void Pause(){}
/// <summary>
/// Restart the game
/// </summary>
public void Restart(){}
/// <summary>
/// Resume the game
/// </summary>
public void Resume(){}
/// <summary>
/// Exit the game
/// </summary>
public void Exit(){}
public event Action Win;
public event Action GameOver;
public event Action Lose;
}
Жизненный цикл можно представить так:

Визуализация
Визуализация на верхнем уровне не привязана к игре. Связь с рендерингом происходит только в конкретной реализации игры.
За визуализацию отвечает интерфейс IRenderer, который обеспечивает реализацию трех методов:
- Initialize выполняется во время инициализации устройства,
- Render вызывается при отрисовке каждого кадра,
- SizeChanged вызывается во время смены размеров экрана, и в этот момент возможна инициализация.
public interface IRenderer<TInit, TRender>: IDisposable
/// <summary>
/// Describes a renderer class
/// </summary>
/// <typeparam name="TInit">Type that used for method Initialize parameter</typeparam>
/// <typeparam name="TRender">Type that used for methods Render and ScreenSizeChanged parameters</typeparam>
public interface IRenderer<TInit, TRender>: IDisposable
{
/// <summary>
/// On initialize a device
/// </summary>
/// <param name="initParameter">Initialize parameter</param>
void Initialize(TInit initParameter);
/// <summary>
/// On render per frame
/// </summary>
/// <param name="renderParameter">Render parameter</param>
void Render(TRender renderParameter);
/// <summary>
/// On screen size changed
/// </summary>
/// <param name="renderParameter">Render parameter</param>
void ScreenSizeChanged(TRender renderParameter);
}
Цикл визуализации:

IRenderer также наследует интерфейс IDisposable, что обеспечивает реализацию комплектом методов по детерминированному уничтожению объектов. В нашей реализации объекты по рисованию также наследуются от класса Component из библиотеки SharpDX, у которого можно использовать методы связанные с помещением ресурсов в список удаления, по которому проходит объект перед уничтожением, и мы получаем готовую реализацию IDisposable.
Логика
В нашей игре представлена интерфейсом ILogic
public interface ILogic
/// <summary>
/// Describes a game logic
/// </summary>
public interface ILogic
{
/// <summary>
/// Start game
/// </summary>
void StartGame();
/// <summary>
/// Stop game
/// </summary>
void StopGame();
/// <summary>
/// Pause game
/// </summary>
void PauseGame();
/// <summary>
/// Resume game
/// </summary>
void ResumeGame();
/// <summary>
/// Fire game event
/// </summary>
void FireEvent(IGameEvent @event);
/// <summary>
/// Win game event
/// </summary>
event Action Win;
/// <summary>
/// Lose game event
/// </summary>
event Action Lose;
/// <summary>
/// Delete game object event
/// </summary>
event Action<string> ObjectDeleted;
/// <summary>
///Character moved event
/// </summary>
event Action<string,float,float,float> CharacterMoved;
/// <summary>
///Character moved by path event
/// </summary>
event Action<string, IList<PathData>> CharacterMovedPath;
/// <summary>
///Character patrol by path event
/// </summary>
event Action<string, IList<PathData>> CharacterPatrolPath;
/// <summary>
///Character patrol event
/// </summary>
event Action<string, float, float, float> CharacterPatrol;
/// <summary>
///Character moved to object event
/// </summary>
event Action<string, string, float> CharacterMovedToObject;
/// <summary>
///Character in chase for object event
/// </summary>
event Action<string, string, float> CharacterChase;
/// <summary>
/// watch if the one object look at another;
/// </summary>
event Action<string, string> WatchedLook;
/// <summary>
/// watch the distance between two objects;
/// </summary>
event Action<string, string, float> WatchedDistance;
/// <summary>
/// character stop;
/// </summary>
event Action<string> ActionStopped;
/// <summary>
///The rules factory
/// </summary>
IRuleFactory RuleFactory { get; }
}
При возникновении игрового события логика обрабатывает набор правил, проверяет условия и возможность их выполнения, и потом инициирует события Win, Lose или Game Over, которые передаются в игру.
Рабочий цикл логики игры:

Физика
public interface IPhysics
public interface IPhysics
{
/// <summary>
/// add object to simulation
/// </summary>
/// <param name="obj">object</param>
void AddObject(IObject obj);
/// <summary>
/// remove object from simulation
/// </summary>
/// <param name="obj">object</param>
void RemoveObject(IObject obj);
/// <summary>
/// simulate world on specified time after start
/// </summary>
/// <param name="time">seconds</param>
void Simulate(float time);
/// <summary>
/// signal that initialization starts
/// </summary>
void BeginInitialization();
/// <summary>
/// signal that initialization included adding of objects is finished
/// </summary>
void EndInitialization();
/// <summary>
/// getting movement observer for observing different events related to movement of
objects
/// </summary>
/// <returns>moevement observer</returns>
IMovementObserver GetMovementObserver();
/// <summary>
/// get object factory
/// </summary>
/// <returns>getting object factory</returns>
IObjectFactory GetObjectFactory();
}
Интерфейс для физики предоставляет методы для добавления, удаления физических объектов,
симуляции мира на определенное время, получение фабрики объектов и слушателя событий
передвижения объектов. Интерфейс физического объекта представлен ниже
public interface IObject
public interface IObject
{
/// <summary>
/// getting transformation matrix of object
/// </summary>
/// <returns>matrix</returns>
Matrix GetTransform();
float X { get; set; }
float Y { get; set; }
float Z { get; set; }
}
С помощью данного интерфейс можно задать и получить начальные координаты объекта, а также
матрицу преобразования в результате симуляции мира.
Выводы:
Хотим сказать, что знакомство с DirectX и самой разработкой игр — это очень интересная и новая для нас сфера.
По C# 5.0 и разработке под Windows Store хотим выделить такие вот особенности:
- очень много изменений в .Net;
- нет синхронных операций чтения файлов, теперь все асинхронное (тут нету ничего плохого, иногда такой дизайн не подходит и приходится превращать асинхронный код в синхронный);
- нет многих стандартных для .Net 4.0 классов;
- внесены изменения в работу с метаданными типов и рефлексией;
- немного отличается Xaml набором полезных классов от WPF;
- чтобы писать под Windows Store нужно обязательно работать в среде Windows 8.