PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : DirectX Einstieg


che g
2003-08-02, 12:09:44
Naja, man kommt eben nicht drumherum...Und solange man nur DirectInput benutzt hat man sich ja noch nicht der dunklen Seite der Macht ergeben ;)

Nur wo kriegt man die passenden Header her? Die mit VC++ 6.0 mitgelieferten sind offenbar veraltet, denn der Versuch ein LPDIRECTINPUT8 Objekt zu deklarieren produziert einen Error. Auf der Microsoft Homepage steht nur Developers mögen doch bitte das SDK installieren, ich hab aberr keine Lust 150MB zu laden.

Wenn ich nur DInput nutzen will dann reicht doch wohl der DInput-Header, da brauch ich doch nicht das ganze SDK. Mit Google hab ich auch nix gefunden...

Demirug
2003-08-02, 12:19:53
Das kleinste Packet gibt es dort http://www.microsoft.com/downloads/details.aspx?FamilyId=BC7DDEDD-AF62-493D-8055-5E57BAB71E1A&displaylang=en

ist aber immer noch 100 MB gross.

Nur mit dem Header und den Libs würde ich persönlich aber nicht entwickeln wollen. Die Beispiele und die Dokumenatation sind teilweise schon recht nützlich. Und die Debug-Runtime (nicht in dem 100 MB Packet enthalten) möchte ich nicht mehr missen.

che g
2003-08-02, 12:37:40
100MB? :abgel:

Dokumentation und Beispiele habe ich in der MSDN hier. Oder unterscheidet sich das SDK davon?
Was ist die Debug-Runtime?

Außerdem: das was ich hier betreibe kann man ja nicht entwickeln nennen ;)


btw. Sehe ich das richtig dass wenn eine neue Version von DX rauskommt man wieder das ganze SDK neu runterladen muss?
--->Micro$oft:rail:<---che

Demirug
2003-08-02, 12:59:30
Original geschrieben von che g
100MB? :abgel:

Dokumentation und Beispiele habe ich in der MSDN hier. Oder unterscheidet sich das SDK davon?

Das hängt davon ab welches welches Datum dein MSDN hat. Die im SDK ist die aktuellste. Höchstens die im Online-MSDN kann noch aktueller sein.

Was ist die Debug-Runtime?

Das ist eine Spezialversion der Runtime die wesentlich genauer prüft und wenn man Fehler macht diese als Text in der Debugausgabe anzeigt.

Außerdem: das was ich hier betreibe kann man ja nicht entwickeln nennen ;)

Das must du wissen.

btw. Sehe ich das richtig dass wenn eine neue Version von DX rauskommt man wieder das ganze SDK neu runterladen muss?
--->Micro$oft:rail:<---che

Ja es gibt ja neue Dokumenation, Beispiele, Verbeserungen an den Debugruntimes, ...

Da ich auch noch alle Betas herunterladen mache ich das in schönen unregelmässigen Abständen.

che g
2003-08-02, 13:54:50
Original geschrieben von Demirug
Das hängt davon ab welches welches Datum dein MSDN hat. Die im SDK ist die aktuellste. Höchstens die im Online-MSDN kann noch aktueller sein.

Juli 2001. DX 8. Reicht mir. :)


Das ist eine Spezialversion der Runtime die wesentlich genauer prüft und wenn man Fehler macht diese als Text in der Debugausgabe anzeigt.

Das wäre natürlich praktisch.

Das must du wissen.

"Entwickeln" klingt so ernst. Wo bleibt denn da der Spass am Programmieren?


Ja es gibt ja neue Dokumenation, Beispiele, Verbeserungen an den Debugruntimes, ...

Da ich auch noch alle Betas herunterladen mache ich das in schönen unregelmässigen Abständen.
Eieiei. Mich würde wirklich interessieren wofür dieser ganze Aufwand gut ist. *hint* ;)


Wie ich das sehe hilft also alles nix - SDK ich komme...*Modemanschmeiß*

Ach ja: Danke für die schnelle Hilfe.

Demirug
2003-08-02, 14:30:03
Original geschrieben von che g

