Russian Qt Forum

Qt => Уроки и статьи => Тема начата: 8Observer8 от Сентябрь 15, 2014, 08:45



Название: Пошаговая инструкция введения в OpenGL на Qt
Отправлено: 8Observer8 от Сентябрь 15, 2014, 08:45
Добавил 1/8/2015 Мои видео-уроки: 001 Qt C++ OpenGL GLSL Рисуем треугольник (http://www.youtube.com/watch?v=jTHvFGjy5uA&list=PLHlHFavas54e0-05vZcZ0wNGhnpRyFmLc&index=1)

Привет!

Пример представляет из себя медленно падающий квадрат, который мы можем перемещать влево и вправо с помощью стрелок.

Инструкция
- Установка Qt (http://www.prog.org.ru/index.php?topic=27563.msg200249#msg200249)
- Переключение Qt Creator'a на английский (http://www.prog.org.ru/index.php?topic=27563.msg200251#msg200251)
- Создание нового проекта (http://www.prog.org.ru/index.php?topic=27563.msg200255#msg200255)
- Скопируем код заготовки в Scene.h и Scene.cpp (см. ниже)
- Запускаем приложение. Мы видим падающий вниз квадрат, который мы можем перемещать влево и вправо

Scene.h
Код
C++ (Qt)
#ifndef SCENE_H
#define SCENE_H
 
#include <QGLWidget>
#include <QTimer>
#include <QKeyEvent>
 
class Scene : public QGLWidget
{
   Q_OBJECT
 
public:
   Scene( QWidget *parent = 0 );
 
private slots:
   void slotMove();
 
private:
   void initializeGL();
   void paintGL();
   void resizeGL( int w, int h );
 
   void keyPressEvent( QKeyEvent * event );
 
private:
   // Square position and size
   int x;
   int y;
   const int rsize;
 
   // Step size in x and y directions
   // (number of pixels to move each time)
   int xstep;
   int ystep;
 
   // Keep track of windows changing width and height
   GLfloat windowWidth;
   GLfloat windowHeight;
 
   // Timer
   QTimer *timer;
};
 
#endif // SCENE_H
 

Scene.cpp
Код
C++ (Qt)
 
#include "Scene.h"
 
Scene::Scene( QWidget *parent ) :
   QGLWidget( parent ),
   x( 0 ),
   y( 100 ),
   rsize( 25 ),
   xstep( 25 ),
   ystep( 1 )
{
   timer = new QTimer( this );
   connect( timer, SIGNAL( timeout() ),
            this, SLOT( slotMove() ) );
   timer->start( 33 );
 
   this->setFocusPolicy( Qt::StrongFocus );
}
 
void Scene::slotMove()
{
   y -= ystep;
 
   updateGL();
}
 
void Scene::initializeGL()
{
   glClearColor( 0.8f, 0.8f, 0.6f, 1.0f );
}
 
void Scene::paintGL()
{
   // Clear the window with current clearing color
   glClear( GL_COLOR_BUFFER_BIT );
 
   // Set current drawing color
   glColor3f( 0.0f, 0.5f, 0.5f );
 
   // Draw a filled rectangle with current color
   glRectf( x, y, x + rsize, y - rsize );
}
 
void Scene::resizeGL( int w, int h )
{
   // Prevent a divide by zero
   if ( h == 0 ) {
       h = 1;
   }
 
   // Set Viewport to window dimensions
   glViewport( 0, 0, w, h );
 
   // Reset coordinate system
   glMatrixMode( GL_PROJECTION );
   glLoadIdentity();
 
   // Establish clipping volume (left, right, bottom, top, near, far)
   GLfloat aspectRatio = ( GLfloat ) w / ( GLfloat ) h;
 
   if ( w <= h ) {
       windowWidth = 100.0f;
       windowHeight = 100.0f / aspectRatio;
       glOrtho( -100.0, 100.0, -windowHeight, windowHeight,
                1.0, -1.0 );
   } else {
       windowWidth = 100.0 * aspectRatio;
       windowHeight = 100.0;
       glOrtho( -windowWidth, windowWidth, -100.0, 100.0,
                1.0, -1.0 );
   }
 
   glMatrixMode( GL_MODELVIEW );
   glLoadIdentity();
}
 
void Scene::keyPressEvent( QKeyEvent *event )
{
   switch( event->key() ) {
   case Qt::Key_Left:
       x -= xstep;
       break;
   case Qt::Key_Right:
       x += xstep;
       break;
   }
}
 

Краткие объяснения основных моментов

Примечание. Начало координат находится в середине окна.

- paintGL() - выполняется автоматически, когда приложению надо перерисовать окно. К примеру, если мы свернём окно и развернём, то тело этой функции выполнится. Или если перекроем наше окно каким-то другим. Или изменим размер нашего окна. В этой функции мы рисуем квадрат с помощью такой функции:

Код
C++ (Qt)
glRectf( x, y, x + rsize, y - rsize );
 

Здесь:
x - глобальная переменная, которая хранит x-координату левого верхнего угла прямоугольника
y - глобальная переменная, которая хранит y-координату левого верхнего угла прямоугольника
rsize - глобальная константа, которая хранит размер стороны квадрата
(x + rsize) - x-координата правого нижнего угла квадрата
(y - rsize) - y-координата правого нижнего угла квадрата

- slotMove() - выполняется примерно 30 раз в секунду. Главное, чтобы было больше, чем 24 кадра в секунду. В этой функции мы меняем координаты квадрата (глобальные переменные x и y) и вызываем updateGL(), чтобы спровоцировать вызов paintGL() и тем самым перерисовать квадрат с новыми координатами

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

- "Почему квадрат падает?" Потому что каждые "30 раз в секунду" вызывается функция slotMove() и уменьшает глобальную переменную y, которая хранит y-координату нашего квадрата

- windowWidth и windowHeight - глобальные переменные, которые хранят актуальные размеры клиентской области (области, в которой мы рисуем)

- glClearColor( 0.3f, 0.3f, 1.0f, 1.0f ) - с помощью этой функции мы задаём цвет фона. Первые три параметра - это соответственно: красный, зелёный, синий. Их можно менять в диапазоне [0.0, 1.0]. Четвёрный параметр нам не нужен, поэтому мы его выставляем в значение поумолчанию - в единицу

- glColor3f( 0.0f, 0.5f, 0.5f ); - с помощью этой функции мы задаём цвет нашего квадрата. Здесь так же: красный, зелёный, синий

- resizeGL() - не обращайте внимания на содержимое этой функции. Просто не трогайте её.

Продолжение: http://www.prog.org.ru/topic_27563_0.html (http://www.prog.org.ru/topic_27563_0.html)

Литература:
- OpenGL Суперкнига (http://rutracker.org/forum/viewtopic.php?t=670006) (диск к книге (http://rutracker.org/forum/viewtopic.php?t=742207))
- Beginning OpenGL Game Programming, 2nd edition, 2009 (book+code) (https://yadi.sk/d/ZJ2JmLyVcLB4U)

P.S. Эта же тема под другим ракурсом:
- http://www.gamedev.ru/code/forum/?id=193241 (http://www.gamedev.ru/code/forum/?id=193241)
- http://programmersforum.ru/showthread.php?t=265504 (http://programmersforum.ru/showthread.php?t=265504)


Название: Re: Инструкция по созданию заготовки для 2D игр (для начинающих)
Отправлено: kambala от Сентябрь 15, 2014, 13:17
лови симпу!

на геймдеве хорошие, годные комментарии.


Название: Re: Инструкция по созданию заготовки для 2D игр (для начинающих)
Отправлено: Igors от Сентябрь 16, 2014, 07:28
- glColor3f( 0.0f, 0.5f, 0.5f ); - с помощью этой функции мы задаём цвет нашего квадрата. Здесь так же: красный, зелёный, синий
Не надо "прикрываться начинающими". Если человек по имени ф-ции не понял что она примерно делает и нуждается в таких разжевываниях как Ваши - значит он полный идиот, и попытки его обучения есть бесполезная трата времени.

Подача такого материала на достаточно профессиональный форум никакой смысловой нагрузки не несет и воспринимается как навязчивая самореклама. Это раздражает. Хотите - пишите, но когда в след раз на Вас кто-то сорвется помните - Вы это 100% заслужили.
 


Название: Re: Инструкция по созданию заготовки для 2D игр (для начинающих)
Отправлено: Bepec от Сентябрь 16, 2014, 10:19
А давайте введём минусы и заминусуем Igors :)
Такие пояснения естественны И. И они нивелируют разницу между "профессионалом" и "новичком". Если они вам не нужны - пропускайте.

А так похоже на возгордившегося "профессионала". Я де много раз так делал, всё знаю. Пусть кто хочет, тот найдет описание функции - изучит его.  Такая точка зрения создаёт не руководства, а извращённое их подобие - когда вместо "прочитал и сделал" получается "прочитал, нашёл все описания функций, изучил их, изучил паттерн используемый в примере и ... бросил это дело, потому что писавший - *****" :)


Название: Re: Инструкция по созданию заготовки для 2D игр (для начинающих)
Отправлено: Igors от Сентябрь 16, 2014, 10:56
получается "прочитал, нашёл все описания функций, изучил их,
Да, так всегда было и будет, и усердное переписывание документации "в популярной форме" никак не помогает начинающему, только вредит. Чтение букваря никто не отменял и чем раньше новичок начнет - тем лучше. 


Название: Re: Инструкция по созданию заготовки для 2D игр (для начинающих)
Отправлено: Bepec от Сентябрь 16, 2014, 11:05
Ну тут уже современное образование напакостило.
Надо не забывать логическую цепочку.
Получить пример -> запустить пример -> по шагам разобрать работу примера -> модифицировать под свои нужды.
В случае подробной инструкции пропускается звено "по шагам разобрать работу примера", что уменьшает время до логического конца % на 80.

Если ваш девиз - обучаться. Тогда проходите всю цепочку.
Если же ваш девиз - использовать наработки других, вместо создания собственных велосипедов - то убираем шаг "по шагам разобрать работу примера".

PS дальше спорить бессмысленно. Своё мнение я выразил.


Название: Re: Пошаговая инструкция введения в OpenGL на Qt
Отправлено: 8Observer8 от Ноябрь 17, 2014, 17:15
Может кому пригодится: http://www.cyberforum.ru/blogs/416874/blog2944.html