Seite 1 von 2
Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 10:19
von kaytec
Hallo !
Bin an einem Space Invaderspiel und versuche ein Dauerfeuer zu verhindern, doch alle Versuche haben nicht den gewünschten Erfolg. In Zeile 120 und 130 versuche ich mittels eines Schalters dieses Verhalten zu erzeugen. Es wird bei einem Tastendruck, ohne die Taste loszulassen, ein Keyrelease - Event gesendet.
Hier der Code:
http://www.python-forum.de/pastebin.php?mode=view&s=103
Gruß Frank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 10:44
von Xynon1
Nein, das Event wird nicht ausgelöst, du hast nur ein zweites Event mit FIRE_PRESS drin, welches schon vorher ausgelöst wird.
Übrigens sieht schon verdammt gut aus, kompliment

Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 10:50
von kaytec
Hallo Xynon1 !
Danke für das Kompliment !
Verstehe gerade nicht was du mir sagen möchtest ?
Gruß Frank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 10:56
von Xynon1
Du hast doch folgende Events gesetzt:
Code: Alles auswählen
RIGHT_PRESS = "<Right>"
LEFT_PRESS = "<Left>"
RIGHT_RELEASE = "<KeyRelease-Right>"
LEFT_RELEASE = "<KeyRelease-Left>"
FIRE_PRESS = ("<space>")
FIRE_RELEASE = ("<KeyRelease-space>")
Und in einer Schleife werden die gesetzt.
Nun hast du aber das Problem das wenn du ein KeyPress (Also ein normales Tasten-Event) nutzt, nämlich "<space>", bedeutet dass das folgende KeyRelease-Event "<KeyRelease-space>" ignoriert wird.
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 11:03
von kaytec
Wenn der KeyRelease-Event ignoriert werden würde, dann würde doch der Schalter "self.fire_button_release" auf False bleiben und ich könnte nicht mehr "ballern". Mein Gedanke war, beim Loslassen der Taste den Schalter auf True zu setzen und das Dauerfeuer abzuschalten.
Gruß Fank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 11:13
von Xynon1
Ok, moment, vieleicht liegt es am OS, hatte bei Tkinter Key-Bindings dort schon häufiger unterschiede, welches nutzt du ?
Ich teste es gleich mal noch mit einem anderen System.
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 11:16
von kaytec
Ich verwende Xubuntu !
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 12:17
von Xynon1
Ist tatsächlich unterschiedlich,
ich seh mir dein Programm gleich nochmal genau an was an den einzelnen Stellen passiert, aber dürfte ich vieleicht einen anderen Stop-Trigger vorschlagen.
Wenn ich mich recht erinnere war das bei Space Inviders immer so, das du nur einen Schuss abgeben konntest und erst wenn der weg war den nächsten.
Also als Stop-Trigger statt KeyRelease das "sterben" des Schusses nehmen.
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 12:26
von kaytec
Danke dir für deine Hilfe ! Eine andere Möglichkeit nehme ich sehr gerne an - stehe gerade selbst auf dem Schlauch.
Gruß Frank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 12:42
von Xynon1
Ok, follgendes wäre meine Idee:
1. mach aus "set_canon_fire" einfach nur "fire"
2. Falls du den Player als Invader Objekt betrachtest, solltest du bei "fire" angeben, ob nach oben oder unten.
Besser wäre es aber wenn du ein "Sprite" Objekt machen würdest, welches die Bewegung steuert und du einmal Player und einmal Invader ableitest und sie damit trennst
3. Dein Schuss muss ein Objekt werden, da du ja nicht nur diesen sehen willst sonder ja auch was bei diesem passieren soll, also hier könnte man ein "Bullet" Objekt von Sprite ableiten
4. Dann kannst du bei "fire" eine Bullet Instanz erzeugen, welches die Kollision auslöst und sich dann auflöst.
5. Dann kannst du auch einfach prüfen, wenn die Schießen geklickt ob ein Projektil existiert, wenn nicht erzeugst du ein neues.
Im Prinzip wirst du hier nicht weit herum kommen um solche Logik, ich wunder mich nur warum du Tkinter und nicht pygame genommen hast, doch prinzipiell macht das keinen allzugroßen unterschied. Nur gäbe es in pygame sowas wie Sprites, etc schon.
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 15:16
von yipyip
Wenn ich das richtig verstanden habe, hast ein Problem mit dem Autorepeat, genauer das hier:
http://wiki.tcl.tk/20299
Vor einiger Zeit hatte ich das gleiche Problem, mein Testprogramm dafür:
Code: Alles auswählen
#!/usr/bin/env python
####
import Tkinter as tk
####
class KeyTest(object):
def __init__(self):
self.root = tk.Tk()
self.svar = tk.StringVar()
self.root.config(takefocus=1)
self.label = tk.Label(self.root, textvariable=self.svar, width=60, height=5)
self.label.pack()
self.root.bind_all('<KeyRelease>', self.release)
self.root.bind_all('<KeyPress>', self.press)
# extra treatment else WM controls the tab
self.root.bind_all('<KeyPress-Tab>', self.press)
self.root.focus_set()
self.reset()
self.check()
def check(self):
if self.key:
s = '%s >%s< >%s< ===> %d' % (self.key, ('-', 'PRESSED')[self.pressed],
('-', 'PUSHED')[self.push], self.counter)
self.svar.set(s)
self.push = 0
self.root.after(50, self.check)
def reset(self):
self.key = None
self.push = 0
self.pressed = 0
self.old_ser = -1
self.new_ser = -2
self.counter = 0
def release(self, ev):
try:
self.new_ser = ev.serial
except AttributeError:
print 'ups'
return
print 'release', ev.serial
self.pressed = 0
self.old_ser = self.new_ser
self.key = str(ev.keysym)
def press(self, ev):
if self.old_ser == ev.serial:
self.push = 0
print 'same key'
else:
self.push = 1
self.counter += 1
self.pressed = 1
self.old_ser = ev.serial
self.key = str(ev.keysym)
def run(self):
self.root.mainloop()
####
if __name__ == '__main__':
KeyTest().run()
Programm starten und beliebig die Tasten drücken. Bei einem Tastendruck erscheint ganz kurz das Wort "PUSHED". Zur besseren Kontrolle wird noch ein Zähler hochgezählt. An dieser Stelle im Programm kannst Du Deine Fire-Methode einklinken, damit pro Tastendruck jeweils nur ein Schuss abgefeuert wird.
yipyip
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 15:53
von Xynon1
Aber dies ist keine Lösung für das eigentliche Problem, dies ist nur eine Verlagerung.
Denn Zeitverzögert ist nur gut wenn man eine bestimmte Pulsrate hat, und das könnte man dann nochmal einfacher machen.
zB. nur mit der ".after(...)"-Methode einfach eine Variable ändern, welche das Schießen zulässt, dann ist es völlig egal wie oft das KeyEvent ausgelöst wird.
Und meine Frage wäre jetzt noch unter welchen Systemen du das bereits getestet hast, sonst ist dies genauso hinfällig wie der normale KeyEvent.
Edit:
Achso, trotzdem ein schönes Snippet, sollte höchstens nochmal etwas aufgearbeitet werden

Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 16:12
von yipyip
Ich habe es nur unter Ubuntu getestet (deshalb auch das X11 im Link). Von Zeitverzögerung oder Pulsrate ist meinens Erachtens überhaupt nicht die Rede. Mit meinem Beispiel kann man ein einmaliges Event auslösen, auch wenn man die Taste länger gedrückt hält und somit das Autorepeat unter X11 umgehen. So hatte ich das Problem verstanden (damit ein Dauerfeuer verhindert wird).
yipyip
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 16:22
von Xynon1
Ja, das ist mir bewusst, aber sein Ziel ist ja nicht "Autorepeat unter X11 umgehen", auch wenn das sein momentanes Problem ist.
Sondern sein Ziel ist ja "Space Invaders" und in Space Invaders, hing das nicht vom Tastendruck ab, sondern ob das Projektil noch existiert.
Denn ansonsten kann man auch dauerfeuer erzeugen in dem man ganz schnell hinter einander Klickt.
Dennoch danke, brauchbar ist deine Info auf jedenfall und das möchte ich hier auch nicht gering schätzen.
Zu mindest versteh ich den Unterschied in der Interpretation des KeyEvents endlich.
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 16:48
von kaytec
Hallo yipyip!
Habe deinen Tip eingebaut und es klappt - danke!
@Xynon
Danke für deine Tips - habe schon mal Snake mit Pygame gemacht, doch irgendwie mag ich Tkinter.
Gruß Frank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 16:52
von Xynon1
Ich habe ja auch nichts dagegen, das du Tkinter nutzt, aber du musst dennoch etwas weiter in OOP streben, ansonsten fällt dir dein schon guter Ansatz auf die Füße.

Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 16:57
von kaytec
Ihr habt ja schon mehr geschrieben - ich war noch am Code von yipyip. Eigentlich wollte ich wirklich nur das Dauerfeuer abstellen, doch ich habe jetzt mal Space-Invaders gespielt und muss, dass Xynon1 recht hat. Man kann nur einen Schuß abgeben, wenn der eine getroffen hat oder aus dem Spielfeld ist. Muss ich noch ändern und dadurch ensteht das Problem mit dem Dauerferuer nicht.
Gruß und Dank Frank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 17:00
von kaytec
kaytec hat geschrieben:Ihr habt ja schon mehr geschrieben - ich war noch am Code von yipyip. Eigentlich wollte ich wirklich nur das Dauerfeuer abstellen, doch ich habe jetzt mal Space-Invaders gespielt und musste feststellen, dass Xynon1 recht hat. Man kann nur einen Schuß abgeben, wenn der eine getroffen hat oder aus dem Spielfeld ist. Muss ich noch ändern und dadurch ensteht das Problem mit dem Dauerferuer nicht.
Gruß und Dank Frank
Wollte eigentlich mich nicht zitieren, sondern den Text verbessern.
Gruß Frank
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 17:22
von yipyip
@Xinon1:
Daß jeweils nur ein Schuss aktiv sein darf, war aus der ursprünglichen Frage aber auch nicht so ersichtlich.

Sollte programmiertechnisch aber auch nicht so ein großes Problem sein.
Kann mich nicht mehr erinnern, wann ich das letzte mal Space Invaders gespielt habe...
@kaytec
Auch wenn wir hier alle Tkinter Liebhaber sind, in diesem Fall hätte ich es doch mit Pygame gemacht.
Willst Du nicht auch noch Sound dazu haben?
yipyip
Re: Keyboard-Event
Verfasst: Dienstag 21. Dezember 2010, 17:28
von Xynon1
Sound kann man doch einbauen zB mit tkSnack.
Wenn man allerdings pygame sound haben willst dann importier doch das einzelne Modul von pygame, das ändert doch nichts daran das die GUI mit Tkinter gebaut ist.