Eieiei. Mich würde wirklich interessieren wofür dieser ganze Aufwand gut ist. *hint* ;)[/SIZE]

Wenn man nicht wenigstens ein bischen die Betas testet schmeisen die einen wieder aus dem Beta-Programm raus und ich bevorzuge es frühzeitig über Veränderungen informiert zu sein.

Ich habe ja eine Flatrate da kann man die Betas auch über Nacht ziehen ist also gar nicht so wild.

che g
2003-08-02, 20:14:34
So, das SDK hab ich. Bei der Installation wurden anscheinend auch schon irgendwelche Pfade in VC++6.0 gesetzt, denn #include <dinput.h>
sucht automatisch in
e:\programme\dxsdk\include\dinput.h
anstatt im VC++ Programmverzeichnis.

Und die ersten Probleme hab ich auch schon:)
1.
DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800
2. Wie heißen die Libs zu denen ich linken muss?

MfG

btw. Gar nicht schlecht, das SDK, nützliche Tools dabei..

Demirug
2003-08-02, 20:41:10
Original geschrieben von che g
So, das SDK hab ich. Bei der Installation wurden anscheinend auch schon irgendwelche Pfade in VC++6.0 gesetzt, denn #include <dinput.h>
sucht automatisch in
e:\programme\dxsdk\include\dinput.h
anstatt im VC++ Programmverzeichnis.

Und die ersten Probleme hab ich auch schon:)
1.
DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800
2. Wie heißen die Libs zu denen ich linken muss?

MfG

btw. Gar nicht schlecht, das SDK, nützliche Tools dabei..

1. Das passt schon. Wenn es dich allerdings stört und du es weghaben möchtest musst du vor dem #include <dinput.h> einfach #define DIRECTINPUT_VERSION 0x0800 einfügen.

2. Dinput8.lib

che g
2003-08-02, 22:07:18
Hm, dinput.h #inkludiert, zu dinput.lib gelinkt und trotzdem:
inputhandler.obj : error LNK2001: unresolved external symbol _IID_IDirectInput8A
Ich übergebe aber ganz was anderes nämlich
IID_IDirectInput8Also ins SDK geschaut ;) und was finde ich da:

Unique identifier of the desired interface. This value is IID_IDirectInput8A or IID_IDirectInput8W. Passing the IID_IDirectInput8 define selects the ANSI or Unicode version of the interface, depending on whether UNICODE is defined during compilation.

In den Header geschaut (kann nie schaden) und was finde ich dort:

#ifdef UNICODE
#define IID_IDirectInput8 IID_IDirectInput8W
#else
#define IID_IDirectInput8 IID_IDirectInput8A

Man beachte dass KEINES dieser #defines mit einem Underline (_) beginnt, der Compiler sich aber über ein nicht aufgelöstes External MIT Underline aufregt.

Demi...?

Demirug
2003-08-02, 22:10:58
Link mal noch dxguid.lib dazu. Das Problem läst sich zwar auch anders lösen aber das ist der schnellste weg.

che g
2003-08-02, 22:26:05
Wie macht er das bloß?
Ich suche im SDK die Funktion, versuche verzweifelt daraus schlau zu werden, suche den ganzen Header durch (4400 Zeilen!), finde die #defines um die es geht, frage mich wo das Underline herkommt weil im #define steht nix davon, frage mich wieso und überhaupt...Und dann kommt er und sagt "Link mal eben noch dxguid dazu" und alles läuft!

:respekt: Demi schafft sie alle :flower:

An was für einem Projekt arbeitet wohl so einer *hinthint* (Nachdem das erste mal danebenging...;))

Demirug
2003-08-02, 22:29:33
Erfahrung. Ich bin schon so lange im DX Geschäft da kennt man die üblichen Probleme warum sich etwas nicht compilieren oder linken läst und wenn ich es gerade nicht im Kopf hat weiss ich wo ich suchen muss.

che g
2003-08-03, 20:05:10
Hola!

Ich werfe gleich mal etwas Code ins Spielvoid CInputHandler::Update(void)
{
HRESULT hr;

hr = this-> DI_Device->GetDeviceState(sizeof(this->KeyboardBuffer), this->KeyboardBuffer);
if FAILED(hr)
DIEXCEPTION("Couldn't get Keyboard state.", EX_ERROR, hr);
}

