вторник, 30 августа 2011 г.

Simple render. Интерфейс IEntity

Всем привет 

Сегодня после небольшого перерыва я продолжу рассказ о своем примере отрисовки.
На сегодня у нас один небольшой вопрос - это создание интерфейса IEntity, а также его реализация в наследнике
Итак поехали 

Интерфейс IEntity представляет любую игровую сущность, это базовый класс для любого игрового объекта. Он на самом деле не большой. Как мне кажется на таком уровне нужно только две вещи:
- сохранение и возможность получения уникального идентификатора нашего объекта
- возможность обновления объекта, выполнения в нем какой-то логики

Соответственно интерфейс имеет следующую реализацию 
       class IEntity
       {
              static unsigned long m_EntityIDCounter;
              int m_EntityID;

       public:
              inline int getEntityID()const
              {
                     return m_EntityID;
              }
              
       private:
              inline void setEntityID(int id)
              {
                     m_EntityID = id;
              }

       public:
              IEntity()
              {
                     setEntityID(++m_EntityIDCounter);
              }

              virtual ~IEntity()
              {
              }

              virtual void update() = 0;
       private:
       };
Целочисленное поле m_EntityID содержит уникальный идентификатор объекта, получить который можно через метод getEntityID, а устанавливается он автоматически при создании объекта. Для того чтобы обеспечить уникальной каждого идентификатора я использую статическую переменную m_EntityIDCounter. Думаю промежутка значений, который можно хранить в long нам хватит выше крыши для идентификаторов. 

Ну а для обновления объекта создан абстрактный метод update. На данный момент он не принимает никаких параметров. 

Идем дальше. В примере я создал только один класс наследник - это класс, который представляет двухмерный объект, как статический, так и динамический. Этот объект не содержит логики, но мы потом сможем это добавить, сейчас же это не важно. 
Вот код нового класса:
       class GameEntity : public IEntity
       {
       private:

              glm::vec2 m_Position;
       public:
              inline const glm::vec2& getPosition()const
              {
                     return m_Position;
              }

              inline void setPosition(const glm::vec2& pos)
              {
                     m_Position = pos;
              }

       public:
              GameEntity();

              virtual void update();
       };

Конструктор просто инициализирует позицию нулями 
       GameEntity::GameEntity()
       {
              m_Position.x = m_Position.y = 0.0f;
       }
А метод update вообще пока не содержит логики
       void GameEntity::update()
       {
       }

Собственно все. 
Теперь у нас есть модель, которую нужно визуализировать. Осталось только дописать вид и все будет в шоколаде. 

Всем доброй ночи.

воскресенье, 21 августа 2011 г.

Simple render. Описание идеи

Всем привет. 

Представляю вашему вниманию первую часть цикла для начинающих об отрисовке в играх. 
Сегодня мы рассмотрим идею в общем и набросаем стартовое приложение. 
Для работы с рендером я буду использовать библиотеку glut. В принципе она сейчас практически не используется, но нам подойдет идеально. Использование glut позволит мне сосредоточится на структуре классов и не отвлекаться на разбор OpenGL или DirectX.

Погнали. 
Идею построена на паттерне MVC, т.е. на разделении данных и их визуального отображения. 

Давайте рассмотрим основные классы и интерфейсы, их в моей схеме 3: 
Renderer - этот класс отвечает за весь рендер в целом, он хранит в себе список всех объектов, которые нужно отобразить в игре, знает порядок их отображения. Также он отвечает за различные действия с рендер конвеером, которые необходимо выполнить в начале каждого кадра и соответственно в конце. 
IEntity - этот интерфейс является базовым для всех объектов с данными, которые находятся в нашей игре. Каждая сущность имеет свой уникальный идентификатор. Одним словом  это model.
IRenderer - данный интерфейс является базовым для всех объектов рендера в игре. Он отвечает за визуализацию модели данных, т.е за визуализацию игровых сущностей. Это view.

Это все что касается основным типов данных нашей игре. Данный подход позволяет реализовать практически любой по сложности рендер, постепенно вырабатывая набор сущностей и способов их представления. 
Конечно при этом нужно будет дорабатывать и класс Renderer, добавляя в него новые возможности по настройке рендера.

Идем дальше, следующий шаг это создание стартового приложения и настройки вывода первого примитива. Пока без реализации схемы классов, только отрисовка одного примитива.

int _tmain(int argc, _TCHAR* argv[])
{
     /// блок инициализации окна
     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
     glutInitWindowSize(800, 600);
     glutCreateWindow("Simple");
     /// устанавливаем различные калбек функции, которые будет вызывать glut
     glutDisplayFunc(renderScene);
     glutReshapeFunc(Reshape);
     glutKeyboardFunc(Keyboard);
     setupRC();
     // запускаем основной цикл приложения
     glutMainLoop();
     return 0;
}

Самый интересный для нас метод renderScene. Именно в него мы будем встраивать код по отрисовке. 
Сейчас он имеет следующий вид:

 void renderScene(void)
{
     //очищаем экран
     glClear(GL_COLOR_BUFFER_BIT);
     // устанавливаем матрицу для нашего объекта
     glPushMatrix();

     glTranslatef(-200.0f+pos, 0.0f, 0.0f);
     // отрисовываем квадрат красного цвета на экране.
     glColor3ub(255,0,0);
     glBegin(GL_QUADS);
         glVertex2f(200,400);
         glVertex2f(200,200);
         glVertex2f(400,200);
         glVertex2f(400,400);
     glEnd();

     glPopMatrix();
     // вызываем свап буфера для того, чтобы наша картинка появилась на кране монитора
     glutSwapBuffers();
     glutPostRedisplay();
}

На сегодня это все. В следующий раз я подробно пройдусь по интерфейсам, покажу реализацию класса Renderer. 
Весь код стартового приложения можно посмотреть здесь. Для использования glut нужно подключить статическую либу к проекту, а потом рядом с исполняемым файлом положить dll библиотеку. Все есть вот тут

Всем доброй ночи.

среда, 17 августа 2011 г.

Simple render. Вступление


Всем привет.

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

Описание разбил на несколько частей:
1. Общее описание и создание окна с помощью glut
2. Интерфейс IEntity
3. Интерфейс IRenderer
4. Renderer и запуск финального приложения.

Вот ссылка на исходники примера для тех, кому код понятнее, чем мои сбивчивые описания.
Для написания примера я использовал Microsoft Visual Studio C++ Express 2010.

Всем доброй ночи.