Помощь - Поиск - Пользователи - Календарь
Полная версия: Моделирование движения шаров
Форум «Всё о Паскале» > Pascal, Object Pascal > Написание игр
Страницы: 1, 2
18192123
Вот такое задание:
Даны два шарика диаметром М. Промоделировать движение шариков по всей плоскости экрана. Шарики могут двигаться по прямым линиям. Изменение угла движения после столкновения с границей экрана или друг с другом может быть случайной величиной. Шарик не может вылететь за пределы квадрата. Пользователь может варьировать скорости движения шариков с помощью стрелок управления курсором.

Хотелось бы разобраться в коде программы... ( дело в том, что код не мой)
Объясните пожалуйста назначение каждой из процедур в тексте приведённой ниже программы!
18192123

procedure Change(g1,g2:integer;var n:integer;a:real);
begin
if g1>=g2 then begin sound(random(100)+880);randomize; n:=-n; a:=3.14*(random(90))/180;end;
end;




как я поняла, эта процедура используется для произвольного изменения угла отклонения при столкновении объёктов. ( обязательно исправляйте меня, если я где-то не точна или, тем более, не права!!!)

теперь вопросы:
для чего используются g1,g2 ?
для чего нужна такая операция n:=-n?

a:=3.14*(random(90))/180;


Это ведь вычисление радианной меры угла?

Дальше....
 
procedure Change2(x,x1:integer;var n,m,n1,m1:integer);
begin
if x>=x1 then begin n:=abs(n);m:=-abs(m1);n1:=-abs(n1);m1:=abs(m);end;
end;



мне вообще не понятно, для чего эта процедура...
за что отвечают передаваемые в процедуру параметры?
каково назначение здесь операций

n:=abs(n); {...} n1:=-abs(n1);



Следующее...

procedure Exit(x,y,r:integer;var flag:boolean);
begin
if (x-r<50) or (x+r>570) or (y-r<50) or (y+r>450) then
begin
flag:=true;
SetColor(red);
OutTextXY(170,190,'Sorry, fatal programm error! Press any key');
ReadKey
end;
end;




Ясно, что процедура для выхода из программы в случае ошибки.
Но не ясно, что означает это длинное условие выхода

if (x-r<50) or (x+r>570) or (y-r<50) or (y+r>450) then



Заранее спасибо.
Lapp
Марина, извини, но ты выбрала неправильную программу для примера..
Она слишком кривая и слабая, чтоб с нее копировать. Даже разбираться в этом коде никакого желания нет..

Движение объектов по экрану разбиралось тут не раз. Попробуй написать сама. Или хотя бы начни с алгоритма, блок-схемы.. Я, например, готов тебе помочь в этом благородном деле, но объяснять для чего в этой программе совершенно ненужные вещи - уволь..

Если согласна, поищи по форуму про движение объектов. Я могу тебе выложить чуть позже примеры основных частей кода, если будут трудности.
18192123
Цитата(Lapp @ 6.04.2007 8:54) *

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

Движение объектов по экрану разбиралось тут не раз. Попробуй написать сама. Или хотя бы начни с алгоритма, блок-схемы.. Я, например, готов тебе помочь в этом благородном деле, но объяснять для чего в этой программе совершенно ненужные вещи - уволь..

Если согласна, поищи по форуму про движение объектов. Я могу тебе выложить чуть позже примеры основных частей кода, если будут трудности.

Да я согласна.
Час буду искать про движение объекта....

Спасибо большое, что согласился помочь!
18192123
Цитата(Lapp @ 6.04.2007 8:54) *

начни с алгоритма..


1. Меню (где можно выбрать радиус 2-х шариков)
Я могу оставить по этому вопросу то, что было в примере(неудачном) - процедуры MENU и _case_?

2. Рисуем шарики(здесь ясно) --> Убираем с экрана( и здесь) --> ВЫбираем новое их положение (каким способом это лучше делать???) --> Показываем на новом месте

3. Проверка на выход за пределы экрана (что делать, если получается вылет за пределы экрана: аварийный выход из программы или ....??????)

---Соударение шаров друг с другом и с пределами экрана (мне не ясно, что нужно указывать по этому пункту...Может связать с законом сохранения импульса???)

4. Управление скоростями с помощью стрелок на клавиатуре - не представляю, как это осуществить!

Все мои соображения..... unsure.gif
Tan
Случайно на компе наткнулся на задачку с шариком погляди может какие - то идем возьмёшь, не помню откуда эта прога в упор cool.gif :
program biljard;
uses crt,graph;
var driver,mode,vektorx,vektory,x,y:integer;
x1,y1,Lx,Ly:real;
begin
clrscr;
driver:=detect;
initgraph(driver,mode,'c:\bp\bgi');
setcolor(15); {white}

rectangle(70,70,500,350);{razmeri stola}
x1:=80;y1:=340; {nachaljnije koordinati kruga}
vektorx:=7;vektory:=12;
x:=round(x1);y:=round(y1);
Lx:=vektorx/(sqrt(vektorx*vektorx+vektory*vektory));{dx}
Ly:=vektory/(sqrt(vektorx*vektorx+vektory*vektory));{dy}
circle(x,y,5);
repeat
setcolor(0); {black}
circle(x,y,5);
if (getpixel(x-6,y)=15) or (getpixel(x+6,y)=15) then Lx:=-Lx;
if (getpixel(x,y-6)=15) or (getpixel(x,y+6)=15) then Ly:=-Ly;
x1:=x1+Lx;y1:=y1+Ly;
x:=round(x1);y:=round(y1); {tak kak circle toljko v integer, okrugljajem xy}
setcolor(15); {white}
circle(x,y,5);
delay(500);{pauza dlja togo 4tobi videtj dvizhenije}
until keypressed;
readkey;
end.
Lapp
Цитата(18192123 @ 7.04.2007 21:31) *

1. Меню (где можно выбрать радиус 2-х шариков)
Я могу оставить по этому вопросу то, что было в примере(неудачном) - процедуры MENU и _case_?

Я бы оставил меню на потом. Начни с реализации движения. Не потому, что это проше, а потому что главное. После этого тебе проще будет определяться с меню.
Цитата(18192123 @ 7.04.2007 21:31) *

2. Рисуем шарики(здесь ясно) --> Убираем с экрана( и здесь) --> ВЫбираем новое их положение (каким способом это лучше делать???) --> Показываем на новом месте

Расчет нового положения производится рпо обычным формулам x1=x0+V*dt
Цитата(18192123 @ 7.04.2007 21:31) *

3. Проверка на выход за пределы экрана (что делать, если получается вылет за пределы экрана: аварийный выход из программы или ....??????)

1. Находить точку пересечения с краем.
2. продолжать движение от нее - либо с отраженной скоростью, либо со случайной (как хочешь)
Цитата(18192123 @ 7.04.2007 21:31) *

---Соударение шаров друг с другом и с пределами экрана (мне не ясно, что нужно указывать по этому пункту...Может связать с законом сохранения импульса???)

Соударение с друг другом пока не делай. Мне кажется, что это не присутствует в первоначальной формулировке. Всегда можно добавить потом (если строго по физике - то потребуется задание массы; она может быть пропорциональна кубу радиуса, например). Сначала сделай без взаимодействия (пусть проходят друг сквозь друга, не замечая)
Цитата(18192123 @ 7.04.2007 21:31) *

4. Управление скоростями с помощью стрелок на клавиатуре - не представляю, как это осуществить!

С помощью стрелок - не очень удобно, поскольку их (шаров) несколько. Это обязательно? Можно сделать цифрами: цифра увеличивает, шифт-цифра уменьшает. Так годится?

Программу Tan'а еще не смотрел, посмотрю.. В любом случае, если уж решилась делать сама - то и делай, это лучше.
18192123
Цитата(Lapp @ 8.04.2007 10:58) *


С помощью стрелок - не очень удобно, поскольку их (шаров) несколько.


Мне нужно именно управление стрелками.
Можно осуществить такой вариант:
стрелки "вправо-влево" для одного шара,
"вверх-вниз" для другого???

volvo
Для того, чтобы начать реализовывать меню (интерфейс), надо сначала реализовать логику работы программы, о чем и говорил Lapp... Сделай сначала это, чтобы потом не получилось как в первой приведенной тобой программе - где "рюшечки" настолько заполонили код, что разобраться в нем просто нереально...

Цитата
Можно осуществить такой вариант:
стрелки "вправо-влево" для одного шара,
"вверх-вниз" для другого?
Можно и так, почему же нельзя? Какие клавиши навесишь, такие и будут...
18192123
Мои "очень скромные" наработки.....
вот только шарики не хотят двигаться...

uses crt,
graph;
var x1, x2, y1, y2, r1, r2,
dx, dy, bgC, Gd, Gm : integer;

procedure draw (x, y, r, c : integer);
begin
Setcolor ©;
circle (x, y, r);
Floodfill(x, y, c);
end;

procedure escape (x, y, r, bgC : integer);
begin
Setcolor (bgC);
circle (x, y, r);
Floodfill(x, y, bgC);
end;

procedure move (x, y, dx, dy : integer);
begin
x := x+ dx;
y := y + dy;
end;

procedure charge_on_oppositeX (x, dx : integer);
begin
dx := -dx;
x := x + dx;
end;

procedure charge_on_oppositeY (y, dy : integer);
begin
dy := -dy;
y := y + dy;
end;

Procedure border (x, y, r : integer);
begin
if (x + r >= GetMaxX - 1) or ( x - r <= 1) then charge_on_oppositeX( x, dx);
if (y+r>=GetMaxY-1) or (y-r<=1) then charge_on_oppositeY ( y, dy);
end;

begin
Gd := Detect;
InitGraph (Gd, Gm, '');
If GraphResult <> grOk then halt(1);
x1 := 50; y1 := 150; x2 := 400; y2 := 300; r1 := 30; r2 := 40; dx := 100; dy := 90;
bgC := 0;
rectangle (1,1, getMaxX - 1, getMaxY - 1);
repeat
begin
draw (x1, y1, r1, white);
draw (x2, y2, r2, red );
delay(100);
escape (x1, y1, r1, bgC);
escape (x2, y2, r2, bgC);
border (x1, y1, r1);
border (x2, y2, r2);
move (x1, y1, dx, dy);
move (x2, y2, dx, dy);
end;
until keypressed;
readkey;
closegraph;
end.


TarasBer
procedure move (x, y, dx, dy : integer);
замените на
procedure move (var x, y: integer; dx, dy : integer);
и в следующих 3х процедурах тоже
18192123
Цитата(TarasBer @ 8.04.2007 17:36) *

procedure move (x, y, dx, dy : integer);
замените на
procedure move (var x, y: integer; dx, dy : integer);
и в следующих 3х процедурах тоже

ээээ.....теперь слишком много стало шаров....
и ещё половина шарика с красным контуром крутится в правом нижнем угле экрана.....
volvo
Значит, смотри, в чем твои ошибки:

1) если ты думаешь, что
procedure escape (x, y, r, bgC : integer);
begin
Setcolor (bgC);
circle (x, y, r);
Floodfill(x, y, bgC);
end;

сотрет с экрана то, что было нарисовано процедурой draw, то очень сильно ошибаешься... Не сотрет... Ибо ты не установила шаблон заливки через SetFillPattern, а по умолчанию заливается все сплошным белым цветом... Да это и лишнее, потому что гораздо проще воспользоваться готовой процедурой отрисовки залитого круга (FillEllipse)...

2) у тебя 2 шара в любом случае будут двигаться "синхронно", то есть при изменении направления движения одного изменится и направление движения второго. Неудивительно, кстати, переменных то на 2 шара всего по одной на координату X и Y... Если хочешь более "независимое" движение шаров - добавляй еще 2 переменные: dx2, dy2...

3) ты задаешь очень большие значения dx и dy, я немного уменьшил ...

Вот так, примерно (примерно - потому, что это тоже еще надо поправить - в момент касания шаром бордюра он затирается - пересмотри условия в процедуре Border):
Нажмите для просмотра прикрепленного файла
Lapp
Марина, я покажу пример программы, которая гоняет объекты по полю. Программа работает в текстовой моде и без меню, но в ней есть управление скоростями. Надеюсь, она будет тебе полезна в некотором отношении..
Дело в том, что в ней четко проведено деление: все, что относится к выводу на экран, выделено в отдельный модуль. Сама же основная программа осуществляет движение и управление. По идее, если вместо существующего модуля, работающего с текстом, написать модуль, работающий с графикой, то основную программу менять не нужно (кроме строчки uses). Модуль для графики можно написать по образу и подобию текстового, заменив текстовый вывод на графический (советы volvo тут очень пригодятся).

Попробуй разобраться в том, как все это работает. Используются абстрактные координаты и экранные, что дает гибкость и удобство. В тексте вместо кружочков - квадратики, но это не самое важное smile.gif. Отражение происходит просто со сменой знака соответствующей составляющей скорости (без случайностей). Начальное положение, скорости и размеры задаются случайно. Названия процедур отражают их суть. Сами объекты называются "It" (оно, нечто smile.gif).

Управление скоростями такое: нужно выбрать объект, нажав клавишу с его номером (по умолчанию выбран первый). Стрелки вверх/вниз увеличивают/уменьшают вертикальную скорость выбранного объекта, влево/вправо - горизонтальную. Пробел делает паузу (продолжение любой клавишей), Esc завершает программу. Можкшь также поиграть параметрами в программе - например, NIt (количество объектов), скоростью.. По идее, она работает в окне любого размера.

Я не совсем до конца протестировал на точность перевода, если заметишь сбои - говори.

Вот головная программа:
{Moving It's}
{By Lapp}
uses
CRT,ItsText;

var
x1,x2,y1,y2,MaxR,MaxV0:real;

procedure CreateIt(n:integer);
begin
with It[n] do begin
r:=Random*MaxR;
rx:=Round(r/(x2-x1)*(MaxX-MinX));
ry:=Round(r/(y2-y1)*(MaxY-MinY));
x:=x1+r+Random*(x2-x1-r*2);
y:=y1+r+Random*(y2-y1-r*2);
vx:=Random*MaxV0-MaxV0/2;
vy:=Random*MaxV0-MaxV0/2;
c:=(n+8)mod 15+1
end
end;

procedure MoveIt(n:integer);
begin
with It[n] do begin
x:=x+vx;
if x<x1+r then begin
x:=2*(x1+r)-x; vx:=-vx
end;
if x>x2-r then begin
x:=2*(x2-r)-x; vx:=-vx
end;
y:=y+vy;
if y<y1+r then begin
y:=2*(y1+r)-y; vy:=-vy
end;
if y>y2-r then begin
y:=2*(y2-r)-y; vy:=-vy
end;
xs:=Round((x-x1)/(x2-x1)*(MaxX-MinX))+MinX;
ys:=Round((y-y1)/(y2-y1)*(MaxY-MinY))+MinY;
end
end;

var
i,NIt,The:integer;
ch:char;
GameOver:boolean;

begin
NIt:=9; {Number of It's, 1<=NIt<=9}
MaxV0:=50; {Maximum speed }
MaxR:=50; {Maximum radius}

OpenBoard;
x1:=0; x2:=MaxX*10;
y1:=0; y2:=Round(MaxY*10*Aspect);
Randomize;
for i:=1 to NIt do begin
CreateIt(i); MoveIt(i)
end;
GameOver:=false;
for i:=1 to NIt do ShowIt(i);
The:=1;
repeat
for i:=1 to NIt do begin
MoveIt(i);
with It[i] do if (xs<>xs0)or(ys<>ys0) then begin
HideIt(i);
ShowIt(i)
end
end;
if KeyPressed then begin
ch:=ReadKey;
case ch of
#0: begin
ch:=ReadKey;
with It[The] do case ch of
#72:if vy<100 then vy:=vy*2;
#75:if vx>0.01 then vx:=vx*0.5;
#77:if vx<100 then vx:=vx*2;
#80:if vy>0.01 then vy:=vy*0.5;
end
end;
'1'..'7':The:=Ord(ch)-48;
' ':repeat ReadKey until not KeyPressed;
#27:GameOver:=true
end
end
until GameOver;
for i:=1 to NIt do HideIt(i);
CloseBoard
end.

А это - текстовый модуль:
{unit for moving It's}
{by Lapp}
unit ItsText;
interface
uses
CRT;

const
MIt=9; {max number of Iteatures}

type
tIt=record
x,y,vx,vy,r:real; {position, speed, real radius}
rx,ry,c,xs,ys,xs0,ys0:integer; {screen radius, color, screen pos, old screen pos}
end;

var
It:array[1..MIt]of tIt;
NIt:integer;
Aspect,MinX,MinY,MaxX,MaxY,x0,y0:integer;
TA:byte;

procedure ShowIt(n:integer);
procedure HideIt(n:integer);
procedure OpenBoard;
procedure CloseBoard;

implementation

procedure ShowIt(n:integer);
var
i,j,xs1,ys1,rx,ry:integer;
begin
with It[n] do begin
TextColor©;
for j:=ys-ry to ys+ry do for i:=xs-rx to xs+rx do begin
GoToXY(i,j);
Write('█')
end;
GoToXY(xs,ys); Write(n);
xs0:=xs;
ys0:=ys;
end
end;

procedure HideIt(n:integer);
var
i,j:integer;
begin
with It[n] do begin
for j:=ys0-ry to ys0+ry do for i:=xs0-rx to xs0+rx do begin
GoToXY(i,j);
Write(' ')
end;
end
end;

procedure OpenBoard;
begin
MinX:=1; MaxX:=WindMax and 255+1;
MinY:=1; MaxY:=WindMax shr 8+1;
Aspect:=2;
x0:=WhereX; y0:=WhereY;
TA:=TextAttr
end;

procedure CloseBoard;
begin
GoToXY(x0,y0);
TextAttr:=TA
end;

begin
end.

18192123
Цитата(Lapp @ 9.04.2007 15:11) *

Марина, я покажу пример программы, которая гоняет объекты по полю.

Спасибо! Буду разбираться!
18192123
Цитата(volvo @ 9.04.2007 2:13) *

в момент касания шаром бордюра он затирается - пересмотри условия в процедуре Border):

Не пойму, почему происходит "затирание"?

Добавлено через 8 мин.
Такой вопрос: как учесть (при столкновении) изменение угла движения?
volvo
Цитата
Не пойму, почему происходит "затирание"?

Потому, что надо сначала менять положение шара, и только потом проверять его на столкновение с бордюром, правда? smile.gif

Вот так:
...
move (x1, y1, dx1, dy1); { <--- Сначала это }
move (x2, y2, dx2, dy2);
border (x1, y1, r1, dx1, dy1); { <--- и только потом - проверка }
border (x2, y2, r2, dx2, dy2);
...


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

А вот как менять - это уже зависит от того, насколько реалистично ты это хочешь сделать... Можно просто поменять знак DX или DY на противоположный, можно рассчитать новые направления движения шаров по формулам...
18192123
Цитата(volvo @ 9.04.2007 22:23) *

А вот как менять - это уже зависит от того, насколько реалистично ты это хочешь сделать... Можно просто поменять знак DX или DY на противоположный, можно рассчитать новые направления движения шаров по формулам...


Я хочу делать наиболее реалистично...
Про ф-цию - понятно, буду делать. Спасибо.
Lapp
Цитата(18192123 @ 9.04.2007 23:56) *

Я хочу делать наиболее реалистично...
Про ф-цию - понятно, буду делать. Спасибо.

Реалистично - я уже говорил: нужно вводить массы. Тогда можно будет использовать ЗСИ. Но это можно сделать только имея нормальную интерперетацию скорости! В моем примере скорость практически реальная, при этом время течет квантами (в цикле). Посмотри, как это устроено, и сможешь менять скорость по ЗСИ.

Для максимальной реалистичности можно использовать натуральное время (в секундах) и натуральные рамеры экранного окна (в см). Это не так сложно, но реально того, как сделано в моей проге, достаточно для описания физики соударений. Только там у меня рассчитано на несколько (до 9) объектов, при этом проверка на соударение производится, ессно, циклом по всем для каждого. При девяти это еще не так много, но если еще увеличивать количество, то производительность может начать падать..
18192123
Цитата(Lapp @ 9.04.2007 15:11) *




x1,x2,y1,y2 : real;




А это - текстовый модуль:

{unit for moving It's}
{by Lapp}
It:array[1..MIt]of tIt;
NIt:integer;
Aspect,MinX,MinY,MaxX,MaxY,x0,y0:integer;
TA:byte;




за что отвечают переменные x1,x2,y1,y2 и Aspect,MinX (относительно чего определяется максимальные и минимальные координаты?),MinY,MaxX,MaxY,x0,y0 и ТА ?
Lapp
Цитата(18192123 @ 11.04.2007 0:36) *

за что отвечают переменные x1,x2,y1,y2 и Aspect,MinX (относительно чего определяется максимальные и минимальные координаты?),MinY,MaxX,MaxY,x0,y0 и ТА ?

Вот, смотри.
x1,x2,y1,y2 - это абстрактные координаты, приписанные окну (границы по Х и по У). Им можно приписать любые значения (есть только ограничения x1<x2 и y1<y2, но и они появляются не сразу, а только при рассмотрении выхода шарика за границу окна). Например, если исходить из реальных размеров на экране, то им можно дать значения в см, типа от 0 до 20 по Х и от 0 до 10 по У. Но если ты представляешь себе окно, как поле космического сражения (в игре), то можно присвоить им значения от 100 до 200 парсеков по Х и от 0 до 50 парсеков по У, например. Если (другой пример) ты используешь окно для построения графика, при этом строишь в нем график синуса, то разумно по Х сделать от -пи до +пи, а по У - от -1 до +1 (или от +1 до -1, поскольку при построении графика не нужно проверять выход за границы окна).

Эти абстрактные координаты мспользуются для осуществления движения шариков. То есть пересчет координат по скорости со времением происходит именно в них. Перевод в реальные координаты экрана (пикселы в графике или символы в тексте) производится только перед выводом (за небольшим исключением, скажу позже). Существуют формулы для перевода, они явно написаны, например, в процедурах ShowIt (ПоказатьЭто) и HideIt (СпрятатьЭто).

Aspect - это параметр, который учитывает "неквадратность" точки. Точка - это маленькое пятнышко. В идеале это квадратик (в ЖК-мониторах так и есть) поверхности, который закрашен в некоторый цвет. В современных мониторах пиксел имеет одинаковые размеры по горизонтали и вертикали (даже если это не квадратик, а пятнышко, как в ЭЛТ-мониторе). Иными словами, сместившись на 100 пикселов вправо и 100 вниз, мы пройдем (примерно) 2.5 см вправо и 2.5 см вниз. Это было не всегда - в старых мониторах типа EGA и CGA эти пути были не равны - но сейчас можно считать, что это так (хотя в некоторых модах все же бывает искажение). Совсем другое дело в текстовой моде.. Пиксел (символ) в ней совсем не квадратный, это прямоугольник. Вот это число, Aspect, как раз и учитывает эту неквадратность. Сейчас объясню, как.

Окно может быть разным - большим, маленьким. (Попробуй менять размер окна. Правда, для этого, пожалуй, нужно использовать FPC.. Кстати, какой компилятор ты используешь?) Я стараюсь сделать абстрактные координаты так, чтоб они как-то соответствовали размерам окна. Поэтому я сначала, в процедуре OpenBoard (ОткрытьПоле) выясняю его размеры (в символах):
  MinX:=1; MaxX:=WindMax and 255+1;
MinY:=1; MaxY:=WindMax shr 8+1;

Информацию о переменной WindMax смотри в описании модуля CRT.
MinX,MinY,MaxX,MaxY - это реальные координаты окна на экране, в пикселах (символах).

После этого я вычисляю абстрактные координаты по реальным, давая по 10 абстрактных единиц на одну ширину пиксела (символа) :
  x1:=0; x2:=MaxX*10;
y1:=0; y2:=Round(MaxY*10*Aspect);

Применение переменной Aspect тут должно учесть, что пиксел наш не квадратный. В моем примере я ему присвоил значение 2, поскольку высота символа примерно вдвое больше ширины (если хочешь, можешь измерить и уточнить это значение).

Что это нам дает? А вот, что.
Если скорости объекта (ну, пока скажем, пиксела) по Х и У одинаковые, то без учета Aspect'а, если пиксел смещать за один цикл на одну позицию, то реальная скорость пиксела на экране по У будет вдвое больше, чем по Х. Мы же делаем так: по формулам с учетом скоростей по Х и У мы высчитываем новое положение объекта. Допустим, по Х он смещается на расстояние 1 пкс, и скорости по Х и У равны. Тогда использование Aspect=2 даст то, что по У смещение будет 0.5 пкс, то есть реально объект по У не сместится. На следующем цикле объект сместится по Х еще на 1 пкс, а по У - еще на 0.5 пкс, что в сумме со смещением на предыдущем ходу даст 1 (0.5+0.5=1). На этот раз объект сместится по У на 1 пкс. Мы же увидим на экране ломаную траекторию, но ведущую в правильном направлении (под 45 градусов).

Этот способ - двойные координаты, абстрактные и реальные - очень эффективен в разных ситуациях. Иногда желательно иметь тройные координаты (например, пикселы - экранные_сантиметры - парсеки). Большей глубины вложения я пока не встречал, хотя возможно.

Таким образом, можно реально осуществлять движение объектов во всех направлениях и при этом скорости по Х и У будут соотноситься между собой правильно. Идея понятна? Про реализацию еще можно повыяснять.. smile.gif

Ну, а ТА, x0, y0 - это глупости... В некотором смысле лишнее smile.gif, но желательное. В эту переменную я запоминаю текущие текстовые атрибуты (цвет символа и цвет фона), чтобы вернуть их по завершении работы программы на место. Я также возвращаю на место курсор (все это в процедуре CloseBoard, ЗакрытьПоле), для запоминания которых я и использую x0 и y0. Если это не сделать, то курсор останется в том месте, где рисовался последний объект, и цвет символов будет такой же, как цвет последнего объекта. Это все тебе в графике не понадобится..

Успехов, и продолжай задавать вопросы. smile.gif
18192123
возник такой вопрос: если теоретически я должна управлять скоростью движения шаров с клавиатуры, есть ли смысл, чтобы писать процедуру, которая бы вычисляла скорости шаров после столкновения, опираясь на ЗСИ (з-н сохранения импульса)? По-моему, смысла в этом нет... или я не права?
18192123
Попыталась добавить в программу движение под углом и меню (не знаю, как при выборе одного из пунктов потом снова вернутся с главное меню.....)

кроме того, проблема в function balls_hit ( на ней выдает ошибку 207)...

что касается реальных и абстрактных координат, то посоветовалась со своим преподавателем....
он сказал, что мне не стоит на этом заоострять внимание (но всё равно спасибо большое, мне это было полезно узнать).

ниже программа....

Lapp
Цитата(18192123 @ 12.04.2007 14:43) *

если теоретически я должна управлять скоростью движения шаров с клавиатуры, есть ли смысл, чтобы писать процедуру, которая бы вычисляла скорости шаров после столкновения, опираясь на ЗСИ (з-н сохранения импульса)?

Вопрос не вполне понятен..
Неясня связь между твоим "если" и "то". blink.gif Управляешь с клавы - ну, управляй. А при чем тут столкновение? Вычисляй по ЗСИ или еще как-то (случайно - это, мне кажется выглядело вы дико на экране).
А может, ты спрашивала, есть ли смысл делать отдельную процедуру для этого или вычислять прямо в тексте?.. Это вопрос вкуса, но я вообще не понимаю (блин, так много стал не понимать.. smile.gif), почему ты делаешь из этого проблему.. ЗСИ - это звучит гордо, даже в сокращении, но фактически - это одна строчка несложных действий! Реши один раз на бумажке (столкновение считай абсолютно упругим), набей это в Паскаль - и забудь про физику! только не на всю жизнь.. smile.gif)))
Цитата(18192123 @ 12.04.2007 21:49) *

что касается реальных и абстрактных координат, то посоветовалась со своим преподавателем....
он сказал, что мне не стоит на этом заоострять внимание (но всё равно спасибо большое, мне это было полезно узнать).

Дело твое, и в принципе я согласен - начинать нужно с самого простого. Но штука в том, что потом (если продолжишь этим заниматься) ты можешь открыть для себя совершенно неожиданно, что абстрактные координаты не усложняют, а упрощают реализацию. Потому что многие вопросы, которым нужно было придумывать специальное решение, тут решаются сами собой очень естественным образом.. smile.gif Но я согласен, что чтобы осознать это, нужно набраться немного опыта. Успехов тебе в этом - а я, если найду время вставить комменты, выложу это в FAQ, чтоб не пропадало..
18192123
Цитата(Lapp @ 12.04.2007 23:52) *

Управляешь с клавы - ну, управляй. А при чем тут столкновение? Вычисляй по ЗСИ или еще как-то (случайно - это, мне кажется выглядело вы дико на экране).

Спасибо , на мой вопрос ты ответил.
18192123
Цитата(18192123 @ 12.04.2007 21:49) *

Попыталась добавить в программу движение под углом и меню (не знаю, как при выборе одного из пунктов потом снова вернутся с главное меню.....)

кроме того, проблема в function balls_hit ( на ней выдает ошибку 207)...

что касается реальных и абстрактных координат, то посоветовалась со своим преподавателем....
он сказал, что мне не стоит на этом заоострять внимание (но всё равно спасибо большое, мне это было полезно узнать).

ниже программа....

никак не получается найти ошибки....
volvo
Цитата
никак не получается найти ошибки....
Насчет #207, которая возникает в balls_hit ...

Для того, чтобы разобраться, откуда возникает эта ошибка, надо вспомнить, что же это вообще такое - RunTime Error #207:
Цитата
Invalid Floating Point Operation (Недопустимая операция с плавающей запятой)
Возможные причины возникновения:
1. Аргумент функции Trunc или Round не может быть преобразован в целое число, находящееся внутри диапазона типа LongInt.
2. Отрицательный аргумент функции Sqrt.
3. Аргумент функции Ln равен нулю, или имеет отрицательное значение.
4. Произошло переполнение стека сопроцессора


Путем небольшой модификации программы (для проверки, КАКАЯ именно из причин приводит к ошибке в твоем случае), выяснилось, что это - причина №4... Вот так программа работает без #207:

function balls_hit (const r1,r2 : integer; x1,y1,x2,y2 : integer) : boolean;
var
dist : real;
t1, t2, t3, t4, t5: real;
begin
t1 := abs(x2-x1); t2 := sqr(t1);
t3 := abs(y2-y1); t4 := sqr(t3);
t5 := t2 + t4;
dist := sqrt(t5);

balls_hit := (dist < (r1 + r2));
end;

18192123
Цитата(18192123 @ 12.04.2007 21:49) *

.... меню (не знаю, как при выборе одного из пунктов потом снова вернутся с главное меню.....)


с этим тоже проблема... как можно это реализовать?
volvo
Цитата
как можно это реализовать?

Обрамляешь все, что делается в меню Repeat / Until ... Вот так:
...
Begin
Gd := Detect;
InitGraph (Gd, Gm, '');
If GraphResult <> grOk then halt(1);

repeat
Choise := Menu ('INFO'#13'Ypravlenie'#13'Moving Balls'#13'Exit');
... { Здесь - все, что было у тебя в программе от Choise := Menu() до ReadKey }
until Choise = 3;

ReadKey;
CloseGraph;
End.
18192123
вот такие вопросы появились:
1. если шарики соприкасаются, то они просто проходят сквозь друг друга, а предполагалось, что направление будет меняться... в чём же дело?

2. не понимаю, как изменить угол ( для взятия угла у меня function ygol) при столкновении со стенками и при столкновени шаров...я применяла эту функцию (это место в программе взято в комментарий), но шарики при движении только колебаются.....

3. про варьирование скоростью с помощью стрелок управления курсором.... не пойму сам механизм этого ( "привязать" к этому клавиши - это ладно..., но вот, так скажем, к чему привязывать - ну не пойму!)
18192123
Цитата(18192123 @ 14.04.2007 20:54) *

вот такие вопросы появились:
1. если шарики соприкасаются, то они просто проходят сквозь друг друга, а предполагалось, что направление будет меняться... в чём же дело?

2. не понимаю, как изменить угол ( для взятия угла у меня function ygol) при столкновении со стенками и при столкновени шаров...я применяла эту функцию (это место в программе взято в комментарий), но шарики при движении только колебаются.....

3. про варьирование скоростью с помощью стрелок управления курсором.... не пойму сам механизм этого ( "привязать" к этому клавиши - это ладно..., но вот, так скажем, к чему привязывать - ну не пойму!)

помогите, пожалуйста! очень хочу разобраться!!! smile.gif
18192123
Цитата(18192123 @ 14.04.2007 20:54) *

вот такие вопросы появились:
1. если шарики соприкасаются, то они просто проходят сквозь друг друга, а предполагалось, что направление будет меняться... в чём же дело?

2. не понимаю, как изменить угол ( для взятия угла у меня function ygol) при столкновении со стенками и при столкновени шаров...я применяла эту функцию (это место в программе взято в комментарий), но шарики при движении только колебаются.....

3. про варьирование скоростью с помощью стрелок управления курсором.... не пойму сам механизм этого ( "привязать" к этому клавиши - это ладно..., но вот, так скажем, к чему привязывать - ну не пойму!)

про 1 - может у меня с вызовом function balls_hit , procedure balls_hit_2, .........._3 что-то не то?

а с остальным - не получается.....
18192123
по вопросу2:

begin
dx := -dx; dy := -dy;
x := round( x + dx*cos(ygol));
y := round( y + dy*sin(ygol));
end;




может я здесь dx и dy не к месту использую или нужно дополнительно вычислять расстояние , которое должен проходить шарик после изменения угла движения?
18192123
а насчёт варьирования скоростями: от чего отталкиваться (какое условие задавать) ,чтобы регулировать скорости?
Lapp
Цитата(18192123 @ 17.04.2007 22:53) *

а насчёт варьирования скоростями: от чего отталкиваться (какое условие задавать) ,чтобы регулировать скорости?

Марина, привет.
Я скажу немного не то, что ты, возможно, ожидаешь.
Ты написала довольно большую программу - сама! что, безусловно, хорошо. Но ты пренебрегла советами.. что не всегда есть хорошо. Я посмотрел твою программу сразу после твоего поста #30, и пришел к выводу, что на разгребание того, что ты наворотила придется потратить несколько часов, а потом еще несколько часов на объяснеия, что там неправильно - и этого времени у меня нету.. Потом я честно посмотрел ее снова после поста 31 - повертел, покрутил и пришел к тому же выводу.. И т.д...

Если можно, я приведу сравнение..
Некто хочет научиться варить суп. Прежде всего он идет на кухню в общаге, хватает с плиты первую попавшуюся кастрюлю, тащит ее к шеф-повару и говорит: "Объясите мне пожалуйста, зачем тут вот эти штуки.." - и показывает на плавающие там обрывки упаковочной бумаги, куски полиэтилена (нет, волосы упоминать не буду, можете не зажмать рты.. smile.gif). Что может сказать шеф-повар? Его спросили не нужно ли это, а именно с какой целью это тут. Прямо показали пальчиком, и заинтересованно и серьезно ждут ответа.. Я думаю, он поступит как в том старом анекдоте из серии про студента кулинарного техникума (у Хазанова было такое амплуа), когда упомянутый студент пришел к врачу с обваренными гениталиями. Он скажет: "вылейте все это на ..."

После этого он прочтет бедному несчастному студенту лекцию на тему о варке супа, и проведет практическое занятие, а также подарит тарелку хорошего супа. А потом скажет, как это свойственно профессорам-шеф-поварам: если что неясно - я к Вашим услугам, милейший.

Но студент, уяснив кое-что (хоть и не много), говорит - а, не хочу я разбираться в его супе. Его суп слишком сложен для меня (и мой семинарист говорит, что мне такой суп никогда не сварить..) Сварю-ка я свой собственный суп.. И варит. Но суп получается горький, пересоленый, мясо в нем не разжевать.. Что делать? Конечно, идти к шеф-повару! И спрашивать: а зачем я сделал так? а почему я сделал этак?..

Понимаешь, если программа небольшая или речь идет о фрагменте, где локализована ошибка - это одно. Но если нужно расхлебывать весь переперченый недосоленный суп... И учесть еще неправильное форматирование текста.. Ей-Богу лучше вылить его ...
Ты бы сделала хотя бы некоторый вывод из того, что тебе никто не отвечает!

Не знаю, поняла ли ты меня.. Если что не так сказал - извини, я не хотел тебя обидеть. Но только на твой вопрос (повторю его) :
Цитата(18192123 @ 17.04.2007 22:53) *

а насчёт варьирования скоростями: от чего отталкиваться (какое условие задавать) ,чтобы регулировать скорости?

- на этот вопрос я ответил в самом начале темы. Если хочешь - я могу снова подключиться. Но только не для того, чтобы отвечать на вопросы типа "а как пришить пуговицу пеньковой веревкой?". Если согласна - you are welcome! smile.gif
18192123
Если у меня положения центров шаров будут находиться с помощью такой процедуры:

procedure move (var x, y: integer; angle : single; speed : integer);
begin
x := round(x + speed*cos(angle));
y := round(y + speed*sin(angle));
end;



то как должны выглядеть процедуры
procedure charge_on_oppositeX
procedure charge_on_oppositeY, которые я использую для изменения направления движения шариков на противоположные при столкновении с границей?

Я сделала предположение ,что так:

procedure charge_on_oppositeX (var x : integer; speed : integer; angle : single);
var dx : integer;
begin
dx := round(speed*cos(angle)); dx := -dx;
x := x + dx;
end;

результат - шарики ,когда сталкиваются с границей , движутся вдоль неё и замирают в углу.


Lapp
Цитата(18192123 @ 18.04.2007 23:50) *

как должны выглядеть процедуры ..., которые я использую для изменения направления движения шариков на противоположные при столкновении с границей?
Я сделала предположение ,что так:
...
результат - шарики ,когда сталкиваются с границей , движутся вдоль неё и замирают в углу.

Нет, не так. Эти процедуры долхны менять угол, а не положение!
Примерно так:
по Х: angle:=180-angle;
по Y: angle:=-angle;
Иначе эффект действительно будет похожим на то, что ты говоришь

PS
Если в названиях процедур ты подразумевала "изменить", то это слово пишется change. А слово charge означает нечто другое.. И предлог лучше to, а не on. Это так, к слову..

Добавлено через 15 мин.
Вообще-то правильние было бы написать не 180, а Pi .. smile.gif
Извиняюсь.
18192123
Цитата(Lapp @ 19.04.2007 7:29) *

Примерно так:
по Х: angle:=180-angle;
по Y: angle:=-angle;


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

Как я полагаю, причина в этом:

function angleX (angle : single):single;
begin
angleX := (pi - angle);
end;

function angleY (angle : single): single;
begin
angleY := -angle;
end;

Procedure border (var x, y: integer; r : integer; speed: integer{; angle : single});
begin
if (x + r >= GetMaxX-1) or (x - r <= 1) then angle := angleX(angle);
if (y + r >= GetMaxY-1) or (y - r <= 1) then angle := angleY(angle);
end;




а это вызов процедур ,описанных выше:

begin
draw (x1, y1, r1, white);
draw (x2, y2, r2, red );
delay(15100);
escape (x1, y1, r1, bgC);
escape (x2, y2, r2, bgC);
move (x1, y1, angle, speed1);
move (x2, y2, angle, speed2);
border (x1, y1, r1, speed1{,angle} );
border (x2, y2, r2, speed2{, angle});
balls_hit_2;
end;



если менять скорость обоих шариков одновременно , то , когда шарики сталкиваются, то они просто сцепливаются.... - не знаю, как это исправить?)
столкновение шаров предусмотрено в следующих процедурах:

