Delphi-PRAXiS
Seite 1 von 3  1 23      

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 7. Feb 2010 18:08


Space Invaders in Delphi5
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo

wir haben die Aufgabe im Informatikunterricht ein Projekt unserer Wahl zu programmieren.
Ein Freund und ich haben uns für einen kleinen Space Invaders - Klon entschieden. (Die Invader sollen einfach nur nach unten kommen und dabei abgeschossen werden, also nicht zurückschießen).

Wir sind auch schon recht gut vorangekommen, hängen nun aber am Abschießen der Invader. Die Kollisionsabfrage passt soweit eigentlich, jedoch haben wir ein Problem mit dem "entfernen" des Schusses und der Invader. Um den Schuss löschen zu können, welcher sich bei uns in einem dynamischen Array befindet, dachten wir den gerade betrachteten Schuss zu löschen indem wir alle folgenden Schüsse "eins weiter nach vorn verschieben" (ich hoffe man weiß was gemeint ist ^^). Jedenfalls bringt Delphi uns eine Fehlermeldung.

Ich hänge das Projekt einfach mal als Anhang in einer .txt Datei an. (es ist vom Aufbau noch nicht optimal und wird, wenn alles funktioniert noch optimiert)

Danke schon einmal
~N4r0

Namenloser 7. Feb 2010 19:03

Re: Space Invaders in Delphi5
 
Hallo N4r0,

Willkommen in der DP :dp:

Euer Ansatz ist schon richtig. Du hast leider nicht verraten, welche Fehlermeldung angezeigt wird. Ich vermute allerdings mal, sie kommt daher, dass durch die vorwärtslaufende Schleife auf Elemente zugegriffen werden, die nicht mehr vorhanden sind. Versucht mal, die Schleife in Zeile 236 andersherum laufen zu lassen.

Sprich:
Delphi-Quellcode:
for j := High(Schuss1) downto 0 do
...
Eine Sache allerdings noch: Ihr gebt die erzeugten Schuss-Images nirgens frei, was zu einem Memory-Leak führt! Ruft Schuss1[j].Free auf, bevor ihr es aus dem Array entfernt.

N4r0 7. Feb 2010 19:22

Re: Space Invaders in Delphi5
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hey,

danke für deine schnelle Antwort :)

ich hab die Schleife mal abgeändert und vor der Schleife, die den Schuss aus dem Array löschen soll Schuss1[j].Free geschreiben.

ich hab nochmal die Fehlermeldung in den Anhang gepackt. (also an sich ne Zugriffsverletzung)

himitsu 7. Feb 2010 19:32

Re: Space Invaders in Delphi5
 
Die Richtung stimmte schon.
Delphi-Quellcode:
Schuss1[j].Free;
for x:=j to high(Schuss1)-1 do
  Schuss1[x] := Schuss1[x+1];
SetLength(Schuss1,length(Schuss1)-1);
Außer daß du an der falschen Stelle angefangen hast.

j-1 ist ja der Schuß vor dem zu Löschenden ... du hattest also den Falschen entfernt
und wenn j der 1. Schuß ist (j=0), dann hast du den Grund für die Berreichsüberschreitung.

Namenloser 7. Feb 2010 19:40

Re: Space Invaders in Delphi5
 
Zitat:

Zitat von himitsu
Die Richtung stimmte schon.

Ich sprach von der äußeren Schleife (Z.236) :wink:

N4r0 7. Feb 2010 19:48

Re: Space Invaders in Delphi5
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von himitsu
Die Richtung stimmte schon.
Delphi-Quellcode:
Schuss1[j].Free;
for x:=j to high(Schuss1)-1 do
  Schuss1[x] := Schuss1[x+1];
SetLength(Schuss1,length(Schuss1)-1);
Außer daß du an der falschen Stelle angefangen hast.

j-1 ist ja der Schuß vor dem zu Löschenden ... du hattest also den Falschen entfernt
und wenn j der 1. Schuß ist (j=0), dann hast du den Grund für die Berreichsüberschreitung.

Der Fehler trifft in diesem Fall ebenfalls auf.

so siehts jetzt aus:

Delphi-Quellcode:
procedure TForm1.SchussTimerTimer(Sender: TObject);
var j,i,x : integer;
    collide : boolean;
begin

     collide := false;

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

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

            collide := true;
            Invader[i].visible := false;

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

         end
       end;

       if collide = false then
          Schuss1[j].top := Schuss1[j].top - 10;

       end;

end;

Namenloser 7. Feb 2010 21:24

Re: Space Invaders in Delphi5
 
Habe das Projekt mal im Debugger durchgesteppt: Das Problem ist, dass die Schleife, in der die Kollision einer Kugel mit einem Invader geprüft wird, beim Auftreten einer Kollision nicht abgebrochen wird. D.h. wenn die Kugel schon entfernt wurde, wird sie trotzdem noch auf eine Kollision mit den übrigen Invadern geprüft, was zu einer Zugriffsverletzung führt.

Beheben kannst du das, indem du nach dem Entfernen der Kugel aus dem Array die innere Schleife mit dem Befehl break; abbrichst. Es wäre übrigens sinnvoller, wenn du die Variable collide in der äußersten Schleife auf False setzen würdest, statt nur am Anfang der Funktion.

N4r0 7. Feb 2010 22:04

Re: Space Invaders in Delphi5
 
Super, danke dir für die schnelle und kompetente Hilfe :D

N4r0 11. Feb 2010 21:18

Re: Space Invaders in Delphi5
 
Hallo ihr,

Ich hätte da ein neues Problem.
Undzwar bin ich gerade dabei meine programmierten functions in in neue Klassen, also in andere Units zu packen, um sie aus dem Hauptprogramm zubekommen.
Nun versuche ich das die ganze Zeit mit meiner funktion kollision:

Delphi-Quellcode:

function kollision(Schuss : TImage ; i : integer) : boolean;

    var xposition, yposition: integer;

   begin

     kollision := 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
         kollision := true
       else
         kollision := false
     end
     else
       kollision := false;

end;
Ich scheine die neue Klasse auch richtig in die Unit1 implementiert zu haben, denn mein Programm startet ohne Probleme.
Jedoch wenn ich versuche einen Schuss auszusenden bekommen ich wieder eine Zugriffsverletzungs-Fehlermeldung und Delphi markiert mir diese Zeile:

Delphi-Quellcode:
if (xposition >= Invader[i].left) and (xposition <= (Invader[i].left + Invader[i].width)) then
Ich nehme also an, dass es damit zu tun hat, dass meine zweite Unit nicht auf die TImages zugreifen kann.
Wie ist es möglich dieses Problem zu beheben?

Blup 12. Feb 2010 07:11

Re: Space Invaders in Delphi5
 
Zitat:

Zitat von N4r0
Ich nehme also an, dass es damit zu tun hat, dass meine zweite Unit nicht auf die TImages zugreifen kann.

In dieser Zeile wird nur auf Invader[i] zugegriffen.
diese Sachen prüfen:
- Invader <> nil (bzw. bei einem Array z.B. Length > 0)
- (i >= 0) and (i < Length(Invader))
- Invader[i] <> nil
- ist Invader[i] wirklich ein gültiges Objekt und nicht bereits an anderer Stelle freigegeben


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:44 Uhr.
Seite 1 von 3  1 23      

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