-
Как правильно подсчитать траекторию полёта мяча.
Вот такой у меня код. В результате от стенок мяч отбивается нормально. от ракетки отбивается правильно только от правой стороны ракетки, а слева вообще ведет себя мячик не реально, или при сталкивании с левой стороной он просто летит верх или отбивается слева задолго от ракетки(на растоянии от ракетки слева).
function PointInRect(X, Y, Left, Right, Top, Bottom: Single): Boolean; begin Result := ( ((X >= Left) and (X <= Right)) = (Right > Left) ) and ( ((Y >= Bottom) and (Y <= Top)) = (Top > Bottom) ); end;
//------------------------------------------------------------------------------ // Возвращает True, если прямоугольники соприкасаются //------------------------------------------------------------------------------ function RectCollides(Left1, Right1, Top1, Bottom1, Left2, Right2, Top2, Bottom2: Single): Boolean; begin Result := (PointInRect(Left1, Top1, Left2, Right2, Top2, Bottom2)) or (PointInRect(Right1, Top1, Left2, Right2, Top2, Bottom2)) or (PointInRect(Right1, Bottom1, Left2, Right2, Top2, Bottom2)) or (PointInRect(Left1, Bottom1, Left2, Right2, Top2, Bottom2)); end;
//------------------------------------------------------------------------------ // Возвращает True, если ПЕРВЫЙ прямоугольник лежит внутри ВТОРОГО (пока без надобности) //------------------------------------------------------------------------------ function RectInside(Left1, Right1, Top1, Bottom1, Left2, Right2, Top2, Bottom2: Single): Boolean; begin Result := (PointInRect(Left1, Top1, Left2, Right2, Top2, Bottom2)) and (PointInRect(Right1, Top1, Left2, Right2, Top2, Bottom2)) and (PointInRect(Right1, Bottom1, Left2, Right2, Top2, Bottom2)) and (PointInRect(Left1, Bottom1, Left2, Right2, Top2, Bottom2)); end;
procedure TBAll.TraceBallTrajectory; var BY, BVY,BVX, BX: Single; procedure AddPoint; begin SetLength(Ball.Trajectory, Length(Ball.Trajectory)+1); Ball.Trajectory[HIGH(Ball.Trajectory)].X := BX; Ball.Trajectory[HIGH(Ball.Trajectory)].Y := BY; end; begin BX := Ball.X; BY := Ball.Y; BVY := Ball.VY; BVX := Ball.VX;
FillChar(Ball.Trajectory, SizeOf(Ball.Trajectory), 0); AddPoint; // начинаем траекторию в текущей позиции шара
repeat BY := BY + BVY; BX := BX + BVX; if ((BY+Ball.Size >= 300) and (BVY > 0)) or ((BY-Ball.Size <= 0) and (BVY < 0)) then begin BVY := -BVY; AddPoint; // добавляем точки, когда шар бьется о стены end; if ((Bx+Ball.Size >= 300) and (BVx > 0)) or ((Bx-Ball.Size <= 0) and (BVx < 0)) then begin BVx := -BVx; AddPoint; // добавляем точки, когда шар бьется о стены end;
until ( (BX+Ball.Size >= player.X-player.PadWidth ) and (Ball.VX > 0) ) or ( (By+Ball.Size >= player.y-player.PadWidth ) and (Ball.Vy > 0) );
AddPoint; // заканчиваем траекторию, там где шар может попасть по доске end;
procedure TBall.BallProc; var path, deltaX, deltaY: Single; begin
ball.y := ball.y + ball.Vy; ball.X := ball.X + ball.VX;
if ((Ball.Y+Ball.Size >= 300) and (Ball.VY > 0)) or ((Ball.Y-Ball.Size <= 0) and (Ball.VY < 0)) then begin Ball.VY := -Ball.VY; Inc(Ball.CurPoint); // показывает к какой точке траектории шар летит end;
if ((Ball.x+Ball.Size >= 300) and (Ball.Vx > 0)) or ((Ball.x-Ball.Size <= 0) and (Ball.Vx < 0)) then begin Ball.Vx := -Ball.Vx; Inc(Ball.CurPoint); // показывает к какой точке траектории шар летит end;
if (RectCollides( Ball.X-Ball.Size, Ball.X+Ball.Size, Ball.Y+Ball.Size, Ball.Y-Ball.Size, player.X-player.PadWidth, player.X+player.PadWidth, player.y+player.PadHeight, player.Y-player.PadHeight )) then begin if ball.y < 10 then begin
deltaX := ball.X + (player.X - Focus); deltaY := ball.Y + (player.Y - Focus); end;
path := Sqrt( Sqr(deltaX) + Sqr(deltaY) ); Ball.VX := Ball.CurSpeed * (deltaX / path); Ball.VY := Ball.CurSpeed * (deltaY / path); TraceBallTrajectory; Ball.CurPoint := 1; end;
end;
-
а тебе точно компилятор никаких warning'ов не даёт?
-
Выдайт разные Сообщения но они же не критични
-
>[2] GAMEZ (31.01.08 11:45) >Выдайт разные Сообщения но они же не критични вот пока «разные сообщения» не исчезнут — чини код. ибо код крив до умопомрачения.
-
Блин мучаюсь над этой мелкой проблемой уже четвертый день. Узнаю как это делается напишу статьи для программистов, что бы они не ломали себе мозги......
-
лучше не пиши статей, кривых статей и без тебя достаточно. лучше учись программировать — оно полезней будет. ибо код твой — страшная каша.
-
Вот посмотрите на этот код.
// точка траекториии шара TPoint2f = record X, Y: Single; end;
T2DVector = record X : single; // Координата Х Y : single; // Координата У end;
T2DRect = record Coord : T2DVector; // Координаты центра Width : integer; // Ширина Height : integer; // Высота end;
TPlayer = class constructor Create; public cord: T2DVector; PadSpeed: Single; PadWidth, PadHeight: Single; end;
TBall = class constructor Create; public cord: T2DVector; dV:T2DVector; Size : Single; public procedure BallProc; end;
var Player : TPlayer; Ball : TBall; i: integer;
procedure EXInit; begin player := TPlayer.Create; ball := TBall.Create; end;
procedure Init; begin
player.cord.X := 0; player.cord.Y := 0; player.PadWidth := 128; player.PadHeight := 32;
ball.cord.X := 150; ball.cord.Y := 0; ball.dv.x := 0.2; ball.dv.y := 0.2; ball.Size := 20;
end;
constructor TPlayer.Create; begin
end;
constructor TBall.Create; begin
end;
PROCEDURE fInc( var Value : single; Amount : single ); BEGIN Value := Value + Amount; END;
FUNCTION SetVector( X, Y : single ) : T2DVector; BEGIN Result.X := X; Result.Y := Y; END;
FUNCTION SetRect( Coord : T2DVector; Width, Height : integer ) : T2DRect; BEGIN;
Result.Coord := Coord; Result.Width := Width; Result.Height := Height;
END;
FUNCTION GetLength( First, Second : T2DVector ) : single; BEGIN Result := sqrt(sqr(First.X - Second.X) + sqr(First.Y - Second.Y)); END;
FUNCTION GetAngle( First, Second : T2DVector ) : single; VAR TMP : single; BEGIN TMP := GetLength(First, Second); if (Second.X >= First.X) and (Second.Y > First.Y) then Result := arccos((Second.X - First.X)/TMP)*180/Pi + 0; if (Second.X < First.X) and (Second.Y >= First.Y) then Result := arccos((Second.Y - First.Y)/TMP)*180/Pi + 90; if (Second.X <= First.X) and (Second.Y < First.Y) then Result := arccos((First.X - Second.X)/TMP)*180/Pi + 180; if (Second.X > First.X) and (Second.Y <= First.Y) then Result := arccos((First.Y - Second.Y)/TMP)*180/Pi + 270; END;
// Возвращает True, если точка лежит в заданном прямоугольнике function PointInRect(X, Y, Left, Right, Top, Bottom: Single): Boolean; begin Result := ( ((X >= Left) and (X <= Right)) = (Right > Left) ) and ( ((Y >= Bottom) and (Y <= Top)) = (Top > Bottom) ); end;
// Возвращает True, если прямоугольники соприкасаются function RectCollides(Left1, Right1, Top1, Bottom1, Left2, Right2, Top2, Bottom2: Single): Boolean; begin Result := (PointInRect(Left1, Top1, Left2, Right2, Top2, Bottom2)) or (PointInRect(Right1, Top1, Left2, Right2, Top2, Bottom2)) or (PointInRect(Right1, Bottom1, Left2, Right2, Top2, Bottom2)) or (PointInRect(Left1, Bottom1, Left2, Right2, Top2, Bottom2)); end;
// Возвращает True, если ПЕРВЫЙ прямоугольник лежит внутри ВТОРОГО function RectInside(Left1, Right1, Top1, Bottom1, Left2, Right2, Top2, Bottom2: Single): Boolean; begin Result := (PointInRect(Left1, Top1, Left2, Right2, Top2, Bottom2)) and (PointInRect(Right1, Top1, Left2, Right2, Top2, Bottom2)) and (PointInRect(Right1, Bottom1, Left2, Right2, Top2, Bottom2)) and (PointInRect(Left1, Bottom1, Left2, Right2, Top2, Bottom2)); end;
FUNCTION Collision_Rect( First, Second : T2DRect ) : boolean; BEGIN Result := (First.Coord.X + First.Width >= Second.Coord.X) and (First.Coord.X <= Second.Coord.X + Second.Width) and (First.Coord.Y + First.Height >= Second.Coord.Y) and (First.Coord.Y <= Second.Coord.Y + Second.Height);
END;
// вот здесь и должно происходить вычисление полёта мяча procedure TBall.BallProc; begin
end;
-------------------------------------------------------------------------
Не знаю как это сделать. Думал ракетку разбить на секции из квадратов просчитать столкновения с этими прямоугольными секциями
000000 <- это типа ракетка
Но потом подумал что если мяч столкнётя с двумя то что я тогда буду делать. Незнаю. Надо Как то подругому просчитывать столкновения. Подскажите пожалуйста.
-
Как правильно подсчитать траекторию полёта мяча.
в какой плоскости?
-
kakaya ploskosty ??? 2D prostranstvo
-
автор, ты несколько не представляешь себе, что пишешь. у тебя вон координаты пиксельные, чего ты привязался к нескольким квадратам? прямоугольник с прямоугольником, всего лишь.
а остальное у тебя там сверху было начато, хоть и корявенько. идея верная ж: скорость извесна, квант времени известен — бери, да трассируй вектор. да в каждой точке проверяй, не буцнулось ли куда.
конечно, проще вычислить расстояние до той же ракетки и безо всякой трассировки выяснить, не шмякнется ли мячик на данном шаге. всё это в принципе обыкновенная планиметрия. вникни в неё да в векторную алгебру — сразу прояснится в голове.
-
кстати, хинт: квадратные мячи человечество не использует, они катятся очень плохо. %-)
-
я тебе в 2Д три плоскости назову. XY, XZ, YZ =) в каких направлениях ракетка движется?
-
> [11] tButton © (03.02.08 13:09)
это уже не 2D.
-
re > KilkennyCat © (03.02.08 15:16) [12] очень даже два Д, каждая из названых плоскостей имет по два измерения =) просто одна плоскость это проекций сверху, другая - сбоку, третья - с другого бока =) от выбраной проекции зависит поведение мяча.
-
Почитал я про кимематику и про векторы. Должно быть такое, если сталкивается мяч с ракеткой то завершается работа приложения это так для проверки Посмотрите...
ball.acceleration.x := force/ball.mass; ball.acceleration.y := force/ball.mass;
ball.Velocity.X := ball.Acceleration.x ; ball.Velocity.y := ball.Acceleration.y ;
ball.Location.X := ball.Location.X + ball.Velocity.x ; ball.Location.y := ball.Location.y + ball.Velocity.y ;
distance.X := player.cord.X - ball.Location.Y; distance.y := player.cord.y - ball.Location.y;
magnitude.X := distance.X * distance.X; magnitude.y := distance.y * distance.y;
minDist := ((player.cord.x + (player.PadWidth / 2)) - (player.cord.y + (player.PadHeight / 2))) + 100 ;
if ((magnitude.X <= minDist)) and ((magnitude.y <= minDist)) then engine.Quit;
Только почему то мячик сталкивается не со всей ракеткой, а только с нижней левой точкой. Почему.
P.S.
А разве этот сайт не называется ДЕЛФИ МАСТЕРА.
-
> А разве этот сайт не называется ДЕЛФИ МАСТЕРА.
Лично меня можешь называть просто МАСТЕР. Приставка ДЕЛФИ вовсе необязательна.
-
if (мяч.x <= (левая_ракетка.x - левая_ракетка.width)) and (мяч.y <= левая_ракетка.y) and (мяч.y >= (левая_ракетка.y + левая_ракетка.width)) then begin
end; ну и аналогично для правой. трудно писать с наладонника, незная какая у тебя система координа используется.
-
Вот так я нашол столкновение с ракеткой. function BOXVsSphere(Minx,Maxx,Pos :T2DVector;R:Single): boolean;
var
d, d2 :single;
begin
d := 0;
if (Pos.x < Minx.x) then
begin
d2:= Pos.x - Minx.x;
d := d+d2 * d2;
end;
if (pos.x > Maxx.x) then
begin
d2:= Pos.x - Maxx.x;
d := d + d2*d2;
end;
if (Pos.y < Minx.y) then begin d2:= Pos.y - Minx.y; d := d+d2*d2; end;
if (pos.y > Maxx.y) then begin d2:= Pos.y - Maxx.y; d := d+d2*d2; end;
result := d <= (R * R);
end;
function Vector(X, Y: single): T2DVector;
begin
Result.X := X;
Result.Y := Y;
end;
---------------------------------
ball.acceleration.x := force/ball.mass;
ball.acceleration.y := force/ball.mass;
ball.Velocity.X := ball.Acceleration.x ;
ball.Velocity.y := ball.Acceleration.y ;
ball.Location.X := ball.Location.X + ball.Velocity.x ;
ball.Location.y := ball.Location.y + ball.Velocity.y ;
if BOXVsSphere(vector(player.cord.X,player.cord.Y), vector(player.cord.x+player.PadWidth,player.cord.Y+player.PadHeight),
vector(ball.Location.X , ball.Location.Y),ball.Size)
then
engine.Quit;
---------------------------------- А как сделать чтобы мячь обратно отлитал с правильной траекторией. Что то нужно делать с углом столкновения наверное. Подскадите.
-
а что такое «правильная траектория»?
в играх типа арканоида обычно да — угол отражения меняется в зависимости от того, по какой части paddle попал мячик. тебе именно это надо?
-
-
|