Für ein einfaches 2D-Spiel muss man nicht unbedingt gleich eine Spiele-Engine auspacken. Für den Anfang reicht auch Canvas. Wenn es flackert, baut man einfach einen Offscreen-Buffer ein.
Im Grunde hat himitsu das Konzept schon erklärt: Statt auf grafische Komponenten zu setzen, die du zur Designzeit in das Formular ziehst, übernimm das Zeichnen selbst.
Objektorientiert kann man das prima umsetzen. Hier ein grobes Gerüst:
Delphi-Quellcode:
type
TSprite = class
FPosition: TPoint;
FBitmap: TBitmap;
procedure Paint(Canvas: TCanvas; Offset: TPoint);
end;
var
Sprites: array of TSprite;
Camera: TPoint;
implementation
procedure TSprite.Paint(Canvas: TCanvas; Offset: TPoint);
var
ScreenPosition: TPoint;
begin
ScreenPosition.X := FPosition.X - Offset.X;
ScreenPosition.Y := FPosition.Y - Offset.Y;
Canvas.Draw(FBitmap, ScreenPosition.X, ScreenPosition.Y);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetLength(Sprites, 2);
with Sprites[0] do
begin
FPosition := Point(0, 0);
FBitmap := TBitmap.Create;
FBitmap.LoadFromFile('player.bmp');
end;
with Sprites[1] do
begin
FPosition := Point(20, 0);
FBitmap := TBitmap.Create;
FBitmap.LoadFromFile('enemy.bmp');
end;
end;
procedure TForm1.Timer1Time(Sender: TObject);
var
i: integer;
begin
for i := low(Sprites) to high(Sprites) do
Sprites[i].Paint(Canvas, Camera);
end;
Wenn die Kamera nach rechts scrollen soll, dann erhöhst du einfach Camera.X.
Das tolle an obigem Ansatz ist, dass man dank Polymorphie auch die komplette Spiellogik selbst wunderbar in die Sprites stecken kann. Das geht z.B. indem man eine abstrakte Basis-Klasse einführt und dann für verschiedene Objekttypen konkrete Klassen ableitet:
Delphi-Quellcode:
type
// ist jetzt abstract
TSprite = class
procedure Paint(Canvas: TCanvas; Offset: TPoint); virtual; abstract;
procedure Move; virtual; abstract;
end;
TPlayer = class(TSprite)
{ hier Variablen für Position, Bitmap, usw... }
procedure Paint(Canvas: TCanvas; Offset: TPoint); override;
procedure Move; override;
end;
TEnemy = class(TSprite)
{ hier Variablen für Position, Bitmap, usw... }
procedure Paint(Canvas: TCanvas; Offset: TPoint); override;
procedure Move; override;
end;
implementation
procedure TPlayer.Paint(Canvas: TCanvas; Offset: TPoint);
begin
{ hier Spieler zeichnen }
end;
procedure TPlayer.Move;
begin
{ hier Spieler ein Stück bewegen }
end;
procedure TEnemy.Paint(Canvas: TCanvas; Offset: TPoint);
begin
{ hier Gegner zeichnen }
end;
procedure TEnemy.Move;
begin
{ hier Gegner ein Stück bewegen (KI) }
end;
Einen Leveleditor musst du dir dann allerdings selbst programmieren, wenn du deine Levels grafisch designen willst... ist aber machbar