bool CInputHandler::KeyDown(const int key)
{
if (this->KeyboardBuffer[key] & 0x80)
return true;

return false;
}



In der Main Loop steht das hier:
InputHandler.Update();
if (InputHandler.KeyDown(DIK_DOWN))
MessageBox(NULL,"down","i",MB_OK);

Ich starte also das Programm und alles läuft. Drück ich "runter", schmeißt er mir einen Runtime Error um die Ohren.
Zuerst hatte ich in der Update() Funktion noch kein Errorcheck, da blieb der RuntimeError aus, dafür kamen am laufenden Band MessageBoxes ich hätte runter gedrückt, auch als ich die Taste schon längst losgelassen hatte. ???

Ich hab auch den KeyboardBuffer unter die Lupe genommen: Ich drücke keine Taste, alle Elemente sind brav auf 0. Ich drücke runter, das 208. Element (aus dinput.h: #define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */) steht auf -128 - müsste das nicht plus sein? Egal, weiter mit F5. Und ab jetzt ist im KeyboarBuffer die Hölle los: Alle Elemente haben irgendwelche Werte, ausgenommen das 208. , das bleibt auf -128. Sollte ein neuer Aufruf von GetDeviceState() nicht den neuen aktuellen Keyboardstatus zurückgeben?

???

Demirug
2003-08-03, 20:23:01
Welchen Fehlercode bekommst du den genau?

Ich würde das Array this->KeyboardBuffer im Fehlerfall komplett löchen da man sich nie sicher sein kann was da nach einem fehlgeschlagenden Aufruf drin steht.

Benutzt du die Debug-Runtime?

Beim Debugen verhält sich Direct Input gerne merkwürdig dafür gibt es die möglichkeit eine Keyboard emulation zu benutzten.

che g
2003-08-04, 06:17:15
Das ist es ja: Ich bekomme überhaupt keinen Fehlercode, wenn ich das Ergebnis mit HREWSULT überprüfe, gibts einen Runtime Error. Lasse ich das mit dme HRESULT weg, läufts.

Wie weißß ich ob ich die Debug Runtime benutze?

che g
2003-08-04, 06:17:56
p.s: Guten Morgen :)

Demirug
2003-08-04, 07:26:18
Original geschrieben von che g
Das ist es ja: Ich bekomme überhaupt keinen Fehlercode, wenn ich das Ergebnis mit HREWSULT überprüfe, gibts einen Runtime Error. Lasse ich das mit dme HRESULT weg, läufts.

Wie weißß ich ob ich die Debug Runtime benutze?

Das es dich beim Fehler raushaut ist klar du hast da ja auch eine Exception im Code. Da müsste aber irgendwie eine Meldung sein welche den Fehlercode enthält.

Die Debug-Runtime kann man über das DX-Panel aktivieren:

Tom Servo
2003-08-04, 12:16:02
Original geschrieben von che g
Man beachte dass KEINES dieser #defines mit einem Underline (_) beginnt, der Compiler sich aber über ein nicht aufgelöstes External MIT Underline aufregt.


Der Fehler kommt übrigens nicht vom Compiler sondern vom Linker.

Das mit dem Unterstrich liegt daran, dass die im C Quelltext definierten Namen vom Compiler einen Unterstrich davorgesetzt bekommen (eine Art Namensbereich). Der Linker sieht nur diese veränderten Namen.


Dazu kommt dann, dass in C der Typbezeichner "int" auch weggelassen werden darf. Man darf also z.B. "int n" zu "n" abkürzen. War m.E. eine der weniger guten Ideen in C.

Normalerweise hätte der Preprozessor das Makro durch z.B. ein Literal ersetzt und der Compiler hätte den Makro-Namen nie zu Gesicht bekommen. Nur hattest du den Header nicht includiert wo der Name als Makro definiert wird.

Am Ende bekommst du dann einen Linker Error obwohl der Fehler eigentlich ein undefiniertes Makro war. Typisch C eben :-/.



int_variable = 1;

int_function()
{
return 1;
}


Wird compiliert zu folgendem Assembler:



.file "test7.c"
.globl _int_variable
.data
.align 4
_int_variable:
.long 1
.text
.align 2
.globl _int_function
.def _int_function; .scl 2; .type 32; .endef
_int_function:
pushl %ebp
movl %esp, %ebp
movl $1, %eax
popl %ebp
ret


In C++ wurde das implizite int aber irgendwann abgeschafft. Hängt sicher vom Compiler oder dessen Einstellungen ab, ob der sowas noch akzeptiert und dadurch dann ziemlich unverständliche Fehlermeldungen produziert.

che g
2003-08-04, 15:56:00
Ich habe mich unklar ausgedrückt: Es liegt nicht an der Exception das ich rausfliege, es ist ein andere Fehler:

Ich starte das Programm. Das Programm läuft. Ich drücke runter, bekomme eine MessageBox die bestätigt, dass ich runter gedrückt habe. Ich klicke die MessageBox weg und habe folgendes: Ein Fenster der "Microsoft Visual C++ Runtime Library" in dem steht
"Runtime Error!

Program: <Programmname>

abnormal program termination"

Dasselbe nochmal, nur starte ich nicht über "Execute program" (Ctrl+F5) sondern über "Go" (F5)
Das gleiche, nur sagt das Fenster jetzt:

"Unhandled Exeption in Terrain.exe(Kernel32.dll): 0xe06d7363: Microsoft C++ Exception."

Deshalb weiß ich auch nichts über den Fehlercode, soweit komme ich garnicht.

che g
2003-08-04, 15:57:42
@Tom Servo:
Danke für die ausführliche Erklärung. :up:
Leider habe ich nur die Hälfte verstanden :D

che g
2003-08-06, 19:59:09
Der Fehler scheint beim Aufruf von GetDevicestate() zu liegen: hr = this-> DI_Device->GetDeviceState(sizeof(this->KeyboardBuffer), this->KeyboardBuffer);
if FAILED(hr)
MessageBox(NULL,"x","x",MB_OK);
//DIEXCEPTION("Couldn't get Keyboard state.", EX_ERROR, hr);

Mit diesem Code bekomme ich die MessageBox angezeigt. Werfe ich die Exception fliege ich raus, aber NICHT aufgrund der Exception. Zur Exception-Handling Routine komme ich garnicht, die würde nämlich eine schöne MessageBox mit Informationen über den Error usw. ausgeben, ich habe aber einen allgemeinen Error. (s. vorletztes Posting)

Vermutlich stimmt mit dem HRESULT etwas nicht und DXGetErrorDescription9() in der Exception Handling Routine produziert dann einen Fehler.
Ich habe auch einen Breakpoint in der MessageBox-Zeile gesetzt: hr hatte den Wert -2147024866.

???Was ist denn da los?

Demirug
2003-08-06, 20:05:10
Hast du den ErrorCode auch als Hey-Zahl? Ich bin zu faul zum Umrechnen zu heiss hier.

In dInput.h sind die Fehlercodes alle enthalten aber eben als Hexzahl koddiert.

che g
2003-08-06, 20:13:25
Der Windows-Rechner hat Probleme beim umrechnen von negativen DezZahlen in Hex...

Demirug
2003-08-06, 20:15:02
Original geschrieben von che g
Der Windows-Rechner hat Probleme beim umrechnen von negativen DezZahlen in Hex...

Welchen Compiler/Debugger hast du denn? Der vom Visual C++ läst sich umschalten das er Werte als Hex anzeigt.

Tom Servo
2003-08-06, 22:04:01
(gdb) printf "0x%x\n", -2147024866
0x8007001e
(gdb)

Hoffe die Hex-Zahl stimmt.

Xmas
2003-08-06, 22:46:32
Original geschrieben von Tom Servo
(gdb) printf "0x%x\n", -2147024866
0x8007001e
(gdb)

Hoffe die Hex-Zahl stimmt.
Es handelt sich um diesen hier:

/*
* Access to the device has been lost. It must be re-acquired.
*/
#define DIERR_INPUTLOST \
MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT)

