Урок 8 - Игровая камера

  В этом уроке я опишу, как сделать игровую камеру, т. е. камера, управляемая при помощи мышки и клавиатуры. Можно будет смотреть во все стороны и передвигаться.

Разбираем код программы:
В раздел Var заносим переменные:

MouseMove1: boolean;
  TempX1,TempY1,SingX,SingY,TempX2,TempY2 : integer;
  Point: Tpoint;
  Camera: TCamera;
В процедуре FormPaint:
try                                                      
if MouseMove1=false then                                 
begin                                                    
GetCursorPos(Point);                                     
TempX1:=point.X;                                         
TempY1:=point.Y;                                         
MouseMove1:=true;                                        
end;                                                     
finally                                                  
                                                         
SetCursorPos(screen.Width div 2,screen.Height div 2); //Центруем курсор
GetCursorPos(Point) ;  //получаем координаты и записываем их в переменную Point
 if MouseMove1=true then                                               
  begin                                                  
TempX2:=point.X;                                         
TempY2:=point.Y;                                         
SingX:=TempX1-TempX2;                                    
SingY:=TempY1-TempY2;                                    
if  (Camera.phiY<=90) and (Camera.phiY>=-90) then        
 begin                                                   
 Camera.phiY:=Camera.phiY+(-SingY/8);                    
 end                                                     
 else                                                    
 begin                                                   
   if Camera.phiY>=90 then  //Ограничения           
  Camera.phiY:=90;          //На 
  if Camera.phiY<=-90 then  //Угол обзора 
  Camera.phiY:=-90;         //По вертикали
  end;                                                 
Camera.phiX:=Camera.phiX+(-SingX/4);                     
TempX1:=0;                                               
TempY1:=0;                                               
TempX2:=0;                                               
TempY2:=0;                                               
SingX:=0;                                                
SingY:=0;                                                
MouseMove1:=false;                                       
 end;                                                    
end;                 

Конструкция try finally здесь обязательна т.к. сначала надо получить координаты курсора и только после этого позволить ему сместится и опять засечь его координаты.

Переменные TempX1 и TempY1 – координаты до смещения.
Переменные TempX2 и TempY2 – координаты после смещения.
Переменные SingX и SingY – разница между предыдущими и новыми координатами.

Для работы кода необходимо создать 2 составных типа переменных:
type

   TVector = record  //Вектор
   X,Y,Z:GLfloat;
   end;


   TCamera = record
   Pos: Tvector;       //Позиция камеры
   PhiY: single;         //вертикальный улол поворота камеры
   PhiX: single;         //горизонтальный
   Speed: glFloat;   //Скорость камеры
   end;
Коэффициенты смещения по горизонтали и вертикали делятся на 4 и 8 – это чувствительность мыши.

Мы будем поворачивать и двигать не камеру а МИР вокруг камеры. Самыми простыми функциями glRotatef и glTranslatef
ВАЖНО: Эти функции нужно вызывать в особом порядке!!!

Сначала повернем мир по вертикале, а потом по горизонтали и совершим перемещение.
glRotatef(-Camera.PhiY-90,1,0,0); //поворот по вертикали
glRotatef(-Camera.PhiX,0,0,1);     //поворот по горизонтали
glTranslatef(-Camera.Pos.X,-Camera.Pos.Y,-Camera.Pos.Z);  //смешение мира
Это нужно делать до отрисовки сцены, позиции источников света тоже надо задавать после. Теперь надо сделать обработку клавиатуры.

В раздел Const:
VK_W = $57;
VK_S = $53;
VK_D = $44;
VK_A = $41;
VK_SHIFT = $10;
VK_SPACE = $20;
В процедуре FormPaint после обработки мыши:
if (GetAsyncKeyState(VK_W)<>0) or (GetAsyncKeyState(VK_S)<>0) or
    (GetAsyncKeyState(VK_D)<>0) or (GetAsyncKeyState(VK_A)<>0)  then
  begin
   Camera.Speed:=0.005;

