Klassen und Properties

Antworten
Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Klassen und Properties

Beitrag von Aloxen »

Einen schönen guten Abend,
ich versuche gerade eine mini Physics engine zu schreiben und hau hier mal wieder was mit den Klassen durcheinander. Ich brauche eine Klasse, mit der ich Objekten in der Scene als Entity beschreibe. Dafür habe ich folgende Klasse aufgestellt:

Code: Alles auswählen

type TEntity = class
  private
    APosition:TVector3f;
    V:TVector3f;
    a:TVector3f;
    m:Real;
    function vec3(x,y,z:Real):TVector3f;
  public
    property Position:TVector3f read APosition write Aposition;
    procedure applyForce(Force:TVector3f);
    procedure applyForce(x,y,z:Real);
    procedure Update;
    constructor Create(x,y,z:Real);
end;
Wenn ein Objekt dieser Klasse wie z.b. den Spieler erstelle, dann soll beim Create der Positionsvektor schon nach dem x,y und z Eingaben verändert werden. Das habe ich in der Create gemacht.

Jetzt kann ein Entity eine Kraft erfahren. Das würde man mit applyForce machen. Die Update funktion berechnet dann die aktuelle Geschwindigkeit und soll sie zur Position des Objekts addieren. So viel zum Grundprinzip.

Um jetzt die bzw die neuen Positionsdaten an die Lookat zu geben, die den Spieler verschieben würde, muss ich auf APosition zugreifen können. Das Problem ist, dass bei jedem versuch auf APosition oder auf bzw Player.Positon eine Fehlermeldung kommt:
Exception-Klasse "External:SIGSEGV"
Das heißt ja, dass hier kein Wert in der benutzen Variable vorliegt (so weit wie ich es verstanden habe).
Der Fehler kommt auch wenn ich versuche in der applyForce a (acceleration) und V(velocity) zu verändern.

Ich bin mir sicher dass ich hier einen Anfängerfehler in der Klassenstruktur gemacht haben muss. Kann mir jemand erklären was ich falsch gemacht habe?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Klassen und Properties

Beitrag von af0815 »

Anfängerfehler: Man sieht mit der Deklaration alleine nicht was du im Code gemacht hat. Weil ein SIGSEGV passiert im Code.

Und die Glaskugeln bleiben bei den Energiepreisen ausgeschaltet.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Klassen und Properties

Beitrag von kupferstecher »

Aloxen hat geschrieben:
Fr 16. Dez 2022, 00:46
Exception-Klasse "External:SIGSEGV"
Das heißt ja, dass hier kein Wert in der benutzen Variable vorliegt (so weit wie ich es verstanden habe).
Ja, es wird auf eine ungültige Speicherstelle zugegriffen, das Betriebssystem blockt das dann mit einem SIGSEGV-Fehler (Signal Segmentation Violation) ab.

Immer daran denken, Variablen einer Klasseninstanz sind im Grunde Pointer auf das im Heap angelegte Objekt. Offensichtlich verwendest du eine solche Variable, obwohl diese (noch) keine gültige Adresse enthält. Meistens heißt das einfach, dass die Instanz noch nicht erzeugt wurde (Create noch nicht aufgerufen). Vielleicht wurde die Instanz auch schon erzeugt, aber noch nicht der Variablen zugewiesen, über die man auf die Member-Variablen zugreifen wollte. Auf jeden Fall wird mit dem Konstruktor die Instanz komplett erzeugt, man kann da eigentlich nichts falsch machen.

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Klassen und Properties

Beitrag von Aloxen »

af0815 hat geschrieben:
Fr 16. Dez 2022, 07:42
Anfängerfehler: Man sieht mit der Deklaration alleine nicht was du im Code gemacht hat. Weil ein SIGSEGV passiert im Code.
Selbstverständlich, mein Fehler. Die Proceduren aus der Klasse sind wie folgt:

Code: Alles auswählen

constructor TEntity.Create(x,y,z:Real);
begin
  inherited Create;
  FPosition:=vec3(x,y,z);
  V:=vec3(0,0,0);
  a:=vec3(0,0,0);
  m:=1;
end;
procedure TEntity.Place(x,y,z:Real);
begin
  FPosition:=vec3(x,y,z);
end;

{apply Force}
procedure TEntity.applyForce(Force:TVector3f);
begin
  a:=a+force;
end;
procedure TEntity.applyForce(x,y,z:Real);
var
  Force:TVector3f;
begin
  Force:=vec3(x,y,z);
  a:=a+force;
end;

{Update}
procedure TEntity.Update;
begin
  V:=a/m;
  FPosition:=Position+V;
end; 
Vec3 ist nicht wirklich wichtig, ich habe es nur noch nicht geschafft eine Help unit zu machen.

