Einzelnen Beitrag anzeigen

ZYLAGON

Registriert seit: 11. Nov 2015
50 Beiträge
 
Delphi 10.3 Rio
 
#1

Tastatursteuerung für Objekt im 3D-Raum

  Alt 15. Jun 2017, 22:26
Schönen guten Abend zusammen,

ich habe mir eine primitive 3D-Steuerung zusammengebastelt.
Das Objekt fährt immer in Blickrichtung solange die Geschwindigkeit positiv ist.
Sieht auch so aus als ob alles korrekt funktioniert.
Bin allerdings mit der Tastatursteuerung unzufrieden und hoffe auf Hilfe.

Hier mal der Code der Steuerung:

Delphi-Quellcode:
unit Test_Vektor;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Viewport3D,
  System.Math.Vectors, FMX.Controls3D, FMX.Objects3D, FMX.StdCtrls,
  FMX.Controls.Presentation, Windows, FMX.MaterialSources;

type
  TForm1 = class(TForm)
    ColorMaterialSource2: TColorMaterialSource;
    Viewport3D1: TViewport3D;
    Dummy1: TDummy;
    Figur: TCube;
    Auge: TSphere;
    Zielpunkt: TSphere;
    procedure FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
      Shift: TShiftState);
  private
    { Private-Deklarationen }
    fZielpunktVektor:TVector3D;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
begin
  if GetAsyncKeystate(VK_UP)<0 then
    begin
      fZielpunktVektor:=Zielpunkt.LocalToAbsoluteVector(Zielpunkt.Position.Vector);
      Figur.Position.Vector:= fZielpunktVektor;
    end;

  if GetAsyncKeystate(VK_LEFT)<0 then
    begin
      Figur.RotationAngle.Y:=Figur.RotationAngle.Y-1;
    end;

  if GetAsyncKeystate(VK_RIGHT)<0 then
    begin
      Figur.RotationAngle.Y:=Figur.RotationAngle.Y+1;
    end;

  if GetAsyncKeystate(VK_Prior)<0 then
    begin
      Figur.RotationAngle.X:=Figur.RotationAngle.X+1;
    end;

  if GetAsyncKeystate(VK_Next)<0 then
    begin
      Figur.RotationAngle.X:=Figur.RotationAngle.X-1;
    end;

  if GetAsyncKeystate(VK_HOME)<0 then
    begin
      Figur.RotationAngle.Z:=Figur.RotationAngle.Z+1;
    end;

  if GetAsyncKeystate(VK_END)<0 then
    begin
      Figur.RotationAngle.Z:=Figur.RotationAngle.Z-1;
    end;

end;

end.


Wenn ich z.B. Pfeiltaste hoch gedrückt halte, bewegt sich das Objekt in Blickrichtung.
Drücke ich jetzt zusätzlich Pfeiltaste links, gibt´s einen kurzen Aussetzer, Objekt bewegt sich dann allerdings korrekt nach vorne links aus Blickwinkelsicht.
Lasse ich irgendwann die Pfeiltaste links los, dann bleibt das Objekt stehen.
Das kann ich noch umgehen, wenn ich eine beliebige Taste (z.B. Taste F) beim Loslassen der Pfeiltaste Links drücke.
Dann habe ich wieder diesen kurzen Aussetzer und das Objekt bewegt sich wie gewünscht nach vorne in Blickrichtung.

Also gibt es 2 Probleme:
1) Kurzer Aussetzer bei Zuschalten einer weiteren Taste.
2) Bei Loslassen einer Taste wird eine zusätzliche, unbeteiligte Taste benötigt, damit Objekt nicht zum Stillstand kommt. Das führt allerdings auch zu einem kurzen Aussetzer.


Falls jemand den obigen Code testen möchte, bedarf es möglicherweise noch ein paar Erklärungen:

Struktur:
Viewport ist Parent von Dummy
Dummy ist Parent von Figur (Dummy wird nicht unbedingt benötigt. Dann wäre Viewport der Parent für Figur)
Figur (hier habe ich einfach nur einen StandardCube der Größe 1 genommen) ist Parent von sowohl Auge als auch von Zielpunkt

Das Auge der Figur dient zur Erkennung der Blickrichtung.
Ich habe hier eine Sphere Größe 0,2 gewählt bei einer Z-Position von 0,51.
Als MaterialSource habe ich ColorMaterialSource2 zugeordnet, um das Auge erkennen zu können.

Jetzt zum Zielpunkt.
Die Figur fährt immer in Richtung Zielpunkt.
So ist es möglich, in Blickrichtung zu fahren.
Ich habe hier eine Sphere Größe 0,1 gewählt bei einer Z-Position von 0,01.
Die Z-Position ist sozusagen die Geschwindigkeit.

VG
ZYL
  Mit Zitat antworten Zitat