Antwort von der VS-Fehlersuche:
"Das System kann nicht vom angegebenen Gerät lesen."

che g
2003-08-07, 07:03:40
Danke euch allen :)

Jetzt frage ich mich aber wieso dieser Error nicht von meiner Exception verarbeitet wird...Wenn das ein gültiger HRWSULT Wert ist sollte es doch keine Probleme geben

Xmas
2003-08-07, 19:19:51
Wo bitte ist denn DIEXCEPTION definiert?

che g
2003-08-08, 06:09:17
Das ist ein Makro um eine selbstgeschriebene Exception zu werfen.

Xmas
2003-08-08, 18:47:09
Original geschrieben von che g
Das ist ein Makro um eine selbstgeschriebene Exception zu werfen.
Könntest du dazu mal den Code posten?

che g
2003-08-08, 20:22:11
Aber latürnich :)



void DirectInputException::GenerateText(void)
{
char error[512];
char *dxerrname = (char *)DXGetErrorString9(this->hr);
char *dxerrdescription = (char *)DXGetErrorDescription9(this->hr);

sprintf(error, "The DirectInput-System caused an Exception in %s, Line %i\n\n"
"Error Message: %s\nErrorCode: %s\nErrorDescription: "
"%s", this->FileName, this->Line, this->Message, dxerrname,
dxerrdescription);

strcpy(this->Message, error);
}

void DirectInputException::Display(void)
{

this->GenerateText();

unsigned int icon=0;

if(EX_WARNING == this->Type)
icon = MB_ICONWARNING;
else if (EX_ERROR == this->Type)
icon = MB_ICONHAND;

MessageBox(NULL, this->Message, "DirectInput-System Exception", MB_OK | icon);
}

und dann noch:
#define DIEXCEPTION(errormessage, type, code) throw DirectInputException(errormessage, type, code, __FILE__, __LINE__)

Demirug
2003-08-08, 20:42:55
Setze doch einfach mal Breakpoints in die Methode deiner Exception Klasse und schaue mal wie weit er kommt.

Tom Servo
2003-08-08, 21:01:04
Original geschrieben von che g

void DirectInputException::GenerateText(void)
{
char error[512];

sprintf(error, "The DirectInput-System caused an Exception in %s, Line %i\n\n"
"Error Message: %s\nErrorCode: %s\nErrorDescription: "
"%s", this->FileName, this->Line, this->Message, dxerrname,
dxerrdescription);

strcpy(this->Message, error);
}



Mir kommt der Code ein wenig komisch vor: Du hast offenbar genug Platz in this->Message weil du ja den Errorstring dorthin kopierst, aber du benutzt error als Buffer obwohl du dann auch direkt nach this->Message formatieren könntest. Vielleicht wolltest du ursprünglich noch Speicher für this->Message besorgen:

this->Message = strcpy(new char[strlen(error)+1], error);

Naja, nur so eine Idee.

che g
2003-08-08, 21:13:27
Original geschrieben von Demirug
Setze doch einfach mal Breakpoints in die Methode deiner Exception Klasse und schaue mal wie weit er kommt.

Breakpoint in dieser Zeile:
char *dxerrname = (char *)DXGetErrorString9(this->hr);

Dasselbe Ergebnis.

@Tom Servo:
Aus der Deklaration von CBaseException

protected:
char Message[512];

che g
2003-08-08, 21:32:59
Nachtrag:

Ich lass die ganze Sache und fahr jetzt übers Wochenende an den See :)
Nachher schaumer weiter.

Wie kann es eigentlich sein dass man den Device verliert und re-acquiren muss?

che g
2003-08-14, 16:59:34
So, da bin ich wieder:)

Neue Lage:
Um zu testen welche Taste gedrückt wurde verwendete ich bisher das hier
if (InputHandler.KeyDown(DIK_DOWN))
MessageBox(NULL,"test","i",MB_OK);


Diese Zeilen geändert in
if (InputHandler.KeyDown(DIK_DOWN))
rot +=0.1f;
else
rot -=0.1f;

schwuppdiwupp, alles läuft!

