Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/43: Рейтинг темы: голосов - 43, средняя оценка - 4.65
 Аватар для CFYZ
11 / 11 / 4
Регистрация: 21.11.2009
Сообщений: 187

Выстрел в игре

05.10.2011, 14:35. Показов 8213. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день всем!
Я вот пытаюсь сделать игру "Танчики" как раньше была на Денди.
И сталкнулся с такой проблемой как выстрел. У меня есть модель танка которая передвигается по полю, упирается в препятствия и т.д. но пока не могу понять как сделать так что бы он еще и стрелял.
Кто знает как это сделать подскажите пожалуйста.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.10.2011, 14:35
Ответы с готовыми решениями:

Реализовать выстрел в игре
Привет программистам данного чудо форума) Помогите мне пожалуйста, мне нужен вот такой код. Что-бы в игре происходил выстрел -_- ...

Выстрел
есть вот такой код для выстрела но проблема вот в чем VbCkegMIEuw как можно исправить это if (Input.GetMouseButton(0)) ...

Выстрел в игрока
Нужно сделать чтобы враг стрелял в направлении игрока. Ваши предложения?

6
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
05.10.2011, 14:56
Несколько небольших игрушек
предупреждая возможные вопросы:
Нужна игра на С++Builder`е
0
 Аватар для QVO
652 / 462 / 80
Регистрация: 26.10.2010
Сообщений: 1,263
Записей в блоге: 4
05.10.2011, 20:30
Пули в 2D и 3D пространстве, проверка попадания, оптимизация и эффекты.
Сначала затронем тему оптимизации. Проблема состоит в том, что для каждой пули мы в каждом кадре считаем SIN и COS угла полёта. При большом количестве пуль это существенно скажется на FPS игры, всё будет "дёргаться". Вот эта часть кода:

Delphi
1
2
3
4
5
6
7
8
// если летит, то
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 летит, кадр за кадром будет выполняться следующий код:

Delphi
1
2
with pulki[i] do x:=x+3*cos(phi*3.14/180);
with pulki[i] do y:=y+3*sin(phi*3.14/180);
Обозначим приращение так:

Delphi
1
2
dx:=3*cos(phi*3.14/180);
dy:=3*sin(phi*3.14/180);
Тогда выражения для полёта пули переменятся:

Delphi
1
2
3
4
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 один раз, когда пуля только-только вылетает. Изменим описание пули. Раньше тип "пулька" выглядел так:

Delphi
1
2
3
4
5
6
type Tpulka=record
x,y:single; // координаты
phi:single; // направление полёта пули
letit:boolean; // true - летит, false - уже не летит (не существует)
life:integer; // сколько прошло времени после выстрела 
end;
Теперь мы заменим угол phi на приращения dx и dy:

Delphi
1
2
3
4
5
6
type Tpulka=record
x,y:single; // координаты
dx,dy:single; // направление полёта пули
letit:boolean; // true - летит, false - уже не летит (не существует)
life:integer; // сколько прошло времени после выстрела 
end;
А теперь посмотрим, как изменится процесс выстрела. Раньше это выглядело так:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
Вместо того, чтобы записывать угол, под которым летит пуля, мы подсчитаем приращения заранее:

Delphi
1
pulki[i].phi:=igrok1.phi;
меняем на

Delphi
1
2
pulki[i].dx:=3*cos(phi*3.14/180);
pulki[i].dy:=3*sin(phi*3.14/180);
и код выглядит так:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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. Ну а теперь реализуем код перемещения пули. Раньше этот код выглядел так:

Delphi
1
2
with pulki[i] do x:=x+3*cos(phi*3.14/180);
with pulki[i] do y:=y+3*sin(phi*3.14/180);
А теперь вот так:

Delphi
1
2
with pulki[i] do x:=x+dx;
with pulki[i] do y:=y+dy;
В этом и заключается оптимизация. Две строчки выше - это оптимизированное перемещение пули. Но здесь возникает одна проблема: а вдруг в вашей игре пули могут лететь не только по прямой, но и отклоняться от своей траектории. Что делать в этом случае? Вернёмся к старому коду, посмотрим на него:

Delphi
1
2
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 заранее (в самом начале программы) и заносим эти значения в массив. Вместо тригонометрических функций в самой игре или демке потом используют массив вместо функции.

Делается это так. сначала мы задаём массивы с кешем:

Delphi
1
2
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 градусов. Раньше это выглядело бы так:

Delphi
1
a:=sin(135*3.14/180)
Намного быстрее использовать значение из кеша. Использовать кеш очень просто:

Delphi
1
a:=sinmassiv[135];
Ну а если угол 15.4817? В этом случае имеет место число с точкой. Придётся округлить значение угла:

Delphi
1
a:=sinmassiv[round(15.4817)];
Разумеется, здесь теряется точность. Ещё небольшой ньюанс заключается в том, что угол в вашей игре может меняться не только от 0 до 360, но и дальше. Например, это может быть -1. Или 376 градусов. В этом случае вы должны просто воспользоваться тем, что SIN и COS обладают периодичностью, т.е. через каждые 360 градусов происходит повторение значений. И поэтому:

Delphi
1
2
3
4
5
sin(376)=sin(16);
 
//а для -1 градуса:
 
sin(-1)=sin(359);
Итак, мы разобрались с вопросом оптимизации. Теперь перейдём к теме 2D/3D игр. Чтобы применить пули в 3D пространстве, достаточно хорошо разобраться в 2D. Посмотрим как мы задавали пулю в 2D:

Delphi
1
2
3
4
5
6
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 - время, то

Delphi
1
2
x:=x+dx*1;
y:=y+dy*1;
Причём t=1, так как мы считаем его не в секундах, а в кадрах. За один кадр пуля пролетает вот столько. Сам вектор скорости выглядит так: (dx,dy). Например, если мы обозначим вектор положения пули за POZ, а скорость пули за SKOR, то векторно перемещение пули будет выглядеть так:

POZ = POZ + SKOR,

где POZ, SKOR - вектора.

Эта формула подходит и для 3D пространства. Наример, если у вас есть скелетно анимированная модель, то вы всегда занаете вектор, соответствующий направлению оружия:

Delphi
1
2
3
napr.x:=...
napr.y:=...
napr.z:=...
И знаете координату пушки в пространстве:

Delphi
1
2
3
pushka.x:=...
pushka.y:=...
pushka.z:=...
Чтобы осуществить движение пули, достаточно сделать следующее:

Delphi
1
2
3
pulya.x:=pulya.x+pulya.napr.x;
pulya.y:=pulya.y+pulya.napr.y;
pulya.z:=pulya.z+pulya.napr.z;
При выстреле мы задаём пуле начальное положение и вектор скорости:

Delphi
1
2
3
4
5
6
7
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;
Поэтому векторно всё понятно. И есть удобные библиотеки для работы с векторами, когда вместо трёх строчек

Delphi
1
2
3
pulya.x:=pulya.x+pulya.napr.x;
pulya.y:=pulya.y+pulya.napr.y;
pulya.z:=pulya.z+pulya.napr.z;
можно писать одну

Delphi
1
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 - частицы) красный, белый и ярко желтый цвет. То есть как бы искры отлетят. Если у вас какой-то супер-бластер, то можно сделать какие-нибудь синие частицы.

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

Ещё один хороший эффект - это следы от пуль. Для этого есть несколько решений. Например, определив точку пересечения пули со полигоном стены, в этом месте можно наложить маленький полигончик (поверх) с картинкой дырки от пули. В некоторых играх для этого сделан массив дырок. Так как массив имеет ограниченный размер, то дырки постепенно исчезают. Хотя это и не обязательно. Возможно применить некоторые ухищрения, благодаря которым ничего не будет исчезать, и существенно повысится реалистичность игры.



Источник: http://www.tmtlib.narod.ru/strelba.htm
0
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
05.10.2011, 20:40
хорошо бы помедленнее и на си
и по ссылке попадаю в комнату № 404
0
 Аватар для QVO
652 / 462 / 80
Регистрация: 26.10.2010
Сообщений: 1,263
Записей в блоге: 4
05.10.2011, 23:54
LK,
C++
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
class TBullet
{
  public:
 
  double X;
  double Y;
  double dX;
  double dY;
  double Speed;
  double Angle;
  Graphics::TBitmap *Buffer;
 
  TBullet();
  ~TBullet();
  void __fastcall Load(AnsiString file);
  void __fastcall Move();
  void __fastcall DrawTo(TCanvas *Canvas);
  bool __fastcall OnForm(int cW,int cH);
  void __fastcall Monitoring(TTList<TBullet*> *BulletsBuffer, int Camera_Right, int Camera_Down, Graphics::TBitmap *Buffer);
};
 
  TTList<TBullet*> *BulletsBuffer = new TTList<TBullet*>();
//---------------------------------------------------------------------------
 
  TBullet::TBullet()
  {
    Buffer = new Graphics::TBitmap;
  }
//---------------------------------------------------------------------------
 
  TBullet::~TBullet()
  {
    delete Buffer;
  }
//---------------------------------------------------------------------------
 
  void __fastcall TBullet::Load(AnsiString file)
  {
    Buffer->LoadFromFile(file);
  }
//---------------------------------------------------------------------------
 
  void __fastcall TBullet::Move()
  {
    X += cos(Angle) * Speed;
    Y += sin(Angle) * Speed;
  }
//---------------------------------------------------------------------------
  
  void __fastcall TBullet::DrawTo(TCanvas *Canvas)
  {
    Canvas->Draw(X, Y, Buffer);
  }
//---------------------------------------------------------------------------
 
  bool __fastcall TBullet::OnForm(int cW,int cH)
  {
    if(X < 0 || X > cW || Y < 0|| Y > cH) return false;
    else return true;
  }
//---------------------------------------------------------------------------
 
  void __fastcall TBullet::Monitoring(TTList<TBullet*> *BulletsBuffer, int Camera_Right, int Camera_Down, Graphics::TBitmap *Buffer)
  {
    if(BulletsBuffer->Count > 0)
    {
        for(int i = 0; i < BulletsBuffer->Count; i++)
        {
            BulletsBuffer->Get(i)->Move();
            BulletsBuffer->Get(i)->DrawTo(Buffer->Canvas);
 
            if(BulletsBuffer->Get(i)->OnForm(Camera_Right, Camera_Down) == false)
            {
                delete BulletsBuffer->Get(i);
                BulletsBuffer->Delete(i);
            }
        }
    }
  }
//---------------------------------------------------------------------------
 
  void __fastcall CreateBullet(AnsiString file, double Speed, int sX, int sY, int mX, int mY)
  {
    TBullet *b      = new TBullet();
    b->Load(file);
    FPoint p1(sX, sY);
    FPoint p2(mX, mY);
    double Angle    = p1.Polar(&p2);
    int dX          = cos(Angle) * 2000 + p2.x;
    int dY          = sin(Angle) * 2000 + p2.y;
    b->X            = sX;
    b->Y            = sY;
    b->Angle        = Angle;
    b->Speed        = Speed;
    BulletsBuffer->Add(b);
  }
//---------------------------------------------------------------------------
В таймере:

C++
1
Bullets->Monitoring(BulletsBuffer, Camera->R, Camera->D, Map->Buffer);
По нажатию кнопки мышки:

C++
1
CreateBullet(".\\bullet.bmp", 10.0, Player->X-Camera->L, Player->Y-Camera->T, Aim->X, Aim->Y);
2
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
06.10.2011, 00:54
судя по всему, оно еще и работает
у меня, к сожалению, на сегодня исчерпан лимит бонусов , примите, уважаемый QVO, простое человеческое СПАСИБО
0
 Аватар для QVO
652 / 462 / 80
Регистрация: 26.10.2010
Сообщений: 1,263
Записей в блоге: 4
06.10.2011, 11:00
LK, сюда же нужны классы от Otaka:
C++
1
const float M_RAD_CONV =  3.14159/180.0;       //Для преобразований градусов и радианов
C++
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
class FPoint
{
public:
float x;
float y;
FPoint()
     {
     x=0;
     x=0;
     }
FPoint(float nX,float nY)
     {
     x=nX;
     y=nY;
     }
float Polar(FPoint*p)
     {
     float X2=p->x;
     float Y2=p->y;
     float res=0;
     if(y==Y2)
          {
          if(X2>=x)
               res=0;
          if(X2<x)
               res=M_PI;
          }else
     if(x==X2)//Сразу исключаем, если точки одна над другой.
          {
          if(Y2==y)
               res=0;
          if(Y2>y)
               res= 90.0*M_RAD_CONV;
          if(Y2<y)
               res= 270.0*M_RAD_CONV;
          }else
          {
          float dx=X2-x;
          float dy=Y2-x;
          float angle=atan2(Y2-y,X2-x);
          res=atan2(Y2-y,X2-x);
          if(res<0)
               {
               res=res*-1;
               res=M_PI-res+M_PI;
               }
          }
     return res;
     }
float Distance(FPoint*p)
     {
     float X2=p->x;
     float Y2=p->x;
     return sqrt((x-X2)*(x-X2)+(y-Y2)*(y-Y2));
     }
};
C++
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
template <class T>
class TTList:public TList
{
public:
T Get(int index)
        {
        return (T)TList::Items[index];
        }
void Add(T item)
        {
        TList::Add((void*)item);
        }
int IndexOf(T item)
        {
        return TList::IndexOf((void*)item);
        }
int Find(T Item)
        {
        for(int i=0;i<Count;i++)
                {
                if(Item==TList::Items[i])return i;
                }
        }
void DeleteAndFree(int index)
        {
        delete TList::Items[index];
        Delete(index);
        }
void DeleteAll()
        {
        for(int i=0;i<Count;i++)
                {
                if(TList::Items[i]!=NULL)
                        {
                        delete TList::Items[i];
                        }
                }
        Clear();
        }
};
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.10.2011, 11:00
Помогаю со студенческими работами здесь

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

Выстрел танка
Доброго времени суток ! у меня такая проблема , есть танк (3д объект) у танка есть пушка , когда танк находит врага , он поворачивает...

Выстрел из пушки
Всем привет,подскажите пожалуйста как сделать выстрел из пушки ядром.

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

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru