Консультация № 167061
12.05.2009, 13:58
0.00 руб.
0 2 1
Уважаемые Эксперты! Исправьте пожалуйста задачу, очень прошу
нужно чтобы границы были четкими, т.е. шарик не заходил на границу(слева так и есть а вот справа чуть чуть заходит), и нужно исключить, чтобы шарик не двигался перпендикулярно линиям фигуры, т.е. только по диагонали, заранее премного благодарен!!!(код в приложении)

Приложение:
Program figure;
uses crt, graph;
type my=object
x,y,x1,y1:integer;
color,color1:byte; r,q,z:real;
x5,y5:integer; x2,y2,x3,y3,x4,y4,x6,y6,a,b:integer;
s,l,i,j,t:integer; p:pointer;
procedure init;
procedure pixel;
procedure show;
procedure step;
end;


procedure my.init;
begin
color:=11;
x:=5;
y:=5;
x1:=x;
y1:=400;
x2:=600;
y2:=y;
x3:=200;
y3:=y1;
x4:=600;
y4:=200;
x5:=200;
y5:=200;

x6:=150;
y6:=350;

end;
procedure my.pixel;
{ Вектор движения }
var dx,dy: integer;
begin

i:=imagesize(15,15,25,25);
getMem(p,i);
(* i:=random(getmaxX); j:=random(getmaxY); *)
{ Начальные координаты точки должны попасть внутрь фигуры }
{ Условие цикла исключает попадание точки в "вырез" }
repeat
i:=x+random(x2-x); j:=y+random(y1-y);
until (i<x5) or (j<y5);

setcolor(red);
setfillstyle(1,red);
fillEllipse(i,j,2,2);
i:=i-3; j:=j-3;
Getimage(i,j,i+6,j+6,p^);

delay(3000);

putimage(i,j,p^,xorput);

{ Зададим начальный вектор движения точки }
{ При таком диапазоне движение будет только под 45 градусов }
{ можно расширить диапазон например -2..2 - тогда точка будет }
{ двигаться быстрее и уже добавятся углы в 30 и 60 градусов }
{ Цикл нужен для того чтобы было смещение хотябы по одной оси }
{ иначе точка будет стоять на месте }
repeat
dx:=random(3)-1; {-1 .. 1}
dy:=random(3)-1; {-1 .. 1}
until (dx<>0) or (dy<>0);

repeat

{ Проверим столкновение со стенками }
{ Не учитываю размеры точки и толщину линий, поэтому по нижним }
{ и правым границам чуть выходит за край фигуры - можно подогнать }
{ по оси X }
if (j<y5) and (i+dx>x2) or (j>y5) and (i+dx>x5) or (i+dx<x) then begin
dx:=-dx;
{ Сделаем случайных отскок, если нет смещения по оси Y }
if dy=0 then dy:=random(3)-1;
end;
{ по оси Y }
if (i<x5) and (j+dy>y1) or (i>x5) and (j+dy>y5) or (j+dy<y) then begin
dy:=-dy;
{ Сделаем случайных отскок, если нет смещения по оси X }
if dx=0 then dx:=random(3)-1;
end;

(* if (i<getmaxX) and (j<getmaxY) then
begin
i:=i+random(2);
j:=j+random(2); *)

i:=i+dx;
j:=j+dy;

putimage(i,j,p^,xorPut);
delay(3000);
putimage(i,j,p^,xorPut);
(* end; *)

{ Проверяем попадание в "цель" }
if (i>=x6) and (j>=y6) and (i<=x5) and (j<=y1) then begin
{ Остановим движение }
{ хотя это не обязательно, если будем выходить из цикла }
dx:=0; dy:=0;
{ А тут рисуем "взрыв" }
{...}

break; { Выходим из цикла }
end;

until keypressed;
readln;
freemem(p,i);
end;

