2012-10-25 3 views
1

Идея состоит в том, что вы должны снимать панель. Таким образом, панель будет установлена ​​в случайном месте в верхней части экрана, а затем переместится вниз в нижнюю часть экрана. Вы должны снять панель с фигурами, прежде чем она достигнет дна. Но я не знаю, как проверить, если созданная форма находится в месте расположения панели для сброса панели. На данный момент это мой код, но тесты if false.Как проверить, находятся ли фигура и панель в одном и том же месте

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, ExtCtrls, StdCtrls, jpeg; 

const 
    MaxRays=100; 
    RayStep=8; 
type 
    TForm1 = class(TForm) 
    Panel1: TPanel; 
    Timer1: TTimer; 
    Timer2: TTimer; 
    Button1: TButton; 
    Shape1: TShape; 
    Timer3: TTimer; 
    Image1: TImage; 
    procedure Timer2Timer(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure FormActivate(Sender: TObject); 
    procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState; 
     MousePos: TPoint; var Handled: Boolean); 
    procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState; 
     MousePos: TPoint; var Handled: Boolean); 
    procedure Timer3Timer(Sender: TObject); 
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton; 
     Shift: TShiftState; X, Y: Integer); 
    private 
    { Private declarations } 
    Rays:array[0..MaxRays-1] of TShape; 

    public 
    procedure StartPanelAnimation1; 
    procedure DoPanelAnimationStep1; 
    function PanelAnimationComplete1: Boolean; 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 
var key : char; 
{$R *.dfm} 

{ TForm1 } 



{ TForm1 } 

procedure TForm1.DoPanelAnimationStep1; 
begin 
Panel1.Top := Panel1.Top+1; 
end; 

function TForm1.PanelAnimationComplete1: Boolean; 
begin 
Result := Panel1.Top=512; 
end; 

procedure TForm1.StartPanelAnimation1; 
begin 
    Panel1.Top := 0; 
    Timer1.Interval := 1; 
    Timer1.Enabled := True; 
end; 

procedure TForm1.Timer2Timer(Sender: TObject); 
begin 
    DoPanelAnimationStep1; 
    if PanelAnimationComplete1 then 
    StartPanelAnimation1; 
    if (shape1.Top < panel1.Top) and (shape1.Left < panel1.Left+104) and (shape1.Left >  panel1.Left) then 
    begin 
    startpanelanimation1; 
    sleep(10); 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
button1.Hide; 
    key := 'a'; 
    timer2.Enabled := true; 
    StartPanelAnimation1; 
end; 

procedure TForm1.FormActivate(Sender: TObject); 
begin 
shape1.Visible := false; 
timer2.Enabled := false; 
end; 

procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
    begin 
image1.Left := image1.Left-10; 
end; 

procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
    begin 
    image1.Left := image1.Left+10; 
    end; 

procedure TForm1.Timer3Timer(Sender: TObject); 
var 
    i:integer; 
begin 
    for i:=0 to MaxRays-1 do 
    if Rays[i]<>nil then 
    begin 
     Rays[i].Top:=Rays[i].Top-RayStep; 
     if Rays[i].Top<0 then FreeAndNil(Rays[i]); 
    end; 
end; 


procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
    var 
    i:integer; 
begin 
    i:=0; 
    while (i<MaxRays) and (Rays[i]<>nil) do inc(i); 
    if i<MaxRays then 
    begin 
    Rays[i]:=TShape.Create(Self); 
    Rays[i].Shape:=stEllipse; 
    Rays[i].Pen.Color:=clRed; 
    Rays[i].Pen.Style:=psSolid; 
    Rays[i].Brush.Color:=clYellow; 
    Rays[i].Brush.Style:=bsSolid; 
    Rays[i].SetBounds(X-4,Y-20,9,41); 
    Rays[i].Parent:=Self; 
    end; 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    i:integer; 
begin 
    for i:=0 to MaxRays-1 do Rays[i]:=nil; 
end; 

end. 

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

Вот новый код

unit Unit1; 

interface 


uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, ExtCtrls, StdCtrls, jpeg; 

    const 
    MaxRays=100; 
    RayStep=8; 
