Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Программирование игр, графики и искусственного интеллекта > Падающий мяч


Автор: sSilence 27.5.2009, 20:02
Здраствуйте. 
Подскажите как сделать мяч который падает с определенной высоты, по законам гравитации и отскакивает.
я не могу (понять, сделать) цикл, по которому, мяч должен падать и отпрыгивать 
все должно происходить по формуле at^2+yt+y(0) 
или еще как... подскажите, можно только цикл. 

Спасибо.

Не откажусь и от примера)

Автор: Mazzi 28.5.2009, 09:50
Делай так.

Задай переменные: скорость, расстояние до земли.

Исходное положение: скорость == 0, расстояние == N

цикл_пока (расстояние > 0) {
     скорость++;
     расстояние--;
     рисуем_мяч();
}

цикл_пока (скорость > 0) {
     скорость--;
     расстояние++;
     рисуем_мяч();
}

Примитивно, но для иллюстрации сгодится.

Автор: Bitter 28.5.2009, 11:16
Нет, не сгодится.

На разных машинах это будет работать по разному. Вот праильная схема:

1. понадобятся три 64 битные переменные (t1, t2, f)
2. При старте Вызываем API QueryPerfomanceCounter(t2);   // Количество тиков на данный момент времени
3. При старте Вызываем API QueryPerformanceFrequency(f); // Частота процессора
3. Тело программы

 While (!Stop)
 { 
    QueryPerfomanceCounter(t1);
    deltaT = (t1 - t2) / f;
    if (deltaT>0.1)  // Скорость работы не быстрее  0.1 секунды
   { 
      QueryPerfomanceCounter(t2);
      Speed += g*deltaT;
      if (Координата_шарика_Y>0)   Координата_шарика_Y + = Speed;
      else Speed = -1; // -1 это значение с потолка, то есть 1 метр в секунду вверх
   }
  
 }

4. переменная g это ускорение свободного падения = 9.822

Типы всех переменных, думаю интуитивно понятны

Автор: Rickert 28.5.2009, 11:24
Люди не гоните, скорость не может задаваться постоянным значением. Она должна расчитываться исходя из разницы во времени между сменой кадра.

Автор: Bitter 28.5.2009, 11:26
Rickert, а я что написал?

Автор: Mazzi 28.5.2009, 11:35
Я показал всего лишь иллюстрацию, без подробностей.

Автор: Bitter 28.5.2009, 11:48
Что же она иллюстрирует? Что мяч должен опускаться вниз, а потом подниматься вверх что ли? Думаю автор сам понимает что значит "падает" и "отскакиваает"

Автор: sSilence 30.5.2009, 20:40
госпада.
все еще проще чем кажется,

Код

float y=0;
float v0=0;
float y0=4;
float t=0;
float a=9.8;
float v=0;
...
// тут он падает собственно по формуле
 t=t + 0.001;
  v=a*(t*t)+y*v0;
  y=a*(t*t)+v*t+y0;

//тут начинается должен самый геморой... который хрен знает ккакой




Автор: Bitter 30.5.2009, 22:53
Цитата(sSilence @  30.5.2009,  20:40 Найти цитируемый пост)
t=t + 0.001;  v=a*(t*t)+y*v0;  y=a*(t*t)+v*t+y0;


это вобще не понятно что
цифры какие-то от балды... лажа. Попробуй запусти на машине в 233 Мг и на машине с 4мя ядрами...

Цитата(sSilence @  30.5.2009,  20:40 Найти цитируемый пост)
все еще проще чем кажется


Цитата(sSilence @  30.5.2009,  20:40 Найти цитируемый пост)
тут начинается должен самый геморой... который хрен знает ккакой


это называется проще? Я тебе реальное решение показал. Ну как знаешь...

Автор: Rickert 31.5.2009, 05:28
Bitter, вы учитываете такты ЦП. Но ведь для получения кадра используется ещё процессор звуковой карты и видео. Нужно искать разницу между кадрами - тогда будет нужный эффект. Ищем её в секундах, используем физическую формулу для расчёта, и умножаем на полученную разницу - она играет роль шага во времени (dt).

Автор: ksnk 31.5.2009, 08:35
Rickert, Хм... А зачем считать какие-то такты ЦП? Картинка должна изменяться не менее чем 20 раз в секунду. Вот они "такты" и  есть! Ставить delay/slip/timeout по вкусу, пусть процессор сам считает свои такты...