if (GetAsyncKeyState(VK_W)<>0) then
   begin
    Camera.Pos.X:=Camera.Pos.X+Camera.Speed*cos((Camera.phiX+90)*Pi/180);
    Camera.Pos.Y:=Camera.Pos.Y+Camera.Speed*sin((Camera.phiX+90)*Pi/180);
   end;
     //Назад
   if (GetAsyncKeyState(VK_S)<>0) then
   begin
    Camera.Pos.X:=Camera.Pos.X+Camera.Speed*cos((Camera.phiX-90)*Pi/180);
    Camera.Pos.Y:=Camera.Pos.Y+Camera.Speed*sin((Camera.phiX-90)*Pi/180);
   end;
     //Вправо
   if (GetAsyncKeyState(VK_D)<>0) then
   begin
    Camera.Pos.X:=Camera.Pos.X+Camera.Speed*cos((Camera.phiX)*Pi/180);
    Camera.Pos.Y:=Camera.Pos.Y+Camera.Speed*sin((Camera.phiX)*Pi/180);
   end;
     //Влево
   if (GetAsyncKeyState(VK_A)<>0) then
   begin
    Camera.Pos.X:=Camera.Pos.X+Camera.Speed*cos((Camera.phiX+180)*Pi/180);
    Camera.Pos.Y:=Camera.Pos.Y+Camera.Speed*sin((Camera.phiX+180)*Pi/180);
   end;
  end;
//Вниз
  if (GetAsyncKeyState(VK_SHIFT)<>0) then   Camera.Pos.Z:=Camera.Pos.Z-0.005;
//Вверх
  if (GetAsyncKeyState(VK_SPACE)<>0) then   Camera.Pos.Z:=Camera.Pos.Z+0.005;
Функция GetAsyncKeyState(индекс) отслеживает нажатия клавиш в системе независимо статуса активности приложения.

Управление:

W – Вперёд
S – Назад
A – Влево
D – Вправо
Shift – Вниз
Space – Вверх

И нарисуем сцену:
glBindTexture(GL_TEXTURE_2D,Glass);
RenderBox; //куб

glBindTexture(GL_TEXTURE_2D,Eart);
glBegin(GL_QUADS);
glNormal(0.5,0.5,1);
glTexCoord(0,1); glVertex3f(-10,10,-1.1);
glTexCoord(1,1); glVertex3f(10,10,-1.1);
glTexCoord(1,0); glVertex3f(10,-10,-1.1);
glTexCoord(0,0); glVertex3f(-10,-10,-1.1);
glEnd;
В этом примере появилась новая функция задания перспективы:
gluPerspective(Угол обзора, ClientWidth/ClientHeight,ближайшая точка, дальняя точка);



Осталось только сделать в ObjectIspector параметр Form1.BorderStyle = none и WindowState = maximize. Всё простенькая игра готова.



Добавил(а): oktavius Дата: 2012-11-21
А как загрузить карту с 3dMax?



Добавил(а): Klesh Дата: 2012-11-21
Окей, в ближайшее время будет опубликован урок по экспорту модели в формате 3DS из 3ds max.



Добавил(а): oktavius Дата: 2012-11-22
Отлично буду очень рад)



Добавил(а): juzhnij Дата: 2013-05-20
У меня возникла проблема с которой я никак не могу справиться - когда я разворачиваюсь в виртуальном пространстве все текстуры начинают просвечиваться насквозь, мне набо накладывать на те же координаты текстуры в обратную сторону или есть проще решение?



Добавил(а): juzhnij Дата: 2013-05-20
Ну и плюс к этому в движении иногда текстура на текстуру в какой то части накладывается, как будто они по многу раз за кадр прорисовываются.



Добавил(а): juzhnij Дата: 2013-05-22
Спасибо за неучастие, проблему решил самостоятельно.



Добавил(а): evgen8195 Дата: 2014-05-12
Вопрос: как сделать так чтобы отображался и двигался(!) курсор мыши?


    No results found.
Отменить.