Also ich habe festgestellt dass ich bei Create den inherited Teil vergessen habe, dass hat den Fehler aber leider auch nicht behoben. Also erstmal kommt der Fehler wenn ich im Programm applyForce aufrufe:

Code: Alles auswählen

procedure TForm1.CAlcPhysics;
var
NewPos:TVector3f;
begin
 //Kräfte hinzufügen
 Player.applyForce(PlayerMovementCalc);
 Player.Update;
 //Verschieben
 NewPos:=Player.Position;
 cam_inv.LookAt(NewPos[0],NewPos[1],NewPos[2],NewPos[0]+camDir[0],NewPos[1]+camDir[1],NewPos[2]+camDir[2],up[0],up[1],up[2]);
 //Kollision
 Collision;
end; 
Der Fehler tritt bei der Stelle a:=a+force auf.
An der Stelle habe ich auch noch etwas anderes festgestellt, was nicht funktioniert. Normalerweise greift man bei TVector3f auf eine Stelle mit [] zu. Wie bei einem Array, da TVector3f nichts anderes ist. Versucht man jetzt im Program auf Player.Position[2] zuzugreifen kommt schon im Kompiler eine Fehlermeldung.

Ps: ich habe bei Aposition das A zum F getauscht

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Klassen und Properties

Beitrag von Aloxen »

Ich habe mit dem Debugger nachgeschaut und für a sagt er bzw an der Stelle wo der Fehler auftritt:
"Cannot access memory at adress 0x20".

Das verstehe ich nicht weil ich die Werte doch alle Deklariert habe. Kann mir jemand weiterhelfen?

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Klassen und Properties

Beitrag von wp_xyz »

Aloxen hat geschrieben:
So 18. Dez 2022, 11:04
Das verstehe ich nicht weil ich die Werte doch alle Deklariert habe.
"Deklarieren", also "var Player: TEntity", ist bei Klassen nicht alles. Du musst irgendwo auch den Konstructor der Klasse aufrufen:

Code: Alles auswählen

var
  Player: TEntity;
...
procedure TForm1.CalcPhysics;
begin
  if Player = nil then
    Player := TEntity.Create;
  ...

Aloxen
Beiträge: 58
Registriert: Di 31. Mai 2022, 17:40

Re: Klassen und Properties

Beitrag von Aloxen »

Das habe ich. Von OnFormCreate ausgelöst initialisiert eine Procedure die Scene. Da habe ich Player.create(4,4,0);

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Klassen und Properties

Beitrag von wp_xyz »

Aloxen hat geschrieben:
So 18. Dez 2022, 11:32
Das habe ich. Von OnFormCreate ausgelöst initialisiert eine Procedure die Scene. Da habe ich Player.create(4,4,0);
"Player.Create(4,4,0)" oder "Player := TPlayer.Create(4, 4, 0)". Bin nicht sicher, ob die erste Variante richtig ist (das gab's bei Turbo Vision). Die ganze LCL initialisiert die Komponenten auf die zweite Art.

[EDIT]
Ich hab's gerade ausprobiert: Leeres Formular, im Formular einen Button deklarieren als "Button1: TButton", dann im OnCreate des Formulars versuchen, den Button zu erzeugen mit "Button1.Create(self)" --> Zugriffsfehler auf $0000. Aber "Button1 := TButton.Create(self)" funktioniert.

Das Problem von "Button1.Create(self)" ist, dass du auf eine Methode des Buttons zugreifst ("Create"), aber der Button ist in diesem Augenblick noch nil. Bei "TButton.Create" ist es anders: das ist eine Methode der Klasse, nicht der Instanz - die Klasse gibt es immer, die Instanz erst nach dem Create.

Hier der getestete Code:

Code: Alles auswählen

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    Button1 : TButton;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.Create(self);                  // FALSCH !!!
//  Button1 := TButton.Create(self);     // RICHTIG
  Button1.Caption := 'test';
  Button1.Parent := Self;
end; 

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Klassen und Properties

Beitrag von fliegermichl »

wp_xyz hat geschrieben:
So 18. Dez 2022, 12:42
Aloxen hat geschrieben:
So 18. Dez 2022, 11:32
Das habe ich. Von OnFormCreate ausgelöst initialisiert eine Procedure die Scene. Da habe ich Player.create(4,4,0);
"Player.Create(4,4,0)" oder "Player := TPlayer.Create(4, 4, 0)". Bin nicht sicher, ob die erste Variante richtig ist (das gab's bei Turbo Vision). Die ganze LCL initialisiert die Komponenten auf die zweite Art.
[/code]
Die erste Version bezieht sich auf ein TObject. Das ist ein statisches Objekt. Die Klassen sind immer dynamisch und müssen über TClassXX.Create erzeugt werden.
Das gilt nicht für Methoden die als class function / procedure deklariert wurden.

Antworten