function value(const r: integer):real;
begin
value := 4/3*pi*r*r*r;
end;

procedure after_hit (spee1, speed2 : integer; x1, y1, x2, y2 : integer; angle : single);
var m1, m2 : real;
begin
m1 := value(r1);
m2 := value(r2);
speed1 := round((2*m2*speed2 + (m1-m2)*speed1)/(m1+m2));
speed2 := round((2*m1*speed1 + (m2-m1)*speed2)/(m1+m2));
x1 := round(x1 + speed1*cos(angle));
y1 := round(y1 + speed1*sin(angle));
x2 := round(x2 + speed2*cos(angle));
y2 := round(y2 + speed2*sin(angle));
end;


function balls_hit (const r1,r2 : integer; x1,y1,x2,y2 : integer) : boolean;
var
dist : real;
t1, t2, t3, t4, t5: real;
begin
t1 := abs(x2-x1); t2 := sqr(t1);
t3 := abs(y2-y1); t4 := sqr(t3);
t5 := t2 + t4;
dist := sqrt(t5);

balls_hit := (dist < (r1 + r2));
end;

procedure balls_hit_2;
begin
if balls_hit(r1,r2,x1,y1,x2,y2) then after_hit (speed1, speed2, x1, y1,x2, y2,angle);
end;



Lapp
Цитата(18192123 @ 19.04.2007 14:46) *

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

Видимо, у тебя один угол на два шара. А надо иметь на каждый шар свой угол.
18192123
Цитата(Lapp @ 19.04.2007 23:47) *

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

а как учесть два угла для разных шаров в процедуре border (может нужно и туда передавать углы?)
или это нужно учитывать в ф-ях angleX и angleY?
18192123
Мне бы хотелось, чтобы шарики, при столкновении друг с другом, изменяли угол движения... но добиться этого не удаётся:

{изменяем скорость и угол после столкновения}
procedure after_hit (spee1, speed2 : integer; x1, y1, x2, y2 : integer; angle1, angle2 : single);
var m1, m2 : real;
begin
m1 := value(r1);
m2 := value(r2);
speed1 := round((2*m2*speed2 + (m1-m2)*speed1)/(m1+m2));
speed2 := round((2*m1*speed1 + (m2-m1)*speed2)/(m1+m2));
x1 := round(x1 + speed1*cos(pi-angle1));
y1 := round(y1 + speed1*sin(-angle1));
x2 := round(x2 + speed2*cos(pi-angle2));
y2 := round(y2 + speed2*sin(-angle2));
end;

{проверка на столкновение}
function balls_hit (const r1,r2 : integer; x1,y1,x2,y2 : integer) : boolean;
var
dist : real;
t1, t2, t3, t4, t5: real;
begin
t1 := abs(x2-x1); t2 := sqr(t1);
t3 := abs(y2-y1); t4 := sqr(t3);
t5 := t2 + t4;
dist := sqrt(t5);

balls_hit := (dist < (r1 + r2));
end;

{если шары стлкнулись - изменяем скорость и угол }
procedure balls_hit_2;
begin
if balls_hit(r1,r2,x1,y1,x2,y2) then after_hit (speed1, speed2, x1, y1,x2, y2,angle1,angle2);
end;



