[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Стрельба
BagrationДата: Среда, 05 Декабря 2007, 16:46 | Сообщение # 1
Начинающий
Группа: Пользователи
Сообщений: 7
Награды: 0
Замечания: 0%
Статус:
Подскажите идейки реализации стрельбы

С уважением, Багратион.
 
Терминатор01Дата: Суббота, 08 Декабря 2007, 10:07 | Сообщение # 2
Продвинутый
Группа: Участники
Сообщений: 191
Награды: 0
Замечания: 0%
Статус:
Спасибо. Отличное объяснение.
 
ГостьДата: Среда, 12 Декабря 2007, 15:08 | Сообщение # 3
Группа: Гости





Delmi, ефекты спрайтами делай или юзай спец либы.
 
DrawДата: Пятница, 21 Декабря 2007, 11:53 | Сообщение # 4
Продвинутый
Группа: Участники
Сообщений: 194
Награды: 0
Замечания: 0%
Статус:

Команда: DeforShys
Проектов: 8 (2 активных 6 инактив)
А нет ли другово способа?


ICQ 557709132 пиши. Отвечу на любой вопрос по блицу
 
DrawДата: Воскресенье, 23 Декабря 2007, 21:26 | Сообщение # 5
Продвинутый
Группа: Участники
Сообщений: 194
Награды: 0
Замечания: 0%
Статус:

Команда: DeforShys
Проектов: 8 (2 активных 6 инактив)
А разве pick'ованием нельзя?


ICQ 557709132 пиши. Отвечу на любой вопрос по блицу


Сообщение отредактировал Draw - Воскресенье, 23 Декабря 2007, 21:30
 
SKOFILDДата: Четверг, 15 Октября 2009, 13:22 | Сообщение # 6
Врубающийся
Группа: Пользователи
Сообщений: 32
Награды: 0
Замечания: 40%
Статус:
скажите плизззззз как зделать чтобе стрельба происходила из того места где у меня находиться камера и в то место куда она смотрет(камета движеться)
вот код

For d.Dude=Each Dude
MoveEntity d\entity,0,0,1
If EntityDistance(cam,d\entity)>200
FreeEntity d\entity
Delete d
EndIf
Next
If MouseHit(1)
For k=1 To 1
sphere=LoadSprite("BLUSPARK.bmp")
EntityType sphere,Typesphere
PositionEntity sphere,0,0,0
HideEntity sphere
If bul=0
d.Dude=New Dude
d\entity=CopyEntity( sphere)
EndIf
Next
EndIf

 
maxturboДата: Четверг, 15 Октября 2009, 14:07 | Сообщение # 7
Профи
Группа: Участники
Сообщений: 379
Награды: 0
Замечания: 0%
Статус:

Профессия: Программер
Проектов: 1 в разработке
Наэтом форуме не раз обсуждалась эта тема, включи поиск и поюзай!!!
 
maxturboДата: Четверг, 15 Октября 2009, 14:10 | Сообщение # 8
Профи
Группа: Участники
Сообщений: 379
Награды: 0
Замечания: 0%
Статус:

Профессия: Программер
Проектов: 1 в разработке
А вот собственно пример выстрела
Code

Graphics3D 640,480,32,2
SetBuffer BackBuffer()
cam=CreateCamera()
PositionEntity cam,0,3,-10
lit=CreateLight()
Type Dude
Field entity,speed#
End Type
Repeat

For d.Dude=Each Dude
MoveEntity d\entity,0,0,1
If EntityDistance(cam,d\entity)>200
FreeEntity d\entity
Delete d
EndIf
Next  
If MouseHit(1)
For k=1 To 1
sphere=CreateSphere()
HideEntity sphere
If bul=0
d.Dude=New Dude
d\entity=CopyEntity( sphere )
EndIf
Next
EndIf
RenderWorld
UpdateWorld
Flip
Until KeyHit(1)
End
 
maxturboДата: Четверг, 15 Октября 2009, 14:15 | Сообщение # 9
Профи
Группа: Участники
Сообщений: 379
Награды: 0
Замечания: 0%
Статус:

Профессия: Программер
Проектов: 1 в разработке
Вот описание создание пуль правда не в b3d

Сначала затронем тему оптимизации. Проблема состоит в том, что для каждой пули мы в каждом кадре считаем SIN и COS угла полёта. При большом количестве пуль это существенно скажется на FPS игры, всё будет "дёргаться". Вот эта часть кода:
// если летит, то
if (pulki[i].letit=true) then
begin
DrawPulka(pulki[i].x,pulki[i].y,pulki[i].phi); // рисуем
pulki[i].life:=pulki[i].life+1; // увеличиваем время полёта
with pulki[i] do x:=x+3*cos(phi*3.14/180);
with pulki[i] do y:=y+3*sin(phi*3.14/180);
end;
Но если пуля летит прямолинейно, то переменная pulki[i].phi не меняется. Например, PHI = 45 градусов. Косинус cos(45*3.14/180) не меняется. Кстати, почему cos(45*3.14/180), а не cos(45)? Дело в том, что функция COS в Delphi принимает аргумент в радианах. Домножение на *3.14/180 служит для перевода градусов в радианы.
Итак, PHI=45, и cos(45)=const. И пока пуля i летит, кадр за кадром будет выполняться следующий код:
with pulki[i] do x:=x+3*cos(phi*3.14/180);
with pulki[i] do y:=y+3*sin(phi*3.14/180);
Обозначим приращение так:
dx:=3*cos(phi*3.14/180);
dy:=3*sin(phi*3.14/180);
Тогда выражения для полёта пули переменятся:
dx:=3*cos(phi*3.14/180);
dy:=3*sin(phi*3.14/180);
with pulki[i] do x:=x+dx;
with pulki[i] do y:=y+dy;
Здесь всё просто. Раз пуля не меняет направление, то PHI=const. То есть значение угла PHI постоянно. А раз угол один и тот же, то и косинусы с синусами будут константами. Таким образом, переменные dx и dy тоже константы.
Для оптимизации достаточно посчитать dx и dy один раз, когда пуля только-только вылетает. Изменим описание пули. Раньше тип "пулька" выглядел так:
type Tpulka=record
x,y:single; // координаты
phi:single; // направление полёта пули
letit:boolean; // true - летит, false - уже не летит (не существует)
life:integer; // сколько прошло времени после выстрела
end;
Теперь мы заменим угол phi на приращения dx и dy:
type Tpulka=record
x,y:single; // координаты
dx,dy:single; // направление полёта пули
letit:boolean; // true - летит, false - уже не летит (не существует)
life:integer; // сколько прошло времени после выстрела
end;
А теперь посмотрим, как изменится процесс выстрела. Раньше это выглядело так:
temp:=false; - если нашли пулю, то будет true
if klavishi.probel=true then - нажат пробел
for i:=0 to 100 do - пройдёмся по всем пулям
begin
// если пулька не летит - значит свободна
if pulki[i].letit=false then
begin
задаём пульке направление,
совпадающее с координатами X,Y и направлением игрока (PHI):
pulki[i].x:=igrok1.x+3*cos(phi*3.14/180);
pulki[i].y:=igrok1.y+3*sin(phi*3.14/180);
pulki[i].phi:=igrok1.phi;
pulki[i].letit:=true; - пуля летит
pulki[i].life:=0; - пуля выпущена ТОЛЬКО ЧТО, то есть время равно НУЛЮ
temp:=true - пуля найдена, поиск можно прекратить
end;
if temp=true then break; // нашли пульку - можно выходить из цикла
end;
Вместо того, чтобы записывать угол, под которым летит пуля, мы подсчитаем приращения заранее:
pulki[i].phi:=igrok1.phi;
меняем на
pulki[i].dx:=3*cos(phi*3.14/180);
pulki[i].dy:=3*sin(phi*3.14/180);
и код выглядит так:
temp:=false; - если нашли пулю, то будет true
if klavishi.probel=true then - нажат пробел
for i:=0 to 100 do - пройдёмся по всем пулям
begin
// если пулька не летит - значит свободна
if pulki[i].letit=false then
begin
задаём пульке направление,
совпадающее с координатами X,Y и направлением игрока (PHI):
pulki[i].x:=igrok1.x+3*cos(phi*3.14/180);
pulki[i].y:=igrok1.y+3*sin(phi*3.14/180);
pulki[i].dx:=3*cos(phi*3.14/180);
pulki[i].dy:=3*sin(phi*3.14/180);
pulki[i].letit:=true; - пуля летит
pulki[i].life:=0; - пуля выпущена ТОЛЬКО ЧТО, то есть время равно НУЛЮ
temp:=true - пуля найдена, поиск можно прекратить
end;
if temp=true then break; // нашли пульку - можно выходить из цикла
end;
Для перемещения теперь уже не потребуется каждый кадр подсчитывать значения SIN и COS, так как это было сделано один раз (при выстреле). Подсчитанные значения мы занесли в pulki[i].dx и pulki[i].dx. Ну а теперь реализуем код перемещения пули. Раньше этот код выглядел так:
with pulki[i] do x:=x+3*cos(phi*3.14/180);
with pulki[i] do y:=y+3*sin(phi*3.14/180);
А теперь вот так:
with pulki[i] do x:=x+dx;
with pulki[i] do y:=y+dy;
В этом и заключается оптимизация. Две строчки выше - это оптимизированное перемещение пули. Но здесь возникает одна проблема: а вдруг в вашей игре пули могут лететь не только по прямой, но и отклоняться от своей траектории. Что делать в этом случае? Вернёмся к старому коду, посмотрим на него:
with pulki[i] do x:=x+3*cos(phi*3.14/180);
with pulki[i] do y:=y+3*sin(phi*3.14/180);
Ведь если phi пули меняется во время полёта, то SIN и COS придётся рассчитывать каждый кадр. А если это не пули, а самонаводящиеся ракеты, то без изменения угла PHI вообще не обойтись! Что здесь можно оптимизировать? Неужели нет способа избавиться от медленного просчёта сотен СИНУСОВ и КОСИНУСОВ каждый кадр?
Способ такой есть! И он уже применяется с давних времён в играх, а больше всего - в демомейкинге. Если вы не знаете, что такое demomaking, то посетите сайты http://www.demoscene.ru и http://www.democoder.ru. На первом сайте вы сможете найти готовые красивые демки с потрясной графикой и звуком, а на втором - узнаете как делаются демки.
Так вот, в демомейкинге с давних пор применяют различные оптимизации и ухищрения. Дело в том, что для создания крутых спецэффектов приходится вычислять значения SIN-усов и COS-инусов тысячи раз. И даже больше.
Метод заключается в следующем: мы создаём "кеш" значений SIN и COS. То есть мы просчитываем для основных углов занчения SIN и COS заранее (в самом начале программы) и заносим эти значения в массив. Вместо тригонометрических функций в самой игре или демке потом используют массив вместо функции.
Делается это так. сначала мы задаём массивы с кешем:
sinmassiv:array[0..360] of single;
cosmassiv:array[0..360] of single;
А потом подсчитываем значения тригонометрических функций и заносим их в массивы:
for i:=0 to 360 do sinmassiv[i]:=sin(i*3.14/180);
for i:=0 to 360 do cosmassiv[i]:=cos(i*3.14/180);
Теперь в нашей игре мы можем использовать вместо SIN и COS подсчитанные заранее значения, которые есть в массивах sinmassiv и cosmassiv.
Например, мы хотим подсчитать значение косинусы угла 135 градусов. Раньше это выглядело бы так:
a:=sin(135*3.14/180)
Намного быстрее использовать значение из кеша. Использовать кеш очень просто:
a:=sinmassiv[135]
Ну а если угол 15.4817? В этом случае имеет место число с точкой. Придётся округлить значение угла:
a:=sinmassiv[round(15.4817)]
Разумеется, здесь теряется точность. Ещё небольшой ньюанс заключается в том, что угол в вашей игре может меняться не только от 0 до 360, но и дальше. Например, это может быть -1. Или 376 градусов. В этом случае вы должны просто воспользоваться тем, что SIN и COS обладают периодичностью, т.е. через каждые 360 градусов происходит повторение значений. И поэтому:
sin(376)=sin(16)
а для -1 градуса:
sin(-1)=sin(359)
Итак, мы разобрались с вопросом оптимизации. Теперь перейдём к теме 2D/3D игр. Чтобы применить пули в 3D пространстве, достаточно хорошо разобраться в 2D. Посмотрим как мы задавали пулю в 2D:
type Tpulka=record
x,y:single; // координаты
dx,dy:single; // направление полёта пули
letit:boolean; // true - летит, false - уже не летит (не существует)
life:integer; // сколько прошло времени после выстрела
end;
Что такое dx, dy? Это приращение, которое каждый кадр прибавляется к координатам x, y. Смысл такой: dx, dy - это вектор. Вектор скорости пули. А так как формула
S=V*t
где S - путь, V - скорость, t - время, то
x:=x+dx*1;
y:=y+dy*1;
Причём t=1, так как мы считаем его не в секундах, а в кадрах. За один кадр пуля пролетает вот столько. Сам вектор скорости выглядит так: (dx,dy). Например, если мы обозначим вектор положения пули за POZ, а скорость пули за SKOR, то векторно перемещение пули будет выглядеть так:
POZ = POZ + SKOR,
где POZ, SKOR - вектора.
Эта формула подходит и для 3D пространства. Наример, если у вас есть скелетно анимированная модель, то вы всегда занаете вектор, соответствующий направлению оружия:
napr.x:=...
napr.y:=...
napr.z:=...
И знаете координату пушки в пространстве:
pushka.x:=...
pushka.y:=...
pushka.z:=...
Чтобы осуществить движение пули, достаточно сделать следующее:
pulya.x:=pulya.x+pulya.napr.x;
pulya.y:=pulya.y+pulya.napr.y;
pulya.z:=pulya.z+pulya.napr.z;
При выстреле мы задаём пуле начальное положение и вектор скорости:
pulya.x:=pushka.x;
pulya.y:=pushka.y;
pulya.z:=pushka.z;

pulya.napr.x:=napr.x;
pulya.napr.y:=napr.y;
pulya.napr.z:=napr.z;
Поэтому векторно всё понятно. И есть удобные библиотеки для работы с векторами, когда вместо трёх строчек
pulya.x:=pulya.x+pulya.napr.x;
pulya.y:=pulya.y+pulya.napr.y;
pulya.z:=pulya.z+pulya.napr.z;
можно писать одну
pulya.AddVector(pulya.napr);
Поэтому в трёхмерном пространстве всё достаточно просто. Если в 3D игрок может стрелять только в горизонтальном направлении, то можно использовать и 2D алгоритм. При этом вручную задавать третью координату, которая определяет высоту плоскости полёта пули над уровнем пола.
Как видите, реализация полёта пуль - это достаточно просто. Но при этом понимание этого вопроса сразу делает из вас крутого gamedeveloper-а. По сути вопрос о полёте пуль является одним из важнейших в плане геймдевелопмента. После того, как вы научились делать пульки и самонаводящиеся ракеты, вы сразу поймёте и некоторые другие вещи по разработке игр.
Теперь затронем вопрос о проверке попадания. Обычно проблема заключается в том, что если пуля слишком быстро летит, то она буквально перескочит через цель, не поразив её. Это происходит из-за того, что не срабатывает алгоритм проверки столкновений.
Например, пуля имела координату x=0, y=0. Скорость dx=100,dy=0. Через один кадр пуля окажется в точке с координатой x=0+100, y=0+0. Из-за этого мы не попадём в объект, который находится в координате x=50, y=0.
Итак, пуля вроде бы пролетела через объект, но шак был слишком большой. То есть приращение большое, а из-за этого collision detection просто не сработал. Что делать в этом случае? Например, можно проверять пересечение отрезка со сферой. Координаты отрезка задавать следующим образом:
точка1 имеет координату пули
точка 2 имеет координату пули плюс скороть.
Скорее всего эту проблему можно решить и другими способами, и ей я особо не занимался. Другой способ заключается в том, чтобы уменьшить скорость полёта пули.
Дело в том, что в играх нужно применять контроль скорости процессора. Вы можете прочитать об этом в моих статьях. Из-за этого на медленных компьютерах пуля имеет более высокую скорость. За один кадр пуле приходется перескочить на большую величину. На быстрых компьютерах эта проблема исчезает. Но если вдуг что-то "затормозит", начнёт подгружаться с диска, то из-за этого замедления может возникнуть ошибка.
Так что решение состоит в том, чтобы делать такую проверку, которая определит попадание со 100%-тной вероятностью
Теперь коснёмся немного вопроса о спецэффектах. После того, как пуля попадёт в какой-нибудь объект, хорошо бы сделать круитой спецэффект. Например, пуля попала в бетонную стену. После этого мы делаем pulka[i].letit:=false. Для создания эффектов хорошо подойдёт какой-нибудь движок частиц (particle engine). Во время попадания у вас есть координата пули и вы в этой точке создаёте 30-40 частиц серого с начальными скоростями, перпендикулярными стене.Теперь после попадания у вас от стены будут отлетать частички. При попадании в металл хорошо бы придать партиклам (particles - частицы) красный, белый и ярко желтый цвет. То есть как бы искры отлетят. Если у вас какой-то супер-бластер, то можно сделать какие-нибудь синие частицы.
Рассмотрим самонаводящуюся ракету. Когда ракета летит, то за собой она оставляет след. Для реализации этого эффекта вам достаточно создавать полупрозрачные партиклы серого в текущей координате ракеты. Если у вас хороший оптимизированный движок, то время существования частиц может быть достаточно большим. Благодаря наличию начальных скоростей и рассеиванию частиц дым от ракеты постепенно будет рассеиваться. То есть в том месте, где производилась стрельба, возникнет дымок.
Ещё один хороший эффект - это следы от пуль. Для этого есть несколько решений. Например, определив точку пересечения пули со полигоном стены, в этом месте можно наложить маленький полигончик (поверх) с картинкой дырки от пули. В некоторых играх для этого сделан массив дырок. Так как массив имеет ограниченный размер, то дырки постепенно исчезают. Хотя это и не обязательно. Возможно применить некоторые ухищрения, благодаря которым ничего не будет исчезать, и существенно повысится реалистичность игры.

Сообщение отредактировал maxturbo - Четверг, 15 Октября 2009, 14:17
 
DrawДата: Четверг, 15 Октября 2009, 15:13 | Сообщение # 10
Продвинутый
Группа: Участники
Сообщений: 194
Награды: 0
Замечания: 0%
Статус:

Команда: DeforShys
Проектов: 8 (2 активных 6 инактив)
тебе не кажется что тема старовата?))
стрельбу можно делать пиками, лайнпиками и банально коллизиями



ICQ 557709132 пиши. Отвечу на любой вопрос по блицу
 
maxturboДата: Четверг, 15 Октября 2009, 15:22 | Сообщение # 11
Профи
Группа: Участники
Сообщений: 379
Награды: 0
Замечания: 0%
Статус:

Профессия: Программер
Проектов: 1 в разработке
Draw, Знаешь если перечислить способы как можно зделать стрельбу то их очень много!!!А я так особо выложил примеры стрельбы, конкретно же не задовался вопрос какой тематики стрельба нужна...
 
DrawДата: Пятница, 16 Октября 2009, 15:39 | Сообщение # 12
Продвинутый
Группа: Участники
Сообщений: 194
Награды: 0
Замечания: 0%
Статус:

Команда: DeforShys
Проектов: 8 (2 активных 6 инактив)
maxturbo, все эти способы исходят из одной из трех веток: кам пики, лайнпики, коллизии


ICQ 557709132 пиши. Отвечу на любой вопрос по блицу
 
  • Страница 1 из 1
  • 1
Поиск: