Autor |
Beitrag |
Bergmann89
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 03:16
Hey,
ich bin grad dabei n Spiel zu schreiben, un da mus ich in verschiedenen Klassen auf Tastatureingaben reagieren. Ich hab mir n InputManager geschrieben, der die Tasten zusammen fast (z.B: 'W' und VK_UP für 'nach oben'). Jetz geht es darum auf vernünftig auf die Tastaureingaben zu reagieren. Meine Idee ist es dem InputManager eine OnKeyDown-Prozedur zu geben, die dann ausgeführt wird wenn auf der Form eine Taste gedrückt wurde. Weiterhin können sich beim Inputmanager Clients regestrieren, die auch über das Event benachrichtig werden wollen. Also führt der InputManager in der OnKeyDown-Prozedur eine Schleife aus, in denen dann die Events bei den Clients ausgelöst werden. Is das so ne gute Idee, oder geht das auch irgendwie über Windows-Messages?
MfG & Thx Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
Zuletzt bearbeitet von Bergmann89 am So 21.02.10 04:26, insgesamt 1-mal bearbeitet
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.02.10 03:28
Der Grundlegende Ansatz ist so durchaus schon okay. Wo du ggf. schauen solltest ist in Bezug auf die Art, wie Ereignisse zugeordnet werden, aber da wären ggf. ein paar Implementationsdetails hilfreich. Den Aufruf der Listener über eine Liste dieser zu realisieren passt aber schon mal. Bliebe nur noch die Frage, wie diese intern organisiert werden (sprich als eine Liste, oder mehrere).
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Bergmann89 
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 03:51
Hey,
für die Ereigniss-Zuordnung woll ich ne Methode im InputManager schreiben, bei der sich der Client mit seiner OnKeyDown-Methode einträgt, genau so umgedreht wenn das Event weider entfernt werden soll, also so in etwa:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure Register(Event: TOnKeyDownEvent) wenn schon nicht regesttiert, dann... trage das Event in die Liste ein procedure-end
procedure Unregister(Event: TOnKeyDownEvent) zähle alle Elemente der Liste rückwärts durch... wenn das aktuelle List-Event gleich dem Event, dann... lösche den aktuellen Listeneintrag procedure-end | Ich habs noch nich implementiert, deshalb erstmal so...
Organiesieren wollt ich das ganze in 3 verschiedenen Listen einmal die OnKeyDown-, die OnKeyPress- und die OnKeyUp-Events. Ich wüsste jetzt auch nciht, wie ich das anderes realisieren kann?!
€: andere Idee für die Zuweisung. Das Object regestriert sich mit der eigenen Instanz un implementiert ein Interface, welches die 3 Events enthält. So kann der InputManager das Object auf Gültigkeit prüfen und ggf. das Object entfernen, wenn es nich mehr exestiert...
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
Zuletzt bearbeitet von Bergmann89 am So 21.02.10 03:56, insgesamt 1-mal bearbeitet
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.02.10 03:55
Okay. Dann ist das im Wesentlichen, wie man es typisch auch bei Java vorfindet.
Je nach Menge der Events hätte auch eine Event-Liste mit ner kleinen Markierung funktioniert. Aber bei grad mal 3 Events passt das so.
Was ggf. auch zu überlegen wäre, wäre, ob du für jede "virtuelle" Taste eine Liste fertig machst. Dann greift aber der grad genannte Punkt, dass man dann eher zu einer Event-Liste mit entsprechenden Markierungen gehen sollt (wegen Verwaltungsoverhead sonst).
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Bergmann89 
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 04:03
Hey,
BenBE hat folgendes geschrieben : | Was ggf. auch zu überlegen wäre, wäre, ob du für jede "virtuelle" Taste eine Liste fertig machst. Dann greift aber der grad genannte Punkt, dass man dann eher zu einer Event-Liste mit entsprechenden Markierungen gehen sollt (wegen Verwaltungsoverhead sonst). |
Mit "virtueller" Taste meinst du meine definierten Taste, also "gehe nach oben", oder? Da hab ich zur Zeit n Array aus Listen, und jede Taste hat ne Konstante. Wenn ich jetzt ne neu Taste hinzufügen will, dann mach ich das Array einfach größer un ne neue Konstante, den Rest verwaltet die Klasse selber, da der Zugriff über die Konstanten erfolgt.
Hast du das mit den Interfaces schon gelesen? Das hab ich kurz vor deim Beitrag noch dran gehängt, das erscheint mir sinnvoller, falls mal ein Client freigegeben wird, ohne sich voher abzumelden...
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.02.10 04:07
Interfaces bei Delphi sind erstmal recht langsam, käme aber der Implementation, wie es bei Java realisiert wird, um einiges näher. Wenn die 3 Events eh zusammengehören, wäre dies aber durchaus eine denkbare Möglichkeit, die Events beim Registrieren\Deregistrieren zu bündeln. Alternativ gingen dafür aber auch Records, statt dem Interface.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Bergmann89 
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 04:10
Hm,
langsam is blöd, weil im 3D-Bereich kann das zu unschönen Rucklern führen...
Wenn ich das ganze über Records realisiere, dann kann ich aber nich mehr prüfen, ob das Objekt noch exestiert, oder?
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.02.10 04:17
Bergmann89 hat folgendes geschrieben : | Hm,
langsam is blöd, weil im 3D-Bereich kann das zu unschönen Rucklern führen...
Wenn ich das ganze über Records realisiere, dann kann ich aber nich mehr prüfen, ob das Objekt noch exestiert, oder?
MfG Bergmann |
Solange Du nicht Multithreaded arbeitest, sollte sich das mit dem Deregistrieren durchaus recht unkompliziert im Destruktor serialisieren lassen. Sprich das Objekt meldet sich beim Zerstören selbstständig vom Input-Manager ab.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Bergmann89 
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 04:22
Jo, so hatte ichs auch vor, aber solche Dinge vergess ich gern mal, un dann such ich ewig nach dem Fehler^^ Naja, muss ich halt ma aufpassen was ich mach...
Da weiß ich ja jetzt wie's weiter geht und danke rest herzlich für die recht späte aber schnelle Hilfe  Schöne Nacht noch.
€: So habs jetzt implementiert, bin mir aber nicht sicher ob ich das mit den Zeigern richtig gemacht hab. Kann dann nochma jmd drüber gucken?
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| const IM_EVENT_KEY_DOWN = 0; IM_EVENT_KEY_UP = 1; IM_EVENT_KEY_PRESS = 2;
var fEvents: array[0..2] of TList;
procedure TInputManager.RegisterKeyPressEvent(Event: TKeyPressEvent); var i: Integer; begin if not Assigned(Event) then exit; for i := 0 to fEvents[IM_EVENT_KEY_PRESS].Count-1 do if fEvents[IM_EVENT_KEY_PRESS][i] = @Event then exit; fEvents[IM_EVENT_KEY_PRESS].Add(@Event); end;
procedure TInputManager.UnregisterKeyPressEvent(Event: TKeyPressEvent); var i: Integer; begin if not Assigned(Event) then exit; for i := fEvents[IM_EVENT_KEY_PRESS].Count-1 downto 0 do if fEvents[IM_EVENT_KEY_PRESS][i] = @Event then fEvents[IM_EVENT_KEY_PRESS].Delete(i); end;
procedure TInputManager.KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var i: Integer; begin for i := 0 to fEvents[IM_EVENT_KEY_DOWN].Count-1 do PKeyEvent(fEvents[IM_EVENT_KEY_DOWN][i])^(self, Key, Shift); end; |
So ich geh dann ma penn... bis später...
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
Bergmann89 
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 12:28
Hey,
also ich hab jetz den implementierten Code von heut Nacht ausprobiert. Un irgendwo is der Wurm drin. Sobald ich das Event an die einzellnen Clients weiterleiten will Kracht es: Zugriffsverletzung an diser Zeile PKeyEvent(fEvents[IM_EVENT_KEY_DOWN][i])^(self, Key, Shift);
Ich versteh aber nich warum. Ich hab den Zeiger auf die Methode in die Liste eingetragen mit List.add(@Event). Das Event is vom Typ TKeyEvent. Also muss ich doch dann beim Zugriff darauf den Pointer casten: PKeyEvent(List[i]) und dann mit Hilfe des Pointers auf die Referenz zugreifen, also PKeyEvent(List[i])^ und dann sollte ich ja wieder mein normales TKeyEvent haben, was ich in die Liste eingetragen hab, oder bin ich da auf dem Holzweg?!
MfG Bergmann
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.02.10 14:06
Das hängt damit zusammen, dass Methoden-Referenzen (und nix anderes sind Events) immer 2 Pointer sind (also Daten+Code). Mach mal statt der TList nen Array of TDeinEventTyp.
Ansonsten halt noch beachten, was ich bzgl. Eventgruppierung mit Records gesagt hab:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| type TMyKeyEvent = procedure(foo:Integer; bar: Integer; baz: Integer) of object; TMyEventTypes = (metKeyDown, metKeyPress, metKeyUp); TMyEventRecord = packed record events: array [TMyEventTypes] of TMyKeyEvent; end; |
Dazu ggf. in deine Manager-Klasse eine Methode zum Initialisieren:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| class procedure TInputManager.InitEventRecord(out er: TMyEventRecord); var et: TMyEventTypes; begin for et := Low(er.events) to High(er.events) do er.events[et] := nil; end; |
Oder ein entsprechendes Analogon mit FillChar.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Bergmann89 
      
Beiträge: 1742
Erhaltene Danke: 72
Win7 x64, Ubuntu 11.10
Delphi 7 Personal, Lazarus/FPC 2.2.4, C, C++, C# (Visual Studio 2010), PHP, Java (Netbeans, Eclipse)
|
Verfasst: So 21.02.10 15:02
Super, geht. Auch wenn die Verwaltung von nem Array nich so easy is wie von ner Liste, aber das war ja schnell implementiert. Also nochma vielen Dank, ich denke das sollte es zu dem Thema gewesen sein
MfG Bergmann.
_________________ Ich weiß nicht viel, lern aber dafür umso schneller^^
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.02.10 15:24
Bei Omorphia hatten wir in die Richtung auch sowas in der Art implementiert. Ansatz war nahezu identisch.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
|