AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

Ein Thema von Premaider · begonnen am 24. Okt 2012 · letzter Beitrag vom 25. Okt 2012
Antwort Antwort
Premaider

Registriert seit: 31. Mär 2012
160 Beiträge
 
#1

Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 24. Okt 2012, 22:09
Hey Leute,
vielleicht kennt einer von euch das Spiel Aspirin. Man muss den Spieler durch die sich bewegenden Gegner zum Ziel bringen. Ich habe noch Items hinzugefügt und man verliert erst wenn die 5 Herzen (5,4,3,2 oder 1 je nach Schwierigkeitsgrad). Mein Probleme sind:
- Manchmal erscheind oben-links in der Form einfach ein weißer Shape (vermutl. Item)
- Ab einer bestimmten Anzahl an Gegnern (TGegner=Abgeleitet von TShape) bekomme ich eine Zugriffsverletzung bei Verlieren (wenn keine Herzen mehr da wären)
- Manchmal passiert nichts wenn man ein Item berührt

Vielleicht ein paar mal spielen. Dann werdet ihr damit sicher "bekanntschaft machen"
Bei mir wird die Hauptarbeit von Timer1 übernommen.
Das gesammte Spiel befindet sich hier: http://www.mediafire.com/?edd20mq7c5f2if2 (Auch mit Grafiken usw., daher kein Anhang mehr möglich)
Den Quellcode von Timer1 findet ihr hier:

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
l,k,m,n,o,AL1,AL2,Zufall: Integer;
begin
//Spieler bewegegen
If Spielerbewegung=True then
  begin
    If ((KeyPressed(VK_Up)) or (KeyPressed($57)) and (Spieler.Top >= Spielflaeche.Top)) Then Spieler.top := Spieler.top - Spieler.Speed;
    If ((KeyPressed(VK_Down)) or (KeyPressed($53)) and (Spieler.Top <= Spielflaeche.height + Spielflaeche.top - Spieler.Height)) Then Spieler.top := Spieler.top + Spieler.Speed;
    If ((KeyPressed(VK_Left)) or (KeyPressed($41)) and (Spieler.Left >= Spielflaeche.left)) Then Spieler.Left := Spieler.Left - Spieler.Speed;
    If ((KeyPressed(VK_Right)) or (KeyPressed($44)) and (Spieler.Left <= Spielflaeche.width + Spielflaeche.left - Spieler.width)) Then Spieler.Left := Spieler.Left + Spieler.Speed;
  end;
//Kollision Spieler und Ziel
if IsCollision(Spieler.BoundsRect, Ziel.BoundsRect) then
  begin
  Punktzahl:=Punktzahl+1;
  PunkteAnzeige.caption:='Punkte: '+IntToStr(Punktzahl);
    If Sounds='EnabledThen
      begin
        SoundPlayer.FileName:=Pfad+'\Datein\Ziel.wav';
        SoundPlayer.Open;
        SoundPlayer.play;
      end;
    ItemCount:=ItemCount+1;
    Ziel.Top:=random(Spielflaeche.Height - Ziel.Height) + Spielflaeche.top;
    Ziel.Left:=random(Spielflaeche.Width - Ziel.width) + Spielflaeche.left;
    // Gegner hinzufügen
      begin
       setLength(gegner,length(Gegner)+1);
       AL1 := length(Gegner)-1;
       Gegner[AL1]:= TGegner.Create(Self);
         With Gegner[AL1] do
          begin
            speed:=3;
            Parent := self;
            Cooldown := 1000;
            BringToFront;
            If RandomAusgabe(1)=1 Then
               begin
                  Width:=5;
                  Height:=30;
                  top:= random( Spielflaeche.Height - height ) + Spielflaeche.top;
                  Left := random( Spielflaeche.Width - Width ) + Spielflaeche.left;
                end;
            If RandomAusgabe(1)=0 Then
               begin
                  Width:=30;
                  Height:=5;
                  top:= random( Spielflaeche.Height - height ) + Spielflaeche.top;
                  Left := random( Spielflaeche.Width - Width ) + Spielflaeche.left;
                end;
          end;
        end;
    //Item hinzufügen
      begin
        If ItemCount=5 Then
          begin
            ItemCount:=0;
            Zufall:=RandomAusgabe(3);
            setLength(Item,length(Item)+1);
            AL2 := length(Item)-1;
            Item[AL2]:= TItem.Create(Self);
            With Item[AL2] do
              begin
                Picture.LoadFromFile(Pfad+'\Datein\Item.jpg');
                Parent:=Self;
                Height:=16;
                Width:=16;
                Stretch:=True;
                Top:=random(Spielflaeche.Height - Ziel.Height) + Spielflaeche.top;
                Left:=random(Spielflaeche.Width - Ziel.width) + Spielflaeche.left;
                Brush.Color:=clblack;
                BringToFront;
                Enabled:=True;
                If ((Zufall=1) or (Zufall=2)) then
                  begin
                    Typ:=True;
                  end;
                If Zufall=3 then
                  begin
                    Typ:=False;
                  end;
              end;
        end;
    end;
  end;
    //Gegner bewegen
    If length(gegner)>=1 then
      begin
        For m:= 0 to high(gegner) do
          begin
            If Gegner[m].width > Gegner[m].Height Then
              begin
                //Waagrecht
                Gegner[m].left:=Gegner[m].left + Gegner[m].Speed;
              end;
            If Gegner[m].width < Gegner[m].Height Then
              begin
                //Senkrecht
                Gegner[m].Top:=Gegner[m].top + Gegner[m].Speed;
              end;
          end;
      end;

//Gegner Cooldown
For o:= low(Gegner) to high(Gegner) do
  begin
    If Gegner[o].cooldown>=1 Then Gegner[o].cooldown:=Gegner[o].cooldown-50;
  end;

//Kollision Gegner und Wand
For l:= low(gegner) to high(gegner) do
  begin
    if Gegner[l].Left <= Spielflaeche.Left then Gegner[l].speed:=Gegner[l].speed*-1;
    if Gegner[l].Left >= Spielflaeche.Width + Spielflaeche.Left - Gegner[l].Width then Gegner[l].speed:=Gegner[l].speed*-1;
    if Gegner[l].top <= Spielflaeche.Top - Gegner[l].Width then Gegner[l].speed:=Gegner[l].speed*-1;
    if Gegner[l].top >= Spielflaeche.height + Spielflaeche.top - Gegner[l].height then Gegner[l].speed:=Gegner[l].speed*-1;
  end;

//Kollision Spieler und Gegner
For k:= low(gegner) to high(gegner) do
  begin
    if ((IsCollision(Gegner[k].BoundsRect, Spieler.BoundsRect)) and (Gegner[k].Cooldown<=0))Then
          begin
            If Spieler.Verletzbar Then Dec(Herzen);
            If ((Herzen=4) and (Spieler.Verletzbar)) Then
              begin
                Spieler.Verletzbar:=False;
                Abwarten2.Enabled:=True;
                Herz5.picture.loadfromfile(Pfad+'\Datein\Herz_Leer.jpg');
              end
            Else If ((Herzen=3) and (Spieler.Verletzbar)) Then
              begin
                Spieler.Verletzbar:=False;
                Abwarten2.Enabled:=True;
                Herz4.picture.loadfromfile(Pfad+'\Datein\Herz_Leer.jpg');
              end
            Else If ((Herzen=2) and (Spieler.Verletzbar)) Then
              begin
                Spieler.Verletzbar:=False;
                Abwarten2.Enabled:=True;
                Herz3.picture.loadfromfile(Pfad+'\Datein\Herz_Leer.jpg');
              end
            Else If ((Herzen=1) and (Spieler.verletzbar)) Then
              begin
                Spieler.Verletzbar:=False;
                Abwarten2.Enabled:=True;
                Herz2.picture.loadfromfile(Pfad+'\Datein\Herz_Leer.jpg');
              end;
          end
        Else If Herzen<=0 then
          begin
            Verloren;
            Herz1.Picture.LoadFromFile(Pfad+'\Datein\Herz_leer.jpg');
          end;
  end;

//Kollision Spieler und Item
For n := low(item) to high(item) do
  begin
    If ((IsCollision(Spieler.BoundsRect,Item[n].BoundsRect)) and (Item[n].Enabled=True)) Then
      begin
        Spieler.Upgrade(n,Item[n].Typ);
        Item[n].Enabled:=False;
      end;
  end;