type 
    TForm1 = class(TForm) 
    Panel1: TPanel; 
    Timer1: TTimer; 
    Timer2: TTimer; 
    Button1: TButton; 
    Shape1: TShape; 
    Timer3: TTimer; 
    Image1: TImage; 
    Timer4: TTimer; 
    procedure Timer2Timer(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure FormActivate(Sender: TObject); 
    procedure FormMouseWheelDown(Sender: TObject; Shift: TShiftState; 
     MousePos: TPoint; var Handled: Boolean); 
    procedure FormMouseWheelUp(Sender: TObject; Shift: TShiftState; 
     MousePos: TPoint; var Handled: Boolean); 
    procedure Timer3Timer(Sender: TObject); 
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton; 
     Shift: TShiftState; X, Y: Integer); 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    Rays:array[0..MaxRays-1] of TShape; 
    public 
    procedure StartPanelAnimation1; 
    procedure DoPanelAnimationStep1; 
    function PanelAnimationComplete1: Boolean; 
    function EllipticShapeIntersectsPanel(Shape: TShape; Panel: TPanel): Boolean; 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 
var key : char; 
{$R *.dfm} 

{ TForm1 } 



{ TForm1 } 

procedure TForm1.DoPanelAnimationStep1; 
begin 
Panel1.Top := Panel1.Top+1; 
end; 

function TForm1.PanelAnimationComplete1: Boolean; 
begin 
Result := Panel1.Top=512; 
end; 

procedure TForm1.StartPanelAnimation1; 
var left : integer; 
begin 
    Panel1.Top := 0; 
    randomize; 
    left := random(clientwidth-105); 
    panel1.Left := left; 
    Timer1.Interval := 1; 
    Timer1.Enabled := True; 
end; 

procedure TForm1.Timer2Timer(Sender: TObject); 
var I: Integer; 
begin 
DoPanelAnimationStep1; 
    if PanelAnimationComplete1 then 
    StartPanelAnimation1; 
    I := 0; 
    while (Rays[I] <> nil) and (I < MaxRays) do 
    begin 
    if EllipticShapeIntersectsPanel(Rays[I], Panel1) then 
    Inc(I); 
    startpanelanimation1; 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
button1.Hide; 
key := 'a'; 
timer2.Enabled := true; 
StartPanelAnimation1; 
end; 

procedure TForm1.FormActivate(Sender: TObject); 
begin 
shape1.Visible := false; 
timer2.Enabled := false; 
end; 