но шарики только проводят друг через друга.....
18192123
Цитата(18192123 @ 22.04.2007 0:21) *


но шарики только проводят друг через друга.....

не пойму, в чём причина?
Lapp
Цитата(18192123 @ 22.04.2007 0:42) *

не пойму, в чём причина?

Причин несколько.
1. ты снова забываешь сменить углы..
2. одна переменная у тебя называется spee1 (должно быть, видимо, speed1)
3. Ты пересчитываешь параметры, но обратно из процедуры они у тебя не передаются. Чтоб передавались, используй декларацию var.

Можно один вопрос? Зачем ты искусственно увеличиваешь код программы? Тебе кажется, так проще? или так от вас требуют препы? Например, функция balls_hit моогла бы выглядеть много короче..
function balls_hit (r1,r2,x1,y1,x2,y2 : integer) : boolean; 
begin
balls_hit := Sqrt(Sqr(x2-x1)+Sqr(y2-y1)) < r1+r2
end;

Разве так не проще? Все сразу видно..

18192123
Цитата(Lapp @ 22.04.2007 11:20) *

Например, функция balls_hit моогла бы выглядеть много короче..
function balls_hit (r1,r2,x1,y1,x2,y2 : integer) : boolean; 
begin
balls_hit := Sqrt(Sqr(x2-x1)+Sqr(y2-y1)) < r1+r2
end;

Разве так не проще? Все сразу видно..

ф-я работала некорректно , компилятор выдавал ошибку 207, и чтобы понять причину этого выражение Sqrt(Sqr(x2-x1)+Sqr(y2-y1)) < r1+r2 было разбито на более простые (пост #27)
18192123
Цитата(Lapp @ 22.04.2007 11:20) *


3. Ты пересчитываешь параметры, но обратно из процедуры они у тебя не передаются. Чтоб передавались, используй декларацию var.


не совсем тебя поняла....какие параметры я ещё должна описать внутри ф-ции? (всё, что нужно я уже передаю из программы)
18192123
Цитата(Lapp @ 22.04.2007 11:20) *

ты снова забываешь сменить углы..

а как их менять? ( по какой состовляющей? ведь другой шарик - это не граница!)
Lapp
Цитата(18192123 @ 22.04.2007 21:38) *

не совсем тебя поняла....какие параметры я ещё должна описать внутри ф-ции? (всё, что нужно я уже передаю из программы)

Вот смотри - ты вычисляешь переменные:
  x1 := round(x1 + speed1*cos(pi-angle1));
y1 := round(y1 + speed1*sin(-angle1));
x2 := round(x2 + speed2*cos(pi-angle2));
y2 := round(y2 + speed2*sin(-angle2));
end;

- после этого выходишь из процедуры.
Как ты думаешь, что случается с переменными x1,y1,x2,y2? Они просто уничтожаются.
Чтобы они передавались в вызывающую программу, ты должна в описании фрмальных параметров употребить декларацию var :

procedure after_hit (spee1, speed2 : integer; VAR x1, y1, x2, y2 : integer; angle1, angle2 : single);

То же самое касается других параметров, которые ты хочешь передать не только туда, но и обратно.
Это понятно? Прочти про это в учебнике, плз.
18192123
Цитата(Lapp @ 23.04.2007 1:47) *



То же самое касается других параметров, которые ты хочешь передать не только туда, но и обратно.
Это понятно? Прочти про это в учебнике, плз.

Да, понятно. Извини, с этим я "стормозила" по полной программе.

Но у меня шарики всё равно проходят друг через друга...

procedure after_hit (var speed1, speed2 : integer; var x1, y1, x2, y2 : integer; var angle1, angle2 : single);
var m1, m2 : real;
begin
m1 := value(r1);
m2 := value(r2);
angle1 := -angle1;
angle2 := pi - angle2;
speed1 := round((2*m2*speed2 + (m1-m2)*speed1)/(m1+m2));
speed2 := round((2*m1*speed1 + (m2-m1)*speed2)/(m1+m2));
x1 := round(x1 + speed1*cos(angle1));
y1 := round(y1 + speed1*sin(angle1));
x2 := round(x2 + speed2*cos(angle2));
y2 := round(y2 + speed2*sin(angle2));
end;


wacko.gif
Lapp
Цитата(18192123 @ 23.04.2007 22:13) *

Но у меня шарики всё равно проходят друг через друга...

Значит, так.
1. Ты выбрала очень неудобное представление - через углы (модули скоростей и углы). Я рекомендовал тебе давно иметь просто Vx и Vy для каждого шара вместо модуля скорости и угла. Ты бы избежала очень многих проблем (это я все брюзжу про то, что то, что кажется на первый взгляд сложнее, на самом деле легче).

2. Тебе совсем не нужно вычислять координаты (x и y) в этой процедуре. Вычисляй только параметры скорости (в твоем представлении - модуль и угол). Только эти параметры используй в загаловке процедуры и описывай их как var.

3. Скорость персчитывай по ЗСИ по каждой компоненте вектора (Vx и Vy). Для этого сначала высчитай эти компоненты (как модуль скорости умножить на косинус и синус угла), потом для каждой реши уравнение ЗСИ и пересчитай. По этим новым компонентам рассчитай новый модуль скорости и угол. Эти значения нужно вернуть в вызывающую программу.

Вот так все будет работать..

PS
Представление в виде модуля и угла удобно только в реальном пространстве. Если осилишь - переделай всю прогу, замени их на компоненты по осям. Ты сама увидишь, насколько будет проще. Я уж не говорю, что на том способе, который я предлагал в начале (абстрактные координаты) ты могла бы сэкономить себе много дней времени..
18192123
Цитата(Lapp @ 24.04.2007 11:14) *


3. Скорость персчитывай по ЗСИ по каждой компоненте вектора (Vx и Vy). Для этого сначала высчитай эти компоненты (как модуль скорости умножить на косинус и синус угла), потом для каждой реши уравнение ЗСИ и пересчитай. По этим новым компонентам рассчитай новый модуль скорости и угол. Эти значения нужно вернуть в вызывающую программу.


вот что написала:

Vx1 := speed1*cos(angle1);
Vy1 := speed1*sin(angle1);
Vx2 := speed2*cos(angle2);
Vy2 := speed2*sin(angle2);




дальше не пойму...объясни, пожалуйста, подробнее.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.