end;
Könnt ihr mir vielleicht beantworten warum diese Bugs entstehen ? Ich habe nämlich keine Ahnung :S
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#2

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 24. Okt 2012, 22:35
Wie wäre es, wenn du uns erstmal sagst was genau los ist?

- Fehlermeldungen (ja, Strg+C funktioniert an sehr vielen Stellen, vorallem in Fehlerdialogen)
- in welchen Zeilen treten die Fehler auf?

- Und hast du dir schonmal angesehn wofür ein Debugger gut ist?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Premaider

Registriert seit: 31. Mär 2012
160 Beiträge
 
#3

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 24. Okt 2012, 22:44
Wie wäre es, wenn du uns erstmal sagst was genau los ist?

- Fehlermeldungen (ja, Strg+C funktioniert an sehr vielen Stellen, vorallem in Fehlerdialogen)
- in welchen Zeilen treten die Fehler auf?

- Und hast du dir schonmal angesehn wofür ein Debugger gut ist?
Also ich hab jetzt ca. 1 Jahr Informatik in der Schule aber von Debugger hab ich noch nie was gehört. Sorry :S
(Edit: hab mal nachgeschaut und jetzt weiß ich was du meinst xD. Aber was soll ich denn machen was sollen mir Haltepunkte bringen. Ich weiß ja nicht warum. Das habe ich auch schon mit Haltepunkten usw. nachgeschaut)

Und eine richtige Zeile gibts ja nur für die Zugriffsverletzung.
Die wäre dann bei if ((IsCollision(Gegner[k].BoundsRect, Spieler.BoundsRect)) and (Gegner[k].Cooldown<=0))Then bei //Kollision Gegner und Spieler