Den ursprünglichen Code (mit der MessageBox) habe ich auch zum Laufen gebracht indem ich folgendes in die InputHandler-Update Routine eingefügt habe:
hr = this-> DI_Device->GetDeviceState(sizeof(this->KeyboardBuffer), this->KeyboardBuffer);
if FAILED(hr)
this-> DI_Device->Acquire();


Jedesmal war ein reacquire nötig!
Wenn ich keine messageBox anzeige ist auch das reacquire nicht nötig! Kann mir irgendjemand erklären was da los ist? Was macht die MessageBox im Hintergrund dass der InputFocus verloren geht?

MfG

Demirug
2003-08-14, 17:09:49
Original geschrieben von che g

Jedesmal war ein reacquire nötig!
Wenn ich keine messageBox anzeige ist auch das reacquire nicht nötig! Kann mir irgendjemand erklären was da los ist? Was macht die MessageBox im Hintergrund dass der InputFocus verloren geht?

MfG

Sie nimmt deinem Fenster den Focus weg und mit dem Focus gehen auch alle Geräte verloren. Deswegen habe ich ja gesagt das man zum Debuggen am besten die Emulation einschaltet.

che g
2003-08-14, 17:15:15
Aha!

1. Was genau ist der Focus? Wie kann ich ihn kontrollieren? (Gibts sowas wie Get() und Release()?)
2. Wenn ich die MessageBox wegklicke dann habe ich ja den Focus wieder. Und solange sie das ist wird das Programm eh nicht ausgeführt, warum also der Fehler?
3. Emulation? Wo einschalten? Vermutlich übers DXControlPanel -> wo finde ich das?

MfG

Demirug
2003-08-14, 20:08:30
Original geschrieben von che g
Aha!

1. Was genau ist der Focus? Wie kann ich ihn kontrollieren? (Gibts sowas wie Get() und Release()?)
2. Wenn ich die MessageBox wegklicke dann habe ich ja den Focus wieder. Und solange sie das ist wird das Programm eh nicht ausgeführt, warum also der Fehler?
3. Emulation? Wo einschalten? Vermutlich übers DXControlPanel -> wo finde ich das?

MfG

1. Den Focus hat immer das gerade aktive Fenster. Ja es gibt eine SetFocus und eine GetFocus Funktion nur darf die Windows jederzeit den Focus wegnehmen.

2. Ja weil die Messagebox den Focus wieder an das Fenster zurückgibt von dem sie in weggenommen hat. Für den Fehler reicht es das du den Focus verloren hast und dein Programm ist weitergelaufen des es hat ja zum Beispiel alle Nachrichten die für die Messagebox bestimmt waren verarbeitet.

3. Im DirectX Kontroll Panel gibt es auch der Direct Input Seite unten eine "Debug Input Device Emulation" in der Dokumentation steht drin wie es genau funktioniert.

che g
2003-08-14, 21:14:04
Wenn ich also etwas in der Art realisieren will
if(SC_MINIMIZE == wParam)
{
WindowSystem.setState(SW_MINIMIZE);
WindowSystem.Active = false;
break;

}
if(SC_RESTORE == wParam)
{
WindowSystem.setState(SW_RESTORE);
WindowSystem.Active = true;
break;
}
In der MessageLoop wird dann auf Active geprüft und das Programm ausgeführt oder WaitMessage() aufgerufen

dann muss ich
1. In der Winproc alle Nachrichten abfangen die dazu führen dass mein Fenster den Focus verliert
2. Das Fenster verstecken/minimieren usw. (je nach Nachricht)
3. Dem DirectInput System mitteilen dass jetzt nix zu tun ist. (Reicht dafür ein Unacquire()/Acquire()?)

che g
2003-08-14, 21:15:06
Wo finde ich das DX Control Panel? Im SDK find ich nix, bei den Tools ist auch nichts dabei, wo kann denn das nur sein?

Demirug
2003-08-14, 21:16:16
Es sollte in der Systemsteuerung sein.

che g
2003-08-14, 21:25:09
Original geschrieben von Demirug
Es sollte in der Systemsteuerung sein.
:bonk: wo denn sonst ;)