如何在不添加相同数量的代码的情况下向表单添加更多对象

时间:2012-10-22 14:56:02

标签: delphi delphi-7 duplication

我一直在制作一款有趣的小游戏。在游戏中,你是一个小型宇宙飞船(一个图像),在物体(面板)上射出激光束(形状)。此时你只能一次发射一个激光束,因为只有一个激光束(形状)并且只有一个物体(面板)可以射击。因此,通过编码,我想知道如何添加更多激光光束和物体,尤其是激光光束,因为我不想重复每个激光光束和每个面板的程序。

这是代码。

unit Unit1;

interface

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

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 }
  public
   procedure StartPanelAnimation1;
   procedure DoPanelAnimationStep1;
   function  PanelAnimationComplete1: Boolean;
   procedure Startlazeranimation1;
   procedure DolazeranimationStep1;
   { 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;
 timer3.Enabled := 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.DolazeranimationStep1;
begin
 shape1.Top := shape1.Top-10;
end;


 procedure TForm1.Startlazeranimation1;
 begin
 shape1.Top := image1.Top;
 shape1.Left := image1.Left+55;
 shape1.Visible := true;
  Timer3.Interval := 1;
  Timer3.Enabled := True;
end;

procedure TForm1.Timer3Timer(Sender: TObject);
var k : integer;
begin
 DolazeranimationStep1;
  if (shape1.Top < panel1.Top) and (shape1.Left < panel1.Left+104) and (shape1.Left > panel1.Left) or         (shape1.Top=clientheight) then
   begin
    timer3.Enabled := false;
    shape1.Visible := false;
    for k := 1 to 5 do
    sleep(1);
    begin
    application.ProcessMessages;
    end;
    shape1.Top := 0;
    shape1.Left := 0;
   end;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
 shape1.Show;
 startlazeranimation1;
end;

end.

(以上是旧代码)

我已经成功完成了Stijn Sanders的建议。但现在在这个

 if (Shape1.top < panel1.Top) and (shape1.Left < panel1.Left+104) and (shape1.Left > panel1.Left)   then

永远不会测试true,因为shape1从不传递panel1它,只有在点击时创建的形状才会传递面板。

还有另一种测试形状是否在pnael的方法。

2 个答案:

答案 0 :(得分:5)

并非所有组件都需要在设计时创建。在运行时,例如使用TTimer及其事件,您可以调用TShape.Create(Self);以获得额外的形状。在方便的地方保持对结果值的引用,例如(动态)数组,并记住设置MyShape.Parent:=Self;MyShape.Parent:=Panel1;,以便系统知道显示此新控件的时间和位置。

unit Unit1;

interface

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

const
  MaxRays=100;
  RayStep=8;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
    Rays:array[0..MaxRays-1] of TShape;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  for i:=0 to MaxRays-1 do Rays[i]:=nil;
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.Timer1Timer(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;

end.

答案 1 :(得分:1)

在运行时动态创建对象并在列表中跟踪它们,然后您可以在需要时循环遍历列表,例如:

unit Unit1; 

interface 

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

type 
  TForm1 = class(TForm) 
    PanelTimer: TTimer; 
    Button1: TButton; 
    LazerTimer: TTimer; 
    Image1: TImage; 
    procedure PanelTimerTimer(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    procedure FormCreate(Sender: TObject); 
    procedure FormDestroy(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 LazerTimerTimer(Sender: TObject); 
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
  private 
    { Private declarations } 
    Lazers: TList; 
    Panels: TList; 
    procedure StartPanelAnimation;
    procedure StartLazerAnimation; 
  public
    { Public declarations } 
  end; 

var 
  Form1: TForm1; 

implementation 

{$R *.dfm} 

{ TForm1 } 

procedure TForm1.StartPanelAnimation; 
var
  Panel: TPanel;
begin 
  Panel := TPanel.Create(Self);
  Panel.Parent := Self;
  Panel.Top := 0;
  // set other Panel properties as needed... 
  Panel.Visible := True; 
  Panels.Add(Panel);
  if not PanelTimer.Enabled then
  begin
    PanelTimer.Interval := 1; 
    PanelTimer.Enabled := True; 
  end;
end; 

procedure TForm1.PanelTimerTimer(Sender: TObject); 
var
  k: Integer;
  Panel: TPanel;
begin 
  for k := 0 to Panels.Count-1 do
  begin
    Panel := TPanel(Panels[k]);
    Panel.Top := Panel.Top + 1; 
    if Panel.Top = 512 then 
      Panel.Top := 0;
  end;
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  StartPanelAnimation1;  
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
  Lazers := TList.Create;
  Panels := TList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject); 
begin 
  Lazers.Free;
  Panels.Free;
end;

procedure TForm1.FormActivate(Sender: TObject); 
begin 
  PanelTimer.Enabled := False; 
  LazerTimer.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.StartLazerAnimation; 
var
  Lazer: TShape;
begin 
  Lazer := TShape.Create(Self);
  Lazer.Parent := Self;
  // set Lazer properties as needed...
  Lazer.Top := Image1.Top; 
  Lazer.Left := Image1.Left + 55; 
  Lazer.Visible := True; 
  Lazers.Add(Lazer);
  if not Lazer.Enabled then
  begin
    Lazer.Interval := 1; 
    Lazer.Enabled := True; 
  end;
end; 

procedure TForm1.LazerTimerTimer(Sender: TObject); 
var
  k, m : integer;
  Lazer: TShape;
  Panel: TPanel;
  PanelHit: Boolean; 
begin 
  k := 0;
  while k < Lazers.Count do
  begin
    Lazer := TShape(Lazers[k]);
    Lazer.Top := Lazer.Top - 10; 
    for m := 0 to Panels.Count-1 do
    begin        
      Panel := TPanel(Panels[m]);
      PanelHit := (Lazer.Top > (Panel.Top+Panel.Height)) and (Lazer.Left > Panel.Left) and (Lazer.Left < (Panel.Left+Panel.Width));
      if PanelHit then
      begin
        Panels.Remove(Panel);
        Panel.Free;
        if Panels.Count = 0 then
          PanelTimer.Enabled := False;
        Break;
      end;
    end;
    if PanelHit or (Lazer.Top = 0) then 
    begin 
      Lazers.Remove(Lazer);
      Lazer.Free;
      if Lazers.Count = 0 then
        LazerTimer.Enabled := False; 
    end else
      Inc(k); 
  end;
end; 

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  StartLazerAnimation; 
end; 

end.  
相关问题