|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 09.06.2007, 19:14 Titel: |
|
|
@Simon: Hmm naja dann geht es immer noch nicht so wie ich es meinte, wenn man das Array außerhalb der Klasse im Header definiert, geht es aber:
CPP: | class CDirectInput
{
// [...]
};
static const unsigned long Keys[26] = { DIK_A, DIK_B, DIK_C, DIK_D, DIK_E, DIK_F, DIK_G, DIK_H, DIK_I, DIK_J,
DIK_K, DIK_L, DIK_M, DIK_N, DIK_O, DIK_P, DIK_Q, DIK_R, DIK_S, DIK_T,
DIK_U, DIK_V, DIK_W, DIK_X, DIK_Z, DIK_Y}; // Deutsche Tastatur: DIK_Y und DIK_Z getauscht |
Hier nochmal die fertige Methode:
CPP: | char CDirectInput::getKeyboardInput(void)
{
// alle Tasten der Tastatur
bool bKeyboard[256];
if(FAILED(m_lpDIDevice->GetDeviceState(sizeof(bKeyboard),(LPVOID)&bKeyboard)))
{
// Kontrolle wiederholen, falls verloren
m_lpDIDevice->Acquire();
return 0;
}
// Klein- / Großschreibung:
// Kleine Buchstaben (ab 97)
unsigned int lower_or_upper = 97;
// Großschreibung (ab 65)
if(bKeyboard[DIK_LSHIFT] || bKeyboard[DIK_RSHIFT])
{
lower_or_upper = 65;
}
// Array überprüfen, ob 'passende' Taste gedrückt
for(int i = 0; i < 26; i++)
{
if(bKeyboard[Keys[i]]) // Ja: Gebe Buchstaben (char) zurück
return (static_cast<char>(i + lower_or_upper));
}
// Ansonsten 0
return NULL;
} |
Ich denke die kann ich so stehen lassen oder? :]
@Fallen: Ich hab versucht den Vorschlag ans laufen zu bekommen, obwohl die Kommentare dazu (unter Discuss this article in the forums) sagen, das es nicht möglich ist (außer der 3. hat es wohl hinbekommen, aber kA wovon der redet XD).
Aber irgendwie will es nicht :/
Denn: was für einen header brauche ich für uchar!? o.O _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
51m0n JLI'ler
Alter: 33 Anmeldedatum: 06.01.2006 Beiträge: 167 Wohnort: Erkelenz Medaillen: Keine
|
Verfasst am: 09.06.2007, 19:25 Titel: |
|
|
GreatFlo hat Folgendes geschrieben: |
Ich denke die kann ich so stehen lassen oder? :]
|
Jo eig schon. Sind nur noch eine Kleinigkeit:
Ganz korrekt müsste es
CPP: | return static_cast<char>(NULL); |
heißen.
Außerdem würde ich unbedingt prüfen ob die Methode NULL zurückgibt, denn das steht für string ende. Wenn du das Zeichen ohne jede Überprügung an den String anhängst heißt das, dass der String an der Stelle zu ende ist, obwohl das evtl gar nicht der Fall ist. _________________ Teigwaren
heißen Teigwaren,
weil sie früher einmal Teig waren |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 09.06.2007, 19:55 Titel: |
|
|
überprüfen tue ich, ob der NULL zurück gibt. muss ich mal in die methode einbauen, aber das folgt:
Als nächstes werde ich aber das ganze mal umbauen ^^
muss ja noch was zum entfernen des letzten Zeichens haben (BACKSPACE) - daher muss der string an die methode übergeben werden
Aber hab das schlimmste ja nun geschafft Vielen dank euch allen _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt
Zuletzt bearbeitet von Asto am 09.06.2007, 22:15, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 09.06.2007, 19:57 Titel: |
|
|
GreatFlo hat Folgendes geschrieben: | Denn: was für einen header brauche ich für uchar!? o.O |
Mit uchar ist unsigned char gemeint, mehr nicht. _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 09.06.2007, 20:16 Titel: |
|
|
Fallen hat Folgendes geschrieben: | GreatFlo hat Folgendes geschrieben: | Denn: was für einen header brauche ich für uchar!? o.O |
Mit uchar ist unsigned char gemeint, mehr nicht. |
warum schreiben die das dann net in ihrem code!? oder kennen compiler den typ? mein VC++ EE nämlich net ^^ _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 09.06.2007, 22:02 Titel: |
|
|
GreatFlo hat Folgendes geschrieben: | Fallen hat Folgendes geschrieben: | GreatFlo hat Folgendes geschrieben: | Denn: was für einen header brauche ich für uchar!? o.O |
Mit uchar ist unsigned char gemeint, mehr nicht. |
warum schreiben die das dann net in ihrem code!? oder kennen compiler den typ? mein VC++ EE nämlich net ^^ |
das sind typedefs oder manchmal (leider) auch noch #defines von früher, die eben aus unsigned char den Typ uchar gemacht haben; z.B. wegen schnellerem schreiben etc.
@Simon: das mit dem static_cast<char> ist unnötig, da NULL zu 0 ausgewertet wird, und der Compiler eine 0 als Zahl für den Rückgabewert des Typs char sowieso in char mapt. Erst wenn du einen konstanten Wert >255 zurückgeben würdest, würde er meckern
Dann noch zu der Sache mit dem Array, GreatFlo: Ich glaube, dass du ein statisches const array auch als privaten class-member haben darfst, da der ISO-Standard ungf. folgendes sagt: Man kann statische numerische (=int, long...) klassenmember-arrays sowohl privat als auch öffentlich in der Klassendefinition selbst deklarieren, wenn sie konstant sein sollen. Demnach sollte das gehen: CPP: | class Foo
{
//...
private:
static const unsigned long Keys[] = { /*und hier die keys*/ };
}; | Diese innere Klassendefinition gilt allerdings nur bei statischen Klassenmembern, die numerisch sind; alle anderen muss man in der cpp-Datei extern definieren
Gruß DXer |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 09.06.2007, 22:12 Titel: |
|
|
also nun die fertige klasse mit "Backspace-Funktion", also zum entfernen des letzten Zeichens. Außerdem habe ich auch die Zeitabfrage direkt eingebaut.
CPP: | string CDirectInput::getKeyboardInput(string str)
{
int laenge = (int)strlen(str.c_str());
if(laenge == 0) // Wenn nicht initialisiert, dann "leeren" String erzeugen.
str = '\0';
// Nur alle Xms tastendruck zulassen
unsigned long CurTime = timeGetTime();
if((CurTime - LastKeyPressed) < 70)
return str;
else
LastKeyPressed = CurTime;
// alle Tasten der Tastatur
bool bKeyboard[256];
if(FAILED(m_lpDIDevice->GetDeviceState(sizeof(bKeyboard),(LPVOID)&bKeyboard)))
{
// Kontrolle wiederholen, falls verloren
m_lpDIDevice->Acquire();
return str;
}
// Wenn Backspace gedrückt, dann letztes Zeichen entfernen
if(bKeyboard[DIK_BACKSPACE] && laenge > 0)
{
str[laenge-1] = '\0';
return str;
}
// Klein- / Großschreibung:
// Kleine Buchstaben (ab 97)
unsigned int lower_or_upper = 97;
// Großschreibung (ab 65)
if(bKeyboard[DIK_LSHIFT] || bKeyboard[DIK_RSHIFT])
{
lower_or_upper = 65;
}
// Array überprüfen, ob 'passende' Taste gedrückt
for(int i = 0; i < 26; i++)
{
if(bKeyboard[Keys[i]]) // Ja: Gebe geänderten String zurück
{
str[laenge] = static_cast<char>(i + lower_or_upper);
str += '\0';
return str;
}
}
// Ansonsten String ohne Änderrungen
return str;
} |
Habe keine andere Möglichkeit gefunden, um das letzte Zeichen zu entfernen, daher auch eine angepasste, komische, methode zum hinzufügen der zeichen.
Diese Methode ist etwas unsauber, da der Rest ja nicht abgeshcnitten wird nach dem \0 oder?
Würde dann ja sowas nach mehrmaligem drücken von Backspace im string stehen: Hallo We\0\0 (2x Drücken)
Gibt es ne bessere Möglichkeit? :X
Naja wie ihr evt. merkt: ich bekomms hin, aber mich interessiert, ob es besser geht
@DirectXer: Bei mir meckerte er, das { nicht erlaubt sei
Zitat: | 1>c:\dokumente und einstellungen\greatflo\eigene dateien\visual studio 2005\projects\menu-co\cdirectinput.h(42) : error C2059: Syntaxfehler: '{'
1>c:\dokumente und einstellungen\greatflo\eigene dateien\visual studio 2005\projects\menu-co\cdirectinput.h(42) : error C2334: Unerwartete(s) Token vor '{'; sichtbarer Funktionstext wird übersprungen |
Aber ich denke das ist ja nicht so tragisch, wenn ich Keys außerhalb der klasse deklariere, oder?
Denn ist ja konstant, ich kann es also nicht ausversehen ändern.
oder hat es performance / speicherverwaltungs-nachteile? _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
51m0n JLI'ler
Alter: 33 Anmeldedatum: 06.01.2006 Beiträge: 167 Wohnort: Erkelenz Medaillen: Keine
|
Verfasst am: 09.06.2007, 22:29 Titel: |
|
|
DirectXer hat Folgendes geschrieben: | @Simon: das mit dem static_cast<char> ist unnötig, da NULL zu 0 ausgewertet wird, und der Compiler eine 0 als Zahl für den Rückgabewert des Typs char sowieso in char mapt. Erst wenn du einen konstanten Wert >255 zurückgeben würdest, würde er meckern |
Ui stimmt.
Hab einfach blind gecasted ohne nachzudenken was ich da tue..
Kommando zurück, kannst alle casts rausnehmen
Aber er meckert schon bei Wert >127 da signed
D.h. man muss, wenn man es ganz korrekt haben will, wenn man ein "Ü" haben will den Wert -102 anstatt 154 nehmen . Oder man nimmt unsigned char
@GreatFlo
CPP: | str.erase(--str.end()); |
_________________ Teigwaren
heißen Teigwaren,
weil sie früher einmal Teig waren
Zuletzt bearbeitet von 51m0n am 09.06.2007, 22:38, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
DirectXer Dark JLI'ler
Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 09.06.2007, 22:37 Titel: |
|
|
ne, tragisch ist das net, es ist ne ganz normale lösung... trotzdem, ich werd mal nachschlagen, da gibts bestimmt was, nur so aus Interesse. Aber wegen Performancegründen musst du dir keine Sorgen machen, das ist eh alles
ziemlich schnell
Zu dem anderen Thema: Die std::string Klasse ist wunderbar, die bietet dir viele Funktionen an, die die C-Funktionen wie strlen() vollständig ersetzen, z.B. str.length() anstatt strlen() (was u.a. auch schneller ist) Die Nullterminierung ist bei std::strings im Grunde auch nicht nötig, das geschieht automatisch.
Und dann noch was zur Performance: Es ist ziemlich teuer, den string als Wert zu übergeben und am Ende als Wert zurückzugeben, da das durchgeführt wird:
- kopieren des ges. Strings für den Funktionsparameter
- Bearbeiten des strings
- kopieren des ges. Strings für den Rückgabewert
- kopieren des ges. Strings für die Zuweisung des Rückgabewertes
Erheblich schneller ginge sowass, da die ganze lahme Kopiererei entfällt:
CPP: | void CDirectInput::getKeyboardInput( std::string& str ) //übergabe als referenz
{
// hier kannst du wie gewohnt an str rumarbeiten, das wird direkt auf
// richtigen string umgeleitet. das return str entfällt dann, du musst
// zum beenden nur nuch:
return;
} |
Gruß DXer
EDIT: naja simon, jetzt warst du schneller und das mit dem >127 von mir war ein genauso dummer flüchtigkeitsfehler |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 09.06.2007, 23:03 Titel: |
|
|
Vielen Dank für die Tipps
naja mit str.erase ist es deutlich bequemer *gg*
Und die übergabe als referenz gefällt mir sollte ich öfter machen
Danke Tolles Forum _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
Otscho Super JLI'ler
Alter: 36 Anmeldedatum: 31.08.2006 Beiträge: 338 Wohnort: Gummibären-Gasse Medaillen: Keine
|
Verfasst am: 09.06.2007, 23:06 Titel: |
|
|
Das sieht schon ganz net aus GreatFlo, doch ein Schönheitsfehler ist mir da noch aufgefallen :
GreatFlo hat Folgendes geschrieben: | // Nur alle Xms tastendruck zulassen
unsigned long CurTime = timeGetTime();
if((CurTime - LastKeyPressed) < 70)
return str;
else
LastKeyPressed = CurTime;
|
Wenn einer sehr schnell auf der Tastatur schreibt, wird ihn deine "Zeitabfrage" vielleicht etwas stören, wenn er sie nach jedem Tastendruck die Tastatur für 70ms sperrt. Ein Tipp: Ich würde eine Taste nur dann "sperren", wenn sie beim vorigem Durchlauf auch schon gedrückt war. Dann brauchst du keinen Timer und schnelle Finger haben auch was wo sie sich austoben können. |
|
Nach oben |
|
|
Asto JLI'ler
Alter: 37 Anmeldedatum: 30.05.2007 Beiträge: 114 Wohnort: Dortmund Medaillen: Keine
|
Verfasst am: 09.06.2007, 23:11 Titel: |
|
|
hmm gute idee
dann hier nochmal die aktuelle (finale? ^^) Version:
CPP: | void CDirectInput::getKeyboardInput(string& str, int max_len)
{
int laenge = str.length(); // Stringlänge
unsigned long CurTime = timeGetTime(); // Aktuelle Zeit in ms
// alle Tasten der Tastatur
bool bKeyboard[256];
if(FAILED(m_lpDIDevice->GetDeviceState(sizeof(bKeyboard),(LPVOID)&bKeyboard)))
{
// Kontrolle wiederholen, falls verloren
m_lpDIDevice->Acquire();
return;
}
// Wenn Backspace gedrückt, dann letztes Zeichen entfernen
if(bKeyboard[DIK_BACKSPACE] && laenge > 0)
{
if(LastKeyPressedType == '!' && (CurTime - LastKeyPressedTime) < 100)
return;
else
{
LastKeyPressedTime = CurTime;
LastKeyPressedType = '!'; // ! Nicht genutzt, da nur Buchstaben -> symbolisiert Backspace
}
str.erase(--str.end());
return;
}
// Klein- / Großschreibung:
// Kleine Buchstaben (ab 97)
unsigned int lower_or_upper = 97;
// Großschreibung (ab 65)
if(bKeyboard[DIK_LSHIFT] || bKeyboard[DIK_RSHIFT])
{
lower_or_upper = 65;
}
// Array überprüfen, ob 'passende' Taste gedrückt
for(int i = 0; i < 26; i++)
{
if(bKeyboard[Keys[i]] && laenge < max_len) // true: Änder den string
{
char temp = static_cast<char>(i + lower_or_upper);
if(LastKeyPressedType == temp && (CurTime - LastKeyPressedTime) < 100)
return;
else
{
LastKeyPressedTime = CurTime;
LastKeyPressedType = temp;
}
str += temp;
return;
}
}
// Ansonsten String ohne Änderrungen
return;
} |
Naja bin immer für Tipps und Kritik offen _________________ "A programmer started to cuss, Because getting to sleep was a fuss, As he lay there in bed, Looping 'round in his head, was: while(!asleep()) sheep++;", Unbekannt |
|
Nach oben |
|
|
KI JLI Master
Alter: 39 Anmeldedatum: 04.07.2003 Beiträge: 965 Wohnort: Aachen Medaillen: Keine
|
Verfasst am: 10.06.2007, 00:30 Titel: |
|
|
edit: oh. das hast du schon gerade angepasst sehe ich...
Du könntest die Funktion von 51m0n noch so erweitern, dass du folgende Membervariablen hast:
CPP: | // Zeit des letzten akzeptierten Tastendrucks
unsigned long LastTimeKeyPressed;
// Letzte Taste
char LastKeyPressed;
|
Und dann wieder in der Funktion:
CPP: | CurTime = timeGetTime();
// Tastendruck akzeptieren wenn genug Zeit seit dem letzten Tastendruck vergangen ist
// oder wenn eine andere Taste gedrückt wurde als zuletzt
if((CurTime - LastKeyPressed > 1000) || LastKeyPressed != CurrentKey)
{
// es ist genug zeit seit dem letzten tastendruck vergangen
// aktualisiere die Variable "LastTimeKeyPressed" (wichtig!)
LastTimeKeyPressed = CurTime;
}
|
Bei Windows ist es ja so, dass alle gedrückten Tasten in eine Warteschleife kommen und selbst wenn der Computer kurz hängt werden die Buchstaben (oder Tasten) nachträglich abgearbeitet.
DirectInput ist aber darauf ausgelegt sofort auf Tasteneingaben reagieren zu können. Die Tasten kommen hier in keine Warteschleife (soweit ich weiß).
Von der Windows Texteingabe ist man es außerdem noch gewöhnt, dass ein durchgehender Tastendruck von ca. einer Sekunde dazu führt, dass ab dann Buchstaben in einem Intervall von ca. 50 ms akzeptiert werden.
Also ich meine sowas hier:
Ich drücke und halte die A-Taste und inder Eingabe erscheint ein "a".
Nach einer Sekunde kommen weitere as in kurzen Abständen, so dass nach 2 Sekunden bereits "aaaaaaaaaaaaaaaaaaaaaaaaaaaa" in meiner Eingabe steht. Die Methode von oben kann man mit wenig Aufwand entprechend anpassen damit auch das smiluliert wird... |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 10.06.2007, 00:46 Titel: |
|
|
Ok nochmals zum Keyrepeat, was passiert wenn ich ganz oft hintereinander die gleiche Taste drücke, also zB "A", das würde immer noch die eingabe verweigern.
Kannst du ermitteln ob eine taste NICHT mehr gedrückt wird, also wenn damit aufgehört wird? Ansonsten wäre diese Sache nie ganz fertig.
Ansonsten solltest du deine Funktion etwas weiter unterteilen.
Hier ein Vorschlag:
CPP: | void CDirectInput::ProcessKeyboardInput(string& str, bool* NewKeyMap, int max_len)
{
unsigned long CurTime = timeGetTime();
// Check if an keystate has changed
bool ChangedKey = false;
for(int i=0; i<255; ++i)
{
ChangedKey = NewKeyMap[i]==OldKeyMap[i] ? ChangedKey : true;
OldKeyMap[i] = NewKeyMap[i];
}
// If so, reset repeat timer
if (ChangedKey)
LastKeyPressedTime = CurTime;
// abort if the time is not right
if ((CurTime - LastKeyPressedTime) < KeyRepeatTime)
return;
// remove last char when user pressed backspace
if (NewKeyMap[DIK_BACKSPACE] && str.length()>0)
{
str.erase(--str.end());
return;
}
// process lower or uppercase
unsigned int KeyOffset = 97;
if(NewKeyMap[DIK_LSHIFT] || NewKeyMap[DIK_RSHIFT])
KeyOffset = 65;
for(int i = 0; i < 26; i++)
{
if(NewKeyMap[Keys[i]] && str.length() < max_len)
{
str += static_cast<char>(i+KeyOffset);
return;
}
}
} |
CPP: | void CDirectInput::getKeyboardInput(string& str, int max_len)
{
int laenge = str.length(); // Stringlänge
// alle Tasten der Tastatur
bool bKeyboard[256];
if(FAILED(m_lpDIDevice->GetDeviceState(sizeof(bKeyboard),(LPVOID)&bKeyboard)))
{
// Kontrolle wiederholen, falls verloren
m_lpDIDevice->Acquire();
return;
}
this->ProcessKeyboardInput(str, bKeyboard, max_len);
} |
_________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
Otscho Super JLI'ler
Alter: 36 Anmeldedatum: 31.08.2006 Beiträge: 338 Wohnort: Gummibären-Gasse Medaillen: Keine
|
Verfasst am: 10.06.2007, 09:46 Titel: |
|
|
KI hat Folgendes geschrieben: |
Von der Windows Texteingabe ist man es außerdem noch gewöhnt, dass ein durchgehender Tastendruck von ca. einer Sekunde dazu führt, dass ab dann Buchstaben in einem Intervall von ca. 50 ms akzeptiert werden.
Also ich meine sowas hier: |
Jo das kann man in der Systemsteuerung einstellen: Verzögerung und Wiederholrate. Da gibt es doch bestimmt ne Funktion, mit der man die eingesellten Werte auslesen kann. Wenn du das noch in dein Programm reinfügst und alles klappt, dann bist du ein Freak |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|