2

アイデアは、パネルを撃たなければならないということです。したがって、パネルは画面上部のランダムな位置に設定され、画面の下部に移動します。パネルが一番下に到達する前に、形状でパネルを撃つ必要があります。しかし、作成された形状がパネルの位置にあるかどうかをテストして、パネルをリセットする方法がわかりません。現時点ではこれは私のコードですが、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. 
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;

(形状が長方形の場合は、ダースマンのルーチンを使用できます。)

次に、配列内の各光線を次のルーチンにフィードします。

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 がオブジェクト 2 の内側にあるかどうか、オブジェクト 1 の 4 つのコーナーすべてをチェックします。

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 に答える