procedure my.show;
begin
setcolor(1);
putpixel(x,y,color);
putpixel(x1,y1,color);
putpixel(x2,y2,color);
putpixel(x3,y3,color);
putpixel(x4,y4,color);
putpixel(x5,y5,color);
setlinestyle(0,0,3);
line(x,y,x1,y1);
line(x,y,x2,y2);
line(x1,y1,x3,y3);
line(x2,y2,x4,y4);
line(x4,y4,x5,y5);
line(x3,y3,x5,y5);
rectangle(x6,y6,x3,y3);
end;

Procedure my.step;
begin
init;
show;
pixel;
end;


var
ch:byte; gd,gm:integer; o:my;
begin
gd:=vga; gm:=vgahi; randomize;
initGraph(Gd, Gm, ''); o.step; readln; closegraph; readln;
end.

Обсуждение

давно
Старший Модератор
31795
6196
12.05.2009, 16:30
общий

Вы даже комментарии не читали.
{ Зададим начальный вектор движения точки }
{ При таком диапазоне движение будет только под 45 градусов }
{ можно расширить диапазон например -2..2 - тогда точка будет }
{ двигаться быстрее и уже добавятся углы в 30 и 60 градусов }
{ Цикл нужен для того чтобы было смещение хотябы по одной оси }
{ иначе точка будет стоять на месте }

repeat
dx:=random(3)-1; {-1 .. 1}
dy:=random(3)-1; {-1 .. 1}
until (dx<>0) or (dy<>0);

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

{ Проверим столкновение со стенками }
{ Не учитываю размеры точки и толщину линий, поэтому по нижним }
{ и правым границам чуть выходит за край фигуры - можно подогнать }

{ по оси X }
if (j<y5) and (i+dx>x2) or (j>y5) and (i+dx>x5) or (i+dx<x) then begin
dx:=-dx;
{ Сделаем случайных отскок, если нет смещения по оси Y }
if dy=0 then dy:=random(3)-1;
end;
{ по оси Y }
if (i<x5) and (j+dy>y1) or (i>x5) and (j+dy>y5) or (j+dy<y) then begin
dy:=-dy;
{ Сделаем случайных отскок, если нет смещения по оси X }
if dx=0 then dx:=random(3)-1;
end;

Добавьте проверку на ширину линий и размеры точки.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
12.05.2009, 20:47
общий
это ответ
Здравствуйте, S K A L T !

1)
Вы считываете изображение шарика с помощью: Getimage(i,j,i+6,j+6,p^);, обратите внимание на шестерки, это есть высота и ширина изображения, которую Вы не учитываете при проверке столкновения со стенкой в строках:
Код:
  { по оси X }
if (j<y5) and (i+dx>x2) or (j>y5) and (i+dx>x5) or (i+dx<x) then dx:=-dx;
{ по оси Y }
if (i<x5) and (j+dy>y1) or (i>x5) and (j+dy>y5) or (j+dy<y) then dy:=-dy;

при проверке нижнего-правого предела границ. Я эти строки переписал так:
Код:
  { по оси X }
if (j<y5) and (i+dx>x2-k) or (j>y5) and (i+dx>x5-k) or (i+dx<x) then dx:=-dx;
{ по оси Y }
if (i<x5) and (j+dy>y1-k) or (i>x5) and (j+dy>y5-k) or (j+dy<y) then dy:=-dy;

где k- константа равная шесть.
2)
В строках генерации начального смещения :
Код:
  repeat
dx:=random(3)-1; {-1 .. 1}
dy:=random(3)-1; {-1 .. 1}
until (dx<>0) and (dy<>0);

замените логическую операцию на AND, после этого у Вас останутся только диагональные направления и соответственно уже строкибудут лишние:
Код:
  if dy=0 then dy:=random(3)-1;
if dx=0 then dx:=random(3)-1;

Окончательный вариант в приложении.

Удачи Вам!

