Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Space Invaders in Delphi5 (https://www.delphipraxis.net/147401-space-invaders-delphi5.html)

N4r0 12. Feb 2010 14:28

Re: Space Invaders in Delphi5
 
Liste der Anhänge anzeigen (Anzahl: 1)
Tut mir leid, aber ich verstehe grad nicht worauf du hinaus willst, bzw. was das bringen soll ^^
hier nochmal mein komplettes Projekt, vielleicht erkennt man ja da genaueres

N4r0 13. Feb 2010 21:09

Re: Space Invaders in Delphi5
 
weiß keiner woran es liegt? ^^

Namenloser 13. Feb 2010 22:24

Re: Space Invaders in Delphi5
 
Du hast UKol nirgens initialisiert. Schriebe am Anfang der Funktion
Delphi-Quellcode:
UKol := TKollision.Create;
und am Ende
Delphi-Quellcode:
UKol.Free
Allerdings ist es nicht sonderlich sinnvoll, Code so in Klassen auszulagern wie du es hier getan hast. Eine Klasse soll dazu dienen, einen Programmteil so abzukapseln, dass er flexibel und leicht wiederverwendbar ist. Dazu ist es nötig, dass möglichst wenig Abhängigkeiten zu Elementen außerhalb der Klasse bestehen.

Deine Klasse ist aber immer noch fest mit den Elementen von Form1 verdrahtet, sodass der Wartungsaufwand eher steigt, als dass er abnimmt, denn bei jeder Änderung musst du jetzt gleich an zwei Stellen Anpassungen vornehmen.

OOP bedeutet nicht, dass man einfach nur seinen Code in mehrere Klassen packt, sondern dass man sein Programm in voneinander unabhängige Bausteine zerlegt. Wenn nämlich hinterher sich alle Klassen gegenseitig kennen, ist nichts gewonnen. Die Kunst besteht darin, zu erkennen, wo und wie man Bestandteile sinnvoll extrahieren könnte, und sein Programm entsprechend zu strukturieren.

N4r0 14. Feb 2010 00:33

Re: Space Invaders in Delphi5
 
hm ja, ich versteh worauf zu hinaus willst. An sich wollte ich das ganze jetzt nur in Klassen packen, weil es auch in der Aufgabenstellung erwähnt ist, dass wir Klassen benutzen sollen.
Aber du hast schon recht, einen wirklkichen sinnvollen Zweck hat das ganze auch nicht, wenn man alles nur "zerreißt".
Hast du vielleicht ne Idee, wie ich das mit dem Klassen besser umsetzen kann, bzw. was sinnvoll wär in Klassen zu packen?

Namenloser 14. Feb 2010 01:26

Re: Space Invaders in Delphi5
 
Zitat:

Zitat von N4r0
Hast du vielleicht ne Idee, wie ich das mit dem Klassen besser umsetzen kann, bzw. was sinnvoll wär in Klassen zu packen?

Das naheliegenste wäre erstmal, alles in eine Klasse zu packen, was auch im spiel hinterher ein Objekt ist - Sprich: Invader = Klasse, Bullet = Klasse, Raumschiff = Klasse usw... diese Klassen leitet man im elegantesten Fall von einer Basisklasse ab, die die abstrakten Methoden Move() und Draw() zur Verfügung stellt. Diese werden von den abgeleiteten Klassen jeweils überschrieben. Die Objekte speichert man alle in einer Objektliste, die man dann zu jedem Frame in einer Schleife durchläuft und für jedes Element diese Methoden aufruft.

Und schon hat man eine eigene kleine Spriteengine. Die Kollisionsabfrage könnte man so ähnlich lösen.

mkinzler 14. Feb 2010 09:23

Re: Space Invaders in Delphi5
 
Zitat:

Die Kollisionsabfrage könnte man so ähnlich lösen.
Da ja jedes Objekt weiss, welche Ausmasse/Besonderheiten es hat.

N4r0 14. Feb 2010 11:56

Re: Space Invaders in Delphi5
 
Ok, ich glaub ich hab verstanden wie du das meinst, klingt logisch.
Ich werds nachher mal versuchen zu realisieren.

N4r0 14. Feb 2010 15:53

Re: Space Invaders in Delphi5
 
Gut, ich habe jetzt mal was zusammengebastelt und mich würde interessieren, ob ich das soweit richtig verstanden habe:

Ich habe eine Basisklasse "TBasis" erstellt:

Delphi-Quellcode:
unit UnitBasis;

interface
uses extctrls;

  type TBasis = class

        protected

            Invader : array[1..21] of TImage;
            Spielfeld,
            Raumschiff,
            Schuss,
            Invader1,
            Invader2,
            Invader3,
            Invader4,
            Invader6,
            Invader7,
            Invader5,
            Invader8,
            Invader9,
            Invader10,
            Invader11,
            Invader12,
            Invader13,
            Invader14,
            Invader15,
            Invader16,
            Invader17,
            Invader18,
            Invader19,
            Invader20,
            Invader21 : TImage;

           procedure MoveSpaceShip ; virtual; abstract;
           function MoveInvader(level: integer): boolean; virtual; abstract;
           procedure ShotCreate ; virtual; abstract;
           procedure MoveShot ; virtual; abstract;
           function Collision(Schuss : TImage ; i : integer) : boolean; virtual; abstract;


   end;

implementation

end.
Vor dieser Klasse habe ich nun drei weitere Klassen abgeleitet:


"TSpaceShip":

Delphi-Quellcode:
unit UnitSpaceShip;

interface
uses UnitBasis, Dialogs, Windows;

  type TSpaceShip = class (TBasis)

        protected

           procedure MoveSpaceShip ;

  end;


implementation


   procedure TSpaceShip.MoveSpaceShip ;

   begin

      if getasynckeystate(VK_RIGHT)<>0 then
             Raumschiff.left := Raumschiff.left + 8
        else if getasynckeystate(VK_LEFT) <> 0 then
             Raumschiff.left := Raumschiff.left - 8;

        if Raumschiff.left < Spielfeld.left then
           Raumschiff.left := Spielfeld.left + 2
        else if Raumschiff.left + Raumschiff.width > Spielfeld.left + Spielfeld.width then
           Raumschiff.left := Spielfeld.left + Spielfeld.width - Raumschiff.width - 2;

   end;

end.

"TInvader":

Delphi-Quellcode:
unit UnitInvader;

interface
uses UnitBasis, Dialogs;

  type TInvader = class (TBasis)

        protected


           Bewegungsrichtung : integer;

           function MoveInvader( level: integer): boolean;

  end;

implementation


  function TInvader.MoveInvader(level: integer): boolean;

     var i,x,y : integer;

  begin  


      for i := 1 to 21 do
      begin
        Invader[i].left := Invader[i].left + (Bewegungsrichtung * 10);
      end;

      if Invader7.left + Invader7.width > Spielfeld.left + Spielfeld.width then
      begin
        i := 1;
        for x := 1 to 3 do
          for y := 1 to 7 do
            begin
              Invader[i].top := Invader[i].top + 25;
              Invader[i].left := Spielfeld.left + Spielfeld.width - ((Invader[i].width + 7) * (8 - y)) - 2;
              i := i + 1;
            end;
        Bewegungsrichtung := -1
      end else
      if Invader1.left < Spielfeld.left then
      begin
        i := 1;
        for x := 1 to 3 do
          for y := 1 to 7 do
            begin
              Invader[i].top := Invader[i].top + 25;
              Invader[i].left := Spielfeld.left + ((Invader[i].width + 7) * (y - 1)) + 9;
              i := i + 1;
            end;
        Bewegungsrichtung := 1
      end;

      for i := 21 downto 1 do
        if (Invader[i].visible = true) and (Invader[i].top + Invader[i].height >= Raumschiff.top - 10) then
        begin
          showmessage('Game Over');
          break;
        end;

  end;

end.

und "TBullet":

Delphi-Quellcode:
unit UnitBullet;

interface
uses UnitBasis, extctrls, MMSystem, Unit1;

   type TBullet = class (TBasis)

       protected

           Schuss1 : array of TImage;

           procedure ShotCreate;
           procedure MoveShot;
           function Collision(Schuss : TImage ; i : integer) : boolean;

   end;

implementation


  procedure TBullet.ShotCreate ;

    var Schusstemp : TImage;

  begin

       SndPlaySound( '.\pew.wav', SND_ASYNC );

       Schusstemp := TImage.Create(FormStarship);

       Schusstemp.Parent := FormStarship; // this is important
       Schusstemp.Left   := Raumschiff.left + (RaumSchiff.width div 2);    // X coordinate
       Schusstemp.Top    := RaumSchiff.top - 20;    // Y coordinate

       Schusstemp.Picture := Schuss.Picture;

       SetLength(Schuss1, High(Schuss1) + 2);

       Schuss1[High(Schuss1)] := Schusstemp;

  end;


  function TBullet.Collision(Schuss : TImage ; i : integer) : boolean;

   var xposition, yposition: integer;

   begin

       Collision := false;

       xposition := Schuss.left;
       yposition := Schuss.top;

       if (xposition >= Invader[i].left) and (xposition <= (Invader[i].left + Invader[i].width)) then
       begin
         if (yposition <= (Invader[i].top + Invader[i].height)) and (yposition >= Invader[i].Top) then
           Collision := true
         else
           Collision := false
       end
       else
         Collision := false;

   end;



  procedure TBullet.MoveShot;

    var j,i,x : integer;
         collide : boolean;

  begin

    for j := High(Schuss1) downto 0 do
    begin

       collide := false;
       for i := 1 to 21 do
       begin
         if (Collision(Schuss1[j],i) = true) and (Invader[i].Visible = true) then
         begin

            collide := true;
            Invader[i].visible := false;
            SndPlaySound( '.\boom1.wav', SND_ASYNC );

            Schuss1[j].Free;
            for x:=j to high(Schuss1)-1 do
               Schuss1[x] := Schuss1[x+1];
            SetLength(Schuss1,length(Schuss1)-1);

            break;
         end
       end;

       if collide = false then
         if Schuss1[j].top > Spielfeld.top + 5 then
            Schuss1[j].top := Schuss1[j].top - 10
         else
         begin

            Schuss1[j].Free;
            for x:=j to high(Schuss1)-1 do
               Schuss1[x] := Schuss1[x+1];
            SetLength(Schuss1,length(Schuss1)-1);

         end;

    end;

  end;

end.

Sieht das soweit verständlich und logisch aus oder was sollte ich ändern?

Wenn ich jetzt die Procedure "TSpaceShip.MoveSpaceShip" in meiner Hauptprogramm aufrufen möchte sagt mir Delphi: "[Fehler] Unit1.pas(247): Undefinierter Bezeichner: 'MoveSpaceShip'".
Ich habe aber im Hauptprogramm die "UnitSpaceShip" unter "uses" bei "implemantation" bekannt gemacht und die Procedure wiefolgt aufgerufen:

Delphi-Quellcode:
procedure TFormStarship.SchiffTimerTimer(Sender: TObject);

  var x : TSpaceShip;

begin
       
  x.MoveSpaceShip;

end;
Woran kann es liegen, dass ich trotzdem diese Fehlermeldung bekomme?


Danke schonmal, hier wird einem wenigstens verständlich geholfen :P

Namenloser 14. Feb 2010 17:19

Re: Space Invaders in Delphi5
 
Ich meinte eher sowas:
Delphi-Quellcode:
type
  TSprite = class
  protected
    FImage: TImage;
    FParent: TForm;
    procedure InitImage; virtual; abstract;
  public
    constructor Create(Parent: TForm; Position: TPoint);
    destructor Destroy; override;
    procedure Move; virtual; abstract;
    function CollidesWith(AObject: TSprite): boolean;
  end;

  TInvader = class(TSprite)
  protected
    procedure InitImage; override;
  public
    procedure Move; override;
  end;

  TBullet = class(TSprite)
  protected
    procedure InitImage; override;
  public
    procedure Move; override;
  end;

implementation

constructor TSprite.Create(Parent: TForm; Position: TPoint);
begin
  inherited Create;
  FParent := Parent;
  FImage := TImage.Create(nil);
  FImage.Parent := Parent;
  InitImage;
  FImage.Left := Position.X;
  FImage.Top := Position.Y;
end;

destructor TSprite.Destroy;
begin
  FImage.Free;
  inherited;
end;

function TSprite.CollidesWith(AObject: TSprite): boolean;
begin
  Result := (FImage.Left+FImage.Width > AObject.Left) and
            (FImage.Top +FImage.Height > AObject.Top ) and
            ...;
end;

procedure TInvader.InitImage;
begin
  FImage.LoadFromFile('invader.bmp'); // z.B...
end;

procedure TInvader.Move;
begin
  FImage.Left := FImage.Left+1; // z.B...
end;


procedure TBullet.InitImage;
begin
  FImage.LoadFromFile('bullet.bmp'); // z.B...
end;

procedure TInvader.Move;
begin
  FImage.Top := FImage.Top-10; // z.B...
end;
Delphi-Quellcode:
TForm1 = class(TForm)
...
private
  FSprites: TObjectList;
...
end;

implementation

procedure TForm1.FormCreate(Sender: TObject);
var
  i,j: integer;
begin
  FSprites := TObjectList.Create(True);
  for i := 0 to 8-1 do
    for j:= 0 to 3-1 do
      FSprites.Add(TInvader.Create(self, Point(i*30, j*20)));
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  i,j: integer;
begin
  for i := 0 to FSprites.Count-1 do
    TSprite(FSprites[i]).Move;
  ...
end;

N4r0 14. Feb 2010 20:34

Re: Space Invaders in Delphi5
 
Delphi-Quellcode:
function CollidesWith(AObject: TBasis): boolean;

[...]

function TSprite.CollidesWith(AObject: TBasis): boolean;
begin
  Result := (FImage.Left+FImage.Width > AObject.Left) and
            (FImage.Top +FImage.Height > AObject.Top ) and
            ...;
end;
Das verstehe ich nicht ganz. Wo kommt das TBasis her? Die Klasse, welche du erstellt hast heißt doch TSprite, oder?


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:21 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz