Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Графика и игры
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 23.06.2012, 11:21
Аватар для DIGS
DIGS DIGS вне форума
Прохожий
 
Регистрация: 23.06.2012
Сообщения: 9
Версия Delphi: Borland Delphi7
Репутация: 10
По умолчанию Delphi+OpenGL помогите разобраться

Здравствуйте дорогие форумчане, сейчас учусь совмещать делфи и OpenGL хотя до сих пор я был знаком только с Delphi.
Я делаю учебную программу(учебную для себя) в которой вам нужно передвигаться стрелочками клавиатуры. Дело в том, что я не знаю, как сделать так, что бы появилась некая непроходимость стен.
Стену рисую обычным GL_QUADS.
вот сам код:
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OpenGL, ExtCtrls, Math;
 
type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
type
  User=record
    Position:record
      x,y,z:Single;
    end;
    Rotation:record
      y,zx:Single;
    end;
  end;
 
var
  Form1: TForm1;
  DC:HDC;
  HRC:HGLRC;
  Human:User;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
const
  SPEED=0.2;
  var tmpx,tmpy:real;
begin
  case key of
    27: Form1.Close;
    37: begin
          Human.Position.z:=Human.Position.z+
          sin(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x+
          cos(DegToRad(Human.Rotation.y))*SPEED;
        end;
    38: begin
          Human.Position.z:=Human.Position.z+
          cos(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x-
          sin(DegToRad(Human.Rotation.y))*SPEED;
        end;
    39: begin
          Human.Position.z:=Human.Position.z-
          sin(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x-
          cos(DegToRad(Human.Rotation.y))*SPEED;
        end;
    40: begin
          Human.Position.z:=Human.Position.z-
          cos(DegToRad(Human.Rotation.y))*SPEED;
          Human.Position.x:=Human.Position.x+
          sin(DegToRad(Human.Rotation.y))*SPEED;
        end;
  end;
 
//---Как по мне, так именно тут должна находиться проверка на столкновения... только почему то она //не работает..
    tmpx:=human.position.x;
    tmpy:=human.position.y;
   
  if (Human.position.z<1) //and (human.Position.x>1)
   and (Human.Position.x<1)
   then
  begin
   Human.Position.z:=Human.Position.z+1;
  Human.Position.x:=Human.Position.x+1;
  end;
//---
  end;
 
procedure SetDCPixelFormat;
var
  pfd:TPixelFormatDescriptor;
  nPixelFormat:Integer;
begin
  FillChar(pfd,SizeOf(pfd),0);
  pfd.dwFlags:=PFD_DRAW_TO_WINDOW or
               PFD_DOUBLEBUFFER or
               PFD_SUPPORT_OPENGL;
  nPixelFormat:=ChoosePixelFormat(DC,@pfd);
  SetPixelFormat(DC,nPixelFormat,@pfd);
end;
 
procedure TForm1.FormCreate(Sender: TObject);
var
  i:Integer;
begin
  DC:=GetDC(Handle);
  SetDCPixelFormat;
  HRC:=wglCreateContext(DC);
  wglMakeCurrent(DC,HRC);
  Form1.WindowState:=wsMaximized;
  ShowCursor(False);
  glClearColor(0.0,0.0,0.0,1.0);
  glEnable(GL_DEPTH_TEST);
  glNewList(1,GL_COMPILE);
    glBegin(GL_LINES);
      glColor3f(0.7,1.0,0.7);
      for i:=-50 to 50 do
      begin
        glVertex3f(-50,-1,i);
        glVertex3f(50,-1,i);
        glVertex3f(i,-1,-50);
        glVertex3f(i,-1,50);
      end;
       glColor3f(1,0,0);
      for i:=-5 to 5 do
      begin
   glBegin(GL_QUADS);
    // back Face
    glColor3f(1,0,0); glVertex3f(-1, -11);
    glColor3f(1,0,0); glVertex3f(0, -11);
    glColor3f(1,0,0); glVertex3f(011);
    glColor3f(1,0,0); glVertex3f(-111);
    // front Face
    glColor3f(0,1,0); glVertex3f(-1, -1, -1);
    glColor3f(0,1,0); glVertex3f(-11, -1);
    glColor3f(0,1,0); glVertex3f(01, -1);
    glColor3f(0,1,0); glVertex3f(0, -1, -1);
    // Top Face
    glColor3f(0,0,1); glVertex3f(-1, 1, -0.5);
    glColor3f(0,0,1); glVertex3f(-110.5);
    glColor3f(0,0,1); glVertex3f(010.5);
    glColor3f(0,0,1); glVertex3f(01, -0.5);
    // Bottom Face
    glColor3f(0,1,1); glVertex3f(-1, -1, -0.5);
    glColor3f(0,1,1); glVertex3f(0, -1, -0.5);
    glColor3f(0,1,1); glVertex3f(0, -10.5);
    glColor3f(0,1,1); glVertex3f(-1, -10.5);    
    // Right face
    glColor3f(1,1,1); glVertex3f(0, -1, -1);
    glColor3f(1,1,1); glVertex3f(01, -1);
    glColor3f(1,1,1); glVertex3f(011);
    glColor3f(1,1,1); glVertex3f(0, -11);
    // Left Face
    glColor3f(1,0,1); glVertex3f(-1, -1, -1);
    glColor3f(1,0,1); glVertex3f(-1, -11);
    glColor3f(1,0,1); glVertex3f(-111);
    glColor3f(1,0,1); glVertex3f(-11, -1);
  glEnd();
      end;
    glEnd;
  glEndList;
  with Human do
  begin
    with Position do
    begin
      x:=5;
      y:=0;
      z:=0;
    end;
    with Rotation do
    begin
      y:=0;
      zx:=0;
    end;
  end;
  SetCursorPos(Round(Form1.ClientWidth/2),
               Round(Form1.ClientHeight/2));
 
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  wglMakeCurrent(0,0);
  wglDeleteContext(HRC);
  ReleaseDC(Handle,DC);
  DeleteDC(DC);
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  SetCursorPos(Round(Form1.ClientWidth/2),
               Round(Form1.ClientHeight/2));
  InvalidateRect(Handle,nil,false);
end;
 
procedure TForm1.FormResize(Sender: TObject);
begin
  glViewport(0, 0, ClientWidth, ClientHeight);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity;
  gluPerspective(30.0, ClientWidth / ClientHeight, 0.1, 1000.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;
 
procedure TForm1.FormPaint(Sender: TObject);
var
  ps:TPaintStruct;
begin
  BeginPaint(Handle,ps);
  glClear(GL_COLOR_BUFFER_BIT or
          GL_DEPTH_BUFFER_BIT);
 
  glLoadIdentity;
  glRotatef(Human.Rotation.zx,Abs(cos(DegToRad(Human.Rotation.y))),0,0);
  glRotatef(Human.Rotation.y,0,1,0);
  glTranslatef(Human.Position.x,
               Human.Position.y,
               Human.Position.z);
 
  glCallList(1);
 
  EndPaint(Handle,ps);
  SwapBuffers(DC);
end;
 
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
const
  Divider=10;
begin
  Human.Rotation.y:=Human.Rotation.y+
      Round((Mouse.CursorPos.X-Round(Form1.ClientWidth/2))/Divider);
  if Human.Rotation.y>=360 then Human.Rotation.y:=0;
  if Human.Rotation.y<0 then Human.Rotation.y:=360;
 
  Human.Rotation.zx:=Human.Rotation.zx+
      Round((Mouse.CursorPos.Y-Round(Form1.ClientHeight/2))/Divider);
  if Human.Rotation.zx>90 then Human.Rotation.zx:=90;
  if Human.Rotation.zx<-90 then Human.Rotation.zx:=-90;
end;
 
end.

Возможно я делаю даже не правильными методами, помогите, пожалуйста, разобраться.
p.s. так же прикрепляю сам проект
Вложения
Тип файла: rar Engine_3D.rar (167.9 Кбайт, 12 просмотров)
Ответить с цитированием
  #2  
Старый 23.06.2012, 17:41
Аватар для Pilot_Red
Pilot_Red Pilot_Red вне форума
Продвинутый
 
Регистрация: 01.11.2006
Адрес: Карелия
Сообщения: 702
Версия Delphi: D7
Репутация: 11581
По умолчанию

Если посмотреть сверху, то у тебя куб образует квадрат, квадрат состоит из 4 отрезков (x1,z1)(x2,z1) .....
Ты двигаешься тоже вдоль какой-то линии от старых координат к новым
В общем вся задача сводится к тому, чтобы проверить пересечение линии движения с линиями препятствия

См. рис.
Ответить с цитированием
  #3  
Старый 23.06.2012, 18:59
Аватар для DIGS
DIGS DIGS вне форума
Прохожий
 
Регистрация: 23.06.2012
Сообщения: 9
Версия Delphi: Borland Delphi7
Репутация: 10
По умолчанию

как сделать это логически я понимаю, а вот как представить это в коде-нет.
Я пришел к такому выводу пока, я описал квадрат проверками, т.е. если я нахожусь в шаге от того квадрата, то просто прекратить движение. т.е. я завел переменную типа boolean и если я в шаге от квадрата я присваиваю ей "ложь" что в переделанном коде значит, что я не могу двигаться...
Мой вариант мне не очень подходит, так как в таком случае я не могу двигаться вообше, а мне надо что бы только в сторону куба
Ответить с цитированием
  #4  
Старый 23.06.2012, 21:45
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Стоит завести переменную не Boolean, а перечисляемого типа (Step = (sLeft, sRight, sTop, sDown)). И запрещать только одно направление.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #5  
Старый 23.06.2012, 22:57
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Лучше разбить куб на треугольники и искать точку пересечения отрезка (как на рисунке Pilot_Red) с этими треугольниками. В случае пересечения присваивать "игроку" координаты точки пересечения. Тогда "игрок" будет как-бы "скользить" вдоль стены (если направление не вдоль нормали к стене).
И обрабатывать передвижение лучше не сразу при нажатии клавиш, а завести отдельные переменные (типа bool movleft, movright, movforv, movback), при нажатии/отпускании соответствующей клавиши давать им true/false, а в процедуре отрисовки (или отдельном таймере) "перемещать" игрока соответственно их значению.
Ответить с цитированием
  #6  
Старый 23.06.2012, 23:28
Аватар для DIGS
DIGS DIGS вне форума
Прохожий
 
Регистрация: 23.06.2012
Сообщения: 9
Версия Delphi: Borland Delphi7
Репутация: 10
По умолчанию

а как вот можно проверить столкновение вообще с чем-либо, без использования координат, т.е. сравнения координаты персонажа и координат обьектов?
Ответить с цитированием
  #7  
Старый 24.06.2012, 13:25
Anklav Anklav вне форума
Прохожий
 
Регистрация: 10.06.2011
Адрес: Харьков
Сообщения: 22
Версия Delphi: 7
Репутация: 10
По умолчанию

Используй физические движки.
Ответить с цитированием
  #8  
Старый 24.06.2012, 13:36
Аватар для DIGS
DIGS DIGS вне форума
Прохожий
 
Регистрация: 23.06.2012
Сообщения: 9
Версия Delphi: Borland Delphi7
Репутация: 10
По умолчанию

поподробнее и в коде пожалуйста
Ответить с цитированием
  #9  
Старый 24.06.2012, 14:48
Anklav Anklav вне форума
Прохожий
 
Регистрация: 10.06.2011
Адрес: Харьков
Сообщения: 22
Версия Delphi: 7
Репутация: 10
По умолчанию

Как бы физический движок это компонент который устанавливается допустим в делфи, или идет в комплекте с каким нибудь 3д движком..

Лично сам делал без сторонних физических движков.
Алгоритм следующий, создается массив из элеметов (целочисленных переменных допустим) допустим 15х15, то есть в 224 элемента. Это будет карта, суть следующая: при значении 0 мы данный квадрат проезжаем, при 1 - нет.

Для начала нужно разделить этот массив в плоскость. Делаем это следующими функциями

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
...
var
map:array [0..224] of integer; //наша карта
NtoX,NtoY:integer;
 
...
 
//Тут все понятно, вводишь x и y и тебе выдают номер квадрата
//15 - это число квадратов на карте
Function TForm1.XYToN(x,y:integer):integer;
var
N:integer;
begin
N:=(x+y*15);
Result:=N;
end;
 
//для этой функции понадобится 2 глобальные переменные
//так как вывести нам нужно 2 значения
//15 - это число квадратов на карте
//Здесь эти перменные: "NtoX" - это собственно Х и "NtoY" - это Y.
Procedure TForm1.NToXY(N:integer);
var
NtoXDemo:Extended;
begin
NtoY:=Trunc(N/15);
NtoXDemo:=Frac(N/15)*15;
NtoX:=Round(NtoXDemo);
end;
 
//Допустим тебе известны координаты квадрата (это будут переменные
// X,Y) и тебе нужно изменить значение матрицы
 
 
procedure TForm1.Button1Click(Sender: TObject);
begin
map[XYtoN(X,Y)]:=0;
end;
 
//Или тебе известен номер квадрата
//и тебе нужно узнать где он находится
//NomerK это будет известный тебе номер квадрата
//X и Y искомые кординаты
 
procedure TForm1.Button2Click(Sender: TObject);
begin
NtoXY(NomerK);
X:=NtoX;
Y:=NtoY;
end;

Но это мы просто работаем с массивом, для связи координат того же OpenGL и нашей карты нужны следующие функции:

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//Данная функция переводит X или Y OpenGL в X или Y карты (map)
//у нас 1 квадрат имеет длину и ширину в 0.25
 
Function TForm1.PixToK(K:Extended):integer;
var
i:integer;
MasPix:array [0..14] of Extended; //Длинна или ширина карты
begin
MasPix[0]:=0;
For i:=1 to 14 do
  begin
    MasPix[i]:=MasPix[i-1]+0.25;//0.25 это длинна квадрата в OpenGL
  end;
 
For i:=0 to 14 do
  begin
    If (MasPix[i]<=K) and (MasPix[i]+0.25>K) then Result:=i;
  end;
end;
 
//Данная функция переводит X или Y (map) в X или Y OpenGL
//у нас 1 квадрат имеет длину и ширину в 0.25
Function TForm1.KToPix(p:integer):Extended;
var
i:integer;
NPix:Extended;
begin
NPix:=0;
For i:=0 to p-1 do NPix:=NPix+0.25;
Result:=NPix;
end;
 
//Примеры X Y - координаты(в OpenGL) нашего героя
//0.01 шаг его ходьбы
//Angle - угол движения героя
procedure TForm1.Button1Click(Sender: TObject);
begin
//если с следующем шаге
//мы поападаем в квадрат с значением 0, то идем дальше
If Map[XYToN(PixToK(X+0.01*cos(Angle)),PixToK(Y+0.01*sin(Angle)))] = 0 then
      begin
        X:=X+0.01*cos(angle);
        Y:=Y+0.01*sin(angle);
      end;
end;

P.S. Видел эту программу в исходниках на сайте..
P.S.S. И по моему для рисования каждой грани объекта нужно заново объявлять glBegin(GL_QUADS); .. glEnd; там достаточно 1 раз указать цвет.
Т.к. скорее всего будут проблемы с нормалями, а они нужны для правильного освещения.

Последний раз редактировалось Anklav, 24.06.2012 в 16:38.
Ответить с цитированием
  #10  
Старый 24.06.2012, 16:34
Pyro Pyro вне форума
Так проходящий
 
Регистрация: 18.07.2011
Сообщения: 805
Версия Delphi: 7Lite
Репутация: 6063
По умолчанию

на gamedev.ru должны быть разжеванные статьи про это, на крайний случай можно на английском найти
Ответить с цитированием
  #11  
Старый 24.06.2012, 17:52
Аватар для DIGS
DIGS DIGS вне форума
Прохожий
 
Регистрация: 23.06.2012
Сообщения: 9
Версия Delphi: Borland Delphi7
Репутация: 10
По умолчанию

Anklav
Не могли бы вы, встроить этот код что вы написали в мое приложение??
У меня не получается...=(
Ответить с цитированием
  #12  
Старый 24.06.2012, 20:42
Anklav Anklav вне форума
Прохожий
 
Регистрация: 10.06.2011
Адрес: Харьков
Сообщения: 22
Версия Delphi: 7
Репутация: 10
По умолчанию

Как встроить? Чему вы научитесь, если за вас все будут делать?

P.S. http://dump.ru/file/5778289
Танчики написанные мной на чистом OpenGL без ботов, но с разрушаемыми препятствиями.

P.S.S. Да и кстати, тонкий намек, проверка проходимость должна быть, как бы, до движения... а не после... Я бы посоветовал бы вам, начать не с 3д редакторов, а хотя бы 2д, что бы уловить суть, надо начинать с малого. А на счет того кода который должен работать, по мне так он работает, только вы как то странно его написали.

Последний раз редактировалось Anklav, 24.06.2012 в 20:54.
Ответить с цитированием
  #13  
Старый 24.06.2012, 22:42
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Вот например, как я писал, проверка по треугольникам. Но добавлены 2 модуля, большинство ф-ций из них не используется, можешь юзать, разрешаю (сам "одолжил" с чужого проекта, немного доработав). Проверка не пересечения линии движения, а границ обьекта, так недежней. Надеюсь разберешся. Это только пример, начинать обучение с него нельзя.
Вложения
Тип файла: rar Engine_3D.rar (215.7 Кбайт, 18 просмотров)
Ответить с цитированием
  #14  
Старый 24.06.2012, 22:51
Аватар для DIGS
DIGS DIGS вне форума
Прохожий
 
Регистрация: 23.06.2012
Сообщения: 9
Версия Delphi: Borland Delphi7
Репутация: 10
По умолчанию

YVitaliy
Спасибо большое, но не могли бы вы обьяснять, куда надо что добавить, что бы заработало и с другими стенами, вот нарисовать я их нарисовал, а дальше что?=)
Заранее еще раз спасибо
Ответить с цитированием
  #15  
Старый 24.06.2012, 22:59
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Из модуля l_math.pas я использую класс TVector - точка с координатами X, Y, Z. Соответственно стену я рисую по 4м точкам - векторам v1, v2, v3..., которые задаю при создании формы
Код:
1
2
3
v1:=vector(-2,-1,-2);
          v2:=vector(-2,2,-2);
..........
Код:
1
2
GLCOLOR3(ColorRGBV(clRed));
        GLQuad(v1, v2, v3, v4);
Вот добавляй такие векторы, задавай их координаты и рисуй. Конечно, лучше не "вручную" рисовать, а загружать соответствующую модель из файла. Поетому советую, например, книгу Краснов OpenGl с примерами, сам с нее начинал, там есть простые примеры, и вообще все азы.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 17:35.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025