2012-10-25 21 views
1

这个想法是,你必须拍摄面板。所以面板将被设置在屏幕顶部的随机位置,然后向下移动到屏幕底部。您必须在形状达到底部之前使用形状拍摄面板。但我不知道如何测试创建的形状是否位于面板的位置以重置面板。目前这是我的代码,但如果测试错误。如何测试一个形状和面板是否在同一位置

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

形状是椭圆形的,但也许这对于OP是足够的。 – NGLN

+0

所以,也许你需要用数学来解决这个问题。没有办法做到这一点_easy_。如果只用一个维度拉伸这个椭圆,那么可以尝试用确定圆的拉伸的一些系数来检查碰撞矩形与圆形。 – Darthman

+0

对于圆和椭圆的数学不是很难,但[这个答案](http://stackoverflow.com/a/13065119/757830)似乎很容易,但我。 – NGLN

0

传统的方法是检查所有的4个角object1 w的论是它的内部对象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碰撞他的面板,然后这个代码再次运行,并再次......在你的代码中,你使用'睡眠(10)'。我期望这是其中的原因。在这个例程中做一些事情来防止它再次发生。例如:清除阵列中的光线。 – NGLN

+0

@NGLN我试过了你说的,但是当我点击鼠标按钮时,形状像10像素移动,然后停止,当它停止正在向下移动的面板时,它现在像在屏幕顶部疯狂地移动,左边的位置不断,但顶部的位置保持为0.任何想法为什么发生这种情况,以及如何解决它? – Craig

相关问题