Супер бильярд, подскажите... |
Супер бильярд, подскажите... |
VelarThind |
11.04.2005 19:38
Сообщение
#1
|
Гость |
Решил тут я бильярд на паскале написать. Ну кий там, шарик ведущий сделал, всё пока работает(кий толкает шарик, он катиться, замедляет ход), но необходимо и другие шары в игру(какой же это будет бильярд с одним шариком), а вот соударение шариков друг с другом, что-то не осилил. Подскажите, пожалуйста!!!! Заранее спасибо.
|
Altair |
11.04.2005 19:58
Сообщение
#2
|
Ищущий истину Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: 45 |
Вот этот пример думаю будет полезен. Код очень хорошо прокоментирован!
По экрану катаются шарики и сталкиваются. Эмитация броуновского движения. Код Uses Graph,Crt; const MaxShar=10; type shar = object { переменные } x,y:integer; { текущие координаты шара } r:word; { радиус } color:byte; { цвет шара } dx,dy:shortint; { скорость. задается значениями перемещения на каждом шаге (в точках) } hits:set of byte; { множество шаров с которыми данный шар уже столкнулся и с которыми не надо обсчитывать столкновение еще раз } { методы } constructor initShar(x0,y0:integer; r0:word; color0:byte; dx0,dy0:shortint); procedure Move; { двигаем } procedure Show; { показываем } procedure Hide; { прячем } procedure CheckBorder; { проверяем на выход за границы экрана } procedure CheckHit(k:byte); { проверяем на столкновение с другим шаром } procedure revertXDirection; { поменять Х/Y-составляющую скорости } procedure revertYDirection; { на противоположную } procedure TurnAfterHit(k:byte); { вычислить новые значения скорости двух шаров после удара. Первый шар - шар данного объекта, второй - с индексом k в массиве } function Value:real; { вычислить объем шара. Нужно для вычисления скорости. Вообще-то там масса нужна, но учитывая, что плотность все-равно сократиться при делении, используем объем } {procedure PrintState;} { отладочные печати } end; var bgColor,i:byte; x,y,dx,dy,ErrCode:integer; r:word; shars: array[1..MaxShar] of shar; { массив шаров } sh:shar; f:text; { файл для отладочных печатей } Procedure shar.Move; begin x:=x+dx; y:=y+dy; end; Procedure shar.Show; begin setColor(color); circle(x, y, r); {PutPixel(x,y,color);} { уберите комментарий чтобы увидеть траекторию } end; Procedure shar.Hide; begin setColor(bgColor); circle(x, y, r); end; procedure shar.revertXDirection; begin dx:=-dx; x:=x+dx; end; procedure shar.revertYDirection; begin dy:=-dy; y:=y+dy; end; Constructor shar.initShar(x0, y0 :integer; r0 :word; color0 :byte; dx0, dy0 :shortint); begin x:=x0; y:=y0; r:=r0; color:=color0; dx:=dx0; dy:=dy0; hits:=[]; end; procedure shar.CheckBorder; begin if (r+x>=GetMaxX-1) or (x-r<=1) then revertXDirection; if (y+r>=GetMaxY-1) or (y-r<=1) then revertYDirection end; {procedure shar.PrintState; begin writeln(f,'x=',x:3,' y=',y:3,' r=',r:3,' dx=',dx:3,' dy=',dy:3); end;} procedure shar.TurnAfterHit(k:byte); { формулы для движения шаров взяты здесь: http://ferro.phys.msu.ru/prak/PDF/01-mechanics/07.pdf } var m1, m2 :real; vx10,vy10,vx20,vy20:integer; begin m1 := Value; { массы } m2 := shars[k].Value; vx10 := dx; { начальные значения скоростей } vy10 := dy; vx20 := shars[k].dx; vy20 := shars[k].dy; { скорость первого шара после удара } dx := round((2*m2*vx20 + (m1-m2)*vx10)/(m1+m2)); dy := round((2*m2*vy20 + (m1-m2)*vy10)/(m1+m2)); { скорость второго шара после удара } shars[k].dx := round((2*m1*vx10 + (m2-m1)*vx20)/(m1+m2)); shars[k].dy := round((2*m1*vy10 + (m2-m1)*vy20)/(m1+m2)); end; function shar.Value:real; begin { возвращает объем шара } Value:=4*Pi*r*r*r/3; end; procedure shar.CheckHit(k:byte); var i1:byte; dist:longint; begin for i1:=1 to MaxShar do if ((i1<>k) and not(k in hits)) then begin shars[i1].hits:=shars[i1].hits+[k]; dist:=round(sqrt(sqr(1.0*x-shars[i1].x)+sqr(1.0*y-shars[i1].y))); if (dist<r+shars[i1].r) then begin TurnAfterHit(i1); CheckBorder; Move; shars[i1].CheckBorder; shars[i1].Move; { скорость задается значениеми dx и dy - шагами движения. Таким образом она дискретна. Момент столкновения определяется по расстоянию между шарами. Но запросто может случиться, что шары на каком-то шаге пересекутся и в этом случае необходимо их развести в разные стороны перед тем как высчитывать расстояние на следуещем шаге, иначе они могут пребывать в состоянии постоянного столкновения } dist:=round(sqrt(sqr(1.0*x-shars[i1].x)+sqr(1.0*y-shars[i1].y))); while (dist<r+shars[i1].r) do begin CheckBorder; Move; shars[i1].CheckBorder; shars[i1].Move; dist:=round(sqrt(sqr(1.0*x-shars[i1].x)+sqr(1.0*y-shars[i1].y))); end; end; end; end; function initializeGraph:integer; var grDriver : Integer; grMode : Integer; begin grDriver:=Detect; InitGraph(grDriver, grMode, ''); initializeGraph:=GraphResult; end; begin ErrCode:=initializeGraph; if ErrCode <> grOk then WriteLn('Ошибка инициализации графики:', GraphErrorMsg(ErrCode)) else begin assign(f,'log.txt'); rewrite(f); bgColor:=0; rectangle(1,1,GetMaxX-1,GetMaxY-1); {shars[1].initShar(100,100,50,3,6,-3); shars[2].initShar(100,200,40,4,5,3); shars[3].initShar(200,200,20,5,-7,-4); shars[4].initShar(400,300,25,2,-9,-1); shars[5].initShar(500,200,35,14,-5,-8); if (MaxShar>5) then} { инициализация шаров случайным образом } for i:=1 to MaxShar do begin r:=20+random(10); shars[i].initShar(1+r+random(GetMaxX-2*r), 1+r+random(GetMaxY-2*r),r,1+random(GetMaxColor-1), random(15)-7,random(12)-6); end; { обсчитываем движение пока не нажата какая-либо клавиша } repeat { показываем все шары } for i:=1 to MaxShar do shars[i].Show; { временная задержка - установите свое значение для вашего компьютера } Delay(580); { убираем с экрана все шары } for i:=1 to MaxShar do shars[i].Hide; { просчитываем следующий шаг } for i:=1 to MaxShar do begin shars[i].Move; shars[i].CheckBorder; shars[i].CheckHit(i); end; for i:=1 to MaxShar do shars[i].hits:=[]; until keyPressed; CloseGraph; close(f); end end. -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
mithquessir |
11.04.2005 20:26
Сообщение
#3
|
Гость |
Светлик, вот нашел pdfник описания какой-то лабораторной изучения закона сохранения импульса, там есть формулы...
Прикрепленные файлы impulse.pdf ( 315.02 килобайт ) Кол-во скачиваний: 1552 |
AlienEmperor |
12.04.2005 11:11
Сообщение
#4
|
Бывалый Группа: Пользователи Сообщений: 160 Пол: Мужской Реальное имя: Серый Репутация: 0 |
А почему бы не представить игровое поле в виде массива (матрица X * Y из нулей, шарик - единица)... У каждого шарика перед движением просчитывается точка, в которой он должен оказаться... Если эта точка занята другим шаром, то меняем направление, если нет, то стираем единицу в предыдущем поле и переставляем шар на новое (двигаем шар)... Дешево и сердито...
-------------------- Все в жизни ботва... Кроме пчел!
|
Бродяжник |
12.04.2005 13:21
Сообщение
#5
|
Бывалый Группа: Пользователи Сообщений: 206 Пол: Мужской Репутация: 3 |
С матричным полем возможны такие траблы:
1. Шары не точечные. Поэтому если мы разобьем поле на клетки и будем просчитывать только нахождение шара в клетке, нам придется траекторию движения шара значительно загрублять. А если шар будет занимать не одну, а несколько точек, то есть представлять собой растр... не замучаемся ли мы с этим? 2. Как быть с изменением скорости? Если один шар движется вдвое быстрее другого, то значит ли это, что в течение того времени, когда более быстрый шар переходит с одной точки на соседнюю, более медленный шар должен тупо стоять на месте? 3. Допустим, два шара с одинаковой скоростью катятся навстречу друг другу. Перед очередным просчетом они находятся в двух соседних клетках. Если мы перед началом движения просчитаем будущее местоположение обоих шаров, то окажется, что они попадут в разные клетки, то есть столкновения как бы и не было. По-моему, проще все-таки вычислять расстояния между центрами шаров. Извините, что встряю, но проблема просчета коллизий меня самого всегда интриговала. Я ее так и не решил. |
AlienEmperor |
12.04.2005 13:51
Сообщение
#6
|
Бывалый Группа: Пользователи Сообщений: 160 Пол: Мужской Реальное имя: Серый Репутация: 0 |
На самом деле я как раз недавно скидывал альфу игры (в теме "тест движка 2") в котором все столкновения (а точнее, проверка соприкосновения с пов-тью и т.д.) проводятся именно через матрицу. Никаких проблем!
-------------------- Все в жизни ботва... Кроме пчел!
|
Atos |
12.04.2005 14:04
Сообщение
#7
|
Прогрессор Группа: Модераторы Сообщений: 602 Пол: Мужской Реальное имя: Михаил Репутация: 9 |
4. А если столкнутся больше двух шаров?
Сейчас юзаем Winapi на C++ За пару надо написать и сдать несложную прогу. Очередная была - сымитировать движение молекул. Вроде бы всё уже отладил, но когда препод стал тестировать, три молекулы столкнулись в центре экрана .. и "слиплись" :D Правда, потом на них налетела четвёртая, и исправила дело. |
Бродяжник |
12.04.2005 15:49
Сообщение
#8
|
Бывалый Группа: Пользователи Сообщений: 206 Пол: Мужской Репутация: 3 |
AlienEmperor
Поделитесь алгоритмом - как нужно обрабатывать следующую ситуацию? Поле: Цитата 000 102 000 Объект "1" движется вправо, объект "2" - влево. Через такт движения они оба должны были бы оказаться в точке по центру. Но по правилам игры вместо этого должно произойти взаимное отталкивание. Какой должна быть последовательность проверок? Я не говорю, что этого сделать нельзя; я просто не знаю как, и хочу узнать. И что изменится, если поле будет выглядеть так (направление движения прежнее): Цитата 000 012 000 |
VelarThind |
12.04.2005 17:18
Сообщение
#9
|
Гость |
Тут ещё какой вопрос. Нужно то не просто их оттолкнуть, да ещё под разными углами. То есть решить как минимум пару сотен задачь. Ведь при разных соотнашениях скоростей и траекторий, разных точках соприкосновения они поползут в разные в определённые стороны. Вот в этом проблема. Конечно можно решить столько задочь. Потом их както сгрупировать, а в зависимости от условий применять, но что-то не хочется. Ведь задачки кик минимум на час, а то и полтора решения.
|
AlienEmperor |
13.04.2005 10:15
Сообщение
#10
|
Бывалый Группа: Пользователи Сообщений: 160 Пол: Мужской Реальное имя: Серый Репутация: 0 |
Цитата Через такт движения они оба должны были бы оказаться в точке по центру. Но по правилам игры вместо этого должно произойти взаимное отталкивание. Какой должна быть последовательность проверок? На самом деле, в данном случае, придется немного попариться... Вообще решать данную проблему можно так: а) через матрицу (только единица матрицы по размерам должна быть МЕНЬШЕ размеров шара, т.е. шар включает в себя несколько единиц), если поле достаточно большое, то можно работать с битами, в результате чего размер матрицы сократится в 8 раз... Чем больше единиц будет в шаре, тем менее заметно будет вхождение друг в друга при столкновении... б) проверять координаты всех шаров, учитывая их радиус (или проще: вписать шары в квадрат, но при этом загрубление... (хотя можно сделать так: вписать шары в квадрат, а при проверке столкновений, в случае вхождения одного в другой проверять чем-нибудь вроде pixelcheck'а)). В данном случае лучше всего шары представлять в виде массива (как это сделано в примере). Мне вот другое интересно... Все это хорошо, я думаю, если посидеть немного, то можно сделать приемлемо... А вот хотел бы я на алгоритм Lemming'ов посмотреть... Ладно, пойду-ка я к лекции готовиться... P.S. Цитата Объект "1" движется вправо, объект "2" - влево. Через такт движения они оба должны были бы оказаться в точке по центру. Но по правилам игры вместо этого должно произойти взаимное отталкивание. Я вообще не понимаю, в чем проблема ? 000 102 000 Ну хорошо, предположим... Но шары-то двигаются НЕ ОДНОВРЕМЕННО - это же иллюзия... Тот шар, который в цикле имеет высший приоритет, просто запишет единицу в данную клетку ПЕРВЫМ, а второй, при проверке "свободна ли клетка дальше" получит -"нет" и, соответственно, должен будет оттолкнуться (а вот для того, чтобы и первый шар снизил скорость и поменял траекторию, надо чтобы второй "сообщил" ему об этом (я бы использовал массив указателей на шары, правда, при таком раскладе нужно еще идентифицировать нужный шар, но это тоже можно сделать). Вообще, такие штуки под DelphiX за пол-часа пишутся... , но это халява. -------------------- Все в жизни ботва... Кроме пчел!
|
volvo |
13.04.2005 11:52
Сообщение
#11
|
Гость |
Цитата(AlienEmperor @ 13.04.05 10:15) Вообще, такие штуки под DelphiX за пол-часа пишутся... , но это халява. Ребята, вы вопрос внимательно читали? Цитата(VelarThind @ 11.04.05 19:38) Решил тут я бильярд на паскале написать. Мало ли что под DelphiX за полчаса пишется. Может, используя другие пакеты, можно это одним вызовом функции реализовать. Вся проблема в том, что человек хочет сделать это самостоятельно. |
AlienEmperor |
13.04.2005 11:56
Сообщение
#12
|
Бывалый Группа: Пользователи Сообщений: 160 Пол: Мужской Реальное имя: Серый Репутация: 0 |
Volvo, ну так я же не спорю... И вариант решения предлагаю по мере возможностей в виде алгоритма... Насчет DelphiX это я так, к слову... Хотя почему бы не ознакомиться с его исходным кодом и не попробовать его части использовать в 16-битном Пасе ?
-------------------- Все в жизни ботва... Кроме пчел!
|
VelarThind |
13.04.2005 12:15
Сообщение
#13
|
Гость |
Олег, спасибо за код, как раз то что нужно. Осталось только разобрать на куски и в мои исходники вставить.
|
Shura |
22.04.2005 20:00
Сообщение
#14
|
Пионер Группа: Пользователи Сообщений: 136 Пол: Мужской Реальное имя: Александр Репутация: -2 |
Процедура TurnAfterHit неправильная!!!. Я писал на днях такую же прогу, тока ещё сила тяжести действует и потеря энергии. Так я тоже сначала просто менял составляющие скоростей шариков. Ну вот пример: первый шарик изначально покоится, а второй висит над ним, но не ровно над ним, а со смещением, скажем в пол-радиуса. После соударения они должны коряво в разные скорости разлететься, а с использованием той процедуры первый шарик просто прыгает вверх-вниз, а второй так вообще не двигаетса - беспредел! Уже второй день в голове крутится... Мне кажется, что надо посчитать угол между осью абсцисс и касательной к шарикам в точке соударения и как-то его использовать. Вот код. В чём ошибка?
Var -------------------- Старайтесь восполнять пробелы в области незнания! ;-D
|
Altair |
22.04.2005 20:11
Сообщение
#15
|
Ищущий истину Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: 45 |
Цитата Процедура TurnAfterHit неправильная!!!. А в чем заключается неправильность? Втом, что не учитывается гравитация? или то, что отскок шариков не в точности с физическими законами? Это неточность физической модели описанной алгоритмом, а не ошибка алгоритма. Программаработает, и создается впечателение правильного отскакивания ... Что еще нужно? p.s. все программы корыея выкладываю, проверенны.... -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
Shura |
22.04.2005 20:22
Сообщение
#16
|
Пионер Группа: Пользователи Сообщений: 136 Пол: Мужской Реальное имя: Александр Репутация: -2 |
Цитата(Oleg_Z @ 22.04.05 21:11) А в чем заключается неправильность? Ну я ж привёл пример. Вот когда они в воздухе сталкиваются, то кажется, что правильно. А вот в крайних случаях... Не может же быть, чтобы не учитывались координаты точки соударения относительно координат самих шариков? -------------------- Старайтесь восполнять пробелы в области незнания! ;-D
|
Altair |
22.04.2005 20:26
Сообщение
#17
|
Ищущий истину Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: 45 |
Если не нравится, исправь!
-------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
Shura |
22.04.2005 20:42
Сообщение
#18
|
Пионер Группа: Пользователи Сообщений: 136 Пол: Мужской Реальное имя: Александр Репутация: -2 |
Цитата(Oleg_Z @ 22.04.05 21:26) Если не нравится, исправь! Хех, так если я б знал как, я бы не спрашивал - я же помощи прошу! -------------------- Старайтесь восполнять пробелы в области незнания! ;-D
|
Altair |
22.04.2005 20:49
Сообщение
#19
|
Ищущий истину Группа: Модераторы Сообщений: 4 824 Пол: Мужской Реальное имя: Олег Репутация: 45 |
а понял
насчет неправильности... l:=Arctan((y2-y1)/(x2-x1)) - PI/2; уверен? что-то оущениечто надо перевоить в грудусы...потмоу что возвращается в радианах... -------------------- Помогая друг другу, мы справимся с любыми трудностями!
"Не опускать крылья!" (С) |
Shura |
22.04.2005 20:58
Сообщение
#20
|
Пионер Группа: Пользователи Сообщений: 136 Пол: Мужской Реальное имя: Александр Репутация: -2 |
Да не - нам то в радианах потом и нужно будет. Это "l" для касательной, а надо для прямой соединяющей коорд. первого шарика и точки касания - т.е. надо без "- PI/2". Но дело не в этом, всё таки в самих формулах скоростей чо-то... Может откомпилируешь тот код вместе с моими формулами, и если надо, изменишь что-то - всё-тки посмотреть на это надо (попробуешь тот случай, что я описывал, проверить).
-------------------- Старайтесь восполнять пробелы в области незнания! ;-D
|
Текстовая версия | 1.11.2024 23:36 |