procedure TForm1.FormMouseWheelDown(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
begin 
image1.Left := image1.Left-10; 
end; 

procedure TForm1.FormMouseWheelUp(Sender: TObject; Shift: TShiftState; 
    MousePos: TPoint; var Handled: Boolean); 
begin 
image1.Left := image1.Left+10; 
end; 


procedure TForm1.Timer3Timer(Sender: TObject); 
var 
    i:integer; 
begin 
    for i:=0 to MaxRays-1 do 
    if Rays[i]<>nil then 
    begin 
     Rays[i].Top:=Rays[i].Top-RayStep; 
     if Rays[i].Top<0 then FreeAndNil(Rays[i]); 
    end; 
end; 

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
var 
    i:integer; 
    left : integer; 
    top : integer; 
begin 
    i:=0; 
    while (i<MaxRays) and (Rays[i]<>nil) do i:= i+10; 
    if i<MaxRays then 
    begin 
    Rays[i]:=TShape.Create(Self); 
    Rays[i].Shape:=strectangle;; 
    Rays[i].Pen.Color:=clRed; 
    Rays[i].Pen.Style:=psSolid; 
    Rays[i].Brush.Color:=clred; 
    Rays[i].Brush.Style:=bsSolid; 
    left := image1.Left+38; 
    top := image1.Top-30; 
    Rays[i].SetBounds(left,top,9,33); 
    Rays[i].Parent:=Self; 
    end; 

end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
Screen.Cursor:=crNone; 
end; 

function TForm1.EllipticShapeIntersectsPanel(Shape: TShape; 
    Panel: TPanel): Boolean; 
var 
    ShapeRgn: HRGN; 
begin 
    with Shape.BoundsRect do 
    ShapeRgn := CreateEllipticRgn(Left, Top, Right, Bottom); 
    try 
    Result := RectInRegion(ShapeRgn, Panel.BoundsRect); 
    finally 
    DeleteObject(ShapeRgn); 
    end; 
end; 

end. 

ответ

0

я, наконец, получил его на работу я редактировал код в этом, как Таймер 3

procedure TForm1.Timer3Timer(Sender: TObject); 
var 
    i:integer; 
begin 
    for i:=0 to MaxRays-1 do 
    if Rays[i]<>nil then 
    begin 
     Rays[i].Top:=Rays[i].Top-RayStep; 
     if (rays[i].Top>panel1.top) and (rays[i].Top<panel1.top+25) and (rays[i].Left>panel1.Left) and (rays[i].left<panel1.Left+150) then 
     begin 
     freeandnil(rays[i]); 
     startpanelanimation1; 
     end; 
    end; 
end; 

Так что теперь он работает так, как надо!

2
if IntersectRect(Panel1.BoundsRect, Shape1.Boundsrect) then 
    // collided 
+0

Формы эллиптические, но, возможно, этого достаточно для ОП. – NGLN

+0

Итак, возможно, вам нужно использовать математику для решения этой проблемы. Нет никаких возможных способов сделать это. Если этот эллипс растянут только с одним размером, вы можете попытаться проверить столкновение rect vs circle с некоторым коэффициентом, определяющим протяженность круга. – Darthman

+0

Математика для обоих кругов и эллипсов не является жесткой, но [этот ответ] (http://stackoverflow.com/a/13065119/757830) кажется мне довольно легким. – NGLN

0

традиционный способ проверить все 4 угла object1 ш hether это внутри объект 2.

function IsPanelCollide(Panel: TPanel; Shape: TShape): boolean; 
var 
    TL, TR, BL, BR: boolean; 
begin 
    // if TOP LEFT panel inside shape 
    TL := (Panel.Top >= Shape.Top) AND (Panel.Top <= Shape.Top + Shape.Height) AND 
     (Panel.Left >= Shape.Left) AND (Panel.Left <= Shape.Left + Shape.Width); 

    // if TOP RIGHT panel inside shape 
    TR := (Panel.Top >= Shape.Top) AND (Panel.Top <= Shape.Top + Shape.Height) AND 
     (Panel.Left + Panel.Width >= Shape.Left) AND (Panel.Left + Panel.Width <= Shape.Left + Shape.Width); 

    // if BOTTOM LEFT panel inside shape 
    BL := (Panel.Top + Panel.Height >= Shape.Top) AND (Panel.Top + Panel.Height <= Shape.Top + Shape.Height) AND 
     (Panel.Left >= Shape.Left) AND (Panel.Left <= Shape.Left + Shape.Width); 

    // if BOTTOM RIGHT panel inside shape 
    BR := (Panel.Top + Panel.Height >= Shape.Top) AND (Panel.Top + Panel.Height <= Shape.Top + Shape.Height) AND 
     (Panel.Left + Panel.Width >= Shape.Left) AND (Panel.Left + Panel.Width <= Shape.Left + Shape.Width); 

    Result := (TL) AND (TR) AND (BL) AND (BR); 
end; 

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

+0

DelphiX - очень, очень старая библиотека, и вы не должны использовать ее сейчас , потому что он основан на DirectDraw, который устарел сейчас. – Darthman

6

Поскольку ваши формы являются эллиптическими, создает область temporarilly и определить пересечение с прямоугольником с RectInRegion: (. Если формами являются rectangular, то вы можете использовать рутину Darthman)

function EllipticShapeIntersectsPanel(Shape: TShape; Panel: TPanel): Boolean; 
var 
    ShapeRgn: HRGN; 
begin 
    with Shape.BoundsRect do 
    ShapeRgn := CreateEllipticRgn(Left, Top, Right, Bottom); 
    try 
    Result := RectInRegion(ShapeRgn, Panel.BoundsRect); 
    finally 
    DeleteObject(ShapeRgn); 
    end; 
end; 

Теперь кормить каждый луч в массиве к этой процедуре:

procedure TForm1.Timer2Timer(Sender: TObject); 
var 
    I: Integer; 
begin 
    ... 
    I := 0; 
    while (Rays[I] <> nil) and (I < MaxRays) do 
    begin 
    if EllipticShapeIntersectsPanel(Rays[I], Panel1) then 
     // Do what you want to do 
    Inc(I); 
    end; 
end; 
+1

Умное мышление. Кроме того, вы можете выполнить рудиментарную проверку на панели и ограничивающий прямоугольник круга, а затем использовать теорему Пифагора для более тонкой проверки. есть еще кое-что, чтобы оптимизировать сначала, если вы используете фигуры для построения игры с.;) – GolezTrol

+0

@Craig Если на следующем интервале таймера одна или несколько фигур сталкиваются с t он панель, затем этот код запускается снова, и снова ... В вашем коде вы используете 'Sleep (10)'. Я ожидаю, что это будет причиной. Сделайте что-нибудь в этой рутине, чтобы это не повторилось. Например: очистите луч от массива. – NGLN

+0

@NGLN Я пробовал то, что вы сказали, но когда я нажимаю кнопку мыши, форма перемещается как 10 пикселей, а затем останавливается, когда она останавливает панель, которая двигалась вниз, как правило, теперь движется как сумасшедшая в верхней части экрана, меняя ее левая позиция постоянно, но верхняя позиция остается 0. Любая идея, почему это происходит и как ее исправить? – Craig

Смежные вопросы