Автор: Rickert 31.5.2009, 15:45
Цитата(ksnk @  31.5.2009,  08:35 Найти цитируемый пост)
Rickert, Хм... А зачем считать какие-то такты ЦП?

Вот и я спрашиваю: зачем Bitter их считает?

Цитата(ksnk @  31.5.2009,  08:35 Найти цитируемый пост)
Картинка должна изменяться не менее чем 20 раз в секунду. Вот они "такты" и  есть! Ставить delay/slip/timeout по вкусу, пусть процессор сам считает свои такты...

Почему именно 20? Почему не 33? Не 1567?

Автор: ksnk 31.5.2009, 15:55
Rickert, В кино, к примеру, частота кадров - 24 кадра в секунду. Вполне реалистичная картинка получается. Зачем пересчитывать чаще и тратить такты процессора, которые можно потратить на что-то нужное...

Автор: Rickert 1.6.2009, 05:24
ksnk, т.е. то ваши личные убеждения? Ну давайте, попробуйте поиграть в кваку с fps = 20 кадров.

Автор: Mazzi 1.6.2009, 09:09
Цитата(Bitter @ 28.5.2009,  11:48)
Что же она иллюстрирует? Что мяч должен опускаться вниз, а потом подниматься вверх что ли? Думаю автор сам понимает что значит "падает" и "отскакиваает"

топикстартер написал

"я не могу (понять, сделать) цикл, по которому, мяч должен падать и отпрыгивать"

вот это и иллюстрирует. Читайте внимательней пожалуйста.

Автор: Rickert 1.6.2009, 09:19
Mazzi, ключевая фраза
Цитата(sSilence @  27.5.2009,  20:02 Найти цитируемый пост)
Подскажите как сделать мяч который падает с определенной высоты, по законам гравитации и отскакивает.


Автор: Bitter 1.6.2009, 12:35
Rickert, вот вы спорите о том, сколько должно быть кадров в секунду, а мой алгоритм не зависит от этого. Мяч будет одинаково выглядеть хоть при частоте 100 fps хоть при частоте 10 fps. Именно для этого я считаю количество тактов пройденных с момента последнего рендера, после чего на основе этой цифры изменяется ускорение. В этом случае не нужно даже думать сколько кадров выбирать. Это называется не зависеть от системы. А звуковая  и графическая карта тут вообще не причем, так как в расчетах скорости участия не принимают и работают паралельно.

Добавлено через 2 минуты и 40 секунд
Цитата(Rickert @  31.5.2009,  05:28 Найти цитируемый пост)
Нужно искать разницу между кадрами


Блин, а я что делаю? 
вот этот кусок кода не о чем не говорит?

Код

    QueryPerfomanceCounter(t1);                                                  
    deltaT = (t1 - t2) / f;                                                                      // РАЗНИЦА ВРЕМЕНИ МЕЖДУ КАДРАМИ
    if (deltaT>0.1)  // Скорость работы не быстрее  0.1 секунды     // это ограничение для того, чтобы избежать deltaT=0
   { 
      QueryPerfomanceCounter(t2);


Добавлено через 4 минуты и 54 секунды
Цитата(ksnk @  31.5.2009,  15:55 Найти цитируемый пост)
 Зачем пересчитывать чаще и тратить такты процессора, которые можно потратить на что-то нужное...

Вот именно - незачем, по этому и считается количество потраченных процессором тактов на другие расчеты, для того, чтобы сохранять неприрывность движения графики

Автор: Rickert 1.6.2009, 15:37
Bitter, ну считайте - считайте, пока на грабли не наступите - не поймёте.

Автор: Bitter 1.6.2009, 18:11
Rickert, ну объяснили бы сразу в чем грабли-то, а то получается как "я такой классный знаю, а вот вам не скажу бугага"

Автор: Dobermann 1.6.2009, 18:17
Я по моему тут все по физике... сила трения, притяжения, вектор падения и т.п. и формулы оттуда же брать надо...

Автор: cardinal 1.6.2009, 18:36
Bitter, помоему не так
Код

 if (Координата_шарика_Y>0)   Координата_шарика_Y + = Speed;

а так
Код

 if (Координата_шарика_Y>0)   Координата_шарика_Y + = Speed * deltaT;

должно быть...

Автор: Bitter 1.6.2009, 18:48
cardinal, ну я просто до этого написал: 

Код

 Speed += g*deltaT;


то есть дельту уже учел.

Автор: cardinal 1.6.2009, 19:34
Bitter, в случае, что g = const

integral a dt = v
integral v dt = s

соответственно перемножать нужно два раза...

Автор: Rickert 1.6.2009, 20:00
Цитата(Bitter @  1.6.2009,  18:11 Найти цитируемый пост)
Rickert, ну объяснили бы сразу в чем грабли-то, а то получается как "я такой классный знаю, а вот вам не скажу бугага" 

Вы разработками в области параллельных вычислений занимались? Вот у вас есть два потока, которые считают два значения и складывают их в область памяти. Каждый работает независимо от другого разное количество секунд. И есть третий поток, который должен сложить результаты работы первых двух. Вопрос: как организовать работу? Как узнать что первые два потока завершили свои вычисления и в обусловленных областях памяти лежат конечные значения?
Когда вы считаете такты ЦП - вы следите за выполнением только одного потока, забывая, что есть ещё поток GPU и остальные вычисления, которые в конечном итоге, дают результирующую картинку. Т.е. чтобы верно отсчитывать время вы должны отталкиваться от реально отображённых кадров, а не от тактов ЦП.
Конечно, возможно что при небольшой нагрузке вы можете учитывать только такты ЦП и иметь на руках достоверную картинку. Но стоит вашему проекту вырасти до шейдеров и большого количества объёма данных - как начнутся непонятные артефакты в просчёте физики, на отлов которых у вас, скорее всего, уйдёт очень много времени.

Автор: arilou 1.6.2009, 23:18
Rickert, кстати, а где тут проблема? Bitter считает дельту с последнего рассчета и учитывает ее. Всё равно у тебя один поток для всего получается, а там где драйвер скидывает command buffer в видео карту, основной поток будет ждать. Т.е. нет смысла заморачиваться на параллелизм в данном случае. Это как из пушки по воробьям.

Автор: sSilence 5.6.2009, 18:06
зачем мне считать такты, кадры! у меня тут идет просто вычиления значения по оси "y"!
программа готова в ней отображается щарик(мячик), только осталось в бить что делать с координатой и все.
и на данный момент как я писал в пред посте, он просто опускается с ускорением

Автор: Bitter 7.6.2009, 01:00
sSilence, либо Вы задете вопрос не относящийся к теме данного раздела, либо Вы не поняли, что Вам отвечают.

Если Вам надо объяснить как работают циклы в С++, то Вам явно не сюда, но если вам нужна физика перемещения падающего упругого объекта, то внимательно еще раз прочитайте ответы, в них всё уже указано.

Цитата(sSilence @  5.6.2009,  18:06 Найти цитируемый пост)
осталось в бить что делать с координатой

именно это вам и объяснили

Цитата(sSilence @  5.6.2009,  18:06 Найти цитируемый пост)
он просто опускается с ускорением

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

Автор: cardinal 7.6.2009, 01:03
http://forum.vingrad.ru/index.php?showtopic=261042&view=findpost&p=1884589

Автор: Rickert 7.6.2009, 06:35
arilou, с пушки попадёшь с большей вероятностью, а точность в физ. расчётах - наше фсё.

Автор: galileopro 5.7.2009, 03:44
Ну если 20 мало, то думаю 30 будет вполне достаточно. А больше для падающего шарика не нужно, скорее всего...

Автор: Somewho 9.7.2010, 19:57
Эммм... падающий мяч легко сделать даже в Паскале. Насколько я понимаю, всё проблема в просчёте формулы движения. Начальная высота - h. Ускорение всегда направлено вниз и по модулю равно g. Начальная скорость 0 (не так ли). Если не учитывать потерю енергии мяча при отскоке, то мяч будет вечно подпрыгивать до постоянной высоты, но не выше.
Система координат одномерная (движение только вверх-вниз). Точка отсчёта - Земля, т.е. точка с у=0. Мяч имеет кординату h (стрелка оси вверх). Формула координаты мяча от времени: y=h-g*(t^2)/2 при падении и y=V*t-g*(t^2)/2. V рассчитывается в самом начале по формуле равенства энергий m*(V^2)/2=m*g*h; V=(2*g*h)^0.5.
Как это на том же Паскале: просто выбираем значения констант (h и g), а также значение "хода", то есть задержки между кадрами dt. А дальше - программная часть. Через каждое прибавление dt к t пересчитывать координату (ну и выводить изображение, конечно). Каждый раз еще просчитывать координату мяча при следующем "ходе" с целью предотвращения падения его под землю. Если y<0 - просто-напросто достаточно под t подставлять значение t про y=0, которое было в первый раз, то есть t=(2*h/g)^0.5.
Как-то так smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)