我在德尔福制作了我的第一个节目,它是一个太空入侵者。所以我有两个问题:
首先,如何将代码复制到每个对象?这就是我现在所拥有的:
procedure TForm2.Timer1Timer(Sender: TObject);
begin
//Label2.Caption := IntToStr(Form2.ClientWidth);
//Label1.Caption := IntToStr(Shape2.Left + Shape2.Width);
if smer = 1 then begin
Shape2.Left:=Shape2.left+56;
Shape3.Left:=Shape3.left+56;
Shape4.Left:=Shape4.left+56;
Shape5.Left:=Shape5.left+56;
Shape6.Left:=Shape6.left+56;
if Shape6.Left+Shape6.Width>Form2.ClientWidth then begin
Shape2.Top:=Shape2.Top+56;
Shape3.Top:=Shape3.Top+56;
Shape4.Top:=Shape4.Top+56;
Shape5.Top:=Shape5.Top+56;
Shape6.Top:=Shape6.Top+56;
smer:=0;
end;
end;
if smer = 0 then begin
Shape2.Left:=Shape2.left-56;
Shape3.Left:=Shape3.left-56;
Shape4.Left:=Shape4.left-56;
Shape5.Left:=Shape5.left-56;
Shape6.Left:=Shape6.left-56;
if Shape2.Left<=0 then begin
Shape2.Top:=Shape2.Top+56;
Shape3.Top:=Shape3.Top+56;
Shape4.Top:=Shape4.Top+56;
Shape5.Top:=Shape5.Top+56;
Shape6.Top:=Shape6.Top+56;
smer:=1;
end;
end;
end;
procedure TForm2.Timer2Timer(Sender: TObject);
begin
if MetakP.Visible=true then begin
MetakP.Top:=MetakP.Top-11;
end;
if MetakN.Visible=true then begin
MetakN.Top:=MetakN.Top+11;
end;
if MetakN.Top>Form2.Height then MetakN.Visible:=false;
if MetakP.Top<=0 then begin
MetakP.Left:=Image1.Left+16;
MetakP.Top:=Image1.Top;
MetakP.visible:=false;
Let:=0;
end;
if (MetakN.left>=Image1.Left) or (MetakN.Left+MetakN.Width >= Image1.left) then begin // da li je metak desno od kocke
if MetakN.left<=Image1.Left+Image1.Width then begin // da li je metak levo od kocke
If MetakN.Top<=Image1.Top+Image1.Height then begin // da li je metak ispod kocke
if MetakN.Top>=Image1.Top-Image1.Height then begin
if MetakN.Visible=true then begin
Image1.Visible:=false;//
MetakN.Left:=Image1.Left+16;
MetakN.Top:=Image1.Top;
MetakN.visible:=false;
Let:=0;
gub:=gub+1;
//Image1.Enabled:=false;
end;
end;
end;
end;
end;
if (MetakP.left>=Shape2.Left) or (MetakP.Left+MetakP.Width >= Shape2.left) then begin // da li je metak desno od kocke
if MetakP.left<=Shape2.Left+Shape2.Width then begin // da li je metak levo od kocke
If MetakP.Top<=Shape2.Top+Shape2.Height then begin // da li je metak ispod kocke
if MetakP.Top>=Shape2.Top-Shape2.Height then begin
if Shape2.Visible=true then begin
Shape2.Visible:=false;//
MetakP.Left:=Image1.Left+16;
MetakP.Top:=Image1.Top;
MetakP.visible:=false;
Let:=0;
pob:=pob+1;
//Shape2.Enabled:=false;
end;
end;
end;
end;
end;
end;
对所有形状都是如此。它基本上是一个hitbox检查。现在,这是很多代码,有没有办法让它分别适用于所有形状?
第二关,如何从随机形状中发射子弹?我有:
procedure TForm2.Timer4Timer(Sender: TObject);
var r:integer;
var rr:string;
begin
MetakN.Visible:=true;
if Shape2.Visible=false then MetakN.Visible:=false;
r:=2+random(5);
rr:=IntToStr(r);
MetakN.Top:= Shape2.top+Shape2.Height;
MetakN.Left:= Shape2.Left+Shape2.Width div 2;
end;
r应该被用作&#34; Shape [r] .top&#34;等等,但它不起作用。
答案 0 :(得分:1)
程序由两部分组成。
您只使用1.
你需要获得一个数据结构来保存你的外星人 因为它只是一群外星人,所以列表可以正常工作。
在表单中添加一个变量,以便将外星人放入。
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, System.Generics.Collections;
TForm1 = class(TForm)
....
private
Aliens: TList<TShape>;
您可以在表单创建时初始化形状。 像这样的东西。
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
AngryAlien: TShape;
begin
Aliens:= TList<TShape>.Create;
for i := 0 to 100 do begin
AngryAlien:= TShape.Create(Form1);
AngryAlien.Parent:= Form1;
AngryAlien.Shape:= stCircle;
AngryAlien.Brush.Color:= clWhite;
AngryAlien.Width:= 30;
AngryAlien.Height:= 30;
AngryAlien.Visible:= false;
Aliens.Add(AngryAlien);
end;
end;
现在你有一个 100 101外星人。
你可以在计时器上移动外星人。
procedure TForm1.Timer1Timer(Sender: TObject);
var
i: integer;
Alien: TShape;
begin
//Move 4 aliens.
for i := 0 to 100 do begin
Alien:= Aliens[i];
Alien.Visible:= true;
Alien.Left:= Alien.Left + Random(30) - Random(20);
Alien.Top:= Alien.Top + Random(15) - Random(10);
end;
end;
现在你只需使用循环来控制每个外星人。
如果你想要一些游戏示例代码,可以开始使用这些代码:http://delphi.about.com/od/gameprogramming/
更具体地说:http://delphi.about.com/library/code/fdac_dodge_src.zip
当然上面的代码是copy-paste anti pattern的一个不好的例子,我会像这样重写它:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
shp_player: TShape;
shp_enemy: TShape;
btnStart: TButton;
timercircle: TTimer;
shparea: TShape;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Edit1: TEdit;
Label5: TLabel;
Shape1: TShape;
Lbl_player: TLabel;
lbl_circle: TLabel;
lbl_enemy: TLabel;
procedure FormCreate(Sender: TObject);
procedure btnStartClick(Sender: TObject);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure timercircleTimer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
//my own category of variables
TLevelArray = Array [1 .. 30] of Boolean;
var
circle: array [1 .. 30] of TShape;
Speedx: array [1 .. 30] of Integer;
Speedy: array [1 .. 30] of Integer;
Level: array [1..30] of TLevelArray;
SpeedxCalculation: Integer;
SpeedyCalculation: Integer;
LevelStore: Integer = 1;
HighScore: Boolean = False;
procedure ShowCircles(Level: TLevelArray);
var
Count: Integer;
begin
for Count:= 1 to 30 do begin
circle[Count].Visible:= Level[Count];
end;
end;
procedure InitLevels;
var
i,j: integer;
begin
for i := 1 to 30 do begin
FillChar(Level[i], SizeOf(Level[i]),#0);
end;
for i := 1 to 30 do begin
for j := 1 to i do begin
Level[i][j]:= true;
end;
end;
end;
procedure Updatecircles; //if the circle needs to be visible for that level
var
Count: Integer;
begin
for Count:= 1 to 30 do begin
ShowCircles(Level[LevelStore]);
end;
end;
Procedure SpeedCalculation;
begin
circle[LevelStore].Left:= 8; //all the circles come from the same position
circle[LevelStore].Top:= 8;
repeat
Randomize; //their speeds are random for more interesting gameplay
SpeedxCalculation:= Random(10) + 1;
Speedx[LevelStore]:= 5 - SpeedxCalculation;
Randomize;
SpeedyCalculation:= Random(10) + 1;
Speedy[LevelStore]:= 5 - SpeedyCalculation;
until (speedy[LevelStore]) and (Speedx[LevelStore]) <> 0;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Count: Integer;
i: integer;
MyCircle: TShape;
begin
InitLevels;
for i := 1 to 30 do begin
MyCircle:= TShape.Create(Self);
MyCircle.Parent:= Self;
MyCircle.Width:= 10;
MyCircle.Height:= 10;
MyCircle.Brush.Color:= clmaroon;
MyCircle.Visible:= false;
MyCircle[i]:= MyCircle;
end;
Randomize;
shp_enemy.Left:= Random(clientwidth) - shp_enemy.width;
shp_enemy.Top:= Random(clientheight) - shp_enemy.height;
lbl_enemy.Left:= shp_enemy.Left;
lbl_enemy.Top:= shp_enemy.Top - 20;
SpeedCalculation;
updatecircles;
end;
procedure TForm1.btnStartClick(Sender: TObject);
begin
TimerCircle.enabled:= True;
btnStart.Visible:= False;
Label2.Caption:= '0';
Edit1.enabled:= False;
lbl_player.Visible:= False;
lbl_enemy.Visible:= False;
lbl_circle.Visible:= False;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
shp_player.Left:= x - shp_player.Width - 10;
shp_player.Top:= y - shp_player.Height - 10; //the green block follows the mouse
lbl_player.Left:= x - lbl_player.Width - 10;
lbl_player.Top:= y - lbl_player.Height - 30;
end;
procedure TForm1.timercircleTimer(Sender: TObject);
var
overlay: Trect;
Count: Integer;
begin
for Count:= 1 to LevelStore do begin
// Moves the circles
circle[Count].Left:= circle[Count].Left + speedx[Count];
circle[Count].Top:= circle[Count].Top + speedy[Count];
//bounces the circles off of the boundaries of the form
if circle[Count].Left > clientwidth - circle[Count].width then speedx[Count]:= -speedx[Count]
else if circle[Count].Left < 0 then speedx[Count]:= -speedx[Count];
if circle[Count].Top > clientheight - circle[Count].Height then speedy[Count]:= -speedy[Count]
else if circle[Count].Top < 0 then speedy[Count]:= -speedy[Count];
//detects a collision between a circle and the players block
if Intersectrect(overlay, circle[Count].BoundsRect, shp_player.BoundsRect) then begin
c1.Left:= 8;
c1.Top:= 8;
btnstart.caption:= 'Restart';
btnstart.Visible:= True;
LevelStore:= 1;
SpeedCalculation;
UpdateCircles;
timercircle.enabled:= false;
if HighScore = True then //if a new high score has been achieved
begin
Edit1.Enabled:= True;
HighScore:= False;
end;
lbl_player.Visible:= True;
lbl_enemy.Visible:= True;
lbl_circle.Visible:= True;
lbl_enemy.Left:= shp_enemy.Left;
lbl_enemy.Top:= shp_enemy.Top - 20;
end;
//detects a collision between the player block and target block
if Intersectrect(overlay, shp_enemy.BoundsRect, shp_player.BoundsRect) then begin
Label2.Caption:= inttostr(strtoint(Label2.Caption) + 1);
if strtoint(Label2.Caption) > strtoint(Label4.Caption) then begin
highscore:= True;
Label4.Caption:= Label2.Caption;
end;
Randomize;
repeat
//the target block goes to a new position on the form
shp_enemy.Left:= Random(clientwidth) + 2 * (shp_enemy.width);
shp_enemy.Top:= Random(clientheight) - 2 * (shp_enemy.height);
until ((shp_enemy.Left) > (Form1.Left + shp_enemy.Width)) and
((shp_enemy.Left) < (Form1.Left + clientwidth - 2 * (shp_enemy.Width))) and
((shp_enemy.Top) > (Form1.Top + shp_enemy.Height)) and
((shp_enemy.Top) < (Form1.Top + clientwidth - 2 * (shp_player.Width)));
LevelStore:= LevelStore + 1;
if LevelStore = 30 then // there are only 30 circles
begin
MessageDlg('Congratulations! - You have completed the game!', mtinformation, [mbOK], 0);
timercircle.enabled:= false;
btnstart.Visible:= True;
LevelStore:= 1;
SpeedCalculation;
UpdateCircles;
end else begin
SpeedCalculation;
UpdateCircles;
end;
end;
end;
end;
end.//FIN - Code by Si (c)