2

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

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. 
4

3 回答 3

7

由于您的形状是椭圆形的,因此请创建一个临时区域并确定与矩形的交集RectInRegion

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;

(如果形状是矩形,那么你可以使用Darthman的例程。)

现在将阵列中的每条射线馈入此例程:

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;
于 2012-10-25T09:03:04.287 回答
2
  if IntersectRect(Panel1.BoundsRect, Shape1.Boundsrect) then
  // collided
于 2012-10-25T06:52:00.893 回答
0

传统的方法是检查对象 1 的所有 4 个角是否在对象 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 的计时器对于动画来说更好更流畅。

于 2012-10-25T08:53:34.737 回答