Geändert von Premaider (24. Okt 2012 um 23:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von RWarnecke
RWarnecke

Registriert seit: 31. Dez 2004
Ort: Stuttgart
4.408 Beiträge
 
Delphi XE8 Enterprise
 
#4

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 25. Okt 2012, 07:50
Ich würde das Spiel über die Delphi IDE starten und spielen. Sobald eine Zugriffsverletzung auftritt, bekommst Du diese Meldung angezeigt und hast unten rechts einen Button Break. Wenn Du diesen dann anklickst, springt die Delphi IDE an die ungefähre Stelle wo die Zugriffsverletzung auftritt. Wenn Du diese Stelle hast, würde ich ein paar Zeilen davor den Haltepunkt setzen. Danach das Spiel wieder neu starten und spielen. Jetzt solltest Du die gleichen Aktionen ausführen wie beim ersten Mal und wenn Du an den Haltepunkt kommst mit Trace Into (F7) oder mit Step Over (F8) die Zeilen Deiner Funktion durchgehen.
Rolf Warnecke
App4Mission
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 25. Okt 2012, 08:41
Der Fehler tritt vermutlich beim Zugriff auf Gegner[k] auf.
Eigentliche Ursache ist dann die Stelle, an der Gegner freigegeben werden.
Dazu fehlt aber der Quellcode.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#6

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 25. Okt 2012, 09:27
Es kann auch nicht schaden, zu erwähnen welche Delphiversion man nutzt. Du kannst dein D7 ja ganz einfach mal im Forenprofil angeben.

Projekt > Optionen > Compiler > Laufzeitfehler > alle Haken dort reinmachen
Sicherheitshalber (wärend du noch am Programm arbeitest) auch bei Projekt > Optionen > Compiler > Coderzeugung die optimierung aus und die Stackframes an. (dann hat es der Debugger einfacher)

Nein, Debugger ist nicht nur "Haltepunkte".

Da kann man nachsehn warum es knallt, indem man sich den aktuellen Wert von Variablen ansieht und so erkennen könnte, was nicht stimmt.
Die sind dennoch praktisch, vorallem weil man ab da auch leicht mal den Code Zeile für Zeile, aka Befehl für Befehl einzeln/schrittweise ausführen und nachsehn kann, was genau passiert. :roll


Und ich fragte nicht umsonst nach eine "genaueren" Fehlerbeschreibung, denn da kann man leichter erkennen, ob sich darin ein Hinweis verbirgt.

z.B. "Zugriffsverletzung bei Adresse $xxxxxxxx auf Adresse $000000xx" = dort wird vermutlich auf "nil" (z.B. nicht existierendes Array oder Objekt) zugegriffen.
Bei "Zugriffsverletzung bei Adresse $000000xx ..." wurde wohl eine Methode in einem nichtexistierenden Prozedurzeiger angesprungen.
Und bei "Zugriffsverletzung bei Adresse $xxxxxxxx auf Adresse $xxxxxxxx" stimmt irgendwas Anderes nicht, aber 66% der Fälle hat man dennoch sofort erkannt.
Wie gesagt ... Strg+C in der Form drücken und dann hier im Editor Strg+V.

(X = irgendein Wert, meistens keine 0 ... und 0 = eine 0)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (25. Okt 2012 um 09:30 Uhr)
  Mit Zitat antworten Zitat
Premaider

Registriert seit: 31. Mär 2012
160 Beiträge
 
#7

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 25. Okt 2012, 12:31
Die genaue Zugriffsverletzung lautet:
"Im Proekt Project1.exe ist eine Exeption der Klasse EAccessViolation aufgetreten. Meldung'Zugriffsverletzung bei Adresse 0046B726 in Modul 'Project1.exe'. Lesen von Adresse 00000008. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start vortsetzen"
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.537 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 25. Okt 2012, 12:56
Dann lies Dir #5 und #6 noch einmal durch. Anscheinend greifst Du ungeprüft auf ein nil-Objekt zu, d.h. es wurde noch gar nicht erzeugt oder bereits freigegeben.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.114 Beiträge
 
Delphi 12 Athens
 
#9

AW: Bugs und Zugriffsverletzungen in meinem Spiel (Aspirin)

  Alt 25. Okt 2012, 12:59
So, daß heißt also es wird auf etwas zugrgriffen, was es nicht gibt ... und das kann man sehr leicht nachprüfen.

Zitat:
Und eine richtige Zeile gibts ja nur für die Zugriffsverletzung.
Die wäre dann bei if ((IsCollision(Gegner[k].BoundsRect, Spieler.BoundsRect)) and (Gegner[k].Cooldown<=0))Then bei //Kollision Gegner und Spieler
Ausgehn würde man erstmal davon, daß der Fehler auch in dieser Zeile liegt (das stimmt nicht immer, da sich der Debugger auch manchmal täucht/verläuft).

Also entweder liegt es am IF oder an dem, was in IsCollision liegt.
(falls es an is colision liegt, dann kann man den Inhalt )


Da es ein nicht "direkt" reproduzierbarer Fehler ist, hilft ein Haltepunkt nicht viel, da man nun jede Ausführung dieser Zeile prüfen müßte, bis es knallt (das kann dauern).

Man läßt es nun also erstmal knallen und schaut sich nach dem Knall im Debugger die Variablen an.
Dort suchst du nun nach einem nil.

Leider sind sind nach einer exception "manchmal" keine Variableninhalte lesbar


Also hilft man sich ganz einfach mit einem Schutzblock, welcher um den code drumrum kommt, wo man den Fehler vermutet.
In dem Except-Block kann man sich entweder via ShowMessage und Co. Variableninhalte anzeigen lassen
oder man kopiert den Code nochmals dort rein (nur sinnvoll wenn mit einem reproduzierbaren Ergebnis zu rechnen ist).

bei dir also
Delphi-Quellcode:
for ... do
  try
    if ... then
    begin
      ...
    end;
  except
    if ... then // hier der Haltepunkt
    begin
      ...
    end;
  end;
Wenn es knallt, dann landet man im Except und kann den Code nochmals ausführen.
Dieses mal Schritt für Schritt und dabei guckt man sich "vorher" die Variableninhalte an.

Bei dir ist es also speziell der Inhalt von Gegner, an der Position k,
bzw. der Inhalt von IsColition.
Daß "Spieler" verschwindet, schließe ich einfach mal aus, aber prüfen kann man es denoch. (ist ja kein Aufwand)



Und zusätzlich nochmals:
- wie vorher schonmal beschrieben, soltest du gewisse Einstellungen in den Projektoptionen vornehmen, womit bestimmte Prüfungen von Delphi automatisch eingebaut werden
- manchmal kann es nicht schaden, wenn man geziehlt FreeAndNil verwendet, statt nur .Free (aber bei der genannten Fehlermeldung, ist sowas erstmal nicht nötig, da es sowieso schon nil ist)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (25. Okt 2012 um 13:03 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:54 Uhr.
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