Приложение:
Program figure;
uses crt, graph;
const k=6;
type my=object
x,y,x1,y1:integer;
color,color1:byte; r,q,z:real;
x5,y5:integer; x2,y2,x3,y3,x4,y4,x6,y6,a,b:integer;
s,l,i,j,t:integer; p:pointer;
procedure init;
procedure pixel;
procedure show;
procedure step;
end;


procedure my.init;
begin
color:=11;
x:=5;
y:=5;
x1:=x;
y1:=400;
x2:=600;
y2:=y;
x3:=200;
y3:=y1;
x4:=600;
y4:=200;
x5:=200;
y5:=200;

x6:=150;
y6:=350;

end;
procedure my.pixel;
{ Вектор движения }
var dx,dy: integer;
begin

i:=imagesize(15,15,25,25);
getMem(p,i);
(* i:=random(getmaxX); j:=random(getmaxY); *)
{ Начальные координаты точки должны попасть внутрь фигуры }
{ Условие цикла исключает попадание точки в "вырез" }
repeat
i:=x+random(x2-x); j:=y+random(y1-y);
until (i<x5) or (j<y5);

setcolor(red);
setfillstyle(1,red);
fillEllipse(i,j,2,2);
i:=i-3; j:=j-3;
Getimage(i,j,i+k,j+k,p^);

delay(3000);

putimage(i,j,p^,xorput);

{ Зададим начальный вектор движения точки }
{ При таком диапазоне движение будет только под 45 градусов }
{ можно расширить диапазон например -2..2 - тогда точка будет }
{ двигаться быстрее и уже добавятся углы в 30 и 60 градусов }
{ Цикл нужен для того чтобы было смещение хотябы по одной оси }
{ иначе точка будет стоять на месте }
repeat
dx:=random(3)-1; {-1 .. 1}
dy:=random(3)-1; {-1 .. 1}
until (dx<>0) and (dy<>0);

repeat

{ Проверим столкновение со стенками }
{ Не учитываю размеры точки и толщину линий, поэтому по нижним }
{ и правым границам чуть выходит за край фигуры - можно подогнать }
{ по оси X }
if (j<y5) and (i+dx>x2-k) or (j>y5) and (i+dx>x5-k) or (i+dx<x) then dx:=-dx;
{ по оси Y }
if (i<x5) and (j+dy>y1-k) or (i>x5) and (j+dy>y5-k) or (j+dy<y) then dy:=-dy;

(* if (i<getmaxX) and (j<getmaxY) then
begin
i:=i+random(2);
j:=j+random(2); *)

i:=i+dx;
j:=j+dy;

putimage(i,j,p^,xorPut);
delay(3000);
putimage(i,j,p^,xorPut);
(* end; *)

{ Проверяем попадание в "цель" }
if (i>=x6) and (j>=y6) and (i<=x5) and (j<=y1) then begin
{ Остановим движение }
{ хотя это не обязательно, если будем выходить из цикла }
dx:=0; dy:=0;
{ А тут рисуем "взрыв" }
{...}

break; { Выходим из цикла }
end;

until keypressed;
readln;
freemem(p,i);
end;

procedure my.show;
begin
setcolor(1);
putpixel(x,y,color);
putpixel(x1,y1,color);
putpixel(x2,y2,color);
putpixel(x3,y3,color);
putpixel(x4,y4,color);
putpixel(x5,y5,color);
setlinestyle(0,0,3);
line(x,y,x1,y1);
line(x,y,x2,y2);
line(x1,y1,x3,y3);
line(x2,y2,x4,y4);
line(x4,y4,x5,y5);
line(x3,y3,x5,y5);
rectangle(x6,y6,x3,y3);
end;

Procedure my.step;
begin
init;
show;
pixel;
end;


var
ch:byte; gd,gm:integer; o:my;
begin
gd:=vga; gm:=vgahi; randomize;
initGraph(Gd, Gm, ''); o.step; readln; closegraph; readln;
end.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа