Sie sind auf Seite 1von 639

directX mit visual basic programmieren

praxis und referenz

uwe kettermann christian schmelzer

new technology
Markt+Technik Verlag

Die Deutsche Bibliothek CIP-Einheitsaufnahme Ein Titeldatensatz fr diese Publikation ist bei Der Deutschen Bibliothek erhltlich. Die Informationen in diesem Produkt werden ohne Rcksicht auf einen eventuellen Patentschutz verffentlicht. Warennamen werden ohne Gewhrleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit grter Sorgfalt vorgegangen. Trotzdem knnen Fehler nicht vollstndig ausgeschlossen werden. Verlag, Herausgeber und Autoren knnen fr fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung bernehmen. Fr Verbesserungsvorschlge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar.

Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulssig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwhnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt. Die Einschrumpffolie zum Schmutz vor Verschmutzung ist aus umweltvertrglichem und recyclingfhigem PE-Material.

10 9 8 7 6 5 4 3 2 1 03 02 01 00

ISBN 3-8272-5766-2

2000 by Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH, Martin-Kollar-Strae 1012, D 81829 Mnchen/Germany Alle Rechte vorbehalten Lektorat: Erik Franz, efranz@pearson.de Herstellung: Ulrike Hempel, uhempel@pearson.de Satz: reemers publishing services gmbh, Krefeld Druck und Verarbeitung: Bercker, Kevelaer Printed in Germany

Inhaltsverzeichnis
Kapitel 1 DirectDraw 1.1 DirectDraw-Grundlagen 1.1.1 Der Aufbau von DirectDraw 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 Kapitel 2 Blitting Sprites durch Transparenz Fullscreen Fullscreen und Spriteanimation Hintergrund-Scrolling Spritekollision Bienenjagd Methoden zum Zeichnen Cooperative Level Display Mode Colorkey Surface Palette Clipper Blitting Page Flipping 17 22 22 25 26 29 30 38 39 40 41 42 51 65 72 75 78 88 93 101 104 105 106 118 120 122 122 123 130

Direct3D 2.1 2.2 2.3 2.4 2.5 2.6 3D-Koordinatensystem 3D-Primitives Zeichnen eines Dreiecks Dreieck-Raster-Regeln World-, View- und Projection-Matrix Matrix-Berechnungen 2.6.1 2.6.2 2.6.3 Translation Rotation Scaling

Inhaltsverzeichnis

2.7 2.8

Polygone Licht 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 Indirektes Licht (Ambientlight) Direktes Licht Licht, Schatten und Polygone Licht aktivieren / deaktivieren Beispiel (Licht) Setzen von Material Beispiel (Material)

132 137 139 139 146 148 151 157 159 161 165 166 170 184 201 212 218 225 225 236 240 246 253 254 257 258 259 259 260 262 268 272 279

2.9

Material 2.9.1 2.9.2

2.10

Texturen 2.10.1 Beispiel (Textur 1) 2.10.2 Textur-Koordinaten 2.10.3 Texture Filtering 2.10.4 Texture Blending

2.11 2.12 2.13

Z-Buffer (Tiefenspeicher) Die SetRenderState()-Methode Effekte 2.13.1 Nebel 2.13.2 Billboarding 2.13.3 Feuer und Explosionen 2.13.4 Antialiasing

Kapitel 3

DirectInput 3.1 3.2 3.3 Objekthierarchie Cooperative Level Datenformat 3.3.1 Standard-Datenformat 3.3.2 3.4 3.5 3.6 3.7 3.8 Benutzerdefiniertes Datenformat Beispiel: Tastatur Beispiel: Joystick Beispiel: Maus Beispiel: DirectInput und Direct3D Bewegung im 3D-Raum

Inhaltsverzeichnis

Kapitel 4

DirectSound 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 DirectSound-Architektur Datenformat HAL und HEL Systemintegration Initialisieren von DirectSound Erstellen des DirectSound-Objektes Buffer-Grundlagen Primary Soundbuffer Static und Streaming Soundbuffer Erzeugen von Soundbuffern Buffer-Einstellungen Buffer Playback Controls Ein einfaches Soundbeispiel Der PlayCursor Playbuffer-Benachrichtigungen Direct3DSound 4.16.1 Grundlagen 4.16.2 Mono- und Stereo-Soundquellen 4.17 DirectSound3DBuffer 4.17.1 Parameter-Manipulation 4.17.2 Entfernungen 4.17.3 Auswhlen von Schallquellen 4.17.4 Operation Mode 4.17.5 Position 4.17.6 Soundprojektion und -ausrichtung 4.17.7 Geschwindigkeit 4.18 DirectSound3DListener 4.18.1 Parameter-Manipulation 4.18.2 Verzgerungseinstellungen 4.18.3 Entfernungsfaktoren 4.18.4 Dopplerfaktoren 4.18.5 Auswahlmglichkeiten 4.18.6 Ausrichtung

283 285 285 286 286 287 288 290 291 291 292 294 294 296 299 301 301 302 303 304 305 307 308 309 310 311 314 315 316 317 317 317 318 318

Inhaltsverzeichnis

4.18.7 Position 4.18.8 Abschwchung 4.18.9 Geschwindigkeit 4.18.10 Beispiel (Klangquellen im 3D-Raum) 4.19 DirectSound Capture 4.19.1 Erstellen eines Capturebuffers 4.19.2 Erluterung zur Aufnahme Kapitel 5 DirectPlay 5.1 5.2 5.3 DirectPlay-Basis Beispiel (Chatsystem) Kommunikationsmodelle 5.3.1 Peer-to-Peer-Session 5.3.2 5.4 5.5 5.6 5.7 Lobbies Service Provider Sicherheit Nachrichten 5.7.1 Nachrichten empfangen 5.7.2 5.8 5.9 5.10 5.11 5.12 Anhang A Synchronisation DirectPlay-Adresse DirectPlay-Protokoll Session Spieler Bienenjagd Multiplayer Demo Client/Server-Session

320 320 322 323 328 328 330 337 341 352 355 355 356 357 358 358 359 360 363 363 364 365 369 372 377 378 390 390 400 402 403 404

Methoden A.1 A.2 Globale DirectX7-Methoden DirectDraw-Methoden A.2.1 A.2.2 A.2.3 A.2.4 A.2.5 DirectDraw7 DirectDrawClipper DirectDrawColorControl DirectDrawEnum DirectDrawEnumModes

Inhaltsverzeichnis

A.2.6 A.2.7 A.2.8 A.2.9 A.3

DirectDrawEnumSurfaces DirectDrawGammaControl DirectDrawIdentifier DirectDrawPalette

405 406 406 409 410 430 430 432 452 453 454 457 457 460 466 472 478 479 482 483 483 484 494 496 499 501 502 503 505 505 524 526 527

A.2.10 DirectDrawSurface7 Direct3D-Methoden A.3.1 Direct3D7 A.3.2 A.3.3 A.3.4 A.3.5 A.4 A.4.1 A.4.2 A.4.3 A.4.4 A.4.5 A.4.6 A.4.7 A.5 Direct3DDevice7 Direct3DEnumDevices Direct3DEnumPixelFormats Direct3DVertexBuffer7 DirectSound DirectSound3DBuffer DirectSound3DListener DirectSoundBuffer DirectSoundCapture DirectSoundCaptureBuffer DirectSoundEnum

DirectSound-Methoden

DirectInput A.5.1 DirectInput A.5.2 A.5.3 A.5.4 A.5.5 A.5.6 A.5.7 A.5.8 DirectInputDevice DirectInputDeviceInstance DirectInputDeviceObjectInstance DirectInputEffect DirectInputEnumDeviceObjects DirectInputEnumDevices DirectInputEnumEffects

A.6

DirectPlay-Methoden A.6.1 DirectPlay4-Methoden A.6.2 A.6.3 A.6.4 DirectPlayEnumConnections DirectPlayEnumLocalApplications DirectPlayEnumPlayers

10

Inhaltsverzeichnis

A.6.5 A.6.6 A.6.7 A.6.8 A.6.9 Anhang B Konstanten B.1 B.2 B.3 B.4 B.5 Anhang C Typen C.1

DirectPlayEnumSessions DirectPlayLobby3 DirectPlayLobbyConnection DirectPlayMessage DirectPlaySessionData

529 530 537 540 546 553 554 565 583 588 595 601

DirectDraw Enum Direct3DEnum DirectSoundEnum DirectInput Enum DirectPlay Enum

DirectDraw-Typen C.1.1 DDBLTFX C.1.2 C.1.3 C.1.4 C.1.5 C.1.6 C.1.7 C.1.8 C.1.9 DDCAPS DDCOLORCONTROL DDCOLORKEY DDGAMMARAMP DDOVERLAYFX DDPIXELFORMAT DDSCAPS2 DDSURFACEDESC2

602 602 602 604 604 604 604 605 605 606 606 606 607 607 607 607 608 608 609

C.1.10 PALETTEENTRY C.1.11 RECT C.2 Direct3D-Typen C.2.1 D3DCLIPSTATUS C.2.2 C.2.3 C.2.4 C.2.5 C.2.6 D3DCOLORVALUE D3DDEVICEDESC7 D3DDEVINFO_TEXTUREMANAGER D3DDEVINFO_TEXTURING D3DLIGHT7

Inhaltsverzeichnis

11

C.2.7 C.2.8 C.2.9

D3DLIGHTINGCAPS D3DLINEPATTERN D3DLVERTEX

609 609 609 610 610 610 611 611 611 611 612 612 612 612 612 613 613 613 613 614 614 615 615 615 615 615 616 616 616 616 616 617 617

C.2.10 D3DMATERIAL7 C.2.11 D3DMATRIX C.2.12 D3DPRIMCAPS C.2.13 D3DRECT C.2.14 D3DTLVERTEX C.2.15 D3DVECTOR C.2.16 D3DVERTEX C.2.17 D3DVERTEXBUFFERDESC C.2.18 D3DVIEWPORT7 C.2.19 DXDRIVERINFO C.3 DirectSound-Typen C.3.1 DS3DBUFFER C.3.2 C.3.3 C.3.4 C.3.5 C.3.6 C.3.7 C.3.8 C.3.9 DS3DLISTENER DSBCAPS DSBPOSITIONNOTIFY DSBUFFERDESC DSCAPS DSCBCAPS DSCBUFFERDESC DSCCAPS

C.3.10 DSCURSORS C.3.11 DXDRIVERINFO C.3.12 WAVEFORMATEX C.4 DirectInput-Typen C.4.1 DICONDITION C.4.2 C.4.3 C.4.4 C.4.5 C.4.6 DICONSTANTFORCE DIDATAFORMAT DIDEVCAPS DIDEVICEOBJECTDATA DIEFFECT

12

Inhaltsverzeichnis

C.4.7 C.4.8 C.4.9

DIENVELOPE DIJOYSTATE DIJOYSTATE2

617 618 618 619 619 619 619 619 620 620 620 620 620 621 621 623

C.4.10 DIKEYBOARDSTATE C.4.11 DIMOUSESTATE C.4.12 DIOBJECTDATAFORMAT C.4.13 DIPERIODICFORCE C.4.14 DIPROPLONG C.4.15 DIPROPRANGE C.4.16 DIRAMPFORCE C.5 DirectPlay-Typen C.5.1 C.5.2 C.5.3 C.5.4 Anhang D Glossar D.1 D.2 D.3 D.4 D.5 D.6 D.7 D.8 D.9 D.10 D.11 D.12 D.13 D.14 D.15 D.16 D.17 Alpha Blending Antialiasing Bilineares Filtering Bump Mapping Clipping Color Key Direct3D DirectX Dithering Double Buffer Fenster / Full-Screen Flat Shading / Gouraud Shading Fogging Hidden Surface Removal Mipmapping Overlay Planes Perspektivenkorrektur DPAPPLICATIONDESC2 DPCAPS DPCREDENTIALS DPSECURITYDESC

624 624 624 624 624 625 625 625 625 625 626 626 626 626 626 627 627

Inhaltsverzeichnis

13

D.18 D.19 D.20 D.21 D.22 D.23 D.24 D.25 D.26 D.27 D.28 Anhang E

Polygon Rendern Shading Specular Highlights Texel Texture Mapping Textur Trilineares Filtering Wireframe WRAM Z-Buffer

627 627 627 627 627 628 628 628 628 628 628 629 630 630 630 630 631 632 633 634 635

Das finden Sie auf der CD E.1 E.2 E.3 DirectX-API Magellan 3D Beispielprogramme E.3.1 DirectDraw E.3.2 E.3.3 E.3.4 E.3.5 Direct3D DirectSound DirectInput DirectPlay

Stichwortverzeichnis

Vorwort
Die Programmiersprache Visual Basic ist fr Broanwendungen wie Datenbankanwendungen oder Verwaltungsprogramme entwickelt worden. Die Anhnger dieser Sprache suchen vergeblich nach leistungsstarken Multimediakomponenten. Diese werden aber von einer modernen Anwendung erwartet. So ist es kein Wunder, dass gerade grafisch anspruchsvolle Anwendungen in Hochsprachen wie C++ erstellt werden. Dieser Missstand wurde mit der Einfhrung von DirectX fr Visual Basic im September 1999 aufgelst. Mit dieser Schnittstelle dringt der VB-Programmierer in die letzte Nische der klassischen Hochsprachen vor. Obwohl Visual Basic nach wie vor eine Interpretersprache ist, sind die Anwendungsgrenzen nicht mehr so deutlich abgesteckt, wie sie es vor DirectX waren. Ihnen als Programmierer wird nicht oft die Chance geboten, von Anfang an in eine Technologie einzusteigen. DirectX ist natrlich nicht neu, dem VB-Programmierer steht sie jedoch erstmalig zur Verfgung. Die Einbindung der DirectX-API lutet den Beginn einer aufregenden Zeit ein. Der Traum von aufwendigen Mulimedia-Anwendungen ist nun Realitt geworden. Obwohl wir versierte C++ Programmierer sind, hat sich das Traumpaar Visual Basic und DirectX einen sicheren Weg in unser Herz erobert. Das liegt zum einen an der zeitsparenden Entwicklung im VB-Umfeld und zum anderen an der robusten und schnellen DirectX Implementierung. Alle Komponenten von DirectX sind ausgezeichnet umgesetzt worden. DirectDraw sorgt fr eine schnelle und trickreiche Umsetzung von 2D-Grafiken. Die Anforderungen an 3D-Grafiken werden von Direct3D auerordentlich gut bernommen. Die dreidimensionale Darstellung ist in einer modernen Multimediaanwendung zu einem Pflichtteil geworden. Dies gilt insbesondere fr Spiele; dehnt sich aber auf die unterschiedlichsten Anwendungen immer weiter aus. DirectSound sorgt fr den guten Ton. Auch dieses Feature beschrnkt sich nicht auf eine zweidimensionale Akustik. Sie knnen Soundquellen frei im Raum platzieren, die je nach Standort und Hrrichtung des Zuhrers unterschiedlich einwirken. Mit DirectInput bekommen Sie Tastatur, Maus oder Joystick fest in den Griff. Hier wurde wirklich eine leicht einsetzbare COM-Schnittstelle geschaffen, die dennoch allen Anforderungen stand hlt. Was wre das tollste Spiel, wenn man es alleine spielen muss. DirectPlay schafft die richtige Verbindung zu anderen Computern. Ob ber das Internet oder per Netzwerk, DirectPlay stellt hierzu die richtigen Methoden bereit.

16

Systemvoraussetzungen

Systemvoraussetzungen
Die Frage, welche Systemanforderungen fr eine DirectX-Anwendung bentigt werden, ist nicht eindeutig zu beantworten. Was die Hardware leisten muss, hngt im Wesentlichen von der Komplexitt der Anwendung ab. Die besten Leistungswerte werden Sie durch eine direkte Untersttzung der Hardware erhalten. Sie knnen zwar die meisten DirectX-Techniken durch eine robuste Softwareemulation betreiben, dies wird jedoch durch starke Leistungseinbuen quittiert. Als hervorragend geeignet haben wir die AMD Athlon CPU kennengelernt. Unserer Ansicht nach hat AMD mit diesem Prozessor einen Volltreffer gelandet. Sein Leistungsniveau konnte uns immer wieder ins Staunen versetzen. Diese CPU bildet eine Referenz, an der sich alle anderen Hersteller messen mssen. Auer dem wirklich sehr gut gelungenem Produkt bietet AMD auch einen hervorragenden Support. Wir fanden fr Fragen immer ein offenes Ohr und die Antworten kamen schnell und kompetent. Bei den Grafikkarten lernten wir die Produkte von ATI schtzen. Die Produkte stehen vielleicht nicht immer an der Spitze der Leistungskurve, dennoch haben sie sich als schnell und robust herausgestellt. So fanden wir Untersttzung fr Features von DirectX, die man bei anderen Herstellern nicht findet. Auch die Qualitt der Umsetzung ist auerordentlich gut gelungen. Abschlieend knnen wir Ihnen nur noch den Hinweis geben, dass Sie nach Mglichkeit nur solche Hardware einsetzen sollten, die eine hundertprozentige DirectX-Untersttzung bietet. Dies gilt insbesondere fr die verwendete Grafikkarte. Sie und die CPU bilden den Rahmen, der die Leistungsfhigkeit Ihres Systems bildet.

Kapitel 1
DirectDraw
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 DirectDraw-Grundlagen Blitting Sprites durch Transparenz Fullscreen Fullscreen und Spriteanimation Hintergrund-Scrolling Spritekollision Bienenjagd Methoden zum Zeichnen 22 42 51 65 72 75 78 88 93

18

Visual Basic und Grafik? Ist es mglich, mit Visual Basic schnelle Grafikoperationen durchzufhren? Diese Fragen wird sich jeder Visual Basic-Programmierer frher oder spter stellen. Trotz der Beschrnkungen durch die Visual Basic-Standardkomponenten ist es machbar. Das Windows-Grafiksubsystem GDI ist bestens dazu geeignet, Textverarbeitungen oder Tabellenkalkulationen zu untersttzen, verfgt jedoch nicht ber eine schnelle Grafikumgebung. Anfnglich sollte dieses Defizit von Subsystemen wie WinG korrigiert werden. Dies fhrte aber nicht zu den gewnschten Ergebnissen. Die Wende kam mit Windows 95. Es folgten DirectX und schlielich DirectDraw, das Standbein von DirectX, das den Zugriff auf schnelle 2D-Grafikaktionen ermglicht. Durch DirectDraw (DD) erhalten Sie den direkten Zugriff auf den Grafikchipsatz sowie den Videospeicher der Grafikkarte. Die meisten Aktionen von DirectDraw werden fr den Anwender unsichtbar im Speicher des Computers ausgefhrt. Im Idealfall werden die Grafikaktionen im Videospeicher der Grafikkarte bearbeitet. Dass die Grafikinformationen im Videospeicher liegen, ist enorm wichtig, denn dann kann eine moderne Grafikkarte ohne Untersttzung der CPU anstehende Arbeiten selbststndig berechnen. So arbeiten zwei CPUs gleichzeitig. Durch diese Arbeitsweise wird die Grafikanzeige enorm beschleunigt. Das Kopieren von Daten aus einem Speicherbereich in einen anderen. Das ist die Hauptaufgabe von DirectDraw. Diese Definition trifft den Kern, auch wenn die komplexen Mglichkeiten von DirectDraw nicht angesprochen werden. Das DirectDraw-Gebilde ist immer gleich aufgebaut. D.h. eine DirectDraw-Anwendung ist immer nach einem festen Schema strukturiert. Zu diesem Zweck werden verschiedene Oberflchen (Surfaces) eingerichtet. Es wird unterschieden zwischen sichtbaren und unsichtbaren Surfaces. Die sichtbare Surface ist die so genannte primre Surface, alle anderen sind Backbuffer bzw. Offscreensurfaces. Nachdem wir festgestellt haben, dass sich DD hauptschlich auf Kopierarbeiten spezialisiert hat, knnen wir eine relativ feste Struktur erkennen. Sie ist folgendermaen aufgebaut: Alles fngt damit an, dass ein DD-Objekt erzeugt wird. Dies geschieht mit der DirectDrawCreate()-Methode. Anschlieend werden mit der CreateSurface()-Methode die verschiedenen Surfaces erstellt. Von den Offscreensurfaces wird auf der Backbuffersurface eine Grafik zusammengestellt. Hier nutzt man die Blt()- oder BltFast()-Methoden. Die neu erstellte Grafik ist fr den Anwender noch unsichtbar. Um sie sichtbar zu machen, muss die Grafik auf die primre Surface. Sie haben dazu drei Mglichkeiten: die Blt()- bzw. BltFast()-Methode und die Flip()-Methode. Welche Technik Sie einsetzen, ist von der Konstruktion Ihrer DD-Anwendung abhngig und wird spter genau erlutert.

Kapitel 1 DirectDraw

19

DirectDrawCreate() CreateSurface()

primre Surface Flip() Blt() BltFast()

Backbuffer Surface

Offscreen Surface

Blt() BltFast()

Bild 1.1:

Aufbau einer DirectDraw-Anwendung

An der Abbildung erkennen Sie den grundstzlichen Aufbau einer DD-Anwendung. Sie nutzen eine oder mehrere unsichtbare Surfaces, um eine Grafik zu erstellen. Dies geschieht komplett im Speicher des Computers. Die Technik, eine Backbuffersurface einzusetzen, wird DoubleBuffer genannt und sichert Ihnen eine flimmerfreie Anzeige. Zustzlich ist der Aufbau der Grafik vor den Augen des Anwenders geschtzt. Der dritte Vorteil ist eine Geschwindigkeitssteigerung. In wenigen Anwendungen kommt das TripleBuffer-Verfahren zum Einsatz. Hierbei wird eine zweite Backbuffersurface erstellt. Whrend der Inhalt des ersten Backbuffers auf die primre Surface kopiert wird, wird auf dem zweiten Backbuffer die neue Grafik erstellt. Die zugeordneten Backbuffer werden der Reihe nach auf die primre Surface geflippt. Dieses Verfahren macht aber nur Sinn, wenn das verwendete Computersystem noch ungenutzte Rechenreserven besitzt. Wie bereits erwhnt, kommt diese Technik nur selten zum Einsatz und ist im Regelfall nicht ntig.

20

Blt(), BltFast() kontra Flip()! Die Flip()-Methode ist schneller als die Blt()- oder BltFast()-Methode. Nachteil: Sie kann nur eingesetzt werden, um den Inhalt einer Backbuffersurface auf die primre Surface zu kopieren. Nutzt man die Flip()Methode, wird im Vorfeld eine Komplexe Surface erstellt, die fest mit einem oder zwei Backbuffer verbunden ist (Double- oder TripleBuffer). Das Flippen der primren Surface kann mit dem Umdrehen eines Blatt Papiers verglichen werden. Die Seite, die zuvor sichtbar war, wird nach dem Umdrehen zur Unterseite. Moderne Grafikkarten bieten einen weiteren Anreiz, die Flip()-Methode zu nutzen. Diese Karten mssen den Surfaceinhalt nicht mehr hin und her kopieren. Der RAMDAC dieser Karten macht es mglich, den Zeiger auf den Speicherbereich zur Bildschirmausgabe neu zu setzen. Die Kopiergeschwindigkeit ist in erster Linie von der verfgbaren Hardware abhngig. Grafikkartenspeicher, Grafikchipsatz, Systemspeicher, CPU ... sind Faktoren, welche einen unmittelbaren Einfluss auf die Performance haben. Sie als Programmierer knnen die Hardware des Anwenders nicht ndern. Dennoch sind Sie an der Performance einer Anwendung nicht unbeteiligt. Klassifizieren wir doch einfach mal die DirectDraw-Geschwindigkeiten. So werden wir drei Beschleunigungsstufen unterscheiden. 1. Performancestufe ist das Arbeiten mit Videospeicher und Systemspeicher. 2. Performancestufe ist das Arbeiten im Videospeicher. Die beste Performancestufe ist die dritte, die Sie durch den Einsatz der Flip()-Methode erreichen. Unabhngig von der eingesetzten Hardware knnen folgende Optimierungsregeln deklariert werden. Surfaces sollten im Videospeicher erstellt werden. Falls der vorhandene Videospeicher nicht ausreicht, um den Backbuffer sowie Offscreensurfaces aufzunehmen, mssen diese Surfaces im Systemspeicher abgelegt werde. Damit ist der Datentransfer aller Surfaces auf normale Kopierbefehle der CPU angewiesen. Diese Befehle sind zum einen sehr langsam und zum anderen wird die CPU fr andere Aufgaben blockiert. Sollte die Grafikkarte gengend Speicher besitzen, um auch den Backbuffer aufzunehmen, werden die Kopierarbeiten vom Grafikchipsatz der Grafikkarte bernommen. Die CPU muss in den Datentransfer nicht eingreifen und steht fr weitere Aufgaben zur Verfgung. Nutzen Sie die Flip()-Methode Die Flip()-Methode ist wesentlich effizienter als die Blt()- bzw. BltFast()-Methoden. Dies hngt natrlich mit der engen Bindung von der Backbuffersurface mit der primren Surface zusammen. Moderne Grafikkarten knnen ber die Flip()-Methode den sichtbaren Grafikkartenspeicher durch einfaches Umprogrammieren des Grafikchipsatzes ndern. Es ist nicht mehr notwendig Daten zu kopieren. Lediglich der Zeiger auf den Anfang der primren Surface wird verschoben.

Kapitel 1 DirectDraw

21

Sparen Sie Videospeicher DirectDraw wird hauptschlich zur Darstellung von Animationen eingesetzt. Diese Animationen setzten sich aus vielen kleinen Grafiken zusammen, welche nacheinander sichtbar gemacht werden. Dies knnen Sie am besten mit einem Daumenkino vergleichen. Die gesamte Szene wird aus Offscreensurfaces zusammengebaut. Legen Sie die wichtigsten Offscreensurfaces zuerst an. DirectDraw wird so lange den Videospeicher verwenden, bis dieser aufgebraucht ist. Nutzen Sie viele kleine Surfaces. So knnen Sie sicherstellen, das mglichst viel vom kostbaren Videospeicher verwendet wird. DirectDraw legt entweder eine Surface komplett in den Videospeicher oder gar nicht.

Wie geht es weiter? Sie werden anhand von einfachen Beispielen an die verschiedenen Facetten von DirectDraw herangefhrt. Wir fangen an mit dem Blitten einer Grafik aus einer Offscreensurface auf die primre Surface. Hierzu werden wir erklren, was notwendig ist, um DirectDraw-Objekte zu erstellen, wie die DirectX-Schnittstelle eingebunden wird und welche Bedeutung RECT-Strukturen haben. Im Verlauf des Kapitels werden wir uns ber eine fensterbasierende Anwendung bis zur FullScreen-Darstellung inklusive Spriteanimation und Hintergrundscrolling vorarbeiten. Blitting Demonstriert den Blitvorgang einer Hintergrundgrafik auf die sichtbare primre Surface. Sprites durch Transparenz In diesem Themenbereich werden wir auf einer Offscreensurface eine Grafik mit Hilfe weiterer Offscreensurfaces zusammenstellen. Wir nutzen den Colorkey (Farbschlssel) um Farben transparent erscheinen zu lassen. Hierdurch erwecken wir die Illusion von nicht rechteckigen Sprites. Full Screen Mode Um unsere Performance zu steigern, verlassen wir die fensterbasierende Anwendung und wechseln auf den Full Screen Mode. Die Flip()-Methode kommt zum Einsatz. Background Scrolling Full Screen Mode, Spriteanimation, Flip()-Methode und Hintergrundanimation. Sprite-Kollision Eine Kollision von Sprite-Objekten zu erkennen ist nicht ganz einfach. Wir werden zwei Mglichkeiten demonstrieren. Ganz nebenbei erfahren Sie auch einiges ber Palettenhandling sowie direkte Speichermanipulation.

22

DirectDraw-Grundlagen

Bienenjagd Bienenjagd ist ein kleines Spielprogramm, welches komplett mit DirectDrawTechniken umgesetzt wurde.

Bevor wir jedoch zur praktischen Arbeit kommen, stellen wir etwas Theorie voran. Das Kapitel DirectDraw-Grundlagen erklrt die Bestandteile der DirectDraw-Anwendung.

1.1
1.1.1

DirectDraw-Grundlagen
Der Aufbau von DirectDraw
In diesem Abschnitt mchten wir Ihnen den Zusammenhang zwischen Direct Draw und den restlichen DirectX-Komponenten darlegen.

Anwendung
Grafik Device Interface (GDI)

Display Device Interface(DDI) DirectDraw

Hardware Emulation Layer HEL

Hardware Abstraction Layer Grafikkarte


Bild 1.2: Einbindung von DirectDraw in der DirectX-Umgebung

Kapitel 1 DirectDraw

23

DirectDraw stellt ber den HAL (Hardware Abstraction Layer) einen direkten Zugriff auf die Grafikkarte zur Verfgung. Sollte dies nicht mglich sein, wird der HEL (Hardware Emulation Layer) verwendet. Hierbei kommt es zu einer erweiterten Kommunikation mit dem GDI (Graphic Device Interface), sowie dem DDI (Device Display Interface). Der HEL emuliert das von DirectDraw angeforderte Leistungsmerkmal. Dennoch besitzt der HEL einen direkten Zugriff auf die Grafikkarte. Die GDI besitzt keinen direkten Zugriff auf die Hardware der Grafikkarte. Objekttypen DirectX organisiert alle Methoden und Techniken in Objektklassen. Mchten Sie z.B. eine Surface manipulieren, so bearbeiten Sie das zugehrige DirectDraw Surface7-Objekt. Mchten Sie die Palette einer Anwendung ndern, so werden Sie das DirectDrawPalette-Objekt bearbeiten. DirectDraw-Objekt Das DirectDraw-Objekt ist der zentrale Knotenpunkt aller DD-Anwendungen. Es ist das erste Objekt, welches erzeugt wird. Mit dem DirectDraw-Objekt wird die Verbindung zu DirectX7 geschaffen. Mit der DirextX7.DirectDraw Create()-Methode wird ein DirectDraw-Objekt erstellt. DirectDrawSurface-Objekt Das DirectDrawSurface-Objekt reprsentiert einen Speicherbereich, welcher das aktuelle Monitorbild darstellt. Auerdem wird dieser Bereich zum Kopieren von Bildern verwendet. Mit den DirectDraw7.CreateSurface(), Direct Draw7.CreateSurfaceFromFile(), DirectDraw7.DuplicateSurface() oder Direct-Draw7.CreateSurfaceFromResource-Methoden wird das DirectDraw Surface-Objekt erstellt. Das DirectDrawSurface-Objekt wird im Allgemeinen als Surface bezeichnet. DirectDrawPalette-Objekt Das DirectDrawPalette-Objekt (kurz Palette) reprsentiert einen 16- oder 256Farben-Index. Dieser Index wird von einer Surface benutzt. Er beinhaltet eine Liste von RGB-Drillingen, welche die Farbanteile einer Farbe definieren. Sie knnen keine Paletten nutzen, wenn eine Surface mit einer Farbtiefe grer 8 Bit arbeitet. Mit der DirectDraw7.CreatePalette()-Methode erstellen Sie eine Palette. DirectDrawClipper-Objekt Das DirectDrawClipper-Objekt hilft Ihnen zu verhindern, dass Grafikdaten in Bereiche auerhalb einer gltigen Surface kopiert werden. Das Clipper-Objekt wird mit der DirectDraw7.CreateClipper-Methode erzeugt.

24

DirectDraw-Grundlagen

Aufbau der DirectDraw7-Objekte:


DirectX7

DirectDraw Objekte

DirectDrawSurface Objekt

DirectDrawSurface Objekt

DirectDrawSurface Objekt
Bild 1.3: DirectDraw-Objekte

Hardware Abstraktion Layer Der Hardware Abstraktion Layer (HAL) untersttzt alle spezifischen Eigenschaften einer Grafikkarte. Diese Eigenschaften werden durch eine grafikkartenspezifische Schnittstelle beschrieben. Diese Grafikkarten-Treiber werden im Regelfall vom Hersteller zur Verfgung gestellt und in das Windows Device Management Concept eingebunden. Dieser Treiber wird entweder als 16- oder 32-Bit-Code bereit gestellt. Unter Windows NT / Windows 2000 ist dies immer ein 32-BitCode. In einigen Fllen gehrt der HAL nicht zu dem Grafikkarten-Treiber, sondern wird durch eine separate DLL eingebunden. Der HAL untersttzt nur Eigenschaften speziell fr die Grafikkarte, fr die er entwickelt wurde. Sollte der HAL Techniken von DirectDraw nicht untersttzen, so werden diese auch nicht emuliert. Dies macht sich bei lteren Systemen beim Einsatz von erweiterten Techniken wie OverlaySurfaces oder BLTFX bemerkbar. Hardware Emulation Layer Wenn der Hardware Abstraktion Layer der Grafikkarte ein Merkmal von Direct Draw nicht untersttzt, kann DirectDraw versuchen dieses Merkmal zu emulieren. Diese Emulation wird durch den Hardware Emulation Layer (HEL) beschrieben. Der HEL prsentiert die Leistungsfhigkeit von DirectDraw, so wie es der HAL tun wrde. Bei dem HEL handelt es sich um eine Softwarelsung. Diese Emulationssoftware ist wesentlich langsamer als die direkte Hardwareuntersttzung des HALs. Andererseits gibt es keine Grafikkarten, welche alle Leis-

Kapitel 1 DirectDraw

25

tungsmerkmale von DirectDraw untersttzen. Somit ist der Einsatz der HEL durchaus legitim. Beachtet man, dass die Computersysteme immer schneller werden, knnen wir damit rechnen, das viele Leistungsmerkmale durch den HEL umgesetzt werden.

1.1.2

Cooperative Level
Der Cooperative Level beschreibt, wie DirectDraw mit dem Display interagiert. Ebenfalls wird beschrieben, wie sich Ereignisse auf das Display auswirken. Um den Cooperative-Level zu setzen, benutzen Sie die DirectDraw7.SetCooperative Level-Methode. Im Regelfall wird der Cooperative Level eingesetzt, um Direct Draw als Full Screen oder als Fensteranwendung zu starten. Full Screen beinhaltet, dass DirectDraw einen exklusiven Zugriff auf die Grafikkarte erhlt. Folgende Einstellungen sind mglich: DirectDraw erlauben, Mode X-Auflsungen zu verwenden (s. Mode X).
(CTRL) + (ALT) + (DEL) erlauben oder verhindern.

Fenster verkleinern oder vergrern, zulassen oder verhindern (minimize oder maximize).

Der normale Cooperative Level beschreibt eine fensterbasierende Anwendung. Es knnen keine nderungen an der Farbpalette oder Auflsung vorgenommen werden. Ebenfalls ist Pageflipping nicht mglich. Der Full-Screen Modus lsst die beste Nutzung der Hardware zu. Hierbei werden die besten Performancewerte erreicht. Ebenfalls ist der Einfluss auf das Display gewachsen. Softwareentwickler nutzen Ereignisse wie WM_ACTIVATEAPP oder WM_DIS PLAYCHANGE um die verwendeten Oberflchen der Anwendung zu aktualisieren. In einigen Fllen kommt es vor, dass die Aktualisierungen vorgenommen werden, obwohl dies nicht notwendig ist. Ebenso unterbleibt eine dringend notwendige Aktualisierung. Mit der DirectDraw7.TestCooperativeLevel()-Methode knnen Sie den aktuellen Status des Cooperative Levels ermitteln. Sie sind somit in der Lage, individuell auf den Status zu reagieren. Die Methode liefert ein DD_OK (Wert 0) zurck, wenn alles in Ordnung ist. Fehler werden nach der Art des verwendeten Cooperative Levels der Anwendung unterschieden. Full-Screen-Anwendung Sie erhalten die Fehlermeldung DDER_NOEXCLUSIVEMODE, falls Ihre Anwendung den exklusiven Zugriff auf die Grafikkarte verloren hat. Dies tritt z.B. ein, wenn der Anwender (ALT) + (_) drckt. In diesem Fall sollten Sie TestCooperativeLevel() so lange in einer Schleife laufen lassen, bis Sie den exklusiven Status wieder erhalten. Alternativ knnen auch Funktionen wie Wait Message() oder Sleep() eingesetzt werden.

26

DirectDraw-Grundlagen

Fensteranwendung Bei einer Fenster-Anwendung knnen zwei Fehlermeldungen auftreten. DD ERR_ECXLUSIVEMODEALREADYSET und DDERR_WRONGMODE. Im ersten Fall wurde von DirectDraw bereits ein Exklusiv-Mode vergeben. Somit kann keine weitere DirectDraw-Anwendung auf die Grafikkarte zugreifen. Ohne direkten Grafikkartenzugriff ist auch keine DirectDraw-Anwendung mglich. Im zweiten Fall wurde der Display Mode gendert. Hierdurch sind die DirectDrawSurface-Objekte zerstrt worden und mssen neu erstellt oder restauriert werden.

1.1.3

Display Mode
Der Display Mode beschreibt die Dimensionen und die Farbtiefe der Hardwareeinstellung, diese werden von der primren Surface an den Monitor gesendet. Ein gebruchlicher Display Mode ist 640 X 480 X 8. Dieser beschreibt eine Monitordarstellung mit 640 Pixel Breite, 480 Pixel Hhe und 8 Bit Farbtiefe. (Dieser Mode ist ein zu DirectDraw konformer Modus. Es lsst sich ohne Probleme ein DirectDrawPalette-Objekt erzeugen. Bei Einstellungen mit einer greren Farbtiefe muss man etwas mehr Arbeit investieren.) Je grer der Display Mode wird desto mehr Videospeicher wird verwendet. Gleiches gilt wenn die Farbtiefe erhht wird. Sie sollten die Kapazitten Ihrer Grafikkarte kennen, bevor Sie den Display Mode fr Ihre Anwendung whlen. Aufbauend auf dem Display Mode werden im Regelfall die Oberflchen (Surfaces) erstellt. Diese sollten aus Performancegrnden im Videospeicher liegen. Die unterschiedlichen Grafikkarten untersttzen unterschiedliche Display Modes. Welche Modes untersttzt werden, hngt von dem verfgbaren Speicher der Grafikkarte ab. Mit der DirectDraw7.GetDisplayModesEnum()-Methode knnen Sie die zur Verfgung stehenden Modes ermitteln. Siehe Listing:
Dim m_dx As New DirectX7 Private Sub Combo1_Click() List1.Clear Dim ddEnum As DirectDrawEnum Dim strGuid As String Set ddEnum = m_dx.GetDDEnum() i = Combo1.ItemData(Combo1.ListIndex) List1.AddItem " Index " + Str(i) List1.AddItem " Name " + ddEnum.GetDescription(i) List1.AddItem " GUID " + ddEnum.GetGuid(i) List1.AddItem "" strGuid = ddEnum.GetGuid(i) GetDisplayModes strGuid End Sub Private Sub Form_Load()

Kapitel 1 DirectDraw

27

Me.Show GetDisplayCards Combo1.ListIndex = 0 End Sub Sub GetDisplayModes(sGuid As String) Dim DisplayModesEnum As DirectDrawEnumModes Dim ddsd2 As DDSURFACEDESC2 Dim dd As DirectDraw7 Set dd = m_dx.DirectDrawCreate(sGuid) dd.SetCooperativeLevel Me.hWnd, DDSCL_NORMAL Set DisplayModesEnum = _ dd.GetDisplayModesEnum(DDEDM_DEFAULT, ddsd2) List2.Clear For i = 1 To DisplayModesEnum.GetCount() DisplayModesEnum.GetItem i, ddsd2 List2.AddItem " Index " + Str(i) List2.AddItem " Width " + Str(ddsd2.lWidth) List2.AddItem " Height " + Str(ddsd2.lHeight) List2.AddItem " Bits Per Pixel" + _ Str(ddsd2.ddpfPixelFormat.lRGBBitCount) List2.AddItem " Refresh Rate " + _ Str(ddsd2.lRefreshRate) List2.AddItem "" Next End Sub Sub GetDisplayCards() Dim ddEnum As DirectDrawEnum Dim strGuid As String Set ddEnum = m_dx.GetDDEnum() For i = 1 To ddEnum.GetCount() Combo1.AddItem (ddEnum.GetDescription(i))Combo1.ItemData(Combo1.NewIndex) = I Next End Sub

Setzen und Restaurieren des Display Mode Sie setzen den Display Mode mit der DirectDraw7.SetDisplayMode()-Methode. Diese beinhaltet fnf Parameter: Weite, Hhe, Farbtiefe, Wiederherstellungsgeschwindigkeit (Refresh Rate) der Grafikkarte und ein Mode Flag. Das Mode Flag hat zur Zeit nur einen gltigen Wert DDSDM_STANDARDVGAMODE. Dieser wird genutzt, wenn Sie den Mode 13 (320 X 200 X 8) verwenden wollen. Alle anderen Mode X verwenden DDSDM_DEFAULT (Wert 0).

28

DirectDraw-Grundlagen

Bild 1.4:

Display Mode

Fr viele Anwendungen ist es von Bedeutung zu wissen, welches Pixelformat verwendet wird. Sie knnen mit SetDisplayMode() die Farbtiefe Ihrer Anwendung angeben, aber Sie wissen nicht, welches Bitmuster zum Erzeugen einer Farbe von Ihre Grafikkarte verwendet wird. Um dies zu erfahren, lesen Sie die Mode-Informationen, nachdem Sie den DisplayMode gesetzt haben, aus der Grafikkarte heraus. Sie bedienen sich der DirectDraw7.GetDisplayMode()-Methode. Diese Methode fllt eine Variable vom Typ DDSURFACEDESC2. In dieser Variablen ist das Typen-Array DDPIXELFORMAT enthalten. Dieses enthlt die Bitmaske zu IRBitMask, IGBitMask und IBBitMask. Abschlieend beachten Sie, dass Sie beim Beenden Ihrer Anwendung den Display Mode auf den Originalzustand zurcksetzen. Dies erreichen Sie durch die Kombination von DirectDraw7.RestoreDisplayMode() und DirectDraw7.SetDis playMode(). Mit RestoreDisplayMode() werden die Einstellung wiederhergestellt, welche vor dem ersten Aufruf von SetDisplayMode() herrschten. Mit dem erneuten Aufruf von SetDisplayMode() werden die alten Einstellungen wirksam.

Kapitel 1 DirectDraw

29

Mode X und Mode 13 DirectDraw untersttzt beide Modes: Mode 13 sowie Mode X. Mode 13 besitzt die Parameter 320 Weite X 200 Hhe X 8 Farbtiefe. Dieser Mode untersttzt kein Seitenflipping (siehe Surface). Er erhielt seinen Namen durch den hexadezimalen Bios-Eintrag: Nummer 13. Mode 13 ist ein linearer. Mode X ist ein Mischmodus. Er erlaubt die Adressierung von bis zu 256 Kilobyte des Display-Speichers (Mode 13 erlaubt nur 64 Kilobyte). Die verfgbaren Mode X sind von der verwendeten Grafikkarte abhngig. Diese knnen ber die Direct Draw7.GetDisplayModesEnum()-Methode ermittelt werden. Wenn Sie einen Mode X verwenden wollen, mssen folgende Flags gesetzt werden: DDSCL_ ALLOWMODEX, DDSCL_FULLSCREEN und DDSCL_EXCLUSIVE. Im Mode X knnen Sie die Blt()-Methode sowie die Lock()-Methode nicht auf die primre Surface anwenden. Stattdessen werden diese Techniken auf Offscreensurfaces angewandt (siehe Surface). Der Mode X wird durch das DDSCAPS_ MODEX-Flag des DDSCAPS2-Typen-Arrays angezeigt. Dieses ist Mitglied der DDSURFACEDESC2-Typen-Arrays, welche durch die DirectDraw7.GetCaps()Methode sowie der DirectDrawEnumModes()-Methode ermittelt werden.

1.1.4

Colorkey
Mit dem Colorkey (Farbschlssel) wird ein Farbbereich gekennzeichnet, welcher beim Kopieren einer Grafik nicht bercksichtigt wird. Dieser Farbbereich bleibt durchsichtig. DirectDraw untersttzt einen Source Colorkey und einen Destination Colorkey. Der Source Colorkey beschreibt einen Farbbereich der Quellgrafik. Alle Pixel, welche in das Farbschema passen, werden beim Kopieren der Grafik ignoriert. hnlich agiert der Destination Colorkey. Der Unterschied liegt darin, dass diesmal die Pixel, welche durch das Farbschema beschrieben werden, beim Kopieren der Grafik nicht berschrieben werden. Der Destination Colorkey wird nicht von allen Grafikkarten untersttzt. Der Colorkey ist folgendermaen definiert:
Type COLORKEY high As Long low As Long End Type

Die Parameter low und high geben den Anfang und das Ende des Farbbereichs an. Diese Werte mssen unter Bercksichtigung des Surface-Pixel-Formats benannt werden. Bei einer 8-Bit-Palette werden die Farbindexe angegeben. Eine 16-BitFarbtiefe verwendet ein Pixelformat von 5:6:5. Eine 24-Bit-Farbtiefe nutzt das Pixelformat 8:8:8. Das Pixelformat kann sich von Grafikkarte zu Grafikkarte ndern.

30

DirectDraw-Grundlagen

Mit DirectDrawSurface7.SetColorkey() wird der Colorkey fr die Surface gesetzt.

1.1.5

Surface
Eine Surface knnen Sie sich am besten als ein Blatt Papier vorstellen. Auf diesem knnen Sie dann mit DirectDraw etwas zeichnen. Genauer betrachtet ist eine DirectDraw-Oberflche (Surface) ein zusammenhngender Speicherbereich. Dieser liegt idealerweise im Videospeicher der Grafikkarte. Da dieser Speicherbereich oftmals sehr begrenzt ist, kann eine Surface auch im Systemspeicher des Computers existieren. Werden beim Erzeugen einer Surface keine spezifischen Parameter gesetzt, so wird zuerst der verfgbare Videospeicher verwendet. Wenn eine Surface im Videospeicher existiert, so werden auftretende Kopierarbeiten vom Grafikkartenchipsatz bernommen. Dadurch wird die CPU des Computers weitgehend entlastet. Im Regelfall arbeiten CPU und Grafikkartenchipsatz parallel zueinander. Das macht sich natrlich bei der Performance bemerkbar. Es werden fnf Surface-Typen unterschieden. Die wichtigsten Surfaces sind die primre Surface und die Offscreensurface. Mit diesen beiden Typen werden den meisten Aufgaben von DirectDraw bewltigt. Wir werden uns auch im Wesentlichen auf diese beiden Surfacearten berufen. Spter werden wir den Einsatz von Fullscreen Anwendungen besprechen. Diese nutzen eine so genannte komplexe Surface. Hierbei handelt es sich um eine Kombination von primrer Surface mit einer fest verbundenen Offscreensurface, welche dann als Backbuffer bezeichnet wird. Den Einsatz von Surfaces knnen Sie am besten anhand unserer Beispielanwendungen erkennen, dennoch sollten Sie sich die Informationen zu den Surfaces durchlesen. Betrachten Sie die Vorstellung der verschiedenen Surface-Typen als hilfreiche Informationen, auf die Sie spter zurckgreifen knnen. Primre Surface Eine primre Surface ist die aktuell auf dem Monitor sichtbare Surface. Sie wird durch das DDSCAPS_PRIMARYSURFACE-Flag identifiziert. Ein DirectDraw-Objekt kann nur eine primre Surface besitzen.

Siehe Listing:
Dim ddsd2 As DDSURFACEDESC2 ddsd2.lFlags = DDSD_CAPS ddsd2.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE

Offscreensurface Eine Offscreensurface ist fr den Anwender nicht sichtbar. Sie wird durch das DDSCAPS_OFFSCREENPLAIN-Flag identifiziert. Es knnen beliebig viele Offscreensurfaces erstellt werden. Der Hauptverwendungszweck ist es, Grafikdaten zu speichern. Oftmals wird eine Offscreensurface als Backbuffer bezeichnet. Auf dieser Backbuffersurface werden alle Grafikoperationen ausgefhrt, bevor sie auf die primre Surface kopiert werden. Einer Offscreensur-

Kapitel 1 DirectDraw

31

face muss man Ihre Dimensionen mitteilen. Hierzu werden die Flags DDSCAPS_WIDTH und DDSCAPS_HEIGHT gesetzt. Anschlieend erhlt man auf die Mitgliedsdaten lWidth und lHeight Zugriff. Die Dimensionen einer Surface werden in Pixeln angegeben. Siehe Listing:
Dim ddsd2 As DDSURFACEDESC2 ddsd2.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN

Alternativ kann die Surface auch im Systemspeicher erstellt werden. Lediglich das DDSCAPS_SYSTEMMEMORY-Flag msste hinzugefgt werden. Dies wrde so aussehen:
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_SYSTEMMEMORY

In dem Sie die Parameter lHeight und lWidth setzten, legen Sie die Hhe und Weite der Offscreensurface fest.
ddsd2.lHeight = 200 ddsd2.lWidth = 250

Wie bereits erwhnt, ist der Videospeicher begrenzt. Um Videospeicher zu sparen und die Performance zu steigern, kann eine Offscreensurface eine von der primren Surface unabhngige Farbtiefe erhalten. Sie erweitern die Surface-Beschreibungen, indem Sie das Pixelformat genauer benennen. Als Beispiel zeigen wir eine 8-Bit-Farbtiefe:
ddsd2.ddpfPixelFormat.lRGBBitCount = 8

Die Dimensionen einer Offscreensurface knnen die Dimensionen der primren Surface nicht berschreiten. Zu diesem Zweck wrde eine Wide Surface erstellt. Nicht alle Grafikkarten sind in der Lage Wide Surfaces zu erstellen. Ebenfalls sollte der Speicher der Grafikkarte genau im Auge behalten werden. Eine Wide Surface kann schnell die Grenzen der Grafikkarte sprengen. Complex Surface Eine komplexe Surface ist eine primre Surface, welche mit einer (oder mehreren) Offscreensurface (Backbuffersurface) fest verbunden ist. Eine komplexe Surface wird durch das DDSCAPS_COMPLEX-Flag identifiziert. Wird es notwendig die Surface zu restaurieren, reicht ein Aufruf von DirecDrawSurface7.Restore() und alle mit der primren Surface verbundenen Backbuffer werden ebenfalls restauriert. Eine komplexe Surface erlaubt das Page-Flipping.

Wird eine Backbuffersurface verwendet, so spricht man vom Doublebuffer. Verwendet man zwei Backbuffer, so wird diese Technik als Triplebuffer bezeichnet.

32

DirectDraw-Grundlagen

Dies lsst sich beliebig fortsetzen. Angemerkt sei, dass im Regelfall alles, was den Doublebuffer bersteigt, selten sinnvoll ist. Sinnvoll wird dies erst dann, wenn Ihre Anwendung eine neue Grafik schneller berechnen kann, als sie von der Grafikkarte dargestellt wird. Mehrere Backbuffer werden durch eine Flipping Chain (Seiten-Umschlage-Kette) verbunden. Da wir uns hauptschlich mit dem Doublebuffer-Verfahren beschftigen, werden wir auf die Flipping Chain nur begrenzt eingehen. Folgende Abbildung verdeutlicht die Flipping Chain.
Primre Surface 3 Backbuffer 1 2 6 Backbuffer 2 4 Backbuffer 3

N
Bild 1.5: Flipping Chain

Schritt 1 bis 6

Um den Inhalt der Backbuffer auf der primren Surface sichtbar zu machen, werden die Backbuffer der Reihe nach durchgeschaltet. Am Ende angelangt, geht alles wieder von vorne los. Betrachten Sie das Listing fr eine Komplexe Surface mit einem Backbuffer.
Dim ddsd2 As DDSURFACEDESC2 ddsd2.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT ddsd2.ddsCaps.lCaps = DDSCAPS_COMPLEX Or DDSCAPS_FLIP Or _ DDSCAPS_PRIMARYSURFACE ddsd2.lBackbufferCount = 1

Wide Surface Mit DirectDraw sind Sie in der Lage eine Offscreensurface zu erstellen, welche die Dimensionen der primren Surface berschreitet. Idealerweise wird auch die Wide Surface im Videospeicher erzeugt. Dies ist aber nur dann mglich, wenn die angesprochene Grafikkarte dies untersttzt. Leider ist dies nicht immer der Fall. Sie knnen mit der DirectDraw7.GetCaps()-Methode prfen, ob diese Eigenschaft untersttzt wird. Den entsprechenden Eintrag finden Sie in dem DDCAPS-Typen-Array unter lCaps2.

Kapitel 1 DirectDraw

33

Wide Surfaces knnen jederzeit im Systemspeicher erstellt werden. Hierzu werden die normalen Parameter einer Offscreensurface eingesetzt. Ein bevorzugtes Einsatzgebiet fr eine Wide Surface ist das Hintergrundscrolling. Eine entsprechende Beispielanwendung finden Sie in einem spteren Kapitel. Client Memory Surface Eine Client Memory Surface ist eine normale DirectDraw-Surface, welche im Systemspeicher erstellt wird. Sie wird verwendet um Grafikdaten zu speichern, die nicht permanent zum Einsatz kommen. Diese Surface ist immer dann sinnvoll, wenn Ihre Anwendung den Videospeicher fr wichtigere Surfaces belegt. Durch Angabe des Pixelformats wird ein fester Speicherbereich reserviert. Auf diesen Speicherbereich kann der Programmierer gezielt zugreifen. Nach Beenden der Anwendung wird der Speicherbereich der Client Memory Surface nicht automatisch freigegeben. Siehe Listing:
Dim ddsd2 As DDSURFACEDESC2 Dim dds As DirectDrawSurface7 With ddsd2 .lFlags = DDSD_WIDTH Or DDSD_HEIGHT Or DDSD_PITCH Or _ DDSD_PIXELFORMAT Or DDSD_CAPS .ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or _ DDSCAPS_SYSTEMMEMORY .lWidth = 100 .lHeight = 100 .lPitch = 3*100 With .ddpfPixelFormat .lFlags = DDPF_RGB .lRGBBitCount = 3 * 8 .lRBitMask = &HFF0000 .lGBitMask = &HFF00& .lBBitMask = &HFF& End With End With

Width contra Pitch Width Die Entfernung zwischen zwei Adressen im Speicher, welche den Anfang und das Ende einer Grafiklinie angibt. Zustzlicher Speicher zum Erreichen der folgenden Linie wird nicht bercksichtigt. Pitch Die Entfernung (in Byte) zwischen zwei Adressen im Speicher, welche den Anfang einer Grafiklinie und den Anfang der folgenden Grafiklinie beschreibt. Bentigter Zusatzspeicher wird bercksichtigt.

34

DirectDraw-Grundlagen

DirectDraw verwendet das DDSURFACEDESC2-Typen-Array, um Informationen einer Surface zu speichern. Unter anderem werden Informationen zu den Dimensionen der Surface erfasst. Die Mitgliedsdaten lHeight und lWidth erfassen die logische Gre der Surface in Pixel. Bei diesen Angaben wird die Farbtiefe einer Surface nicht bercksichtigt.
Surface 1 lHeight 640 lWidth 800 Farbtiefe 8 Bit 800
Bild 1.6: Width

Surface 2 640 640 lHeight 640 lWidth 800 Farbtiefe 24 Bit 800

Die Werte lHeight (640) und lWidth (800) sind bei beiden Surfaces gleich. Da die Surfaces unterschiedliche Farbtiefen haben, wird aber unterschiedlich viel Speicherplatz bentigt. Pitch erfasst die tatschliche Gre des reservierten Speicherbereiches in Byte. Es ist falsch, anzunehmen, dass Pitch durch lWidth * lHeight * Farbtiefe zu berechnen ist. Betrachten Sie hierzu folgende Abbildung:
Front Buffer einer Surface bentigter Cache einer Surface

Width Pitch
Bild 1.7: Pitch

Der Pitch-Wert ist hilfreich, wenn Sie den Surface-Speicher direkt manipulieren mchten. Diese Technik wird z.B. bei der Farbenanimation genutzt. Zugriff auf den Speicherbereich erhalten Sie durch die DirectDrawSurface.Lock()-Methode. Bitte beachten Sie, dass Sie bei solchen Speichermanipulationen direkt an der Hardware arbeiten. Bei solch einem hardwarenahen Arbeiten wird der kleinste Fehler mit einem Systemabsturz belohnt. Beispielsweise drfen Sie niemals den geschtzten Speicherbereich der Surface verlassen. Sie wrden in Speicherbereiche schreiben, welche von irgendwelchen Modulen belegt sind. Dies hat im Regelfall fatale Auswirkungen.

Kapitel 1 DirectDraw

35

Overlay Surface Eine Overlay Surface ist eine Surface, welche auf die primre Surface gelegt wird. Bisher gingen wir davon aus, dass die primre die einzig sichtbare Surface sei. Mit der Overlay Surface mssen wir die Annahme etwas modifizieren. Vergleichen Sie die Overlay Surface mit einer Folie, welche auf den Monitor geklebt wird. Auf dieser Folie knnen sie dann Bitmaps abbilden. Hauptschlich wird diese Surface zur Darstellung von Videos eingesetzt. Natrlich knnen Sie auch einfache Bitmaps darstellen. Overlay Surfaces sind immer auf die Hardwareuntersttzung der Grafikkarte angewiesen. Sie knnen nicht emuliert werden. Da die Overlay Surface mit einer klaren Folie vergleichbar ist und sie sich vor der primren Surface befindet, knnen Sie beide Surfaces gemeinsam sehen. Entfernen Sie die Overlay Surface, so ist die Grafik der primren Surface unbeschdigt sichtbar.

primre Surface

Overlay Surface

Bild 1.8:

Overlay Surface ber einer primren Surface

Die Hardware der Grafikkarte berprft fr jedes Pixel der primren Surface, ob es durch ein Overlay-Surface-Pixel verdeckt wird. Ist dies der Fall, so wird das Pixel (soweit vorhanden) sichtbar. Die Grafikkarte kombiniert die Bitmap der primren Surface mit der Overlay Surface, unter Verwendung von Transparenz und Dehnung der Overlay Surface. Die Overlay Surface wird durch die normale DirectDraw7.CreatSurface()Methode erzeugt. Bentigt wird das DDSCAPS_OVERLAY-Flag des DDSCAPS2-Typen-Arrays. Da die Overlay Surface im Videospeicher erstellt werden muss, mssen Sie auch noch das DDSCAPS_VIDEOMEMORY-Flag setzten. Die Position der Overlay Surface wird mit der DirectDraw Surface7.SetOverlay Position()-Methode bestimmt. Sie nutzt nur zwei Parameter. X und Y geben die Koordinaten auf der primren Surface an.

36

DirectDraw-Grundlagen

Wenn Sie mehr als eine Overlay Surface nutzen, mssen Sie die Reihenfolge (ZOrder) der berlagerungen definieren. Die DirectDrawSurface7.UpdateOverlay ZOrder()-Methode bernimmt das fr Sie. Beachten Sie die beiden Parameter dieser Methode. Zuerst bentigen wir ein Flag. Dieses Flag definiert die Tiefenposition. Folgende Auswahl steht zur Verfgung:
DDOVERZ_INSERTINBACKOF DDOVERZ_INSERTINFRONTOF DDOVERZ_MOVEBACKWARD DDOVERZ_MOVEFORWARD DDOVERZ_SENDTOBACK DDOVERZ_SENDTOFRONT = = = = = = 5 4 3 2 1 0

Der zweite Parameter ist dds vom Typ DirectDrawSurface7. Er bestimmt, von welcher Overlay Surface das Z-Order-Attribut gendert werden soll. Overlay Surfaces werden durch den Einsatz einer Blitting-Methode nicht sichtbar. Um Sie sichtbar zu machen, mssen Sie den Colorkey nutzen. Overlay Color Key Im Vergleich zu anderen Surfaces knnen Sie eine Overlay Surface nicht durch die gebruchlichen Blitting Methoden fr den Anwender sichtbar machen. Dies ist dadurch begrndet, das die Overlay Surface ber die primre Surface gelegt wird. Da uns DirectDraw diese Technik verwehrt, greifen wir zu einem Trick. Wir nutzen den Colorkey. Mit der DirectDrawSurface7.UpdateOverlay()-Methode aktualisieren Sie die Overlay Surface. Sie knnen den Source Colorkey nutzen. Damit legen Sie fest, welche Pixel der Overlay Surface transparent sein sollen. Gleichermaen ist es erlaubt, den Destination Colorkey einzusetzen. Mit ihm bestimmen Sie, welche Pixel der primren Surface von der Overlay Surface berschrieben werden. Kombinationen beider Mglichkeiten sind erlaubt. Compressed Texture Surfaces Ein hochgelobtes Feature von DirectX ist die Texturkompression. Dieses 1998 mit DirectX6 eingefhrte Feature basiert auf einem Algorithmus von S3. Bekannt unter der Bezeichnung S3TC wurde er von Microsoft lizenziert. S3TC Algorithmus: Ein Texel ist ein Pixel auf einer Textur. DirectDraw nutzt eine Kompressionstechnik (S3TC), welche die Textur in 4X4-Texel-Blcke teilt. Jedes Texel wird mit 2 Bit beschrieben. Zustzlich wird jeder Block mit zwei 16-Bit-Farben (RGB565) versehen. Der S3TC-Algorithmus bildet nun aus diesen beiden Wertegruppen und zwei weiteren ber die ersten Werte interpolierten Farbwerten eine so genannte Color Look-Up-Table (CLUT). Diese CLUT wird verwendet, um die richtigen Farbwerte des jeweiligen Texel in der Matrix zu bestimmen. Insgesamt bentigen die 16 Texel der Matrix nun 64 Bit, d.h. durchschnittlich nur 4 Bit pro Pixel. Bei Transparenzeffekten kommen weitere 64 Bit dazu.

Kapitel 1 DirectDraw

37

Texturkompression erhlt eine besondere Bedeutung, da die Bildqualitt erheblich gesteigert werden kann. Ohne Texturkompression ist der Programmierer darauf angewiesen, mglichst kleine Texturen zu verwenden. Es sollten mglichst viele Texturen im Speicher der Grafikkarte Platz finden. Mit diesem Ziel vor Augen wurden Texturen mit acht Bit Farbtiefe erstellt. Zu Zeiten von 32 Bit Rendering machte dies natrlich wenig Sinn. Alternativ knnen 16 Bit Farbtiefe eingesetzt werden, aber dann wurde oftmals an der Auflsung gespart. Wie man es auch drehen und wenden mag, das Ergebnis konnte nie recht berzeugen. Texturkompression steigert den Spielraum des Programmierers. So ist es mglich, Texturen, welche ohne Kompression ca. 20 MB verschlingen wrden, auf ca. 6,5 MB zu reduzieren. Kompressionsraten von ber 50 % sind kein Problem. So hilfreich die Texturkompression auch sein mag, kann man nicht leugnen, das diese Technik an Bedeutung verliert. Wir haben mit Grafikkarten von bis zu 64 MB Speicher gearbeitet. Mit solchen Grafikkarten kommt man recht selten in die Verlegenheit, dass der Speicherplatz nicht mehr ausreicht. Auerdem arbeiten die Computer mit sehr schnellem Systemspeicher. Der Datenaustausch erfolgt ber einen 100 MHz (oder schneller) schnellem Frontside Bus. Werden Texture Surfaces in den Systemspeicher ausgelagert, knnen Sie dennoch mit einer akzeptablen Performance eingesetzt werden. Zum Erzeugen einer komprimierten Texture Surface setzen Sie das DDSCAPS_ TEXTURE-Flag in den lCaps-Parameter des DDSCAPS2-Typen-Arrays. Die Hhe und die Breite der Surface muss ein Vielfaches von 4 (Pixel) sein. Der IfourCC-Parameter des DDPIXELFORMAT-Typen-Arrays muss auf einen DXT-Code (siehe unten) gesetzt werden. Zu guter Letzt setzen Sie das DDPF_ FOURCC-Flag des Parameters lFlags des DDPIXELFORMAT-Typen-Arrays. Mgliche DXT-Codes: ber den DXT-Code werden interne Informationen der komprimierten Texture Surface organisiert. Genaue Kenntnisse ber die interne Struktur werden fr die Nutzung nicht bentigt. Sie werden erst hilfreich, wenn Sie eine komprimierte Texture Surface direkt manipulieren wollen. Moderne Grafikkarten nutzen Speicher von bis zu 64 MB. So hat dieses hilfreiche Feature an Nutzen verloren. Da sich der Trend, immer mehr Speicher auf der Grafikkarte zu platzieren, fortsetzt, werden wir die DXT-Codes und somit die Texturekompression nicht ausgiebig besprechen.
FORCC DXT1 DXT2 DXT3 DXT4 DXT5 Beschreibung Lichtdurchlssigkeit / ein Bit Alpha ausdrcklich Alpha ausdrcklich Alpha interpoliert Alpha interpoliert Alpha Ja Nein Ja Nein vormultiplizierter AlphaKanal

38

DirectDraw-Grundlagen

Jede einzelne Texture muss spezifiziert sein, dass sie 64 oder 128 Bits fr eine Gruppe von 16 Texel speichert. Ein 64 Bit Block wird durch den DXT1-Code gekennzeichnet. Werden 128 Bit Blocks verwendet so sind dies die DXT2- und DXT3-Formate. Im interpoliertem Modus sind es die DXT4- und DXT5-Formate. Es gibt zwei Wege, um eine Grafik in ein komprimierte Texture Surface zu laden. Erstellen Sie eine normale Surface mit einer Bitmap. Benutzen Sie die Blt()Methode oder die BltFast()-Methode, um die Bitmap von der normalen Surface in die komprimierte Surface zu blitten. DirectDraw komprimiert die Bitmap automatisch. Als zweite Mglichkeit knnen Sie eine komprimierte Bitmap direkt in den Speicher der komprimierten Surface laden.

1.1.6

Palette
Eine DirectDraw-Palette ist ein Array von 2, 4, 16 oder 256 Farben. In dem Array sind die Farbanteile fr Rot, Grn und Blau gespeichert. Eine Palette kann maximal 8 Bit tief sein. Die Paletteneintrge von 0 bis 255 werden aus einer Bandbreite von 16 oder 24 Bit selektiert.
Farbe1 Rotanteil Farbe2 Rotanteil Farbe3 Rotanteil Farbe1 Grnanteil Farbe2 Grnanteil Farbe3 Grnanteil Farbe1 Blauanteil Farbe2 Blauanteil Farbe3 Blauanteil 8 Bit 16 Bit Farbe256 Rotanteil
Bild 1.9:

RGB Farben

Farbe256 Grnanteil

Farbe256 Blauanteil

24 Bit

Palettenmodell von DirectX

Die Palette knnen wir uns als Malkasten vorstellen. In diesem Malkasten werden 256 Farben abgelegt. Mit einer Palette ist der Programmierer in der Lage, 8-BitSurfaces zu erstellen, welche aber ein besonderes Farbniveau haben. Z.B. Paletten in bestimmte Farbrichtungen: viele Blautne. 8-Bit-Surfaces sparen im Ver-

Kapitel 1 DirectDraw

39

gleich zu 16- oder 24-Bit-Surfaces viel Speicherplatz. Ebenfalls wirkt sich eine 8-Bit-Surface auf die Performance positiv aus. Mit der DirectDraw7.CreatePalette()-Methode wird eine Palette erstellt. Mit der DirectDrawSurface7.SetParlette()-Methode wird die erstellte Palette einer oder mehrerer Surfaces zugewiesen. Auf die einzelnen Paletteneintrge knne Sie mit den Methoden DirectDrawPalette.GetEntries() und DirectDrawPalette.SetEn tries() zugreifen. Bei der DirectDraw7.CreatePalette()-Methode mssen Sie die DDPCAPS_1Bit-, DDPCAPS_2Bit-, DDPCAPS_4Bit- und DDPCAPS_8Bit-Flags setzen. Somit kennzeichnen Sie die Anzahl der Paletteneintrge. Mit dem DDPCAPS_AL LOW256- Flag erhalten Sie den Zugriff auf die Paletteneintrge.
Dim Dim Dim Dim For Palette As DirectDrawPalette Surface As DirectDrawSurface7 DDraw As DirectDraw7 Pal(255) As PALETTEENTRY I = 0 To 255 'Farbverlauf Blau Pal(i).red = 0 Pal(i).green = 0 Pal(i).blue = I Next I Set Palette = DDraw.CreatePalette(DDPCAPS_8Bit Or _ DDPCAPS_ALLOW256, Pal()) Surface.SetPalette Palette

1.1.7

Clipper
Das DirectDrawClipper-Objekt erlaubt es, auf selektierte Bereiche einer Surface zu blitten. Ein Clipper wird als rechteckiger Bereich definiert. Alle Blitter-Methoden, welche innerhalb des definierten Bereichs liegen, sind fr den Anwender sichtbar. So ist es mglich, mit Hilfe des Clippers Teile des Bildschirms vor den Augen des Anwenders zu verbergen. Sie drfen fr eine Surface mehrere ClipperBereiche festlegen. Diese werden durch eine Clipper-Liste (Clip List) verwaltet. Das einfachste und hufigste Einsatzgebiet des Clippers ist es, die Grenzen eines Fensters oder Bildschirm zu markieren. Ein weiteres hufig genutztes Einsatzgebiet steht im Zusammenhang mit der Sprite-Animation. Hierbei ist es gewnscht, das ein Sprite sanft in einen sichtbaren Bildschirmbereich bewegt wird. Ohne Clipper wrde das Sprite so lange unsichtbar bleiben, bis seine gesamte RECT Struktur innerhalb des sichtbaren Bereichs liegt. Erst dann wrde das Sprite auf einen Schlag sichtbar. Mit Hilfe des Clippers ist DirectDraw in der Lage zu entscheiden, welche Teile des Sprites innerhalb des sichtbaren Bereichs (Clipper) liegen, und nur diese wrden fr den Anwender sichtbar. Der Teil des Sprites, welcher auerhalb des Clippers liegt, bleibt unsichtbar.

40

DirectDraw-Grundlagen

Bereich 1 sichtbar fr den Anwender

Bereich 2 sichtbar fr den Anwender

unsichtbar fr den Anwender


Bild 1.10: Clipperbereiche

In einer Fullscreen-Anwendung kann der Clipper nicht eingesetzt werden.

1.1.8

Blitting
Blitting (BitBlock Transfer) bedeutet nichts anderes, als Grafikdaten aus dem Speicher auf eine Surface zu kopieren. Da die Surface ebenfalls im Speicher existiert, werden die entsprechenden Daten im Speicher verschoben. Es stehen fnf Blitting-Methoden zur Verfgung. DirectDrawSurface7.Blt() Dies ist die Standart-Blit-Methode. Es wird ein definierter rechteckiger Bereich in einen anderen definierten rechteckigen Bereich kopiert. Sollten diese Bereiche unterschiedliche Dimensionen haben, so wird die Bitmap automatisch angepasst (Stretch). Diese Methode untersttzt synchrones und unsynchrones Blitten. Weiterhin knnen die Daten in unterschiedlichen Speicherbereichen liegen. Video-Speicher->Video-Speicher Video-Speicher ->System-Speicher System-Speicher->Video-Speicher System-Speicher->System-Speicher

Die Blt()-Methode ist in der Lage, den Source Colorkey sowie den Destination Colorkey zu nutzen. DirectDrawSurface7.BltFast Die BltFast()-Methode ist (wie es der Name bereits sagt) schneller als die Blt()-Methode. Die Performancesteigerung liegt bei etwa 10%. Sie birgt aber auch Nachteile. So wird Sie nicht von allen Grafikkarten untersttzt (Sollten Sie eine einigermaen moderne Grafikkarte besitzen, brauchen Sie sich nicht

Kapitel 1 DirectDraw

41

zu sorgen.). Sie arbeitet ausschlielich mit Surfaces, welche im Videospeicher erstellt wurden. Sie ist nicht in der Lage das Clipper-Objekt zu nutzen. Sie ist nicht fhig, eine Bitmap zu dehnen. DirectDrawSurface7.BltColorFill() Sie fllt einen rechteckigen Bereich mit einer Farbe. DirecDrawSurface7.BltToDC() Diese Methode blittet eine Bitmap auf ein beliebiges Objekt mit einem Handle. Es mssen zwei rechteckige Bereiche angegeben werden, welche exakt die gleichen Dimensionen haben. Die Lage der Bereiche kann variieren. DirectDrawSurface7.BltFx() Dies ist der Trickknstler unter den Blitting-Methoden. Als Besonderheit werden BltFx Parameter bergeben. Diese Parameter beschreiben Trickeffekte wie Spiegeln einer Bitmap oder Rotieren einer Bitmap. Von DirectDraw werden eine Reihe dieser Effekte untersttzt. Leider findet man nur selten eine Grafikkarte, welche alle Mglichkeiten von DirectDraw umsetzen kann. Effekte wie horizontales oder vertikales Spiegeln sind Standardeffekte, welche von nahezu allen Grafikkarten untersttzt werden.

Nun ist es Zeit etwas ber das Blit Timing zu sagen. Im Zusammenhang mit Blitter-Methoden versteht man unter Timing ein synchrones oder unsynchrones Blitten von Grafikdaten. Synchron bedeutet, dass sich die Blitter-Methode nach dem Zeilenaufbau der Grafikkarte und somit des Monitors richtet. Wenn Sie eine der oben vorgestellten Blit-Methoden einsetzen und der Hardware Blitter ist mit seiner aktuellen Aufgabe noch nicht fertig, so wird eine Fehler verursacht. Sie erhalten die Fehlernachricht DDERR_WASSSTILLDRAWING. Um sicher zu stellen, dass der Hardware Blitter seine Arbeit vollstndig beendet, wird das DDBLT_WAIT-Flag der Blt()-Methode gesetzt. DDBLTFAST_WAIT ist das entsprechende quivalent fr die BltFast()-Methode. DirectDraw akzeptiert eine unsynchrone Arbeitsweise. Hierzu wird das DDBLT_ ASYNC-Flag gesetzt. Diese Technik ist von den Mglichkeiten der Grafikkarte abhngig. Sie wird erst sinnvoll, wenn Sie Blt-Methoden schneller aufrufen, als sie vom Zeilenraster des Monitors aufgebaut werden. Um eine mglichst hohe Kompatibilitt zu anderen Systemen zu wahren, sollten Sie auf eine unsynchrone Arbeitsweise verzichten oder zumindest dem Anwender die Wahl berlassen.

1.1.9

Page Flipping
Das Flippen knnen Sie sich am besten am Beispiel eines Blatt Papiers verdeutlichen. Whrend die Oberseite fr Sie sichtbar ist, wird auf der Unterseite gezeichnet. Ist die Grafik erstellt, wird das Blatt umgedreht und die neu erstellte Grafik wir fr Sie sichtbar. Man spricht hierbei von dem so genannten Page Flipping. Moderne Grafikkarten beherrschen einen besonderen Trick. Sie mssen die Grafikkarten nicht mehr von der Unterseite auf die Oberseite kopieren, sondern ver-

42

Blitting

schieben lediglich einen Zeiger auf den sichtbaren Bereich des Videospeichers. Diese Technik wird durch das DACRAM der Grafikkarte ermglicht. Page Flipping wird vor allem bei der Double- und Triplebuffer Technik eingesetzt. Bei der Doublebuffer Technik wird nur eine Backbuffersurface eingesetzt. Die Anwendung schaltet nun immer zwischen der sichtbaren und der unsichtbaren Surface hin und her. Jedes Mal, wenn sich die Grafik auf der nicht sichtbaren Surface gendert hat, wird sie mit Hilfe der Flip()-Methode zu einer sichtbaren Surface gemacht. Bei der Triplebuffer-Technik werden zwei Backbuffersurfaces eingesetzt. Die Surfaces werden durch eine Flipping Chain miteinander verbunden. Die Flip()-Methode stellt eine gewaltige Anforderung dar. Sie kann nur eingesetzt werden, wenn Ihre Anwendung im Fullscreen-Modus arbeitet. Der Fullscreen-Modus verlangt einen exklusiven Zugriff auf die Grafikkarte. Natrlich lohnt sich der Aufwand, denn die Flip()-Methode ist im Vergleich zu den Blitteraktionen schneller. Die Flip()-Methode wird von fast allen Grafikkarten untersttzt. In wenigen Fllen kommt es vor, dass DirectDraw die Flip()-Methode emulieren muss. Diese Emulation wirkt sich negativ auf die Performance aus, da diese Arbeit von der CPU des Computers verrichtet wird. Mgliche Grnde fr eine Emulation knnen sein: Die Grafikkarte untersttzt die Flip()-Methode nicht Die Surfaces wurden nicht oder nur teilweise im Videospeicher erstellt.

Synchron oder Unsynchron? Die Flip()-Methode ist unsynchron. Unsynchron bedeutet, Sie richtet sich nicht nach dem vertikalem Zeilenaufbau des Monitors. Dies fhrt natrlich zu einem Problem. Wird die Flip()-Methode aufgerufen, obwohl der letzten Grafikaufbau noch nicht beendet wurde, werden Sie eine eventuell eine fehlerhafte Grafikdarstellung erhalten. Dies macht sich oftmals als Doppelbilder oder Umrissschatten bemerkbar. Dieses Problem knnen Sie mit dem DDFLIP_WAIT-Flag schnell und elegant lsen. Durch dieses Flag zwingen Sie DirectDraw, auf die Fertigstellung eines aktuellen Grafikaufbaus zu warten. In vielen Fllen knnen Sie dennoch auf ein synchrones Arbeiten verzichten. Durch ein unsynchrones Arbeiten knnen Sie Darstellung von Einzelbildern (Bilder pro Sekunde) deutlich steigern und schaffen zustzliche frei verfgbare Rechenzeit.

1.2

Blitting
Mit dem Kapittel Blitting demonstrieren wir, wie Sie eine primre Surface sowie eine Offscreensurface erstellen. Um die Grafik von der Offscreensurface auf die primre Surface zu kopieren, wird die Blt()-Methode zum Einsatz kommen. Weiterhin erklren wir die Einbindung von DirectX und DirectDraw in Ihre VB-Anwendung. Unser Ziel ist es, eine Grafik aus der Offscreensurface auf die

Kapitel 1 DirectDraw

43

primre Surface zu blitten. An der folgenden Grafik knnen Sie gut erkennen, welche Objekte wir erstellen mssen und wie die Objekte eingebunden sind.
DirectDrawCreate() CreateSurface()

primre Surface

Backbuffer Surface

Blt()

Bild 1.11: Einfaches Blitten vom Backbuffer auf die primre Surface mit der Blt()-Methode

Folgende Methoden werden in diesem Abschnitt vorgestellt. Sie sind die Grundlage fr alle DirectDraw-Anwendungen.
DirectDrawCreate() Erzeugt ein DirectDraw7-Objekt object.DirectDrawCreate (guid As Long) As DirectDraw7 object guid ein gltiges DirectX7-Objekt Adresse zu einem eindeutigen Display-Treiber, der erzeugt werden soll. Der String kann leer sein, dann wird der zur Zeit aktive Display-Treiber genommen. DDCREATE_EMULATIONONLY Es werden keine Hardware-Eigenschaften untersttzt. Alle Eigenschaften werden emuliert. DDCREATE_HARDWAREONLY Hardware-Eigenschaften werden niemals emuliert. Werden Eigenschaften genutzt, welche von der Hardware nicht untersttzt werden, so fhrt dies zu einem Fehler.

44

Blitting

TestCooperativeLevel() Ermittelt den aktuellen CooperativeLevelStatus fr eine Fensteranwendung oder Fullscreen-Anwendung object.TestCooperativeLevel() As Long object CreateSurface() Erzeugt ein DirectDrawSurface-Objekt object.CreateSurface( _ dd As DDSURFACEDESC2) As DirectDrawSurface7 object dd ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDSURFACEDESC2 enthlt die Beschreibungen der Surface ein gltiges DirectDraw7-Objekt

CreateSurfaceFromFile() Erzeugt ein DirectDrawSurface-Objekt aus einer Bitmap. object.CreateSurfaceFromFile( _ dd As DDSURFACEDESC2) As DirectDrawSurface7 object dd ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDSURFACEDESC2 enthlt die Beschreibungen der Surface

GetWindowsRect() Ermittelt die Eckwerte eines Rechtecks, welche den Clientbereich eines Fensters beschreibt. Call object.GetWindowRect(hwnd As Long, r As RECT) object hwnd r Blt() Kopiert Daten per Bit Block Transfer aus einem Speicherbereich in einen anderen object.Blt(destRect As RECT, ddS As DirectDrawSurface7, srcRect As RECT, flags As CONST_DDBLTFLAGS) As Long object ein gltiges DirectDrawSurface7-Objekt ein gltiges DirectDraw7-Objekt Handle eines Fensters, dessen Clientbereich ermittelt werden soll. Eine Variable vom Typ RECT, welche die ermittelten Werte aufnimmt.

Kapitel 1 DirectDraw

45

Blt() destRect Variablen vom Typ RECT, welche die Punkte oben links und unten rechts eines Rechtecks beschreiben. Wird dieser Wert nicht angegeben oder sind die Werte der Variablen leer, so wird der gesamte Bereicht der Ziel-Surface angenommen. Ein gltiges Surface-Objekt, welches die Daten aufnehmen soll. Variable vom Typ RECT, welche die Punkte oben links und unten rechts eines Rechtecks beschreiben. Wird dieser Wert nicht angegeben oder sind die Werte der Variablen leer, so wird der gesamte Bereicht der Quell-Surface angenommen. Eine Kombination von Argumenten aus der CONST_DDBLTFLAGS-Liste.

dds srcRect

Flags

Blitting bildet die Grundlage aller DirectDraw-Anwendungen. Deshalb erklren wir diese Technik von A bis Z. Das angestrebte Ziel ist nicht besonders spektakulr. Wir wollen lediglich ein Bild auf dem Monitor sichtbar machen. Das hrt sich nach keiner besonderen Herausforderung an, aber um dies zu erreichen, mssen wir einiges an Arbeit leisten. Um die Schematik zu verdeutlichen, knnen wir die anstehenden Aufgaben in vier Schritte unterteilen. Schritt 1 Schritt 2 Schritt 3 Schritt 4 Erstellen einer Form Variablen benennen Variablen initialisieren Blit

Schritt1: Erstellen einer Form ffnen Sie ein Standard-Visual-Basic-Projekt. Platzieren Sie eine Picturebox. Die Left- und die Top-Eigenschaften setzen Sie auf den Wert 0. Die Name-Eigenschaft der Picturebox belassen Sie auf dem Wert Picture1. In der Picturebox wird spter die Grafik dargestellt. Es ist nicht ntig, die Grafik in der Picturebox darzustellen, ebenso knnte die Grafik direkt auf dem Form Objekt dargestellt werden. Welche Objekte als Empfnger fr die Grafik geeignet sind, wird durch die Objekt-Eigenschaften bestimmt. So ist z.B. die Objekt-Zugriffsnummer (Handle) zwingend erforderlich. Das Handle ist ein ganzzahliger Wert, der von der Betriebsumgebung vergeben wird. Anhand von diesem Wert ist das Objekt eindeutig gekennzeichnet. Grundlegend kann man feststellen, das die Windows API auf solche Zugriffsnummern angewiesen ist. Schritt 2: Variablen benennen Zuerst mssen wir die DirectX7-Klassen einbinden.

46

Blitting

Die Einbindung erfolgt folgendermaen: ffnen Sie unter Visual Basic die Symbolleiste Projekt > Verweise. Es wird das Dialogfeld Verweise geffnet. Aktivieren Sie den Eintrag DirectX 7 for Visual Basic Type Library. Besttigen Sie mit OK. Die eigentliche Einbindung fr Ihr Projekt erreichen Sie folgendermaen:
Dim objDX as New DirectX7

Die DirectX7-Klasse kann man als Ursprung der DirectX-Technologie betrachten. Von diesem Punkt aus wird in alle Sektionen von DirectX verzweigt. Der grobe Rahmen wird durch DirectDraw, Direct3D, DirectSound, DirectInput, DirectPlay und DirectMusic gebildet.
Dim objDD As DirectDraw7

Wird bentigt um DirectDraw-Objekte zu erzeugen. DirectDraw-Objekte sind der Kern jeder DirectDraw-Anwendung. DirectDraw-Objekte kann man als Reprsentanten der Display-Devices betrachten. Insofern das Display-Device Hardwarebeschleunigungen zulsst, werden diese ber das DirectDraw-Objekt umgesetzt.
Dim objDDSurf As DirectDrawSurface7 Dim objDDPrimSurf As DirectDrawSurface7

Wird bentigt um DirectDrawSurface-Objekte zu erzeugen. Als Surface wird ein zusammenhngender Speicherbereich bezeichnet. Surfaces werden normalerweise im Speicherbereich der Grafikkarte erzeugt, knnen aber auch im Systemspeicher existieren. Da die Verwaltung der Videografikspeichers von der Videografikkarte bernommen wird, kann eine Surface parallel zum normalen CPUTakt abgearbeitet werden. Dies macht sich natrlich auch durch einen erheblichen Performancegewinn bemerkbar. Es werden in der Regel mehr als eine Surface erzeugt.
Dim ddsd1 As DDSURFACEDESC2 Dim ddsd2 As DDSURFACEDESC2

Enthlt die Beschreibung einer DirectDrawSurface. DDSURFACEDESC2 steht vor der DirectDraw.CreateSurface()-Methode. Schritt 3: Variablen initialisieren Mit dem Initialisieren der Variablen ist das Erzeugen der notwendigen Direct Draw-Objekte gemeint. Als Erstes wird der Zugriff auf die Grafikkarte erzeugt.
Set objDD = objDX.DirectDrawCreate("")

Kapitel 1 DirectDraw

47

Der leere String bei der DirectDrawCreate()-Methode besagt, dass das primre Display-Device genutzt werden soll.
Call objDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)

Mit der SetCooperativeLevel()-Methode wird die grundlegende Darstellungsform bestimmt. Me.hWnd gibt uns das Handle (Zugriffsnummer) des aktiven FormObjeks. DDSCL_NORMAL besagt, dass eine normale Windows-Anwendung vorliegt. Es werden keine nderungen an der Farbtiefe oder am Display vorgenommen. Direct Draw passt sich dem aktuellen Form-Objekt an. Wir bentigen zwei Surfaces. Eine sichtbare und eine unsichtbare. Der Trick mit der Geschwindigkeit liegt darin, dass alle anfallenden Arbeiten auf der unsichtbaren Surface vorgenommen werden. Nach Abschluss der Arbeiten wird der Inhalt der unsichtbaren auf die sichtbare geblittet. Surface 1: Jetzt folgen die genauen Beschreibungen der DirectDraw-Surface.
ddsd1.lFlags = DDSD_CAPS

Gibt uns den Zugriff auf die ddsCaps-Datenstruktur frei. Somit ist die ddsCapsDatenstruktur als gltiges Mitglied definiert.
ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE

Hiermit wird festgelegt, dass ddsd1 eine primre, fr den Anwender sichtbare Surface sein soll. Nun knnen wir die primre DirectDraw-Surface erzeugen.
Set objDDPrimSurf = objDD.CreateSurface(ddsd1)

Das Erzeugen erfolgt problemlos, da alle Parameter in ddsd1 definiert wurden. Surface 2:
ddsd2.lFlags = DDSD_CAPS

Auch bei der Surface 2 geben wir die ddsCaps-Datenstruktur als gltiges Mitglied frei.
ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN

ddsd2 wird diesmal nicht als sichtbare Surface definiert, sondern als unsichtbare Offscreensurface. Die generelle Aufgabe einer Offscreensurface ist es, Grafikdaten zu speichern. Diese Daten werden dann auf die primre Surface geblittet.
Set objDDSurf = objDD.CreateSurfaceFromFile("Beispielbitmap", _ ddsd2)

48

Blitting

Auch beim Erzeugen der eigentlichen Surface macht sich eine kleine nderung bemerkbar. Die eingesetzte Methode ist nicht mehr CreateSurface(), sondern CreateSurfaceFromFile(). Der Unterschied lsst ich bereits vom Namen ableiten. Diesmal wird die Surface direkt mit den Grafikdaten einer Bitmap gefllt. Surface 1 und Surface 2 sind definiert. Also steht dem Blitting nichts mehr im Weg. Schritt 4: Blit Zum Blitten bentigen wir nur einen Befehl. Vorher mssen wir zwei rechteckige Bereiche definieren, welche uns zeigen, von wo die Grafikdaten kommen und wohin Sie sollen. r1 und r2 sind jeweils Zeiger auf eine RECT-Datenstruktur. Um die genaue Gre des Ziels zu ermitteln, bedienen wir uns der Methode GetWin dowRect(). Diese Methode schreibt uns die Daten des Clientbereiches (auf den das Handel weist) in die RECT-Struktur von r1. Die Struktur von r2 knnen wir durch einfache Zuweisungen fllen. Dies ist mglich, da diese Surface durch die Methode CreateSurfaceFromFile() erzeugt wurde und somit schon mit Daten gefllt ist und eine logische Gre besitzt. Ist die Gre des Zielrechtecks ungleich der Gre des Quellrechtecks, so werden die Grafikdaten automatisch angepasst.
Dim r1 As RECT Dim r2 As RECT Call objDX.GetWindowRect(Picture1.hWnd, r1) r2.Bottom = ddsd2.lHeight r2.Right = ddsd2.lWidth

Jetzt sind alle Daten komplett. Es folgt das lang erwartete Ergebnis. Blitting per DirectX.
ddrval = objDDPrimSurf.blt(r1, objDDSurf, r2, DDBLT_WAIT)

Der Vollstndigkeit halber sei noch DDBLT_WAIT erklrt. Dieses Flag gibt lediglich an, das DirectDraw auf die Fertigstellung des Blitvorgangs warten soll. Dieses Warten wird auch als synchrones Arbeiten bezeichnet. Beispiel (Blitting) Nachdem Sie das Kapitel Blitting gelesen haben, sollte dieses Beispiel kein Problem darstellen. Folgende Grafik zeigt die Bitmap, welche dargestellt werden soll. Im Deklarationsabschnitt werden die Surfaces sowie die notwendigen DDSURFACEDESC2 definiert. Natrlich werden auch die Knotenpunkte von DirectX und dem untergeordneten DirectDraw eingerichtet.

Kapitel 1 DirectDraw

49

Bild 1.12: Bitmap fr das Blitting-Beispiel Dim Dim Dim Dim Dim Dim objDX As New DirectX7 objDD As DirectDraw7 objDDSurf As DirectDrawSurface7 objDDPrimSurf As DirectDrawSurface7 ddsd1 As DDSURFACEDESC2 ddsd2 As DDSURFACEDESC2

Um die bersicht in den Programmen zu wahren, werden alle notwendigen Arbeiten ber Subroutinen erledigt. Somit bleibt fr die Abschnitte Form_Load() und Picture1_Paint() nur der Aufruf von Init() und Blt().
Private Sub Form_Load() Init End Sub

Der Aufruf der Blt() Routine wurde mit Absicht in das Paint-Ereignis von Picture1 gelegt. Dadurch wird die Grafik der Anwendung immer aktualisiert sobald das Fernster z.B. verschoben, berlagert oder in der Gre gendert wird. Eben immer wenn das Paint-Ereignis ausgelst wird.

50

Blitting

Private Sub Picture1_Paint() Blt End Sub

Die Subroutine Init() erledigt die meiste Arbeit. Zugriff auf die Grafikkarte herstellen, Top Level der Anwendung setzen und die beiden Surfaces einrichten und erstellen.
Private Sub Init() Set objDD = objDX.DirectDrawCreate("") Call objDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL) 'Surface 1 erzeugen ddsd1.lFlags = DDSD_CAPS ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Set objDDPrimSurf = objDD.CreateSurface(ddsd1) ' Surface 2 erzeugen ddsd2.lFlags = DDSD_CAPS ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Set objDDSurf = objDD.CreateSurfaceFromFile(App.Path & _ "\BlittingToTheScreen.bmp", ddsd2) End Sub

Fr den kleinen Blitabschnitt bleibt nicht mehr viel zu tun. Das Zielrechteck in der Gre der Picturebox definieren. Die Gre der Quellgrafik ermitteln und in einer RECT-Struktur speichern. Zum Abschluss bleibt noch die eigentliche Blit()Methode.
Private Sub Blt() Dim r1 As RECT Dim r2 As RECT Call objDX.GetWindowRect(Picture1.hWnd, r1) r2.Bottom = ddsd2.lHeight r2.Right = ddsd2.lWidth ddrval = objDDPrimSurf.Blt(r1, objDDSurf, r2, DDBLT_WAIT) End Sub

Sollten Zielrechteck und Quellrechteck nicht die gleiche Gre besitzen, wird die Grafik automatisch angepasst. Dies ist eine recht praktische Eigenschaft der Blt()Methode. Dieses automatische Dehnen oder Stauchen einer Bitmap verbraucht allerdings viel Rechenzeit des Systems. Wenn Sie spter High-PerformanceAnwendungen erstellen mchten, sollten Sie akribisch auf die Einhaltung der Bitmapgren achten.

Kapitel 1 DirectDraw

51

1.3

Sprites durch Transparenz


Transparentes Blitting basiert auf dem Konzept von Blitting. Bei dieser Technik wird die Illusion erzeugt, als wrde ein nicht rechteckiger Bereich geblittet. Dies ist wie gesagt eine Illusion. Blit bezieht sich immer auf einen rechteckigen Bereich. Der Eindruck einen nicht rechteckigen Bereich zu blitten, entsteht bei der Darstellung von Sprites. Sprites sind in der Regel nicht rechteckig. Wird nun ein Sprite dargestellt, sieht es so aus, als wrde nur das eigentliche Sprite bewegt. In Wirklichkeit ist es jedoch ein Rechteck. Die Illusion wird erzeugt, indem alle Pixel welche nicht zum Sprite gehren als transparent betrachtet werden und die Pixel auf der Ziel-Surface nicht berschreiben. Die Kunst beim Erzeugen eines Sprites liegt bei der Definition einer transparenten Farbe oder eines transparenten Farbbereiches. Diese transparenten Farben werden in einem Farbschlssel gespeichert. Dieser Farbschlssel wird genutzt, um Farbbereiche der Sprite Surface fr die Blitter Methoden zu sperren.
CreateClipper() Erzeugt ein DirectDrawClipper-Objekt DirectDrawSurface7.GetClipper, DirectDrawSurface7.SetClipper object.CreateClipper(flags As Long) As DirectDrawClipper object flags BltFast() Kopiert Daten per Bit Block Transfer aus einem Speicherbereich in einen anderen. Diese Methode kann nicht auf einen Clipper-Bereich zugreifen. Siehe die Blt()-Methode. object.BltFast( dx As Long, dy As Long, ddS As DirectDrawSurface7, _ srcRect As RECT, trans As CONST_DDBLTFASTFLAGS) As Long object dx, dy dds srcRect trans Ein gltiges DirectDrawSurface7-Objekt. Koordinatenpaar auf der Zielsurface. Quellsurface, aus der die Grafik kopiert werden soll. Eine gltige RECT-Struktur, welche den Bereich auf der Quellsurface beschreibt, von der die Grafikdaten kopiert werden sollen. DDBLTFAST_DESTCOLORKEY = 2 Transparentes Blit unter Verwendung des Ziel-Farbschlssels. DDBLTFAST_DONOTWAIT = 32 Wartet nicht, bis der Blitter fertig ist. DDBLTFAST_NOCOLORKEY = 0 Ein gltiges DirectDraw7-Objekt. Wird zur Zeit nicht verwendet. Muss 0 sein.

52

Sprites durch Transparenz

BltFast() Normales Blit ohne Farbschlssel ohne Transparenz. DDBLTFAST_SRCCOLORKEY = 1 Transparentes Blit unter Verwendung des Source-Farbschlssels. DDBLTFAST_WAIT = 16 Wartet, bis der Blitter fertig ist.

Wir werden eine primre Surface sowie drei Offscreensurfaces erstellen. Eine Offscreensurface verwenden wir als Backbuffer. Die zweite wird als Container fr das Hintergrundbild bentigt. In der dritten Surface wird das Sprite gespeichert. Auf der Backbuffersurface werden Hintergrund und Sprite miteinander kombiniert und anschlieend auf die primre Surface geblittet. Zustzlich richten wir noch das Clipper-Objekt ein. Dieses sichert uns eine saubere Darstellung in der Windowsumgebung. Das eigentliche DirectDraw-Fenster kann von anderen Fenstern berlagert werden. Ohne den Clipper wrde die Grafik des DirectDrawFensters immer im Vordergrund gezeichnet. Die Auswirkungen des ClipperObjekts knnen Sie am besten im direkten Vergleich mit der Beispielanwendung Blitting erkennen. In dieser Anwendung ist es nicht mglich, das DirectDrawFenster zu berlagern. Die folgende Grafik zeigt Ihnen die bentigten DirectX-Objekte sowie deren Einbindung. Zum einfachen Verstndnis knnen wir diese Technik in fnf Schritte zerlegen. Schritt 1: Erstellen einer Form ffnen Sie ein Standard-Visual-Basic-Projekt. Platzieren Sie eine Picturebox. Die Left- und die Top-Eigenschaften setzen Sie auf den Wert 0. Die Name-Eigenschaft der Picturebox setzen Sie auf den Wert Picture1. In der Picturebox wird spter die Grafik dargestellt. Schritt 2: Variablen benennen
Dim objDX As New DirectX7 Dim objDD As DirectDraw7

Standard-DirectX-Einbindungen (siehe Projekt Blitting).


Dim Dim Dim Dim objDDBackgroundSurf As DirectDrawSurface7 objDDSpriteSurf As DirectDrawSurface7 objDDScreenSurf As DirectDrawSurface7 objDDBackbufferSurf As DirectDrawSurface7

Kapitel 1 DirectDraw

53

DirectDrawCreate() CreateSurface()

primre Surface

Backbuffer Surface

Blt()

Offscreen Surface

Blt() BltFast()

Bild 1.13: Erweitertes Blitten

Wir bentigen vier Surfaces. ObjDDScreenSurf wird die primre Surface. ObjDDBackgroundSurf wird die unsichtbare Surface mit der Hintergrundgrafik. ObjDDSpriteSurf wird die Grafikdaten des Sprites aufnehmen. ObjBackbuffer wird das gemischte Bild von objDDBackgroundSurf und objDDSpriteSurf aufnehmen, bevor es der primren Surface objDDScreenSurf bergeben wird.
Dim objDDClip As DirectDrawClipper

Das Clipper-Objekt ist neu. Mit dem Clipper-Objekt erhalten Sie den Zugriff auf einen ausgewhlten rechteckigen Bereich einer Surface. Der ausgewhlte Bereich wird wiederum durch eine RECT-Struktur beschrieben.
Dim Dim Dim Dim ddsdBackground As DDSURFACEDESC2 ddsdSprite As DDSURFACEDESC2 ddsdScreen As DDSURFACEDESC2 ddsdBackbuffer As DDSURFACEDESC2

54

Sprites durch Transparenz

Die DDSURFACEDESC2 nehmen wieder die Surface-Beschreibungen auf.


Dim rBackbuffer As RECT Dim rBackground As RECT Dim rSprite As RECT

Zum Abschluss werden die Variablen fr die RECT-Strukturen festgelegt. Schritt 3: Variablen initialisieren Insgesamt mssen wir vier Surfaces, ein Clipper Objekt und drei RECT-Strukturen einrichten. Beginnen wir mit den vier Surfaces. Surface 1 (primre Surface)
ddsdScreen.lFlags = DDSD_CAPS ddsdScreen.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Set objDDScreenSurf= objDD.CreateSurface(ddsdScreen)

Hier ist nichts Neues zu entdecken. Farbtiefe und Auflsung der Anwendung werden nicht gendert. Sie wird als primre Surface bestimmt und ist somit fr den Anwender sichtbar. Surface 2 (Hintergrundbild)
ddsdBackground.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT

Wir geben uns den Zugriff auf die ddsCaps- sowie Width- und Height-Eigenschaften frei.
ddsdBackground.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN

Die zuknftige Surface ddsdBackground wird als unsichtbare Offscreenoberflche definiert.


ddsdBackground.lWidth = Picture1.Width ddsdBackground.lHeight = Picture1.Height

Durch die Freigabe der Width- und Height-Eigenschaften als gltige Mitgliedsdaten knnen wir nun Zuweisungen treffen. Hier wird die Gre des Hintergrundes der Gre des Vordergrundes angepasst. Da wir ein aus verschiedenen Surfaces gemischtes Bild ausgeben mchten, sind die Gren der primren (sichtbaren) Surface und der unsichtbaren (sekundren) Surface von groer Bedeutung. Sie sollten gleich gro sein.
Set objDDBackgroundSurf = _ objDD.CreateSurfaceFromFile("Bild.bmp", ddsdBackground)

Die Hintergrundsurface erstellen und mit den Bilddaten fllen.

Kapitel 1 DirectDraw

55

Surface 3 (Sprite)
ddsdSprite.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsdSprite.lWidth = 64 ddsdSprite.lHeight = 64 ddsdSprite.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Set objDDSpriteSurf = _ objDD.CreateSurfaceFromFile("Sprite.bmp", ddsdSprite)

Hier wird genau das Gleiche wie bei Surface 2 gemacht. Nur die Gre der Sprite Surface wird auf 64 x 64 Pixel begrenzt. Mehr ist nicht notwendig. Surface 4 (Backbuffer) Die Backbuffersurface wird bentigt, um das aus Surface 2 und 3 gemischte Bild auf der Surface 1 auszugeben.

Surface 2 Hintergrund

Surface 3 Sprite

Surface 4 Backbuffer

Surface 1 primre Surface

Bild 1.14: Zusammenbau von Hintergrund und Sprite

Warum wird der Umweg ber den Backbuffer gemacht? Bedeutet dies nicht einen Performanceverlust? Die Performance wird durch das Zwischenspeichern der Grafikdaten positiv beeinflusst. Eine direkte Zusammenfhrung auf der sichtbaren Surface wrde in Zusammenhang mit Aktualisierungen der gesamten Windowsoberflche stehen. Dadurch wirkt sich der Backbuffer als hilfreiches Instrument zur Performance-

56

Sprites durch Transparenz

steigerung aus. Wrde man die Grafiken von Surface 2 und 3 auf der Surface 1 direkt durchfhren, wrde der Aufbau durch ein unangenehmes Flimmern berschattet. Auerdem ist ein Arbeiten im Backbuffer (also rein im Speicher des Computers) von der Hardwareverarbeitung des angeschlossenen Bildschirms nicht abhngig. Ein Arbeiten auf einer sichtbaren Surface bedeutet immer ein Warten auf den Rasterstrahl des Monitors. Dies entfllt beim Arbeiten im Speicher. In diesem Beispiel werden lediglich 2 Surfaces zusammengefhrt. Stellen Sie sich einmal vor, Sie wollen aber 10, 20 oder 100 Surfaces zusammenfhren, so ist es sinnvoll, dies im schnellen Speicher zu tun und anschlieend alles in einem Schwung auf die sichtbare Surface zu blitten. Das Handling der Surfaces wird oftmals von den Prozessoren der Grafikkarte bernommen und entlastet somit die ohnehin schon berarbeitet CPU des Computers. Die Technik des Backbuffers:
ddsdBackbuffer.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH

Den Zugriff auf die ddsCaps-Struktur sowie der Height- und Width-Eigenschaften freigeben.
ddsdBackbuffer.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or _ DDSCAPS_SYSTEMMEMORY

Auch der Backbuffer wird als Offscreensurface festgelegt. Zustzlich wird der Speicherort explizit in den Systemspeicher verlagert. Dies ist nicht unbedingt notwendig und fhrt zu einem ganz erheblichen Geschwindigkeitsverlust. Dadurch stellen wir aber sicher, das genug Speicher zur Verfgung steht. Dennoch sei nochmals ausdrcklich gesagt, das der Backbuffer im Videospeicher besser aufgehoben wre und die Anwendung eine deutlich hhere Performance htte.
ddsdBackbuffer.lWidth = Picture1.Width ddsdBackbuffer.lHeight = Picture1.Height

Der Backbuffer wird auf die Gre der Picturebox begrenzt. Es soll schlielich kein Speicher vergeudet werden. Ein zu kleiner Backbuffer wre ebenfalls nicht gut. Auerdem msste DirectX die unterschiedlichen Gren skalieren und dies wrde sehr viel Rechenzeit beanspruchen.
Set objDDBackbufferSurf = objDD.CreateSurface(ddsdBackbuffer)

Das Erstellen der Surface kennen wir ja schon. Das Clipper-Objekt: Nachdem die Surfaces eingerichtet sind, wird nun das Clipper-Objekt definiert. Der normale Gebrauch eines Clipper-Objekts ist es, die Grenzen einer Surface oder eines Fensters festzulegen. Der Sinn wird anhand eines Beispiels am besten deutlich. Wir wollen ein Sprite von links nach rechts ber den Bildschirm bewegen. Natrlich soll der Sprite sanft in den Bildschirm bewegt werden und auch

Kapitel 1 DirectDraw

57

wieder sanft aus dem Bildschirm verschwinden. Dazu ist es notwendig, Teile des Sprites auerhalb des definierten Bildschirmbereiches auszulagern. Dies wrde zu einem Fehler fhren, da die ausgelagerten Spritegrafiken in einen nicht reservierten Speicherbereich geschrieben wrden. Durch das Clipper-Objekt wei DirectDraw, welcher Teil des Sprites kopiert werden darf und welcher nicht. Das Clipper-Objekt wird im Regelfall in der gleichen Gre wie die Zielsurface erstellt. Somit ist der gesamte Bereich fr den Bit Block Transfer erlaubt.

Ziel Surface Sprite normaler Blitterbereich auerhalb des normalen Blitterbereichs


Bild 1.15: Blitterbereiche

Die Funktionsweise des Clipper-Objekts knnen Sie an einem weiteren Merkmal erkennen. Vergleichen Sie die beiden Anwendungen Blitting und Tranzparenz. Blitting arbeitet ohne Clipper. Wenn Sie nun irgendein Windowsfenster nehmen und ber das Blittingfenster schieben, so wird das Blittingfenster durch das Windowsfenster scheinen. Dies ist natrlich ein ungewnschter Effekt. Wenn Sie das Clipper-Objekt nutzen, tritt dieser Effekt nicht mehr auf. Kommen wir nun zur Einbindung des Clipper-Objekts in die DD-Anwendung.
Set objDDClip = objDD.CreateClipper(0)

Die CreateClipper() Methode erzeugt ein Clipper-Objekt.


objDDClip.SetHWnd Picture1.hWnd

Verbindet die Picturebox, in der die Grafik dargestellt werden soll, mit dem Clipper-Objekt.
objDDScreenSurf.SetClipper objDDClip

Die primre Surface wird mit dem Clipper-Objekt verbunden.

58

Sprites durch Transparenz

Jetzt ist es an der Zeit, die RECT-Strukturen zu bestimmen. Wie zum Anfang dieses Abschnitts bereits erwhnt, sind insgesamt drei RECT-Strukturen zu bestimmen. Da wre einmal die RECT-Struktur des Hintergrundbildes. Da wir immer den gesamten Hintergrund sehen mchten, knnen wir die gesamte Gre des Hintergrundes festlegen. Dies tun wir mit folgenden Anweisungen:
rBackground.Bottom = ddsdBackground.lHeight rBackground.Right = ddsdBackground.lWidth

Es folgt die RECT-Struktur des Sprites. Auch hier wollen wir das ganze Sprite sehen. Somit definieren wir:
rSprite.Bottom = ddsdSprite.lHeight rSprite.Right = ddsdSprite.lWidth

Da wir Hintergrund und Sprite im Backbuffer zusammenfhren und der Backbuffer die gleiche Gre wie das Hintergrundbild hat, wird auch hier die gesamte Gre definiert.
rBackbuffer.Bottom = ddsdBackbuffer.lHeight rBackbuffer.Right = ddsdBackbuffer.lWidth

An dieser Stelle sei schon einmal erwhnt, das wir spter noch weitere RECTStrukturen bentigen. Diese sind in Ihrer Position aber variabel und werden auf lokaler Ebene definiert. Schritt 4: Erstellen des Farbschlssels Um den Hintergrund des Sprites transparent erscheinen zu lassen, ist es notwendig, diesen durch einen Farbschlssel zu kennzeichnen. Dieser Farbschlssel ist definiert durch eine Variable vom Typ DDCOLORKEY. Der Farbschlssel bezieht sich nicht nur auf eine Farbe, sondern definiert einen Farbbereich. Der Aufbau der Variable DDCOLORKEY ist wie folgt:
Type COLORKEY high As Long low As Long End Type

Die Einbindung in die Anwendung gestaltet sich recht einfach. Zuerst wird eine Variable als DDCOLORKEY definiert.
Dim Colorkey As DDCOLORKEY

Anschlieend wird der Farbbereich definiert.


Colorkey.low = 0 Colorkey.high = 0

Kapitel 1 DirectDraw

59

Somit ist die transparente Farbe als Schwarz definiert. Es fehlt noch die Zuweisung an die richtige Surface. In diesem Fall ist das die Spirtesurface.
objDDSpriteSurf.SetColorkey DDCKEY_SRCBLT, Colorkey

DDCKEY_SRCBLT besagt, dass es sich um einen Farbschlssel fr eine Quellsurface handelt. Ebenso wird festgelegt, das es sich um Blitter-Aktionen handelt. Die schwarze Hintergrundfarbe der Sprite Surface wird bei allen Blitter-Aktionen nicht kopiert. Sie wird einfach ignoriert. Schritt 5: Blit Der Blit-Vorgang ist eigentlich ganz einfach. Von der Technik sieht es folgendermaen aus. Die Grafik, die wir spter auf dem Bildschirm sehen werden, wird vorher im Backbuffer zusammengesetzt. Hierzu knnten wir den gesamten Hintergrund und anschlieend das Sprite in den Backbuffer kopieren und dann auf die primre Surface. Diese Technik wrde funktionieren, wre aber eine sinnlose Vergeudung von Systemressourcen. Eine wesentlich schnellere Methode ist es, nur die vernderten Grafikdaten der Backbuffersurface zu bearbeiten. Wenn man nun berlegt, welche Einflsse den Backbuffer verndern knnen, kann man sehr schnell eine Lsung finden. Zum einen wre da der Hintergrund. Dieser wird in den Backbuffer kopiert. Dieser wird sich im Laufe der Anwendung aber nicht mehr ndern. Somit bleibt nur noch das Sprite. Das Sprite bewegt sich ber den Bildschirm und kopiert somit immer wieder neue Daten in den Backbuffer. Da das Sprite aber nur einmal erscheinen soll, mssen die alten Grafikdaten korrigiert werden. Lange Rede kurzer Sinn fangen wir an. 1. Wiederherstellen des Backbuffers Backbuffer und Hintergrund haben genau die gleichen Dimensionen. Das erleichtert die Arbeit ungemein. Wir bestimmen die alte Position des Sprites und eine temporre RECT-Struktur mit den Maen der Sprite Surface. Dann schneiden wir diesen Bereich aus der Hintergrundsurface aus und kopieren Ihn in den Backbuffer. Somit ist der Hintergrund wieder hergestellt. Damit dies noch etwas schneller geht, nutzen wir die Methode BltFast().
Dim rClean As RECT rClean.Left = lastX rClean.Top = lastY rClean.Right = lastX + ddsdSprite.lWidth rClean.Bottom = lastY + ddsdSprite.lHeight Call objDDBackbufferSurf.BltFast(lastX, lastY, _ objDDBackgroundSurf, rClean, DDBLTFAST_WAIT)

2. Kopieren des Sprites an die neue Position

60

Sprites durch Transparenz

Wir bestimmen die neue Position des Sprites. Anschlieend definieren wir eine temporre RECT-Struktur mit den Maen der Spritesurface. Abschlieend wird die Spritesurface an die neue Position in die Backbuffersurface kopiert. Hierzu verwenden wir nicht die BltFast()-Methode, sondern die Blt()Methode. Die BltFast()-Methode knnen wir nicht verwenden, da wir mit dem Sprite oder Teilen des Sprites in den Clipperbereich geraten knnten. Bei der Blt()-Methode ist das Flag DDBLT_KEYSRC zu beachten. Dieses Flag besagt, dass auf die Quellsurface der Farbschlssel anzuwenden ist.
Dim rtemp As RECT rtemp.Left = x rtemp.Top = y rtemp.Right = x + ddsdSprite.lWidth rtemp.Bottom = y + ddsdSprite.lHeight objDDBackbufferSurf.Blt rtemp, objDDSpriteSurf, rSprite, _ DDBLT_KEYSRC Or DDBLT_WAIT

3. Den erstellten Backbuffer auf die primre Surface kopieren Dieser Teil ist identisch mit dem Blit-Vorgang aus dem Kapitel Blitting.
Dim rPrim As RECT Call objDX.GetWindowRect(Picture1.hWnd, rPrim) Call objDDScreenSurf.Blt(rPrim, objDDBackbufferSurf, _ rBackbuffer, DDBLT_WAIT)

Beispiel (Sprites durch Transparenz) Dieses Beispiel beginnt mit einem kleinen Auswahlfenster. Hier werden Sie gefragt, ob Sie den Backbuffer in den Systemspeicher oder in den Videospeicher legen wollen. Probieren Sie beides einmal aus. Sie werden sehen, das der Videospeicher wesentlich schneller ist. Den Backbuffer in den Videospeicher zu legen ist nicht immer mglich; da wir hier aber sehr kleine Grafikdaten verwenden, kommt es zu keinen Problemen. Betrachten Sie das Bildschirmfoto fr dieses Beispiel. Ihnen wird sicherlich die kleine Biene auffallen. Diese Biene ist unser Sprite. Im Deklarationsabschnitt fallen natrlich die vier Surfaces auf. Im Gegensatz zu dem Beispiel Blitting bentigen wir diesmal zwei Surfaces mehr. Zum einen ist das die Backbuffersurface und zum anderen die Sprite Surface.
Dim Dim Dim Dim Dim Dim Dim Dim objDX As New DirectX7 objDD As DirectDraw7 objDDBackgroundSurf As DirectDrawSurface7 objDDScreenSurf As DirectDrawSurface7 objDDSpriteSurf As DirectDrawSurface7 objDDBackbufferSurf As DirectDrawSurface7 ddsdBackground As DDSURFACEDESC2 ddsdScreen As DDSURFACEDESC2

Kapitel 1 DirectDraw

61

Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim

ddsdSprite As DDSURFACEDESC2 ddsdBackbuffer As DDSURFACEDESC2 rBackground As RECT rScreen As RECT rSprite As RECT rBackbuffer As RECT lastX As Single lastY As Single objDDClip As DirectDrawClipper MoveX As Single GameLoop As Boolean Richtung As Boolean

Bild 1.16: Hintergrund mit einem nicht animierten Sprite

In dem Form_Load-Ereignis verzweigen wir in die Init()-Routine und anschlieend in die Game()-Routine. Die Init erledigt wieder einmal die meiste Arbeit. Bevor es in die Game()-Routine geht, wird noch eine Indexvariable gesetzt, welche der Game()-Routine das Arbeiten erlaubt.

62

Sprites durch Transparenz

Private Sub Form_Load() Init GameLoop = True game End Sub Private Sub Init() Me.Show Set objDD = objDX.DirectDrawCreate("") Call objDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL) 'Surface 1 erzeugen (Bildschirm) ddsdScreen.lFlags = DDSD_CAPS ddsdScreen.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Set objDDScreenSurf = objDD.CreateSurface(ddsdScreen) ' Surface 2 erzeugen (Hintergrund) ddsdBackground.lFlags = DDSD_CAPS Or DDSD_WIDTH Or _ DDSD_HEIGHT ddsdBackground.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN ddsdBackground.lWidth = Picture1.Width ddsdBackground.lHeight = Picture1.Height Set objDDBackgroundSurf = _ objDD.CreateSurfaceFromFile(App.Path & _ "\UsingTransparancy.bmp", ddsdBackground) ' Surface 3 erzeugen (Sprite) ddsdSprite.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsdSprite.lWidth = 64 ddsdSprite.lHeight = 81 ddsdSprite.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Set objDDSpriteSurf = objDD.CreateSurfaceFromFile _ (App.Path & "\Biene.bmp", ddsdSprite) ' Surface 4 erzeugen (Backbuffer) ddsdBackbuffer.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or _ DDSD_WIDTH

Jetzt macht sich die Auswahl des Speicherortes beim Login bemerkbar. Systemspeicher oder Videospeicher? Das ist hier die Frage.
If Form2.Option1.Value = True Then ddsdBackbuffer.ddsCaps.lCaps = _ DDSCAPS_OFFSCREENPLAIN Or DDSCAPS_SYSTEMMEMORY Else ddsdBackbuffer.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN End If ddsdBackbuffer.lWidth = Picture1.Width ddsdBackbuffer.lHeight = Picture1.Height Set objDDBackbufferSurf = _ objDD.CreateSurface(ddsdBackbuffer) ' Clipper Objekt erzeugen

Kapitel 1 DirectDraw

63

Set objDDClip = objDD.CreateClipper(0) objDDClip.SetHWnd Picture1.hWnd objDDScreenSurf.SetClipper objDDClip ' RectStrukturen rBackground.Bottom = ddsdBackground.lHeight rBackground.Right = ddsdBackground.lWidth rSprite.Bottom = ddsdSprite.lHeight rSprite.Right = ddsdSprite.lWidth rBackbuffer.Bottom = ddsdBackbuffer.lHeight rBackbuffer.Right = ddsdBackbuffer.lWidth

Der Farbschlssel filtert die Farbe Schwarz aus der Spritegrafik heraus. Somit wird der Hintergrund des Sprites unsichtbar, da er bei den Blitteraktionen ignoriert wird. Die RGB-Funktion gibt uns einen Wert vom Typ Long zurck. So wird er von der DDCOLORKEY-Struktur verlangt.
' Farbschlssel definieren Dim Colorkey As DDCOLORKEY Colorkey.low = RGB(0, 0, 0) Colorkey.high = RGB(0, 0, 0) objDDSpriteSurf.SetColorkey DDCKEY_SRCBLT, Colorkey ' Kopieren des Hintergrundbildes in den Backbuffer Call objDDBackbufferSurf.Blt(rBackbuffer, _ objDDBackgroundSurf, rBackground, DDBLT_WAIT) End Sub

Die Sub game() sorgt fr die Bewegung des Sprites. Hier luft eine Do...LoopSchleife. Wichtig ist die Anweisung DoEvents. Somit kann das Betriebssystem neben dieser Schleife auch noch andere Aufgaben bernehmen, z.B. auf einen Mausklick reagieren.
Private Sub game() Do While GameLoop = True If Richtung = True Then MoveX = MoveX + 2 Else MoveX = MoveX 2 End If If MoveX > Picture1.ScaleWidth ddsdSprite.lWidth Then _ Richtung = False If MoveX < 3 Then Richtung = True Blt MoveX, 200 DoEvents Loop If GameLoop = False Then End End Sub

64

Sprites durch Transparenz

Jetzt kommt es zur eigentlichen Blitteraktion. Dies funktioniert immer nach dem gleichen Prinzip: den Hintergrund an der Stelle, wo das Sprite verschwinden soll, restaurieren. Anschlieend das Sprite an die neue Stelle in den Backbuffer kopieren. Zum Abschluss den neu erstellten Backbuffer auf die sichtbare primre Surface blitten.
Private Sub Blt(ByVal X As Single, ByVal Y As Single)

Hintergrund restaurieren!
If lastX <> 0 Then Dim rClean As RECT rClean.Left = lastX rClean.Top = lastY rClean.Right = lastX + ddsdSprite.lWidth rClean.Bottom = lastY + ddsdSprite.lHeight Call objDDBackbufferSurf.BltFast(lastX, lastY, _ objDDBackgroundSurf, rClean, DDBLTFAST_WAIT) End If

Sprite an die neue Position kopieren!


Dim rTemp As RECT rTemp.Left = X rTemp.Top = Y rTemp.Right = X + ddsdSprite.lWidth rTemp.Bottom = Y + ddsdSprite.lHeight objDDBackbufferSurf.Blt rTemp, objDDSpriteSurf, rSprite, _ DDBLT_KEYSRC Or DDBLT_WAIT lastX = X lastY = Y Call objDX.GetWindowRect(Picture1.hWnd, rScreen)

Neu erstellten Backbuffer in die primre Surface kopieren!


Call objDDScreenSurf.Blt(rScreen, objDDBackbufferSurf, _ rBackbuffer, DDBLT_WAIT) End Sub

Es bleiben noch zwei Subroutinen brig. Die mssen eigentlich auch nicht erklrt werden. Sie dienen legendlich als Mglichkeit das Programm zu beenden. Das MausDown-Ereignis wre nicht mglich, wenn die DoEvents-Anweisung in der game()-Routine fehlen wrde.
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As _ Integer) GameLoop = False End Sub

Kapitel 1 DirectDraw

65

Private Sub Picture1_MouseDown(Button As Integer, Shift As _ Integer, X As Single, Y As Single) GameLoop = False End Sub

1.4

Fullscreen
Full Screen Mode bedeutet, dass die Anwendung nicht mehr in einem Windowsfenster ausgefhrt wird, sondern exklusiv auf einer eigenen Oberflche. Die Anwendungen unterscheiden sich im Wesentlichen kaum von einer normalen Windows-Anwendung. Dieses Kapitel baut auf dem Kapitel Sprites durch Transparenz auf und zeigt nur die nderungen die Sie durchfhren mssen. Die neuen Methoden werden hauptschlich dafr verwendet, um einen exklusiven Zugriff auf die Grafikkarte zu erhalten. Dieser Zugriff ist bei einer FullscreenAnwendung erforderlich. Da wir uns die exklusiven Rechte der Grafikkarte sichern, steht der Anwendung eine grere Performance zur Verfgung. Die Performancesteigerung wird nicht unbedingt sichtbar, da im Regelfall die Flip()Methode mit dem Zeilenaufbau des Monitors synchronisiert wird. Die Flip()Methode ersetzt die Blt()-Methode. Alternativ kann man mit der Flip()-Methode auch unsynchron arbeiten. Dies kann aber zu Fehlern bei der Bilddarstellung fhren.
SetDisplayMode() Setzt einen gltigen Displaymode einer Grafikkarte. Der gewhlte Mode muss von der Grafikkarte untersttzt werden. DirectDraw7.RestoreDisplayMode, DirectDraw7.GetDisplayModesEnum, DirectDraw7.SetCooperativeLevel object.SetDisplayMode( w As Long, h As Long, bpp As Long, _ ref As Long, _ mode As CONST_DDSDMFLAGS) object w und h bpp ref mode ein gltiges DirectDraw7-Objekt Weite und Hhe des neuen Modes Auflsung in Bits per Pixel Wiederholfrequenz. Dieser Wert kann auf 0 gesetzt werden, dann wird die voreingestellte Wiederholfrequenz der Garfikkarte verwendet. Eine Konstante aus der CONST_DDSDMFLAGS-Liste. Zur Zeit ist der einzig gltige Eintrag DDSDM_STANDARDVGAMODE.

GetAttachedSurface() Liest die Surface-Eigenschaften aus. object.GetAttachedSurface( caps As DDSCAPS2) As DirectDrawSurface7

66

Fullscreen

GetAttachedSurface() object caps ein gltiges DirectDrawSurface7-Objekt Eine Variable vom Typ DDSCAPS2, welche als Empfnger der SurfaceEigenschaften dient.

GetSurfaceDesc() Liest die Surface-Beschreibungen aus. object.GetSurfaceDesc(surface As DDSURFACEDESC2) object Surface ein gltiges DirectDrawSurface7-Objekt Eine Variable vom Typ DDSURFACEDESC2, welche als Empfnger der Surface-Beschreibungen dient.

Flip() Wechselt von Backbuffer-Speicher zum Frontbuffer-Speicher object.Flip( ddS As DirectDrawSurface7, flags As CONST_DDFLIPFLAGS) object dds ein gltiges DirectDrawSurface7-Objekt Dieser stellt die Verbindung zu einer beliebigen Surface aus der Flipping-Kette her. Die Defaulteinstellung ist Nothing. In diesem Fall wrde DirectDraw in der Reihenfolge der einzelnen Kettenglieder die Surfaces flippen. Ist dieser Wert nicht Nothing, so flippt DirectDraw zu der angegeben Surface. eine Konstante aus der CONST_DDFLIPFLAGS-Konstantenliste

flags

RestoreDisplyMode() Restauriert den Display Mode der primren Surface auf den Zustand, der vor dem Aufruf der Methode DirectDraw7.SetDisplayMode() herrschte. DirectDraw7.SetDisplayMode, DirectDrawEnumModes, DirectDraw7.SetCooperativeLevel object.RestoreDisplayMode() object DrawText() Zeichnet Text auf eine Surface. object.DrawText(x As Long, y As Long, text As String, b As Boolean) object x und y ein gltiges DirectDrawSurface7-Objekt Horizontale und vertikale Position auf der Surface ein gltiges DirectDraw7-Objekt

Kapitel 1 DirectDraw

67

DrawText() text b der zu zeichnende Text Boolean Wert, welcher definiert, ob der Text an den zugewiesenen xund y-Positionen oder an der aktuellen Cursorposition gezeichnet wird. Ist der Wert FALSE, werden die angegebenen x- und y-Koordinaten genommen.

Mode X DDSDM_STANDARDVGAMODE Mode 13, 320x200x8 DDSDM_DEFAULT Jeder andere Modus

Auch hierbei knnen wir die nderungen in vier Schritte gliedern. Schritt 1: Setzen des Cooperative Level und des Display Mode
Call objDD.SetCooperativeLevel(Me.hWnd, DDSCL_FULLSCREEN _ Or DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE

Beim Cooperative Level fallen drei neue Flags auf. DDSCL_FULLSCREEN, DDSCL_ALLOWMODEX und DDSCL_EXCLUSIVE. Das DDSCL_FULLSCREEN-Flag legt fest, dass die primre Surface alleine auf die Grafikoberflche zugreift. Mit diesem Flag muss auch das DDSCL_EXCLUSIVE-Flag gesetzt werden. Dieses legt das alleinige Zugriffsrecht der primren Surface auf die Grafikoberflche fest. DDSCL_ALLOWMODEX legt fest, dass die Bildschirmauflsung gendert werden darf. Dies entspricht den Richtlinien von Mode X. Nun wird der Display Mode gesetzt.
objDD.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT

Die ersten beiden Parameter definieren die Breite und die Hhe des neuen Modus. Der dritte Parameter gibt die Auflsung in Bits per Pixel an. Der vierte Parameter bestimmt die Refresh Rate der Grafikkarte. Da dieser auf 0 gesetzt ist, wird die Defaulteinstellung aus dem Grafikkartentreiber bernommen. Der letzte Parameter setzt die Mode X-Einstellung. Schritt 2: Erstellen einer komplexen Surface Im vorherigen Kapitel Sprites durch Transparenz wurde der Backbuffer als Offscreen-Surface erstellt. Der Backbuffer wurde genutzt, um die Grafikdaten aus der Hintergrundsurface und der Spritesurface zu kombinieren und anschlieend durch die Blt()-Methode auf die sichtbare primre Surface zu blitten. Auch dies-

68

Fullscreen

mal wird ein Backbuffer bentigt, aber jetzt ist der Backbuffer ein Teil der primren Surface. Somit wird keine eigenstndige Surface bentigt. Die Technik, um die kombinierten Grafikdaten von Hintergrund und Sprite sichtbar zu machen, hat sich gendert. Es wird nicht mehr die Blt()-Methode genutzt, sondern die Flip()Methode der primren Surface. Zur Flip()-Methode kommen wir etwas spter. Fangen wir mit dem Erstellen der primren Surface an. Da die primre Surface und der Backbuffer eine feste Einheit bilden, spricht man von einer komplexen Surface. Um eine komplexe Surface zu erstellen, werden eigentlich nur ein paar Flags gesetzt.
ddsdScreen.lFlags = DDSD_CAPS Or DDSD_BACKBUFFERCOUNT

Hier wird der Zugriff auf die ddsCaps-Struktur sowie den Backbuffer-Zhler freigegeben.
ddsdScreen.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or _ DDSCAPS_FLIP Or DDSCAPS_COMPLEX

In der ddsCaps-Struktur legen wir fest: Die Surface soll die primre Surface sein, die Surface soll die Flip-Eigenschaft besitzen und die Surface ist eine komplexe Surface.
ddsdScreen.lBackbufferCount = 1

Wir wollen in der komplexen Surface einen Backbuffer einrichten.


Set objDDScreenSurf = objDD.CreateSurface(ddsdScreen)

Die Surface wird erstellt. Da der Backbuffer keine eigenstndige Surface ist, mssen wir die SurfaceBeschreibungen von der primren Surface zurcklesen. Dazu ist es notwendig eine Hilfsstruktur zu definieren.
Dim caps As DDSCAPS2 caps.lCaps = DDSCAPS_BACKBUFFER

Der Variablentyp DDSCAPS2 nimmt die Definitionen aller Eigenschaften einer Surface auf. Diese Struktur wird als Backbuffer definiert. Jetzt knnen wir mit GetAttachedSurface() die genauen Strukturen des Backbuffers unserer komplexen Surface auslesen.
Set ddsdBackbuffer =objDDScreen.GetAttachedSurface(caps)

Somit sind alle Eigenschaften und Beschreibungen des Backbuffers ordnungsgem bergeben worden.

Kapitel 1 DirectDraw

69

Schritt 3: Surfaces einrichten Das Einrichten der Offscreensurfaces fr die Hintergrundsurface sowie der Sprite-Surface ist im Wesentlichem gleich der Technik, wie Sie im Kapitel Sprites durch Transparenz beschrieben wurde. Der einzige Unterschied liegt darin, das die Hintergrundsurface mit den Beschreibungen der Backbuffersurface erstellt wird.
Backbuffer.GetSurfaceDesc ddsdBackbuffer

Wir nutzen die GetSurfaceDesc()-Methode, um der Variablen ddsdBackbuffer alle Eigenschaften der Backbuffersurface zu bergeben. Die Variable ddsdBackbuffer ist vom Typ DDSURFACEDESC2. Anschlieend werden die Strukturen der Hintergrundsurface festgelegt.
ddsdHintergrund.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or _ DDSD_WIDTH ddsdHintergrund.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN ddsdHintergrund.lWidth = ddsdBackbuffer.lWidth ddsdHintergrund.lHeight = ddsdBackbuffer.lHeight Set objDDHintergrundSurf = objDD.CreateSurfaceFromFile _ ("Hintergrund.bmp",ddsdHintergrund)

Hier gibt es eigentlich nichts Neues zu berichten. Schritt 4: Flipping statt Blitting
objDDScreenSruf.Flip Nothing, DDFLIP_WAIT

Die Flip()-Methode enthlt zwei Parameter. Der erste Parameter ist dds. Dieser stellt die Verbindung zu einer beliebigen Suface aus der Flipping-Kette her. Die Defaulteinstellung ist Nothing. In diesem Fall wrde DirectDraw in der Reihenfolge der einzelnen Kettenglieder die Surfaces flippen. Ist dieser Wert nicht Nothing, so flippt DirectDraw zu der angegeben Surface. Der zweite Parameter ist der obligatorische Flag-Parameter. Hier wird eine Konstante aus der CONST_ DDFLIPFLAGS-Liste angegeben. In unserm Beispiel wird das Flag DDFLIP_ WAIT gesetzt. Hierdurch wird DirectDraw aufgefordert, den aktuellen Flipp-Vorgang abzuwarten, bevor mit einem neuen begonnen wird. Achten Sie darauf, dass nach Beendigung der Anwendung der Display Mode wieder zurckgestellt wird. Dies erreichen Sie mit der RestoreDisplayMode()Methode. Anschlieend noch den CooperativeLevel auf Normalzustand setzen, und alles ist beim Alten.
Call objDD.RestoreDisplayModeCall objDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)

70

Fullscreen

Beispiel (Fullscreen) In diesem Beispiel werden ein paar nderungen deutlich. Diese nderungen beziehen sich hauptschlich auf die Darstellungsart der primren Surface. In dem Kapitel Sprites durch Transparenz haben wir die Hintergrundgrafik einmal in den Backbuffer kopiert. Dies haben wir direkt in der Subroutine Init() getan. In der Subroutine Blt() wurde das Sprite bewegt. Um eine saubere Darstellung zu erreichen, haben wir folgendes Prinzip angewendet: Hintergrund restaurieren Es wurde nur der Teil des Hintergrunds restauriert, welcher von dem Sprite verdeckt war. Dadurch brauchten wir nur einen kleinen Teil des Hintergrunds in den Backbuffer blitten und erreichen somit einen Performancegewinn. Sprite an die neuen Koordinaten zeichnen Den neu erstellten Backbuffer auf die primre Surface blitten

Von diesem Prinzip weichen wir diesmal ab. Der Teil, in dem der Hintergrund restauriert wird, verwendet diesmal nicht einen kleinen Ausschnitt, sondern bezieht sich auf den gesamten Backbuffer. Es scheint unlogisch den gesamten Backbuffer zu restaurieren, wenn doch nur ein kleiner Teil verndert werden muss. Fhrt dies nicht zu Performanceverlust? Diese Frage ist mit Ja und Nein zu beantworten. In unserem Beispiel macht sich das Restaurieren des gesamten Backbuffers negativ bemerkbar. Dennoch haben wir diese Technik bewusst ausgewhlt. Nehmen wir einmal an, Sie wollen nicht nur ein Sprite bewegen, sondern 30, 50 oder mehr. Um den Hintergrund zu restaurieren, wrde es nach alter Technik bedeuten, dass sie fr jedes Sprite die Blt()- bzw. BltFast()-Methode aufrufen mssten. Anschlieend wrden Sie genauso oft diese Methode aufrufen, um das Sprite an die neuen Koordinaten zu blitten. Ich denke, dass Sie das Problem erkannt haben. Viele kleine Blitteraktionen sind eben nicht schneller, als eine etwas komplexere. An dem Bildschirmfoto knnen Sie erkennen, das wir die normalen Fensterelemente nicht mehr finden. In der Fullscreenanwendung wird eben die ganze Bildschirmgre genutzt. So sieht die neue Blt()-Sub aus:
Private Sub Blt(ByVal X As Single, ByVal Y As Single)

Hier wird der Hintergrund restauriert. Der gesamte Backbuffer wird mit einem Befehlsaufruf wieder hergestellt.
Call objDDBackbufferSurf.BltFast(0, 0, objDDBackgroundSurf, _ rBackground, DDBLTFAST_WAIT)

Dieser Abschnitt zeigt Ihnen eine Technik, um die Frames per Second zu zhlen. Ebenso sehen Sie die DrawText()-Methode. Diese muss nicht genauer erklrt werden. Dieser Abschnitt gehrt nicht zur eigentlichen Technik, ist aber recht hilfreich.

Kapitel 1 DirectDraw

71

Bild 1.17: Fullscreen-Bildschirmfoto If Zeit = 30 Then If tLast <> 0 Then fps = 30 / (Timer tLast) tLast = Timer Zeit = 0 End If Zeit = Zeit + 1 Call objDDBackbufferSurf.DrawText _ (10, 10, "640x480x16 Frames per Second " + Format$(fps, _ "#.0"), False) Call objDDBackbufferSurf.DrawText _ (500, 10, "Maus Klick fr Ende", False) Call objDDBackbufferSurf.DrawText _ (550, 440, "Full Screen", False)

Nachdem wir den Informationstext auf den Backbuffer gezeichnet haben, knnen wir nun das Sprite an die neuen Koordinaten blitten.
objDDBackbufferSurf.BltFast X, 200, objDDSpriteSurf, rSprite, _ DDBLTFAST_SRCCOLORKEY Or DDBLTFAST_WAIT

Flipping statt Blitting. Wie bereits erklrt, wird die komplexe Surface einfach einmal gedreht. Wirklich einfach, oder?
objDDScreenSurf.Flip Nothing, DDFLIP_WAIT End Sub

72

Fullscreen und Spriteanimation

1.5

Fullscreen und Spriteanimation


In der Theorie ist die Spriteanimation wirklich simpel. In der Praxis bedarf es bei sehr komplexen Anwendungen etwas Organisationstalent. Bleiben wir bei der Theorie. Schauen wir uns einmal an, wie die Spritegrafiken bisher ausgesehen haben.

Bild 1.18: Nicht animiertes Sprite

Bisher hatten wir eine Bitmap, auf der ein einzelnes Sprite dargestellt wurde. Somit konnten wir die Sprite-RECT-Struktur immer in der gesamten Gre der Spritebitmap erstellen. Die Darstellung solch einen Sprites ist natrlich nicht animiert. Schauen wir uns an, was wir fr ein animiertes Sprite bentigen. In Bild 1.19 haben wir eine Bitmap, auf der viele Sprites dargestellt werden. Sinnvollerweise bilden die Einzelbilder eine Animation (vergleichen Sie das mit einem Daumenkino). In dem Beispiel knnte man sagen, dass das Mnnchen mit dem rechten Arm winkt. Legen Sie ber die gesamte Grafik ein Raster von 3 x 2 Feldern. Diese Felder sind nichts anderes als die RECT-Strukturen, welche Sie zum blitten verwenden mssen. Sie nehmen also immer den richtigen Ausschnitt der Gesamtgrafik und blitten diesen an die richtige Stelle der Backbuffersurface. Das ist das ganze Geheimnis der Spriteanimation. Fr die programmtechnische Umsetzung betrachten wir zuerst, wie die richtigen RECT-Strukturen ermittelt werden. Bekannt ist die Anzahl der Rows sowie die Anzahl der Cols. Damit ist die Spritebreite und Spritehhe gleich:
SpriteBreite = ddsdSprite.lWidth / Anzahl Col SpriteHhe = ddsdSprite.lHeight / Anzahl Row

Jetzt ist die richtige Navigation in der groen Sprite Surface gefragt.

Kapitel 1 DirectDraw

73

Col 0

Col 1

Col 2

Row 0

Row 1

Bild 1.19: Animiertes Sprite

Als Beispiel nehmen wir das winkende Mnnlein mit einem Raster von 3 x 2 Feldern. Ein Algorithmus, um alle Sprites der Reihe nach darzustellen, knnte so aussehen.
Dim SpriteRect as RECT For Row = 0 to 1 For Col = 0 to 2 SpriteRect.Left = Col * SpriteBreite SpriteRect.Top = Row * SpriteHhe SpriteRect.Right = Col * SpriteBreite + SpriteBreite SpriteRect.Bottom = Row * SpriteHhe + SpriteHhe Next Col Next Row

Mit dieser kleinen Routine wird das Sprite in einer flssigen Bewegung einmal durchlaufen. Schauen Sie sich das Beispiel zur Spriteanimation an. Beispiel (Spriteanimation) Diese Beispiel baut auf dem Beispiel Full Screen auf. Im Grunde sind diese beiden Demos identisch. Der einzige Unterschied liegt in der Spritedarstellung. Diesmal ist das Sprite animiert und sieht so aus:

74

Fullscreen und Spriteanimation

Bild 1.20: Animierte Biene zur Darstellung eines animierten Sprites

Um die animierte Biene darzustellen, wurden folgende nderungen und Ergnzungen gemacht. Die Definition der Sprite-RECT-Struktur wurde aus der Init()Sub herausgenommen und in die Blt()-Sub verlegt. Diese sieht jetzt so aus:
Private Sub Blt(ByVal X As Single, ByVal Y As Single) Call objDDBackbufferSurf.BltFast(0, 0, objDDBackgroundSurf, _ rBackground, DDBLTFAST_WAIT) If Zeit = 30 Then If tLast <> 0 Then fps = 30 / (Timer tLast) tLast = Timer Zeit = 0 End If Zeit = Zeit + 1 Call objDDBackbufferSurf.DrawText _ (10, 10, "640x480x16 Frames per Second " + Format$(fps, #.0"),_ False) Call objDDBackbufferSurf.DrawText _ (500, 10, "Maus Klick fr Ende", False) Call objDDBackbufferSurf.DrawText _ (520, 440, "Sprite Animation", False)

Erst hier finden die nderungen statt. Da das Sprite der Reihe nach animiert werden soll, muss die richtige RECT-Struktur definiert werden. Diese ist abhngig von den aktuellen Col- und Row-Werten. Die Col- und Row-Werte werden in der game()-Sub festgelegt.
'Den richtigen Spriteausschnitt whlen rSprite.Left = Col * SpriteBreite rSprite.Top = Row * SpriteHhe rSprite.Right = Col * SpriteBreite + SpriteBreite rSprite.Bottom = Row * SpriteHhe + SpriteHhe objDDBackbufferSurf.BltFast X, 200, objDDSpriteSurf, _ rSprite, DDBLTFAST_SRCCOLORKEY Or DDBLTFAST_WAIT objDDScreenSurf.Flip Nothing, DDFLIP_WAIT End Sub

In der game()-Sub werden die Col- und Row-Werte festgelegt. Dies sieht so aus:
Private Sub game() Do While GameLoop = True If Richtung = True Then MoveX = MoveX + 2

Kapitel 1 DirectDraw

75

Befindet sich das Sprite in der Bewegung von links nach rechts, so soll die obere Spritereihe der Spritebitmap genommen werden. Dazu wird der Row-Wert auf Null festgelegt.
Row = 0 Else

Die zweite Spritereihe wird genommen, wenn sich das Sprite in der Bewegung von rechts nach links befindet. Einfach den Row-Wert mit 1 definieren.
Row = 1 MoveX = MoveX 2 End If

Hier werden die Sprites immer schn der Reihe nach durchgeschaltet. Ist das letzte Sprite der Reihe erreicht, fngt alles wieder von vorne an. Welches Sprite an der Reihe ist, bestimmt der Col-Wert.
Col = Col + 1 If Col > 3 Then Col = 0 If MoveX > 637 SpriteBreite Then Richtung = False If MoveX < 3 Then Richtung = True Blt MoveX, 200 DoEvents Loop If GameLoop = False Then End End Sub

1.6

Hintergrund-Scrolling
Hintergrund- (Background-) Scrolling bedeutet, dass Sie eine Hintergrundgrafik an dem sichtbaren Bereich der primren Surface vorbeilaufen lassen. Zu diesem Zweck ist die Hintergrundgrafik grer als die primre Surface. Betrachten wir uns dieses mit einem Beispiel. Unsere Hintergrundgrafik ist ebenso hoch wie die primre Surface. Sie ist aber doppelt so breit. Unser Ziel ist es, die Hintergrundgrafik einmal von links nach rechts darzustellen. Somit schneiden wir aus der Hintergrundgrafik immer den Teil aus, welchen wir gerade betrachten wollen (s. Bild 1.21). Den richtigen Teil der Hintergrundsurface definieren wir mit der HintergrundRECT-Struktur. Nachdem die RECT-Struktur festgelegt wurde, blitten wir diesen Bereich in den Backbuffer. Anschlieend wrden die Sprites geblittet. Wenn alles fertig ist wird das ganze per Blt()-Methode oder Flip()-Methode sichtbar gemacht. Hier ein kleiner Algorythmus zur Auswahl des richtigen RECT-Bereiches.

76

Hintergrund-Scrolling

sichtbarer Bereich der primren Surface Hintergrundgrafik

Bild 1.21: Hintergrund-Scrolling For i = 0 to Hintergrundbreite HintergrundRECT.Left = i HintergrundRECT.Top = 0 HintergrundRECT.Right = i + PrimreSurface.Width HintergrundRECT.Bottom = PrimreSurface.Height Next i

Die Hintergrund-RECT-Struktur wird nun in die Blt()-Methode eingesetzt. Unser Beispiel Background Scrolling zeigt das noch etwas genauer. Beispiel (Hintergrund-Scrolling) Dieses Beispiel baut auf dem Beispiel Fullscreen und Spriteanimation auf. In der Init()-Sub haben wir die Background Surface in der Breite verdoppelt. Dies ist kein Problem, da DirectDraw die Grafikdaten automatisch auf die passende Gre dehnt.
Private Sub Init() . . . ddsdBackground.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsdBackground.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or _ DDSCAPS_SYSTEMMEMORY

Bisher waren die Backbuffersurface und die Hintergrundsurface immer gleich gro. Etwas anderes wre auch nicht sinnvoll gewesen, da wir immer den gesamten Hintergrund darstellen wollten. Jetzt zeigen wir das Prinzip des Background

Kapitel 1 DirectDraw

77

Scrollings. Hierzu bentigen wir eine grere Hintergrundsurface. In unserem Beispiel erzeugen wir eine bergroe Hintergrundsurface. Dazu multiplizieren wir den Parameter lWidth mit dem Faktor 2. Somit haben wir einen Hintergrund erzeugt, welcher doppelt so breit ist wie die Backbuffersurface. Die Grafikdaten (fr die Hintergrundsurface) werden von DirectDraw automatisch angepasst. Da die Hintergrundsurface eine statische Surface ist, werden wir nicht einmal Performanceverluste hinnehmen mssen. Die Hintergrundsurface bezeichnen wir als statische Surface, da sie nicht unmittelbar fr den Bildschirmaufbau verwendet wird. Aus ihr werden lediglich Bildbereiche ausgeschnitten und auf die Backbuffersurface kopiert. So muss DirectDraw den Grafikinhalt der Hintergrundsurface nicht immer neu erstellen und es entfllt das Performance verschlingende Dehnen der Grafikdaten.
ddsdBackground.lWidth = ddsdBackbuffer.lWidth * 2 ddsdBackground.lHeight = ddsdBackbuffer.lHeight Set objDDBackgroundSurf = objDD.CreateSurfaceFromFile _ (App.Path & "\Backgroundscrolling.bmp ", ddsdBackground) . . . ' RectStrukturen rBackground.Bottom = ddsdBackground.lHeight

Da wir vorher die Breite des Backgrounds verdoppelt haben, legen wir jetzt die neue Breite des sichtbaren Backgrounds fest. Sichtbar natrlich nur, nachdem wir den Background in den Backbuffer geblittet und diesen wiederum in die primre Surface geflippt haben.
rBackground.Right = ddsdBackground.lWidth / 2 . . . End Sub

Die nchsten nderungen finden wir in der game()-Sub. Dort legen wir die gltige RECT-Struktur fr den Hintergrund fest. Das sieht so aus:
Private Sub game() Do While GameLoop = True If Richtung = True Then MoveX = MoveX + 2 Row = 0

Befinden wir uns in der Bewegung von links nach rechts, so addieren wir auf die Rnder der RECT-Struktur jeweils zwei Pixel auf. Somit verschiebt sich das Rechteck permanent. Obwohl wir uns in der Bewegung von links nach rechts befinden, wird der Hintergrund von rechts nach links scrollen.

78

Spritekollision

rBackground.Left = rBackground.Left + 2 rBackground.Right = rBackground.Right + 2 Else Row = 1 MoveX = MoveX 2

Jetzt befinden wir uns in der Bewegung von rechts nach links. Der Hintergrund soll wiederum entgegengesetzt scrollen. Somit ziehen wir bei jedem Durchlauf zwei Pixel ab. Die RECT-Struktur ist wieder neu definiert und steht fr die nchste Blitteraktion bereit.
rBackground.Left = rBackground.Left 2 rBackground.Right = rBackground.Right 2 End If Col = Col + 1 If Col > 3 Then Col = 0 If MoveX > 637 SpriteBreite Then Richtung = False If MoveX < 3 Then Richtung = True Blt MoveX, 200 DoEvents Loop If GameLoop = False Then End End Sub

1.7

Spritekollision
Das Erkennen einer Kollision zwischen zwei Sprites ist ein komplexes Thema. Es gibt viele unterschiedliche Arten um eine Kollision zu registrieren. Welche Technik zum Einsatz kommt, hngt im Wesentlichen von der Art der Applikation ab. Die verschiedenen Mglichkeiten, eine Kollision zu erkennen, kann man in zwei Kategorien einteilen. Diese Einteilung ist zum einen die grobe Kollisionskontrolle und zum anderen die feine Kollisionskontrolle. Die feine Kollisionskontrolle berprft die einzelnen Pixel der Sprites. Hierfr mssen wir direkt auf den Speicher der Surfaces zugreifen. Die folgenden Methoden werden fr den direkten Zugriff auf den Surfacespeicher bentigt. Diese Speichermanipulationen sind ein heikles Thema, denn Fehler werden erbarmungslos bestraft. Dennoch sollte diese Kapitel Ihnen helfen, den Surfacespeicher sicher in den Griff zu bekommen.
Lock() Erstellt einen Zeiger auf den Surface-Speicher. Gleichzeitig wird der Speicherbereich geschtzt. object.Lock(r As RECT, desc As DDSURFACEDESC2, _ flags As CONST_DDLOCKFLAGS, hnd As Long)

Kapitel 1 DirectDraw

79

Lock() object r desc flags hnd Unlock() Hebt die Lock() Methode wieder auf. Sie signalisiert DirectDraw, das die Surfacemanipulationen abgeschlossen sind. object.Unlock(r As RECT) object r ein gltiges DirectDrawSurface7-Objekt Eine RECT-Struktur, welche den Speicherbereich beschreibt. Dieser Parameter kann nur dann leer (Nothing) sein, wenn zuvor mit der Lock()-Methode die gesamte Surface geschtzt wurde. ein gltiges DirectDrawSurface7-Objekt Eine RECT-Struktur, welche den Speicherbereich beschreibt. Wird eine leere RECT-Struktur bergeben, so wird die gesamte Surface geschtzt. Eine Varibale vom Typ DDSURFACEDESC2, welche mit den relevanten Details der Surface gefllt wird. Eine Konstante aus der CONST_DDLOCKFLAGS-Liste; sie beschreibt, in welcher Art der Speicherbereich gesperrt werden soll. Wird zur Zeit nicht genutzt. Muss auf 0 gesetzt werden.

GetLockedArray() Erstellt einen Zeiger auf ein Array von geschtzten Pixel nach dem Aufruf der Lock() Methode. object.GetLockedArray( array() As Byte) object array() ein gltiges DirectDrawSurface7-Objekt Feld von geschtzten Pixel in Byte

GetDisplayMode() Liest den aktuellen DisplayMode. DirectDraw7.SetDisplayMode, DirectDraw7.RestoreDisplayMode, DirectDraw7.GetDisplayModesEnum object.GetDirect3D() As Direct3D7 object surface ein gltiges DirectDraw7-Objekt Eine Variable vom Type DDSURFACEDESC2, welche die Beschreibungen des aktuellen Display-Modes aufnimmt.

80

Spritekollision

Die grobe Kollisionskontrolle beschrnkt sich darauf, eine berlappung zweier RECT-Strukturen zu erkennen. Diese Art ist mit Sicherheit die schnellste Technik. Sie birgt aber ein gewaltiges Problem. Dazu schauen wir uns folgende Grafik an:

Sprite 1 Sprite 2
Bild 1.22: Spites mit RECT-Struktur

Sprite 1 und Sprite 2 bewegen sich aufeinander zu. Im Laufe der Bewegung werden die beiden RECT-Strukturen aufeinander stoen. Wenn sich die beiden RECT-Strukturen berlappen, hat eine Kollision stattgefunden.

Sprite 1 Sprite 2
Bild 1.23: Keine echte Kollision

Diese Annahme ist nur zum Teil richtig. Schauen Sie sich nochmals die beiden Sprites genau an. Sie werden feststellen, das die RECT-Strukturen wesentlich grer sind als die eigentlichen Sprites. Der gesamte Hintergrund wird bei der Darstellung auf dem Bildschirm fr den Anwender unsichtbar sein. Dies haben wir in Kapitel Sprites durch Transparenz dargestellt. Der Computer wrde eine

Kapitel 1 DirectDraw

81

Kollision erkennen, obwohl der Kreis und das Dreieck noch nicht zusammengestoen sind. Dazu vorherige Grafik. Analysieren wir das Problem. Was uns das Leben im Moment schwer macht ist, dass der Computer nur mit rechteckigen Dimensionen arbeiten kann. Alles was DirectDraw als nicht rechteckige Objekte darstellt, ist in Wirklichkeit eine normale RECT-Struktur. Um nun eine Kollision von Kreis und Dreieck zu registrieren mssen wir eine Mglichkeit finden, das eigentliche Objekt vom Hintergrund zu trennen. Anschlieend knnen wir auf eine berlappung der Objekte prfen. Hier kommt die Maus ... h, die Lsung. Als Grundlage zur Lsung nehmen wir den Colorkey, welcher fr die jeweilige Sprite Surface definiert wurde. Dieser Colorkey trennt den Hintergrund vom eigentlichen Sprite. Jetzt legen wir fest, welches Sprite wir auf eine Kollision prfen mchten. In unserem Fall wird das Sprite 1 sein. Dies ist wichtig, da wir programmtechnisch das zu berprfende Sprite vor allen anderen Sprites in den Backbuffer kopieren mssen. Wir kopieren also Sprite 1 in den Backbuffer. Anschlieend kopieren wir Sprite 2 in den Backbuffer. Sollte der Kreis oder ein Teil des Kreises von dem Dreieck im Backbuffer berlagert sein, knnen wir dieses anhand eines Mustervergleiches mit der Sprite-1-Surface feststellen. Schauen wir uns die berlagerung einmal an.

Sprite 1 Sprite 2
Bild 1.24: Echte Kollision

Wie Sie sehen, wurde Sprite 1 von Sprite 2 berlagert. Wenn wir jetzt einen Mustervergleich der RECT-Struktur von Sprite 1 des Backbuffers mit der RECTStruktur von Sprite 1 der Sprite-1-Surface durchfhren, werden wir feststellen, dass diese Muster nicht bereinstimmen. Siehe Grafik.

82

Spritekollision

RECT -Struktur von Sprite 1 auf der Backbuffer Surface

RECT -Struktur von Sprite 1 auf der Sprite 1 Surface

Bild 1.25: Echte Kollision

Sie knnen deutlich die nderung der RECT-Struktur erkennen. Nun knnen wir einen Mustervergleich vornehmen. Der Mustervergleich: Beim Mustervergleich werden nur die Farbinformationen der Pixel innerhalb der beiden RECT-Strukturen verglichen. Hierbei ist die Farbtiefe der Surfaces zu beachten. Hauptschlich werden drei Farbtiefen verwendet. 8 Bit fr 256 Farben, 16 Bit fr 65536 Farben und 24 Bit fr 16777216 Farben. Die Farbtiefe ist insofern wichtig, da wir die Farbinformationen nur aus dem Speicherbereich lesen knnen. Um die Farbe fr ein Surface-Pixel im 24 Bit Mode zu erhalten, mssen wir drei aufeinander folgende Bytes des Speicherbereiches lesen. Diese Bytes haben Werte im Bereich von 0 bis 255. Sie reprsentieren der Reihe nach den Blau-, Grn- und Rotanteil der Farbe. Hierbei spricht man auch von der RGBFarbe. Bei der RGB-Farbe werden die Farbanteile Rot, Grn und Blau angegeben. Im Speicher liegen diese Informationen jedoch gespiegelt vor. Als Blau-, Grnund Rot-Werte. Mit der folgenden Funktion sind Sie in der Lage, die Farbinformationen der drei unterschiedlichen Farbtiefen herauszulesen. Als Voraussetzungen wird angenommen, das wir eine Fullscreen-Anwendung (komplexe Surface) erstellt haben. Die notwendige DDSURFACEDESC2-Variable ist mit ddsdScreen bezeichnet. Die Farbe soll aus dem Backbuffer gelesen werden.
Function GetColor( x, y) On Error GoTo fehler

Die GetDisplayMode()-Methode bertrgt die notwendigen Daten in die Variable ddsdScreen. Anschlieend knnen wir ber ddpfPixelFormat.lGGBBitCount() die Farbtiefe entnehmen.

Kapitel 1 DirectDraw

83

objDD.GetDisplayMode ddsdScreen Cobit = ddsdScreen.ddpfPixelFormat.lRGBBitCount If Cobit = 8 Then mp = 1 If Cobit = 16 Then mp = 2 If Cobit = 24 Then mp = 3 Dim pict1() As Byte

Die Lock()-Methode liefert uns den Zeiger auf den Speicherbereich der Surface. Hierbei verwenden wir eine RECT-Struktur, welche die gesamte Surface abdeckt. Diese RECT-Struktur ist mit rSurface bezeichnet. ddsdBackbuffer erstellt den Verweis auf den Backbuffer der komplexen Surface.
Backbuffer.Lock rSurface, ddsdBackbuffer, DDLOCK_WAIT, 0

Mit der GetLockedArray()-Methode fllen wir das Array pict1() mit den Farbwerten als Byte.
Surface.GetLockedArray pict1()

Der folgende Abschnitt liest die einzelnen Farbanteile aus dem Speicher und setzt Sie anschlieend zu dem gewnschten Farbwert vom Typ Long zusammen. Je nach Farbtiefe mssen wir die Farbanteile selektiert auslesen.
sx = x * mp sy = y If mp = 3 Then byte1 = pict1(sx, sy) byte2 = pict1(sx + 1, sy) byte3 = pict1(sx + 2, sy) ccolor = (byte3 * 65536) + (byte2 * 256) + (byte1 * 1) End If If mp = 2 Then byte1 = pict1(sx, sy) byte2 = pict1(sx + 1, sy) ccolor = (byte2 * 256) + (byte1 * 1) End If If mp = 1 Then byte1 = pict1(sx, sy) ccolor = (byte1 * 1) End If

Der Funktion wird der Rckgabewert zugewiesen.


GetColor = ccolor

Sollte ein Fehler auftreten, mssen wir den geschtzten Bereich wieder freigeben. Dieses geschieht mit der Unlock()-Methode.

84

Spritekollision

fehler: Backbuffer.Unlock rSurface End Function

Kehren wir zum Mustervergleich zurck. Wir wollen ber den Mustervergleich eine mgliche Kollision feststellen. Um eine Kollision festzustellen, vergleichen wir die Farben. Jetzt ist es wichtig, das wir nur die Farbbereiche berprfen, welche nicht zum Hintergrund der RECT-Struktur auf der Sprite-1-Surface gehren. Wrden wir den Hintergrundbereich in den Mustervergleich einbeziehen, wrden eine Kollision festgestellt, sobald das Dreieck von Sprite 2 die RECT-Struktur von Sprite 1 berlappt. Dies ist nicht gewollt. Wir wollen nur die berlagerung von Kreis und Dreieck registrieren. Beispiel (Spritekollision) In unserm Kollisionsbeispiel bewegt sich das Dreieck auf den Kreis zu. Wenn das Dreieck den Kreis berhrt, wird das Programm beendet. Um die Kollision zu erkennen, verwenden wir zwei Techniken. Die erste Technik ist die grobe Kollisionserkennung durch die RECT-Strukturen der beiden Objekte. Da uns die RECTStrukturen keine echte Kollision anzeigen, verwenden wir noch eine feine Kollisionserkennung, sobald sich die RECT-Strukturen berlappen.

Bild 1.26: Bildschirmfoto Spritekollision

Kapitel 1 DirectDraw

85

Zum einfacheren Verstndnis ist der VB-Code nun in Module unterteilt. Aufrufen der Module zum Initialisieren von DirectX und Einrichten der Backgrounds, Sprite1 und Sprite 2 sowie des Backbuffers und Screensurface. Zu Beginn erstellen Sie ein Standard-Exe-Projekt und fllen die Form_Load()Routine mit folgenden Anweisungen:
Private Sub Form_Load() Init Form1 InitScreen InitSurface 1, App.Path & "\Back.bmp" InitSurface 2, App.Path & "\Sprite1.bmp" InitSurface 3, App.Path & "\Sprite2.bmp" CreateSpriteBuffer 4

Zuweisen der RECT-Strukturen durch Auslesen der ddsdSurface.Caps


For i = 1 To 4 rSurface(i).Right = ddsdSurface(i).lWidth rSurface(i).Bottom = ddsdSurface(i).lHeight Next End Sub

In der Form_Paint()-Sub steht die eigentliche Routine zum Bewegen der SpriteObjekte und dem Aufruf der Kollisionsabfrage.
Private Sub Form_Paint()

Wir bentigen als Erstes eine Schleife, in der wir die X-Position des zweiten Sprite-Objekts von 500 auf 50 herunterzhlen.
For xx = 500 To 50 Step -1

Da wir in diesem Projekt die Flip()-Methode einsetzen, mssen wir bei jedem Bildschirmaufbau auch den Hintergrund wieder neu zeichnen. Dazu kopieren wir das Hintergrundbild (Surface Index 1) in den Backbuffer.
BlitSurfaceInBuffer 1, 0, 0, 640, 480, 0, 0, 640, 480, False

Als Nchstes legen wir den Colorkey fr die transparente Darstellung des rechteckigen Bereichs der beiden Sprite-Objekte fest und kopieren beide Sprites (Surface Index 2 und 3) ebenfalls in den Backbuffer.
SetColorkey 2, RGB(255, 0, 255) BlitSurfaceInBuffer 2, 0, 0, 60, 60, 100, 100, 160, 160, True SetColorkey 3, RGB(255, 0, 255) BlitSurfaceInBuffer 3, 0, 0, 60, 60, xx, 120, xx + 60, 180, _ True

86

Spritekollision

Um nun zu berprfen, ob es eine berlappung der beiden Sprite-RECT-Strukturen gibt, rufen wir die Funktion GetOverlapRect() auf. Als Rckgabewert erhalten wir eine 1 wenn eine berlappung vorhanden ist und eine 0 wenn keine berlappung stattfindet. Erst wenn eine berlappung der beiden Sprite-Objekte stattfindet, verzweigen wir in die Subroutine DetectCollision(), die dann pixelweise nach einer Kollision berprft. In der Variable coli bekommen wir nun eine 1 nach einer Kollision auf Pixelebene zurck und beenden damit das Programm.
msg = GetOverlapRect(100, 100, xx, 120, 2, 3) If msg = 1 Then coli = DetectCollision(2, 100, 100, RGB(255, 0, 255)) If coli = 1 Then End End If

Nach der Kollisionsberprfung wird der Backbuffer auf den sichtbaren Bildschirm geflippt.
Flip DoEvents Next End Sub

Beschreibung der Module: Als Erstes die Funktion zur berprfung, ob die beiden Sprite-RECT-Strukturen berlappen. Hierzu bentigt die Routine die Koordinaten beider Sprites. Diese bergeben wir an die Funktion mit Sprite1_X,Sprite1_Y . Die Gre der Sprites bekommen wir aus der Surface-Beschreibung. Weiterhin sind noch die Indexnummern mit denen wir die Sprites erzeugt haben von Nutzen, um auf die richtigen Surface-Beschreibungen zugreifen zu knnen.
Function GetOverlapRect(Sprite1_X, Sprite1_Y, Sprite2_X, _ Sprite2_Y, Sprite1_Index, Sprite2_Index) X1 = Sprite1_X X2 = X1 + ddsdSurface(Sprite1_Index).lWidth Y1 = Sprite1_Y Y2 = Y1 + ddsdSurface(Sprite1_Index).lHeight q1 = Sprite2_X q2 = q1 + ddsdSurface(Sprite2_Index).lWidth w1 = Sprite2_Y w2 = w1 + ddsdSurface(Sprite2_Index).lHeight GetOverlapRect = 0: pp = 0

Kapitel 1 DirectDraw

87

Um eine berlappung feststellen zu knnen, berprfen wir, ob die linke obere Ecke von Sprite 1 (X1,Y1) grer als die rechte obere Ecke (q1,w1) von Sprite 2 und gleichzeitig X1,Y1 kleiner als die rechte untere Ecke von Sprite 2 ist. Wenn ja, liegt eine berschneidung vor. Dieses Spiel treiben wir noch in umgekehrter Reihenfolge mit Sprite 2. Je nach Resultat der berprfung geben wir als Rckgabewert an die Funktion GetOverlapRect() eine 0 oder 1 zurck.
If X1 >= q1 And X1 <= q2 Then pp If q1 >= X1 And q1 <= X2 Then pp If pp = 0 Then Exit Function If Y1 > q1 And Y1 < q2 Then pp = If q1 > Y1 And q1 < Y2 Then pp = If pp = 1 Then Exit Function GetOverlapRect = 1 End Function = 1 = 1 2 2

Sollte eine berlappung der RECT-Strukturen stattgefunden haben, verzweigt die Hauptroutine in folgendes Modul zur berprfung einer Kollision auf Bitebene. Hierzu bentigen wir den Surface Index des zu prfenden Sprites, die X- und YPosition sowie die transparente Farbe der Surface.
Function DetectCollision(SpriteIndex As Integer, Sprite_X, _ Sprite_Y, TransColor As Long) On Error GoTo fehler

Die Surfacegre bekommen wir wieder von den Caps-Eigenschaften der Surface-Beschreibung geliefert.
d_Width = rSurface(SpriteIndex).Right _ rSurface(SpriteIndex).Left d_Height = rSurface(SpriteIndex).Bottom _ rSurface(SpriteIndex).Top DetectCollision = 0

Zur eigentlichen bitweisen Abfrage des Spritesurfaces lassen wir zwei verschachtelte Schleifen in X- und Y-Richtung laufen. Um Rechenzeit zu sparen, fragen wir nur jedes 5. Pixel ab, dies reicht fr gewhnlich aus.
For y = 0 To d_Height 1 Step 5 For x = 0 To d_Width 1 Step 5

ber die Subroutine GetColor() ermitteln wir den Farbwert des Pixels (x, y). spcolor beinhaltet den Pixelwert des Sprite-Orginals aus der Spritesurface, bucolor hingegen den Pixelwert der Sprite-Kopie auf dem Backbuffer.

88

Bienenjagd

Beide Werte sollten, bis auf die Ausnahme des transparenten Hintergrundes der Spritekopie oder einer vorhandenen Kollision, gleich sein.
spcolor = GetColor(SpriteIndex, x, y, FROM_SURFACE) bucolor = GetColor(0, Sprite_X + x, Sprite_Y + y, _ FROM_BACKBUFFER)

Um eine Nichtbereinstimmung des transparenten Bereichs der Kopie mit der transparenten Farbe des Originals zu vermeiden, fhren wir einen Vergleich von spcolor mit bucolor nur durch, wenn spcolor nicht der Transparentfarbe entspricht. Sollte nun der RECT-Bereich der Kopie nicht mit der Spritesurface bereinstimmen, setzten wir als Funktion fr den Rckgabewert eine eins.
If spcolor <> TransColor Then If spcolor <> bucolor Then DetectCollision = 1 Exit For End If End If Next Next fehler: End Function

1.8

Bienenjagd
Bienenjagd ist ein kleines Spiel, welches auf Techniken von DirectDraw basiert. Ziel dieser Anwendung ist es, die Handhabung von mehreren Surfaces zu demonstrieren. Auf dem Startbildschirm knnen Sie die Spielzeit und Anzahl der Bienen einstellen. Reizen Sie ruhig einmal die Anzahl der Bienen etwas aus, so knnen Sie (im kleinen Rahmen) die 2D-Leistungsfhigkeit Ihres Systems testen. Wir konnten z.B. bei der Darstellung von 1000 Bienen ber 30 Frames erzielen. Da wir diesmal nicht nur ein Sprite bewegen mchten, haben wir einen eigenen Typ fr Sprite-Arrays definiert.
Type SpriteArray Breite As Single Hhe As Single Col As Integer Row As Integer ACol As Integer ARow As Integer Speed As Long Richtung As String Posx As Long Posy As Long

Kapitel 1 DirectDraw

89

StartZeit As Long Visible As Boolean Bildausschnitt As RECT End Type Public Sprite() As SpriteArray

Bild 1.27: Bildschirmfoto Bienenjagd

Mit Hilfe eines solchen Arrays knnen wir die Bewegungen der Sprites besser organisieren. Durch die Dimensionierung des Arrays knnen wir die Anzahl der Sprites problemlos variieren. Weiterhin werden durch das Array Eigenschaften der Sprites beschrieben. So wird die Flugrichtung oder ob das jeweilige Sprite sichtbar ist in dem Array gespeichert. Indem wir jedem Sprite individuelle Eigenschafen mitgeben, knnen wir die Spites ber eine zentrale Schleife abarbeiten und dennoch reagieren sie individuell. Betrachten wir zunchst die InitDD()-Subroutine. Diese wird Ihnen mitlerweile vertraut vorkommen. Im Grunde wird hier nicht viel anderes getan, als wenn wir ein einzelnes Sprite ber den Bildschirm bewegen.
Public Sub InitDD() ReDim tempRect(MaxSprite) ReDim Sprite(MaxSprite) Set g_DD = g_DX.DirectDrawCreate("") Call g_DD.SetCooperativeLevel(Form1.hWnd, DDSCL_FULLSCREEN Or _

90

Bienenjagd

DDSCL_ALLOWMODEX Or DDSCL_EXCLUSIVE) g_DD.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT ddsdPrimry.lFlags = DDSD_CAPS ddsdPrimry.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Set PrimrySurf = g_DD.CreateSurface(ddsdPrimary) ' Surface erzeugen (HintergrundBild) ddsdOffScreen1.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsdOffScreen1.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Set OffScreen1surf = g_DD.CreateSurfaceFromFile(App.Path & _ "\hintergrund.bmp ", ddsdOffScreen1) rectHintergrund.Bottom = ddsdOffScreen1.lHeight rectHintergrund.Right = ddsdOffScreen1.lWidth ' Surface erzeugen (Zum Mischen) ddsdOffScreen2.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsdOffScreen2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN ddsdOffScreen2.lWidth = ScreenWidth + 200 ddsdOffScreen2.lHeight = ScreenHeight + 200

Da wir uns in einer Fullscreen-Anwendung befinden, knnen wir das ClipperObjekt nicht einsetzen. Dennoch mchten wir, dass die Sprites sanft in den Bildschirm scrollen. Deshalb erzeugen wir eine Offscreensurface, welche grer ist als die primre Surface. Dies ist nicht mit jeder Grafikkarte mglich. Sollten Sie beim Erzeugen dieser Surface Probleme bekommen, knnen Sie die Surface explizit in des Systemspeicher auslagern. Dies schafft in den meisten Fllen Abhilfe.
Set OffScreen2surf = g_DD.CreateSurface(ddsdOffScreen2) OffScreen2surf.SetForeColor RGB(255, 255, 255) rectMischen.Left = 100 rectMischen.Top = 100 rectMischen.Bottom = ScreenHeight + rectMischen.Top rectMischen.Right = ScreenWidth + rectMischen.Left ' Surface erzeugen (Sprite) ddsdSprite1.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsdSprite1.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Set Sprite1Surf = g_DD.CreateSurfaceFromFile(App.Path & _ \biene2.bmp", ddsdSprite1) CK.high = RGB(0, 0, 0) CK.low = RGB(0, 0, 0) Sprite1Surf.SetColorkey DDCKEY_SRCBLT, CK rectSprite1.Right = ddsdSprite1.lWidth rectSprite1.Bottom = ddsdSprite1.lHeight Dim i As Integer For i = 1 To MaxSprite Sprite(i).Posy = Int((460 * Rnd) + 100) Sprite(i).Speed = Int((MaxSpriteSpeed * Rnd) + _ MinSpriteSpeed)

Kapitel 1 DirectDraw

91

If Int((2 * Rnd) + 1) = 1 Then Sprite(i).Richtung = Rechts"_ Else Sprite(i).Richtung = "Links" Sprite(i).Row = 2 Sprite(i).Col = 7 Sprite(i).Breite = rectSprite1.Right / Sprite(1).Col Sprite(i).Hhe = rectSprite1.Bottom / Sprite(1).Row Sprite(i).Visible = True Next I

Die ForNext()-Schleife initialisiert die Sprites fr den ersten Start. Hierbei wird per Zufall die Flugrichtung, Flughhe und Fluggeschwindigkeit zugeordnet.
GameLoop = True End Sub

Die nchste Subroutine welche wir uns anschauen ist DrawSprite(). Sie ist fr die Darstellung der Sprites verantwortlich.
Public Sub DrawSprite() Dim i As Integer For i = 1 To MaxSprite If g_DX.TickCount > Sprite(i).StartZeit + Sprite(i).Speed _ Then Sprite(i).StartZeit = g_DX.TickCount Select Case Sprite(i).Richtung Case "Rechts" Sprite(i).ARow = 0 Sprite(i).ACol = Sprite(i).ACol + 1 If Sprite(i).ACol >= Sprite(i).Col Then _ Sprite(i).ACol = 0 Sprite(i).Posx = Sprite(i).Posx + 2 If Sprite(i).Posx > ddsdOffScreen2.lWidth Then _ Sprite(i).Posx = 1 Case "Links" Sprite(i).ARow = 1 Sprite(i).ACol = Sprite(i).ACol + 1 If Sprite(i).ACol > Sprite(i).Col 1 Then _ Sprite(i).ACol = 0 Sprite(i).Posx = Sprite(i).Posx 2 If Sprite(i).Posx < 1 Then Sprite(i).Posx _ = ddsdOffScreen2.lWidth End Select

Wenn Sie sich die Spritebitmap anschauen, werden Sie feststellen, dass die Bienen in einem 7 X 2 groen Raster abgelegt sind. Die Case...Select-Abfrage ist fr die Navigation auf dieser Bitmap zustndig. Hierbei unterscheiden wir, ob die

92

Bienenjagd

Biene sich von links nach rechts oder von rechts nach links ber den Bildschirm bewegt. Entsprechend der Bewegungsrichtung legen wir die aktuelle Zeile Acol und Spalte Arow fest. Da uns die Breite und die Hhe der Zellen bekannt ist, knnen wir mit diesen beiden Werten die Position und die Gre der aktuellen RECT-Struktur auf der Spritebitmap bestimmen.
Sprite(i).Bildausschnitt.Left = Sprite(i).Breite * _ Sprite(i).Acol Sprite(i).Bildausschnitt.Right = (Sprite(i).Breite * _ Sprite(i).ACol) + Sprite(i).Breite Sprite(i).Bildausschnitt.Top = Sprite(i).Hhe * _ Sprite(i).Arow Sprite(i).Bildausschnitt.Bottom = (Sprite(i).Hhe * _ Sprite(i).ARow) + Sprite(i).Hhe

Dieser kleine Block definiert die passenden RECT-Struktur von der Spritesurface.
tempRect(i).Left = Sprite(i).Posx tempRect(i).Top = Sprite(i).Posy tempRect(i).Right = Sprite(i).Breite + tempRect(i).Left tempRect(i).Bottom = Sprite(i).Hhe + tempRect(i).Top

In der tempRect() RECT-Struktur wird die neue Position des Sprites definiert. Diese ndert sich natrlich permanent.
End If

Wenn ein Sprite im Laufe des Spieles getroffen wurde, wird seine Visible Eigenschaft auf False gesetzt. Dies ist fr uns ein Indikator um die Eigenschaften des Sprites neu zu definieren. Dadurch erscheint das Sprite mit vernderten Flugeigenschaften erneut am Rande des Bildschirms.
If Sprite(i).Visible = True Then OffScreen2surf.BLT tempRect(i), Sprite1Surf, _ Sprite(i).Bildausschnitt, DDBLT_ASYNC Or DDBLT_KEYSRC Else Sprite(i).Posy = Int((460 * Rnd) + 100) Sprite(i).Speed = Int((MaxSpriteSpeed * Rnd) + _ MinSpriteSpeed) If Int((2 * Rnd) + 1) = 1 Then Sprite(i).Richtung = "Rechts" Sprite(i).Posx = 0 Else Sprite(i).Richtung = "Links" Sprite(i).Posx = ddsdOffScreen2.lWidth End If Sprite(i).Visible = True End If Next i End Sub

Kapitel 1 DirectDraw

93

1.9

Methoden zum Zeichnen


Vielleicht ist es Ihnen bereits aufgefallen, eine DirectDraw-Surface beinhaltet eine Reihe von Methoden zum Zeichnen von Linien, Kreisen oder Rechtecken. Diese Fhigkeiten knnen Sie mit den Grafikeigenschaften eines Visual BasicForm-Objekts vergleichen. Sicherlich gehrt die Darstellung von Linien, Kreisen, Rechtecken ... nicht zur Hauptaufgabe von DirectDraw, dennoch stellen diese Methoden eine hilfreiche Ergnzung dar. Diese Methoden knnen auch auf eine primre Surface angewandt werden. Mit den folgenden Methoden knnen Sie einfache Zeichenaktionen ausfhren:
DrawBox() Zeichnet ein Rechteck auf eine Surface. object.DrawBox(x1 As Long, y1 As Long, x2 As Long, y2 As Long) object x1, y1 x2, y2 DrawCircle() Zeichnet einen Kreis auf eine Surface. object.DrawCircle(x1 As Long, y1 As Long, r As Long) object x1, y1 r DrawEllipse() Zeichnet ein Oval auf eine Surface. Die Parameter x1,y1 sowie x2,y2 legen ein Rechteck fest, dieses wird als Oval umgeformt. object.DrawEllipse(x1 As Long, y1 As Long, x2 As Long, y2 As Long) object x1, y1 x2, y2 DrawLine() Zeichnet ein Linie auf eine Surface. object.DrawLine(x1 As Long, y1 As Long, x2 As Long, y2 As Long) object ein gltiges DirectDrawSurface7-Objekt ein gltiges DirectDrawSurface7-Objekt legt die linke obere Ecke fest legt die rechte untere Ecke fest ein gltiges DirectDrawSurface7-Objekt legt den Mittelpunkt des Kreises fest bestimmt den Radius des Kreises in Pixel ein gltiges DirectDrawSurface7-Objekt legt die linke obere Ecke des Rechtecks fest legt die rechte untere Ecke des Rechtecks fest

94

Methoden zum Zeichnen

DrawLine() x1, y1 x2, y2 Legt ein Koordinatenpaar fest, ab wo die Linie gezeichnet werden soll. Legt ein Koordinatenpaar fest, bis wo die Linie gezeichnet werden soll.

DrawRoundedBox() Zeichnet ein Rechteck mit abgerundeten Ecken auf eine Surface. object.DrawLine(x1 As Long, y1 As Long, x2 As Long, y2 As Long, _ rw As Long, rh As Long) object x1, y1 x2, y2 rw rh ein gltiges DirectDrawSurface7-Objekt Legt die linke obere Ecke fest. Legt die rechte untere Ecke fest. Bestimmt die horizontale Gre der Rundung. Bestimmt die vertikale Gre der Rundung.

Um Text auf einer Surface auszugeben, steht folgende Methode zur Verfgung:
DrawText() Zeichnet einen String auf eine Surface object.DrawLine(x As Long, y As Long, text As Long, b As Long,) object x, y text b ein gltiges DirectDrawSurface7-Objekt Bestimmt ein Koordinatenpaar, an dem der Text gezeichnet werden soll. Der Text der gezeichnet werden soll. Sie knnen eine Variable vom Typ Sring bergeben oder direkt einen Text in Hochkommata angeben. True Der Text wird an der aktuellen Cursorposition gezeichnet. Die Parameter x,y werden ignoriert. False Der Text wird an dem Koordinatenpaar gezeichnet, welches durch die Parameter x,y beschrieben wurde.

Neben den eigentlichen Zeichenmethoden bietet DirectDraw eine Reihe von Methoden, mit denen Sie das Erscheinungsbild der Zeichenmethoden beeinflussen knnen. Dies funktioniert genauso wie bei dem Visual Basic-Form-Objekt. Erst legen Sie das Erscheinungsbild fest, dann zeichnen Sie z.B. die Linie.

Kapitel 1 DirectDraw

95

SetDrawStyle() Setzt den Zeichenstil object.SetDrawStyle(drawStyle As Long) object drawStyle ein gltiges DirectDrawSurface7-Objekt 0 voll (Solid), massiv 1 gestrichelt 2 gepunktet 3 Strich und Punkt wechseln sich ab 4 erst ein Strich, dann zwei Punkte 5 durchsichtig 6 gefllt (Bei einem Rechteck wird nicht nur der Rahmen gezeichnet, sondern das Rechteck wird gefllt. Gleiches gilt bei einem Kreis, Oval oder abgerundetem Rechteck.)

SetDrawWidth() Setzt die Strichbreite fr Zeichenmethoden object.SetDrawWidth(drawWidth As Long) object drawWidth ein gltiges DirectDrawSurface7-Objekt Strichbreite in Pixel Der voreingestellte Wert ist 1. Der erlaubte Wertebereich liegt zwischen 1 und 32,767.

SetFillColor() Setzt die Fllfarbe fr Zeichenmethoden. object.SetFillColor(color As Long) object color ein gltiges DirectDrawSurface7-Objekt Farbe Der voreingestellte Wert ist Schwarz (&H00000000).

SetFillStyle() Setzt das Fllmuster fr Zeichenmethoden. object.SetFillStyle(fillStyle As Long) object ein gltiges DirectDrawSurface7-Objekt

96

Methoden zum Zeichnen

SetFillStyle() fillStyle 0 1 2 3 4 5 6 7 voll (solid), massiv durchsichtig horizontale Linien vertikale Linien diagonal aufwrts diagonal abwrts horizontale und vertikale Linien diagonale horizontale und diagonale vertikale Linien

SetFont() Setzt einen neuen Zeichensatz fr die DrawText()-Methode. object.SetFont(font As Ifont) object font ein gltiges DirectDrawSurface7-Objekt Zeichensatz

SetFontBackColor() Setzt eine Hintergrundfarbe fr einen Zeichensatz. object.SetFontBackColor(color As Long) object color ein gltiges DirectDrawSurface7-Objekt Farbe

SetFontTransparency() Legt fest, ob der aktuelle Zeichensatz transparent sein soll. object.SetFontTransparency(b As Boolean) object b ein gltiges DirectDrawSurface7-Objekt True transparent False nicht transparent

SetForeColor() Setzt die Zeichenfarbe, welche von den Zeichenmethoden verwendet wird. object.SetForeColor(color As Long) object color ein gltiges DirectDrawSurface7-Objekt Farbe

Kapitel 1 DirectDraw

97

Beispiel (Zeichnen) Die allgemeinen Zeichenmethoden sind gnzlich unkompliziert einzusetzen. Wir werden eine primre Surface sowie eine Offscreensurface erstellen. Das Blitten wird ber einen Timer gesteuert. Dies ist zwar unblich, aber fr unser Beispiel durchaus ausreichend. An der rechten Seite finden Sie einige Option-Buttons. Mit diesen knnen Sie einige der Zeichen Methoden ausprobieren.

Bild 1.28: Anwendung Zeichnen

Wir beginnen mit den Definitionen der Variablen. Diese sind Ihnen bestens bekannt und werden nicht weiter erklrt. Auch die Init()-Subroutine stellt keine Herausforderung dar. Die eigentlichen Zeichenmethoden werden erst in der Blt()Subroutine eingesetzt.
Dim objDX As New DirectX7 Dim objDD As DirectDraw7 Dim objDDSurf As DirectDrawSurface7 Dim objDDPrimSurf As DirectDrawSurface7 Dim ddsd1 As DDSURFACEDESC2 Dim ddsd2 As DDSURFACEDESC2 Private Sub Form_Load() Init

98

Methoden zum Zeichnen

End Sub Private Sub Init() Set objDD = objDX.DirectDrawCreate("") Call objDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL) 'Surface 1 erzeugen ddsd1.lFlags = DDSD_CAPS ddsd1.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Set objDDPrimSurf = objDD.CreateSurface(ddsd1) ' Surface 2 erzeugen ddsd2.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT ddsd2.lWidth = Picture1.ScaleWidth ddsd2.lHeight = Picture1.ScaleHeight ddsd2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Set objDDSurf = objDD.CreateSurface(ddsd2) End Sub

In der Blt()-Soubroutine werden die Zeichenmethoden ausgefhrt. Diese Routine wird all 100 Millisekunden per Timer aufgerufen.
Private Sub Blt() Dim r1 As RECT Dim r2 As RECT Call objDX.GetWindowRect(Picture1.hWnd, r1) r2.Bottom = ddsd2.lHeight r2.Right = ddsd2.lWidth objDDSurf.BltColorFill r2, &HFFFFFFFF

Da wir immer eine saubere Zeichenflche haben mchten, lschen wir die Offscreensurface mit der DirectDrawSurface7.BltColorFill()-Methode. Lschen ist eigentlich nicht der richtige Ausdruck, wir bermalen mit der Farbe Wei den aktuellen Inhalt der Surface.
If Option1(1).Value = True Then objDDSurf.DrawLine 0, 0, 500, 500

Zeichnen einer Linie.


ElseIf Option1(2).Value = True Then objDDSurf.DrawCircle 250, 250, 200

Zeichnen eines Kreises. Eine Ellipse kann mit dieser Methode nicht dargestellt werden. Dazu verwenden Sie die DirectDrawSurface7.DrawEllipse()-Methode.
ElseIf Option1(3).Value = True Then objDDSurf.DrawBox 100, 100, 300, 300

Kapitel 1 DirectDraw

99

Zeichnen eines Rechtecks. In diesem Beispiel wird ein Quadrat dargestellt. Natrlich muss das Rechteck nicht quadratisch sein.
ElseIf Option1(4).Value = True Then objDDSurf.DrawRoundedBox 100, 100, 300, 300, 40, 40

Die DirectDrawSurface7.DrawRoundedBox()-Methode erstellt ebenfalls ein Rechteck. Diesmal sind die Ecken abgerundet. Die rw- und rh-Parameter bestimmen die Ausdehnung der Rundung. Haben Sie z.B. ein Quadrat mit einer Seitenlnge von 200 Pixel erstellt und anschlieend weisen Sie den Parametern rw und rh den Wert 200 zu, so werden Sie einen Kreis erhalten. Probieren Sie dies an unserem Beispiel aus.
ElseIf Option1(5).Value = True Then objDDSurf.DrawText 100, 100, "This is a Demo!", False

Mit der DirectDrawSurface7.DrawText()-Methode knnen Sie Text auf eine Surface zeichnen. Die Parameter x und y bestimmen die Position, an der ein Text eingeblendet werden soll. Diese Koordinaten werden aber nur dann wirksam, wenn Sie den Parameter b auf False setzten. Ansonsten wird die aktuelle Cursorposition bernommen.
End If ddrval = objDDPrimSurf.Blt(r1, objDDSurf, r2, DDBLT_WAIT)

Nachdem mit einer Zeichen-Methode die Offscreensurface gendert wurde, blitten wir diese auf die primre Surface.
End Sub

Kapitel 2
Direct3D
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 2.12 2.13 3D-Koordinatensystem 3D-Primitives Zeichnen eines Dreiecks Dreieck-Raster-Regeln World-, View- und Projection-Matrix Matrix-Berechnungen Polygone Licht Material Texturen Z-Buffer (Tiefenspeicher) Die SetRenderState()-Methode Effekte 104 105 106 118 120 122 132 137 157 165 212 218 225

102

Direct3D (D3D) ist das Tor von DirectX, welches den Weg zur 3D-Computergrafik ffnet. Es wurde konzipiert, um High-Performance-Grafik umzusetzen. Im Gegensatz zu Techniken wie Glide oder OpenGL arbeitet die D3D-API mit allen modernen Grafikkarten zusammen. Obwohl D3D eine leistungsfhige Softwareemulation beinhaltet, entwickelt es seine volle Leistungsfhigkeit erst bei der direkten Nutzung der Hardware. In der Vergangenheit stellte dies oftmals ein Problem dar. Viele Grafikkarten waren nicht in der Lage, den Leistungsumfang von D3D zu untersttzen. Somit weichen viele Softwareentwickler auf die alternativen Glide bzw. OpenGL aus. Mit den modernen Grafikkarten vollzog sich ein Wandel. Eine starke D3D-Untersttzung gehrt mittlerweile zum Standard. Mit der DirectX Version 7 kommt auch der VB-Programmierer in den Genuss der dritten Dimension. Direct3D stellt zwei verschiedene Modes zur Verfgung. Zum einen ist da der Retained Mode (RM). Der zweite Weg ist der Immediate Mode (IM). Der RM ist ein High Level Interface. Er ist vergleichbar mit einer kleinen 3D-Engine. Hier werden bereits eine Reihe von fortgeschrittenen Techniken bereitgestellt. Mit wenig Quellcode lassen sich anschauliche Ergebnisse erzeugen. Er ist relativ einfach zu erlernen. (Dies muss ein bisschen modifiziert werden. Obwohl der RMMode einfacher als der IM-Mode anzuwenden ist, kommt man auch hierbei nicht ohne entsprechende Hintergrundinformationen aus.) Die beiden Hauptgrnde fr uns, auf den RM zu verzichten, heien Performance und Flexibilitt. Im Vergleich zum IM ist der RM langsamer. Auerdem sind Sie in der Gestaltung Ihres 3DRaums nicht so flexibel. Da Sie sich fr die Programmierung von Grafik entschieden haben, stoen Sie zwangslufig an die Grenzen der Computerperformance. Hierbei sollte man nicht auf Leistung verzichten, nur um eine etwas bequemere Programmiertechnik zu nutzen. Auerdem wrden sich irgendwann die Fhigkeiten von RM ausreizen und Sie zu einer leistungsfhigeren Technik zwingen. Also knnen wir auch sofort mit IM beginnen. Letztendlich sparen wir viel Zeit und erreichen schnelle und beeindruckende Ergebnisse. Sie werden Sich wundern, was Sie mit VB und DirectX im IM erreichen. Stellen wir beide Wege einmal gegenber: Immediate Mode Pro 1. flexibler fr Spezialeffekte 2. schneller Contra 1. schwieriger zu programmieren 2. schwieriger zu verwalten

Kapitel 2 Direct3D

103

Retained Mode Pro 1. einfacher zu programmieren 2. einfacher zu erlernen 3. einfacher zu verwalten Contra 1. langsamer 2. unflexibel Kommen wir zu unserm favorisiertem Weg. Der Immediate Mode ist ein Low Level Interface. Wie es der Name bereitst verrt (immediate = direkt, unverzglich), erhalten Sie den direkten Zugriff auf 3D-Grafik-Pipelines. Sollte eine direkte Verbindung zu verfgbaren Hardware fehlen, so tritt eine robuste Softwareemulation in Aktion. IM stellt einfache und offene Methoden zum Initialisieren und Rendern einer Szene zur Verfgung. Um diesen kraftvollen Mode zu nutzen, mssen Sie aber auch einen Preis bezahlen. Dieser Preis besteht darin, das Sie alle Elemente einer 3D-Szene explizit benennen mssen. Sie bentigen genaue Kenntnisse ber die verfgbare Hardware. Ebenfalls werden Sie Ihre 3DObjekte durch Matrizenmanipulationen berechnen. Hierdurch werden Form, Lage, Perspektive... definiert. Betrachten wir zuerst die Einbindung von D3D im Windows-System.
Win32 Anwendung

GDI

Direct3D

Weitere 3D APIs

Windows DDI

Hardware Abstraction Layer Hardware Emulation Layer

Grafikkarte

Bild 2.1:

Einbindung von Direct3D in die Systemumgebung

104

3D-Koordinatensystem

2.1

3D-Koordinatensystem
Typische 3D-Anwendungen verwenden zwei Arten von Koordinatensystemen. Linkshndig oder rechtshndig. In beiden Systemen liegt die positive X-Achse zur rechten Seite und die positive Y-Achse senkrecht nach oben. Bei dem linkshndigen System liegt die positive Z-Achse zwischen der X- und Y-Achse.
Y Z Y

linkshndig

rechtshndig

Bild 2.2:

Koordinatensystem

Direct3D benutzt das linkshndige Koordinatensystem. Falls Sie eine Anwendung basierend auf dem rechtshndigen Koordinatensystem erstellen mchten, ist es notwendig zwei nderungen an den Daten zur bergabe an Direct3D vorzunehmen. (Diese nderungen sind nur dann notwendig, wenn Sie von dem normalen linkshndigen System abweichen. Fr das normale Koordinatensystem sind diese nderungen absolut berflssig und knnen von Ihnen ignoriert werden.) Drehen Sie die Dreiecks-Scheitelpunkte so, dass sie sich aus der Vorderansicht im Uhrzeigersinn bewegen.
aus V0, V1, V2 wird V0, V2, V1

Tauschen Sie die Vorzeichen der Mitgliedsdaten rc31, rc32, rc32 und rc34 der D3DMATRIX-Struktur.
Type D3DMATRIX rc11 As Single rc12 As Single rc13 As Single

Kapitel 2 Direct3D

105

rc14 rc21 rc22 rc23 rc24 rc31 rc32 rc33 rc34 rc41 rc42 rc43 rc44 End Type

As As As As As As As As As As As As As

Single Single Single Single Single Single Single Single Single Single Single Single Single

Natrlich gibt es noch weitere Koordinatensysteme, aber das linkshndige und das rechtshndige sind die am weitesten verbreiteten Systeme. Das Koordinatensystem bildet die Grundlage fr alle wesentlichen Techniken, welche ein Objekt im 3D-Koordinatensystem bentigen. Techniken wie Translation, Rotation oder Scalling beruhen auf dem Koordinatensystem und werden in einer TransformMatrix miteinander kombiniert.

2.2

3D-Primitives
Eine 3D-Primitive ist eine Sammlung von Scheitelpunkten, die eine einzelne 3DStruktur bilden. Die einfachste Primitive ist eine Sammlung von Punkten im 3DKoordinatensystem. Solch eine Sammlung wird als Pointlist bezeichnet. Wesentlich fter werden Polygone (Vielecke) als Primitive verwendet. Ein Polygon ist eine geschlossene 3D-Figur. Das kleinste Polygon besteht aus drei Scheitelpunkten (Vertex). Solch ein Dreieck wird verwendet, um komplexere 3D-Figuren zu erstellen. Dreiecke sind besonders beliebt, da sie quasi dafr brgen, eine geschlossene Figur zu bilden. Auerdem sind Dreiecke von D3D extrem schnell zu berechnen. Betrachten Sie das Dreieck als primitivstes Polygon. Es stellt die Grundlage fr komplexere 3D-Objekte dar. Aus einer Ansammlung von vielen Dreiecken lassen sich quasi alle 3D-Objekte einer 3D-Welt (eines 3D-Raums) konstruieren. Das folgende Beispiel zeigt einen Wrfel. Jede Seite des Wrfels wurde aus zwei Dreiecken gebildet. Natrlich ist es auch mglich komplexere Figuren zu gestalten. Als Beispiel sei eine Kugel oder ein Zylinder genannt.

106

Zeichnen eines Dreiecks

Bild 2.3:

Wrfel aus Dreiecken erstellt

2.3

Zeichnen eines Dreiecks


Es hrt sich verrckt an, aber zum Konstruieren einer komplexen 3D-Welt bentigen Sie lediglich eine Vielzahl von Dreiecken. Wie bereits erwhnt sind Dreiecke die primitivste Form eines Polygons. Es stellt die ideale Basis zum Gestalten komplexerer 3D-Objekte dar. Die Eckpunkte eines Dreiecks werden durch Vertexe dargestellt. Diese Vertexe flieen anschlieend (unbemerkt vom Programmieren) in die Matrixstrukturen von D3D ein. Natrlich knnen Sie die Matrixstrukturen auch manuell transformieren. Dies werden wir spter genauer erlutern. Es werden eine Reihe von Methoden vorgestellt, die quasi als Basis fr alle Direct3D-Anwendungen betrachtet werden knnen. Zum jetzigen Zeitpunkt wollen wir die Methoden nicht besprechen, sondern Ihnen einen kleinen berblick vermitteln. Sicherlich ist Ihnen bewusst, dass dies nur die Spitze des Eisbergs ist.
CreateDevice() Erzeugt ein Direct3D-Device welches mit den DrawPrimitive-Methoden genutzt wird. object.CreateDevice(guid As String, surf As DirectDrawSurface7)) _ As Direct3Ddevice7 Objekt Guid ein gltiges Direct3D7-Objekt IID_IDirect3DHALDevice Nutzen der Hardwareeigenschaften der Grafikkarte IID_IDirect3DRGBDevice Verwendet den Software-Emulations-Modus IID_IDirect3DrefDevice Erzeugt ein Referenzdevice. Wird zum Testen oder Demonstrationsaufgaben eingesetzt.

Kapitel 2 Direct3D

107

CreateDevice() surf Eine DirectDrawSurface, auf welcher gerendert werden soll. (Zielsurface) Die Surface muss als 3D-Device mit dem Flag DDSCAPS_ 3DDEVICE erstellt worden sein.

SetViewport() Setzt die Viewport-Parameter fr ein Device. object.SetViewport(Viewport As D3Dviewport7) Objekt Viewport ein gltiges Direct3DDevice7-Objekt Eine Variable vom Typ D3DVIEWPORT7, welche die zu setzenden Viewportparameter enthlt.

IdentityMatrix() Erzeugt eine einheitliche Matrix. (Alle Eintrge auf 0 auer die diagonalen Werte von links oben nach rechts unten auf 1) object.IdentityMatrix(Matrix As D3DMATRIX) Objekt mDest ein gltiges DirectX7-Objekt Eine Variable vom Typ D3DMATRIX, welche die einheitliche Matrix aufnimmt.

SetTransform() Weist eine einzelne Transformation einem Device zu. object.SetTransform(transformType As D3DMATRIX, matrix As D3DMATRIX) object transformType matrix ein gltiges Direct3DDevice7-Objekt Eine Variable vom Typ CONST_D3DTRANSFORMSTATETYPE Eine Matrix vom Typ D3DMATRIX, welche die aktuelle Transformation modifiziert.

ViewMatrix() Erzeugt eine Viewmatrix basierend auf den Koordinaten (Betrachterposition) der Kamera. Call object.ViewMatrix(mDest As D3DMATRIX, vFrom As D3DVECTOR, _ vTo As D3DVECTOR, vUp As D3DVECTOR, roll As Single) object mDest ein gltiges DirectX7-Objekt Nimmt die neue transformierte Matrix auf.

108

Zeichnen eines Dreiecks

ViewMatrix() vFrom vTo vUp roll Beschreibt die aktuelle Position der Kamera (des Betrachters). Beschreibt die Koordinaten, wohin die Kamera schauen soll. (Wohin der Betrachter schauen soll) Definiert die Lage der gesamten 3D Welt. Fr gewhnlich wird dieser Vektor mit 0,1,0 festgelegt. Bestimmt den Winkel, mit dem die Kamera (im Uhrzeigersinn) um die Blickrichtung rotiert. Fr gewhnlich 0.

ProjectionMatrix() Diese Methode setzt den Renderbereich (clipping plane). Ebenfalls wird der Blickwinkel des Betrachters festgelegt. object.ViewMatrix(mDest As D3DMATRIX, nearPlane As Single, _ farPlane As Single, fov As Single) object mDest nearPlane farPlane fov ein gltiges DirectX7-Objekt Nimmt die neue transformierte Matrix auf. Bestimmt die Entfernung zum Anfang des Zeichenbereichs (Clipping Plane). Bestimmt die Entfernung zum Ende des Zeichenbereichs (Clipping Plane). Definiert den Radius des Blickwinkels. Das menschliche Auge hat einen Blickwinkel von ungefhr 150 Grad.

CreateD3DVertex() Diese Methode fllt ein D3DVERTEX-Typen-Array. object.ViewMatrix(x As Single, y As Single, z As Single, nx As _ Single, ny As Single, nz As Single, tu As Single, tv As Single, _ v As D3DVERTEX) object x, y und z nx, ny und nz tu und tv v ein gltiges DirectX7 Objekt Beschreiben die Koordinaten im 3D Raum eines Vektors. Beschreiben die Orientierung des normalen Vektors. Enthalten die Texturkoordinaten fr den Vektor. Eine Variable vom Typ D3DVERTEX, welche mit den erzeugten Vertexkomponenten gefllt wird.

Kapitel 2 Direct3D

109

Clear() Diese Methode lscht einen Viewport (oder Teile des Viewport) mit einer bestimmten Farbe. Ebenfalls lscht Sie den Stencil Buffer oder Z Buffer mit einem angegebenen Wert. object.Clear(count As Long, recs() As D3DRECT, flags As CONST_ D3DCLEARFLAGS, color As Long, z As Single, stencil As Long) object count recs() ein gltiges Direct3DDevice7-Objekt Anzahl der Rechtecke im recs() Array. Ein Array von D3DRECT-Typen, welche die Bereiche definieren, die gelscht werden sollen. Wird ein Rechteck auf die Dimensionen des Renderziels gesetzt, so wird das gesamte Ziel gelscht. Diese Flags indizieren, welches Ziel (Surface) gelscht werden soll. Hierbei sind Kombinationen verschiedener Ziele zugelassen. D3DCLEAR_TARGET Lscht das Renderziel (im Regelfall die Backbuffersurface) mit der angegebenen Farbe. D3DCLEAR_STENCIL berschreibt den Stencil Buffer mit dem stencil-Wert. D3DCLEAR_ZBUFFER berschreibt den Z Buffer mit dem z Wert. color Definiert die Farbe zum Lschen einer Surface (oder Teile der Surface). Die Farbe kann mit der DirectX7.CreateColorRGBA()-Methode erzeugt werden. Neuer Wert mit dem der Z Buffer gelscht werden soll. Zugelassen ist ein Wert zwischen 0.0 und 1.0. Neuer Wert mit dem der Stencil-Buffer gelscht werden soll. Zugelassen ist ein Wert zwischen 0 und 2 n -1 inklusive.

flags

z stencil

BeginScene() Mit dieser Methode wird das Rendern einer Szene eingeleitet. Bevor BeginScene() erneut aufgerufen wird, muss die aktuelle Szene mit der Direct3DDevice7.EndScene()Methode abgeschlossen sein. object.BeginScene() object ein gltiges Direct3DDevice7-Objekt

110

Zeichnen eines Dreiecks

EndScene() Mit dieser Methode wird das Ende einer Szene signalisiert. Der Anfang einer Szene wurde mit der Direct3DDevice7.BeginScene Methode eingeleitet. object.EndScene() object ein gltiges Direct3DDevice7-Objekt

DrawPrimitive() Diese Methode rendert einen definierten Block von Vertexes als Sequenz eines typischen geometrischen Polygons. object.DrawPrimitive(d3Dpt As CONST_D3DPRIMITIVETYPE, _ d3dfvf As CONST_D3DFVFFLAGS, vertices As Any, vertexCount As _ Long, flags As CONST_D3DDPFLAGS) object d3Dpt ein gltiges Direct3DDevice7-Objekt Eine Variable vom Typ CONST_D3DPRIMITIVETYPE. Er definiert die Art des Polygontyps (Type of primitive), mit dem die Szene gerendert werden soll. Eine Variabel vom Typ CONST_D3DFVFFLAGS. Er beschreibt das verwendete Vertexformat. Das erste Element in einem Vertex-Array Anzahl der Vertexe, welche gerendert werden sollen. Das Maximum ist auf 65535 (&HFFFF) begrenzt. Variable vom Typ CONST_D3DDPFLAGS. Sie definiert, wie das Polygon gezeichnet werden soll.

d3dfvf vertices vertexCount flags

Wir werden ein Dreieck im Koordinatensystem der 3D-Welt definieren und auf dem Bildschirm darstellen. Dabei werden wir weder Licht noch Material des Dreiecks bercksichtigen. Dies ist normalerweise ein gewaltiger Fehler. Dennoch begehen wir diesen Fehler, schlielich wollen wir das Listing recht bersichtlich gestalten. Licht sowie Objektmaterial werden spter ausgiebig besprochen. In dieser ersten Demonstration der Leistungsfhigkeit von D3D sollten Sie nicht zu viel erwarten, denn es geht nur um die Technik und nicht um gestalterische Hchstleistungen. Betrachten Sie das Bildschirmfoto zu unserem Beispiel. Zerlegen wir die anstehenden Aufgaben in Einzelschritte: Schritt 1: Schritt 2: Schritt 3: Schritt 4: Variablen benennen Variablen initialisieren Koordinaten fr das Dreieck bestimmen Zeichnen des Dreiecks

Kapitel 2 Direct3D

111

Bild 2.4:

Ein einfaches Polygon

Schritt 1: Variablen benennen In dieser Grundanwendung flieen die Komponenten aus DirectDraw und Direct3D zusammen. Schauen wir uns direkt die Dimensionierungen der Variablen an.
Dim Dim Dim Dim Dim g_dx As New DirectX7 g_dd As DirectDraw g_ddsd As DDSURFACEDESC2 g_ddsPrimary As DirectDrawSurface7 g_ddsBackBuffer As DirectDrawSurface7

Bis hierher sieht das alles recht vertraut aus. Sollten Sie Probleme mit diesen Strukturen haben, dann schauen Sie einfach in den Fullscreen-Abschnitt von DirectDraw.
Dim g_d3d As Direct3D7

Das Direct3D7-Objekt stellt die Verbindung zu Direct3D von DirectX her.


Dim g_d3dDevice As Direct3DDevice7

ber das Direct3DDevice7-Objekt laufen alle Aufgaben, welche zum Rendern einer Szene notwendig sind.

112

Zeichnen eines Dreiecks

Dim vPort As D3DVIEWPORT7

Den Viewport knnen Sie mit einem Fenster vergleichen. Durch dieses Fenster knnen wir in die 3D-Welt hineinsehen. Mit Hilfe des D3DVIEWPORT7-Typen-Arrays werden die Dimensionen des Renderziels definiert. Normalerweise werden die Szenen auf der Backbuffersurface gerendert. Somit werden wir spter die Dimensionen der Backbuffersurface bergeben. Dieses Typenarray beinhaltet zwei Mitglieder (maxz und minz), die fr unser Beispiel noch keine Bedeutung besitzen, dennoch erklren wir jetzt deren Aufgabe. Das Array ist folgendermaen aufgebaut:
Type D3DVIEWPORT7 lHeight As Long lWidth As Long lX As Long lY As Long maxz As Single minz As Single End Type

Die ersten vier Eintrge sind recht einfach erklrt. lX und lY bestimmen die linke obere Ecke des Zielrechtecks. lHeight und lWidth bestimmen die Dimensionen (in Pixel) des Zielrechtecks. Diese Daten sind zwingend erforderlich. Die letzen beiden Mitglieder erhalten erst eine Bedeutung, wenn wir mit dem Z Buffer arbeiten. ber den Z Buffer definieren Sie, welches Objekt im 3D-Raum vor einem anderen Objekt gezeichnet wird. Die meisten Anwendungen setzen diese Eintrge auf die Werte 1.0 (fr maxz) und 0.0 (fr minz). Somit werden die Deklarationen des Z Buffers bercksichtigt. Werden beide Werte auf 0.0 gesetzt, so zwingen Sie D3D dazu, das Objekt in den Vordergrund zu rendern. Vorerst ignorieren wir diese Eintrge.
Dim g_d3drcViewport(0) As D3DRECT

Hierbei handelt es sich um eine fast normale RECT-Struktur. Der Unterschied liegt in der Dimensionierung der Mitglieder. Diese sind jetzt vom Typ Long.
Dim matProj As D3DMATRIX Dim matView As D3DMATRIX Dim matWorld As D3DMATRIX

Diese drei Matrizen bestimmen alles, was Sie auf Ihrem Bildschirm zu sehen bekommen. Sie werden noch ausgiebig besprochen. In diesem Anfangsbeispiel knnen wir auf eine Transformation der Worldmatrix verzichten. Spter wird dies aber notwendig sein.
Dim Vertex(100) As D3DVERTEX

Kapitel 2 Direct3D

113

In den Vertex-Strukturen werden die Vektordaten der Polygoneckpunkte gespeichert. Schritt 2: Variablen initialisieren Die Initialisierungssequenz beginnt mit dem initialisieren der DirectDraw-Strukturen. Diese ist uns aus dem DirectDraw-Abschnitt bestens bekannt. Die einzige Erneuerung besteht in der lCaps-Deklaration. Hier wird ein zustzliches Flag DDSCAPS_3DDEVICE gesetzt. Es ermglicht den Zugriff auf das notwendige Direct3Ddevice.
Set g_dx = New DirectX7 Set g_dd = g_dx.DirectDrawCreate("") g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_FULLSCREEN Or _ DDSCL_EXCLUSIVE g_dd.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT Dim ddsd2 As DDSURFACEDESC2 ddsd2.lFlags = DDSD_BACKBUFFERCOUNT Or DDSD_CAPS ddsd2.ddsCaps.lCaps = DDSCAPS_COMPLEX Or DDSCAPS_FLIP Or _ DDSCAPS_PRIMARYSURFACE Or DDSCAPS_VIDEOMEMORY Or _ DDSCAPS_3DDEVICE ddsd2.lBackBufferCount = 1 Set g_ddsPrimary = g_dd.CreateSurface(ddsd2) Dim Caps As DDSCAPS2 Caps.lCaps = DDSCAPS_BACKBUFFER Set g_ddsBackBuffer = g_ddsPrimary.GetAttachedSurface(Caps)

Ab hier wird es interessanter. Wir initialisieren die direkte Verbindung zur gewnschten 3D-Welt.
Set g_d3d = g_dd.GetDirect3D

Die DirectDraw7.GetDirect3D()-Methode kreiert das zuvor dimensionierte Direcet3D7-Objekt. Es wird ber die Set-Anweisung ohne Angabe von Parametern zugewiesen und ist somit gnzlich unkompliziert.
Set g_d3dDevice = g_d3d.CreateDevice _ ("IID_IDirect3DHALDevice", g_ddsBackBuffer)

Jetzt erzeugen wir das Direct3DDevice. Es mssen zwei Parameter bercksichtigt werden. Als ersten Parameter mssen wir den guid As String bergeben. IID_ IDirect3DHALDevice, IID_IDirect3DRGBDevice oder IID_IDirect3DRef Device stehen zur Auswahl. Mit IID_IDirect3DHALDevice erreichen Sie die beste Performance. Sie adressieren die Grafikkarte auf direktem Weg. Welche Mglichkeiten zur Auswahl stehen, knnen Sie mit der Direct3D7.GetDevicesEnum()-Methode abfragen.
vPort.lX = 0 vPort.lY = 0

114

Zeichnen eines Dreiecks

vPort.lHeight = 480 vPort.lWidth = 640 g_d3dDevice.SetViewport vPort

Bei diesen Zuweisungen muss nicht viel erklrt werden. Die ersten beiden Parameter lX und lY definieren die linke obere Ecke des Viewports. Die beiden anderen Parameter bestimmen die Dimension des Viewports. Anschlieend weisen wir den definierten Viewport dem Direct3DDevice zu.
With g_d3drcViewport(0) .X1 = 0: .Y1 = 0 .X2 = 640 .Y2 = 480 End With

Diese 3D-RECT-Struktur bentigen wir nur, um zum spteren Zeitpunkt den Viewport ber die Direct3DDevice7.Clear()-Methode zu bereinigen. (Wird gleich noch genauer erklrt.)
g_dx.IdentityMatrix matView

Die DirectX7.IdentityMatrix()-Methode erstellt eine identische Matrix. Die Koeffizienten dieser Matrix sind mit 0 gefllt, mit Ausnahme der Eintrge rc11, rc22, rc33 und rc44. Diese Eintrge haben den Wert 1. Diese Matrix ist die Ausgangsmatrix fr Transformationen wie Rotation.
Call g_dx.ViewMatrix(matView, MakeVector(0, 0, -15), _ MakeVector(0, 0, 0), MakeVector(0, 1, 0), 0)

Hiermit wird eine Viewmatrix erstellt. Sie basiert auf der aktuellen Kameraposition. DirectX7.ViewMatrix() beinhaltet vier Parameter. vFrom As D3DVector bestimmt die Position, an der die Kamera steht. vTo As D3DVector legt fest, wohin die Kamera ausgerichtet ist. vUp As D3DVector beschreibt, wie sich die 3D-Welt zur Kamera verhlt. Fr gewhnlich steht dieser Wert auf [0,1,0]. Experimentieren Sie mit diesen Werten. Die Effekte sind verblffend und durchaus einsetzbar. Der letzte Parameter heit roll As Single. Mit ihm knnen Sie einen Winkel angeben, auf den die Kamera (um die Blickrichtung) rotiert werden soll.
g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView

Die Direct3DDevice7.SetTransform()-Methode weist eine einzelnen Transformation dem Device zu. Diese Methode besitzt zwei Parameter. Zum einen transformType as CONST_D3DTRANSFORMSTATETYPE. Die wichtigsten Definitionen sind D3DTRANSFORMSTATE_WORLD, D3DTRANSFORMSTATE_ VIEW, und D3DTRANSFORMSTATE_PROJECTION. Der zweite Parameter verlangt eine Matrix As D3DMATRIX. matView wurde von uns als D3DMATRIX definiert und jetzt fr Transformationen zur Verfgung gestellt.

Kapitel 2 Direct3D

115

g_dx.IdentityMatrix matProj Call g_dx.ProjectionMatrix(matProj, 1, 100, 3.14159 / 2) _ g_d3dDevice.SetTransform D3DTRANSFORMSTATE_PROJECTION,_ matProj

Die Projektionsmatrix berechnet, von wo (nearPlane As Single) und bis wo (farPlane As Single) Objekte im 3D-Raum dargestellt werden. Zustzlich knnen Sie die Blickwinkel (fov As Single) des Betrachters (Kamera) einstellen. Natrlich wird auch eine Matrix (mDest As D3DMATRIX) verlangt.
g_d3dDevice.SetRenderTarget g_ddsBackBuffer

Mit der Direct3DDevice7.SetRenderTarget()-Methode legen Sie das Ziel zum Rendern fest. Der einzige Parameter dieser Methode verlangt eine gltige Surface. Schritt 3: Koordinaten fr das Dreieck bestimmen
g_dx.CreateD3DVertex 2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(0) g_dx.CreateD3DVertex -2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(1) g_dx.CreateD3DVertex 0, 2.5, 0, 0, 0, -1, 0, 0, Vertex(2)

Die Koordinaten fr einen Punkt in einem 3D-Raum werden in Vektoren organisiert. Vertex bersetzt heit Spitze oder Scheitelpunkt. Die DirectX7.Create D3Dvertex()-Methode erfasst die relevanten Daten eine Punktes (Spitze) im 3DRaum. Die ersten drei (x As Single, y As Single und z As Single) Parameter sind die absoluten Werte im 3D-Raum, welche den Punkt beschreiben. Die folgenden drei Parameter (nx As Single, ny As Single und nz As Single) beschreiben die Orientierung (Ausrichtung) des Normalvektors. Der Normalvektor ist ein senkrechtes Lot auf die Dreiecksflchen (Eigentlich von den Vertexen eines Dreiecks). Er gewinnt an Bedeutung in Verbindung mit Lichteinflssen. Es folgen die nchsten beiden Parameter tu As Single und tv As Single. Dies sind Texturkoordinaten und fr den jetzigen Zeitpunkt noch uninteressant. Der letzte Parameter v As D3DVertex verlangt eine Vertexvariable. Diese haben wir bereits dimensioniert und sie wird jetzt zugewiesen. Schritt 4: Zeichnen des Dreiecks
g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ RGB(255, 0, 0), 0, 0

Die Direct3DDevice7.Clear()-Methode ermglicht das Lschen des Viewports (oder Teilen des Viewports) mit einer bestimmten Farbe. Des Weiteren knnen Sie den Z Buffer und den Stencil Buffer lschen. Wir bentigen sie zum Lschen des Viewports. count As Long enthlt die Anzahl der Rechtecke des folgenden recs As D3DRECT-Arrays. Der dritte Parameter flags As CONST_ D3DCLEARFLAGS bestimmt das Ziel, welches Sie lschen wollen. Zur Auswahl stehen 3DCLEAR_TARGET, D3DCLEAR_STENCIL und D3DCLEAR_

116

Zeichnen eines Dreiecks

ZBUFFER. Der Parameter color As Long versteht sich von alleine. Natrlich wird hier die Farbe definiert, mit welcher der Viewport gelscht werden soll. Am besten nutzen Sie die DirectX7.CreateColorRGBA()-Methode. Alternativ knnen Sie auch die normale RGB()-Methode nutzen. Die letzten beiden Parameter z und stencil sind noch uninteressant und werden auf den Wert 0 gesetzt.
g_d3dDevice.BeginScene

Mit der Direct3DDevice7.BeginScene()-Methode leiten Sie das Rendern einer Szene ein. Es sind keine Parameter zu bercksichtigen.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, D3DFVF_VERTEX, Vertex(0), 3, D3DDP_WAIT

Um das Dreieck zu rendern, bedienen wir uns der Direct3DDevice7.Draw Primitive()-Methode.


g_d3dDevice.EndScene

Das Ende einer Szene wird mit der Direct3DDevice7.EndScene()-Methode markiert.


g_ddsPrimary.Flip Nothing, DDFLIP_WAIT

Zum Abschluss bleibt nur noch eins zu tun. Mit der bekannten Flip()-Methode kopieren wir die gerenderte Szene vom Backbuffer auf die sichtbare primre Surface. Beispiel Dreieck Unser Beispielprogramm zum Darstellen eines einfachen Dreiecks, ohne Bercksichtigung von Material und Licht, beginnt mit der Subroutine Form_Load(). Im allgemeinen Deklarationsabschnitt finden Sie alle verwendeten Variablen des Programms.
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal _ vKey As Long) As Integer

Diese allgemein zugngliche API-Methode verwenden wir, um das Programm ber die Escape-Taste zu beenden. Natrlich knnte dieses auch mit DirectInput erledigt werden, wrde aber die Transparenz des Beispielprogramms verschleiern und der eigentliche Kontext ginge verloren. Somit haben wir uns fr eine einfachere Methode entschieden.
Dim g_dx As New DirectX7 Dim g_dd As DirectDraw7 Dim g_d3d As Direct3D7

Kapitel 2 Direct3D

117

Initialisierung der DirectX-Knotenpunkte.


Dim ddsd As DDSURFACEDESC2 Dim g_ddsPrimary As DirectDrawSurface7 Dim g_ddsBackBuffer As DirectDrawSurface7

Surfaces definieren. ddsd dient als zentrale Surfacebeschreibung.


Dim g_d3dDevice As Direct3DDevice7 Dim vPort As D3DVIEWPORT7 Dim g_d3drcViewport(0) As D3DRECT

Direct3D-Objekte dimensionieren.
Dim matProj As D3DMATRIX Dim matView As D3DMATRIX

Die notwendigen Matrizen festlegen. (In diesem Beispiel wird auf die Weltmatrix verzichtet.)
Dim Vertex(2) As D3DVERTEX

Das Vertex-Array wird die drei Eckpunkte des Dreiecks aufnehmen.


Private Sub Form_Load() InitDDraw InitD3D

Nach dem Starten des Programms wird zuerst in die Initialisierungsroutinen InitDDraw() und InitD3D() verzweigt. Diese werden nicht mit aufgelistet, da sie in dem vorherigem Abschnitt erklrt sind.
g_dx.CreateD3DVertex 2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(0) g_dx.CreateD3DVertex -2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(1) g_dx.CreateD3DVertex 0, 2.5, 0, 0, 0, -1, 0, 0, Vertex(2)

Anschlieend erstellen wir die Eckpunkte des Dreiecks. Diese werden in den Array-Elementen Vertex(0 bis 2) gespeichert.
Do g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ &HFF, 0, 0 g_d3dDevice.BeginScene 'Anfang Szene g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(0), 3, D3DDP_WAIT g_d3dDevice.EndScene 'Ende Szene g_ddsPrimary.Flip Nothing, DDFLIP_WAIT Loop Until GetAsyncKeyState(vbKeyEscape) <> 0

In der Do...Loop Until GetAsyncKeyState(vbKeyEscape) <> 0-Schleife tun wir Folgendes. Mit der Clear()-Methode lschen wir den gesamten Viewport.

118

Dreieck-Raster-Regeln

Anschlieend starten wir eine neue Szene mit der BeginSzene()-Methode. Das eigentliche Dreieck wird mit der DrawPrimitive()-Methode gerendert. Jetzt bleibt nur noch, die aktuelle Szene mit der EndScene()-Methode zu beenden und auf die primre Surface zu kopieren.
g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL g_dd.RestoreDisplayMode Set g_dd = Nothing Set g_d3dDevice = Nothing Set g_dx = Nothing End

Die Do...Loop Schleife luft so lange, bis die Escape-Taste gedrckt wird. Ist dies der Fall, sorgen wir fr ein ordentliches Verlassen des Programms.
End Sub

2.4

Dreieck-Raster-Regeln
Oft ist es so, dass die Koordinaten, welche einen Scheitelpunkt beschreiben, die Pixel des Bildschirms nicht genau treffen. Wenn dies passiert, werden die Dreieck-Raster-Regeln angewendet. Sie bestimmen welche Pixel des Bildschirms zu der erstellten Figur gehren. Direct3D baut die Figuren immer von links oben nach rechts unten (top-left filling convention) auf. Dies ist die gleiche Technik, wie sie von GDI und OpenGL benutzt wird. Direct3D geht immer davon aus, dass die Koordinaten das Zentrum eines Pixel beschreiben. Ist das Zentrum innerhalb eines Dreiecks so, ist das Pixel ein Teil des Dreiecks. Pixelzentren werden immer als Ganzzahl (Integer) angegeben. Folgende Grafik zeigt eine Matrix mit 25 Pixeln. Sie beginnt mit (0, 0) und endet mit (5, 5). Die Breite des Rechtecks wird beschrieben mit: Rechts minus Links. Die Hhe wird beschrieben durch: Unten minus Oben. Die top-left filling convention besagen, das eine Kante keine obere Kante (top edge) sein kann, auer sie verluft horizontal. An der Grafik oben knnen Sie erkennen, wann eine Kante als top Edge bezeichnet wird. Nun wird es selten vorkommen, das eine Kante horizontal verluft. Somit haben die meisten Dreiecke nur eine linke und rechte Kante. Sollten Sie in Ihrem Koordinatensystem zwei Dreiecke definieren, welche teilweise die gleichen Pixel verwenden, so werden die gemeinsamen Pixel dem ersten Dreieck zugeordnet. Siehe Grafik. Die gemeinsamen Pixel in der Diagonalen von links oben nach rechts unten werden Dreieck 1 zugeordnet, da dieses frher definiert wurde. Die Scheitelpunkte (Spitzen) der Dreieck sind wie folgt definiert.

Kapitel 2 Direct3D

119

Bild 2.5:

Pixeldarstellung eines Rechtecks

0 Top Edge 0 1 2 3 4 5
Bild 2.6: Obere Kante

keine obere Kante wrde als rechte Kante beschrieben

120

World-, View- und Projection-Matrix

Dreieck 1

Dreieck 2
Bild 2.7: Pixelzuweisung

Dreieck 1: (0, 0) ; (5, 0) ; (5, 5) Dreieck 2: (0, 0) ; (5, 5) ; (0, 5)

2.5

World-, View- und Projection-Matrix


Das zweidimensionale Computerbild, welches wir auf dem Monitor zu sehen bekommen, wird durch die Welt-Matrix, Sicht-Matrix sowie Projektions-Matrix bestimmt. Alle 3D-Grafiken haben mit einem gemeinsamen Problem zu kmpfen. Wie stellt man ein 3D-Objekt auf einer 2D-Flche dar? Die wichtigste Grundlage fr 3D-Applikationen bildete das Koordinatensystem. Das kartesische Koordinatensystem mit drei Dimensionen x, y und z bildet die Basis fr Direct3D. Die Beschreibung und Berechnung unserer dreidimensionalen Welt findet zunchst nur im Speicher des Computers statt, ohne dass eine visuelle Ausgabe erfolgt. Damit eine ordentliche 2D-Ausgabe ber den Monitor erfolgen kann, nutzten alle Objekte dieser Welt drei verschiedene Koordinatensysteme. Sie bedienen sich drei verschiedener Matrizen. World-Matrix (World Transformation) Jedes Objekt in der 3D-Welt hat ein eigenes Koordinatensystem. So werden die Koordinaten fr das Objekt relativ zu seinem eigenen Ursprung (vollkommen unabhngig von den Weltkoordinaten) definiert. ber die Welt-Transformation werden diese Objekte in das Gefge der Weltkoordinaten eingefgt.

Kapitel 2 Direct3D

121

lokale Koordinaten Y Z X Z X Weltkoordinaten X Y Z

Bild 2.8:

Lokale Objektkoordinaten in dem Weltkoordinatensystem

View-Matrix (View-Transformation) Die View-Transformation ermittelt den Betrachter (die Kamera) in der 3DWelt und transformiert die Polygone wie sie der Betrachter mit seiner aktuellen Blickrichtung sehen wrde. Ein wesentlicher Faktor ist die Tiefe (welche Objekte werden durch andere Objekte fr den Betrachter verdeckt) des Objektes im 3D-Raum. Beachten Sie, dass fr diese Berechnungen das linkshndige Koordinatensystem (siehe Koordinatensystem) zugrunde gelegt wird. Es gibt viele Wege um eine View-Matrix zu erstellen. In allen Fllen hat die Kamera eine logische Position und eine logische Orientierung im 3D-Raum. Das ist der Ursprung der View-Matrix. Die View-Matrix bersetzt und rotiert die Objekte einer 3D-Welt so, wie Sie der Betrachter sehen wrde.
hintere Seite

vordere Seite

3D Welt
Bild 2.9: 3D-Welt mit den Sichtbegrenzungen

122

Matrix-Berechnungen

Projektions-Matrix (Projektion-Transformation) Die Projektions-Transformation ist fr die richtige perspektivische Darstellung des 3D-Raums auf den 2D-Monitor zustndig. Die Objekte im 3D-Raum sind in einem wrfelhnlichem Gebilde definiert. Die vordere Seite des Gebildes ist kleiner als die hintere Seite. Vergleichbar ist dieses Gebilde mit einer Pyramide, bei der die Spitze abgeschnitten wurde. Da solch ein Gebilde nicht einfach auf eine zweidimensionale Flche bertragbar ist, wird es ber die ProjektionsMatrix berechnet.

2.6

Matrix-Berechnungen
Matrizen werden Ihnen vielleicht etwas fremdartig anmuten. Dennoch werden wir uns mit diesem Thema beschftigen mssen. Matrizen sind die Basis fr Ihre gesamte 3D-Welt. Matrizen werden in D3D als einheitliche 4 X 4-Matrix reprsentiert. Hierzu dient das D3DMATRIX (siehe 3D-Koordinatensystem) Typen-Array. 3D-Transformation (Umformung) ist der Schlssel zu allen Aktionen im 3DRaum. Mit der Matrix-Transformation bestimmen Sie die Gre sowie die Position eines Objektes (relativ zu den Weltkoordinaten). Sie definieren die Position, Blickrichtung und Perspektive des Betrachters. Sie knnen Objekte in Bezug auf Rotation oder Verzerrung beeinflussen. Um es auf einen Nenner zu bringen, mit der Matrix-Transformation bestimmen Sie alle Berechnungen zum Navigieren im 3D-Raum, sowie das Verhalten aller Objekte relativ zum 3D-Raum. Sie knnen jeden Punkt im 3D-Raum in einen anderen transformieren. Sie nutzen dann die homogene 4 X 4-Matrix. [x y z 1] = [x y z 1] M11 M21 M31 M41 M12 M22 M32 M42 M13 M23 M33 M43 M14 M24 M34 M44

x = (x * M11) + (y * M21) + (z * M31) + (1 * M41) y = (x * M12) + (y * M22) + (z * M32) + (1 * M42) z = (x * M13) + (y * M23) + (z * M33) + (1 * M43)

2.6.1

Translation
Um ein Objekt im 3D-Raum zu positionieren, mssen die Koordinaten auf die aktuellen Welt-Koordinaten bersetzt werden. Hierzu knnen Sie folgende Subroutine nutzen.
Sub TranslateMatrix(m As D3DMATRIX, v As D3DVECTOR) Call dx.IdentityMatrix(m) m.rc41 = v.x m.rc42 = v.y m.rc43 = v.z End Sub

Kapitel 2 Direct3D

123

Diese Routine knnen Sie explizit in Ihrem Quelltext einfgen oder sie binden das Math.bas Modul ein. Als Matrix sieht die bersetzung so aus : [x y z]=[x y z] 1 0 0 TX 0 1 0 TY 0 0 1 TZ 0 0 0 1

2.6.2

Rotation
Jedes Objekt im 3D-Raum besitzt drei Achsen. Um jede dieser Achsen kann das Objekt rotieren. Diese Rotation knnen Sie fr eine effektreiche Gestaltung Ihrer 3D-Welt einsetzen. Denken Sie dabei einfach an die Rotation eines Deckenventilators. Die Rotationsberechnungen sind aber auch notwendig, um ein Objekt im 3D-Raum zu platzieren. Die Rotationsberechnungen werden mit Hilfe von Matrizen vorgenommen. Bevor wir zu den eigentlichen Berechnungen kommen, schauen Sie sich die folgenden Methoden an. Diese Methoden erleichtern die Matrizenrechnungen und werden von DirectX zur Verfgung gestellt.
RotateXMatrix() Rotiert den Punkt (x,y,z) um die X-Achse und erzeugt den neuen Punkt (x,y,z). object.RotateXMatrix(mDest As D3DMATRIX, radians As Single) object mDest radians ein gltiges DirectX7-Objekt Nimmt die transformierten Koordinaten des Punktes (x,y,z) auf. Der Winkel der Rotation um die X-Achse. Wird angegeben im Uhrzeigersinn um die X-Achse (betrachtet vom Ursprung der Achse).

RotateYMatrix() Rotiert den Punkt (x,y,z) um die Y-Achse und erzeugt den neuen Punkt (x,y,z). object.RotateYMatrix(mDest As D3DMATRIX, radians As Single) object mDest radians ein gltiges DirectX7-Objekt Nimmt die transformierten Koordinaten des Punktes (x,y,z) auf. Der Winkel der Rotation um die Y-Achse wird angegeben im Uhrzeigersinn um die Y-Achse (betrachtet vom Ursprung der Achse).

124

Matrix-Berechnungen

RotateZMatrix() Rotiert den Punkt (x,y,z) um die Z-Achse und erzeugt den neuen Punkt (x,y,z). object.RotateZMatrix(mDest As D3DMATRIX, radians As Single) object mDest radians ein gltiges DirectX7-Objekt Nimmt die transformierten Koordinaten des Punkes (x,y,z) auf. Der Winkel der Rotation um die Z-Achse. Wird angegeben im Uhrzeigersinn um die Z-Achse (betrachtet vom Ursprung der Achse).

Die folgenden drei Matrizen beschreiben die Rotationsmglichkeiten um die XAchse, Y-Achse sowie Z-Achse. Als DirectX-Programmierer sind Sie nicht zwingend darauf angewiesen, diese Berechnungen direkt an Matrizen vorzunehmen. Sie knnen auf die oben vorgestellten Rotationsmethoden RotateZMatrix(), RotateZMatrix() und RotateZMatrix() zurckgreifen. Dennoch ist es hilfreich, zu wissen was diese Methoden eigentlich tun. Rotation um die X-Achse 0 0 0 0 Rotation um die Y-Achse cos 0 sin 0 Rotation um die Z-Achse cos -sin 0 0 sin cos 0 0 0 0 1 0 0 0 0 1 0 1 0 0 -sin 0 cos 0 0 0 0 1 0 cos -sin 0 0 sin cos 0 0 0 0 1

[x y z]=[x y z] 1

[x y z]=[x y z]

[x y z]=[x y z]

Das griechische Zeichen Theta () steht fr den Rotationsgrad (Radiant-Winkel). Der Winkel wird im Uhrzeigersinn gemessen, entlang der entsprechenden Achse) Die Umsetzung auf die D3D-Matrix sieht fr eine Rotation der X-Achse so aus:
Sub CreateXRotation(ret As D3DMATRIX, rads As Single) Call dx.IdentityMatrix(ret) ret.rc22 = Cos(rads)

Kapitel 2 Direct3D

125

ret.rc23 = Sin(rads) ret.rc32 = Sin(rads) ret.rc33 = Cos(rads) End Sub

Glcklicherweise kann der VB-Programmierer vorgefertigte Methoden von Direct3D nutzen. Fr die Rotation der drei Achsen stehen die Methoden DirectX7.RotateXMatrix(), DirectX7.RotateYMatrix() sowie DirectX7.RotateZMatrix() bereit. Diese Methoden beinhalten zwei Parameter. mDest As D3DMATRIX dient als Empfnger der Transformation. Radians As Single gibt den Winkel der Rotation an. Es folgt die Syntax der Methoden:
object.RotateXMatrix(mDest As D3DMATRIX, radians As Single) object.RotateYMatrix(mDest As D3DMATRIX, radians As Single) object.RotateZMatrix(mDest As D3DMATRIX, radians As Single)

Beispiel (Rotation um die Y-Achse) Dieses Beispiel ist im Wesentlichen identisch mit der Applikation zum Erstellen eines Dreiecks. Wiederum werden wir Material und Licht gnzlich ignorieren. Wichtig ist es zu erwhnen, dass wir ein einzelnes Objekt im 3D-Raum rotieren lassen. Dies ist komplizierter, als die gesamte 3D-Welt rotieren zu lassen. Auch dieses Demo knnen wir mit der Escape-Taste verlassen. Da sich in unserem Rotationsbeispiel im Vergleich zur Darstellung eines einfachen Dreiecks kaum nderungen einstellen, betrachten wir nur die Form_Load()-Subroutine. Diese enthlt alle relevanten Aufgaben.
Private Sub Form_Load() InitDDraw InitD3D

Die beiden Initialisierungsroutinen beinhalten keine nderungen und brauchen nicht weiter erklrt werden.
g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex 2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(0) -2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(1) 0, 2.5, 0, 0, 0, -1, 0, 0, Vertex(2) 7.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(3) 2.5, -2.5, 0, 0, 0, -1, 0, 0, Vertex(4) 5, 2.5, 0, 0, 0, -1, 0, 0, Vertex(5)

Quasi als Beweis, dass wir ein Objekt drehen und nicht die ganze 3D-Welt, erstellen wir zwei Dreiecke. Ein Dreieck wird gedreht, das andere nicht.
Dim Winkel As Single Dim ObjectMatrix(2) As D3DMATRIX g_dx.IdentityMatrix ObjectMatrix(0) g_dx.IdentityMatrix ObjectMatrix(1)

126

Matrix-Berechnungen

Wir erstellen zwei einheitliche Matrizen. ObjectMatrix(0) wird dem rotierendem Dreieck zugeordnet.
Do Winkel = Winkel + 1: If Winkel > 360 Then Winkel = 0 g_dx.RotateYMatrix ObjectMatrix(0), Winkel / 57.296

ber den Ausdruck Winkel / 57.296 erfolgt die Umrechnung des in Grad angegebenen Winkels in Radiant. Der Wert 57.296 ergibt sich aus 180o geteilt durch die Kreiszahl PI(3.14159...). Hier lassen wir die ObjectMatrix(0) immer um ein Grad weiter rotieren.
g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ _ &HFF, 0, 0 g_d3dDevice.BeginScene g_d3dDevice.SetTransform D3DTRANSFORMSTATE_WORLD, _ ObjectMatrix(0)

Jetzt wird es wirklich interessant. Wir transformieren die World Matrix auf die manipulierte Matrix von Dreieck 1. Diese Matrix wird bei jedem Durchlauf der Do...Loop Schleife neu berechnet.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(0), 3, D3DDP_WAIT

Nachdem wir die ganze Welt etwas gedreht haben, rendern wir mit der Draw Primitive()-Methode das erste Dreieck.
g_d3dDevice.SetTransform D3DTRANSFORMSTATE_WORLD, _ ObjectMatrix(1)

Das zweite Dreieck soll nicht rotieren. Deshalb transformieren wir die WorldMatrix zurck auf den Ausgangswert. Lschen Sie diese Zeile aus dem Quelltext, dann rotiert die gesamte Welt. Somit auch alle Objekte in der Welt.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(3), 3, D3DDP_WAIT

Nachdem die Welt wieder gerade gerckt wurde, knnen wir das zweite Dreieck zeichnen.
g_d3dDevice.EndScene g_ddsPrimary.Flip Nothing, DDFLIP_WAIT Loop Until GetAsyncKeyState(vbKeyEscape) <> 0

Die Vorgehensweise wird so lange wiederholt, bis die Escape-Taste gedrckt wird. Fassen wir noch einmal zusammen. Die Technik besteht aus fnf Schritten.

Kapitel 2 Direct3D

127

Mit Hilfe der Hilfsmatrix ObjectMatrix(0) wird die gesamte Welt gedreht. Nachdem die Welt gedreht wurde, wird das erste Objekt gerendert. Die Welt wird auf die Ausgangswerte zurck gesetzt. Dazu dient uns Object Matrix(1). Wir knnten auch jedes Mal die IdentitiyMatrix()-Methode aufrufen. Nachdem die Welt wieder in Ordnung ist, wird das zweite Objekt gerendert. Anschlieend wird die gerenderte Szene auf die primre Surface geflippt.

g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL g_dd.RestoreDisplayMode Set g_dd = Nothing Set g_d3dDevice = Nothing Set g_dx = Nothing End

Wir sorgen dafr, dass wir das Programm ordentlich verlassen.


End Sub

Sicherlich stellen Sie sich die Frage: Warum ist das Dreieck nur von einer Seite sichtbar? Das ist kein greres Problem. Es gibt zwei Wege zur Lsung. Der eine Weg ist, einfach ein weiteres Dreieck an die gleichen Koordinaten zu zeichnen. Bei diesem Dreieck mssen die Vektoren gegen den Uhrzeigersinn angegeben werden. Dadurch wird der Normalvektor entgegen dem Normalvektor des ersten Dreiecks erzeugt. Der zweite Weg benutzt den Cull-Status. ber den Cull-Status knnen Sie definieren, welche Seite sichtbar sein soll bzw. ob beide Seiten sichtbar sein sollen. Beispiel (Rotation 2) In dem ersten Rotationsbeispiel haben wir ein Objekt um den Ursprung der 3DWelt erstellt. Anschlieend haben wir die Welt gedreht und das Objekt an der richtige Position in der 3D-Welt platziert. Diese Technik ist eine uerst schnelle Technik. Leider bringt Sie auch Nachteile mit sich. Da das Objekt eigentlich an den Koordinaten [0, 0, 0] steht und nachtrglich in der Welt positioniert wird, werden die aktuellen Lichteinflsse falsch bercksichtigt. Aus diesem Grund haben wir uns entschieden, Ihnen eine weitere Technik zu prsentieren. Die neue Technik ist nicht ganz so schnell wie die alte Technik, sie ergibt aber eine realistischere Darstellung der Szene. Im Beispiel zum Nebeleffekt werden wir die Technik richtig nutzen. Jetzt begngen wir uns mit der eigentlichen Rotation. Betrachten Sie zuerst das Bildschirmfoto. Sie werden zwei Dreieck erkennen; das linke Dreieck rotiert, das rechte Dreieck ist statisch.

128

Matrix-Berechnungen

Bild 2.10: Bildschirmfoto Rotation 2

Unser Ziel ist es, ein Objekt im 3D-Raum zu platzieren und dann an Ort und Stelle rotieren zu lassen. Um dies zu erreichen, mssen wir die Vertexe des Objektes manipulieren. Wir lassen alle Vertexe um einen Mittelpunkt drehen. Der Mittelpunkt ist insofern wichtig, da er den Bezugspunkt fr das gesamte Objekt darstellt. Wenn wir einen Mittelpunkt whlen, welcher nicht das Zentrum des Objektes darstellt, sondern z.B. auerhalb des Objektes liegt, so wird das Objekt wie ein Satellit den Punkt umkreisen. Wollen wir eine Rotation ohne dass sich die Position des Objektes ndert, so mssen wir das genaue Zentrum des Objektes als Rotationsmittelpunkt festlegen. Bei komplexeren Objekten hilft es Ihnen, wenn Sie zur Ermittlung des Mittelpunkes die kleinsten und grten x-, y-, z-Koordinaten ermitteln und davon die Mitte whlen.
Mitte_X = (Grter_X Kleinster_X) / 2 Mitte_Y = (Grter_Y Kleinster_Y) / 2 Mitte_Z = (Grter_Z Kleinster_Z) / 2

Diese bergeben wir an eine Variable vom Typ D3DVECTOR.


Dim Mitte Mitte.x = Mitte.y = Mitte.z = As D3DVECTOR Mitte_X Mitte_Y Mitte_Z

Kapitel 2 Direct3D

129

Anschlieend bergeben wir die x-, y-, z-Werte der Vertexe einer Variablen vom Typ D3DVECTOR.
Dim Temp1 Temp1.x = Temp1.y = Temp1.z = As D3DVECTOR Vertex(n).x Vertex(n).y Vertex(n).z

Jetzt bentigen wir noch die Variable Temp2 vom Typ D3DVECTOR. In dieser Variablen werden wir die transformierten x-, y-, z-Koordinaten zwischenspeichern. Nun knnen wir die Rotation()-Subroutine aufrufen. Wir bergeben folgende Parameter:
Rotation Temp1, Temp2, Mitte, Winkelvernderung

Der letzte Parameter Winkelvernderung definiert, um wie viel Grad sich das Objekt drehen soll. Die Rotation()-Subroutine sieht so aus:
Public Sub Rotation(VecIn As D3DVECTOR, VecOut As D3DVECTOR, _ Mitte As D3DVECTOR, ByVal Winkelvernderung As Single) Dim RMat As D3DMATRIX Dim PMat As D3DMATRIX Dim DMat As D3DMATRIX g_dx.IdentityMatrix Rmat g_dx.IdentityMatrix Pmat g_dx.IdentityMatrix DMat g_dx.RotateYMatrix RMat, Winkel / 57.296 PMat.rc41 = VecIn.x Mitte.x PMat.rc42 = VecIn.y Mitte.y PMat.rc43 = VecIn.z Mitte.z RMat.rc41 = Mitte.x RMat.rc42 = Mitte.y RMat.rc43 = Mitte.z g_dx.MatrixMultiply DMat, PMat, Rmat VecOut.x = DMat.rc41 VecOut.y = DMat.rc42 VecOut.z = DMat.rc43 End Sub

Das Ergebnis der Rotation erhalten wir in dem VecOut-Vektor. Diesen haben wir als Temp2-Vektor bergeben und knnen die manipulierten Daten dem originalen Vertex wieder zuweisen.
Vertex(n).x = Temp2.x Vertex(n).y = Temp2.y Vertex(n).z = Temp2.z

130

Matrix-Berechnungen

Beim nchsten Rendern der Szene macht sich die Manipulation der Vertexe bemerkbar. Das Objekt wird sich mit jedem Durchlauf der Rotation()-Subroutine um ein Grad mehr drehen. In unserem Beispiel wenden wir diese Technik auf ein Dreieck an. Das Dreieck hat drei Vertexe. Wir knnen natrlich auch ein Objekt whlen, welches aus eintausend (oder mehr) Vertexen konstruiert wurde. Irgendwann wird sich dieses Verfahren als zu langsam entpuppen, aber dann knnen Sie immer noch auf die erste Technik zurckgreifen. Wann diese Technik zur Bremse wird, hngt von der CPU-Performance des eingesetzten PC ab. Der Vorteil dieser Technik ist jedoch offensichtlich. Da das Objekt an Ort und Stelle in der 3D-Welt gedreht wird, werden auch die Licht- und Schattenberechnungen auf das Objekt angewandt. Dadurch wirkt das Objekt wesentlich realistischer. In unserm jetzigen Beispiel bermerken Sie keinen Unterschied. Dies liegt natrlich daran, das wir die Lichteinflsse einer Szene sowie die Materialeigenschaften des Dreiecks nicht bercksichtigen. Unser Nebelbeispiel verwendet diese Technik. Dort knnen Sie die Einflsse von Licht und Schatten bestens beobachten.

2.6.3

Scaling
Mit der Scaling-Matrix knnen Sie den Mastab von jedem Punkt mit einem beliebigen Wert transformieren. Somit knnen Sie die Gre eines Objektes ndern. [x y z]=[x y z] ScaleX 0 0 0 ScaleY 0 0 0 0 0 0 0

ScaleZ 0 0 1

Beispiel (Scaling) Mit dem Scaling-Beispiel erkennen Sie, wie Sie die Gre eines einzelnen Objektes im 3D-Raum verndern knnen. Betrachten Sie dazu das Bildschirmfoto und vergleichen dieses mit dem Bildschirmfoto unserer ersten Beispielanwendung. Wir ignorieren erneut Licht und Material des Objektes. Auch die Initialisierungsroutinen sind unkompliziert. Schauen wir uns direkt die Do...Loop-Schleife in der Form_Load()-Subroutine an. Verlassen knnen Sie das Programm mit der Escape-Taste. Bei diesem Beispielprogramm kann man schnell den Eindruck bekommen, als wrden wir uns auf das Dreieck zubewegen und wieder entfernen. Das ist aber nicht der Fall. Wir verndern unsere Position nicht. Auch das Dreieck verndert seine Position nicht.

Kapitel 2 Direct3D

131

Bild 2.11: Bildschirmfoto Scale Do If Richtung = 0 Then ScaleFaktor = ScaleFaktor + 0.1 Else ScaleFaktor = ScaleFaktor 0.1 End If If ScaleFaktor > 6 Then Richtung = 1 If ScaleFaktor < 0 Then Richtung = 0

Hier lassen wir den Vergrerungsfaktor (ScaleFaktor) zwischen 0 und 6 pendeln.


ObjectMatrix(0).rc11 = ScaleFaktor ObjectMatrix(0).rc22 = ScaleFaktor

Diese unscheinbare Zuordnung des Vergrerungsfaktors zu den Mitgliedsdaten rc11 und rc12 sorgen fr die nderung der Gre.
g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ &HFF, 0, 0 g_d3dDevice.BeginScene g_d3dDevice.SetTransform D3DTRANSFORMSTATE_WORLD, _ ObjectMatrix(0)

132

Polygone

Die transformierte Matrix ObjectMatrix(0) wird der Welt-Matrix zugewiesen. Mit der folgenden DrawPrimitive()-Methode wird das Objekt in den neuen Grenverhltnissen gerendert.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _ Vertex(0), 3, D3DDP_WAIT g_d3dDevice.EndScene g_ddsPrimary.Flip Nothing, DDFLIP_WAIT Loop Until GetAsyncKeyState(vbKeyEscape) <> 0

2.7

Polygone
Die berschrift ist eigentlich falsch. Direct3D unterscheidet keine Polygontypen, sondern arbeitet nur mit einem Polygontyp. Die einzige Form eines Polygons, welches von D3D verwendet wird, ist das Dreieck. Mit dem Dreieck erstellen Sie alle Objekte einer 3D-Welt. Die Eckpunkte des Polygons werden in Vektoren organisiert. Unter Direct3D bedienen wir uns der Vertex-Strukturen. D3D stellt Ihnen verschiedene Techniken zur Verfgung, um entweder die Vertexe sichtbar zu machen oder miteinander zu verbinden. Pointlist Eine Punktliste ist eine Sammlung von Vertexen, welche als alleinstehender Punkt gerendert werden. Eine Punktliste sieht auf dem Monitor wie ein Sternenfeld aus. Eigentlich kann man dieser Technik nur wenig Bedeutung beimessen, dennoch lsst sich eine Punktliste aller Vertexe zur Entwicklungszeit eines Programms gut nutzen.
Dim Verts(6) As D3DVERTEX Verts(0) = dx.CreateD3DVertex(0, 0, 0, 0, 0, -1, 0, 0) Verts(1) = dx.CreateD3DVertex(3, 3, 0, 0, 0, -1, 0, 0) Verts(2) = dx.CreateD3DVertex(6, 0, 0, 0, 0, -1, 0, 0) Verts(3) = dx.CreateD3DVertex(9, 3, 0, 0, 0, -1, 0, 0) Verts(4) = dx.CreateD3DVertex(12, 0, 0, 0, 0, -1, 0, 0) Verts(5) = dx.CreateD3DVertex(15, 3, 0, 0, 0, -1, 0, 0) Call d3ddev.DrawPrimitive(D3DPT_POINTLIST, D3DFVF_VERTEX, _ Verts(0), 6, D3DDP_WAIT)

Da die Tiefenwerte (Z-Achse) bei allen Punkten 0 ist, knnen wir die Punkte auf ein zweidimensionales Koordinatensystem bertragen und abbilden. Betrachen wir es einmal. Sie knnen zwar den einzelnen Punkten Material oder Texturen zuweisen, jedoch sind diese nur direkt auf dem Punkt sichtbar. Da wir hier von einem Monitorpixel sprechen, hat dies kaum einen Sinn. Was sich wohl die Entwickler von DirectX dabei gedacht haben?

Kapitel 2 Direct3D

133

Y Achse

3,3,0 0,0,0 6,0,0

9,3,0 12,0,0

15,3,0

X Achse
Bild 2.12: Pointlist

Linelist Eine Linienliste ist ein Liste von geraden Linien. Dabei wird immer ein Vertex mit dem folgendem Vertex verbunden. Da eine Linie immer einen Anfangspunkt und einen Endpunkt, hat muss die Anzahl der verwendeten Vertexe ein Vielfaches von zwei sein. Eine Linelist knnen Sie hervorragend einsetzen, um z.B. starken Regen oder Schneeregen zu simulieren.
Dim Verts(6) As D3DVERTEX Verts(0) = dx.CreateD3DVertex(0, 0, 0, 0, 0, -1, 0, 0) Verts(1) = dx.CreateD3DVertex(3, 3, 0, 0, 0, -1, 0, 0) Verts(2) = dx.CreateD3DVertex(6, 0, 0, 0, 0, -1, 0, 0) Verts(3) = dx.CreateD3DVertex(9, 3, 0, 0, 0, -1, 0, 0) Verts(4) = dx.CreateD3DVertex(12, 0, 0, 0, 0, -1, 0, 0) Verts(5) = dx.CreateD3DVertex(15, 3, 0, 0, 0, -1, 0, 0) Call d3ddev.DrawPrimitive(D3DPT_LINELIST, D3DFVF_VERTEX, _ Verts(0), 6, D3DDP_WAIT)

Y Achse

3,3,0 0,0,0 6,0,0

9,3,0 12,0,0

15,3,0

X Achse
Bild 2.13: Linelist

134

Polygone

Sie knnen den Linien Materialien und Texturen zuweisen. Diese sind aber nur auf der Linie sichtbar. Die Zwischenrume von einer Linie zur anderen bleiben unberhrt. Linestrip Mit Linestrip (frei bersetzt: ein Streifen von Linien) verbinden Sie die Vertexe nacheinander. Sie knnen Linestrip nutzen, um Polygone zu erzeugen, welche nicht geschlossen sind. Ein geschlossenes Polygon ist nur dann geschlossen, wenn der letzte Punkt mit dem ersten Punkt verbunden ist.
Dim Verts(6) As D3DVERTEX Verts(0) = dx.CreateD3DVertex(0, 0, 0, 0, 0, -1, 0, 0) Verts(1) = dx.CreateD3DVertex(3, 3, 0, 0, 0, -1, 0, 0) Verts(2) = dx.CreateD3DVertex(6, 0, 0, 0, 0, -1, 0, 0) Verts(3) = dx.CreateD3DVertex(9, 3, 0, 0, 0, -1, 0, 0) Verts(4) = dx.CreateD3DVertex(12, 0, 0, 0, 0, -1, 0, 0) Verts(5) = dx.CreateD3DVertex(15, 3, 0, 0, 0, -1, 0, 0) Call d3ddev.DrawPrimitive(D3DPT_LINESTRIP, D3DFVF_VERTEX, _ Verts(0), 6, D3DDP_WAIT)

Y Achse 3,3,0 9,3,0


15,3,0

0,0,0

6,0,0

12,0,0 X Achse

Bild 2.14: Linestrip

Trianglelist Die Dreiecksliste ist durchaus mit der Linienliste vergleichbar. Natrlich werden bei diesem Verfahren sofort ganze Dreiecke erzeugt. Dabei werden immer drei Vertexe genommen, um ein Dreieck zu erstellen. Die Anzahl der Vertexe muss durch drei teilbar sein. Nutzen Sie diese Technik immer dann, wenn Sie Objekte erzeugen wollen, welche aus vielen einzelnen Teile bestehen. Auch fr Spezialeffekte knnen Sie diese Technik nutzen. Wollen Sie z.B. einen Schutzschild erzeugen, dann platzieren Sie eine Vielzahl von kleinen Dreiecken vor dem Objekt. Belegen Sie die Dreiecke mit Material und Textur. Diese nehmen nun das Umgebungslicht auf und das Objekt im Hintergrund ist durch die Lcken der Dreiecke sichtbar.

Kapitel 2 Direct3D

135

Dim Verts(6) As D3DVERTEX Verts(0) = dx.CreateD3DVertex(0, 0, 0, 0, 0, -1, 0, 0) Verts(1) = dx.CreateD3DVertex(3, 3, 0, 0, 0, -1, 0, 0) Verts(2) = dx.CreateD3DVertex(6, 0, 0, 0, 0, -1, 0, 0) Verts(3) = dx.CreateD3DVertex(9, 3, 0, 0, 0, -1, 0, 0) Verts(4) = dx.CreateD3DVertex(12, 0, 0, 0, 0, -1, 0, 0) Verts(5) = dx.CreateD3DVertex(15, 3, 0, 0, 0, -1, 0, 0) Call d3ddev.DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _ Verts(0), 6, D3DDP_WAIT)

Y Achse 3,3,0 9,3,0


15,3,0

0,0,0

6,0,0

12,0,0 X Achse

Bild 2.15: Trianglelist

Sie knnen die Dreiecke mit Material und Texturen berziehen. Trianglestrip Bei Trianglestrip handelt es sich um eine Serie von verbundenen Dreiecken. Das erste Dreieck wird aus den Vertexen eins, zwei und drei gebildet. Das folgende Dreieck wird aus den Vertexen zwei und drei des ersten Dreiecks sowie einem neuen Vertex gebildet. Dies setzt sich so fort. Beachten Sie, dass alle Vertexe eines Dreiecks im Uhrzeigersinn erstellt werden mssen. Ansonsten sind sie fr den Betrachter nicht sichtbar.
Dim Verts(6) As D3DVERTEX Verts(0) = dx.CreateD3DVertex(0, 0, 0, 0, 0, -1, 0, 0) Verts(1) = dx.CreateD3DVertex(3, 3, 0, 0, 0, -1, 0, 0) Verts(2) = dx.CreateD3DVertex(6, 0, 0, 0, 0, -1, 0, 0) Verts(3) = dx.CreateD3DVertex(9, 3, 0, 0, 0, -1, 0, 0) Verts(4) = dx.CreateD3DVertex(12, 0, 0, 0, 0, -1, 0, 0) Verts(5) = dx.CreateD3DVertex(15, 3, 0, 0, 0, -1, 0, 0) Call d3ddev.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, _ Verts(0), 6, D3DDP_WAIT)

136

Polygone

Y Achse 3,3,0 9,3,0


15,3,0

0,0,0

6,0,0

12,0,0 X Achse

Bild 2.16: Trianglestrip

Sie knnen die Dreiecke mit Material und Texturen berziehen. Diese Technik ist uerst beliebt. Zum einen lassen sich komplexe Objekte erstellen, zum anderen ist dieses Verfahren speicherschonend und sehr schnell. Sie erreichen mit Trianglestrip die beste Performance. Trianglefan Die letzte Technik ist der Dreiecksfcher. Der Fcher hat einen Anfangspunkt, auf den sich alle folgenden Vertexe beziehen. Zwischen allen Vertexen werden Verbindungen geschlossen.
Vertex 1 Vertex 2

Vertex 0

Vertex 3

Vertex 4 Vertex 7 Vertex 5 Vertex 6


Bild 2.17: Trianglefan Dim Verts(6) As D3DVERTEX Verts(0) = dx.CreateD3DVertex(1, 1, 0, 0, 0, -1, 0, 0) Verts(1) = dx.CreateD3DVertex(4, 8, 0, 0, 0, -1, 0, 0) Verts(2) = dx.CreateD3DVertex(6, 6, 0, 0, 0, -1, 0, 0)

Kapitel 2 Direct3D

137

Verts(3) = dx.CreateD3DVertex(7, 4, 0, 0, 0, Verts(4) = dx.CreateD3DVertex(7, 2, 0, 0, 0, Verts(5) = dx.CreateD3DVertex(6, 0, 0, 0, 0, Call d3ddev.DrawPrimitive(D3DPT_TRIANGLEFAN, Verts(0), 6, D3DDP_WAIT)

-1, 0, 0) -1, 0, 0) -1, 0, 0) D3DFVF_VERTEX, _

4,8,0 Y Achse 6,6,0

7,4,0

7,2,0 1,1,0 6,0,0 X Achse


Bild 2.18: Trianglefan

2.8

Licht
Licht und Material eines Objektes im 3D-Raum sind als zusammenhngende Komponenten zu betrachten. Ein Objekt ohne Material kann durch einfallendes Licht nicht reflektiert werde. Ebenso wird ein Objekt mit Material aber ohne Licht immer schwarz bleiben. In diesem Abschnitt wollen wir uns auf die Einflsse von Lichtquellen in einer 3D-Welt konzentrieren. Direct3D bernimmt die Berechnung von Licht und Material, dennoch ist der erfahrene Programmierer in der Lage, D3D so zu leiten, wie er es fr notwendig hlt. Der Umgang mit Beleuchtung und Material hat einen entscheidenden Anteil am Erscheinungsbild der gerenderten Szene. Material bestimmt, wie ein Objekt das einstrmende Licht reflektieren soll. Direktes Licht oder indirektes Licht definieren die Lichtquellen, welche reflektiert werden sollen. Das Licht von D3D wird mathematisch berechnet. Anders als in der Natur, sind diese Berechnungen von ein paar berschaubaren Parametern abhngig. In der Natur wird eine Lichtquelle von tausenden Objekten reflektiert, bevor sie das Auge des Betrachters erreicht. Von jedem Lichtteilchen welches reflektiert wird, wird auch ein Teil vom reflektierendem Objekt aufgenommen. Andere Teilchen

138

Licht

werden in verschiedene Richtungen gestreut. Irgendwann gelangen einige Lichtteilchen zum Betrachter. D3D steht nun vor der unlsbaren Aufgabe, das natrliche Licht zu simulieren. Um das natrliche Licht mglichst perfekt zu simulieren und dennoch den Performanceansprchen zu gengen, spaltet D3D jede Lichtquelle in ihre Rot-, Grn- und Blauanteile. Die endgltige Farbe eines Objektes ist eine mathematische Mischung von Lichtanteilen und Materialanteilen. D3D unterteilt Licht in zwei Gruppen: indirektes Licht (Ambientlight) und direktes Licht. Beide haben unterschiedliche Eigenschaften und agieren unterschiedlich mit der Materialoberflche des Objektes. Indirektes Licht flutet die gesamte Welt mit einer definierten Lichtstrke und Lichtfarbe. Dieses Licht ist berall sichtbar. Es ist gut vergleichbar mit indirektem Licht beim Fotografen. Auch dieses Licht erhellt den gesamten Raum, ohne ein Objekt im besonderen Mae zu erhellen. Oftmals wird indirektes Licht (Ambientlight) dazu eingesetzt, um eine gewisse Grundhelligkeit aufrechtzuerhalten. Ambientlight verursacht keine spiegelnden (specular) Reflektionen eines Objektes. Direktes Licht in einer Szene hat immer einen Ursprung. Zu seinen Eigenschaften gehrt Lichtstrke und Farbe. Zustzlich wird dem direktem Licht eine Orientierung der Lichtstrahlen zugeordnet. (Dies gilt auch fr ein Punktlicht (Pointlight). Die Richtung wird aber nicht explizit angegeben. Es strahlt in alle Richtungen wie z.B. die Sonne.) Die Richtung der Lichtquelle fliet in die Berechung fr Schatten ein. Wird das direkte Licht von Objekten reflektiert, so bleibt die allgemeine Lichtstrke in der Szene davon unberhrt. Welche Lichtart besser oder schlechter ist kann nicht beantwortet werden. Die beste Beleuchtung einer Szene werden Sie durch die Kombination aller Lichtmglichkeiten erhalten. Indirektes Licht als Grundlicht und direktes Licht um Highlights zu erzeugen. Scheuen Sie nicht die Kombination verschiedener Lichtquellen, um auch nur ein Objekt richtig zu erhellen. Die Lichtfarbe wird durch das D3DCOLORVALUE-Typen-Array erfasst. Die Anteile von Rot, Grn, Blau sowie einer Alpha-Komponente ergeben die endgltige Farbe. Die Alpha-Komponente ermglicht das Mischen der Farben mit dem Hintergrund.
Type D3DCOLORVALUE a As Single b As Single g As Single r As Single End Type

Jede beliebige Farbe knnen Sie mit einem Wertebereich von b (Blau), g (Grn) und r (Rot) zwischen 0.0 und 1.0 bestimmen. Werte grer 1.0 erzeugen ein extrem starkes Licht, welches dazu neigt die Szene zu berblenden. Werte kleiner

Kapitel 2 Direct3D

139

0.0 erzeugen ein Schwarzlicht. Dieses Schwarzlicht entfernt Licht aus einer Szene. Anzumerken ist, dass Licht die Alpha-Komponente ignoriert. Da das D3DCOLORVALUE Typen Array auch fr die Materialfarbe genutzt wird, ist der Alphawert enthalten. Mit der Direct3Ddevice7.SetRenderState()-Methode knnen Sie das Licht einoder ausschalten. Das Ein- oder Ausschalten der Lichtberechnungen bezieht sich auf die gesamte Lichtberechnung von Direct3D. Ausschalten:
Direct3Ddevice7.SetRenderState D3DRENDERSTATE_LIGHTING, 0

Einschalten:
Direct3Ddevice7.SetRenderState D3DRENDERSTATE_LIGHTING, 1

2.8.1

Indirektes Licht (Ambientlight)


Ambientlight knnen Sie mit der Direct3Ddevive7.SetRenderState()-Methode erstellen. Dieser Lichttyp ist unkompliziert, da wir zum Erzeugen lediglich zwei Parameter beachten mssen. Der erste Parameter heit state. Zur Auswahl steht eine Konstante aus der CONST_D3DRENDERSTATETYPEListe. Fr uns ist der Eintrag D3DRENDERSTATE_AMBIENT von Bedeutung. Der folgende Parameter renderstate ist von dem zuvor gewhlten state Parameter abhngig. Beziehen wir dies auf unser Status D3DRENDERSTATE_AMBIENT, so wird nun eine Farbe erwartet. Diese erzeugen wir mit der DirectX7.CreateColorRGBA()-Methode.
Direct3DDevice7.SetRenderState D3DRENDERSTATE_AMBIENT, _ DirectX7.CreateColorRGBA(1#, 1#, 1#, 1#)

Wenn Sie diese Befehlszeile Ihrem Programmcode hinzufgen, wird Ihre gesamte 3D-Welt mit einem einheitlichem weien Licht geflutet. Natrlich werden Sie die Auswirkungen erst dann merken, wenn Sie Ihren Objekten Materialeigenschaften zugewiesen haben.

2.8.2

Direktes Licht
Zur Verwendung von direktem Licht, stellt uns D3D drei unterschiedliche Lichtarten bereit: Punktlicht (Pointlight), Scheinwerferlicht (Spotlight), sowie eine richtungsorientierte Lichtquelle (Directional Light). Diesen Lichttypen mssen unterschiedliche Eigenschaften zugewiesen werden.

140

Licht

Lichteigenschaften Die Lichteigenschaften aller drei Lichttypen werden in einem zentralem TypenArray gesammelt. Das D3DLIGHT7-Typen-Array besitzt folgenden Aufbau:
Type D3DLIGHT7 ambient As D3DCOLORVALUE attenuation0 As Single attenuation1 As Single attenuation2 As Single diffuse As D3DCOLORVALUE direction As D3DVECTOR dltType As CONST_D3DLIGHTTYPE falloff As Single phi As Single position As D3DVECTOR range As Single specular As D3DCOLORVALUE theta As Single End Type

Die Lichtfarbe wird durch die Mitgliedsdaten ambient, diffuse und specular bestimmt. Sie werden durch das Direct3D-Beleuchtungsmodell miteinander verschmolzen. Zusammen mit dem Gegenstck des Objektmaterials (Materialeigenschaften beinhalten ebenfalls ambient, diffuse und specular Anteile) ergibt sich die endgltige Farbe. ber die Mitgliedsdaten position beschreiben Sie die Position der Lichtquelle. Dazu nutzen Sie das D3DVECTOR-Typen-Array. Das Koordinatentrio x, y und z stehen relativ zu den Weltkoordinaten. Anders als bei dem indirektem Licht knnen Sie bei dem direktem Licht eine Reichweite definieren. Die Variable range ist auf einen Maximalwert von 18.446+e18 begrenzt. Um das natrliche Licht mglichst optimal zu simulieren, mssen Objekte, welche von der Lichtquelle weiter entfernt liegen, dunkler dargestellt werden als Objekte, welche nher an der Lichtquelle liegen. Direct3D stellt drei Parameter bereit, um solch eine Abschwchung zu simulieren. Mit den Mitgliedsdaten attenuation0, attenuation1 und attenuation2 beschreiben Sie, wie sich die Lichtintensivitt ber die Lichtreichweite verhalten soll. Der normale Wertebereich liegt zwischen 0.0 und 1.0. Erlaubt sind aber auch Zuweisungen von kleiner 0 und grer 1. Fr eine gleichmige Lichtverteilung ber die gesamte Strecke knnen Sie folgende Einstellung whlen.
attenuation0 = 0.0 attenuation1 = 1.0 attenuation2 = 0.0

Kapitel 2 Direct3D

141

Sie drfen den normalen Wertebereich fr die Abschwchung von Licht verlassen. So knnen Sie mit Werten grer 1.0 eine Verstrkung der jeweiligen Abschwchung erreichen. Diese Abschwchung knnte manchmal etwas befremdend wirken. Mit Werten kleiner 0.0 erreichen Sie ein helleres Licht ber die gesamte Reichweite. Den Lichttypen Spotlight und Directional Light knnen Sie eine Richtung zuweisen. Der direction-Vektor beschreibt die Entfernung vom logischen Ursprung, unabhngig von der Lichtposition in der Szene. Dementsprechend leuchtet ein Spotlight mit dem Richtungsvektor 0,0,1 entlang der positiven Z-Achse. Eine richtungsorientierte Lightquelle mit dem Richtungsvektor 0,-1,0 wrde direkt von oben in die Szene leuchten. Natrlich knnen Sie auch einen Punkt im 3D-Raum fixieren. Einen Richtungsvektor mit den Daten 0,0,0 drfen Sie allerdings nicht verwenden. Wenn Sie einen Punkt im 3D-Raum fixieren mchten, reicht es nicht aus, die Koordinaten des Punktes anzugeben. Der direction-Vector ist lediglich ein Richtungszeiger. Um einen Punkt im 3D-Raum zu treffen, mssen die Richtungszeiger entsprechend umgerechnet werden. Die verbleibenden vier Parameter dltType, falloff, phi und theta werden bei den Zuweisungen der Eigenschaften (direkt im Anschluss) erlutert. Betrachten wir, welche Eintrge fr welchen Lichttyp bentigt werden. Pointlight
dltType As CONST_D3DLIGHTTYPE = D3DLIGHT_POINT

Bild 2.19: Pointlight

Ein Pointlight knnen Sie am besten mit einer kleinen Sonne vergleichen. Es strahlt gleichmig in alle Richtungen.

142

Licht

Eigenschaften
D3DLIGHT7. ambient D3DLIGHT7.diffuse D3DLIGHT7.specular D3DLIGHT7.position D3DLIGHT7.range D3DLIGHT7.attenuation0 D3DLIGHT7.attenuation1 D3DLIGHT7.attenuation2

Beispiel
Dim Light As D3DLIGHT7 Dim Farbe As D3DCOLORVALUE Dim Position As D3DVECTOR With Position .x = 5 .y = 5 .z = 5 End With With Farbe .r = 255 .g = 255 .b = 255 End With With Light .dltType = D3DLIGHT_POINT .Ambient = Farbe .diffuse = Farbe .specular = Farbe .Position = Position .range = 10 .attenuation0 = 0 .attenuation1 = 1 .attenuation2 = 0 End With

Mit der Methode Direct3Ddevice7.SetLight() setzen Sie die Lichtquelle in Ihre Szene. Nun muss Sie noch eingeschaltet werde. Hierbei hilft uns die Methode Direct3DDevice7.LightEnable(). Sie knnen jederzeit die Lichteigenschaften mit einem erneuten Aufruf der SetLight() Methode berschreiben. Die nderungen werden beim Rendern der Szene sofort wirksam. In diesem Beispiel verwenden wir die Variable Position As D3DVECTOR. Diesem Vektor weisen wir die Koordinatenwerte zu. Anschlieend wird dieser Vektor den Lichteigenschaften (.Position = Position) zugewiesen. Diese Vorgehensweise

Kapitel 2 Direct3D

143

ist nicht zwingend notwendig. Wir htten die Lichtposition auch wie folgt bestimmen knnen:
Light.Position.x = 5 Light.Position.y = 5 Light.Position.z = 5

Die gleiche Vorgehensweise finden Sie bei der Zuordnung der Lichtfarbe. Eine direkte Zuweisung and die Lichteigenschaften sieht so aus:
Light.Ambient.r = 255 Light.Ambient.g = 255 Light.Ambient.b = 255 Light.diffuse.r = 255 Light.diffuse.g = 255 Light.diffuse.b = 255 Light.specular.r = 255 Light.specular.g = 255 Light.specular.b = 255

Diese Einstellung erzielt ein hell leuchtendes weies Licht. Directional Light

L i c h t

Koordinatensystem
Bild 2.20: Directional Light

Directional (richtungsorientiertes) Licht besitzt als Eigenschaften Farbe und Richtung. Diese Lichtquelle erzeugt ein paralleles Licht, welches in einer einheitlichen Richtung durch die gesamte Szene wandert. Richtungsorientiertes Licht wird weder von Reichweiten noch von Abschwchungsfaktoren beeinflusst.

144

Licht

Eigenschaften
D3DLIGHT7. ambient D3DLIGHT7.diffuse D3DLIGHT7.specular D3DLIGHT7.direction

Beispiel
Dim Light As D3DLIGHT7 Dim Farbe As D3DCOLORVALUE Dim Richtung As D3DVECTOR With Richtung .x = 5 .y = 5 .z = 5 End With With Farbe .r = 255 .g = 255 .b = 255 End With With Light .dltType = D3DLIGHT_POINT .Ambient = Farbe .diffuse = Farbe .specular = Farbe .direction = Richtung End With

Spotlight Spotlight ist exakt mit einer Taschenlampe vergleichbar. Spotlight ist das am aufwendigsten zu programmierende Licht. Es nutzt alle Mitgliedsdaten des D3DLIGHT7 Typen Arrays. Der helle innere Lichtkegel wird mit dem ThetaWert festgelegt. Entsprechend wird der uere Lichtkegel mit dem Phi-Wert bestimmt. Das falloff-Mitglied aus dem D3DLIGHT7-Typen-Array definiert, wie sich das Licht zwischen Zentrum und uerem Rand abschwchen soll. Der Phi-Wert ist eine Winkelangabe (radiant). Er liegt zwischen 0.0 und 3.14159. Der Theta-Wert ist ebenfalls eine Winkelangabe und liegt zischen 0.0 und <Phi. Der falloff-Wert beschreibt den Helligkeitsverlauf zischen innerem und uerem Lichtkegel. Der zulssige Wert liegt zwischen 0.0 und 1.0. Setzen Sie diesen Wert auf 1.0. Mit diesem Wert wird ein gleichmiger Helligkeitsverlauf hergestellt.

Kapitel 2 Direct3D

145

Phi Theta innerer Lichtkegel

uerer Lichtkegel
Bild 2.21: Spotlight

Eigenschaften
D3DLIGHT7.ambient D3DLIGHT7.diffuse D3DLIGHT7.specular D3DLIGHT7.position D3DLIGHT7.direction D3DLIGHT7.range D3DLIGHT7.attenuation0 D3DLIGHT7.attenuation1 D3DLIGHT7.attenuation2 D3DLIGHT7.phi D3DLIGHT7.theta D3DLIGHT7.falloff

Beispiel
Dim Light As D3DLIGHT7 Dim Farbe As D3DCOLORVALUE Dim Position As D3DVECTOR Dim Richtung As D3DVECTOR With Position .x = 5 .y = 5 .z = 5 End With With Richtung .x = 5 .y = -1 .z = 5 End With

146

Licht

With Farbe .r = 255 .g = 255 .b = 255 End With With Light .dltType = D3DLIGHT_SPOT .Ambient = Farbe .diffuse = Farbe .specular = Farbe .Position = Position .Direction = Richtung .range = 10 .attenuation0 = 0 .attenuation1 = 1 .attenuation2 = 0 .phi = 180 / 57.296 .theta = 20 / 57.296 .falloff =1.0 End With

2.8.3

Licht, Schatten und Polygone


DirectX unterscheidet zwei Schattenmodelle. Je nachdem welches Schattenmodel Sie verwenden, beeinflussen Sie das Erscheinungsbild der gerenderten Szene. Flat Shading und Gouraud Shading unterscheiden sich sehr stark von einander. ber das Schattenmodel beeinflussen Sie die Farbe und Beleuchtung jedes einzelnen Pixels eines Polygons. Flat Shading liegt ein einfaches, nicht lineares Berechnungssystem zu Grunde. Das Gouraud Shading Verfahren ist eine sehr viel feinere Technik. Diese Technik ermglicht uns fr jedes Pixel, (in Abhngigkeit von Material, Licht und Normalvektor) eine individuelle Farbe zu berechnen. Diese Berechnung wird glcklicherweise von D3D bernommen. Dieses individuelle Pixeldesign bezeichnet man als Schatten. Verwechseln Sie diesen Schatten bitte nicht mit einem Schatten, der durch ein Objekt verursacht wird, z.B. ein Baum, der seinen Schatten auf eine Wiese wirft. Dies ist ein gnzlich anderes Verfahren und muss explizit berechnet werden. Flat Shading Mit dem Flat Shading Mode berechnet Direct3D das gesamte Polygon mit der Materialfarbe der ersten Vertexstruktur. Betrachtet man das gesamte Objekt, so ist das Ergebnis eine Aufteilung in Kltzchen. Zwischen den vielen Polygonen eines Objektes bilden sich scharfe, deutlich sichtbare Kanten. In einigen Fllen wird diese Methode bewusst eingesetzt, allerdings liegt der wahre Vorteil bei der Performancesteigerung. Bei modernen Anwendungen ist diese Technik quasi nicht mehr zu finden. Das begrndet sich mit der gestiegenen Leistungsfhigkeit eines modernen PC. Alle modernen Grafikkarten beherrschen neben

Kapitel 2 Direct3D

147

dem Flat Shading auch die verbesserte Gouraud Shading Technik. Oftmals sogar ohne bzw. mit kaum merklichem Performanceverlust. So knnen Sie den Renderstatus von D3D auf Flat Shading stellen:
Dim ShadeMode As CONST_D3DSHADEMODE ShadeMode = D3DSHADE_FLAT Direct3Ddevice7.SetRenderState D3DRENDERSTATE_SHADEMODE, _ ShadeMode

Sicherlich werden Sie feststellen, dass Ihnen bei der Auswahl der Variablen ShadeMode As CONST_D3DSHADEMODE eine dritte Variante angeboten wird. D3DSHADE_PHONG steht uns zurzeit nicht zur Verfgung. Der Phong-Algorithmus wrde eine weitere Verbesserung darstellen. Allerdings wrden wir auch einen Performanceverlust hinnehmen mssen. Warten wir einfach auf die nchste DirectX-Version. Der Aufruf dieser Technik wird wahrscheinlich analog zu den bereits bekannten Algorithmen implementiert. Gouraud Shading Gouraud Shading ist die zur Zeit einzige Alternative zu der bekannten FlatShading-Technik. Verglichen mit der Alternative, bentigt diese Technik mehr Rechenzeit. Der Verlust an Performance ist aber mehr als gerechtfertigt. Die Voreinstellung von Direct3D ist Gouraud Shading. Anders als bei der Flat Shading-Methode wird nicht nur die erste Vertexstruktur als Berechnungsgrundlage genommen. D3D berechnet jede Vertexstruktur einzeln und interpoliert alle anderen Pixel des Polygons. Die Interpolation wird linear berechnet. Als Beispiel: Der Rotanteil von Vertex eins ist 0.8. Der Rotanteil von Vertex zwei ist 0.4. Der Mittelpunkt zwischen den beiden Vertexstrukturen betrgt 0.6. Diese lineare Berechnung wird fr alle Pixel zwischen Vertex eins und Vertex zwei durchgefhrt. Das Ergebnis ist ein feiner Farbverlauf. Die unangenehme Kltzchenbildung der Flat-Shading-Methode entfllt. So knnen Sie den Renderstatus von D3D auf Flat Shading stellen:
Dim ShadeMode As CONST_D3DSHADEMODE ShadeMode = D3DSHADE_GOURAUD Direct3Ddevice7.setRenderState D3DRENDERSTATE_SHADEMODE, _ ShadeMode

Wie schon im Vorfeld erklrt wurde, sorgt die Gouraud Shading Methode fr einen feinen Farbverlauf eines Polygons. Dies kann aber auch zu Problemen fhren. Die Probleme werden immer dann deutlich, wenn eine Lichtquelle so klein ist, das Sie die Ecken des Polygons nicht erreicht. In der Abbildung knnen Sie erkennen, dass die Lichtquelle (in unserem Fall ein Spotlight) die Ecke der Polygone nicht erreicht. Somit liegt keine Vertexstruktur innerhalb des Lichtes. Gouraud Shading steht nun vor dem Problem, dass dieser Methode die Berechnungsgrundlage fehlt. Das Ergebnis ist, dass wir berhaupt kein Licht sehen werden. D3D tut so, als wrde es nicht existieren.

148

Licht

Polygon 2

Spot Light Polygon 1


Bild 2.22: Der Lichtpunkt trifft keine Ecke eines Polygons

Die Lsung dieses Problems besteht darin, dass Sie sehr viel detaillierter arbeiten mssen. Kleinere Polygone, Erhhen der Bildschirmauflsung oder Steigern der Farbtiefe knnen Abhilfe schaffen. Insbesondere durch den Einsatz kleinerer Polygone knnen Sie sehr viel realistischere Szenen erzeugen. Viele Polygone bedeuten aber auch, dass die Performance strker belastet wird. Wie bei allen Dingen des Lebens sollten Sie ein ausgewogenes Verhltnis schaffen. In manchen Bereichen der Szene, in denen Sie eine sehr feine Verteilung des Lichts bentigen, vergrern Sie die Anzahl der Polygone. In anderen Bereichen knnen Sie etwas grber arbeiten.

2.8.4

Licht aktivieren / deaktivieren


Die Lichteigenschaften werden in dem D3DLIGHT7 Typen Array (siehe Abschnitt Direktes Licht) erfasst. Diese Informationen mssen Sie jetzt an das Renderdevice weiterleiten. Genau diese Aufgabe wird von der Direct3D Device7.SetLight()-Methode bernommen. Anschlieend muss die zugewiesene Lichtquelle eingeschaltet werden. Fr das Ein- und Ausschalten einer Lichtquelle ist die Direct3DDevice7.LightEnable()-Methode verantwortlich. Sollten Sie LightEnable() aufrufen, ohne zuvor die Lichteigenschaften bestimmt zu haben, dann wird von D3D eine Lichtquelle mit den folgenden Standartwerten erstellt:
Mitgliedsdaten des D3DLIGHT7-TypenArrays dltType Diffuse Specular Ambient Standardwert D3DLIGHT_DIRECTIONAL (R:1, G:1, B:1, A:0) (R:0, G:0, B:0, A:0) (R:0, G:0, B:0, A:0)

Kapitel 2 Direct3D

149

Mitgliedsdaten des D3DLIGHT7-TypenArrays Position Direction Range Falloff Attenuation0 Attenuation1 Attenuation2 Theta Phi

Standardwert (0, 0, 0) (0, 0, 1) 0 0 0 0 0 0 0

Die folgenden Methoden helfen Ihnen, die Lichtquellen sicher in den Griff zu bekommen. Sie geben Ihnen die Mglichkeit, die Parameter einer Lichtquelle zu ndern oder deren Parameter auszulesen. Es ist wichtig, dass die zugewiesenen Parameter innerhalb des erlaubten Wertebereichs liegen und zu der gewhlten Lichtquelle passen. Ansonsten wird die Lichtquelle nicht aktiviert und ein Fehler ist die Folge.
SetLight() Setzt die Lichteigenschaften fr eine Lichtquelle. object.SetLight(LightIndex As Long, Light As D3DLIGHT7) object LightIndex Light ein gltiges Direct3DDevice7-Objekt Ein Index fr eine Lichtquelle. Jede Lichtquelle wird durch diesen Index identifiziert. Ist eine Lichtquelle mit dem gleichen Index bereits vorhanden, so werden die Lichteigenschaften berschrieben. Variable vom Typ D3DLIGHT7, welche die notwendigen Parameter der Lichtquelle enthlt.

LightEnable() Aktiviert oder deaktiviert eine Lichtquelle. object.LightEnable(LightIndex As Long, bEnable As Boolean) object LightIndex bEnable ein gltiges Direct3DDevice7-Objekt Ein Index fr eine Lichtquelle. Jede Lichtquelle wird durch diesen Index identifiziert. Ist eine Lichtquelle mit dem gleichen Index bereits vorhanden, so werden die Lichteigenschaften berschrieben. True aktiviert die Lichtquelle False deaktiviert die Lichtquelle

150

Licht

GetLight() Liest die Lichteigenschaften einer Lichtquelle und bergibt sie an das Light-As D3DLIGHT7-Typen-Array. object.GetLight(LightIndex As Long, Light As D3DLIGHT7) object LightIndex Light ein gltiges Direct3DDevice7-Objekt Ein Index fr eine Lichtquelle. Jede Lichtquelle wird durch diesen Index identifiziert. Variable vom Typ D3DLIGHT7, welche die notwendigen Parameter der Lichtquelle aufnimmt.

GetLightEnable() Empfngt den aktiven Status einer Lichtquelle. Das Ergebnis wird als Boolean-Wert zurckgeliefert. (True = aktiv; False = inaktiv) object.GetLightEnable(LightIndex As Long) As Boolean object LightIndex ein gltiges Direct3DDevice7-Objekt Ein Index fr eine Lichtquelle. Jede Lichtquelle wird durch diesen Index identifiziert.

Um eine Lichtquelle zu aktivieren, mssen Sie zwei Schritte durchfhren. Schritt 1: Schritt 2: Zuweisen der Lichteigenschaften Einschalten der Lichtquelle

Schritt 1: Zuweisen der Lichteigenschaften


Dim Light As D3DLIGHT7 With Light .dltType = D3DLIGHT_POINT .Ambient.r = 1 .Ambient.g = 1 .Ambient.b =1 .Position.x = 5 .Position.y = 5 .Position.z = 5 .range = 10 .attenuation1 = 1 End With Call Direct3DDevice7.SetLight (1, Light) Call Direct3DDevice7.LightEnable(1, True)

Kapitel 2 Direct3D

151

Die Lichtquelle mit dem Index eins knnen Sie deaktivieren, indem Sie die LightEnable()-Methode aufrufen und dem Parameter bEnable den Wert False zuweisen. Zu der Laufzeit des Programms ist es hilfreich, wenn Sie die Parameter und den Status Ihrer Lichtquellen abfragen knnen. Natrlich bietet uns D3D auch fr diese Aufgaben entsprechende Methoden an. Ob eine Lichtquelle ein- oder ausgeschaltet ist, knnen Sie mit der Direct3DDevice7.GetLightEnable()-Methode abfragen. Der Aufruf ist unkompliziert und liefert den aktuellen Status.
Dim Msg As Boolean Msg = Direct3DDevice7.GetLightEnable(1)

Ist Msg = True, so ist die Lichtquelle mit dem Index 1 eingeschaltet. Ist der Rckgabewert = False, so ist die Lichtquelle ausgeschaltet. In unserem Beispiel erhalten Sie den Wert True. Die Lichteigenschaften knnen Sie mit der Direct3DDevice7.GetLight()Methode in Erfahrung bringen. Die gesammelten Informationen werden in dem Parameter Light As D3DLIGHT7 gespeichert. Die Mitgliedsdaten dieses Typen Arrays knnen Sie nach belieben abfragen.
Dim TempLight AS D3DLIGHT7 Dim Range As Single Call Direct3DDevice7.GetLight (1, TempLight) Range = TempLight.range

In unserm Beispiel wrde die Variable Range den Wert 10 enthalten.

2.8.5

Beispiel (Licht)
Unser Lichtbeispiel zeigt Ihnen alle verfgbaren Lichtquellen. Im Quelltext finden Sie Abschnitte speziell fr Pointlight, Spotlight, Directional Light und Ambient Licht. Zustzlich drehen wir den Betrachter bei Pointlight und Ambientlight. Damit wir die Lichteinflsse gut beobachten knnen, haben wir die Wnde mit jeweils 50 Dreiecken erstellt. Wir wollten weder Ihnen noch uns zumuten, die Vektoren der Dreiecke per Hand anzugeben. Dies wren immerhin ca. 300 Programmzeilen. Deshalb nutzen wir die CreateWall()-Subroutine. Sie erstellt die bentigten Wnde automatisch. Wir werden Texturen verwenden, ohne den Aufbau einer Texturesurface zu erklren. Wir bentigen die Texturen, um die Auswirkungen der Lichtquellen besser beobachten zu knnen. Hoffentlich sind Sie uns nicht bse, dass wir die Texturen ohne Erluterungen verwenden. Dies werden wir im Textureabschnitt des Buches ausgiebig nachholen. Bei den Dimensionierungen der Variablen gibt es keine Neuerungen ber die wir berichten mssten. Hier finden wir nur alte Bekannte, die momentan keine Herausforderungen darstellen.

152

Licht

Bild 2.23: Bildschirmfoto Light

Das Programm startet mit der Form_Load()-Routine. Direkt am Anfang finden wir die Subroutinen InitDDraw() und InitD3D(). Diese Routinen sind uns ebenfalls bekannt und werden nicht erklrt.
Private Sub Form_Load() InitDDraw InitD3D LichtText(0) = "Point-Light" LichtText(1) = "Spot-Light" LichtText(2) = "Directional-Light" LichtText(3) = "Ambient-Light"

Diesen Text knnen Sie oben links am Bildschirm lesen. Er dient zur Information.
Dim Anzahl(6) As Long Dim First(6) As Long First(0) = 0 Anzahl(0) = CreateWall(Vector(-5, 5, 5), _ Vector(5, -5, 5), 5, 5, First(0), 0, Vector(0, 1, -1)) First(1) = First(0) + Anzahl(0) Anzahl(1) = CreateWall(Vector(-5, 5, -5), _ Vector(5, -5, -5), 5, 5, First(1), 0, Vector(0, 1, 1)) First(2) = First(1) + Anzahl(1)

Kapitel 2 Direct3D

153

Anzahl(2) = CreateWall(Vector(-5, 5, -5), _ Vector(-5, -5, 5), 5, 5, First(2), 0, Vector(1, 1, 0)) First(3) = First(2) + Anzahl(2) Anzahl(3) = CreateWall(Vector(5, 5, -5), _ Vector(5, -5, 5), 5, 5, First(3), 0, Vector(-1, 1, 0)) First(4) = First(3) + Anzahl(3) Anzahl(4) = CreateWall(Vector(-5, 5, 5), _ Vector(5, 5, -5), 5, 5, First(4), 1, Vector(0, 1, 0)) First(5) = First(4) + Anzahl(4) Anzahl(5) = CreateWall(Vector(-5, -5, 5), _ Vector(5, -5, -5), 5, 5, First(5), 1, Vector(0, 1, 0))

Wir rufen die Funktion CreateWall() insgesamt sechsmal auf. Fr jede Wand einen Aufruf. In dem Array Anzahl As Array erhalten wir die Anzahl der verwendeten Vertexe. Die Elemente des Array First speichern einen Index, der den Anfang einer Wand reprsentiert. Dieser wird spter beim Rendern bentigt.
CreateTextur App.Path & "\Mauer.bmp"

Die CreateTexture() Subroutine ist eine kleine Eigenentwicklung. In ihr erstellen wir die bentigte Texturesurface und laden gleichzeitig die Texture von der Festplatte. Zu diesem Zeitpunkt stehen wir vor dem Problem, dass wir Texturen benutzen, ohne sie vorher erlutert zu haben. Dies ist ein kleiner Teufelskreis. Ohne Licht sind Texturen nicht sichtbar. Ohne Texturen knnen die Lichtvariationen nicht richtig beobachtet werden. Nun knnen wir Sie nur bitten, die Texturen als gegeben anzusehen. Genauere Erklrungen zu Texturen erfolgen spter im Textureabschnitt des Buches. Deshalb werden wir die Texturen zu diesem Zeitpunkt nicht erklren und vertrsten Sie auf spter.
Dim mat As D3DMATERIAL7 mat.diffuse.r = 1 mat.diffuse.g = 1 mat.diffuse.b = 0 mat.diffuse.a = 1 mat.Ambient.r = 1 mat.Ambient.g = 1 mat.Ambient.b = 0 mat.Ambient.a = 1 g_d3dDevice.SetMaterial mat

Wir benutzen ein Material, welches in der Lage ist, diffuses sowie ambientes Licht zu reflektieren. Die Reflexion der Blauanteile klammern wir aus.
Do g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ RGB(255, 0, 0), 0, 0 g_d3dDevice.BeginScene r = r + 1: If r > 360 Then r = 0

154

Licht

g_dx.IdentityMatrix matView Call g_dx.ViewMatrix(matView, Vector(5 * Sin(r / 5 * Cos(r / 57.296)), Vector(0, 0, 0), Vector(0, If AktTyp = LT_POINT Or AktTyp = LT_AMBIENT Then g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW,

57.296) , 0, _ 1, 0), 0) _ _ matView

Bei den Lichttypen Pointlight und Ambientlight soll sich der Betrachter im Kreis drehen.
If If If If AktTyp AktTyp AktTyp AktTyp = = = = LT_POINT Then PointLicht LT_SPOT Then SpotLicht r LT_DIRECT Then DirectLicht r LT_AMBIENT Then AmbientLicht

Bei den Lichttypen Spotlight und Directionallight soll sich die Lichtquelle drehen. Dafr bergeben wir den Routinen den Paramater r. Dieser enthlt den aktuellen Winkel fr die Rotation. Hier verzeigen wir in die entsprechende Subroutine, um das richtige Licht zu initialisieren.
g_d3dDevice.SetTexture 0, TextureSurf g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, Vertex(First(0)), Anzahl(0), D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, Vertex(First(1)), Anzahl(1), D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, Vertex(First(2)), Anzahl(2), D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, Vertex(First(3)), Anzahl(3), D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, Vertex(First(4)), Anzahl(4), D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, Vertex(First(5)), Anzahl(5), D3DDP_WAIT g_d3dDevice.EndScene D3DFVF_VERTEX, _ D3DFVF_VERTEX, _ D3DFVF_VERTEX, _ D3DFVF_VERTEX, _ D3DFVF_VERTEX, _ D3DFVF_VERTEX, _

Mit der DrawPrimitive()-Methode werden die sechs Wnde gerendert.


g_ddsBackBuffer.SetForeColor (RGB(255, 255, 255)) g_ddsBackBuffer.DrawText 10, 10, LichtText(AktTyp), False g_ddsBackBuffer.DrawText 10, 450, "PRESS SPACEBAR FOR NEXT _ LIGHT-TYP OR <ESC> TO EXIT DEMO", False g_ddsBackBuffer.DrawText 10, 420, "PRESS <S> FOR SOLID", False g_ddsBackBuffer.DrawText 10, 390, "PRESS <W> FOR WIREFRAME", _ False

Hier werden ein paar Informationen fr den Anwender auf den Bildschirm geschrieben.
g_ddsPrimary.Flip Nothing, DDFLIP_WAIT

Kapitel 2 Direct3D

155

Die gerenderte Szene wird auf die primre Surface geflippt und die Szene ist auf dem Monitor sichtbar.
DoEvents

Die DoEvents-Anweisung ist sehr wichtig, da wir auf Tastatureingaben reagieren wollen.
Loop Until GetAsyncKeyState(vbKeyEscape) <> 0 g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL g_dd.RestoreDisplayMode Set g_dd = Nothing Set g_d3dDevice = Nothing Set g_dx = Nothing End End Sub

Nun brauchen wir uns nur noch die vier Subroutinen fr die Lichtinitialisierung anzuschauen. Beginnen wir mit dem Pointlight. Pointlight:
Private Sub PointLicht() g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, RGB(0, 0, 0)

Da wir nur das Pointlight beobachten wollen, schalten wir ein mglicherweise aktives, indirektes Licht aus. Einfach die Lichtfarbe auf Schwarz setzen.
Dim LC As D3DCOLORVALUE LC.r = 20 LC.g = 20 LC.b = 20 Dim LightPos As D3DVECTOR LightPos = Vector(5, 6, 5) Dim Licht As D3DLIGHT7 Licht.diffuse = LC Licht.attenuation1 = 5 Licht.dltType = D3DLIGHT_POINT Licht.position = LightPos Licht.range = 20

Fr Pointlight bentigen wir die Definitionen fr Position, Reichweite und Lichtfarbe. Diese werden hier zugewiesen.
g_d3dDevice.SetLight 0, Licht g_d3dDevice.LightEnable 0, True

Abschlieend brauchen wir die Lichtquelle nur noch zuweisen und einschalten.
End Sub

156

Licht

Directional Light:
Private Sub DirectLicht(ByVal Ang As Single) g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, RGB(0, 0, 0) Dim LC As D3DCOLORVALUE LC.r = 20 LC.g = 20 LC.b = 20 Dim LightPos As D3DVECTOR Dim LightDir As D3DVECTOR LightPos = Vector(0, 0, 0) LightDir = Vector(10 * Sin((360 Ang) / 57.296), 0, _ 10 * Cos((360 Ang) / 57.296))

Wir mchten, dass sich die Richtung des direktionalen Lichts dreht. Dies erreichen wir, indem wir den Richtungsvektor verndern. Der aktuelle Winkel wird der Subroutine bergeben und findet sich im Parameter Ang.
Dim Licht As D3DLIGHT7 Licht.diffuse = LC Licht.attenuation1 = 2 Licht.dltType = D3DLIGHT_DIRECTIONAL Licht.direction = LightDir Licht.range = 10 g_d3dDevice.SetLight 0, Licht g_d3dDevice.LightEnable 0, True End Sub

Spotlight:
Private Sub SpotLicht(ByVal Ang As Single) g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, RGB(0, 0, 0) Dim LC As D3DCOLORVALUE LC.r = 20 LC.g = 20 LC.b = 20 Dim LightPos As D3DVECTOR Dim LightDir As D3DVECTOR LightPos = Vector(0, 0, 0) LightDir = Vector(10 * Sin((360 Ang) / 57.296), 0,_ 10 * Cos((360 Ang) / 57.296))

Auch das Spotlight soll sich drehen. Ebenfalls wird der Winkel an den Parameter Ang bergeben.
Dim Licht As D3DLIGHT7 Licht.diffuse = LC Licht.attenuation1 = 2 Licht.dltType = D3DLIGHT_SPOT

Kapitel 2 Direct3D

157

Licht.position = LightPos Licht.direction = LightDir Licht.range = 10 Licht.phi = 160 / 57.296 Licht.theta = 2 / 57.296 Licht.falloff = 1 g_d3dDevice.SetLight 0, Licht g_d3dDevice.LightEnable 0, True End Sub

Ambient Light:
Private Sub AmbientLicht() g_d3dDevice.LightEnable 0, False g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, _ RGB(255, 255, 255) End Sub

Beim indirekten Licht sind quasi keine Parameter zu bercksichtigen. Lediglich die Lichtfarbe muss angegeben werden.

2.9

Material
Material beschreibt, wie ein Polygon das einfallende Licht reflektieren oder absorbieren soll. Die Materialeigenschaften werden in dem D3DMATERIAL7Typen-Array erfasst.
Type D3DMATERIAL7 ambient As D3DCOLORVALUE diffuse As D3DCOLORVALUE emissive As D3DCOLORVALUE power As Single specular As D3DCOLORVALUE End Type

Dieses Array beinhaltet die gesamte Materialbeschreibung. Im Detail werden die Parameter ambient, diffuse (beide fr das Reflexionsverhalten verantwortlich), emmisiv (beschreibt die Eigenleuchtkraft) und specular sowie power (regeln Glanzlichter) gesetzt. Die einzelnen Parameter werden im Folgenden beschrieben. diffuse und ambient Das Material wird mit einer Lichtquelle beleuchtet. Die Lichtquelle enthlt unter anderem die Eigenschaften fr diffuse und ambient. Die Eigenschaften diffuse und ambient beschreiben, wie viel von dem Licht reflektiert werden soll. Dabei teilt D3D die Farbe in Ihre Einzelkomponenten (Rot-, Grn- und Blauanteil). Der Alphawert der Materialbeschreibung bestimmt wie sich die Komponenten mischen sollen (blending factor).

158

Material

Wie viel von dem eintreffenden Licht reflektiert wird, steht in einem engen Zusammenhang mit dem Normalvektor eines Polygons. Die Summe des reflektierenden Lichtes ist der Kosinus (Winkel) zwischen einfallendem Licht und dem Normalvektor.

Normalvektor Licht

Summe des reflektierenden Lichts = cos


Bild 2.24: Lichtreflexion

Trifft das Licht annhernd parallel zum Normalvektor auf das Polygon, so verzeichnen wir die strkste Reflexion. Die entgegengesetzte Wirkung tritt ein, wenn das Licht annhernd parallel zum Polygon verluft. diffuse und ambient arbeiten eng zusammen, um das Erscheinungsbild der Materialfarbe zu bestimmen. Gewhnlich nutzen beide Parameter die gleichen Werte. Wollen Sie z.B. eine rot glhende Oberflche erzeugen, so whlen Sie ein Material mit den Werten:
ambient.r ambient.g ambient.b diffuse.r diffuse.g diffuse.b = = = = = = 1 0 0 1 0 0

Wird diese Oberflche mit einer weien Lichtquelle beleuchtet, so werden nur die Rotanteile der Lichtquelle reflektiert. Das Material wirkt rot glhend.

Kapitel 2 Direct3D

159

Einstellungen fr ein weies Licht:


ambient.r ambient.g ambient.b diffuse.r diffuse.g diffuse.b = = = = = = 1 1 1 1 1 1

Sollten Sie die Oberflche (mit den ersten Werten fr ambient & diffuse) mit einem blauem Licht beleuchten, so bleibt die Oberflche schwarz. Mit den Materialeinstellungen werden nur die Rotanteile des Lichtes reflektiert. Da bei einem blauen Licht keine Rotanteile vorhanden sind, wir auch nichts reflektiert. Emission ber den emissive-Parameter des D3DMATERIAL-Typen-Arrays knnen Sie ein Material dazu anregen, von sich aus zu leuchten. Dieser Parameter beeinflusst die Materialfarbe. Ein mglicher Einsatz ist es, ein dunkles Objekt heller wirken zu lassen. Sie knnen den Eindruck erwecken, als wrde ein Objekt beleuchtet, ohne zustzliche Lichtquellen setzen zu mssen. Ein Objekt, welches den emissive-Parameter nutzt, erscheint so als wrde es Licht ausstrahlen. Dies ist aber nicht der Fall. Somit wird dieses scheinbare Licht auch nicht von anderen Oberflchen (Objekten) reflektiert. Specular Reflexion (Glanzpunkte auf einer Oberflche) Mit dem specular-Parameter des D2DMATERIAL-Typen-Arrays erzeugen Sie Glanzpunkte auf der Materialoberflche. Beeinflusst wird der Glanzeffekt durch den Parameter power. Die am weitesten verbreitete Einstellung fr die Glanzfarbe ist wei.
specular.r = 1 specular.g = 1 specular.b = 1

Wie stark der Glanzeffekt ausfallen soll, wird mit dem power Parameter bestimmt. Ein Wert von 0 bedeutet keinen Glanz. Ein angemessener Wert von etwa 10 erzeugt einen deutlichen Glanzeffekt.

2.9.1

Setzen von Material


Bevor Sie ein Polygon zeichnen, sollten Sie die Materialeigenschaften definiert haben. Einem Polygon knnen Sie mit der SetMaterial()-Methode ein Material zuweisen. Genauer gesagt wird es nicht dem Polygon direkt zugewiesen, sondern Sie informieren Direct3D, dass alle Polygone die ab der Zuweisung gerendert werden die Materialeigenschaften erhalten. Whrend eine Szene gerendert wird, knnen Sie die Materialeigenschaften beliebig oft ndern. Mit der GetMaterial()Methode knnen Sie die zurzeit aktuellen Materialparameter auslesen.

160

Material

SetMaterial() Setzt die Materialeigenschaften fr ein Polygon. object.SetMaterial(mat As D3DMATERIAL7) object mat ein gltiges Direct3DDevice7-Objekt Eine Variable vom Typ D3DMATERIAL7. Sie enthlt die Beschreibungen fr die Materialeigenschaften.

GetMaterial() Liest die aktuellen Materialeigenschaften, welche D3D nutzen wrde, um das nchste Polygon zu erstellen. object.GetMaterial(Material As D3DMATERIAL7) object Material ein gltiges Direct3DDevice7-Objekt Eine Variable vom Typ D3DMATERIAL7. Sie empfngt die Beschreibungen der aktuellen Materialeigenschaften.

Zeichnen Sie ein Polygon, ohne ein Material gesetzt zu haben, so verwendet D3D die Materialgrundeinstellungen. Diese sehen wie folgt aus:
Dim Material As D3DMATERIAL7 Material.diffuse.r = 0.5 Material.diffuse.g = 0 Material.diffuse.b = 0.5 Material.diffuse.a = 1 Material.ambient.r = 0.5 Material.ambient.g = 0 Material.ambient.b = 0.5 Material.ambient.a = 1 Material.specular.r = 1 Material.specular.g = 1 Material.specular.b = 1 Material.specular.a = 1 Material.power = 50 Call Direct3DDevice7.SetMaterial (Material)

Die aktuellen Materialeigenschaften knnen Sie wie folgt auslesen:


Dim Material As D3DMATERIAL7 Call Direct3DDevice7.GetMaterial (Material) Ambient_Rot = Material.ambien.r Ambient_Grn = Material.ambien.g Ambient_Blau = Material.ambien.b Ambient_Alpha = Material.ambien.a Diffuse_Rot = Material.diffuse.r Diffuse_Grn = Material.diffuseg.g

Kapitel 2 Direct3D

161

. . . Power = Material.power

2.9.2

Beispiel (Material)
Unser Materialdemo wir Ihnen die Zusammenhnge zwischen Material und Licht veranschaulichen. Es ist nicht mglich, Material darzustellen ohne eine Lichtquelle zu platzieren. (Mit Ausnahme des Emissivanteils des Material. Dieser leuchtet aus eigener Kraft und bentigt kein Licht.) Wir haben vier Wnde erzeugt und um den Mittelpunkt der 3D-Welt platziert. Der Betrachter umkreist den Mittelpunkt. Zur Beleuchtung verwenden wir ein Spotlight welches sich immer an den Koordinaten des Betrachters befindet. Ausgerichtet ist das Spotlight auf die Mitte. Hierzu ist es notwendig, bei jeder Positionsvernderung der Lichtquelle die Lichtrichtung neu zu berechnen.

Bild 2.25: Bildschirmfoto Material

162

Material

Auf der linken Bildschirmseite finden Sie alle Parameter fr die Materialeinstellungen. Die rechte Seite ist fr die Lichteinstellungen reserviert. Mit den Pfeiltasten rauf und runter knnen Sie die einzelnen Parameter erreichen, mit den Pfeiltasten rechts und links verndern Sie die Einstellungen. Obwohl wir den Einsatz von Texturen noch nicht besprochen haben, werden wir diese zum Einsatz bringen. Wir tun dies, da sich ein Objekt mit Textur anders verhlt als ein Objekt ohne Textur. Wir beginnen mit der Form_Load()-Subroutine.
Private Sub Form_Load() InitDDraw InitD3D DefaultWerte

In der DefaultWerte()-Subroutine setzen wir einen Standardparameter fr Material und Licht. Dies ist auch deshalb wichtig, damit wir beim Initialisieren von Licht und Material keine ungltigen Werte bergeben. Dies wrde natrlich eine Fehlermeldung zur Folge haben.
LichtIndex = True TextureKachelX = 1 TextureKachelY = 1 CreateWall

Die CreateWall()-Subroutine enthlt alle Vertexe fr die eingesetzten Polygone. . . .


r = r + 1: If r > 360 Then r = 0 g_dx.IdentityMatrix matView Call g_dx.ViewMatrix(matView, Vector(10 * Cos(r / 57.296), 0, _ 10 * Sin(r / 57.296)), Vector(0, 0, 0), Vector(0, 1, 0), 0) g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView

Mit dieser kleinen Berechnung lassen wir den Betrachter um den Mittelpunkt rotieren. Die Variable r definiert den aktuellen Winkel.
SpotLicht r

Da wir das Spotlight mit dem Betrachter rotieren lassen wollen, rufen wir die Subroutine SpotLicht() auf. Diese betrachten wir uns gleich noch etwas genauer, denn dort wird nicht nur die Position der Lichtquelle festgelegt, sonder auch die Lichtrichtung.

Kapitel 2 Direct3D

163

. . .
End Sub

Nun werfen wir einen Blick in die SpotLicht()-Subroutine.


Private Sub SpotLicht(ByVal Ang As Single) On Error Resume Next Dim LightPos As D3DVECTOR Dim LightDir As D3DVECTOR x = 1 * Cos((360 Ang) / 57.296) 1 z = 1 * Sin((360 Ang) / 57.296) + 1 LightPos = Vector(15 * Cos((Ang) / 57.296), 0, _ 15 * Sin((Ang) / 57.296))

Fr die Berechnung der Lichtposition verwenden wir den Algorithmus zur Positionsbestimmung des Betrachters.
LightDir = Vector(1 * Cos((Ang + 180) / 57.296), 0, 1 * _ Sin((Ang + 180) / 57.296))

Die Lichtrichtung soll immer auf die Mitte der 3D-Welt gerichtet sein. Dazu whlen wir den um 180 Grad versetzten Winkel von unserer Positionsberechnung. Dies ist mglich, da sich der Winkel zur Positionsberechnung im Ursprung der 3D-Welt befindet. In unserem Beispiel zu Billboarding finden Sie einen Algorithmus, welcher die Winkel zu einem frei platzierten Objekt ermittelt.
Licht.position = LightPos Licht.direction = LightDir g_d3dDevice.SetLight 0, Licht If LichtIndex = True Then g_d3dDevice.LightEnable 0, True

Wichtig ist es, dass wir die genderten Lichtparameter neu zuweisen. Tun wir dies nicht, so werden sich auch keine nderungen ergeben. Das reine Zuweisen an die Parameter des Lichtobjektes reicht nicht aus. Die nderungen mssen auch Direct3D mitgeteilt werden.
End Sub

Sie sollten noch einen Blick in die CreateWall()-Subroutine werfen. Diese ist nicht sonderlich spektakulr, dennoch ist die Ausrichtung des Normalvektors interessant. Diese muss fr die vier Wnde unterschiedlich sein. Wrden alle in eine Richtung weisen, wrden wir das umkreisende Licht nur aus einem bestimmten Winkel sehen.
Private Function CreateWall() . .

164

Material

. posz = 2 g_dx.CreateD3DVertex 0 + posx, 0 + posy, 0 + posz, 0, 0, 1, 0 * _ Texturefaktorx, 4 * texturefaktory, Vertex(0)

Fr die vordere Wand richten wir den Normalvektor auf 0, 0, 1. Interessant ist der Parameter Vertex.nz, den wir auf 1 setzten.
. . . posz = -2 g_dx.CreateD3DVertex 0 + posx, 0 + posy, 0 + posz, 0, 0, -1, 0 * _ Texturefaktorx, 4 * texturefaktory, Vertex(40)

Fr die hintere Wand richten wir den Normalvektor auf 0, 0, -1. Wiederum ist der Parameter Vertex.nz interessant.
. . . posz = -2 posx = -2 g_dx.CreateD3DVertex 0 + posx, 0 + posy, 0 + posz, -1, 0, 0, _ 0 * Texturefaktorx, 4 * texturefaktory, Vertex(80)

Bei der linken Wand verliert der Parameter Vertex.nz an Bedeutung. Wichtiger wurde der Parameter Vertex.nx diesen setzten wir auf -1.
. . . posz = -2 posx = 2 g_dx.CreateD3DVertex 0 + posx, 0 + posy, 0 + posz, 1, 0, 0, _ 0 * Texturefaktorx, 4 * texturefaktory, Vertex(120)

Fr die rechte Wand gilt das Gleiche wie fr die linke Wand. Die grte Bedeutung erlangt der Vertex.nx-Parameter. Dieser wird auf 1 gesetzt.
. . . End Function

Sie haben natrlich erkannt, wie die Normalvektoren ausgerichtet wurden. Immer nach auen, sozusagen in den freien Raum. Kreist nun die Lichtquelle um die Wnde, so knnen die Wnde das Licht optimal reflektieren.

Kapitel 2 Direct3D

165

Der Normalvektor ist kein Punkt im Koordinatensystem, sondern eine Richtung. Besonders bei drehenden Objekten ist es manchmal recht schwer den Normalvektor optimal zur Lichtquelle auszurichten. Deshalb wird bei vielen Spielen darauf verzichtet. Meistens bemerkt das der Anwender nicht. Dies hngt damit zusammen, dass im Regelfall nicht nur eine Lichtquelle ein Objekt beeinflusst. Oftmals ist sogar ein allgemeines (ambientes) Licht gesetzt. Dies ist in der gesamten 3DWelt vorhanden, also auch von allen Seiten des Objektes.

2.10

Texturen
Die meisten Objekte in der Realitt sind nicht einfarbig, sondern haben ein Oberflchenmuster. Dieses Oberflchenmuster wird in der Computergrafik Texture genannt. Texturen sind zweidimensionale Felder von Farbinformationen (Bitmaps). Die Bitmaps werden auf eine Texturesurface aufgezogen. Die einzelnen Pixel einer Texturesurface werden Texel genannt. Texturen sind zweidimensional. Da sie zweidimensional sind, verleihen sie einer Oberflche auch keine dreidimensionalen Eigenschaften. Dennoch knnen Texturen einer Oberflche den Anschein verleihen, als wre sie dreidimensional. Diese Illusion kann aber nur aufrechterhalten werden, solange der Betrachter die Textur aus einer bestimmten Perspektive sieht. Bewegt sich der Betrachter um die Oberflche herum, so fllt dieser Schwindel schnell auf. Komplexe Texturen, welche z.B. einen Horizont oder eine Huserwand entlang einer Strae darstellen, werden meistens nur aus fest definierten Positionen mit fest definierten Blickrichtungen betrachtet. Bei solch einem Einsatz fllt der Schwindel oftmals nicht auf. Natrlich werden Texturen nicht nur dazu eingesetzt, um ganze Bilder darzustellen. Die primre Aufgabe der Textur ist es, ein einzelnes 3D-Objekt realistisch zu gestalten. Erstellen Sie z.B. eine Schachtel mit einem Deckel. In diesem Beispiel knnen Sie der Auenseite der Schachtel ein Schmuckdesign zuweisen und der Innenseite ein einfaches Papiermuster. Fr den Deckel verfahren Sie genauso. Betrachtet man nun die Schachtel im 3D-Raum, so wirkt diese sehr viel realistischer. Diese Effekte erreichen Sie nicht, indem Sie nur Materialeigenschaften verwenden. Oberflchen, die nur mit Materialeigenschaften konstruiert wurden, wirken immer knstlich. Um eine Textur fr D3D verfgbar zu machen, mssen wir eine Textursurface erstellen. Diese besondere Art einer Surface dient als Container. Diese Textursurface steht allen Polygonen einer 3D-Welt zur Verfgung. Bevor wir tiefer in die Theorie gehen, schauen wir uns direkt ein Texturbeispiel an.

166

Texturen

2.10.1 Beispiel (Textur 1)


In unserem ersten Texturenbeispiel erstellen wir zwei Dreiecke, die ein Quadrat bilden. Auf dem erstellten Quadrat werden wir eine Textur einblenden. Dieses Beispiel sollte fr Sie kein Problem darstellen. Sie werden ein paar neue Elemente entdecken. Diese werden im Verlauf des Kapitels Textur erlutert. Schauen Sie sich das folgende Beispiel einfach einmal im Schnelldurchgang an.

Bild 2.26: Bildschirmfoto Textur_1

Beginnen wir mit den Dimensionierungen. Dabei fllt die TextureSurf As DirectDrawSurface7 auf. Sie wird die eingesetzte Textursurface sein.
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey _ As Long) As Integer Dim g_dx As New DirectX7 Dim g_dd As DirectDraw7 Dim g_d3d As Direct3D7 Dim ddsd As DDSURFACEDESC2 Dim g_ddsPrimary As DirectDrawSurface7 Dim g_ddsBackBuffer As DirectDrawSurface7 Dim TextureSurf As DirectDrawSurface7

Zustzlich zu unseren normalen Surfaces bentigen wir eine Textursurface. Diese dimensionieren wir mit TextureSurf As DirectDrawSurface7.

Kapitel 2 Direct3D

167

Dim Dim Dim Dim Dim Dim

g_d3dDevice As Direct3DDevice7 vPort As D3DVIEWPORT7 g_d3drcViewport(0) As D3DRECT matProj As D3DMATRIX matView As D3DMATRIX Vertex(5) As D3DVERTEX

Private Sub Form_Load() InitDDraw InitD3D

In der Form_Load()-Subroutine verzweigen wir nach InitDDraw() und InitD3D(). Diese beiden Subroutinen sind Ihnen bereits bekannt. Die Routinen finden Sie etwas spter im Listing. Nachdem wir aus den Initialisierungsroutinen zurckgekehrt sind, geht es mit den Objektkoordinaten weiter.
g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex -2.5, -2.5, 0, 0, 0, -1, 0, 1, Vertex(0) -2.5, 2.5, 0, 0, 0, -1, 0, 0, Vertex(1) 2.5, 2.5, 0, 0, 0, -1, 1, 0, Vertex(2) 2.5, 2.5, 0, 0, 0, -1, 1, 0, Vertex(3) 2.5, -2.5, 0, 0, 0, -1, 1, 1, Vertex(4) -2.5, -2.5, 0, 0, 0, -1, 0, 1, Vertex(5)

Beim Erstellen der beiden Dreiecke sind die Parameter tu und tv interessant. Sie bestimmen, wie die Textur ber die beiden Dreiecke verteilt werden soll.
CreateTextur App.Path & "\Lake.bmp"

CreateTexture() ist ebenfalls eine eigene Subroutine. Sie sorgt dafr, das wir der Texturesurface die ausgewhlte Bitmap zuweisen. In dem Zusammenhang wird natrlich auch die eigentliche Textursurface erstellt.
g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, _ &HFFFFFF

Wir setzten einfach ein allgemeines Licht. Ohne Licht wre die Textur nicht sichtbar.
Dim mat As D3DMATERIAL7 mat.Ambient.r = 1 mat.Ambient.g = 1 mat.Ambient.b = 1 mat.Ambient.a = 1 g_d3dDevice.SetMaterial mat

Ebenfalls mssen wir die Materialeigenschaften fr die Dreiecke setzen. Wrden wir das 3D-Objekt ohne Material rendern, so knnte das eintreffende Licht nicht reflektiert werden.

168

Texturen

Do g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ RGB(255, 0, 0), 0, 0 g_d3dDevice.BeginScene g_d3dDevice.SetTexture 0, TextureSurf g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(0), 6, D3DDP_WAIT g_d3dDevice.EndScene g_ddsPrimary.Flip Nothing, DDFLIP_WAIT DoEvents Loop Until GetAsyncKeyState(vbKeyEscape) <> 0

In der Do...Loop Until()-Schleife wird das 3D-Objekt gerendert und anschlieend auf die primre Surface geflippt.
g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL g_dd.RestoreDisplayMode Set g_dd = Nothing Set g_d3dDevice = Nothing Set g_dx = Nothing End

Nachdem die Escape-Taste gedrckt wurde, verlassen wir das Programm.


End Sub

Jetzt folgen die beiden Initialisierungsroutinen InitDDraw() und InitD3D(). Beide Routinen sind bereits bekannt und brauchen nicht weiter erklrt werden.
Private Sub InitDDraw() Set g_dx = New DirectX7 Set g_dd = g_dx.DirectDrawCreate("") g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_FULLSCREEN Or _ DDSCL_EXCLUSIVE g_dd.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT ddsd.lFlags = DDSD_BACKBUFFERCOUNT Or DDSD_CAPS ddsd.ddsCaps.lCaps = DDSCAPS_COMPLEX Or DDSCAPS_FLIP _ Or DDSCAPS_PRIMARYSURFACE Or DDSCAPS_VIDEOMEMORY Or _ DDSCAPS_3DDEVICE ddsd.lBackBufferCount = 1 Set g_ddsPrimary = g_dd.CreateSurface(ddsd) Dim Caps As DDSCAPS2 Caps.lCaps = DDSCAPS_BACKBUFFER Set g_ddsBackBuffer = g_ddsPrimary.GetAttachedSurface(Caps) End Sub Private Sub InitD3D() Set g_d3d = g_dd.GetDirect3D Set g_d3dDevice = g_d3d.CreateDevice _

Kapitel 2 Direct3D

169

("IID_IDirect3DHALDevice", g_ddsBackBuffer) vPort.lX = 0 vPort.lY = 0 vPort.lHeight = 480 vPort.lWidth = 640 g_d3dDevice.SetViewport vPort With g_d3drcViewport(0) .X1 = 0: .Y1 = 0 .X2 = 640 .Y2 = 480 End With g_dx.IdentityMatrix matView Call g_dx.ViewMatrix(matView, MakeVector _ (0, 0, -5),MakeVector(0, 0, 0), MakeVector(0, 1, 0), 0) g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView g_dx.IdentityMatrix matProj Call g_dx.ProjectionMatrix(matProj, 1, 100, 3.14159 / 2) d3dDevice.SetTransform D3DTRANSFORMSTATE_PROJECTION, matProj g_d3dDevice.SetRenderTarget g_ddsBackBuffer End Sub

Private Function MakeVector(a As Double, b As Double, c As _ Double) As _ D3DVECTOR Dim vecOut As D3DVECTOR With vecOut .x = a .y = b .z = c End With MakeVector = vecOut End Function

Nun folgt der wichtigste Teil des Listings. Die CreateTexture()-Subroutine bernimmt alle Aufgaben um eine Textursurface zu erzeugen.
Private Sub CreateTextur(sFile As String) Dim ddsd3 As DDSURFACEDESC2 Dim TextureEnum As Direct3DenumPixelFormats Set TextureEnum = g_d3dDevice.GetTextureFormatsEnum() TextureEnum.GetItem 1, ddsd3.ddpfPixelFormat ddsd3.ddsCaps.lCaps = DDSCAPS_TEXTURE

Grundstzlich ist eine Textursurface eine ganz normale Surface. Sie unterscheidet sich von einer primren oder Offscreensurface nur durch die gesetzten Flags. Fr unseren Fall ist das DDSCAPS_TEXTURE-Flag wichtig.

170

Texturen

Set TextureSurf = g_dd.CreateSurfaceFromFile(sFile, ddsd3) End Sub

2.10.2 Textur-Koordinaten
Texturen sind zweidimensionale Bilder. Ein 3D-Objekt wird aus vielen kleinen Polygonen zusammengebaut. Das zweidimensionale Bild muss nun auf die gesamte Flche aller Polygone verteilt werden. Ist die Bitmap genauso gro wie die Flche aller Polygone, so werden die Pixel 1:1 auf das 3D-Objekt bertragen.

Bitmap

Polygon

Bild 2.27: Bitmap mit gleich groer Polygonflche

Dabei besitzt jedes Texel (Pixel auf einer Textursurface) eine eindeutige Adresse. Glcklicherweise brauchen wir nicht jede Texeladresse definieren. Unsere Aufgabe beschrnkt sich auf die Vertexe der Polygone. Betrachten wir uns einmal die Eckpunkte der Bitmap. Die Bitmap hat eine Gesamtlnge von 1. Ebenfalls hat Sie eine Gesamthhe von 1. Dies ist vllig unabhngig davon, welche tatschlichen Dimensionen die Bitmap besitzt.

Kapitel 2 Direct3D

171

(0,0)

(1,0)

Bitmap

(0,1)
Bild 2.28: Bitmap

(1,1)

Das heit, eine Bitmap mit den Dimensionen 128,128 wird genauso wie eine Bitmap mit den Dimensionen 64,64 auf 1,1 (generic addressing scheme)gesetzt. Dies hat natrlich den Vorteil, das man die Bitmap mathematisch leicht berechnen kann. Da fr D3D alle Bitmaps quasi gleich gro sind, braucht man sich um die tatschlichen Gren nicht weiter zu kmmern. Mchten Sie diese Bitmap nun auf ein 3D-Objekt auftragen, so knnen Sie dieses tun, indem Sie den einzelnen Vektoren eines Polygons mitteilen, welchen Anteil Sie von der gesamten Bitmap erhalten sollen.
(0,0) Polygon 1 (1,0)

Polygon 2 (0,1)
Bild 2.29: Quadrat aus zwei Polygonen

(1,1)

Dies ist die einfachste Zuweisung eines Bitmaps. Mit zwei Dreiecken haben wir ein Rechteck gebildet. Schauen wir uns die Vertextrukturen fr die beiden Polygone an:

172

Texturen

Dim Vert(5) As D3DVERTEX 'Polygon 1 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Polygon 2 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex

0, 0, 0 , -1, 0, -1, 0, 1, Vert(0) 0, 5, 0 , -1, 0, -1, 0, 0, Vert(1) 5, 5, 0 , -1, 0, -1, 1, 0, Vert(2) 5, 5, 0, -1, 0, -1, 1, 0, Vert(3) 5, 0 ,0, -1, 0, -1, 1, 1, Vert(4) 0, 0 ,0, -1, 0, -1, 0, 1, Vert(5)

Rufen wir uns nochmals die CreateD3Dvertex()-Methode in Erinnerung.


DirectX7.CreateD3DVertex( x As Single, _ y As Single, _ z As Single, _ nx As Single, _ ny As Single, _ nz As Single, _ tu As Single, _ tv As Single, _ v As D3DVERTEX)

Fr die Texturkoordinaten sind die Mitgliedsdaten tu und tv von Bedeutung. Projizieren Sie die Bitmap auf das rechteckige 3D-Objekt. So knnen Sie erkennen, wie die tu- und tv- Parameter gefllt werden mssen. Wir haben zuerst das erste Dreieck im Uhrzeigersinn erstellt. Dies beschreibt den Bitmapbereich von links unten nach links oben und anschlieend nach rechts oben. Wir weisen den Parametern tu und tv der Vertexe die Werte 0,0, 0,1 und 1,1 zu. Anschlieend haben wir das zweite Dreieck erstellt. Dieses verluft von rechts oben nach rechts unten und anschlieend nach links unten. Die zugewiesenen Werte lauten diesmal 1,1, 1,0 und 0,0. Beide Dreiecke zusammen beschreiben nun die gesamten Dimensionen der Bitmap. Da die Bitmap und das 3D-Objekt die gleichen Dimensionen haben, wird die Textur in der gerenderten Szene ohne Verzerrungen dargestellt. Natrlich nur dann, wenn Sie die Textur gerade von vorne betrachten. Betrachten Sie die Textur von der Seite, so wird die Textur perspektivisch entsprechend gerendert. Dieses Beispiel ist recht einfach zu verstehen. Aber wie sieht es aus, wenn wir ein Rechteck bilden, welches aus mehr als zwei Dreiecken erstellt wurde. Verdeutlichen wir uns das Problem mit einem rechteckigen 3D-Objekt, das aus acht Dreiecken gebildet wird. Wir haben die einzelnen Dreiecke nummeriert. So knnen Sie erkennen, in welcher Reihenfolge wir die Polygone erstellt haben. Natrlich drfen Sie auch eine andere Reihenfolge whlen. Die Parameter tu und tv ndern sich dadurch nicht. (Auer Sie ndern nicht nur die Reihenfolge, sondern auch die Parameter x, y und z.)

Kapitel 2 Direct3D

173

0, 0

0.5, 0

1, 0

0, 0.5

0.5, 0.5

1, 0.5

Bitmap

0, 1

0.5, 1

1, 1

Bild 2.30: Rechteck aus acht Polygonen Dim Vert(23) As D3DVERTEX 'Dreieck 1 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex Vert(1) DirectX7.CreateD3DVertex Vert(2) 'Dreieck 2 DirectX7.CreateD3DVertex Vert(3) DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 3 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 4 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex Vert(10) DirectX7.CreateD3DVertex Vert(11) 'Dreieck 5 DirectX7.CreateD3DVertex Vert(12) DirectX7.CreateD3DVertex Vert(13) DirectX7.CreateD3DVertex 'Dreieck 6

0, 0, 0 , -1, 0, -1, 0, 1, Vert(0) 0, 2.5, 0 , -1, 0, -1, 0, 0.5, _ 2.5, 2.5, 0 , -1, 0, -1, 0.5, 0.5, _

2.5, 2.5, 0, -1, 0, -1, 0.5, 0.5, _ 2.5, 0 ,0, -1, 0, -1, 0.5, 1, Vert(4) 0, 0 ,0, -1, 0, -1, 0, 1, Vert(5) 0, 2.5, 0, -1, 0, -1, 0, 0.5, Vert(6) 0, 5 ,0, -1, 0, -1, 0, 0, Vert(7) 2.5, 5 ,0, -1, 0, -1, 0.5, 0, Vert(8) 2.5, 5, 0, -1, 0, -1, 0.5, 0, Vert(9) 2.5, 2.5 ,0, -1, 0, -1, 0.5, 0.5, _ 0, 2.5 ,0, -1, 0, -1, 0, 0.5, _

2.5, 2.5, 0, -1, 0, -1, 0.5, 0.5, _ 2.5, 5 ,0, -1, 0, -1, 0.5, 0, _ 5, 5 ,0, -1, 0, -1, 1, 0, Vert(14)

174

Texturen

DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex Vert(16) DirectX7.CreateD3DVertex Vert(17) 'Dreieck 7 DirectX7.CreateD3DVertex Vert(18) DirectX7.CreateD3DVertex Vert(19) DirectX7.CreateD3DVertex Vert(20) 'Dreieck 8 DirectX7.CreateD3DVertex Vert(21) DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex Vert(23)

5, 5, 0, -1, 0, -1, 1, 0, Vert(15) 5, 2.5 ,0, -1, 0, -1, 1, 0.5, _ 2.5, 2.5 ,0, -1, 0, -1, 0.5, 0.5, _

2.5, 0, 0, -1, 0, -1, 0.5, 1, _ 2.5, 2.5 ,0, -1, 0, -1, 0.5, 0.5, _ 5, 2.5 ,0, -1, 0, -1, 1, 0.5, _

5, 2.5, 0, -1, 0, -1, 1, 0.5, _ 5, 0 ,0, -1, 0, -1, 1, 1, Vert(22) 2.5, 0 ,0, -1, 0, -1, 0.5, 1, _

Anhand dieses Beispiels sehen Sie, dass den Vertexen der Polygone immer ein entsprechender Anteil der Gesamttextur zugewiesen wird. Beachten Sie, dass Sie die Polygone im Uhrzeigersinn erstellen. Dadurch richten Sie den Normalvektor der Polygone zum Betrachter und das Polygon ist sichtbar. Ist der Normalvektor vom Betrachter abgewandt, so ist das gesamte Polygon nicht sichtbar. Sie mssten das Polygon umlaufen und von der anderen Seite betrachten, damit es sichtbar wird. Was passiert eigentlich, wenn das 3D-Objekt nicht rechteckig ist? In diesem Fall werden Sie vor eine Entscheidung gestellt. Sie haben die Mglichkeit, entweder die Textur zu dehnen oder Sie entscheiden sich dafr, nur einen bestimmten Ausschnitt aus der Textur herauszuschneiden. Nehmen wir als Beispiel ein Trapez, welches aus zwei Dreiecken erstellt wurde. Dehnen / Stauchen der Textur: Die obere Kante des Trapezes ist lnger als die untere Kante. Interpolieren wir die Lnge beider Kanten auf [1], so wird die aufgezogene Textur gestaucht.
Dim Vert(5) As D3DVERTEX 'Polygon 1 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Polygon 2 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex

1, 0, 0 , -1, 0, -1, 0, 1, Vert(0) 0, 5, 0 , -1, 0, -1, 0, 0, Vert(1) 4, 0, 0 , -1, 0, -1, 1, 1, Vert(2) 0, 5, 0, -1, 0, -1, 0, 0, Vert(3) 5, 5 ,0, -1, 0, -1, 1, 0, Vert(4) 4, 0 ,0, -1, 0, -1, 1, 1, Vert(5)

Kapitel 2 Direct3D

175

0, 0 Polygon 2

1, 0

Polygon 1 0, 1
Bild 2.31: Gestauchte Polygone

1, 1

Wenn Sie sich das Texturbeispiel 3 auf der CD anschauen, dann knnen Sie einen seltsamen Effekt beobachten. Wir verwenden zwei Dreiecke. Diese bilden ein Trapez. Nun sollte die Bitmap nach unten hin zusammenlaufen. Dies ist aber nicht der Fall. Sie knnen erkennen, das die vertikalen Linien der Textur zwar schrg verlaufen aber nicht gestaucht werden. Dies liegt hauptschlich an einer Vereinfachung der Algorithmen. Direct3D steht immer zwischen den Fronten. Auf der eine Seite erwartet der Anwender eine optimale Qualitt. Auf der anderen Seite wird optimale Performance erwartet. Optimale Qualitt und optimale Performance lassen sich nie richtig verbinden. Im Zweifelsfall wird sich D3D fr eine Lsung entscheiden, welche die besseren Performance bietet. In diesem Fall ist das sowieso kein echtes Problem. Dass eine rechteckige Bitmap auf eine Trapez aufgezogen wird, kommt recht selten vor. Sollten Sie diesen Effekt bentigen, dann nutzen Sie ein 3D-Objekt, welches aus vielen Polygonen besteht. In der 3DWelt werden Sie den vereinfachten Algorithmus nicht mehr erkennen knnen. (Auer Sie verwenden eine so deutlich strukturierte Bitmap, wie wir es in unserem Beispiel tun.) Ausschneiden der Textur:
Dim Vert(5) As D3DVERTEX 'Polygon 1 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Polygon 2 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex

0, 0, 0 , -1, 0, -1, 0.25, 1, Vert(0) 0, 5, 0 , -1, 0, -1, 0, 0, Vert(1) 5, 5, 0 , -1, 0, -1, 0.75, 1, Vert(2) 5, 5, 0, -1, 0, -1, 0, 0, Vert(3) 5, 0 ,0, -1, 0, -1, 1, 0, Vert(4) 0, 0 ,0, -1, 0, -1, 0.75, 1, Vert(5)

176

Texturen

0, 0 Polygon 2

1, 0

Polygon 1 0.25, 0
Bild 2.32: Ausgeschnittene Textur

0.75, 0

In diesem Beispiel setzten wir die obere Kante und die untere Kante in das richtige Verhltnis. Der Vorteil ist, das wir die Bitmap ohne Verzerrungen betrachten knnen. Der Nachteil ist, das uns Daten von der Bitmap verloren gehen. Die verlorenen Bitmapdaten finden wir an den Seitenteilen des Trapezes. Da wir nun aus einer rechteckigen Bitmap die Daten fr die Textur heraustrennen, werden die abgeschnittenen Bitmapteile nicht angezeigt. Folgende Abbildung verdeutlicht dies Welches Verfahren Sie wann einsetzen, ist von der jeweiligen Situation abhngig. Texturen welche z.B. ein verworrenes Muster (rauer Beton, Felsen) darstellen, knnen Sie meistens dehnen oder stauchen, ohne einen sichtbaren Fehler zu bemerken. Fr strukturierte Texturen wie Mauerwerk oder Bilder eignet sich dieses Verfahren nicht. Am besten entscheiden Sie beim Konstruieren Ihrer Szene, wie die Texturen dargestellt werden sollen. Texture Warp Bisher haben wir behauptet, dass die Texturadressen fr die Vertexe eines Polygons zwischen 0.0 und 1.0 liegen. Diese Aussage wollen wir etwas modifizieren. Stellen Sie sich vor, Sie wollen in Ihrer 3D-Welt eine lange Wand mit einer kleinen Mauerstruktur einbauen. Jetzt haben Sie zwei Mglichkeiten. Zum einen knnen Sie eine sehr groe Textur benutzen. Dies ist allerdings vom Speicherhandling her problematisch, wenn nicht sogar unmglich. Als Alternative zu einer sehr groen Textur steht uns das Kacheln der Textur zur Verfgung. Diese Technik wird als Warp Texture Address Mode bezeichnet. Diese Technik wird nicht von allen Grafikkarten untersttzt. Dennoch besitzen alle moderneren Grafikkarten diese Fhigkeit.

Kapitel 2 Direct3D

177

0, 0 Polygon 2

1, 0

Polygon 1 0.25, 0 Verlust an Bitmapdaten


Bild 2.33: Ausgeschnittene Textur

0.75, 0 Verlust an Bitmapdaten

Kombinationen mit dem Border-, Mirror- und Clamp-Mode sind erlaubt.


0, 0 5 Bitmap 0, 1 6 1, 0 11 Bitmap 1, 1 2, 0 17 Bitmap 18 3, 1 3, 0 Bitmap

12 2, 1

3 Bitmap 0, 2 4

9 Bitmap 1, 2

15 Bitmap 16 3, 2

10 2, 2

1 Bitmap 0, 3 2

7 Bitmap 1, 3 8

13 Bitmap 2, 3 14 3, 3

Bild 2.34: Warp

178

Texturen

Das Bildschirmfoto zeigt den Warp-Effekt in der Realitt.

Bild 2.35: Bildschirmfoto Warp

Hier sehen Sie, dass der Adressbereich nicht mehr auf den Wertebereich zwischen 0.0 und 1.0 begrenzt ist. Der Warp Address Mode wird nun die Bitmap auf jede Ganzzahl dehnen bzw. stauchen. Die Bitmap wird sich in diesem Beispiel insgesamt neunmal wiederholen. Betrachten wir die Zuweisungen der tu- und tv-Parameter des D3DVERTEX-Typen-Arrays.
Dim Vert(53) As D3DVERTEX 'Dreieck 1 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 2 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 3 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 4

0, 0, 0 , -1, 0, -1, 0, 0, Vert(0) 0, 5, 0 , -1, 0, -1, 0, 1, Vert(1) 5, 5, 0 , -1, 0, -1, 1, 1, Vert(2) 5, 5, 0, -1, 0, -1, 1, 1, Vert(3) 5, 0 ,0, -1, 0, -1, 1, 0, Vert(4) 0, 0 ,0, -1, 0, -1, 0, 0, Vert(5) 0, 5, 0, -1, 0, -1, 0, 1, Vert(6) 0, 10 ,0, -1, 0, -1, 0, 2, Vert(7) 5, 10 ,0, -1, 0, -1, 1, 2, Vert(8)

Kapitel 2 Direct3D

179

DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex . . . 'Dreieck 15 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 16 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 17 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex 'Dreieck 18 DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex DirectX7.CreateD3DVertex

5, 10, 0, -1, 0, -1, 1, 2, Vert(9) 5, 5 ,0, -1, 0, -1, 1, 1, Vert(10) 0, 5 ,0, -1, 0, -1, 0, 1, Vert(11)

10, 5, 0, -1, 0, -1, 2, 1, Vert(42) 10, 10 ,0, -1, 0, -1, 2, 2, Vert(43) 15, 10 ,0, -1, 0, -1, 3, 2, Vert(44) 15, 10, 0, -1, 0, -1, 3, 2, Vert(45) 15, 5 ,0, -1, 0, -1, 3, 1, Vert(46) 10, 5 ,0, -1, 0, -1, 2, 1, Vert(47) 10, 10, 0, -1, 0, -1, 2, 2, Vert(48) 10, 15 ,0, -1, 0, -1, 2, 3, Vert(49) 15, 15 ,0, -1, 0, -1, 3, 3, Vert(50) 15, 15, 0, -1, 0, -1, 3, 3, Vert(51) 15, 10 ,0, -1, 0, -1, 3, 2, Vert(52) 10, 10 ,0, -1, 0, -1, 2, 2, Vert(53)

Einschalten des WARP-Modus fr die Parameter tu und tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_WARP Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESS, _ TextureAD

Dieses Beispiel aktiviert den Warp-Modus fr die Parameter tu und tv. Alternativ knnen Sie auch selektiert auf einen der Parameter zugreifen. Einschalten des WARP-Modus fr den Parameter tu:
Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_WARP Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSU, _ TextureAD

Einschalten des WARP-Modus fr den Parameter tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_WARP Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSV, _ TextureAD

Der Warp-Modus ist der voreingestellte Modus von D3D. Um den Modus explizit zuzuweisen, dimensionieren Sie eine Variable vom Typ CONST_D3DTEXTURE ADDRESS. Somit stehen Ihnen folgende Mglichkeiten zur Verfgung:

180

Texturen

Enum CONST_D3DTEXTUREADDRESS D3DTADDRESS_WARP D3DTADDRESS_MIRROR D3DTADDRESS_CLAMP D3DTADDRESS_BORDER End Enum

= = = =

1 2 3 4

Texture Mirror Der Mirror-Modus spiegelt Texturen horizontal und vertikal oder nur horizontal bzw. nur vertikal. Dabei wird die Textur ebenfalls gekachelt wie in dem WarpModus. Die Spiegelung wirkt sich immer auf eine volle Ganzzahl der gesamten Texturdimension aus. In der Abbildung unten spiegeln wir in horizontaler und vertikaler Richtung. Die erste Textur von 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 bis 0.0, 1.0 wird normal dargestellt. Die horizontal benachbarte Textur wird horizontal gespiegelt. Die vertikal benachbarte Textur wird vertikal gespiegelt. Die diagonal liegende Textur wird horizontal und vertikal gespiegelt. Anschlieend wiederholt sich alles. Kombinationen mit dem Warp-, Border- und Clamp-Mode sind erlaubt.

0,0 Bitmap normal 0,1

1,0

2,0

3,0 Bitmap 3,1

Bitmap Bitmap tu gespiegelt normal 1,1 2,1

Bitmap Bitmap Bitmap tv gespiegelt tu gespiegelt tv gespiegelt 0,2 Bitmap normal 0,3
Bild 2.36: Mirror

1,2 Bitmap tu gespiegelt 1,3

2,2 Bitmap normal 2,3

3,2

3,3

Einschalten des MIRROR-Modus fr die Parameter tu und tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_MIRROR Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESS, _ TextureAD

Kapitel 2 Direct3D

181

Bild 2.37: Bildschirmfoto Mirror

Einschalten des MIRROR-Modus fr den Parameter tu:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_MIRROR Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSU, _ TextureAD

Einschalten des MIRROR-Modus fr den Parameter tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_MIRROR Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSV, _ TextureAD

Texture Clamp Der Clamp-Mode stellt im Bereich von 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 bis 0.0, 1.0 die Textur normal dar. Die aktuellen Pixel am Ende der Zeilen und Spalten werden auf die gesamt Texturdimension erweitert. Das wirkt so, als htten Sie die Textur ber eine nasse Farbe gezogen. Kombinationen mit dem Warp-, Mirror- und Border-Mode sind erlaubt.

182

Texturen

0, 0 Bitmap normal 0, 1

1, 0

2, 0

3, 0 Bitmap

1, 1

2, 1

3, 1

0, 2

1, 2

2, 2

3, 2

0, 3
Bild 2.38: Clamp

1, 3

2, 3

3, 3

Bild 2.39: Bildschirmfoto Clamp

Kapitel 2 Direct3D

183

Einschalten des CLAMP-Modus fr die Parameter tu und tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_CLAMP Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESS, _ TextureAD

Einschalten des CLAMP-Modus fr den Parameter tu:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_CLAMP Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSU, _ TextureAD

Einschalten des CLAMP-Modus fr den Parameter tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_CLAMP Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSV, _ TextureAD

Texture Border Der Border-Mode stellt im Bereich von 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 bis 0.0, 1.0 die Textur normal dar. Der Rest der gesamten Texturdimension wird mit der aktuellen Zeichenfarbe gefllt. Kombinationen mit dem Warp-, Mirror- und Clamp- Mode sind erlaubt.
0, 0 Bitmap normal 0, 1 1, 1 2, 1 3, 1 1, 0 2, 0 3, 0 Bitmap

0, 2

1, 2

2, 2

3, 2

aktuelle Zeichenfarbe

0, 3
Bild 2.40: Border

1, 3

2, 3

3, 3

184

Texturen

Bild 2.41: Bildschirmfoto Border

Einschalten des BORDER-Modus fr die Parameter tu und tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_BORDER Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESS, _ TextureAD

Einschalten des BORDER-Modus fr den Parameter tu:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_BORDER Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSU, _ TextureAD

Einschalten des BORDER-Modus fr den Parameter tv:


Dim TextureAD As CONST_D3DTEXTUREADDRESS TextureAD = D3DTADDRESS_BORDER Direct3DDevice7.SetTextureStageState 0, D3DTSS_ADDRESSV, _ TextureAD

2.10.3 Texture Filtering


Direct3D rendert ein dreidimensionales Polygon auf einen zweidimensionalen Bildschirm. Ist dieses Polygon mit einer Textur berzogen, so muss D3D die Texel (Pixel auf einer Textursurface) der Textur auf die Pixel des Monitors

Kapitel 2 Direct3D

185

umrechnen. Dies bringt Darstellungsprobleme mit sich, da eine Textur nur zweidimensional und nicht unendlich genau ist. Einerseits soll die Textur perspektivisch korrekt auf das Polygon gelegt werden, anderseits kann die Textur aufgrund fehlender Bandbreite und Speicherplatz nicht unendlich gro sein, so dass normalerweise relativ kleine Texturen gezoomt werden, wenn man sich dem Objekt nhert. Auch das Gegenteil, das Verkleinern einer Textur, bringt Probleme mit sich. Es mssen Lsungen gesucht werden, um die fehlenden Pixel und die aus der Ungenauigkeit entstehenden visuellen Artefakte zu vermindern. Vergrerungsproblem:

Texel

Texel

Texture
Bild 2.42: Vergrerungsproblem

Monitorbild

Stellen Sie sich vor, Sie haben eine Wand mit einer Textur erzeugt. Diese positionieren Sie in Ihrer 3D-Welt. Aus der Ferne betrachtet, sieht die Wand recht gut aus. Je mehr Sie sich der Wand nhern, desto grber werden die Texel auf dem Monitorbild dargestellt. Stehen Sie unmittelbar vor der Wand, so wirkt die Wand, als wre sie aus groben Kltzchen erstellt worden. Vergleichen Sie das mit einem Blick durch ein Mikroskop. Dort sieht eine scheinbar glatte Oberflche wie eine Mondlandschaft aus. Da Direct3D groe Farbfelder bildet, wirkt das noch viel schlimmer. Verkleinerungsproblem: Stehen wir in der 3D-Welt sehr weit entfernt von unserer Wand, treten folgende Probleme auf. Auf der Textur sind z.B. vier Texel; diese sollen in Pixel des Monitorbildes umgerechnet werden. Bei der Darstellung der Wand auf dem Monitor ist aber nur Platz fr z.B. ein Pixel. Direct3D muss nun entscheiden, welches von den vier Texeln dargestellt werden soll. Welches Texel gewhlt wird, ndert sich je nach Position und Blickrichtung des Betrachters. Nun tritt der so genannte Shimmering-Effekt auf.

186

Texturen

Texel

Texel

Texture
Bild 2.43: Verkleinerungsproblem

Monitorbild

Shimmering: Bildfehler, bei dem einem einzelnen Pixel eines Objekts je nach Betrachtungsstandort eine andere Farbe zugewiesen wird. Bei 30 Bildern pro Sekunde wirkt dies wie ein schnelles Flackern. Problemlsung: Um die beschriebenen Probleme zu lsen, gibt es eine Vielzahl von Vorschlgen. Direct3D stellt uns vier Techniken bereit. Nearest Point Sampling Nearest Point Sampling war eine der ersten Techniken zur Verbesserung der Bildqualitt von Texturen. Diese Technik, wenn man berhaupt von einer Technik sprechen kann, ist recht einfach erklrt. Der Grundgedanke ist, dass Pixel auf dem Monitor immer als Ganzzahlkoordinaten angegeben werden. Also ging man hin und hat die Fliekommawerte einfach gerundet. Somit sollte das wahrscheinlichste Texel selektiert werden. Wurde von D3D das Koordinatenpaar [x = 103,8] und [y = 103,2] errechnet, so wird das entsprechende Texel letztendlich am Koordinatenpaar [x = 104] und [y = 103] dargestellt. Sie knnen sich vorstellen, dass diese Technik mit wenig Rechenzeit auskommt. Damit erhlt dieses Verfahren eine groe Beliebtheit. Ob diese Technik den Begriff Technik verdient, sollten Sie selber entscheiden.

Natrlich verliert diese Technik mit steigenden Rechnerkapazitten ihre Bedeutung. Linear Texture Filtering Bilineares Filtering: Nhert man sich einer Textur, bilden sich Blcke. Mit dem bilinearen Fil-

Kapitel 2 Direct3D

187

tering werden weiche bergnge berechnet. Durch Aliasing verursachtes Flimmern wurde ebenfalls durch Filtering beseitigt. Trilineares Filtering: hnlich dem bilinearen Filtering, jedoch um einiges rechenaufwendiger (ca. 8 mal aufwendiger als bilinerar), da der Mittelwert von zwei bilinear gefilterten Pixeln genommen werden muss! Dieser Effekt wird unter anderem fr das Mipmapping verwendet.

Anisotropic Texture Filtering Anisotropic Filtering: Eine neue Filtertechnik fr Texturen, damit diese auch unter flachen Winkeln anschaulich bleiben und Texte darauf lesbar bleiben. Texture Filtering mit Mipmaps

Mipmapping: (MIP abk. fr Multum In Parvum; viele unter gleichen) Um bei Annherung an ein Objekt mehr Details erkennen zu knnen, werden diesem Objekt mehrere Texturen zugeordnet. Je nher der Betrachter kommt, umso mehr Details werden sichtbar. Hochauflsende Texturen werden in der Nhe verwendet, niedrigauflsende fr entfernte Objekte. In Zusammenhang mit linearem Filtering sehr wirkungsvoll.

Nearest Point Sampling Die Nearest-Point-Sampling-Technik kann die Bildung von Artefakten nicht verhindern. Diese Artefakte entstehen an den Grenzen eines Polygons in einem 3DObjekt. Begrndet wird dieses Verhalten dadurch, das diese Technik lediglich ein Texel aus einer Auswahl von vielen darzustellenden Texel auf dem Monitor auswhlt. Diese Auswahl knnte man auf Bezug der Texelfarbe als willkrlich bezeichnen. Die folgenden zwei Abbildungen verdeutlichen das Problem. Wir erstellen eine 3D-Flche aus insgesamt achtzehn Polygonen. ber diese Flche spannen wir eine Textur mit horizontalen Streifen. Das Ergebnis bei der Darstellung auf dem Monitor knnte so aussehen. Konzentrieren Sie sich lediglich auf die Grenze zwischen Polygon 17 und 18. In unserem Beispiel sind die Texel der Streifentextur berdimensional gro dargestellt. Dennoch knnen Sie die Entstehung eines Artefaktes gut erkennen. Eigentlich sollte sich das Streifenmuster beim bergang von Polygon 17 nach 18 ganz normal fortsetzten. Dies ist aber nicht der Fall. Direct3D hat den Ansatz des Streifenmusters fr Polygon 18 etwas nach unten verschoben. Dies erklrt sich durch die simple Berechnungsmethode der Nearest Point Sampling Technik. Die Position des Texels auf dem Bildschirm wird durch einfaches Auf- und Abrunden der errechneten Pixelkoordinaten bestimmt. In Abhngigkeit von der Position und Blickrichtung des Betrachters treten diese Artefakte willkrlich auf.

188

Texturen

0, 0 5 0, 1 3 0, 2 1 0, 3 2 4 6

1, 0 11 1, 1 9 1, 2 7 1, 3 8

2, 0 17 12 2, 1 15 10 2, 2 13 2, 3

3, 0

18 3, 1

16 3, 2

14 3, 3

Bild 2.44: Flche aus 18 Polygonen

0, 0

1, 0

2, 0

3, 0

0, 1

3, 1

0, 2

3, 2

Artefakt

3, 3 0, 3 1, 3 2, 3

Bild 2.45: Texturfehler bei Polygon 18

Bei Polygon 17 wurde fr den Betrachter noch richtig gerundet und bei Polygon 18 kam es fr den Betrachter zu einer fehlerhaften Rundung. Aktivieren der Nearest-Point-Sampling-Technik: Sie mssen die Filtertechnik fr den Fall der Vergrerung sowie fr den Fall der Verkleinerung einzeln setzen. Direct3D bezeichnet diese Elemente als magnificaption filering modes und minification filtering modes.

Kapitel 2 Direct3D

189

Vergrerung:
Dim TextureMagFilter As CONST_D3DTEXTUREMAGFILTER TextureMagFilter = D3DTFG_POINT Direct3DDevice7.SetTextureStageState 0, D3DTSS_MAGFILTER, _ TextureMagFilter

Verkleinerung:
Dim TextureMinFilter As CONST_D3DTEXTUREMAGFILTER TextureMinFilter = D3DTFG_POINT Direct3DDevice7.SetTextureStageState 0, D3DTSS_MINFILTER, _ TextureMinFilter

Linear Filter Eine deutliche Verbesserung der Bildqualitt biete die lineare Filterung. Diese Technik wird auch als Bilinear Filtering bezeichnet. Das bilineare Filtern ist die heute am weitesten verbreitete Technik. Sie sorgt weitgehend dafr, das die lstigen Artefakte verschwinden. Mit aktivierter bilinearer Filterung wirken Texturen auf den ersten Blick etwas verwaschen. Objekte haben oftmals keine scharfen Kanten mehr. Dies kann dazu fhren, dass Ihr Auge ein Objekt fokussieren mchte, das nicht zu fokussieren ist. Dennoch vermittelt diese Technik ein sehr viel harmonischeres, weicheres Bild, als es die Nearest-Point-Sampling-Technik vermag. Der Wischi-Waschi-Effekt ist besonders bei Texturen mit einer geringen Detailtiefe zu beobachten. Mit zunehmend steigender Performance werden immer detailliertere Texturen eingesetzt. Dies vermindert den Wischi-Waschi-Effekt. Bei der Nearest-Point-Sampling-Technik wurde das auf dem Monitor sichtbare Pixel durch einfaches Runden des Koordinatenpaars ermittelt. Dies fhrte zu abrupten Farbbergngen und zu unangenehmen Artefakten. Die bilineare Filterung benutzt vier Texel der Textur, zur Berechnung des endgltigen Pixels auf dem Monitor. Aus diesen vier Textur-Texeln wird ein gewichteter Mittelwert ermittelt. Dieser Mittelwert stellt die neue Farbe des Pixels auf dem Monitor dar. Wurde z.B. das Koordinatenpaar x = 12.2 und y = 20.2 ermittelt, so werden die Texel 12,20, 11,20, 12,19 und 11,19, als Berechnungsgrundlage genommen. Diese Texel flieen nicht zu gleichen Anteilen in die Berechnung ein, sondern sie werden entsprechend dem Abstand zum berechneten Koordinatenpaar vermischt. Als Gewicht wird das Verhltnis der Abstnde der jeweiligen Texel zum genauen Wert bezeichnet. Gehen wir einmal davon aus, dass die oben abgebildeten Texel zur Berechnung des Pixels benutzt werden. Der Farbwert des neuen Pixel wrde sich wie folgt ergeben Um die neue Farbe zu ermitteln, muss erst die Farbe des jeweiligen Texels in die RGB-Bestandteile zerlegt werden. Nachdem die neuen Anteile ermittelt wurden, kann die neue Pixelfarbe wieder zusammengesetzt werden.

190

Texturen

Bild 2.46: Texturfehler bei Polygon 18

Gewicht *

+ Gewicht *

neue Farbe

Gewicht *

+ Gewicht *

Bild 2.47: Gewichtete neue Farbe

Rotanteil der Farbe:


Gewicht(1) * Rotanteil(1) + Gewicht(2) * Rotanteil(2) + Gewicht(3) * Rotanteil(3) + Gewicht(4) * Rotanteil(4) = Rotanteil der neuen Farbe

Blauanteil der Farbe:


Gewicht(1) * Blauanteil(1) + Gewicht(2) * Blauanteil(2) + Gewicht(3) * Blauanteil(3) + Gewicht(4) * Blauanteil(4) = Blauanteil der neuen Farbe

Grnanteil der Farbe:


Gewicht(1) * Grnanteil(1) + Gewicht(2) * Grnanteil(2) + Gewicht(3) * Grnanteil(3) + Gewicht(4) * Grnanteil(4) = Grnanteil der neuen Farbe

Neue Farbe:
RGB(Rotanteil der neuen Farbe, Blauanteil der neuen Farbe, Grnanteil der neuen Farbe)

Sie sehen, dass die neue Farbe nur mit einigem Rechenaufwand erstellt werden kann. Um die einzelnen Farbanteile der neuen Farbe zu ermitteln, werden 12 Multiplikationen und 9 Additionen bentigt. Sollte Ihre Grafikkarte die Fhigkeit des bilinearen Filterns nicht besitzen, so werden Sie mit einem Performancever-

Kapitel 2 Direct3D

191

lust rechnen mssen. Es ist allerdings recht unwahrscheinlich, dass Ihre Grafikkarte diese Technik nicht untersttzt. Wir kennen keine Grafikkarte mit 3DUntersttzung, die bilineares Filtern nicht untersttzt. Aktivieren des linearen Filters: Auch bei dieser Technik mssen Sie die Filtertechnik fr den Fall der Vergrerung sowie fr den Fall der Verkleinerung einzeln setzen. Direct3D bezeichnet diese Elemente als magnification filering modes und minification filtering modes. Vergrerung:
Dim TextureMagFilter As CONST_D3DTEXTUREMAGFILTER TextureMagFilter = D3DTFG_LINEAR Direct3DDevice7.SetTextureStageState 0, D3DTSS_MAGFILTER, _ TextureMagFilter

Verkleinerung:
Dim TextureMinFilter As CONST_D3DTEXTUREMAGFILTER TextureMinFilter = D3DTFG_LINEAR Direct3DDevice7.SetTextureStageState 0, D3DTSS_MINFILTER, _ TextureMinFilter

Diese Filterung funktioniert perfekt, wenn die Dreiecke senkrecht zum Betrachter stehen. Dies ist aber sehr unwahrscheinlich. Im Regelfall ist es so, dass das Dreieck etwas geneigt ist, dann bietet diese Technik keine hundertprozentigen Ergebnisse. Auf jeden Fall bietet bilineare Filterung eine deutliche Verbesserung zur Nearest-Point-Sampling-Technik. Uneinheitlicher Filter Das uneinheitliche Filtern wird auch als anisotropic filtering bezeichnet. Nach unseren Informationen besteht fr diese Technik kein einheitlicher Algorithmus. Die Hardwarehersteller sind somit ziemlich frei in der Art, wie sie dieses Feature untersttzen wollen. Dies fhrt natrlich dazu, das es immer Hersteller geben wird, welche einen minderwertigen Algorithmus verwenden. Dies wird die Performance der Grafikkarte zwar steigern, aber der gewnschte grafische Vorteil leidet darunter am meisten. Die Softwareemulation von Direct3D benutzt einen absolut reinen Algorithmus. Diesen betrachten wir als Referenz zu denen, welche von diversen Grafikkartenherstellern eingesetzt werden. Die teilweise wirklich schlechte Qualitt ist dann am ehesten mit einem bilinearen Filter zu vergleichen. Im Gegensatz zum bilinearen Filtern werden nicht mehr viereckige Texelbereiche zur Interpolation der neuen Pixelfarbe bercksichtigt, sondern unregelmige Formen. Beim linearen Filtern werden bei geneigten Flchen die rumlich tiefen Pixel zuwenig stark gefiltert, die rumlich nheren Pixel werden leicht berfiltert. Anisotropisches Filtern bercksichtigt die perspektivischen Verzerrungen und

192

Texturen

nutzt umso mehr Texel fr ein Pixel, je weiter sich das jeweilige Pixel in der Tiefe des Raums befindet. Besonders gut lsst sich die Verbesserung der Bildqualitt beobachten an Texten, die in die Tiefe scrollen. Aktivieren des anisotropischen Filters: Auch bei dieser Technik mssen Sie die Filtertechnik fr den Fall der Vergrerung sowie fr den Fall der Verkleinerung einzeln setzen. Direct3D bezeichnet diese Elemente als magnification filering modes und minification filtering modes. Zustzlich mssen Sie dem Renderdevice noch mitteilen, wie sich die anisotropische Filterung auswirken soll. Nutzen Sie hierfr die D3DTSS_MAXANI SOTROPY- Parameter der SetTextureStage()-Methode. Ein Wert grer eins aktiviert den Filter. Der Standardwert ist eins. Vergrerung:
Dim TextureMagFilter As CONST_D3DTEXTUREMAGFILTER TextureMagFilter = D3DTFG_ANISOTROPIC Direct3DDevice7.SetTextureStageState 0, D3DTSS_MAGFILTER, _ TextureMagFilter Direct3DDevice.SetTextureStageState 0, D3DTSS_MAXANISOTROPY, 2

Verkleinerung:
Dim TextureMinFilter As CONST_D3DTEXTUREMAGFILTER TextureMinFilter = D3DTFG_ANISOTROPIC Direct3DDevice7.SetTextureStageState 0, D3DTSS_MINFILTER, _ TextureMinFilter Direct3DDevice.SetTextureStageState 0, D3DTSS_MAXANISOTROPY, 2

Filter mit Mipmaps Die Erfinder der Mipmap-Filter-Technik sind des Lateinischen wohl mchtig. MIP steht fr Multum in Parvo. Zeitgem in die deutsche Sprache bersetzt bedeutet es so viel wie Viele unter Gleichen. Eine Mipmap ist eine Reihe von Texturen. Jede Textur stellt die gleiche Bitmap dar, jedoch mit abnehmender Auflsung. Eine Textur mit niedriger Auflsung wird eingesetzt, wenn der Betrachter noch sehr weit entfernt ist. Je nher der Betrachter sich nhert, desto hher werden die aufgelsten Texturen von D3D eingesetzt. Dabei ist D3D eigenstndig in der Lage abzuschtzen, welche Textur im Moment am besten geeignet ist. Direct3D verwaltet die Texturreihe als Kette. Die Textur mit der grten Auflsung steht am Anfang der Kette. Betrachten wir den elementaren Vorteil dieser Technik. Stellen Sie sich eine Wand vor, die sehr weit entfernt ist. Die Texture die auf die Wand projiziert wird, muss stark verkleinert werden. Trotz Filtertechnik entstehen die bekannten, hsslichen Shimmering-Effekte. Auerdem ist es unlogisch immer eine groe Textur (z.B. 512 x 512 Pixel) zu verwenden, wenn lediglich 20 x 20 Pixel dargestellt werden.

Kapitel 2 Direct3D

193

Diese Textur mit einer relativ hohen Auflsung von 256 * 256 Pixel wird verwendet, wenn sich der Betrachter recht nah an der Textur befindet. Der Text ist gut lesbar.

Bild 2.48: Gewichtete neue Farbe

Diese Textur besitzt eine kleine Auflsung. Sie wird verwendet, wenn sich der Betrachter aus dem lesbaren Bereich entfernt. Die Auflsung betrgt 128 * 128 Pixel.

Bild 2.49: Gewichtete neue Farbe

Die folgende Textur ist sehr schlecht lesbar. Sie besitzt eine Auflsung von 64 * 64 Pixel. Sie wird bentigt, wenn sich der Betrachter der Textur langsam nhert, aber den Text noch nicht lesen soll.

194

Texturen

Bild 2.50: Gewichtete neue Farbe

Natrlich kann man die Auflsung der Texturen noch weiter verkleinern. Dies ist bis zu 1 * 1 Pixel mglich. Um Mipmap-Filter zu verwenden, mssen Sie eine Mipmap-Kette erstellen. Die normale Mipmap-Kette verwendet fnf Surfacelevel mit den Gren [256 * 256], [128 * 128], [64 * 64], [32 * 32] und [16 * 16]. Den Texturesurfaces mssen zu dem normalem DDSCAPS_TEXTURE-Flag noch die Flags DDSCAPS_ MIPMAP und DDSCAPS_COMPLEX zugewiesen werden. Der folgende Source-Code zeigt die notwendigen Schritte zum Einrichten einer Mipmapsurface.
Dim ddsd As DDSURFACEDESC2 Dim DDMipmap As DirectDrawSurface7 ddsd.lFlags = DDSD_CAPS Or DDSD_MIPMAPCOUNT

Das DDSD_MIPMAPCOUNT-Flag mssen wir setzen, damit wir im Anschluss angeben knnen, wie viele Mipmap-Level verwendet werden.
ddsd.lMipmapCount = 5

Hiermit geben wir die Anzahl der verwendeten Mipmap-Level an.


ddsd.ddsCaps.lCaps = DDSCAPS_TEXTURE Or DDSCAPS_MIPMAP Or _ DDSCAPS_COMPLEX ddsd.lWidth = 256 ddsd.lHeight = 256

Mit den Parametern lWidth und lHeight bestimmen wir den Toplevel der Mipmap-Textur. Dies ist wichtig fr D3D, da anhand dieser Angaben die Gren der untergeordneten Mipmap-Level berechnet werden. In unserem Beispiel definieren wir die Parameter lWidth mit 256 und lHeight mit 256. Somit ergeben sich die Mipmap-Level: Level 0 Level 1 Level 2 Level 3 Level 4 [256 * 256] [128 * 128] [64 * 64] [32 * 32] [16 * 16]

Kapitel 2 Direct3D

195

Sie mssen mit den Parametern vorsichtig umgehen. So wre die Kombination von lMipmapCount 5 und lWidth 8 sowie lHeight 8 nicht zulssig. Dies wird zu einem Fehler fhren. Level 0 Level 1 Level 2 Level 3 Level 4 [8 * 8] [4 * 4] [2 * 2] [1 * 1] [F E H L E R]

Jeder folgende Level einer Mipmap-Kette besitzt die halben Dimensionen des vorangegangenen Levels. Dies fhrt in dem zweiten Beispiel bei Level 4 zu einem Wert kleiner eins und somit zu einem Fehler.
Set DDMipmap = DD.CreateSurface(ddsd)

Leider knnen wir der Mipmapsurface nicht direkt eine Bitmap zuordnen. Diese mssen wir explizit ber eine kleine Routine erledigen. Jetzt begngen wir uns mit der CreateSurface()-Methode. Betrachten wir uns einmal, was wir bisher geschaffen haben. Wir haben eine Surface mit vier Untersurfaces (Untersurface ist nicht ganz richtig, denn alle Level einer Mipmapsurface sind gleichberechtigt.) erstellt. Diese sind durch eine Kette miteinander verbunden.
Level 0 Level 1 Level 2 Level 3 Level 4 Level 0 256 *256 128 * 128 64 * 64 32 * 32 16 * 16

Level 1
Bild 2.51: Mipmap-Kette

Level 2

Level 3

Level 4

196

Texturen

Wie Sie erkennen, sind die Surfaces vorbereitet, aber die Bitmaps fehlen noch. Die anstehende Aufgabe besteht darin, dass wir eine Bitmap mit fnf verschiedenen Auflsungen erstellen und auf die Mipmapsurface kopieren. Wir nutzen eine kleine Routine:
On Local Error Resume Next Dim DDLevel As DirectDrawSurface7 Dim DDNextLevel As DirectDrawSurface7 Dim TempSurface As DirectDrawSurface7 Dim DestRect As RECT Dim SourcRect As RECT Dim ddsCaps As DDSCAPS2 Dim DDsdTemp As DDSURFACEDESC2 Dim ddsd2 As DDSURFACEDESC2 Set DDLevel = DDMipmap

Hiermit setzen wir die Surface DDLevel gleich der zuvor erstellten DDMipmapSurface.
While Err.Number = DD_OK

Die WhileWend-Schleife luft so lange, bis ein Fehler auftritt. So lange zu Arbeiten, bis ein Fehler auftritt, ist durchaus legitim. Immerhin sorgen wir dafr, dass der Fehler ordentlich abgefangen wird und das Programm somit strungsfrei weiterarbeitet.
DDLevel.GetSurfaceDesc DdsdTemp

Die aktuellen Surface-Beschreibungen der DDLevel-Surface werden der Variablen DdsdTemp bergeben. Dadurch sind wir spter in der Lage, die Dimensionen der aktuellen Mipmapsurface auszulesen.
Set TempSurface = g_dd.CreateSurfaceFromFile(sFile & _ Trim(Str(i)) & ".bmp", ddsd2)

Mit Hilfe der Tempsurface laden wir die unterschiedlich groen Texturen. Sie dient lediglich als Container der Bitmapdaten. Von ihr werden spter die Bitmapdaten in die entsprechende Mipmapsurface geblittet.
DestRect.Right = DDsdTemp.lWidth DestRect.Bottom = DDsdTemp.lHeight

Fr die folgende Blitteraktion bentigen wir die richtigen Dimensionen. Diese werden dem Typen-Array DestRect As RECT bergeben.
DDLevel.Blt DestRect, TempSurface, SourcRect, DDBLT_WAIT

Mit der Blt()-Methode fllen wir die aktuelle Mipmapsurface mit der Bitmap der Tempsurface.

Kapitel 2 Direct3D

197

ddsCaps.lCaps = DDSCAPS_TEXTURE Or DDSCAPS_MIPMAP Set DDLevel = DDLevel.GetAttachedSurface(ddsCaps)

Hiermit schalten wir auf den nchsten Mipmap-Level weiter. Sobald kein weiterer Level zur Verfgung steht, wird eine Fehler erzeugt. Der Fehler sorgt dafr, dass wir die While...Wend-Schleife verlassen.
i = i + 1 Wend

Beispiel (Mipmap) Das Mipmap-Beispiel demonstriert den gewaltigen Qualittsgewinn der MipmapFiltertechnik. Sie sehen eine Wand. Die linke Hlfte der Wand nutzt die Mipmap sowie die lineare Filtertechnik. Die rechte Hlfte der Wand wird nur mit der linearen Filtertechnik gerendert. In diesem Teil der Wand knnen wir ganz eindeutig die grafischen Artefakte beobachten. Der grte Teil des Listings wird Ihnen vertraut sein. Somit erklren wir hauptschlich den Mipmap-relevanten Teil.
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal _ vKey As Long) As Integer Dim TimerStatus As Boolean Dim Zhler As Double Dim g_dx As New DirectX7 Dim g_dd As DirectDraw7 Dim g_d3d As Direct3D7 Dim ddsd As DDSURFACEDESC2 Dim g_ddsPrimary As DirectDrawSurface7 Dim g_ddsBackBuffer As DirectDrawSurface7 Dim g_d3dDevice As Direct3DDevice7 Dim vPort As D3DVIEWPORT7 Dim g_d3drcViewport(0) As D3DRECT Dim matProj As D3DMATRIX Dim matView As D3DMATRIX Dim Vertex(11) As D3DVERTEX

Bis hierher gehren die Dimensionierungen zu den Standardobjekten von DirectX.


Dim Dim Dim Dim Dim Dim Dim Dim DDLevel As DirectDrawSurface7 TempSurface As DirectDrawSurface7 DDMipmap As DirectDrawSurface7 DestRect As RECT SourcRect As RECT ddsCaps As DDSCAPS2 DDsdTemp As DDSURFACEDESC2 ddsd2 As DDSURFACEDESC2

198

Texturen

Dieser Abschnitt ist fr Mipmap interessanter. Die DDMipmap-Surface bentigen wir, um die eigentliche Mipmap Surface zu erstellen. Da wir an dieser Surface keine direkten Grafikzuweisungen vornehmen, nutzen wir die DDLevel-Surface als Hilfsmittel (sozusagen als Zwischensurface). Die dritte Surface, Tempsurface, bentigen wir nur, um die Bitmap von der Festplatte laden zu knnen.
Private Sub Form_Load() Zhler = -6 InitDDraw InitD3D

Die beiden Subroutinen InitDDraw() und InitD3D() sind bereits bekannt und werden nicht weiter erklrt. Sie werden auch nur genutzt, um die normalen Surfaces zu erstellen bzw. das Direct3D-Device einzurichten.
' Dreieck erstellen g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex -5, -2.5, 0, 0, 0, -1, 0, 1, Vertex(0) -5, 2.5, 0, 0, 0, -1, 0, 0, Vertex(1) 0, 2.5, 0, 0, 0, -1, 1, 0, Vertex(2) 0, 2.5, 0, 0, 0, -1, 1, 0, Vertex(3) 0, -2.5, 0, 0, 0, -1, 1, 1, Vertex(4) -5, -2.5, 0, 0, 0, -1, 0, 1, Vertex(5) 0, -2.5, 0, 0, 0, -1, 0, 1, Vertex(6) 0, 2.5, 0, 0, 0, -1, 0, 0, Vertex(7) 5, 2.5, 0, 0, 0, -1, 1, 0, Vertex(8) 5, 2.5, 0, 0, 0, -1, 1, 0, Vertex(9) 5, -2.5, 0, 0, 0, -1, 1, 1, Vertex(10) 0, -2.5, 0, 0, 0, -1, 0, 1, Vertex(11)

Diese Vertexe ergeben eine Mauer aus vier Dreiecken.


CreateTextur App.Path & "\mauer"

Die CreateTexture()-Subroutine wurde ein wenig modifiziert. Normalerweise bergeben wir als Argument den kompletten Filenamen der Bitmap. Dies tun wir diesmal nicht. Statt dessen bergeben wir nun den Stamm des Filenamens. Dadurch erhalten wir die Mglichkeit alle fnf Mipmap Surfaces ber eine indexgesteuerte Schleife zu initialisieren. Der komplette Filename setzt sich damit wie folgt zusammen:
Stamm + Index + Endung = Filename

z.B.
Mauer + 0 + .bmp = Mauer0.bmp g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, &HFFFFFF

Kapitel 2 Direct3D

199

Wir setzen ein indirektes Licht.


Dim mat As D3DMATERIAL7 mat.Ambient.r = 1 mat.Ambient.g = 1 mat.Ambient.b = 1 mat.Ambient.a = 1 g_d3dDevice.SetMaterial mat

Wir weisen ein Standardmaterial zu.


Do g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET,_ RGB(255, 0, 0), 0, 0 g_d3dDevice.BeginScene g_d3dDevice.SetTextureStageState 0, D3DTSS_MIPFILTER, _ D3DTFP_LINEAR

Hier wird der Mipmap-Modus eingeschaltet. Dieser wird durch den Parameter D3DTFP_LINEAR mit der linearen Filtertechnik verbunden. Wenn Sie sich das Demo anschauen, sollten Sie auf die eingeblendete Zahl unten rechts achten. Die verschiedenen Mipmap-Level werden sanft berblendet. Sie knnen Rechenzeit sparen, indem Sie den Parameter D3DTFP_POINT anstelle des Parameters D3DTFP_LINEAR verwenden. Dann werden die einzelnen Mipmap-Level aber nicht mehr sanft berblendet, sondern schalten abrupt um.
g_d3dDevice.SetTexture 0, DDMipmap g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _ Vertex(0), 6, D3DDP_WAIT g_d3dDevice.SetTextureStageState 0, D3DTSS_MIPFILTER, _ D3DTFP_NONE

Fr die rechte Hlfte der Wand schalten wir den Mipmap-Modus wieder aus. Beobachten Sie den Unterschied.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _ Vertex(6), 6, D3DDP_WAIT g_d3dDevice.EndScene g_ddsPrimary.Flip Nothing, DDFLIP_WAIT DoEvents Loop Until GetAsyncKeyState(vbKeyEscape) <> 0 ' DirectX Zurcksetzen und Bildschirm herstellen g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL g_dd.RestoreDisplayMode Set g_dd = Nothing Set g_d3dDevice = Nothing Set g_dx = Nothing End

200

Texturen

Nach einem Druck auf die Escape-Taste wird das Programm verlassen.
End Sub Private Function MakeVector(a As Double, b As Double, c As _ Double) As D3DVECTOR Dim vecOut As D3DVECTOR With vecOut .x = a .y = b .z = c End With MakeVector = vecOut End Function Private Sub CreateTextur(sFile As String) On Local Error Resume Next

Die Anweisung On Local Error Resume Next muss enthalten sein. Spter nehmen wir einen Fehler absichtlich in Kauf.
ddsd2.lFlags = DDSD_CAPS Or DDSD_MIPMAPCOUNT Or DDSD_WIDTH Or _ DDSD_HEIGHT ddsd2.lMipmapCount = 5 ddsd2.ddsCaps.lCaps = DDSCAPS_TEXTURE Or DDSCAPS_MIPMAP Or _ DDSCAPS_COMPLEX ddsd2.lWidth = 256 ddsd2.lHeight = 256 Set DDMipmap = g_dd.CreateSurface(ddsd2)

Mit den paar Zeilen haben wir bereits die gesamte Mipmapsurface erstellt. Sie beinhaltet fnf Level. Der grte Level besitzt die Dimensionen [256 * 256]. Die Mipmapsurface ist zwar erstellt, aber es sind noch keine Bitmapdaten geladen. Dies knnen wir auch nicht direkt an der Mipmapsurface durchfhren. Wir bentigen einige Hilfsstrukturen.
Set DDLevel = DDMipmap

Der DDLevel-Surface bergeben wir alle Eigenschaften der DDMipmap-Surface. Mit Ihr knnen wir freier arbeiten.
While Err.Number = DD_OK DDLevel.GetSurfaceDesc DDsdTemp

Wir lesen die zurzeit aktuellen Surface-Beschreibungen und speichern diese in der Variablen DDsdTemp.

Kapitel 2 Direct3D

201

Set TempSurface = g_dd.CreateSurfaceFromFile(sFile & _ Trim(Str(i)) & ".bmp", ddsd2)

Wie anfangs bereits erwhnt, bentigen wir die Tempsurface als Container fr Bitmaps. Die CreateSurfaceFromFile()-Methode ist uns bekannt und muss nicht weiter erlutert werden.
DestRect.Right = DDsdTemp.lWidth DestRect.Bottom = DDsdTemp.lHeight DDLevel.Blt DestRect, TempSurface, SourcRect, DDBLT_WAIT ddsCaps.lCaps = DDSCAPS_TEXTURE Or DDSCAPS_MIPMAP Set DDLevel = DDLevel.GetAttachedSurface(ddsCaps)

Mit der GetAttachedSurface()-Methode verzweigt Direct3D auf das nchste Mitglied der Mipmap-Kette.
i = i + 1 Wend End Sub

Die Timer()-Routine sorgt lediglich fr die Bewegung. Wir verndern die Position des Betrachters. Dadurch wirkt es so, als wrde die Wand sich uns nhern und anschlieend wieder entfernen. Natrlich hat die Wand ihre Position nie verlassen.
Private Sub Timer1_Timer() If TimerStatus = True Then Zhler = Zhler 1 If Zhler < -70 Then TimerStatus = False Else Zhler = Zhler + 1 If Zhler > -6 Then TimerStatus = True End If g_dx.IdentityMatrix matView Call g_dx.ViewMatrix(matView, MakeVector(0, 0, Zhler), _ MakeVector(0, 0, 0), MakeVector(0, 1, 0), 0) g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView g_dx.IdentityMatrix matProj Call g_dx.ProjectionMatrix(matProj, 1, 100, 3.14159 / 2) g_d3dDevice.SetTransform D3DTRANSFORMSTATE_PROJECTION, _ matProj End Sub

2.10.4 Texture Blending


Direct3D kann Transparenzeffekte durch Mischen einer Textur mit einer einfachen Farbe erzeugen. Ebenfalls knnen Transparenzeffekte durch Mischen mehrerer Texturen erstellt werden. Texture-Blending beschreibt das Mischen von Texturen. Dies kann in folgende Verfahren eingestuft werden:

202

Texturen

Alpha Texture Blending Multipass Texture Blending Multiple Texture Blending

Die Performance ist im Wesentlichen von den Fhigkeiten der Grafikkarte abhngig. Fr moderne Grafikkarten gehrt die Untersttzung von Blendingtechniken zum Pflichtteil. ltere Grafikkarten (insbesondere Grafikkarten ohne 3D-Untersttzung) haben bei diesen Techniken groe Probleme. Alpha Texture Blending Alpha-Blending erzeugt eine Mischfarbe aus einem Texturpixel (Texel) mit dem Hintergrundpixel einer Szene. Bei dieser Berechnung flieen die Materialeigenschaften des Polygons sowie die Lichtinformationen der Szene ein. Folgende Formel beschreibt die endgltige Farbe, die der Anwender auf dem Monitor sieht.
FinalColor = TexelColor * Source-Blend-Faktor + PixelColor * Dest-Blend-Faktor

TexelColor beschreibt das aktuelle Pixel des Polygons. Der Source-Blend-Faktor ist der prozentuale Anteil, mit dem das aktuelle Texel in die endgltige Farbe (FinalColor) einflieen soll. Der Source-Blend-Faktor wird durch den AlphaWert der Materialeigenschaften des Polygons beschrieben. Dieser wird mit den einzelnen Farbanteilen des Materials multipliziert.
Rot_Anteil * Alpha_Wert Grn_Anteil * Alpha_Wert Blau_Anteil * Alpha_Wert

Der Alpha-Wert liegt in einem Wertebereich von 0.0 bis 1.0. Die PixelColor ist die Farbe eines Pixels (des Pixels welches mit dem Texel des Polygons gemischt werden soll) aus der Szene. Der Dest-Blend-Faktor ist der prozentuale Anteil, mit dem das Szenenpixel in die FinalColor einfliet. Der Wertebereich liegt zwischen 0.0 und 1.0. Daraus knnen wir ableiten, dass ein Polygon gnzlich undurchsichtig ist, wenn der Source-Blend-Faktor 1.0 und der Dest-Blend-Faktor 0.0 ist. Fr die endgltige Farbe werden keine Anteile des Hintergrundbildes bercksichtigt. Hingegen werden zu 100% alle Farben des aktuellen Polygons bercksichtigt. Komplett durchsichtig wird das Polygon sein, wenn der Sourc-Blend-Faktor 0.0 und der Dest-Blend-Faktor 1.0 ist. Die Einstellungen des Mischfaktors knnen Sie ber die Direct3DDevice7. SetRenderState()-Methode kontrollieren.

Kapitel 2 Direct3D

203

Fr den Source-Blend-Faktor:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_SRCBLEND, _ CONST_D3DBLEND

Fr den Dest-Blend-Faktor:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_DESTBLEND, _ CONST_ D3DBLEND

Diese Methode beinhaltet zwei Parameter. Der erste Parameter benennt, welchen Blend-Faktor Sie beeinflussen. Der zweite Parameter beschreibt, wie Sie den Blend-Faktor beeinflussen. Fr den zweiten Parameter stehen folgende Konstanten bereit:
Enum CONST_D3DBLEND D3DBLEND_ZERO D3DBLEND_ONE D3DBLEND_SRCCOLOR D3DBLEND_INVSRCCOLOR D3DBLEND_SRCALPHA D3DBLEND_INVSRCALPHA D3DBLEND_DESTALPHA D3DBLEND_INVDESTALPHA D3DBLEND_DESTCOLOR D3DBLEND_INVDESTCOLOR D3DBLEND_SRCALPHASAT D3DBLEND_BOTHINVSRCALPHA End Enum = = = = = = = = = = = = 1 2 3 4 5 6 7 8 9 10 11 13

Schauen Sie sich die Berechnungsgrundlage der Konstantenliste an:


D3DBLEND_ZERO BlendFaktor (0, 0, 0, 0). D3DBLEND_ONE BlendFaktor (1, 1, 1, 1). D3DBLEND_SRCCOL OR BlendFaktor (Rs, Gs, Bs, As). D3DBLEND_INVSRCCOLOR BlendFaktor (1-Rs, 1-Gs, 1-Bs, 1-As). D3DBLEND_SRCALPHA BlendFaktor (As, As, As, As). D3DBLEND_INVSRCALPHA BlendFaktor (1-As, 1-As, 1-As, 1-As). D3DBLEND_DESTALPHA BlendFaktor (Ad, Ad, Ad, Ad). D3DBLEND_INVDESTALPHA BlendFaktor (1-Ad, 1-Ad, 1-Ad, 1-Ad). D3DBLEND_DESTCOLOR BlendFaktor (Rd, Gd, Bd, Ad).

204

Texturen

D3DBLEND_INVDESTCOLOR BlendFaktor (1-Rd, 1-Gd, 1-Bd, 1-Ad). D3DBLEND_SRCALPHASAT BlendFaktor (f, f, f, 1); f = min(As, 1-Ad). D3DBLEND_BOTHINVSRCALPHA

SourceBlendFaktor (1-As, 1-As, 1-As, 1-As), und DestBlendFaktor (As, As, As, As) Wie Sie sehen, wird der Blend-Faktor auf diverse Arten erzeugt. Welche fr Ihre Anwendung die geeignetste ist, knnen Sie experimentell erforschen. Wir haben mit der Konstante D3DBLEND_BOTHINVSRCALPHA hervorragende Ergebnisse erzielt. Ebenfalls ist die Konstante D3DBLEND_ONE fr den schnellen unkomplizierten Einsatz geeignet. Diese Berechnungsart kommt ohne AlphaWerte des Materials aus und erzeugt meistens eine gute Transparenz zwischen Szene und Polygon. Beispiel Alpha Blending Unser Alpha-Blending-Beispiel demonstriert eine stufenlose Transparenz eines Polygons. Das im Vordergrund sichtbare Polygon wird langsam transparent und anschlieend wieder voll sichtbar. Hierzu nutzen wir die Berechnungsmethode D3DBLEND_BOTHINVSRCALPHA. Da nicht alle Grafikkarten Alpha Blending untersttzen, fhren wir eine kleine Prfung dieser Eigenschaft durch. Leider knnen wir diese Blending-Technik nicht softwareemuliert darstellen, so wird es zu einem Programmabbruch kommen, wenn Ihre Grafikkarte die Technik nicht beherrscht. Das Beispiel ist im Wesentlichen identisch mit den ersten Texturbeispielen im Abschnitt Texturen. Somit knnen wir uns auf die nderungen konzentrieren.
Private Sub CreateTextur(ByVal Index As Integer, sFile As _ String) Dim ddsd3 As DDSURFACEDESC2 Dim TextureEnum As Direct3DenumPixelFormats Set TextureEnum = g_d3dDevice.GetTextureFormatsEnum() TextureEnum.GetItem 1, ddsd3.ddpfPixelFormat ddsd3.ddsCaps.lCaps = DDSCAPS_TEXTURE Set TextureSurf(Index) = g_dd.CreateSurfaceFromFile(sFile, _ dsd3) End Sub

Der CreateTexture()-Methode haben wir einen weiteren bergabeparameter Index mitgegeben. Somit sind wir in der Lage, mit der Routine mehrere Texturesurfaces zu erstellen. Der Aufruf der Routine sieht so aus:
CreateTextur 0, App.Path & "\Boden.bmp" CreateTextur 1, App.Path & "\lake.bmp"

Kapitel 2 Direct3D

205

Der erste Parameter als Index und der zweite Parameter als Filename des zu ladenen Bildes. Die nchste nderung finden wir in der Form_Load()-Routine.
g_d3dDevice.SetRenderState D3DRENDERSTATE_DESTBLEND, _ D3DBLEND_BOTHINVSRCALPHA g_d3dDevice.SetRenderState D3DRENDERSTATE_SRCBLEND, _ D3DBLEND_BOTHINVSRCALPHA

Hier setzten wir die Berechnungsmethode fr berblendungen. D3DBLEND_ BOTHINVSRCALPHA sorgt fr ein weiches Ein- und Ausblenden. Diese Berechnungsart bercksichtigt den Alpha-Wert des aktuellen Materials zum Mischen der Texel mit den Pixeln. An dieser Stelle knnen Sie etwas experimentieren. Tauschen Sie den D3DBLEND_BOTHINVSRCALPHA-Eintrag mit einem beliebigen aus der CONST_D3DBLEND-Auflistung. Sie knnen wunderbar beobachten, wie sich die Transparenz des Polygons verndert. Beachten Sie, das ein Eintrag aus der CONST_D3DBLEND-Auflistung von dem Alpha-Wert des Materials unabhngig ist. Sie werden nur eine statische Transparenz erhalten, ohne dass sich die nderungen des Alpha-Werts bemerkbar macht. Einer dieser Eintrge ist z.B. die D3DBLEND_ONE-Konstante.
Do g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ RGB(0, 0, 0), 0, 0 g_d3dDevice.BeginScene g_d3dDevice.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, _ False

Das erste Polygon mit dem Hintergrundmotiv rendern wir ohne Alpha Blending. Wir schalten das Alpha Blending ber die SetRenderState()-Methode aus. Dazu setzen wir den zweiten Parameter der Methode auf False.
g_d3dDevice.SetTexture 0, TextureSurf(1) g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _ Vertex(0), 6, D3DDP_WAIT g_d3dDevice.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, _ True

Das Polygon, welches im Vordergrund gerendert wird, soll mit Transparenzeffekten dargestellt werden. Natrlich mssen wir ber die SetRenderState()-Methode das Alpha Blending aktivieren. Der zweite Parameter wird auf True gesetzt.
g_d3dDevice.SetTexture 0, TextureSurf(0) g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, D3DFVF_VERTEX, _ Vertex(6), 6, D3DDP_WAIT g_d3dDevice.EndScene

206

Texturen

g_ddsBackBuffer.SetForeColor &HFFFFFFFF g_ddsBackBuffer.DrawText 10, 10, "Alpha-Wert : " & _ Str(AlphaWert), False

Hiermit wird lediglich der aktuelle Alpha-Wert des Materials auf den BackBuffer geschrieben.
g_ddsPrimary.Flip Nothing, DDFLIP_WAIT DoEvents Loop Until GetAsyncKeyState(vbKeyEscape) <> 0

Nun fehlt noch eine Technik, mit der wir den aktuellen Alpha-Wert des Materials verndern knnen. Wir nutzen ein Timerobjekt von Visual Basic. Im Timer addieren oder subtrahieren wir den Alpha-Wert um 0.01. Anschlieend weisen wir den genderten Wert ber die SetMaterial()-Methode, dem aktuellen Material zu. Somit wird er bei dem nchsten Renderaufruf bercksichtig.
Private Sub Timer1_Timer() If TimerStatus = True Then AlphaWert = AlphaWert + 0.01 If AlphaWert > 1 Then AlphaWert = 1: TimerStatus = False Else AlphaWert = AlphaWert 0.01 If AlphaWert < 0 Then AlphaWert = 0: TimerStatus = True End If mat.diffuse.a = AlphaWert g_d3dDevice.SetMaterial mat End Sub

Multiple Texture Blending Direct3D kann bis zu acht Texturen gleichzeitig auf ein Polygon rendern. Das gleichzeitige Rendern von mehreren Texturen ermglicht eine Reihe von Spezialeffekten. So knnen Sie z.B. Licht und Schatten simulieren. Ebenso knnen Sie den Eindruck von Glanzeffekten erzeugen. Moderne Grafikkarten untersttzen Multi Texture Blending. Alternativ sind die meisten Multi-Texture-Effekte durch einfaches Texture Blending nachzuahmen. Die unterschiedlichen Texturen werden in Stufen (Blending Stages) organisiert. Gemeinsam ergeben Sie die Texture Blending-Kaskade. Die Texture-BlendingKaskade beschreibt, wie die einzelne Textur in die fr den Anwender sichtbare Textur integriert wird. Beim mischen von bis zu acht Texturen ergeben sich einige Dutzend Kombinationsmglichkeiten. Es ist schwer einzuschtzen, wie sich die Mischparameter der einzelnen Texturen auswirken. Hier hilft eigentlich nur Erfahrung und Freude am Ausprobieren.

Kapitel 2 Direct3D

207

Die meisten Anwendungen kommen mit zwei oder drei Texturstufen aus. Je weniger Texturstufen eingesetzt werden, desto berschaubarer sind die Mischparameter. Ebenfalls wird die Performance des Systems nicht zu stark belastet. Die folgende Abbildung visualisiert die Textur Blending-Kaskade.
Texturestufe 0

Texturestufe 0 Texturestufe 1

Mischparameter Mischparameter

Texturestufe 2 Mischparameter

Texturestufe n Mischparameter

fr den Anwender sichtbare Texture

Bild 2.52: Multi Texture

Im Grunde ist diese Kaskade ein Aufruf von mehreren Alpha-Blending-Aktionen. Texturstufe 0 wird mit dem Hintergrund gemischt. Das Ergebnis erzeugt einen neuen Hintergrund. Anschlieend wird Texturstufe 1 mit dem Hintergrund gemischt. Wieder entsteht ein neuer Hintergrund. Das wiederholt sich bis Texturstufe n. Sie knnen Multi Texture Blending durch Aufrufen mehrer Alpha-Blending-Aktionen simulieren. Das bringt natrlich den Nachteil, dass Sie fr jede Alpha-Blending-Aktion auch eine DrawPrimitive()-Methode aufrufen mssen. Bei Multi Texture Blending werden alle Texturstufen mit einem Aufruf der DrawPrimitive()-Methode gemischt. Im Vergleich erhalten Sie mit Multi Texture

208

Texturen

Blending einen Performancegewinn. Auerdem ist das programmtechnische Handling einfacher. Sie knnen fr jede Textur ein Farbmischverhalten und ein Alphamischverhalten definieren. Dabei unterscheidet man zwischen Mischoperation und Mischargument. Sie werden in der CONST_D3DTEXTURESTAGESTATETYPE-Liste definiert.
Enum CONST_D3DTEXTURESTAGESTATETYPE D3DTSS_ADDRESS = 12 D3DTSS_ADDRESSU = 13 D3DTSS_ADDRESSV = 14 D3DTSS_ALPHAARG1 = 5 D3DTSS_ALPHAARG2 = 6 D3DTSS_ALPHAOP = 4 D3DTSS_BORDERCOLOR = 15 D3DTSS_COLORARG1 = 2 D3DTSS_COLORARG2 = 3 D3DTSS_COLOROP = 1 D3DTSS_MAGFILTER = 16 D3DTSS_MAXANISOTROPY = 21 D3DTSS_MAXMIPLEVEL = 20 D3DTSS_MINFILTER = 17 D3DTSS_MIPFILTER = 18 D3DTSS_TEXCOORDINDEX = 11 D3DTSS_TEXTURETRANSFORMFLAGS = 24 End Enum

Aus dieser Liste sind die Operatoren D3DTSS_COLOROP und D3DTSS_ ALPHAOP interessant. Sie werden mit der Direct3DDevice7.SetTextureStageState()-Methode aufgerufen. Diese Methode bentigt einen zweiten Parameter. Der zweite Parameter wird durch die CONST_D3DTEXTUREOP-Konstantenliste beschrieben.
Enum CONST_D3DTEXTUREOP D3DTOP_DISABLE = 1 D3DTOP_SELECTARG1 = 2 D3DTOP_SELECTARG2 = 3 D3DTOP_MODULATE = 4 D3DTOP_MODULATE2X = 5 D3DTOP_MODULATE4X = 6 D3DTOP_ADD = 7 D3DTOP_ADDSIGNED = 8 D3DTOP_ADDSIGNED2X = 9 D3DTOP_SUBTRACT = 10 D3DTOP_ADDSMOOTH = 11 D3DTOP_BLENDDIFFUSEALPHA = 12 D3DTOP_BLENDTEXTUREALPHA= 13

Kapitel 2 Direct3D

209

D3DTOP_BLENDFACTORALPHA = 14 D3DTOP_BLENDTEXTUREALPHAPM = 15 D3DTOP_BLENDCURRENTALPHA = 16 D3DTOP_PREMODULATE = 17 D3DTOP_MODULATEALPHA_ADDCOLOR = 18 D3DTOP_MODULATECOLOR_ADDALPHA = 19 D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20 D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21 D3DTOP_BUMPENVMAP = 22 D3DTOP_BUMPENVMAPLUMINANCE = 23 D3DTOP_DOTPRODUCT3 = 24 End Enum

Die Mischargumente werden durch die Texturargument-Flags beschrieben. D3DTA_CURRENT Das Mischargument resultiert aus der vorherigen Texturstufe. In der ersten Texturstufe (Stufe 0) ist dieses Argument quivalent zu D3DTA_DIFFUSE. D3DTA_DIFFUSE Das Mischargument ist die diffuse Farbe der Vertexkomponente. Der voreingestellte Farbwert ist 0xFFFFFFFF. D3DTA_TEXTURE Das Mischargument ist die Texturfarbe der Texturstufe. Es ist nur fr die ersten Texturargumente D3DTSS_COLORARG1 und D3DTSS_ALPHAARG1 gltig. D3DTA_SPECULAR Das Mischargument ist die Specularfarbe der Vertexkomponente. Der voreingestellte Farbwert ist 0xFFFFFFFF. Nun wird es Zeit, dass wir die Texturoperatoren und deren Texturargumente praxisnah betrachten. Wir konstruieren folgenden Fall. Auf das aktuelle Polygon mchten wir zwei Texturen mischen. Texturstufe 0 wird ohne Mischfaktoren angegeben. Texturstufe 1 soll mit der Texturstufe 0 gemischt werden. Wir setzten also folgende Parameter:
Direct3DDevice7.SetTextureStageState D3DTA_TEXTURE Direct3DDevice7.SetTextureStageState D3DTA_CURRENT Direct3DDevice7.SetTextureStageState D3DTOP_MODULATE Direct3DDevice7.SetTextureStageState D3DTOP_DIFFUSE Direct3DDevice7.SetTextureStageState D3DTOP_SELECTARG2 1, D3DTSS_COLORARG1, _ 1, D3DTSS_COLORARG2, _ 1, D3DTSS_COLOROP, _ 1, D3DTSS_ALPHAARG2, _ 1, D3DTSS_ALPHAOP, _

210

Texturen

Direct3DDevice7.SetTexture 0, Texture1 Direct3DDevice7.SetTexture 1, Texture2

Beispiel Multi Texture Blending In unserem Beispiel verwenden wir zwei Texturen. Wir simulieren einen Lichtkegel, welcher die Hintergrundtextur beleuchtet. Natrlich ist dies keine Lichtquelle, sondern eine Textur, welche mit dem Hintergrund gemischt wird. Beachten Sie, dass wir beide Texturen durch einen Aufruf der Direct3DDevice. DrawPrimitiv()-Methode mischen. Im Vergleich zu dem Alpha-Texture-Blending-Verfahren bentigen wir nur noch ein Polygon. Erinnern Sie sich, dass wir beim Alpha-Texture-Blending-Verfahren zwei Polygone bentigen. Somit wrden wir auch zwei Direct3DDevice7.DrawPrimitiv()-Methoden bentigen. Das gesamte Blending-Verfahren haben wir in der Form_Load()-Subroutine untergebracht.
Private Sub Form_Load() InitDDraw InitD3D g_dx.CreateD3DVertex -2.5, -2.5, 2, 0, 0, -1, 0, 1, Vertex(0) g_dx.CreateD3DVertex -2.5, 2.5, 2, 0, 0, -1, 0, 0, Vertex(1) g_dx.CreateD3DVertex 2.5, 2.5, 2, 0, 0, -1, 1, 0, Vertex(2) g_dx.CreateD3DVertex 2.5, 2.5, 2, 0, 0, -1, 1, 0, Vertex(3) g_dx.CreateD3DVertex 2.5, -2.5, 2, 0, 0, -1, 1, 1, Vertex(4) g_dx.CreateD3DVertex -2.5, -2.5, 2, 0, 0, -1, 0, 1, Vertex(5)

Hier erstellen wir ein Polygon aus zwei Dreiecken. Natrlich werden zwei Polygone erzeugt, dennoch werden diese mit einem Direct3DDevice7.DrawPrimitive()-Aufruf gerendert. Also betrachten wir die beiden Dreiecke als ein Polygon.
CreateTextur 0, App.Path & "\lake.bmp" CreateTextur 1, App.Path & "\spotlite.bmp"

Unsere Subroutine CreateTexture() ist Ihnen bereits bekannt. Sie erzeugt die notwendigen Textursurfaces.
g_d3dDevice.SetRenderState D3DRENDERSTATE_AMBIENT, &HFFFFFFFF

Damit wir die Polygone mit den Texturen sehen knnen, mssen wir eine Lichtquelle aktivieren. Wir haben uns fr ein indirektes (Ambient-) Licht entschieden.
Dim Farbe As D3DCOLORVALUE With Farbe .a = 1 .b = 1 .g = 1 .r = 1 End With mat.Ambient = Farbe

Kapitel 2 Direct3D

211

mat.diffuse = Farbe mat.specular = Farbe g_d3dDevice.SetMaterial mat

Wir setzen ein allgemeines Material. Indem wir alle Werte auf 1.0 setzen, werden die Farben der Texturbitmap nicht verndert.
Do g_d3dDevice.Clear 1, g_d3drcViewport(), D3DCLEAR_TARGET, _ RGB(0, 0, 0), 0, 0

Die Direct3DDevice7.Clear()-Methode kennen Sie bereits. Mit ihr lschen wir das Renderziel. In unserm Fall ist das der BackBuffer.
g_d3dDevice.BeginScene g_d3dDevice.SetTextureStageState 1, D3DTSS_MAGFILTER, _ D3DTFG_LINEAR

Diese Anweisung hat mit dem eigentlichen Texturmischen nichts zu tun. Eine lineare Filterung sieht einfach schner aus.
g_d3dDevice.SetTextureStageState D3DTA_TEXTURE g_d3dDevice.SetTextureStageState D3DTA_CURRENT g_d3dDevice.SetTextureStageState D3DTOP_MODULATE g_d3dDevice.SetTextureStageState D3DTOP_DIFFUSE g_d3dDevice.SetTextureStageState D3DTOP_SELECTARG2 1, D3DTSS_COLORARG1, _ 1, D3DTSS_COLORARG2, _ 1, D3DTSS_COLOROP, _ 1, D3DTSS_ALPHAARG2, _ 1, D3DTSS_ALPHAOP, _

Diese Anweisungen bestimmen das Mischverhalten der Texturen. Mit diesen Kombinationen konnten wir einen Lichtkegel gut simulieren.
g_d3dDevice.SetTexture 0, TextureSurf(0) g_d3dDevice.SetTexture 1, TextureSurf(1)

Das Setzen der Texturen ist ebenfalls bekannt. Interessant ist es, dass wir die Textur 1 auf Texturstufe 1 setzen. Damit haben wir Multi Texture Blending bereits erzeugt.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(0), 6, D3DDP_WAIT

Wir bentigen nur einen Aufruf der Direct3DDevice7.DrawPrimitive()-Methode. Dennoch werden beide Texturen miteinander gemischt.

212

Z-Buffer (Tiefenspeicher)

g_d3dDevice.EndScene g_ddsBackBuffer.SetForeColor &HFFFFFFFF g_ddsBackBuffer.DrawText 10, 10, "Multi Texture Beispiel", _ False g_ddsPrimary.Flip Nothing, DDFLIP_WAIT DoEvents Loop Until GetAsyncKeyState(vbKeyEscape) <> 0 g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_NORMAL g_dd.RestoreDisplayMode Set g_dd = Nothing Set g_d3dDevice = Nothing Set g_dx = Nothing End End Sub

2.11

Z-Buffer (Tiefenspeicher)
Ein Tiefenspeicher wird auch als Z-Buffer oder W-Buffer bezeichnet. Er ist eine Direct Draw Surface, welche Tiefeninformationen von Polygonen fr Direct3D speichert. Direct3D nutzt den Z-Buffer um zu unterscheiden, welches Polygon vor einem anderen Polygon sichtbar ist. Betrachten Sie eine Szene, in der zwei Polygone gerendert werden. Polygon 1 wird von Polygon 2 berlagert. Jetzt betrachten Sie die gleiche Szene von der Rckseite: Polygon 2 sollte von Polygon 1 berlagert werden. Dies ist aber nicht der Fall. Da der Renderaufruf fr Polygon 2 nach Polygon 1 erfolgt, wird Polygon 2 immer im Vordergrund liegen. Dies stellt ein gewaltiges Problem dar. Sie mssen jedes Mal, wenn Sie die Position des Betrachters ndern, entscheiden, welche Polygone im Vordergrund liegen sollen. Diese mssen Sie dann als letzte rendern. Praktisch ist dies fast unmglich. Glcklicherweise bnimmt der Z-Buffer diese Aufgaben. Im Z-Buffer werden also die Z-Werte der Polygone gespeichert. Anhand dieser Informationen ist Direct3D in der Lage zu entscheiden, welche Polygone in den Vordergrund gehren. Trotz der eigentlich komplizierten Aufgabenstellung lsst sich der Z-Buffer recht problemlos in ein Programm integrieren. Der Z-Buffer wird vor dem Direct3DDevice-Objekt erzeugt. Unterteilen wir die notwendigen Aufgaben in vier Schritte. Schritt 1: Auslesen des Z-Bufferformats und des Pixelformats

Es ist wichtig zu wissen, welche Formate die aktuelle Grafikkarte untersttzt. Mit der Direct3D7.GetEnumZBufferFormats()-Methode knnen wir die gewnschten Informationen auslesen.
Dim ddpfZBuffer As DDPIXELFORMAT Dim d3dEnumPFs As Direct3DenumPixelFormats Set g_d3d = g_dd.GetDirect3D

Kapitel 2 Direct3D

213

Set d3dEnumPFs = _ g_d3d.GetEnumZBufferFormats("IID_IDirect3DHALDevice") Dim I As Long For I = 1 To d3dEnumPFs.GetCount() Call d3dEnumPFs.GetItem(I, ddpfZBuffer) If ddpfZBuffer.lFlags = DDPF_ZBUFFER Then Exit For End If Next I

Schritt 2: Vorbereiten des DDSURFACEDESC2-Typen-Arrays fr die Z-Buffer Surface

Dim g_ddsd As DDSURFACEDESC2 g_ddsd.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT Or _ DDSD_PIXELFORMAT g_ddsd.ddsCaps.lCaps = DDSCAPS_ZBUFFER g_ddsd.lWidth = 640 g_ddsd.lHeight = 480 g_ddsd.ddpfPixelFormat = ddpfZBuffer

Schritt 3: Erzeugen der Z-Buffer Surface

Dim g_ddsZBuffer As DirectDrawSurface7 g_ddsd.ddsCaps.lCaps = g_ddsd.ddsCaps.lCaps Or _ DDSCAPS_SYSTEMMEMORY

Alternativ knnen Sie die Z-Buffersurface auch in den Videospeicher legen. Der Aufruf wrde so aussehen:
g_ddsd.ddsCaps.lCaps = g_ddsd.ddsCaps.lCaps Or _ DDSCAPS_VIDEOMEMORY Set g_ddsZBuffer = g_dd.CreateSurface(g_ddsd)

Schritt 4: Verbinden der Z-Buffer Surface mit der Rendersurface

Die Render Surface ist im Regelfall die Backbuffer Surface.


g_ddsBackBuffer.AddAttachedSurface g_ddsZBuffer

Nachdem der Z-Buffer erzeugt wurde, muss dieser zum Rendern bereitgestellt werden. Dies erfolgt durch einen einfachen Aufruf der Direct3DDevice7.SetRenderState()-Methode. Fr den ersten Parameter whlen wir den Eintrag D3DREN DERSTATE_ZENABLE. Der zweite Parameter wird durch die CONST_ D3DZBUFFERTYPE-Konstantenliste beschrieben. Zur Auswahl stehen:
Enum CONST_D3DZBUFFERTYPE D3DZB_FALSE = 0 D3DZB_TRUE = 1

214

Z-Buffer (Tiefenspeicher)

D3DZB_USEW End Enum

= 2

D3DZB_FALSE deaktiviert den Z-Buffer


D3DZB_TRUE

aktiviert den Z-Buffer


D3DZB_USEW

aktiviert den W-Buffer (W-Buffer wird heute kaum noch benutzt und wird deshalb von uns vernachlssigt.) Der komplette Aufruf der Direct3DDevice7.SetRenderState()-Methode zum Aktivieren des Z-Buffers sieht so aus:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_ZENABLE, _ D3DZB_TRUE

Zum Deaktivieren ndern Sie den zweiten Parameter der SetRenderState()Methode.


Direct3DDevice7.SetRenderState D3DRENDERSTATE_ZENABLE, _ D3DZB_FALSE

Es ist notwendig, den Z-Buffer vor jeder neuen Renderaktion zu lschen. Hierbei hilft uns die Direct3DDevice7.Clear()-Methode.
Direct3DDevice7.Clear 1, Viewport, D3DCLEAR_ZBUFFER, 0, 1, 0

Sie knnen den Schreibstatus des Z-Buffers aktivieren oder deaktivieren. Im Regelfall ist das Beschreiben des Z-Buffers erlaubt. Diese Einstellung erlaubt einen korrekten Aufbau einer Szene. Einige Spezialeffekte sperren das Beschreiben des Z-Buffers. Aktivieren des Schreibzugriffs auf den Z-Buffer:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_ZWRITEENABLE, 1

Deaktivieren des Schreibzugriffs auf den Z-Buffer:


Direct3DDevice7.SetRenderState D3DRENDERSTATE_ZWRITEENABLE, 0

Beispiel (Z-Buffer) In dem Z-Buffer-Beispiel werden zwei Polygone dargestellt. Dem ersten Polygon wird eine feste Position zugewiesen. Das zweite Polygon verndert stetig die ZPosition. Es pulsiert vor und zurck. Ohne Z-Buffer wird das zweite Dreieck

Kapitel 2 Direct3D

215

immer im Vordergrund gerendert. Das ist perspektivisch nicht korrekt. Sobald sich das zweite Dreieck von der Z-Koordinate hinter dem ersten Dreieck befindet, sollte es im Hintergrund gerendert werden. Dies erreichen wir durch den Einsatz des Z-Buffers. An dem Bildschirmfoto knnen Sie erkennen, wie das gelbe Dreieck von dem roten Dreieck berlagert wird. Das gelbe Dreieck wird berlagert, obwohl es nach dem roten Dreieck gerendert wird.

Bild 2.53: Bildschirmfoto Z-Buffer

ber die Space-Taste knnen Sie den Z-Buffer aktivieren oder deaktivieren. Mit der Escape-Taste verlassen Sie das Programm. In der InitDDraw()-Subroutine richten wir den Z-Buffer ein.
Private Sub InitDDraw() Set g_dx = New DirectX7 Set g_dd = g_dx.DirectDrawCreate("") Set d3d = g_dd.GetDirect3D g_dd.SetCooperativeLevel Form1.hWnd, DDSCL_FULLSCREEN Or _ DDSCL_EXCLUSIVE Or DDSCL_ALLOWREBOOT g_dd.SetDisplayMode 640, 480, 16, 0, DDSDM_DEFAULT Dim ddsd2 As DDSURFACEDESC2 ddsd2.lFlags = DDSD_BACKBUFFERCOUNT Or DDSD_CAPS

216

Z-Buffer (Tiefenspeicher)

ddsd2.ddsCaps.lCaps = DDSCAPS_COMPLEX Or DDSCAPS_FLIP _ Or DDSCAPS_PRIMARYSURFACE Or DDSCAPS_VIDEOMEMORY _ Or DDSCAPS_3DDEVICE ddsd2.lBackBufferCount = 1 Set g_ddsPrimary = g_dd.CreateSurface(ddsd2) Dim Caps As DDSCAPS2 Caps.lCaps = DDSCAPS_BACKBUFFER Set g_ddsBackBuffer = g_ddsPrimary.GetAttachedSurface(Caps)

Bis hierher wird eine normale komplexe Surface mit dem zugehrigen Backbuffer eingerichtet.
Dim Dim Dim Set For fenum As Direct3DenumPixelFormats ddsdZ As DDSURFACEDESC2 ddpfZBuffer As DDPIXELFORMAT fenum = d3d.GetEnumZBufferFormats("IID_IDirect3DHALDevice") i = 1 To fenum.GetCount() Call fenum.GetItem(i, ddpfZBuffer) If ddpfZBuffer.lFlags = DDPF_ZBUFFER Then Exit For Next

In diesem Abschnitt prfen wir, ob die Grafikkarte Z-Buffer untersttzt. Finden wir die Z-Buffer-Untersttzung, so verlassen wir die Schleife.
ddsdZ.lFlags = DDSD_CAPS Or DDSD_WIDTH Or DDSD_HEIGHT _ Or DDSD_PIXELFORMAT ddsdZ.ddsCaps.lCaps = DDSCAPS_ZBUFFER Or DDSCAPS_VIDEOMEMORY ddsdZ.lWidth = 640 ddsdZ.lHeight = 480 ddsdZ.ddpfPixelFormat = ddpfZBuffer

Hier werden die Z-Buffer-Surfacebeschreibungen zugewiesen. In unserem Beispiel erstellen wir den Z-Buffer im Videospeicher der Grafkikkarte. Beachten Sie, dass Sie das DDSCAPS_ZBUFFER-Flag setzen mssen. Ansonsten wei Direct3D nicht, dass es sich um einen Z-Buffer handelt.
Set g_ddsZBuffer = g_dd.CreateSurface(ddsdZ) g_ddsBackBuffer.AddAttachedSurface g_ddsZBuffer

Wir erzeugen den Z-Buffer mit der CreateSurface()-Methode. Anschlieend stellen wir mit der AddAttachedSurface()-Methode die Verbindung zum Renderziel her. In diesem Fall handelt es sich um die Backbuffer Surface.
End Sub

In der InitD3D()-Subroutine hat sich eine kleine nderung eingestellt. Beim Einrichten des Viewports mssen wir die Viewportparameter erweitern.

Kapitel 2 Direct3D

217

Private Sub InitD3D() . . . vPort.lX = 0 vPort.lY = 0 vPort.lHeight = 480 vPort.lWidth = 640 vPort.minz = 0 vPort.maxz = 1

Die Parameter minz und maxz werden beim Einsatz des Z-Buffers bentigt. Bisher haben wir diese Paramerter ignoriert. Jetzt sind sie zwingend notwendig. Sie beschreiben die Reichweite der Tiefenwerte, mit der eine Szene gerendert wird. Ein normales Rendern nach der Z-Buffer-Philosophie erreichen Sie, indem Sie den minz-Wert auf 0.0 und den maxz-Wert auf 1.0 setzten. Wenn Sie beide Werte auf 0.0 setzen, zwingen Sie Direct3D ein Objekt in den Vordergrund zu rendern. Solche Einstellungen mssen aber sorgfltig eingesetzt werden.
g_d3dDevice.SetViewport vPort . . . End Sub

In der Form_Load()-Subroutine aktivieren wir den Z-Buffer. ber die SpaceTaste knnen Sie den Z-Buffer aktivieren oder deaktivieren. Den Tastendruck bearbeiten wir in der Form_KeyDown()-Subroutine. Hier wir die Indexvariable ZBufferIndex auf True oder False gesetzt. Betrachten wir die Form_Load()-Subroutine:
Private Sub Form_Load() . . . Dim BewegungZ As Single Dim Richtung As Byte Do If Richtung = 0 Then BewegungZ = BewegungZ + 0.2 Else BewegungZ = BewegungZ 0.2 End If If BewegungZ > 10 Then Richtung = 1 End If If BewegungZ < -10 Then Richtung = 0 ObjectMatrix(1).rc43 = BewegungZ

218

Die SetRenderState()-Methode

Dieser Abschnitt ist fr die Bewegung des zweiten Dreiecks zustndig. Wir verndern die Z-Position der Vertexe, indem wir die Objektmatrix manipulieren.
If ZBufferIndex = False Then g_d3dDevice.SetRenderState D3DRENDERSTATE_ZENABLE, _ D3DZB_FALSE Else g_d3dDevice.SetRenderState D3DRENDERSTATE_ZENABLE, _ D3DZB_TRUE End If

Abhngig von dem Wert der Indexvariablen ZBufferIndex wird der Z-Buffer aktiviert oder deaktiviert. ZBufferIndex verndern Sie durch die Space-Taste.
g_ddsBackBuffer.SetForeColor &HFFFFFFFF g_ddsBackBuffer.DrawText 10, 10, "Press Space to aktivate / _ deaktivate Z Buffer", False Dim Text As String If ZBufferIndex = True Then Text = "Z Buffer --> A K T I V <--" If ZBufferIndex = False Then Text = _ "Z Buffer --> nicht A K T I V <--" g_ddsBackBuffer.DrawText 10, 30, Text, False

Abschlieend lassen wir noch einen Informationstext auf den Backbuffer schreiben. Der Text ist von der Indexvariablen ZBufferIndex abhngig.

2.12

Die SetRenderState()-Methode
Der Direct3DDevice7.SetRenderState()-Methode wollen wir ein eigenes Kapitel widmen. Diese Methode ist ein wahres Multitalent. Mit dieser Methode werden alle Parameter, die das Erscheinungsbild einer Szene beeinflussen, gesetzt. Die vollstndige Syntax lautet:
Direct3DDevice7.SetRenderState ( _ state As CONST_D3DRENDERSTATETYPE, _ renderstate As Long)

Sicherlich ist Ihnen aufgefallen, dass wir in den vorangegangenen Kapiteln diese Methode in den verschiedensten Zusammenhngen eingesetzt haben. Obwohl die Methode nur zwei Parameter beinhaltet, ist sie die vielseitigste Methode von Direct3D. Dies liegt an ihrer Variationsfhigkeit. Betrachten wir den ersten Parameter. Dieser wird durch die Konstantenliste CONST_D3DRENDERSTATE TYPE beschrieben.
Enum CONST_D3DRENDERSTATETYPE D3DRENDERSTATE_ALPHABLENDENABLE D3DRENDERSTATE_ALPHAFUNC D3DRENDERSTATE_ALPHAREF = 27 = 25 = 24

Kapitel 2 Direct3D

219

D3DRENDERSTATE_ALPHATESTENABLE D3DRENDERSTATE_AMBIENT D3DRENDERSTATE_AMBIENTMATERIALSOURCE D3DRENDERSTATE_ANTIALIAS D3DRENDERSTATE_CLIPPING D3DRENDERSTATE_CLIPPLANEENABLE D3DRENDERSTATE_COLORKEYBLENDENABLE D3DRENDERSTATE_COLORKEYENABLE D3DRENDERSTATE_COLORVERTEX D3DRENDERSTATE_CULLMODE D3DRENDERSTATE_DESTBLEND D3DRENDERSTATE_DIFFUSEMATERIALSOURCE D3DRENDERSTATE_DITHERENABLE D3DRENDERSTATE_EDGEANTIALIAS D3DRENDERSTATE_EMISSIVEMATERIALSOURCE D3DRENDERSTATE_EXTENTS D3DRENDERSTATE_FILLMODE D3DRENDERSTATE_FOGCOLOR D3DRENDERSTATE_FOGENABLE D3DRENDERSTATE_FOGTABLEMODE D3DRENDERSTATE_FOGVERTEXMODE D3DRENDERSTATE_LASTPIXEL D3DRENDERSTATE_LIGHTING D3DRENDERSTATE_LINEPATTERN D3DRENDERSTATE_LOCALVIEWER D3DRENDERSTATE_NORMALIZENORMALS D3DRENDERSTATE_RANGEFOGENABLE D3DRENDERSTATE_SHADEMODE D3DRENDERSTATE_SPECULARENABLE D3DRENDERSTATE_SPECULARMATERIALSOURCE D3DRENDERSTATE_SRCBLEND D3DRENDERSTATE_STENCILENABLE D3DRENDERSTATE_STENCILFAIL D3DRENDERSTATE_STENCILFUNC D3DRENDERSTATE_STENCILMASK D3DRENDERSTATE_STENCILPASS D3DRENDERSTATE_STENCILREF D3DRENDERSTATE_STENCILWRITEMASK D3DRENDERSTATE_STENCILZFAIL D3DRENDERSTATE_STIPPLEDALPHA D3DRENDERSTATE_TEXTUREFACTOR D3DRENDERSTATE_TEXTUREPERSPECTIVE D3DRENDERSTATE_VERTEXBLEND D3DRENDERSTATE_WARP0 D3DRENDERSTATE_WARP1 D3DRENDERSTATE_WARP2 D3DRENDERSTATE_WARP3

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

15 139 147 2 136 152 144 41 141 22 20 145 26 40 148 138 8 34 28 35 140 16 137 10 142 143 48 9 29 146 19 52 53 56 58 55 57 59 54 33 60 4 151 128 129 130 131

220

Die SetRenderState()-Methode

D3DRENDERSTATE_WARP4 D3DRENDERSTATE_WARP5 D3DRENDERSTATE_WARP6 D3DRENDERSTATE_WARP7 D3DRENDERSTATE_ZBIAS D3DRENDERSTATE_ZENABLE D3DRENDERSTATE_ZFUNC D3DRENDERSTATE_ZVISIBLE D3DRENDERSTATE_ZWRITEENABLE End Type

= = = = = = = = =

132 133 134 135 47 7 23 30 14

Was macht diese Methode zum wahren Multitalent? Die Antwort liegt im zweiten Parameter. Anders als bei den meisten Methoden wird der zweite Parameter nicht durch einen festen Wertebereich beschrieben. Der Parameter renderstate ist abhngig vom ersten Parameter. Verdeutlichen wir dies mit zwei Beispielen. Beispiel 1: Der erste Parameter soll D3DRENDERSTATE_SRCBLEND sein. Somit wird der zweite Parameter durch die Konstantenliste CONST_D3DBLEND beschrieben.
Enum CONST_D3DBLEND D3DBLEND_ZERO D3DBLEND_ONE D3DBLEND_SRCCOLOR D3DBLEND_INVSRCCOLOR D3DBLEND_SRCALPHA D3DBLEND_INVSRCALPHA D3DBLEND_DESTALPHA D3DBLEND_INVDESTALPHA D3DBLEND_DESTCOLOR D3DBLEND_INVDESTCOLOR D3DBLEND_SRCALPHASAT D3DBLEND_BOTHSRCALPHA D3DBLEND_BOTHINVSRCALPHA End Enum = = = = = = = = = = = = = 1 2 3 4 5 6 7 8 9 10 11 12 13

Beispiel 2: Der erste Parameter ist D3DRENDERSTATE_SHADEMODE. Der zweite Parameter wird dann durch die Konstantenliste CONST_D3DSHAREMODE festgelegt.
Enum CONST_D3DSHADEMODE D3DSHADE_FLAT D3DSHADE_GOURAUD D3DSHADE_PHONG = 1 = 2 = 3

Kapitel 2 Direct3D

221

End Enum

Der zweite Parameter muss nicht immer durch eine Konstantenliste definiert werden. Er kann z.B. eine Farbe enthalten oder einen Boolean-Ausdruck, True oder False. Diese doch recht komplexen Zusammenhnge haben wir in der folgenden Liste zusammengefasst.
Parameter 1 D3DRENDERSTATE_ALPHABLENDENABLE D3DRENDERSTATE_ALPHAFUNC D3DRENDERSTATE_ALPHAREF D3DRENDERSTATE_ALPHATESTENABLE D3DRENDERSTATE_AMBIENT Parameter 2 True, um Alphablending zu erlauben, und False, um Alphablending zu deaktivieren. Default -> False CONST_D3DCMPFUNC Default -> D3DCMP_ALWAYS Wert zwischen 0.0 und 1.0 Default -> 0.0 True, um alpha Test zu erlauben, und False, um alpha Test nicht zu erlauben. Default -> False Eine ambiente Lichtfarbe z.B. fr die Farbe Wei &HFFFFFFFF oder RGB (255, 255, 255). Default -> 0 CONST_D3DMATERIALCOLORSOURCE Default -> D3DMCS_COLOR2 CONST_D3DANTIALIASMODE Default -> D3DANTIALIAS_NONE ungleich 0, um Clipping zu erlauben, und gleich 0, um Clipping nicht zu erlauben Default -> ungleich 0 CONST_D3DCLIPPLANEFLAGS Default -> D3DCPF_DISABLEALL. ungleich 0, um alpha-blend Colorkey zu erlauben, und gleich [0], um alpha-blend Colorkey nicht zu erlauben True, um Colorkey-Transparenz zu erlauben, und False, um Colorkey-Transparenz nicht zu erlauben. Default -> False ungleich [0], um per-vertex-Farbe zu erlauben, und gleich [0], um per-vertex-Farbe nicht zu erlauben. Default -> ungleich 0

D3DRENDERSTATE_AMBIENTMATERIALSOURCE D3DRENDERSTATE_ANTIALIAS D3DRENDERSTATE_CLIPPING

D3DRENDERSTATE_CLIPPLANEENABLE D3DRENDERSTATE_COLORKEYBLENDENABLE D3DRENDERSTATE_COLORKEYENABLE

D3DRENDERSTATE_COLORVERTEX

222

Die SetRenderState()-Methode

Parameter 1 D3DRENDERSTATE_CULLMODE D3DRENDERSTATE_DESTBLEND D3DRENDERSTATE_DIFFUSEMATERIALSOURCE D3DRENDERSTATE_DITHERENABLE D3DRENDERSTATE_EDGEANTIALIAS D3DRENDERSTATE_EMISSIVEMATERIALSOURCE D3DRENDERSTATE_EXTENTS D3DRENDERSTATE_FILLMODE D3DRENDERSTATE_FOGCOLOR

Parameter 2 CONST_D3DCULL Default -> D3DCULL_CCW CONST_D3DBLEND Default -> D3DBLEND_ZERO CONST_D3DMATERIAL COLORSOURCE Default -> D3DMCS_COLOR1 True, um Dithering zu erlauben Default -> False True, um Linienantialias zu erlauben Default -> False CONST_D3DMATERIAL COLORSOURCE Default -> D3DMCS_MATERIAL ungleich 0, um Screenupdates zu erlauben Default -> gleich 0 CONST_D3DFILLMODE Default -> D3DFILL_SOLID Nebelfarbe vom Typ Long. z.B. mit der Directx7.CreateColorRGB()-Methode erzeugt Default -> 0 True, um Nebel zu erlauben Default -> False CONST_D3DFOGMODE Default -> D3DFOG_NONE CONST_D3DFOGMODE Default -> D3DFOG_NONE False, um das Zeichnen des letzten Pixels in einer Linie oder Dreiecks zu erlauben Default -> True ungleich 0, um Lichtberechnungen zu erlauben, oder gleich 0, um Lichtberechnungen nicht zu erlauben Default -> ungleich 0

D3DRENDERSTATE_FOGENABLE D3DRENDERSTATE_FOGTABLEMODE D3DRENDERSTATE_FOGVERTEXMODE D3DRENDERSTATE_LASTPIXEL

D3DRENDERSTATE_LIGHTING

Kapitel 2 Direct3D

223

Parameter 1 D3DRENDERSTATE_LINEPATTERN

Parameter 2 Das D3DLINEPATTERN-Typen-Array beschreibt das Linienmuster. Type D3DLINEPATTERN linePattern Long repeatFactor As Long End Type Default linePattern -> 0 Default repentFactor -> 0 ungleich 0, um relative Betrachter-SpecularGlanzlichter zu erlauben, oder gleich 0, um senkrechte Specular-Glanzlichter zu erlauben Default -> ungleich 0 ungleich 0, um ein automatisches Normalisieren des Normalvektors zu erlauben, oder gleich 0, um dies nicht zu erlauben Default -> 0 True, um Range-Based Vertex Fog zu erlauben, oder False, um Range-Based Vertex Fog nicht zu erlauben Default -> False CONST_D3DSHADEMODE Default -> D3DSHADE_GOURAUD True, um Specular-Glanzlicher zu erlauben Default -> False CONST_D3DMATERIAL COLORSOURCE Default -> D3DMCS_COLOR2 CONST_D3DBLEND Default -> D3DBLEND_ONE True, um Stencil zu erlauben Default -> False CONST_D3DSTENCILOP Default -> kein Default (wird zum Testen des Stencil verwendet) CONST_D3DCMPFUNC Default -> D3DCMP_ALWAYS Stencil-Maske Default -> 0xFFFFFFFF CONST_D3DSTENCILOP Default -> D3DSTENCILOP_KEEP

D3DRENDERSTATE_LOCALVIEWER

D3DRENDERSTATE_NORMALIZENORMALS

D3DRENDERSTATE_RANGEFOGENABLE

D3DRENDERSTATE_SHADEMODE D3DRENDERSTATE_SPECULARENABLE D3DRENDERSTATE_SPECULARMATERIALSOURCE D3DRENDERSTATE_SRCBLEND D3DRENDERSTATE_STENCILENABLE D3DRENDERSTATE_STENCILFAIL

D3DRENDERSTATE_STENCILFUNC D3DRENDERSTATE_STENCILMASK D3DRENDERSTATE_STENCILPASS

224

Die SetRenderState()-Methode

Parameter 1 D3DRENDERSTATE_STENCILREF D3DRENDERSTATE_STENCILWRITEMASK D3DRENDERSTATE_STENCILZFAIL D3DRENDERSTATE_STIPPLEDALPHA D3DRENDERSTATE_TEXTUREFACTOR

Parameter 2 Referenzwert fr den Stenciltest Default -> 0 Schreibmaske fr Stencil Default -> 0xFFFFFFFF CONST_D3DSTENCILOP Default -> D3DSTENCILOP_KEEP True, um Tpfel-Alpha zu erlauben Default -> False Farbe als Berechnungsfaktor bei Multitexturberechnungen Default -> abhngig von D3DTA_TFACTOR oder D3DTOP_BLENDFACTORALPHA True, um perspektivisch korrektes Mipmap zu erlauben Default -> True CONST_D3DVERTEXBLENDFLAGS Default -> D3DVBLEND_DISABLE CONST_D3D Default -> 0 CONST_D3D Default -> 0 CONST_D3D Default -> 0 CONST_D3D Default -> 0 CONST_D3D Default -> 0 CONST_D3D Default -> 0 CONST_D3D Default -> 0 CONST_D3D Default -> 0 Integer-Wert zwischen 0 und 16 Default -> 0 CONST_D3DZBUFFERTYPE Default -> D3DZB_TRUE ist der Z-Buffer mit dem Renderziel verbunden, ist der Default -> D3DZB_FALSE

D3DRENDERSTATE_TEXTUREPERSPECTIVE D3DRENDERSTATE_VERTEXBLEND D3DRENDERSTATE_WARP0 D3DRENDERSTATE_WARP1 D3DRENDERSTATE_WARP2 D3DRENDERSTATE_WARP3 D3DRENDERSTATE_WARP4 D3DRENDERSTATE_WARP5 D3DRENDERSTATE_WARP6 D3DRENDERSTATE_WARP7 D3DRENDERSTATE_ZBIAS D3DRENDERSTATE_ZENABLE

Kapitel 2 Direct3D

225

Parameter 1 D3DRENDERSTATE_ZFUNC D3DRENDERSTATE_ZVISIBLE D3DRENDERSTATE_ZWRITEENABLE

Parameter 2 CONST_D3DCMPFUNC Default -> D3DCMP_LESSEQUAL wird nicht verwendet True, um das Beschreiben des Z-Buffers zu erlauben Default -> True

2.13

Effekte

2.13.1 Nebel
Nebel kann das Erscheinungsbild einer Szene wesentlich realistischer wirken lassen. Geht man durch den Nebel auf ein weit entferntes Objekt zu, so wird es immer deutlicher sichtbar. Auerdem vermindert der Einsatz von Nebel die beim Rendern eventuell auftretenden Artefakte. Letztendlich knnen Sie die Sichtweite mit Nebel begrenzen. Diese Begrenzung wird aber nicht abrupt sein, sondern ermglicht ein weiches Ausblenden. Direct3D untersttzt zwei Nebelmodelle, Pixel Fog und Vertex Fog. Beim Einsatz von Nebel werden die Farben der Szene mit der eingestellten Nebelfarbe gemischt. Beim Mischen der Objekte in der Szene werden die Entfernungen zum Betrachter bercksichtigt. Weiter enfernte Objekte werden vom Nebel strker berlagert als nher liegende Objekte. Objekte, die an der maximalen Nebelreichweite liegen, sind nicht mehr sichtbar. Sie werden komplett von der Nebelfarbe berblendet. Hingegen werden Objekte, welche sich unmittelbar vor dem Betrachter befinden, vom Nebel nicht beeinflusst. Moderne Grafikkarten untersttzen beide Nebelmodelle. Um sicherzustellen, welche Nebelmodelle von der aktuellen Grafikkarte untersttzt werden, mssen wir die Grafikkarte prfen. Prfen der Grafikkarte auf die verfgbaren Nebelmodelle:
Set g_d3d = g_dd.GetDirect3D Set g_d3dDevice = g_d3d.CreateDevice _ ("IID_IDirect3DHALDevice", g_ddsBackBuffer) Dim d3ddevdesc As D3DDEVICEDESC7 g_d3dDevice.GetCaps d3ddevdesc If (d3ddevdesc.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_FOGVERTEX) = D3DPRASTERCAPS_FOGVERTEX Then VertexFogIndex = True Else VertexFogIndex = False End If

226

Effekte

In diesem Abschnitt prfen wir die Grafikkarte auf die Fhigkeit, Vertex Nebel darzustellen.
If (d3ddevdesc.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_FOGTABLE) = _ D3DPRASTERCAPS_FOGTABLE Then PixelFogIndex = True Else PixelFogIndex = False End If

Dieser Teil ist fr die Prfung auf Pixelnebel zustndig. Pixelnebel wird auch als Table Fog bezeichnet. Diese Prfroutine finden Sie in unserem Nebelbeispiel auf der CD. Berechnungsarten Direct3D unterscheidet zwischen drei Berechnungsarten zur Darstellung von Nebel. Linear, EXP und EXP2 liefern die geeigneten Ergebnisse fr eine individuelle Nebeldarstellung. Die CONST_D3DFOGMODE-Konstantenliste identifiziert die Berechnungstechniken.
Enum CONST_D3DFOGMODE D3DFOG_NONE D3DFOG_EXP D3DFOG_EXP2 D3DFOG_LINEAR End Enum = = = = 0 1 2 3

D3DFOG_LINEAR F = end d / end start Die Parameter end und start werden von Ihnen angegeben. Der Parameter d ist ein Tiefenwert. Dieser ist von der jeweiligen Szene und der aktuellen Position des Betrachters abhngig. Sie werden sicherlich erkennen, dass hier eine einfache lineare Verteilung der Nebelintensivitt stattfindet. Explizit knnen Sie die Intensivitt des Nebels nicht angeben. Wollen Sie einen schwcheren Nebel, so mssen Sie die Entfernung zwischen end und start erhhen. D3DFOG_EXP F = 1 / e^d*density D3DFOG_EXP2 F = 1 / e^(d*density)^2 Diese beiden Berechnungsmodelle sind logarithmischer Natur. Der Parameter e hat ungefhr den Wert 2.71828. Der Parameter density (Dichte) wird von Ihnen angegeben und liegt in dem Wertebereich zwischen 0.0 und 1.0. Der Parameter d ist widerum ein Tiefenwert.

Kapitel 2 Direct3D

227

Im Grunde ist die Nebeldarstellung eine weitere Form von Blending. Das Erscheinungsbild der Szene ist von den Lichteinflssen genauso abhngig wie von der Nebelfarbe oder Materialfarbe der Polygone. Alle Faktoren ergeben die gerenderte Szene. Vertex Fog Vertex Fog berechnet den Nebeleinfluss fr jeden Vertex eines Polygons. Anschlieend wird der Nebel ber das gesamte Polygon verteilt. Diese Berechnungen werden von der D3D Licht- und Transformationsroutine bernommen. Vertex Fog bietet Ihnen die Mglichkeit, auf die genaue Entfernung zum Objekt in der 3D-Welt den Nebel zu berechnen. Die Berechnung bercksichtigt die Ausrichtung des Viewports. Diese Technik wird als Range Based Fog bezeichnet. Alle uns bekannten Grafikkarten, die Vertex Fog untersttzen, bieten ebenfalls die Untersttzung fr Range Based Fog an. Dies ist keine eigenstndige Berechnungsmethode, sondern eine Erweiterung fr die Vertex-Fog-Technik. ber die Direct3DDevice7.SetRenderState()-Methode knnen Sie Range Based Fog aktivieren oder deaktivieren. Aktivieren des Range-Based-Fog-Modus:
Direct3DDevice7.SetRenderState _ D3DRENDERSTATE_RANGEFOGENABLE, True

Deaktivieren des Range-Based-Fog-Modus:


Direct3DDevice7.SetRenderState _ D3DRENDERSTATE_RANGEFOGENABLE, False

Um den Vertex Fog in eine Anwendung einzubinden sind vier Schritte notwendig. Schritt 1: Allgemeines Einschalten des Nebels
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGENABLE, True

Mit diesem SetRenderState()-Aufruf erlauben Sie die Verwendung von Nebel. Setzen Sie den zweiten Parameter auf False, so wird die Berechnung fr Nebel deaktiviert. Schritt 2: Setzen der Nebelfarbe
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGCOLOR, Farbe

Der zweite Parameter Farbe enthlt einen gltigen Farbwert. Diesen knnen Sie hexadezimal (z.B. &HFFFFFFFF fr Farbe Wei) oder per Befehlsargument (z.B. RGB (255, 255, 255)) bergeben. Eine beliebte Nebelfarbe ist ein helles Grau (RGB(200, 200, 200)). Ein reines Wei ist nicht so gut geeignet. Es wrden ungewnschte Blendeffekte auftreten. Die eingesetzte Farbe sollte die gewnschte Szene untersttzen und wird meistens den verwendeten Lichtverhltnissen angepasst.

228

Effekte

Schritt 3: Whlen der Berechnungsmethode


Direct3DDevice7.SetRenderState _ D3DRENDERSTATE_FOGVERTEXMODE, Mode

Der Parameter Mode ist eine Konstante aus der CONST_D3DFOGMODEKonstantenliste. Genauere Informationen erhalten Sie im Abschnitt Berechnungsarten. Schritt 4: Setzen der Nebelparameter Die Nebelparameter stehen in Abhngigkeit der verwendeten Nebelberechnungsmethode. So werden fr eine lineare Berechnung die Parameter D3DRENDERSTATE_FOGSTART und D3DRENDERSTATE_FOGEND bentigt. Hingegen wird fr die Berechnungsmethoden EXP und EXP2 lediglich der Parameter D3DRENDERSTATE_FOGDENSITY bentigt. Berechnungsmethode D3DFOG_LINEAR:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGSTART, _ Fstart Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGEND, FEnd

Der Parameter FStart bestimmt, ab wo der Nebel sichtbar sein soll. Der Parameter FEnd definiert, bis wo der Nebel sichtbar sein soll. ber die gesamte Distanz wird die Nebelintensitt linear ansteigen. Berechnungsmethode D3DFOG_EXP und D3DFOG_EXP2:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGDENSITY, _ Density

Der Parameter Density bildet die Grundlage der logarithmischen Berechnung der Nebeldichte. Da die Nebeldichte logarithmisch berechnet wird, sind Angaben wie FStart oder FEnd nicht notwendig. Je ger der Wert Density ist, desto dichter ist der Nebel. Der Wertebereich fr Density liegt zwischen 0.0 und 1.0. Pixel Fog Pixel Fog bildet seine Berechnung nicht aus den Vertexinformationen eines Polygons, sondern kalkuliert fr jedes Pixel einer Szene einen individuellen Nebelwert. Diese Berechnung per Pixelbasis unterscheidet sich somit von der VertexFog-Berechnungsmethode. Pixel Fog untersttzt nicht die Range-Based-FogBerechnung. Einige ltere Grafikkarten untersttzen anstelle des Pixel Fogs den WFog. Dieser ist zu der normalen Berechnung eines Z-Buffer-basierenden Systems nicht kompatibel. Um WFog zu untersttzen, mssten Sie die gesamte Projektionsmatrix umrechnen. Da alle modernen Grafikkarten den normalen Pixel Fog untersttzen, werden wir die Umrechnung nicht erlutern.

Kapitel 2 Direct3D

229

Der Einsatz von Pixel Fog verluft simultan zum Einsatz von Vertex Fog. Die verwendeten Parameter sind ebenfalls identisch. Die verwendeten RenderState()Aufrufe unterscheiden sich ein wenig, deshalb stellen wir die gesamte Prozedur nochmals vor. Schritt 1: Allgemeines Einschalten des Nebels
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGENABLE, True

Der Parameter True aktiviert den Nebel. False wrde ihn deaktivieren. Schritt 2: Setzen der Nebelfarbe
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGCOLOR, Farbe

ber den Parameter Farbe setzen Sie die aktuelle Nebelfarbe. Die DirectX7.CreateColorRGB()-Methode ist fr die Definition der Farbe bestens geeignet. Schritt 3: Whlen der Berechnungsmethode
Direct3DDevice7.SetRenderState _ D3DRENDERSTATE_FOGTABLEMODE, Mode

Der Parameter Mode ist eine Konstante aus der CONST_D3DFOGMODEKonstantenliste. Mode bestimmt die Berechungsmethode der Nebelintensitt. Schritt 4: Setzen der Nebelparameter Die Nebelparameter stehen in Abhngigkeit zu der verwendeten Nebelberechnungsmethode. So werden fr eine lineare Berechnung die Parameter D3DRENDERSTATE_FOGSTART und D3DRENDERSTATE_FOGEND bentigt. Hingegen wird fr die Berechnungsmethoden EXP und EXP2 lediglich der Parameter D3DRENDERSTATE_FOGDENSITY bentigt. Berechnungsmethode D3DFOG_LINEAR:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGSTART, _ Fstart Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGEND, FEnd

Der Parameter FStart bestimmt, ab wo der Nebel sichtbar sein soll. Der Parameter FEnd definiert, bis wo der Nebel sichtbar sein soll. ber die gesamte Distanz wird die Nebelintensitt linear ansteigen. Berechnungsmethode D3DFOG_EXP und D3DFOG_EXP2:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_FOGDENSITY, _ Density

230

Effekte

Der Parameter Density bildet die Grundlage der logarithmischen Berechnung der Nebeldichte. Da die Nebeldichte logarithmisch berechnet wird, sind Angaben wie FStart oder FEnd nicht notwendig. Je ger der Wert Density ist, desto dichter ist der Nebel. Der Wertebereich fr Density liegt zwischen 0.0 und 1.0. Beispiel (Nebel) Unser Nebelbeispiel ist etwas umfangreicher ausgefallen. Wir haben einen langen Raum erzeugt. In diesem Raum haben wir insgesamt sieben Lichtquellen platziert. Zustzlich haben wir noch vier drehende Objekte eingebunden. Diesen Aufwand haben wir betrieben, damit Sie die Wirkungsweise des Nebeleffekts besser beobachten knnen. Zum besseren Vergleich zwischen Vertex und Pixel Fog knnen Sie ber die V-Taste auf Vertex Fog, ber die V- + Shift-Taste auf Vertex Fog ohne Range-Based-Fog-Berechung, P-Taste auf Pixel Fog und N-Taste auf ohne Nebel umschalten. ber die Escape-Taste verlassen Sie das Programm.

Bild 2.54: Bildschirmfoto Nebel

Das Programm startet mit der Form_Load()-Routine. Am Anfang der Routine verzweigen wir in einige Subroutinen.
Private Sub Form_Load() InitDDraw

Kapitel 2 Direct3D

231

PrfeNebelModel InitD3D Licht RenderState MakeVertex

Die Subroutinen InitDDraw() sowie InitD3D() sind Ihnen bereits bekannt. Mit der Subroutine Licht() werden die Lichtquellen initialisiert und gesetzt. In der Subroutine RenderState() haben wir alle allgemeinen Direct3DDevice7.Set RenderState()-Aufrufe zusammengefasst. Dies dient vor allem der bersichtlichkeit. MakeVertex() ist eine Subroutine in der die Vertexe fr die verwendeten Polygone abgelegt wurden. Die PrfeNebelModel()-Subroutine ist eine Prfroutine. Sie berprft ob die aktuelle Grafikkarte Vertex- und / oder Pixel Fog darstellen kann. In ihr werden Indexvariabeln gesetzt, die ein spteres Einschalten des entsprechenden Nebelmodels zulassen.
CreateTextur CreateTextur CreateTextur CreateTextur 0, 1, 2, 3, App.Path App.Path App.Path App.Path & & & & "\mauer3.bmp" "\bholz03.bmp" "\arbpl19.bmp" "\bild36.bmp"

Die CreateTexture()-Subroutine kennen Sie bereits. Sie initialisiert und erstellt die verwendeten Texture Surfaces.
. . . Do If GetTickCount > TimerZeit + ZeitInterval Then

Mit dieser If...Then Abfrage lassen wir das Rendern nur alle 15 Millisekunden zu. Bei der Drehung des Betrachters am Ende und Anfang des Raums verkrzt sich die Zeit auf 1 Millisekunde.
If TimerStatus = True Then TimerIndex = TimerIndex + 0.05 If TimerIndex >= 14.8 Then If BlickRichtungWinkel > -90 Then ZeitInterval = 1 BlickRichtungWinkel = BlickRichtungWinkel 2 BlickrichtungX = 1 + 100 * _ Cos(BlickRichtungWinkel / 57.296) BlickrichtungZ = 14.8 + 100 * _ Sin(BlickRichtungWinkel /57.296) TimerIndex = 14.8 Else ZeitInterval = 15 TimerStatus = False

232

Effekte

End If End If Else TimerIndex = TimerIndex 0.05 If TimerIndex <= 0.2 Then If BlickRichtungWinkel < 90 Then ZeitInterval = 1 BlickRichtungWinkel = BlickRichtungWinkel + 2 BlickrichtungX = 1 + 100 * _ Cos(BlickRichtungWinkel / 57.296) BlickrichtungZ = 0.2 + 100 * _ Sin(BlickRichtungWinkel / 57.296) TimerIndex = 0.2 Else ZeitInterval = 15 TimerStatus = True End If End If End If g_dx.IdentityMatrix matView Call g_dx.ViewMatrix(matView, MakeVector(1, 0.2, TimerIndex), _ MakeVector(BlickrichtungX, BlickrichtungY, BlickrichtungZ), _ MakeVector(0, 1, 0), 0) g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView

Dieser Block ist fr die Bewegung und fr das Drehen des Betrachters zustndig. Beachten Sie, dass Sie jedes Mal, wenn sich die Position des Betrachters ndert, diese nderung in die Viewmatrix einflieen muss.
Dim Temp1 As D3DVECTOR Dim Temp2 As D3DVECTOR Dim Mitte As D3DVECTOR Mitte.z = 10 For i = 136 To 151 Select Case I Case 136, 137, 138, Mitte.x = 1.75 Mitte.z = 10 Case 140, 141, 142, Mitte.x = 0.25 Mitte.z = 5 Case 144, 145, 146, Mitte.x = 0.25 Mitte.z = 14 Case 148, 149, 150, Mitte.x = 1.75 Mitte.z = 1 End Select

139

143

147

151

Kapitel 2 Direct3D

233

Temp1.x = Vertex(i).x Temp1.y = Vertex(i).y Temp1.z = Vertex(i).z Rotation Temp1, Temp2, Mitte, 1 Vertex(i).x = Temp2.x Vertex(i).y = Temp2.y Vertex(i).z = Temp2.z Next i

Wir lassen die vier Anzeigetafeln im Raum rotieren. Hierzu manipulieren wir die Vertexdaten der entsprechenden Polygone.
. . . Loop Until GetAsyncKeyState(vbKeyEscape) <> 0 . . . End Sub

Die Aktivierung des Nebeleffekts wird von der Form_KeyDown()-Routine bernommen. Diese verzweigt in die Subroutinen SetupPixelFog() und SetupVertex Fog().
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case vbKeyV If Shift = 0 Then If VertexFogIndex = True Then SetupPixelFog RGB(200, 200, 200), _ D3DFOG_NONE, 0.3, 0, 10 SetupVertexFog RGB(200, 200, 200), D3DFOG_EXP, True, _ 0.3, 0,10 InfoText = "Vertex Fog / D3DFOG_EXP / Density -> 0.3" Else InfoText = _ "Ihre Grafikkarte untersttzt keinen Vertex Fog" End If Else If VertexFogIndex = True Then SetupPixelFog RGB(200, 200, 200), _ D3DFOG_NONE, 0.3, 0, 10 SetupVertexFog RGB(200, 200, 200), _ D3DFOG_EXP, False, 0.3, 0, 10

234

Effekte

InfoText = "Vertex Fog / D3DFOG_EXP / Density -> 0.3" Else InfoText = _ "Ihre Grafikkarte untersttzt keinen Vertex Fog" End If End If

Beim Drcken der V-Taste verzweigen wir in die eigenliche Vertex-Nebelroutine. Beachten Sie, dass wir den Pixel Fog vorher deaktivieren.
Case vbKeyN g_d3dDevice.SetRenderState D3DRENDERSTATE_FOGENABLE, False InfoText = "N O N E" Case vbKeyP If PixelFogIndex = True Then SetupVertexFog RGB(200, 200, 200), D3DFOG_NONE, False, _ 0.3, 0, 10 SetupPixelFog RGB(200, 200, 200), D3DFOG_EXP, 0.3, 0, 10 InfoText = "Pixel Fog / D3DFOG_EXP / Density -> 0.3" Else InfoText = _ "Ihre Grafikkarte untersttzt keinen Pixel Fog" End If

Beim Drcken der [P]-Taste verzweigen wir in die eigenliche Pixel-Nebelroutine. Beachten Sie, dass wir den Vertex Fog vorher deaktivieren.
End Select End Sub

Wir verwenden bei dem Einsatz von Vertex Fog und Pixel Fog die gleichen Parameter. Dies ermglicht es, genau zu vergleichen, wie sich die beiden Typen auf die Gestaltung der Szene auswirken. Sie sollten auf jeden Fall die Parameter der SetupPixelFog() und SetupVertexFog() Subroutinen mal verndern. So lernen Sie alle Varianten genau kennen. Nun kommen wir endlich zu den eigentlichen Subroutinen, welche fr die Darstellung der Nebeleffekte verantwortlich sind. Vertex Fog:
Sub SetupVertexFog(lColor As Long, Mode As CONST_D3DFOGMODE, _ bUseRange As Boolean, Optional Density As Single, _ Optional StartFog As Single, Optional EndFog As Single) g_d3dDevice.SetRenderState D3DRENDERSTATE_FOGENABLE, True g_d3dDevice.SetRenderState D3DRENDERSTATE_FOGCOLOR, lColor If Mode = D3DFOG_LINEAR Then g_d3dDevice.SetRenderState _ D3DRENDERSTATE_FOGVERTEXMODE, Mode

Kapitel 2 Direct3D

235

g_d3dDevice.SetRenderStateSingle _ D3DRENDERSTATE_FOGSTART, StartFog g_d3dDevice.SetRenderStateSingle _ D3DRENDERSTATE_FOGEND, EndFog Else g_d3dDevice.SetRenderState _ D3DRENDERSTATE_FOGVERTEXMODE, Mode g_d3dDevice.SetRenderStateSingle _ D3DRENDERSTATE_FOGDENSITY, Density End If If bUseRange = True Then g_d3dDevice.SetRenderState _ D3DRENDERSTATE_RANGEFOGENABLE, True Else g_d3dDevice.SetRenderState _ D3DRENDERSTATE_RANGEFOGENABLE, False End If End Sub

Pixel Fog:
Sub SetupPixelFog(lColor As Long, Mode As CONST_D3DFOGMODE, _ Optional Density As Single, Optional StartFog As Single, _ Optional EndFog As Single) g_d3dDevice.SetRenderState D3DRENDERSTATE_FOGENABLE, True g_d3dDevice.SetRenderState D3DRENDERSTATE_FOGCOLOR, lColor If Mode = D3DFOG_LINEAR Then g_d3dDevice.SetRenderState _ D3DRENDERSTATE_FOGTABLEMODE, Mode g_d3dDevice.SetRenderStateSingle _ D3DRENDERSTATE_FOGSTART, StartFog g_d3dDevice.SetRenderStateSingle _ D3DRENDERSTATE_FOGEND, EndFog Else g_d3dDevice.SetRenderState _ D3DRENDERSTATE_FOGTABLEMODE, Mode g_d3dDevice.SetRenderStateSingle _ D3DRENDERSTATE_FOGDENSITY, Density End If End Sub

Die MakeVertex()-Subroutine erfasst alle Vertexe, die wir zur Darstellung der Polygone bentigen.
Public Sub MakeVertex() 'Linke Wand

236

Effekte

g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex . . . 'drehendes Dreieck4 g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex g_dx.CreateD3DVertex

0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 1, 0, 1, 0, 1, 0, 1, 0,

0, 0, 1, 1, 2, 2, 3, 3, 4,

1, 1, 1, 1, 1, 1, 1, 1, 1,

0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 0, 0, 0, 0, 0, 0, 0,

0, 0, 1, 1, 2, 2, 3, 3, 4,

1, 0, 1, 0, 1, 0, 1, 0, 1,

Vertex(0) Vertex(1) Vertex(2) Vertex(3) Vertex(4) Vertex(5) Vertex(6) Vertex(7) Vertex(8)

1.5, 0.25, 1, -1, 0, -1, 0, 1, Vertex(148) 1.5, 0.75, 1, -1, 0, -1, 0, 0, Vertex(149) 2, 0.25, 1, -1, 0, -1, 1, 1, Vertex(150) 2, 0.75, 1, -1, 0, -1, 1, 0, Vertex(151)

Insgesamt definieren wir 152 Vertexe. Sie knnen sich leicht vorstellen, das eine Menge Arbeit auf einen zukommt, wenn die 3D-Welt komplexer wird. Letztendlich wird man an einem 3D-Editor mit entsprechender 3D-Engine nicht vorbeikommen. Schauen Sie sich doch einmal unseren mitgelieferten 3D-Editor an. Auf der CD finden Sie eine small Version, mit der Sie allerding schon einiges anstellen knnen. Durch den Kauf des Buches knnen Sie das Vollprodukt zu einem absoluten Sonderpreis von 69,-- DM erwerben. Der normale Verkaufspreis betrgt immerhin 129,-- DM.

2.13.2 Billboarding
Mit Billboarding ist Direct3D in Lage ein 2D-Objekt so zu rendern, dass es wie ein 3D-Objekt aussieht. Um diese Sinnestuschung zu verwirklichen, wird ein normales Polygon erzeugt. Auf das Polygon wird eine Textur gelegt. Das Polygon wird nun immer zum Betrachter ausgerichtet. Sie werden das Polygon also nie von der Seite sehen. Ein typisches Beispiel fr den Einsatz von Billboarding ist die Darstellung eines Baumes. Ein Baum mit seinen vielen sten und Blttern ist als 3D-Objekt nur mit sehr viel Mhe zu erstellen. Auerdem wre eine sehr hohe Anzahl von Polygonen notwendig. Das Auflegen einer Textur wre ebenfalls nicht einfach. Wenn wir Billboarding nutzen, knnen wir uns die Arbeit wesentlich erleichtern. Wir erstellen aus mehreren Dreiecken ein Rechteck. Auf das Rechteck legen wir eine Textur. Nun aktivieren wir den Farbschlssel, um alle nicht zum Baum gehrenden Bildpixel transparent zu rendern. Wenn wir das Rechteck immer auf den Betrachter ausrichten, wird der Baum dreidimensional wirken.

Kapitel 2 Direct3D

237

Natrlich wird der knstliche 3D-Baum nicht die gleichen Eigenschaften haben wie ein echter 3D-Baum. So ist es nicht mglich sich in den 3D-Raum des Baumes zu begeben. Der Baum selber wird etwas starr wirken. Als Kulisse einer Szene wird man diese Mankos nicht bemerken. Beispiel (Billboarding) Wir haben eine Bodenplatte mit insgesamt 2646 Vertexen erstellt. Zustzlich wurden vier Bume und ein Schild eingebunden. Das Schild wurde mit 486 Vertexen aufgelst. Die Bume bestehen aus je 4 Vertexen. Bei jedem Baum haben wir eine Pointlicht platziert. Bei der weien Lichtquelle befindet sich noch ein Spotlicht. Dieses ist auf das Schild gerichtet und enthlt nur speculare Lichtanteile. Dadurch erhalten wir ein Glanzlicht immer dann, wenn sich das Schild zu der weien Lichtquelle dreht. Mit der B-Taste knnen Sie Billboarding aktivieren. Die N-Taste deaktiviert Billboarding. Mit der Space-Taste knnen Sie den Text ein- oder ausblenden. Die Escape-Taste dient zum Verlassen des Programms.

Bild 2.55: Bildschirmfoto Billboarding

Die Technik von Billboarding: Die fnf Objekte auf der Bodenplatte sind einfache Polygone. Sie sind im Grunde unendlich dnn. Um Billboarding einzusetzen mssen wir dem Betrachter vorgaukeln, die Objekte wrden eine Tiefe besitzen. Dies ist nicht ganz einfach, denn

238

Effekte

jedes Mal wenn sich der Betrachter einem Objekt von der Seite nhert, wird er sofort erkennen, dass die Objekte keine Tiefe besitzen. Der Weg von Billboarding besteht darin, es einfach nicht zuzulassen, dass sich der Betrachter ein Objekt von der Seite betrachten kann. Wir mssen die Polygone bei jeder nderung von Position oder Blickrichtung des Betrachters immer wieder zum Betrachter ausrichten. Der Betracher wird das Objekt dann immer direkt von vorne sehen. Es ist ihm dadurch nicht mglich zu erkennen, wie dick das Objekt ist. Unser Beispiel beginnt mit der Form_Load()-Subroutine. Nach den blichen Initialisierungsroutinen geht es in die Do...Loop()-Schleife. Bevor wir die Objekte zum Betrachter ausrichten knnen, mssen wir die jeweiligen Winkel der Objekte zum Betrachter ermitteln.
Private Sub Form_Load() . . . Do If GetTickCount > TimerZeit + ZeitInterval Then w = w + 0.5: If w > 360 Then w = 0

Die Variable w ist eine Hilfsvariable. Mit ihr knnen wir uns kreisend ber die Bodenplatte bewegen.
g_dx.IdentityMatrix matView posx = 10 * Cos(w / 57.296) posz = (-15 * Sin(w / 57.296)) 10

Die Variablen posx und posz speichern die X- und Z-Koordinate des Betrachters. Seine Blickrichtung ist immer auf die Mitte der Bodenplatte gerichtet und wird auch nicht verndert.
baumwinkel1 baumwinkel2 baumwinkel3 baumwinkel4 baumwinkel5 = = = = = 360 360 360 360 360 (ATAN2(-5 posx, 5 posz) * 57.296) (ATAN2(5 posx, 5 posz) * 57.296) (ATAN2(-5 posx, -5 posz) * 57.296) (ATAN2(5 posx, -5 posz) * 57.296) (ATAN2(0 posx, 0 posz) * 57.296)

In den Variablen baumwinkel1 bis 5 speichern wir die Winkel der Objekte (auf der Bodenplatte) zum Betrachter. Die Subroutine ATAN2() ist dabei sehr ntzlich.
Dim DestVect As D3DVECTOR If Billboard = True Then For i = 0 To 502 Select Case I Case 0 To 3 Rotation MakeVector(Vertex(i).X, Vertex(i).Y, _ Vertex(i).z), DestVect, MakeVector(-5, 0, 5), baumwinkel1 TempVertex(i).X = DestVect.X

Kapitel 2 Direct3D

239

TempVertex(i).Y = DestVect.Y TempVertex(i).z = DestVect.z Case 4 To 7 Rotation MakeVector(Vertex(i).X, Vertex(i).Y, _ Vertex(i).z), DestVect, MakeVector(5, 0, 5), baumwinkel2 TempVertex(i).X = DestVect.X TempVertex(i).Y = DestVect.Y TempVertex(i).z = DestVect.z

An dieser Stelle manipulieren wir die Vertexdaten der platzierten Objekte. Sie werden immer in Richtung des Betrachters gedreht. Das ist eigentlich schon der gesamte Trick von Billboarding. Beachten Sie bitte, dass wir die manipulierten Vertexdaten an die temporre Vertexvariable TempVertex(i) bergeben. Somit bleiben die Originaldaten der Objekte erhalten.
. . . Case 16 To 502 Rotation MakeVector(Vertex(i).X, Vertex(i).Y, _ Vertex(i).z), DestVect, MakeVector(0, 0, 0), baumwinkel5 TempVertex(i).X = DestVect.X TempVertex(i).Y = DestVect.Y TempVertex(i).z = DestVect.z TempVertex(i).nx = -1 * Sin((360 baumwinkel5) / 57.296) TempVertex(i).nz = -1 * Cos((360 baumwinkel5) / 57.296) TempVertex(i).ny = 0

In diesem Teil der Select-Case-Abfrage manipulieren wir die Vertexe von dem Schild in der Mitte. Das Besondere an dieser Manipulation ist, dass wir nicht nur die x-, y-, z-Eintrge verndern, sondern auch eine Anpassung an den nx- und nzEintrgen vornehmen. Diese beschreiben die Ausrichtung des Normalvektors eines Vertex. Indem wir den Normalvektor immer senkrecht (nach vorne blickend) zum Schild ausrichten, kann das Schild die verschiedenen Lichtquellen reflektieren. Dadurch wirken die Lichtverhltnisse sehr viel realistischer.
End Select Next i . . . End Sub

Werfen Sie doch vielleicht noch einen Blick in die Subroutine Licht(). Als Lichtquelle fnf legen wir die Parameter fr das Spotlicht fest. Interessant ist, dass wir nur speculare Lichtanteile zuweisen. Diese Lichtquelle dient also ausschlielich zum Erzeugen von Glanzlichtern. Natrlich muss das verwendete Material entsprechende Specularanteile beinhalten und die Specularreflexion ber die SetRenderState()-Methode aktiviert sein.

240

Effekte

Direct3DDevice7.SetRenderState _ D3DRENDERSTATE_SPECULARENABLE, True

Ansonsten ist ein Glanzlichteffekt unmglich.


Public Sub Licht() . . . With Licht_5 .specular = Farbe_2 .range = 10 .attenuation0 = 0.8 .dltType = D3DLIGHT_SPOT .position.X = 5 .position.Y = 3 .position.z = 5 wi = 225 .direction.X = Cos(wi / 57.296) 0.3 .direction.Y = 0.1 .direction.z = Sin(wi / 57.296) .phi = 20 / 57.296 .theta = 2 / 57.296 .falloff = 2 End With . . . End Sub

2.13.3 Feuer und Explosionen


Feuer und Explosionen sind mit der Technik zur animierten Darstellung von Sprites (Abschnitt DirectDraw) fast identisch. berlegen wir uns einmal, was wir fr die Darstellung einer Flamme bentigen. Zunchst stellen wir fest, dass eine Flamme als normale Textursurface in D3D eingebunden wird. Dennoch unterscheidet sie sich von der Darstellung von z.B. einer Mauer. Die Mauer verndert ihr Erscheinungsbild nicht. Im Gegensatz dazu wird eine Flamme pulsieren. Sie wird stndig kleiner, grer, heller, breiter oder verndert die Farbe. Wir bentigen also eine animierte Flamme. Abbildung 2.56 zeigt eine Flamme mit 32 Einzelbildern. Zur Darstellung der Flamme in der 3D-Welt werden wir nun nacheinander die einzelnen Flammen ausschneiden und auf die passende Textursurface kopieren (blitten). Das verhlt sich genauso wie bei der animierten Spritedarstellung.

Kapitel 2 Direct3D

241

Bild 2.56: Animierte Flamme

Um die Flamme realistisch erscheinen zu lassen, werden wir die Flamme etwas transparent darstellen. Damit nur die Elemente der Flamme auf dem Bildschirm sichtbar sind, werden wir den Hintergrund mit Hilfe des Farbschlssels herausfiltern. Fassen wir die Aufgaben zusammen: Einschalten der RenderStates fr Transparenz und Aktivieren des Farbschlssels um den Hintergrund der Flamme zu entfernen. Wir erzeugen eine Textursurface, welche die gesamte animierte Flamme enthlt (Textursurface 1). Wir erzeugen eine Textursurface, welche die Dimension einer einzelnen Flamme hat. Diese ist zum Anfang noch leer (Textursurface 2). Wir erzeugen ein Polygon (blicherweise ein Rechteck), welchem wir die leere Textursurface zuweisen. Wir kopieren die erste Flamme von Textursurface 1 auf Textursurface 2. Da Textursurface 2 bereits einem Polygon in der 3D-Welt zugeordnet ist, wird die Flamme beim nchsten Zeichnen der Szene dargestellt. Vor dem nchsten Rendern der Szene kopieren wir die zweite Flamme von Textursurface 1 auf Textursurface 2. Diese wird bei dem folgenden Rendern dargestellt. Wir wiederholen Schritt 5, bis alle Flammen einmal dargestellt wurden. Anschlieend fangen wir wieder bei der ersten Flamme an. Explosionen werden mit der gleichen Technik realisiert. Programmtechnisch werden Explosionen durch ein Ereignis ausgelst. Bei der Explosion lassen Sie die Animationsfolge nur einmal durchlaufen.

242

Effekte

Wenn Sie eine Flamme oder Explosion nicht direkt an einer Wand platzieren, sondern frei im Raum, so sollten Sie die Billboardingtechnik noch einsetzen. Ansonsten wird es vorkommen, dass Sie die Textur von der Seite betrachten und diese ist dann natrlich unendlich dnn. Beispiel (Feuer) Unser Feuerdemo baut auf dem Demoprogramm der Billboardingtechnik auf. Wiederum haben wir eine drehende Bodenplatte. Auf der Bodenplatte haben wir vier Fackelflammen platziert. Bei jeder Fackel befinden sich zwei Lichtquellen. Die eine Lichtquelle strahlt ein gelbes Licht, die andere strahlt ein rotes Licht. Die Intensitt der Lichtquellen wird per Zufall ermittelt. Dadurch erhalten wir realistisches Fackellicht. An einer Flamme haben wir einen virtuellen Scheinwerfer platziert. Das erzeugte Spotlight erzeugt das Glanzlicht auf dem Schild in der Mitte. Diese ist nur in einem bestimmten Winkelbereich zu sehen. Die Normalvektoren des Schildes richten wir immer zum Betrachter, dadurch haben wir eine natrliche Reflexion der Flammen auf dem Schild.

Bild 2.57: Bildschirmfoto Feuer

Kapitel 2 Direct3D

243

Mit der B-Taste knnen Sie Billboarding aktivieren. Mit der N-Taste deaktivieren Sie Billboarding. Die Escape-Taste dient zum Verlassen des Progamms. Alles beginnt mit der Form_Load()-Subroutine.
Private Sub Form_Load() . . . CreateTextur 1, False, App.Path & "\bholz03.bmp"

TextureSurf(1) benutzen wir fr die Textur der Bodenplatte.


CreateTextur 3, False, App.Path & "\logo.bmp"

TextureSurf(3) wird fr die Darstellung des Schilds bentigt.


CreateTextur 4, False, App.Path & "\feuer.bmp"

Die vierte Textursurface enthlt die gesamte Bildreihe der Flamme. Aus ihr werden wir spter die bentigten Teile herauskopieren und an TextureSurf(2) bergeben. Auf der Flammenbitmap befinden sich vier Reihen mit jeweils acht Spalten. Die Breite der Bitmap betrt 256 Pixel, die Hhe betrgt 256 Pixel. Somit ergibt sich fr die einzelne Flamme eine Breite von 32 Pixeln und eine Hhe von 64 Pixeln.
CreateTextur 2, True, ""

Die TextureSurf(2) wird als leere Surface erstellt. Entsprechend der Animationsfolge wird sie mit Bitmapdaten von der TextureSurf(4) gefllt.
. . . Feuer

Die Subroutine Feuer() kopiert den richtigen Ausschnitt von TextureSurf(4) auf TextureSurf(2). Das werden wir uns noch genauer anschauen.
Licht

Wir wollen ein Flackerlicht erzeugen. Dazu ist es notwendig die Lichtparmeter permanent zu ndern. Anschlieend mssen diese nderungen Direct3D mitgeteilt werden. Dies bernimmt die Subroutine Licht().
. . . g_d3dDevice.SetTexture 0, TextureSurf(2) g_d3dDevice.SetRenderState D3DRENDERSTATE_DESTBLEND, _ D3DBLEND_ONE

244

Effekte

g_d3dDevice.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, _ True

Bevor wir die Flammen rendern, aktivieren wir die Alpahtransparenz. Zum Mischen der Textur verwenden wir den Mischmodus D3DBLEND_ONE. Dieser ist von den Alphawerten des Materials nicht abhngig und erzeugt eine fr die Flammen gute Transparenz.
g_d3dDevice.SetMaterial Material(DXColor(1, 1, 1, 1), _ DXColor(1, 1, 1, 1), DXColor(1, 1, 1, 1), _ DXColor(1, 1, 1, 1), 0.1, 0) g_d3dDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, TempVertex(0), 4, D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, TempVertex(4), 4, D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, TempVertex(8), 4, D3DDP_WAIT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX, TempVertex(12), 4, D3DDP_WAIT g_d3dDevice.SetRenderState D3DRENDERSTATE_ALPHABLENDENABLE, _ False

_ _ _ _

Nachdem wir die vier Flammen gerendert haben, deaktivieren wir die Alphatransparenz. Ansonsten wrden beim nchsten Renderdurchlauf die Bodenplatte sowie das Schild ebenfalls transparent dargestellt. Da liegt natrlich nicht in unserer Absicht. Vielleicht ist Ihnen aufgefallen, dass wir im Vergleich zu dem Billboardingdemo die Renderreihenfolge der Polygone umgestellt haben. Die Flammen werden als Letztes gerendert. Da die Flammen transparent sein sollen, mssen wir sie mit dem Hintergrund mischen. Wrden wir die Flammen z.B. vor dem Schild rendern so knnte die Transparenz zum Schild nicht berechnet werden. Das Schild wrde ja noch gar nicht existieren, also knnte sich auch nichts mischen.
. . . End Sub

Bevor wir uns die Subroutine Feuer() betrachten, betrachten wir die CreateTexture()-Subroutine. Diese wurde von uns etwas modifiziert, sodass wir auch Textursurfaces ohne Textur erstellen knnen. Auerdem legen wir fest, ob auf die zu erstellende Textursurface der Farbschlssel angewendet werden soll.
Private Sub CreateTextur(ByVal Index As Integer, ColorKey As _ Boolean, sFile As String) Dim ddsd3 As DDSURFACEDESC2 Dim TextureEnum As Direct3DenumPixelFormats Set TextureEnum = g_d3dDevice.GetTextureFormatsEnum()

Kapitel 2 Direct3D

245

TextureEnum.GetItem 1, ddsd3.ddpfPixelFormat If sFile <> "" Then ddsd3.ddsCaps.lCaps = DDSCAPS_TEXTURE Set TextureSurf(Index) = g_dd.CreateSurfaceFromFile(sFile, _ ddsd3)

Bis hierher ist Ihnen die Routine bekannt.


Else ddsd3.lFlags = DDSD_WIDTH Or DDSD_HEIGHT ddsd3.lHeight = 64 ddsd3.lWidth = 32 ddsd3.ddsCaps.lCaps = DDSCAPS_TEXTURE Set TextureSurf(Index) = g_dd.CreateSurface(ddsd3)

In diesem Teil erstellen wir eine Textursurface, ohne gleichzeitig eine Textur von der Festplatte zu laden. Die Dimensionen der Textur legen wir mit den Parametern lHeight und lWidth fest. Sie entsprechen in unserem Beispielprogramm genau den Dimensionen einer einzelnen Flamme.
End If Dim ck As DDCOLORKEY If ColorKey = True Then TextureSurf(Index).SetColorKey _ DDCKEY_SRCBLT, ck End Sub

Nun kommen wir endlich zum Kernstck des Feuertricks. Die Subroutine Feuer() sorgt fr die Animation der Flammen. Die Variablen CelX und CelY sind global dimensioniert worden. Mit ihnen bewegen wir uns auf der TextureSurf(2) so, dass sie die Koordinaten fr die linke obere Ecke einer Rechtstruktur festlegen.
Public Sub Feuer() If g_dx.TickCount > FeuerZeit + 40 Then FeuerZeit = g_dx.TickCount CelX = CelX + 1 If CelX > 7 Then CelX = 0 CelY = CelY + 1 End If If CelY > 3 Then CelX = 0 CelY = 0 End If Dim Rect1 As RECT Dim Rect2 As RECT Rect1.Left = CelX * 32 Rect1.Right = Rect1.Left + 32 Rect1.Top = CelY * 64 Rect1.Bottom = Rect1.Top + 64

246

Effekte

Da wir die Breite und Hhe der einzelnen Flamme kennen, ist es ein Kinderspiel, die gesamte RECT-Struktur zu fllen. Innerhalb dieser Struktur befindet sich immer eine einzelne Flamme.
TextureSurf(2).Blt Rect2, TextureSurf(4), Rect1, DDBLT_WAIT

Zum Abschluss brauchen wird nur noch die Flamme auf die TextureSurf(2) blitten. Diese wird beim Rendern der Flammen verwendet.
End If End Sub

2.13.4 Antialiasing
Antialiasing ist eine Technik um die Treppenbildung von Linien zu reduzieren. Linien, welche nicht hundertprozentig horizontal oder vertikal verlaufen, werden immer als Treppe dargestellt. Die Ausprgung der Treppe ist von der verwendeten Auflsung abhngig. Mit eingeschaltetem Antialiasing wird zwischen der Linie und dem Hintergrund eine Mischfarbe erstellt. Da diese im Prinzip von Linienfarbe und Hintergrundfarbe einen gewissen Anteil enthlt, wirkt der bergang viel weicher und die Kanten sind nicht mehr deutlich zu erkennen. Antialiasing knnte man nur einen Nachteil vorwerfen. Die Bildschrfe nimmt ab. Alles wirkt ein wenig verwischt. Besonders in Szenen, in denen eine Kantenschrfe zur Gesamtstimmung gehrt, erweist sich Antialiasing als nachteilig.

Bild 2.58: Antialiasing

Direct3D untersttzt zwei Antialiasing-Techniken: Kanten-Antialiasing und Fullscreen-Antialiasing. Welche Technik die geeignete ist, hngt im Wesentlichen von der verfgbaren Performance ab.

Kapitel 2 Direct3D

247

Leider untersttzen lngst nicht alle Grafikkarten Antialiasing. Fr moderne Grafikkarten gehrt dieses Merkmal zum Pflichtteil. Dennoch sollten Sie die Grafikkarte zuvor prfen. Prfung der Grafikkarte auf Antialiasing Zur Prfung der Grafikkarte benutzen wir die Direct3DDevice7.GetCaps()Methode. Untersttzt die Grafikkarte Kanten-Antialiasing finden wir das notwendigen Flag in den Mitgliedsdaten IRasterCaps des D3DprimCaps-TypenArrays.
Dim PrimCaps As D3DDEVICEDESC7 g_d3dDevice.GetCaps PrimCaps If (PrimCaps.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_ANTIALIASEDGES) = _ D3DPRASTERCAPS_ANTIALIASEDGES Then

Ist das Flag vorhanden, so wird die If...Then-Abfrage mit True beantwortet.
End If

Bei der Prfung auf Fullscreen-Antialiasing fragen wir die Sortierart fr Fullscreen-Antialiasing ab. Wir suchen nach den Flags D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT und D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT. Sind beide Flags nicht vorhanden, so wird FullscreenAntialiasing nicht untersttzt. Sortierter Aufbau der Polygone von hinten nach vorne:
Dim PrimCaps As D3DDEVICEDESC7 g_d3dDevice.GetCaps PrimCaps If (PrimCaps.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT) = _ D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT Then

Ist das Flag vorhanden, so wird die If...Then-Abfrage mit True beantwortet.
End If

Unsortierter Aufbau der Polygone:


Dim PrimCaps As D3DDEVICEDESC7 g_d3dDevice.GetCaps PrimCaps If (PrimCaps.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) = _ D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT Then

Ist das Flag vorhanden, so wird die If...Then-Abfrage mit True beantwortet.
End If

248

Effekte

Kanten-Antialiasing Mit der Kanten-Antialiasing-Technik rendern Sie die Szene wie gewohnt. Anschlieend mssen Sie die Umrisse der Objekte mit eingeschaltetem KantenAntialiasing nochmals rendern. Dabei werden die beiden Linien miteinander verwischt. Durch das Verwischen der Linien sind die einzelnen Treppen nicht mehr klar zu erkennen. Sie sind immer noch vorhanden, wirken aber sehr viel weicher und somit realistischer. Beim zweiten Rendern der Szene benutzen Sie ebenfalls die Direct3DDevice7.DrawPrimitive()-Methode. Diesmal setzen Sie allerdings die Parameter D3DPT_LINESTRIP oder D3DPT_LINELIST. Welchen Parameter Sie nutzen, ist natrlich von dem ersten DrawPrimitive()Aufruf abhngig. Bei diesem stehen Ihnen die Parameter D3DPT_TRIANG LESTRIP und D3DPT_TRIANGLELIST zur Verfgung.

Aktivieren von Kanten-Antialiasing: Kanten-Antialiasing aktivieren Sie, indem Sie den zweiten Parameter der SetRenderState()-Methode auf ungleich 0 setzen.
Direct3DDevice7.SetRenderState D3DRENDERSTATE_EDGEANTIALIAS, 1

Deaktivieren von Kanten-Antialiasing: Wenn Sie den Renderstate-Parameter der SetRenderState()-Methode auf 0 setzen deaktivieren Sie den Kanten-Antialiasing-Modus.
Direct3DDevice7.SetRenderState D3DRENDERSTATE_EDGEANTIALIAS, 0

Fullscreen-Antialiasing Fullscreen-Antialiasing verwischt die Kanten aller Polygone in einer Szene. Im Gegensatz zum Kanten-Antialiasing muss die Szene nicht zweimal gerendert werden. Diese Technik zeigt ihre Wirkung nur bei Dreiecken oder Gruppen von Dreiecken. Einzelnen Linien beleiben unberhrt. Einige Grafikkarten sind nur in der Lage, Fullscreen-Antialiasing einzusetzen, wenn die Szene von hinten nach vorne aufgebaut wird. Bei der Prfung der Grafikkarte auf die Untersttzung von Antialiasing-Techniken haben wir bereits gezeigt, wie Sie die Fhigkeit der aktuellen Grafikkarte abfragen. Das Ergebnis dieser Prfung entscheidet, wie die notwendige Direct3DDevice7.SetRenderState()-Methode aufgerufen werden muss.

Zum Aktivieren des Fullscreen-Antialiasing-Modus bestehen somit zwei Alternativen: sortiert:


Direct3DDevice7.SetRenderState D3DRENDERSTATE_ANTIALIAS, _ D3DANTIALIAS_SORTDEPENDENT

Kapitel 2 Direct3D

249

unsortiert:
Direct3DDevice7.SetRenderState D3DRENDERSTATE_ANTIALIAS, _ D3DANTIALIAS_SORTINDEPENDENT

Zum Deaktivieren des Fullscreen-Antialiasing-Modus whlen Sie folgenden Aufruf:


Direct3DDevice7.SetRenderState D3DRENDERSTATE_ANTIALIAS, _ D3DANTIALIAS_NONE

Antialiasing ist eine feine Technik, um eine Szene wesentlich realistischer darzustellen. Die unangenehme Treppenbildung bleibt aus. Besonders beim FullscreenAntialiasing wird die Bildung von Artefakten gemindert. Leider bentigt diese Technik viel Rechenzeit. Einige moderne Grafikkarten knnen Antialiasing allerding fast ohne Performanceverluste einbinden. Manchmal wird dies auf Kosten der Qualitt verwirklicht. Einen kleinen Performancetrick haben wir aber noch fr Sie. Beim Erstellen der Render Surface (im Regelfall ist das die Backbuffer Surface) sollen Sie das DDSCAPS_HINTANTIALIASING-Flag setzten. Einige Grafikkarten verlangen dieses Flag, ansonsten wird Antialiasing ohne Erfolg bleiben. Die genaue Initialisierung der Surface knnen Sie sich in unserem Antialiasing-Beispiel anschauen.
Dim ddsd2 As DDSURFACEDESC2 ddsd2.lFlags = DDSD_BACKBUFFERCOUNT Or DDSD_CAPS ddsd2.ddsCaps.lCaps2 = DDSCAPS2_HINTANTIALIASING ddsd2.ddsCaps.lCaps = DDSCAPS_COMPLEX Or DDSCAPS_FLIP Or _ DDSCAPS_PRIMARYSURFACE Or DDSCAPS_3DDEVICE Or _ DDSCAPS_SYSTEMMEMORY ddsd2.lBackBufferCount = 1 Set g_ddsPrimary = g_dd.CreateSurface(ddsd2)

Noch ein Hinweis: Antialiasing knnen Sie beim Aufbau einer Szene ein- und ausschalten. Sie knnen also die Objekte, bei denen sich Anitaliasing positiv bemerkbar macht, mit eingeschaltetem Antialiasing rendern und die brigen mit ausgeschaltetem Antialiasing. Nicht zuletzt knnen Sie mit dem Ein- und Ausschalten auch Rechenzeit sparen. Beispiel (Antialiasing) Dieses Beispiel zeigt zwei Dreiecke. Das linke Dreieck wurde mit Antialiasing gerendert. An der Diagonalen des Dreiecks kommen die Auswirkungen von Antialiasing besonders gut zur Wirkung. Leider haben wir festgestellt, dass weitaus weniger Grafikkarten diese feine Technik untersttzen. Einige Grafikkarten, welche Antialiasing anbieten, arbeiten offensichtlich mit einem minderwertigen Algorithmus. Dadurch sind die Auswirkungen von Antialisasing kaum wahrzunehmen. Aus diesem Grund haben wir uns entschlossen, dieses Beispielprogramm nicht im HAL oder RGB (Hardware- oder Software-Emulation) zu betrei-

250

Effekte

ben, sondern whlen den Referenz Rasterizer. Dieser Modus von Direct3D ist ein Testmodus. Fr den praktischen Einsatz ist er allerdings ungeeignet. Zur Demonstration von Antialiasing ist er dennoch geeignet. Das Beispielprogramm beginnt mit der Form_Load()-Subroutine. Da wir den Referenz Rasterizer nutzen, haben sich die Initialisierungsroutinen InitDDraw() und InitD3D() gendert. In der InitDDraw() erstellen wir das DirectDraw-Objekt im Software-Emulations-Modus. Alle Surfaces werden nicht im Videospeicher der Grafikkarte, sondern im Systemspeicher erstellt. Beim Erstellen des D3D-Device whlen wir die Auswahl IID_IDirect 3DREFDevice. Somit ist der Referenz Rasterizer zugeordnet und alle Renderaufgaben laufen ber ihn. Als Nchstes prfen wir den Referenz Rasterizer auf seine Anitaliasing-Fhigkeiten. Dies bernimmt die AnitaliasingPrfen() Subroutine.
Public Sub AntialiasingPrfen() Dim AntialiasingMode As D3DDEVICEDESC7 g_d3dDevice.GetCaps AntialiasingMode If (AntialiasingMode.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_ANTIALIASEDGES) = _ D3DPRASTERCAPS_ANTIALIASEDGES Then EdgeAntialiasing = "TRUE" Else EdgeAntialiasing = "FALSE" End If

Prfung auf Kanten-Antialiasing.


If (AntialiasingMode.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT) = _ D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT Then UnsortAntialiasing = "TRUE" Else UnsortAntialiasing = "FALSE" End If

Prfung auf unsortiertes Fullscreen-Antialiasing.


If (AntialiasingMode.dpcTriCaps.lRasterCaps And _ D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT) = _ D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT Then SortAntialiasing = "TRUE" Else SortAntialiasing = "FALSE" End If

Prfung auf sortiertes Fullscreen-Antialiasing.

Kapitel 2 Direct3D

251

End Sub

Je nachdem welche Prfung erfolgreich ist, wird eine Infotext gespeichert. Dieser wird in der Do...Loop()-Schleife aus der Form_Load()-Subroutine auf dem Bildschirm angezeigt. Das eigentliche Aktivieren des Antialiasing Modes finden wir beim Rendern der Szene.
g_d3dDevice.BeginScene g_d3dDevice.SetRenderState D3DRENDERSTATE_ANTIALIAS, _ D3DANTIALIAS_SORTINDEPENDENT g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(0), 3, D3DDP_WAIT

Das linke Dreieck wird mit eingeschaltetem Antialiasing gerendert.


g_d3dDevice.SetRenderState D3DRENDERSTATE_ANTIALIAS, _ D3DANTIALIAS_NONE

Bevor wir das rechte Dreieck rendern, deaktivieren wir den Antialiasing Mode.
g_d3dDevice.DrawPrimitive D3DPT_TRIANGLELIST, _ D3DFVF_VERTEX, Vertex(3), 3, D3DDP_WAIT g_d3dDevice.EndScene

Kapitel 3
DirectInput
3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 Objekthierarchie Cooperative Level Datenformat Beispiel: Tastatur Beispiel: Joystick Beispiel: Maus Beispiel: DirectInput und Direct3D Bewegung im 3D-Raum 254 257 258 260 262 268 272 279

254

Objekthierarchie

DirectInput (DI) ist eine API fr Eingabegerte. Durch die Bereitstellung allgemeiner Device Interfaces bietet DirectInput die Sicherheit, auch in der Zukunft auf eine Vielzahl von Gerten zugreifen zu knnen, deren technische Mglichkeiten heute noch nicht definiert sind. DirectInput unterscheidet drei Typen von I/OGerten. Standard-System-Tastatur Maus oder maushnliche Gerte (Maus, Trackball, Touchpad ...) Joysticks bzw alle brigen Gerte (Joystick, Gamepad, Lenkrder...)

Die normale Windows API bietet eine Reihe von unterstzenden Methoden zur Steuerung von I/O-Gerten, dennoch werden diese durch DirectInput ersetzt. Dies hat zum einen den Grund, dass mit DI eine freie (fr die Zukunft offene) Schnittstelle geschaffen wurde, zum anderen wurde die Geschwindigkeit der bestehenden Technik problematisch. Der Grundkonzeption von DirectX entsprechend, wurde auch bei den Eingabegerten Wert auf hohe Performance gelegt. Natrlich finden wir auch bei DI einen direkten Zugriff auf die Hardware. Dabei wird das bliche Nachrichtensystem von Windows ignoriert. Dies garantiert quasi eine schnelle Reaktionszeit. Das Verhalten von DirectInput ist vom Programmierer konfigurierbar. Je nach Einsatzzweck wird er unterschiedliche Konfigurationen festlegen.

3.1

Objekthierarchie
DirectInput Interface Das DirectInput Interface stellt die erste Verbindung zum I/O Gert her. Es dient zur Konfiguration und Initialisierung. Devices Mit DirectInput Device werden die Ein- / Ausgabegerte bezeichnet. Diese Objekte (Maus, Tastatur, Joystick...) bestehen aus verschiedenen Objekten. Objekte Objekte sind die Bestandteile eines Devices. Objekte knnen Tasten, Knpfe, Achsen, Drehrder ... sein. Effekte Neben den Objekten existieren noch die Effekte. Effekte finden vor allem bei neueren Gerten Verwendung. Insbesondere sei der Force Feedback Joystick genannt.

Die verschiedenen Bestandteile der DirectInput Architekture erfassen im Regelfall Daten. Dabei ist es ohne Bedeutung, wie die Daten erfasst wurden. Ob eine Maus die Koordinaten mechanisch per Kugel und Zahnrad oder optisch an DirectInput weiterleitet spielt keine Rolle. Betrachten wir die Architektur an einem Beispiel, so wrden wir eine einfache Maus folgendermaen skizzieren.

Kapitel 3 DirectInput

255

Bild 3.1:

Objekthierarchie

Device Objekte

Maus zwei Tasten zwei Achsen (X- und Y-Achse)

Effekte

keine

Auflisten der verfgbaren Gerte und Objekte Anhand eines Beispielprogramms werden wir demonstrieren, wie Sie Informationen ber die angeschlossene Inputhardware sammeln. Diese Informationen bilden die Grundlage fr alle spteren Aktionen. Anders als bei Direct3D oder DirectDraw knnen die Inputgerte von DirectX nicht simuliert werden. Unser Beispielprogramm erkennt alle eingetragenen I/O-Gerte. Die Gerte mssen nicht angeschlossen sein, es reicht wenn die Gerte von Windows als I/OGerte registriert wurden. So knnen Sie z.B. ber die Systemsteuerung/Gamecontroller weitere Joysticks eintragen. Diese werden dann ebenfalls mit aufgelistet. Beginnen wir mit den Dimensionierungen.
Dim Dim Dim Dim Dim dx As New DirectX7 di As DirectInput diDEV As DirectInputDevice diEnumDev As DirectInputEnumDevices diEnumOBJ As DirectInputEnumDeviceObjects

Um auf die Gerteliste sowie auf die Objektliste zugreifen zu knnen, bentigen wir die Variablen vom Typ DirectInputEnumDevices und DirectInputEnum DeviceObjects. Diese werden die gewnschten Informationen beinhalten. Wir beginnen mit der Form_Load()-Subroutine.

256

Objekthierarchie

Bild 3.2:

Gerteliste

Private Sub Form_Load() Set di = dx.DirectInputCreate()

Zuerst bentigen wir das DirectInput-Objekt. Dieses erzeugen wir mit der DirectX7.DirectInputCreate() Methode. Diese Methode besitzt keine Parameter.
Set diEnumDev = di.GetDIEnumDevices(0 , DIEDFL_INCLUDEPHANTOMS)

Mit der DirectInput.GetDiEnumDevices() Methode weisen wir das DirectInput EnumDevices Objekt zu. Der erste Parameter ist vom Typ CONST_DIDEVICE TYPE, der zweite Parameter ist ein Flag aus der CONST_DIENUMDEVICES FLAGS Konstantenliste. Indem wir den ersten Parameter einfach auf 0 setzten, werden uns spter alle Gerte (Maus, Tastatur, Joystick ...) aufgelistet werden. Das Flag DIEDFL_INCLUDEPHANTOMS des zweiten Parameters sorgt dafr, dass auch die Gerte aufglistet werden, welche zurzeit nicht angeschlossen sind.

Kapitel 3 DirectInput

257

DeviceCount = diEnumDev.GetCount() For i = 1 To DeviceCount Set diDEV = _ di.CreateDevice(diEnumDev.GetItem(i).GetGuidInstance) Combo1.AddItem (diEnumDev.GetItem(i).GetProductName)

Der Reihe nach werden alle gefundenen Gerte mit der DirectInput.Create Device()-Methode erzeugt und die Namen der Gerte ausgelesen.
Next i Combo1.Text = Combo1.List(0) Listen 1 End Sub

Mit der Subroutine Listen() aktualisieren wir die Listboxen auf Form1. Wiederum zustzlich zu dem Device erzeugen wir noch das DirectInput-Objekt. In diesem Objekt finden wir Informationen ber das Gert selber. Diese bertragen wir an die jeweiligen Listboxen.
Public Sub Listen(Index As Integer) List1.Clear List2.Clear Set diDEV = _ di.CreateDevice(diEnumDev.GetItem(Index).GetGuidInstance) DeviceCount = diEnumDev.GetCount() List1.AddItem "ProductName :" & _ (diEnumDev.GetItem(Index).GetProductName) List1.AddItem "InstanceName :" & _ (diEnumDev.GetItem(Index).GetInstanceName) List1.AddItem "GuidInstance :" & _ (diEnumDev.GetItem(Index).GetGuidInstance) List1.AddItem "GuidProduct :" & _ (diEnumDev.GetItem(Index).GetGuidProduct) Set diEnumOBJ = diDEV.GetDeviceObjectsEnum(DIDFT_ALL) ObjectCount = diEnumOBJ.GetCount() For u = 1 To ObjectCount List2.AddItem (diEnumOBJ.GetItem(u).GetName) Next u End Sub

3.2

Cooperative Level
Der Cooperative Level bestimmt, wie ein Gert mit anderen Anwendungen oder dem Windowssystem geteilt wird. Fr den Zugriff auf einzelnen I/O-Gerte stehen eine gewisse Zahl von Cooperative Levels zur Wahl. Die korrekte Festlegung des Cooperative Levels kann einige Probleme beim Umgang mit DirectX-Anwendungen in Windows vermeiden helfen.

258

Datenformat

Werden z.B. die I/O-Gerte nur abgefragt, wenn sich die Anwendung im Vordergrund befindet, kann es passieren (falls die Anwendung den Fokus verliert), dass eine gestartete Aktion beim Loslassen einer Taste nicht beendet wird. Die mglichen Cooperative Levels sind:
Cooperativ Level DISCL_NONEXCLUSIVE DISCL_EXCLUSIVE DISCL_FORDERGROUND DISCL_BACKGROUND Kurzbeschreibung Die Anwendung erhlt den Zugriff auf das Gert nicht exklusiv (zwingend fr die Tastatur). Andere Anwendungen knnen nicht exklusiv auf das Gert zugreifen (zwingend fr Force Feedback). Die Anwendung erhlt nur Daten, wenn sie sich im Vordergrund befindet. Die Anwendung erhlt Daten im Vordergund und Hintergrund.

Die folgende Tabelle gibt an, welche Kombinationen fr welche I/O-Gerte zulssig sind.
Cooperative Level DISCL_NONEXCLUSIVE DISCL_BACKGROUND DISCL_NONEXCLUSIVE DISCL_FORDERGROUND DISCL_EXCLUSIVE DISCL_FORDERGROUND DISCL_EXCLUSIVE DISCL_BACKGROUND Kurzbeschreibung alle Gerte ohne Force Feedback Default alle Gerte ohne Force Feedback alle auer Tastatur Joysticks sowie Gerte mit Force Feedback nicht zulssig fr Tastatur und Maus

Wenn eine Anwendung den exklusiven Zugriff auf die Tastatur erhlt, unterdrckt DirectInput alle Tastaturnachrichten auer [Strg]+[Alt]+[Del] sowie [Alt)+ [].

3.3

Datenformat
Um gegenber neuen Entwicklungen offen zu sein, bietet DirectInput eine sehr allgemeine Mglichkeit um auf die Hardware zuzugreifen. So existieren weitreichende Mglichkeiten zur Erstellung selbstdefinierter Datenformate. Fr die normalen I/O-Gerte existieren bereits vordefinierte Datenformate. Diese knnen Sie der folgenden Tabelle entnehmen.

Kapitel 3 DirectInput

259

Datenformat DIFORMAT_KEYBOARD

Beschreibung Tastatur: Fr jede Taste ein Byte. Wird eine Taste momentan gedrckt, so ist das oberste Bit des entsprechenden Bytes gesetzt. Maus: vier Tasten, drei Achsen Joystick: <= 32 Knpfe, <= 6 Achsen, <= 2 Schieberegler, <= 4 Richtungsschalter Datenformat fr erweiterte Joysticks

DIFORMAT_MOUSE DIFORMAT_JOYSTICK DIFORMAT_JOYSTICK2

Die DirectInputDevice.SetCommonDataFormat()- und DirectInputDevice.SetDateFormat()-Methoden teilen DirectInput mit, welche Objekte benutzt und wie die Daten empfangen werden.

3.3.1

Standard-Datenformat
Mit der DirectInputDevice.SetCommonDataFormat()-Methode knnen wir die Standard Datenformate festlegen. Die Methode beinhaltet nur einen Parameter. Der Parameter format ist vom Typ CONST_DICOMMONDATAFORMATS.
Enum CONST_DICOMMONDATAFORMATS DIFORMAT_JOYSTICK DIFORMAT_JOYSTICK2 DIFORMAT_KEYBOARD DIFORMAT_MOUSE End Enum = = = = 3 4 1 2

Um das Datenformat z.B. fr die Tastatur zu setzen, whlen Sie folgende Syntax:
DirectInputDevice.SetCommonDataFormat DIFORMAT_KEYBOARD

Bevor Sie auf ein Gert zugreifen knnen, muss das Datenformat festgelegt werden. Whrend Sie auf das Gert zugreifen, knnen Sie das Datenformat nicht ndern.

3.3.2

Benutzerdefiniertes Datenformat
Mit der DirectInputDevice.SetDataFormat()-Methode knnen Sie ein benutzerdefiniertes Datenformat festlegen. Diese Methode beinhaltet zwei Parameter. Der erste Parameter format empfngt Daten ber des Gert selber. Der zweite Parameter formatArray() ist fr die Objekte des Gertes reserviert. Bevor wir die Methode aufrufen drfen, mssen wir die Eigenschaften fr die beiden Parameter bestimmen. Das folgende Listing definiert das Datenformat fr eine Maus mit zwei Achsen, allerdings ohne Knpfe.

260

Beispiel: Tastatur

Dim dx As New DirectX7 Dim di As DirectInput Dim diDev As DirectInputDevice Dim DataFormat As DIDATAFORMAT Dim ObjektFormat(1) As DIOBJECTDATAFORMAT Private Sub Form_Load() Set di = dx.DirectInputCreate() Set did = di.CreateDevice("GUID_SysMouse") ObjektFormat (0).lFlags = DIDOI_POLLED ObjektFormat (0).lOfs = 0 ObjektFormat (0).lType = DIDFT_RELAXIS ObjektFormat (0).strGuid = "GUID_XAxis" ObjektFormat (1).lFlags = DIDOI_POLLED ObjektFormat (1).lOfs = 4 ObjektFormat (1).lType = DIDFT_RELAXIS ObjektFormat (1).strGuid = "GUID_YAxis" DataFormat.dataSize = 8 DataFormat.lFlags = DIDF_RELAXIS DataFormat.lObjSize = 4 DataFormat.numObjs = 2 diDev.SetDataFormat DataFormat, fDA() End Sub

3.4

Beispiel: Tastatur
Fr die Eingabe ber die Tastatur erstellen wir zuerst das DirectInput-Objekt. Anschlieend wird das DirectInput-Device erstellt, welches die Tastatur reprsentiert. Es bestimmt das Verhalten der Tastatur und empfngt die Daten, welche von der Tastatur gesendet werden. Unser Beispielprogramm zeigt eine Listbox. In dieser werden die gedrckten Tasten angezeigt. Schritt 1: Erstellen des DirectInput-Objektes und des Tastaturgertes Schritt 2: Tastaturparameter setzen Schritt 3: Verbindung zur Tastatur herstellen Schritt 4: Daten von der Tastatur empfangen Fr unser Beispielprogramm dimensionieren wir folgende Variablen.
Dim dx As New DirectX7 Dim di As DirectInput Dim diDev As DirectInputDevice Dim TastaturStatus As DIKEYBOARDSTATE Dim Tasten(255) As String Private Sub Form_Load()

Kapitel 3 DirectInput

261

Bild 3.3:

Bildschirmfoto Tastatur

Schritt 1: Erstellen des DirectInput-Objektes und des Tastaturgertes


Set di = dx.DirectInputCreate() Set diDev = di.CreateDevice("GUID_SysKeyboard")

Schritt 2: Tastaturparameter setzen Fr das Standardgert Tastatur knnen wir auf ein vordefiniertes Datenformat zugreifen. Deshalb benutzen wir die SetCommonDataFormat()-Methode mit dem Parameter DIFORMAT_KEYBOARD. Fr Cooperative Level brauchen wir keinen exklusiven Zugriff (ist fr die Tastatur auch nicht erlaubt), aber gleichzeitig mchten wir die Tastaturdaten empfangen, auch wenn die Anwendung den Focus verliert.
diDev.SetCommonDataFormat DIFORMAT_KEYBOARD diDev.SetCooperativeLevel Me.hWnd, DISCL_NONEXCLUSIVE Or _ DISCL_BACKGROUND

Schritt 3: Verbindung zur Tastatur herstellen Die Methode Acquire() besitzt keine Parameter und erstellt die Verbindung zum Eingabegert. Zu welchem Eingabegert die Verbindung hergestellt werden soll, wird durch die DirectInput.CreateDevice()-Methode festgelegt.
diDev.Acquire Timer1.Enabled = True End Sub

262

Beispiel: Joystick

Schritt 4: Daten von der Tastatur empfangen ber das Timerobjekt fragen wir die Tastaturdaten ab. Die DirectInput.Get DeviceStateKeyboard()-Methode empfngt unverzglich die gewnschten Daten.
Private Sub Timer1_Timer() List1.Clear diDev.GetDeviceStateKeyboard TastaturStatus For i = 0 To 255 If TastaturStatus.Key(i) <> 0 Then List1.AddItem KeyNames(i)

Die Funktion KeyNames() interpertiert den in TastaturStatus.Key() gespeicherten Rckgabewert. So erhalten wir eine aussagefhige Information auf dem Bildschirm angezeigt.
End If Next End Sub

Interpretation der empfangenen Tastaturdaten:


Function KeyNames(ByVal iNum As Integer) As String Tasten(1) = "DIK_ESCAPE" Tasten(2) = "DIK_1 On main keyboard" Tasten(3) = "DIK_2 On main keyboard" . . . Tasten(220) = "DIK_RWIN Right Windows key" Tasten(221) = "DIK_APPS Application key" Tasten(116) = "DIK_PAUSE" KeyNames = Tasten(iNum) End Function

3.5

Beispiel: Joystick
Bei dem Joystickdemo werden wir zuerst die angeschlossenen Joysticks abfragen. Anschlieend werden die Joystickfhigkeiten ermittelt und die notwendigen Parameter gesetzt. Zum Abschluss werden die Joystickdaten empfangen. Bei dem Tastaturdemo konnten wir voraussetzen, dass eine Tastatur am Computer angeschlossen ist. Die Annahme, das ein Joystick angeschlossen ist, knnen wir nicht treffen. Es ist deshalb notwendig abzufragen, welcher Joystick zur Zeit verfgbar ist. Gleichzeitig ist es wichtig, dass wir genaue Informationen ber die Fhigkeiten des Eingabegertes erhalten. Zu diesem Zeitpunkt wre es verfrht, wenn wir auf die vielfltigen Mglichkeiten des Force Feedback Joysticks eingehen wrden, deshalb werden wir diese etwas vernachlssigen.

Kapitel 3 DirectInput

263

Bild 3.4:

Bildschirmfoto Joystick

Die Abfrage der Joystickdaten gestaltet sich komplizierter als bei dem Tastaturdemo. Die eintreffenden Daten per Timer-Objekt abzufragen wre viel zu langsam. Der bliche Weg zum Empfangen von Joystickdaten ist es, eine CallbackFunktion einzurichten. Diese wird immer dann aufgerufen wenn neue Daten eintreffen. Der Joystick liefert allerdings permanent Daten. Schritt 1: Auflisten der verfgbaren Joysticks und Erzeugen des Joystick-Objektes Schritt 2: Abfragen der Joystickfhigkeiten Schritt 3: Setzen der Joystickeigenschaften Schritt 4: Direktes Empfangen der Joystickdaten per Callback-Funktion Fr unser Beispielprogramm dimensionieren wir folgende Variablen:
Implements DirectXEvent

Da wir die Joystickdaten per Callback abrufen wollen, treffen wir mit der Implements-Anweisung die Vorbereitung. DirectXEvent ist eine eigene Klasse. Sie beinhaltet nur eine Methode: DirectXEvent.DXCallback()
Dim Dim Dim Dim Dim Dim Dim Dim dx As New DirectX7 di As DirectInput diDev As DirectInputDevice diDevEnum As DirectInputEnumDevices EventHandle As Long joyCaps As DIDEVCAPS js As DIJOYSTATE Achsen(8) As Boolean

264

Beispiel: Joystick

Dim Dim Dim Dim Dim Dim Dim

Knpfe(32) As Boolean Pov(4) As Boolean JoyGuid(16) As String Fd As DIDATAFORMAT fda(1) As DIOBJECTDATAFORMAT Running As Boolean JoyAngeschlossen As Boolean

Schritt 1: Auflisten der verfgbaren Joysticks und Erzeugen des JoystickObjektes Mit diesem Beispielprogramm fhren wir die Subroutine InitDirectInput() ein. Sie wird jetzt und in Zukunft die Initialisierungsaufgaben bernehmen. Gleichzeitig werden wir dieser Routine diverse Prfungsaufgen anvertrauen. In dem jetzigem Beispielprogramm prfen wir das System auf alle registrierten Joysticks. Wird ein gltiger Joystick gefunden, so knnen wir das notwendige Gert erstellen. Wir aber kein Joystick gefunden, so beenden wir das Programm. Das Ergebnis der Prfung bergeben wir an die Combobox1 auf Form1 unserer Anwendung.
Sub InitDirectInput() Set di = dx.DirectInputCreate() Set diDevEnum = di.GetDIEnumDevices(DIDEVTYPE_JOYSTICK, _ DIEDFL_INCLUDEPHANTOMS)

Die DirectInput.GetDIEnumDevices()-Methode fllt das Typen-Arrays diDev Enum. Die Parameter der DirectInput.GetDIEnumDevices()-Methode bestimmen, dass wir Informationen ber Joysticks erhalten mchten. Die Konstante DIEDFL_INCLUDEPHANTOMS im zweiten Parameter informiert DirectInput, dass Informationen ber alle vom System registrierten Joysticks gewnscht sind. Es wird nicht unterschieden, ob der Joystick angeschlossen ist oder nicht.
If diDevEnum.GetCount = 0 Then MsgBox "Es wurde kein Joystick gefunden." Unload Me End If

Die Prfung, ob berhaupt ein Joystick verfgbar ist, knnen wir mit DirectInput EnumDevices.GetCount()-Methode durchfhren. Liefert diese Methode eine 0 zurck, so wissen wir, das kein Joystick angeschlossen ist. Ansonsten wird die Methode die Anzahl der angeschlossenen Joysticks bekannt geben.
Dim i As Integer For i = 1 To diDevEnum.GetCount Combo1.AddItem diDevEnum.GetItem(i).GetInstanceName JoyGuid(i) = diDevEnum.GetItem(i).GetGuidInstance Next i

Kapitel 3 DirectInput

265

Nacheinander lassen wir alle Joystickbezeichnungen in die Combobox eintragen. Zustzlich merken wir uns den Guid der gefundenen Joysticks, dieser wird beim Erstellen des Gertes bentigt. ber diese Box knnen wir dann einen der gelisteten Joysticks whlen und testen.
EventHandle = dx.CreateEvent(Me)

Die DirectX7.CreateEvent() liefert das Handle des Event-Objektes, welches in der Form eingebunden ist. Fr den vollautomatischen Callback ist das Handle unverzichtbar.
End Sub

Schritt 2: Abfragen der Joystickfhigkeiten Wenn das Combo1_Click()-Ereignis ausgelst wird, ermitteln wir die Fhigkeiten des selektierten Joysticks. Ebenso ermitten wir, ob der selektierte Joystick mit dem Computer verbunden ist.
Set diDevEnum = di.GetDIEnumDevices(DIDEVTYPE_JOYSTICK, _ DIEDFL_ATTACHEDONLY) For EunmCount = 1 To diDevEnum.GetCount If JoyGuid(Index + 1) = _ diDevEnum.GetItem(EunmCount).GetGuidInstance Then Label3 = "Joystick ist mit dem Computer verbunden" Else Label3 = _ "Joystick ist --> N I C H T <-- mit dem Computer verbunden" End If Next EunmCount If diDevEnum.GetCount = 0 Then Label3 = "Joystick ist _ --> N I C H T <-- mit dem Computer verbunden"

Entsprechend der Prfung ob der gewhlte Joystick mit dem System verbunden ist, verndern wir den Infotext von Label3. Nur von den angeschlossenen Joysticks werden wir spter die Daten empfangen und auf dem Bildschirm anzeigen. Die eigentliche Prfung der Joystickfhigkeiten bernimmt die CheckCaps()Subroutine. Diese haben wir in drei Abschnitte unterteilt. Fr die Abfrage der Achsen, Knpfe und Coolie Steuerungen (Richtungsschalter) nutzen wir die DirectInputDevice.GetDeviceObjectsEnum()-Methode. Sie verlangt den Parameter flags As CONST_DIDFTFLAGS. Er bestimmt welche Fhigkeit des Joysticks abgefragt werden soll.
Set didoEnum = diDev.GetDeviceObjectsEnum(DIDFT_AXIS)

Mit der For...Next-Schleife berprfen wir die gefundnen Joystickfhigkeiten. Zum Vergleich stellt uns DirectInput die CONST_DIJOYSTICKOFS-Konstantenliste zur Verfgung.

266

Beispiel: Joystick

For i = 1 To didoEnum.GetCount Set dido = didoEnum.GetItem(i) Select Case dido.GetOfs Case DIJOFS_X Achsen(1) = True Case DIJOFS_Y Achsen(2) = True Case DIJOFS_Z Achsen(3) = True Case DIJOFS_RY Achsen(4) = True Case DIJOFS_RX Achsen(5) = True Case DIJOFS_RY Achsen(6) = True Case DIJOFS_SLIDER0 Achsen(7) = True Case DIJOFS_SLIDER1 Achsen(8) = True End Select Next

In unserm Beispiel bertragen eine eine positive Prfung der mglichen Achsen in das Array Achsen(). Die Auswertung fr die Bildschirmanzeige ist gnzlich unkompliziert und muss nicht erlutert werden.
For i = 1 To 8 If Achsen(i) = True Then Check1(i 1).Value = 1 Check1(i 1).Enabled = True Text1(i 1).Visible = True Else Check1(i 1).Value = 0 Check1(i 1).Enabled = False Text1(i 1).Visible = False End If Next i

Schritt 3: Setzen der Joystickeigenschaften Unterschiedliche Joysticks liefern unterschiedliche Wertebereiche bei der Achsenabfrage. Da Sie als Programmierer nicht wissen knnen, welchen Joystick der Anwender einmal nutzen wird, legen wir den gltigen Wertebereich einfach fest. Die Joystick werden die selbstdefinierten Grenzen beachten, sodass wir eine einheitliche Interpretation der empfangenen Daten erstellen knnen. Bevor wir uns um die Interpretation kmmern, setzen wir nun die Joystickeigenschaften. Hierzu nutzen wir die SetProperties()-Subroutine.

Kapitel 3 DirectInput

267

Public Sub SetProperties() Dim DiProp_Range As DIPROPRANGE With DiProp_Range .lHow = DIPH_DEVICE

Da wir den Wertebereich fr alle Achsen begrenzen mchten, whlen wir die Einstellung DIPH_DEVICE.
.lSize = Len(DiProp_Range) .lMin = 0 .lMax = 10000

Durch die Parameter lMin und lMax wird der Wertebereich der Achsen begrenzt. Diese Berenzung wirkt sich auf alle Joysticks aus. Programmtechnisch ist solch eine Einschrnkung von Nutzen, denn dadurch wird es mglich, ber eine einheitliche Routine die Daten unterschiedliche Joysticks auszuwerten. Ohne solch eine Einschrnkung msste man fr verschieden Joysticks auch unterschiedliche Auswertungen erstellen.
End With diDev.SetProperty "DIPROP_RANGE", DiProp_Range

Die folgenden Gerteeigenschaften definieren die Deadzone. Die Deadzone ist ein Wertebereich in dem der Joystick nicht reagieren soll. Die Mitte des Wertebereichs ist die Nullstellung (wenn Sie den Joystick nicht bewegen).
Dim DiProp_Dead As DIPROPLONG With DiProp_Dead .lData = 1000

Die Deadzone wird in unserem Beispiel mit 1000 (10% der Maximalwerte) festgelegt. Setzen Sie diesen Wert doch mal auf 1, Sie werden beobachten, dass die Daten des Joysticks immer etwas schwanken, obwohl er sich in Nullstellung befindet.
.lSize = Len(DiProp_Dead) .lHow = DIPH_BYOFFSET .lObj = DIJOFS_X diDev.SetProperty "DIPROP_DEADZONE", DiProp_Dead

Zuerst legen wir die Deadzone fr die X Achse fest. Anschlieend folgt die Definition fr die Y Achse.
.lObj = DIJOFS_Y diDev.SetProperty "DIPROP_DEADZONE", DiProp_Dead End With End Sub

268

Beispiel: Maus

Schritt 4: Direktes Empfangen der Joystickdaten per Callback-Funktion Die Joystickdaten werden ber die DirectXEvent_DXCallback()-Subroutine empfangen. Bevor wir an die Daten gelangen, mssen wir das Gert erstellen, das Datenformat festlegen, den Cooperativ Level festlegen, die Callbackbenachrichtigung einschalten und die Verbindung zu dem Gert schaffen. Dies wird von uns im letzten Abschnitt der Combo1_Click()-Subroutine erledigt.
Private Sub Combo1_Click() . . . Set diDev = di.CreateDevice(JoyGuid(Index + 1)) diDev.SetCommonDataFormat DIFORMAT_JOYSTICK diDev.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or _ DISCL_NONEXCLUSIVE Call diDev.SetEventNotification(EventHandle) SetProperties diDev.Acquire Do While Running = True diDev.Poll

Die DirectInputDevice.Poll()-Methode stellt die Joystickdaten zur Verfgung. Der Joystick wird ohne Unterbrechung Daten senden, deshalb wird auch unterbrechungsfrei die Callback-Routine aufgerufen.
DoEvents Loop

3.6

Beispiel: Maus
Der Zugriff auf die Systemmaus als Eingabegert ist vergleichbar mit der eingesetzten Joysticktechnik. In unserem Beispiel gehen wir davon aus, dass nur eine Maus angeschlossen ist. Es entfllt somit die Auflistung der verfgbaren Eingabegerte und wir konzentrieren uns aus die Systemmaus. Je nachdem welche Maus der Anwender angeschlossen hat, besitzt die Maus unterschiedliche Fhigkeiten. DirectInput untersttzt folgende Objekte: 3 Achsen (X-Achse, Y-Achse und Z-Achse) 4 Knpfe

Per Callback-Funktion fragen wir die Joystickdaten ab. Im Gegensatz zum Joystick sendet die Maus nicht permanent Daten, sondern nur dann, wenn Sie die Maus bewegen oder eine Taste drcken.

Kapitel 3 DirectInput

269

Bild 3.5:

Bildschirmfoto Maus

Schritt 1: Erzeugen des Maus-Objektes Schritt 2: Abfragen der Mausfhigkeiten Schritt 3: Setzen der Mauseigenschaften Schritt 4: Direktes Empfangen der Mausdaten per Callback-Funktion Neben den bentigten DirectInput-Methoden mssen wir noch einige API-Funktionen deklarieren. Diese sind fr die Abfrage der Mausinformationen nicht notwendig, werden aber fr eine ordentliche Auswertung bentigt. In einer DirectXAnwendung, in der Sie nicht unmittelbar mit der Windowsoberflche arbeiten, knnen Sie auf diese getrost verzichten.
Implements DirectXEvent Private Declare Function GetCursorPos Lib "user32" _ (lpPoint As POINTAPI) As Long Private Declare Function SetCursorPos Lib "user32" _ (ByVal X As Long, ByVal Y As Long) As Long Private Declare Function ScreenToClient Lib "user32" _ (ByVal hWnd As Long, lpPoint As POINTAPI) As Long Private Type POINTAPI X As Long Y As Long End Type Dim dx As New DirectX7 Dim di As DirectInput Dim diDev As DirectInputDevice Dim diDevEnum As DirectInputEnumDevices Dim Achsen(8) As Boolean

270

Beispiel: Maus

Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim Dim

Knpfe(32) As Boolean EventHandle As Long MausCaps As DIDEVCAPS js As DIMOUSESTATE Running As Boolean JoyAngeschlossen As Boolean MouseX As Long MouseY As Long CursorPos As POINTAPI ClientWindowsLeft As Long ClientWindowsTop As Long ZeichenModus As Boolean Speed As Long

Schritt 1: Erzeugen des Maus-Objektes


Sub InitDirectInput() Set di = dx.DirectInputCreate() Set diDevEnum = di.GetDIEnumDevices(DIDEVTYPE_MOUSE, _ DIEDFL_ATTACHEDONLY) If diDevEnum.GetCount = 0 Then MsgBox "Es wurde kein Mouse gefunden." End End If

Sollte keine Maus gefunden werden, so beenden wir das Programm. Diesmal ist es nur notwendig, das System auf angeschlossene Gerte zu prfen. Von den angeschlossenen Gerten interessiert uns auch nur die Maus. Fr den ersten Parameter der DirectInput.GetDIEnumDevices()-Methode whlen wir DIDEVTYPE_ MOUSE. Dieser besagt, das wir nur nach einem Gert vom Typ Maus suchen. Der zweite Parameter DIEDFL_ATTACHEDONLY besagt, dass wir nur angeschlossene Gerte suchen.
EventHandle = dx.CreateEvent(Me) Set diDev = di.CreateDevice("guid_SysMouse")

Nachdem eine Maus gefunden wurde, knnen wir das Gert erstellen. Zum Erstellen einer Systemmaus verwenden wir die Konstante guid_SysMouse.
CheckCaps

Die Prfung der Mausfhigkeiten bernimmt die CheckCaps()-Subroutine. Diese betrachten wir im Anschluss.
diDev.SetCommonDataFormat DIFORMAT_MOUSE diDev.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or ISCL_NONEXCLUSIVE Call diDev.SetEventNotification(EventHandle) SetProperties

Kapitel 3 DirectInput

271

Nachdem wir das Gert erstellt haben und bevor wir die Verbindung zum Gert herstellen, knnen wir die Eigenschaften des Gerts festlegen. Dies bernimmt die SetProperties()-Subroutine.
diDev.Acquire Running = True Do While Running = True DoEvents Loop End Sub

Schritt 2: Abfragen der Mausfhigkeiten


Public Sub CheckCaps() diDev.GetCapabilities MausCaps

Wir bergeben die Mausfhigkeiten an MausCaps As DIDEVCAPS. Aus MausCaps bentigen wir eigentlich nur die Anzahl der Mausknpfe. Programmtechnisch knnen Sie das auch anders lsen, dies wrde aber der DirectX Philosophie etwas widersprechen.
Dim didoEnum As DirectInputEnumDeviceObjects Dim dido As DirectInputDeviceObjectInstance . . .

Prfung der Achsen.


Set didoEnum = diDev.GetDeviceObjectsEnum(DIDFT_AXIS) For i = 1 To didoEnum.GetCount Set dido = didoEnum.GetItem(i) Select Case dido.GetOfs Case DIMOFS_X Achsen(1) = True Case DIMOFS_Y Achsen(2) = True Case DIMOFS_Z Achsen(3) = True End Select Next

Prfung der Knpfe.


Set didoEnum = diDev.GetDeviceObjectsEnum(DIDFT_BUTTON) For i = 1 To didoEnum.GetCount Set dido = didoEnum.GetItem(i) a = dido.GetOfs Select Case dido.GetOfs

272

Beispiel: DirectInput und Direct3D

Case DIMOFS_BUTTON0 Knpfe(1) = True Case DIMOFS_BUTTON1 Knpfe(2) = True Case DIMOFS_BUTTON2 Knpfe(3) = True Case DIMOFS_BUTTON3 Knpfe(4) = True End Select Next . . . End Sub

Schritt 3: Setzen der Mauseigenschaften


Public Sub SetProperties() Dim DiProp_Range As DIPROPRANGE Dim diProp As DIPROPLONG diProp.lHow = DIPH_DEVICE diProp.lData = DIPROPAXISMODE_REL

Die Konstante DIPROPAXISMODE_REL besagt, dass die von der Maus gesendeten Daten relative Daten sind. Dem Programmierer werden nur die nderungen von einer Abfrage zur darauf folgenden Abfrage mitgeteilt. Sie knnen auch die Konstante DIPROPAXISMODE_ABS verwenden, dann erhalten Sie absolute Werte. In unserem Beispiel sind relative Daten besser auszuwerten.
diProp.lSize = Len(diProp) Call diDev.SetProperty("DIPROP_AXISMODE", diProp) End Sub

3.7

Beispiel: DirectInput und Direct3D


Mit diesem Beispielprogramm demonstrieren wir die Integration von DirectInput in einer Direct3D-Anwendung. Nach dem Starten des Programms erhalten Sie ein Auswahlfenster. Hier knnen Sie zwischen einer Steuerung per Tastatur oder per Joystick whlen. Es werden Ihnen nur Joysticks, welche mit dem System verbunden sind, angezeigt. Benutzen Sie einen analogen Joystick, so wird die Laufgeschwindigkeit entsprechend der Joystickintensitt angepasst. Zustzlich haben wir eine einfache Technik einer Kollisionserkennung eingebunden. Die Tastatur wir diesmal per Callback abgefragt. In unserem ersten Beispiel wurde die Abfrage noch per Timerobjekt ausgefhrt. Diese Lsung wre fr dieses Beispiel nicht so geeignet. Da wir fr den Joystick eine Callback-Funktion einrichten, bietet es sich an, die Tastaturabfrage in der gleichen Subroutine durchzufhren.

Kapitel 3 DirectInput

273

Bild 3.6:

Bildschirmfoto Bewegung

Zuerst betrachten wir das Auswahlfenster fr die verfgbaren Eingabegerte. Bevor wir ein Eingabegert auswhlen knnen, mssen die verfgbaren Gerte angezeigt werden. Wir gehen davon aus, dass eine Tastatur immer angeschlossen ist, sodass wir diese nicht testen und auflisten mssen. Fr die Auswahl eines Joysticks sieht das ganz anders aus.
Private Sub Form_Load() Set di = dx.DirectInputCreate() Set diEnumDev = di.GetDIEnumDevices(DIDEVTYPE_JOYSTICK, _ DIEDFL_ATTACHEDONLY) devicecount = diEnumDev.GetCount() . . . For i = 1 To devicecount Set diDev = _ di.CreateDevice(diEnumDev.GetItem(i).GetGuidInstance) Combo1.AddItem (diEnumDev.GetItem(i).GetProductName)

274

Beispiel: DirectInput und Direct3D

Bild 3.7:

Bildschirmfoto Bewegung (Login)

Alle angeschlossenen Joysticks werden in die Comb1-Combobox eingetragen. Diese Prozedur ist Ihnen bereits bekannt und kann im Beispielprogramm Auflisten der verfgbaren Gerte und Objekte nachgelesen werden.
Next i Combo1.Text = Combo1.List(0) Listen 1

Die Subroutine Listen() zeigt die Joystickfhigkeiten an. Auch diese ist Ihnen bekannt und wird jetzt nicht nher erklrt.
End Sub

Nachdem Sie das Eingabegert gewhlt haben, klicken Sie auf die Schaltflche Weiter.
Private Sub Command1_Click() If Label5 = "N/A" Or Label6 = "N/A" Then MsgBox "Sie haben _ keine Eingabegert gewhlt!": Exit Sub

Sollten Sie kein Eingabegert gewhlt haben, verlassen wir die Subroutine direkt.

Kapitel 3 DirectInput

275

InputName = Label5 InputGuid = Label6

Die Variablen InputName und InputGuid nutzen wir, um spter das Eingabegert zu erzeugen. InputName dient hauptschlich dazu, um die beiden Eingabegerte (Tastatur oder Joystick) zu unterscheiden.
Unload Me Load Form1 End Sub

Weiter geht es mit der Subroutine Form_Load() von Form1.


Private Sub Form_Load() InitDDraw InitD3D InitInput Licht RenderState MakeVertex . . . End Sub

Die Subroutine InitInput() richtet das Eingabegert ein. Bevor wir auf weitere Elemente der Form_Load()-Subroutine eingehen, schauen wir uns die InitInput()-Subroutine genauer an.
Public Sub InitInput() Select Case Form2.InputName Case "Tastatur" Set di = g_dx.DirectInputCreate() EventHandle = g_dx.CreateEvent(Me) Set diDev = di.CreateDevice("GUID_SysKeyboard")

Beim Einrichten der Tastatur sind wir auf eine individuelle Guid nicht angewiesen. Wir knnen die feste Kennung GUID_SysKeyboard verwenden.
diDev.SetCommonDataFormat DIFORMAT_KEYBOARD diDev.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or _ DISCL_NONEXCLUSIVE Call diDev.SetEventNotification(EventHandle) diDev.Acquire Case Else Set di = g_dx.DirectInputCreate() EventHandle = g_dx.CreateEvent(Me) Set diDev = di.CreateDevice(Form2.InputGuid)

276

Beispiel: DirectInput und Direct3D

Fr das Erzeugen des Joysticks bentigen wir eine individuelle Guid. Diese wurde bei der Joystickauswahl ermittelt und in der Variablen InputGuid gespeichert.
diDev.SetCommonDataFormat DIFORMAT_JOYSTICK diDev.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or _ DISCL_NONEXCLUSIVE Call diDev.SetEventNotification(EventHandle) SetProperties diDev.Acquire End Select End Sub

Um die Eingabedaten zu empfangen, haben wir uns bei beiden Eingabemglichkeiten fr eine Callback-Funktion entschieden.
Private Sub DirectXEvent_DXCallback(ByVal eventid As Long) On Local Error Resume Next If InputFrei = False Then Exit Sub InputFrei = False If diDev Is Nothing Then Exit Sub If Form2.InputName <> "Tastatur" Then diDev.GetDeviceStateJoystick js SpeedY = (5000 js.y) / 5000 SpeedX = ((5000 js.x) / 500) * -1

Als wir den Joystick erzeugt haben, wurden auch die Joystickeigenschaften neu definiert. Die Subroutine SetProperties() beschrnkt den Wertebereich der Joystickachsen auf 0 bis 10000. Die Mittelstellung liegt also bei 5000. Wir werden also von allen Joysticks Daten in einem gemeinsamen Wertebereich erhalten, somit sind wir in der Lage, die Daten programmtechnisch auszuwerten. Die Daten bergeben wir an die globalen Variablen SpeedY und SpeedX.
Else diDev.GetDeviceStateKeyboard If ks.Key(200) And OldButton SpeedY = 0.3 OldButton = 200 End If If ks.Key(208) And OldButton SpeedY = -0.3 OldButton = 208 End If If ks.Key(203) And OldButton SpeedX = -4 OldButton = 203 End If If ks.Key(205) And OldButton ks <> 200 Then

<> 208 Then

<> 203 Then

<> 205 Then

Kapitel 3 DirectInput

277

SpeedX = 4 OldButton = 205 End If If ks.Key(200) = 0 And ks.Key(208) = 0 SpeedY = 0 OldButton = 0 End If If ks.Key(203) = 0 And ks.Key(205) = 0 SpeedX = 0 OldButton = 0 End If If ks.Key(200) <> 0 And ks.Key(208) <> SpeedY = 0 OldButton = 0 End If If ks.Key(203) <> 0 And ks.Key(205) <> SpeedX = 0 OldButton = 0 End If

Then

Then

0 Then

0 Then

Fr die Datenauswertung der Tastatur mussten wir die Tastatureigenschaften nicht neu definieren. Schlielich gibt es fr eine Taste nur zwei Zustnde (gedrckt oder nicht gedrckt). Anders als beim Joystick werden die empfangenen Daten auch nicht weiter interpretiert. Drcken Sie z.B. die Vorwrtstaste, so wird die Geschwindigkeit direkt auf einen festen Wert gesetzt. In unserem Beispiel auf 0.3. Analoge Zwischenwerte existieren nicht.
End Sub

Nachdem wir die Eingabegerte erzeugt haben und in der Lage sind, die Eingabedaten zu empfangen, werden die Informationen in der Form_Load()-Subroutine von Form1 weiter ausgewertet.
Private Sub Form_Load() . . . Do If g_dx.TickCount > TimerZeit + ZeitInterval Then TimerZeit = g_dx.TickCount tempVector.x = BetrachterPos.x tempVector.z = BetrachterPos.z

Wir haben eine kleine Kollisionserkennung in das Programm eingebunden. Diese soll folgende Aufgabe lsen: Erkennen einer Kollision mit einem Baum zwei Einheiten vor unserer aktuellen Laufrichtung. Es ist wichtig, dass Sie eine mgliche Kollision vor Ihrer aktuellen Position prfen. Wir haben uns fr zwei Einheiten vor uns entschieden. Wenn wir den Abstand zu unserer Position zu klein

278

Beispiel: DirectInput und Direct3D

whlen, treten unschne Effekte (der Betrachter steht halb in dem Baum, der Betrachter kann durch den Baum sehen ...) auf.
If SpeedY > 0 Then If speed > 2 Then xx = speed Else tempVector2.x = BetrachterPos.x + Sin(BetrachterWinkel / 57.296)) tempVector2.z = BetrachterPos.z + Cos(BetrachterWinkel / 57.296)) Else If speed < 2 Then xx = speed * -1 tempVector2.x = BetrachterPos.x Sin(BetrachterWinkel / 57.296)) tempVector2.z = BetrachterPos.z Cos(BetrachterWinkel / 57.296)) End If xx = 2 (xx * _ (xx * _

Else xx = 2 (xx * _ (xx * _

Beim Erzeugen der Bume in der MakeVertex()-Subroutine haben wir das TypenArrays Kollision mit den Baumkoordinaten gefllt. Diese Daten knnen wir nun fr die Kollisionserkennung nutzen. Dazu fragen wir eine rechteckigen Bereich um den Baum herum ab. Befinden wir uns in diesem Bereich, dann wird eine Kollision erkannt.
For i = 1 To 60 If tempVector2.x > Kollision(i).PosX 0.5 And _ tempVector2.x < Kollision(i).PosX + 0.5 And _ tempVector2.z > Kollision(i).PosZ 0.5 And _ tempVector2.z < Kollision(i).PosZ + 0.5 Then BetrachterPos.x = tempVector.x BetrachterPos.z = tempVector.z kolli = 1 Exit For

Wenn eine Kollision erkannt wurde, wird die Betrachterposition nicht verndert. Der Betrachter verharrt an einer Stelle, ohne sich in die angestrebte Richtung bewegen zu knnen.
Else kolli = 0 End If Next i If kolli = 0 Then BetrachterPos.x = BetrachterPos.x + _ (SpeedY * Sin(BetrachterWinkel / 57.296)) BetrachterPos.z = BetrachterPos.z + _ (SpeedY * Cos(BetrachterWinkel / 57.296))

Kapitel 3 DirectInput

279

Wurde keine Kollision erkannt, so darf der Betrachter die neue Position einnehmen.
End If BetrachterWinkel = BetrachterWinkel + SpeedX BetrachterSicht.x = BetrachterPos.x + _ 100 * Sin(BetrachterWinkel / 57.296) BetrachterSicht.z = BetrachterPos.z + _ 100 * Cos(BetrachterWinkel / 57.296) BetrachterPos.y = 1.5 BetrachterSicht.y = 1.5 Call g_dx.ViewMatrix(matView, BetrachterPos,_ BetrachterSicht, MakeVector(0, 1, 0), 0) g_d3dDevice.SetTransform D3DTRANSFORMSTATE_VIEW, matView

Durch die Transformation der ViewMatrix werden die Vernderungen von Betrachterposition und Betrachterblickwinkel fr den Anwender sichtbar.
. . . End Sub

3.8

Bewegung im 3D-Raum
Position, Ausrichtung und Blickrichtung des Betrachters oder der Spielfigur wird im Allgemeinen ber die Viewmatrix berechnet. Diese Parameter werden ber verschiedene Vektoren festgelegt. Als Erstes haben wir die absolute Position im dreidimensionalen Raum. Diese Werte splitten sich in die drei Vektorkoordinaten x, y und z auf. Als Nchstes bentigen wir xyz Koordinaten fr den Punkt auf den wir blicken, weiterhin knnen wir die Kopfneigung und Drehung festlegen. In unserem Beispiel beschrnken wir uns zunchst auf die ersten beiden Parameter. Das Problem: ber den ersten 3D-Vektor sind wir generell in der Lage uns durch einen beliebigen Raum zu bewegen. Allerdings wrden wir immer auf einen bestimmten Punkt (0,0,0) im Raum schauen. Wrden wir zum Beispiel ein Objekt umkreisen, wre diese Technik angebracht. Die Position des Betrachters wrde sich stets verndern und der Blick fiele immer auf das umkreiste Objekt. Diese Vorhergehensweise macht bei einsetzbaren Anwendungen wenig Sinn. Vielmehr versucht man die Realitt nachzuahmen, getreu dem Motto Ich gehe, wohin ich sehe. Viele Programme benutzen hierzu eine bewhrte Steuerungstechnik. Bettigt man die Links-Rechts-Cursortasten, so dreht sich der Betrachter um die eigene Achse. Drckt man nun die Vor-Zurck-Cursortasten, bewegt man sich in die Richtung, in die man gerade schaut.

280

Bewegung im 3D-Raum

Bild 3.8:

Umkreisen eines Objekts im 3D-Raum

Um diese Eigenart zu simulieren, bentigen wir einen Blickrichtungsvektor. Stellen wir uns vor, wir knnten genau 5 Meter weit sehen und wir wrden uns einmal um unsere eigene Achse drehen. So wrde das Ende unseres Blickfeldes einen Kreis mit einem Radius von 5 Metern um uns ziehen. Das hiee also, die Blickrichtung liegt auf einem Kreisbogen um uns herum und unsere jetzige Standposition ist der Mittelpunkt dieses Kreises.

Bild 3.9:

Blickrichtung

Kapitel 3 DirectInput

281

Anhand der Grafik sehen wir, dass der Blickpunkt ber einfache geometrische Kreisberechnungen ermittelt werden kann. Bercksichtigt werden muss nur noch, dass wir weiter sehen knnen, als wir mit einem Schritt gehen knnen. Hierzu berechnen wir einfach einen neuen Standort auf einem kleineren Kreisbogen, den wir dann der alten Position hinzuaddieren knnen.

Bild 3.10: Berechnung des neuen Standorts auf einen neuen Blickpunkt hin

So viel zur Theorie. Was nun folgt, ist die Praxis. Unsere aktuellen Standortvariablen benennen wir (AktX,AktZ). Als Weiteres bentigen wir die aktuelle Blickrichtung in Grad. Nennen wir diese AktBR. Um nun eine Drehung auszuf hren, mssen wir AktBR in einem Bereich von 0-359 Grad verndern. Fr die Tastaturabfrage eignet sich der API-Aufruf GetAsyncKeyState, den wir in einer DoEvents-Endlosschleife auf einen vorhandenen Tastendruck abfragen.
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer Dim AktX as Single Dim AktZ as Single Dim AktBR as Single Private Sub Schleife() Do

Drehung links um die Y-Achse


If GetAsyncKeyState(vbKeyLeft) <> 0 then AktBR = AktBR -1 If AktBR <0 then AktBR=359 End If

282

Bewegung im 3D-Raum

Drehung rechts um die Y-Achse


If GetAsyncKeyState(vbKeyRight) <> 0 then AktBR = AktBR+1 If AktBR >359 then AktBR=0 end if

Berechnung des Positionsabgleichs Vorwrtsbewegung.


If GetAsyncKeyState(vbKeyUp) <> 0 then px = 0.5 * Cos( AktBR / 180 / Pi ) pz = 0.5 * Sin( AktBR / 180 / Pi ) AktX = AktX + px AktZ = AktZ + pz End If

Berechnung des neuen Blickpunktes.


BlickX = 100 * Cos (AktBR / 180 / Pi ) BlickY = 100 * Sin (AktBR / 180 / Pi ) Call g_dx.ViewMatrix(matView, _ MakeVector(AktX,0,AktZ), MakeVector(BlickX, _ 0, BlickY), MakeVector(0, 1, 0), 0) Loop End Sub Private Function MakeVector( a As Double, b As Double, _ c As Double ) as D3DVECTOR Dim vecOut as D3DVECTOR vecOut.x = a vecOut.y = b vecOut.z = c MakeVector = vecOut End Function

Bild 3.11: Berechnung der neuen Position im Koordinatensystem

Kapitel 4
DirectSound
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 4.15 4.16 4.17 4.18 4.19 DirectSound-Architektur Datenformat HAL und HEL Systemintegration Initialisieren von DirectSound Erstellen des DirectSound-Objektes Buffer-Grundlagen Primary Soundbuffer Static und Streaming Soundbuffer Erzeugen von Soundbuffern Buffer-Einstellungen Buffer Playback Controls Ein einfaches Soundbeispiel Der PlayCursor Playbuffer-Benachrichtigungen Direct3DSound DirectSound3DBuffer DirectSound3DListener DirectSound Capture 285 285 286 286 287 288 290 291 291 292 294 294 296 299 301 301 304 315 328

284

DirectX ist nicht nur ein hervorragendes Werkzeug zum Erstellen von atemberaubenden 2D-und 3D-Grafiken sowie Landschaften, sondern eignet sich auch sehr gut fr den Einsatz im musikalischen Bereich. Die Entwickler von DirectX haben sich auch bei der Erstellung und Wiedergabe von Soundeffekten und Musik mchtig ins Zeug gelegt. Bei modernen Spielen wird heutzutage ebenso viel Wert auf eine brillante Soundwiedergabe mit realistischen Effekten wie auf Grafik und Animation gelegt. Richtig eingesetzte Klangeffekte sowie gut abgestimmte Hintergrundmusik verleihen einem Spiel erst das gewisse Etwas. Ein Spiel soll den Spieler fesseln und wie bei einem Spielfilm in die Handlungsperson versetzen. Bei DirectSound handelt es sich nicht nur um ein gewhnliches Modul zum einfachen Abspielen von Soundeffekten und Samples, sondern um ein leistungsfhiges Werkzeug zum Erstellen von zwei- und dreidimensionalen Klangbildern. Bei der Entwicklung wurde Wert auf eine mglichst realistische und naturgetreue Wiedergabe gelegt. So werden z.B. Effekte dem menschlichen Hrvermgen mathematisch so angepasst, dass sie den Zuhrer in eine virtuelle dreidimensionale Klangwelt versetzen. Die Aufgabenstellung an die Entwickler von DirectSound war es, ein Modul zu erschaffen, dass das gleichzeitige Abspielen mehrerer Sounds ermglicht. Einige Klnge sollten dabei vielleicht immer wieder abgespielt werden, beispielsweise in einer Endlosschleife, andere hingegen nur einmal oder zu bestimmten Zeiten. Auerdem mssen die einzelnen Lautstrkepegel aufeinander abgestimmt und mit unterschiedlichen klanglichen Effekten rumlich bewegt werden knnen. Man bentigt also eine mglichst groe Anzahl von Tonkanlen die annhernd verzgerungsfrei abgespielt werden sollen, um somit zu verhindern, dass keine zeitlichen Verzgerungen zwischen Ursache eines Gerusches und Wiedergabe des passenden Samples auftritt. Natrlich kann die Funktionalitt von DirectSound nicht nur fr Computerspiele eingesetzt werden, sondern findet auch in anderen Anwendungsgebieten ihre Aufgaben und Einsatzgebiete. DirectSound stellt dem Anwender die zuvor beschriebenen Mglichkeiten zur Verfgung. Fr das Mischen von Sounds, das Anwenden verschiedener Effekte sowie die rumliche Positionierung von Schallquellen kann die Hardware der Soundkarte (HAL, 3D-HAL), soweit diese die speziellen Eigenschaften zur Verfgung stellt, bernehmen. Ebenso kann auch, vergleichbar mit der Grafikausgabe, auf einen Emulationsmodus (HEL) zurckgegriffen werden. Die Schnittstelle fr das Aufzeichnen von Klangdaten, das DirectSound Capture Interface, untersttzt keine Hardwareoptimierung, sondern wird allein ber die HEL (Win32 Funktionen) abgewickelt. Aber hierzu kommen wir noch ausgiebig im weiteren Verlauf dieses Buches.

Kapitel 4 DirectSound

285

4.1

DirectSound-Architektur
DirectSound beinhaltet alle Module zum Abspielen und Aufzeichnen von digitalen Sound-Samples. Die meisten Funktionen knnen ber die Soundkartenhardware verarbeitet werden. Sollten spezielle Funktionen von der Hardware nicht untersttzt werden, greift DirectSound auf softwareemulierte Funktionen zurck. DirectSound beinhaltet zum Abspielen und Manipulieren von Sounddaten folgende Klassen: DirectSoundBuffer DirectSound3DBuffer DirectSound3DListener DirectSoundCapture DirectSoundCaptureBuffer

weiterhin wird ber die DirectX7-Klasse DirectXEvent

auf die DirectX7.CreateEvent()-Methode zurckgegriffen.

4.2

Datenformat
DirectSound und DirectSoundCapture arbeiten mit Wellenform-Audiodaten, welche als digitale Samples eines Sounds vorliegen. Das genaue Format eines Samples wird in einem Typenblock, dem WAVEFOR MATEX, beschrieben.
Type WAVEFORMATEX lAvgBytesPerSec As Long lExtra As Long lSamplesPerSec As Long nBitsPerSample As Integer nBlockAlign As Integer nChannels As Integer nFormatTag As Integer nSize As Integer End Type

nChannels beschreibt die Anzahl von Kanlen (Normal 1= Mono oder 2= Stereo). lSamplesPerSec beschreibt die Samplingrate in Hertz (Hz). Typische Werte sind 11.025, 22.050 und 44.100. nBitsPerSample beschreibt die Bitbreite des Samples 8 oder 16 Bit.

286

HAL und HEL

nBlockAlign Anzahl der Bytes, die fr einen kompletten Sample bentigt werden. Berechnungsgrundlage (nBitsPerSample * nChannels / 8). lAvgBytesPerSec ist das Produkt aus nBlockAlign * lSamplesPerSec. nSize gibt die Gre der Felder an, die fr spezielle Sampleinformationen bentigt wird.

4.3

HAL und HEL


DirectSound HAL (Hardware Abstraction Layer) ist vorgesehen fr folgende Funktionen Freier Zugriff und Kontrolle auf die Audiohardware (Soundkarte). Beschreiben der Leistungsfhigkeit der Audiohardware. Ausfhren von soundkartenspezifischen Methoden.

Rckgabe von Fehlermeldungen, die durch die Audiohardware gemeldet wurden. Sollten beim Ausfhren von hardwarespezifischen Methoden mgliche Fehler durch die Audiohardware gemeldet werden, z.B. weil die Soundkarte einige Eigenschaften nicht untersttzt, so leitet DirectSound diese Prozedur zum HEL (Hardware Emulations Layer) um.

4.4

Systemintegration
Win32 Programm

DirectSound
HAL Emulation

MIDI
DirectSound HAL

Wave

Windows Audio DDI

Soundkarte
Bild 4.1: Systemintegration

Kapitel 4 DirectSound

287

4.5

Initialisieren von DirectSound


Um DirectSound zu verwenden, mssen zuvor verschiedene Parameter angegeben werden. Die folgenden Methoden werden fr die Initialisierung von DirectSound eingesetzt.
GetCount() Gibt die Anzahl der Eintrge im Enumerationsobjekt zurck. object.GetCount() As Long object ein gltiges DirectSoundEnum-Objekt

GetDescription() Gibt die Treiberbeschreibung des ausgewhlten DirectSound-Gertes zurck. object.GetDescription(index As Long) As String object index GetGuid() Gibt die Identifikationsnummer des DirectSound-Gertes zurck. object.GetGuid(index As Long) As String object index GetName() Gibt die Bezeichnung des DirectSound-Gertes zurck. object.GetName(index As Long) As String object index ein gltiges DirectSoundEnum-Objekt Index des DirectSound-Gertes in der Aufzhlung ein gltiges DirectSoundEnum-Objekt Index des DirectSound-Gertes in der Aufzhlung ein gltiges DirectSoundEnum-Objekt Index des DirectSound-Gertes in der Aufzhlung

DirectX7-Objekt und DirectSound vorbereiten:


Dim g_dx as DirectX7 Dim m_ds as DirectSound Dim g_dx as new DirectX7

Auslesen der Enumeration von DirectSound:


Dim dsEnum as DirectSoundEnum Set dsEnum = g_dx.GetDSEnum

288

Erstellen des DirectSound-Objektes

For i = 1 to dsEnum.GetCount Debug.Print dsEnum.GetDescription (i) Next i

ber die dsEnum knnen nun folgende Parameter ausgelesen werden: Enthlt die Anzahl der auszulesenden Audiogerte
dsEnum.GetCount

Herstellerbezeichnungen und Soundkartentypen


dsenum.GetDescription (index)

Zusatzbezeichnungen und andere Infos zum Audiogert


dsEnum.GetName (Index)

Identifizierungsstring der Audiohardware. Dieser wird zum Erstellen des Direct Sound Objektes bentigt.
dsEnum.GetGuid (index)

Es wird Ihnen nicht entgangen sein, dass Ihnen, obwohl Sie nur eine Soundkarte in Ihrem System haben, zwei Audiogerte angezeigt werden. Dies ist hnlich wie bei den im Kapitel DirectDraw beschriebenen Grafikkarten Guids. Die erste Guid stellt den primren Audiotreiber dar und reprsentiert somit das aktive Audiogert in Ihrem System, wobei die zweite das eigentliche physische Audiogert ist.

4.6

Erstellen des DirectSound-Objektes


SetCooperativeLevel() Setzt den Cooperative Level der Applikation auf die Soundkarte. object.SetCooperativeLevel(hwnd As Long, _ level As CONST_DSSCLFLAGS) object hwnd level ein gltiges DirectSound-Objekt Windows-Handle der Aplikation Priorittsstufe CONST_DSSCLFLAGS

Um nun das DirectSound-Objekt zu erstellen und zu aktivieren, fgen wir in unser Beispiellisting die DirectSoundCreate()-Methode ein und bergeben dieser die Guid des aktiven Audiogertes.
Set m_ds = g_dx.DirectSoundCreate (dsEnum.GetGuit(1))

Kapitel 4 DirectSound

289

Da Windows eine Multitaskingumgebung besitzt und mehrere Applikationen auf die Soundkarte gleichzeitig zugreifen knnen, setzen wir hnlich wie bei DirectDraw den Cooperative Level und schtzen somit unsere Anwendung vor fehlerhaften Zugriffen auf geschtzte Bereiche.
m_ds.SetCooperativeLevel Form1.hWnd, DSSCL_NORMAL

Normal Cooperative Level Im normalen Cooperative Level ist es nicht mglich, das Format des primren SoundBuffers zu ndern sowie in diesen zu schreiben. Alle Applikationen mit diesem CooperativeLevel nutzen das Primrbufferformat 22KHz Stereo Sound und 8 Bit Sampling. In diesem Modus ist es mglich, das Audiogert zwischen verschiedenen Applikationen hin und her zu schalten. Priority Cooperative Level Wenn DirectSound im Priority Cooperative Level Modus ausgefhrt wird, hat Ihre Applikation das erste Recht auf die Hardwarerecourcen des Audiogertes. Das Format des primren Soundbuffers sowie das Komprimieren des OnBoard-Speichers des Audiogertes ist mglich. Exclusive Cooperative Level Im Exlusive Cooperative Level hat, wie der Name schon sagt, Ihre Applikation alle exclusiven Zugriffsrechte auf das Audiogert. Ist die Anwendung aktiv, ist der Soundbuffer ausschlielich Ihrer Applikation zugeordnet. Andere laufende Anwendungen haben keinen Zugriff mehr auf das Audiogert. Write-primary Cooperative Level Der hchste Cooperative Level ist der Write-primary Cooperative Level. Wenn DirectSound mit dieser Einstellung ausgefhrt wird, hat Ihre Anwendung direkten Zugriff auf den primren Soundbuffer. In diesem Modus muss von Ihrer Applikation direkt in den primren Soundbuffer geschrieben werden. Wird Direct Sound nicht in dieser Einstellung ausgefhrt, fhren alle Versuche, mit DirectSoundBuffer.ReadBuffer und DirectSoundBuffer.WriteBuffer auf den Primrbuffer zuzugreifen, zwangslufig zu einem Fehler.

Wenn Sie diesen Modus benutzen und Ihre Anwendung hat den Fokus, stoppen alle Sekundrbuffer anderer Applikationen. Wenn Ihre Applikation den Fokus verliert, wird der Primrbuffer als verloren gekennzeichnet. Um Ihre Anwendung fortzusetzen, muss der Primrbuffer erneuert werden. Mehr Informationen hierzu unter Buffer-Management.
objekt.SetCooperativeLevel (hwnd as Long, level As_ CONST_DSSCLFLAGS)

290

Buffer-Grundlagen

4.7

Buffer-Grundlagen
Die DirectSoundBuffer reprsentieren einen Speicherbereich, in dem die Sounddaten abgelegt werden. Bufferobjekte werden fr Start, Stopp, Pause und zum Ablegen der Sampledaten eines Sounds bentigt. Sie enthalten die Attribute von Frequenz und Sampleformat. Wenn Sie DirectSound in Ihrer Applikation initialisiert haben, wird automatisch der primre Soundbuffer zum Mischen von SoundSampleDaten und zur Ausgabe auf Ihrem Audiogert angelegt. Sie mssen lediglich noch von Hand die Sekundrbuffer zum Speichern und Abspielen ihrer individuellen Sounds erstellen. Hierzu aber mehr in den nchsten Kapiteln. Sekundrbuffer werden von Ihrer Applikation erstellt und knnen, wenn Sie nicht mehr bentigt werden, auch wieder gelscht werden. Sie speichern SoundSample-Daten und spielen sie bei Bedarf in einer Endlosschleife oder zu einem bestimmten Ereignis nur einmal ab. Sekundrbuffer knnen zur Laufzeit auch mit neuen Sounddaten gefllt werden. Sollte die Datenmenge grer der Aufnahmefhigkeit der Soundkarte sein oder diese nicht ber einen eigenen Speicher verfgen, so werden die Streamdaten im Speicher des Computers abgelegt. Dieses wirkt sich allerdings negativ auf die Performance aus. Typische Zugriffszeiten sind bei vorhandenem Soundkartenspeicher < 10 ms und bei Zugriff auf den Speicherbereich des PCs ca. 100 150 ms. Dieses ist aber meist fr den Hrer nicht wahrnehmbar, sodass quasi keine Verzgerung zwischen Ursache und Auswirkung bemerkt wird. Die Anzahl der Sekundrbuffern ist theoretisch unbegrenzt und wird nur durch den physikalischen Speicher limitiert. Mehr Informationen zu verschiedenen Arten von Sekundrbuffern bekommen Sie unter Static-und Streaming Soundbuffer. Unter Verwendung der DirectSound.DuplicateSoundBuffer()-Methode kann eine Kopie eines existierenden Soundbuffers erstellt werden. Diese teilt sich den selben Speicherbereich mit dem Original, kann aber autonom gesteuert werden. Der primre Soundbuffer kann nicht dupliziert werden, da er sich im Audiogert befindet und diese Eigenschaften nicht zur Verfgung stehen. Ein Versuch, den primren Soundbuffer zu duplizieren, fhrt zu einem Fehler. Sie brauchen sich nicht um die Angelegenheiten des primren Soundbuffers zu kmmern. Dieser managt sich zum grten Teil von ganz allein. Wollen Sie Performance einsparen, so knnen Sie auch sofort in den Primrbuffer schreiben. Sie verzichten damit auf die Mischeigenschaften und es knnen keine Sekundrbuffer mehr erzeugt werden. Mehr Informationen hierzu im folgenden Kapitel.
objekt.DuplicateSoundBuffer (original as DirectSoundBuffer) As_ DirectSoundBuffer

Kapitel 4 DirectSound

291

Buffer
Primary Buffer Streaming Buffer 3D Buffer
Bild 4.2: Buffer

Secondary Buffer Static Buffer

4.8

Primary Soundbuffer
Der primre Soundbuffer enthlt die momentan abgespielten Sounddaten. Der sekundre Soundbuffer enthlt ein gesamtes Sample. DirectSound erstellt automatisch einen Primrbuffer. Die Sekundrbuffer hingegen mssen in Ihrer Applikation erstellt werden. Wenn ein Sound aus einem Sekundrbuffer abgespielt wird, so wird dieser von DirectSound automatisch dem Primrbuffer hinzugemischt. Sollten mehrere Sekundrbuffer gleichzeitig abgespielt werden, so enthlt der Primrbuffer eine Mischung aller laufenden Audiodaten. Man kann sich diesen Vorgang als eine Art Audiomischpult vorstellen, wobei die Sekundrbuffer die klangerzeugenden Gerte widerspiegeln und der Primrbuffer das Mischpult reprsentiert. Die gemischten Daten im Primrbuffer werden dann zum Augabegert weitergeleitet.

4.9

Static und Streaming Soundbuffer


Wenn Sie einen SecoundarySoundBuffer erzeugen, mssen Sie DirectSound mitteilen, ob es sich um einen Static oder einem Streaming Soundbuffer handelt. Ein Static Soundbuffer speichert einen kompletten Sound in seinem Speicherbereich, ein Streaming Soundbuffer hingegen speichert immer nur einen Ausschnitt des gesamten Samples, wobei Ihre Applikation periodisch neue Daten in den Streamingbuffer schreiben muss.

292

Erzeugen von Soundbuffern

Hat Ihre Audiohardware einen eigenen Speicher, wird DirectSound versuchen, einen Static Soundbuffer in diesem zu erzeugen. Um ein effizientes Schreiben von Sounddaten zu gewhrleisten, werden im Allgemeinen Streaming Soundbuffer im Systemspeicher erzeugt.

2D-Ausgabe
Secondary Buffer
Static Streaming Static Streaming Buffer Buffer Buffer Buffer

Primary Buffer
Streaming Buffer

Ausgabe
Bild 4.3: 2D-Soundausgabe

4.10

Erzeugen von Soundbuffern


Um Audiodaten in einem Soundbuffer zu speichern, mssen wir diesen zuerst einmal erzeugen. Hierzu dient die von DirectSound bereitgestellte CreateSoundBuffer()-Methode.

Kapitel 4 DirectSound

293

CreateSoundBuffer() Erstellt einen DirectSoundBuffer DirectSound.DuplicateSoundBuffer(), DirectSound.SetCooperativeLevel(), DirectSoundBuffer.GetFormat(), DirectSoundBuffer.GetVolume(), DirectSoundBuffer.Play(), DirectSoundBuffer.SetFormat(), DirectSoundBuffer.SetFrequency() object.CreateSoundBuffer(bufferDesc As DSBUFFERDESC, _ format As WAVEFORMATEX) As DirectSoundBuffer Object BufferDesc format ein gltiges DirectSound-Objekt DSBUFFERDESC-Typ beinhaltet die Beschreibung zum Erstellen eines Soundbuffers. WAVEFORMATEX-Typ beschreibt das Wellenformat der Audiodaten.

Anhand eines Beispiels erstellen wir einen Secondary Static-Soundbuffer.


Public Sub CreateSoundBuffer() Dim m_dsb As DirectSoundBuffer Dim buffdesc As DSBUFFERDESC Dim format As WAVEFORMATEX

Zuerst muss das Waveformat bestimmt werden.


format.nFormatTag = WAVE_FORMAT_PCM format.nChannels = 2 format.lSamplesPerSec = 22050 format.nBitsPerSample = 16 format.nBlockAlign = _ (format.nChannels * format.nBitsPerSample)/ 8 format.lAvgBytesPerSec = _ format.lSamplesPerSec * format.nBlockAlign format.nSize = 0

Beschreibung des Soundbuffers


buffdesc.lBufferBytes = format.lAvgBytesPerSec buffdesc.lFlags = DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME Or DSBCAPS_CTRLFREQUENCY Or DSBCAPS_STATIC _

Soundbuffer erzeugen
Set m_dsb = m_ds.CreateSoundBuffer(buffdesc, format) End Sub

Sie sollten fr Ihre Applikation die Soundbuffer, die am meisten abgespielt werden, zuerst erstellen. Dies wirkt sich positiv auf die Performance der Anwendung aus, da Hardwareressourcen der Soundkarte zuerst aufgebraucht werden.

294

Buffer-Einstellungen

Mchten Sie hingegen selbst bestimmen, ob ein Sound in den Speicher der Soundkarte oder im Systemspeicher des Rechners geladen werden soll, so knnen Sie dieses ber die Flags DSBCAPS_LOCHARDWARE oder DSBCAPS_ LOCSOFTWARE festlegen. ber das DSBCAPS_STATIC-Flag teilen Sie Direct Sound den Buffertype mit. Ist dieses Flag gesetzt, wird ein Static Soundbuffer erzeugt, ansonsten geht DirectSound davon aus, das es sich bei diesem Buffer um einen Streaming Soundbuffer handelt.
objekt.CreateSoundBuffer(bufferDesc as DSBUFFERDESC, format as_ WAVEFORMATEX) as DirectSoundBuffer

4.11

Buffer-Einstellungen
Wenn Sie Soundbuffer erzeugen, muss Ihre Applikation diese ber die lFlags im DSBUFFERDESC spezifizieren. Zulssige Werte bekommen Sie ber die Konstanten-Enumeration DSBCAPS_CTRL. 3D-Einstellungen Frequenz Pan Lautstrke Positionsmitteilungen

Um einen dieser Parameter eines Soundbuffers zu verndern, muss dieser beim Erstellen des Soundbuffers ber die lFlags freigegeben werden. Wurde dieses unterlassen, fhrt z.B. eine nderung der Lautstrke ber die DirectSound Buffer.SetVolume()-Methode zwangslufig zu einem Fehler.

4.12

Buffer Playback Controls


Zum Einstellen und Auslesen der aktuellen Lautstrke eines Soundbuffers benutzen Sie in Ihrer Applikation die DirectSoundBuffer.GetVolume()- und Direct SoundBuffer.SetVolume()-Methoden. Verndern Sie die Lautstrkeeinstellung des Primary Soundbuffers, so verndern Sie damit die Masterlautstrke Ihrer Soundkarte.
GetFrequency() Empfngt die Frequenz in Samples pro Sekunde DirectSoundBuffer.SetFrequency() object.GetFrequency() As Long object ein gltiges DirectSoundBuffer-Objekt

Kapitel 4 DirectSound

295

GetFrequency() Gltige Werte liegen im Bereich von DSBFREQUENCY_MIN und DSBFREQUENCY_MAX (100 100.000 Samples pro Sekunde) object volume ein gltiges DirectSoundBuffer-Objekt neuer Lautstrkewert

Gltige Werte liegen im Bereich von DSBVOLUME_MIN (keine Abschwchung 0db) und DSBVOLUME_MAX (grte Abschwchung 100db) SetFrequency() Setzt die Frequenz, in der Audiosamples abgespielt werden. object.SetFrequency(frequency As Long) object frequency ein gltiges DirectSoundBuffer-Objekt neue Frequenz in Hertz (Hz)

Gltige Werte liegen im Bereich von DSBFREQUENCY_MIN und DSBFREQUENCY_MAX (100 100.000 Samples pro Sekunde) Gltige Werte liegen im Bereich von DSBVOLUME_MIN (keine Abschwchung 0db) und DSBVOLUME_MAX (grte Abschwchung 100db) GetPan() Empfngt einen Panwert, der die Lautstrkebalance der Lautsprecher beschreibt. DirectSoundBuffer.SetPan() object.GetPan() As Long object ein gltiges DirectSoundBuffer-Objekt

Gltige Werte liegen im Bereich von DSBPAN_LEFT (-10.000) 100db Abschwchung rechts und DSBPAN_RIGHT (+10.000) 100db Abschwchung links. DSBPAN_CENTER ( 0 ) beschreibt die normale Mittelstellung. SetVolume() Setzt die aktuelle Lautstrke eines Soundbuffers object.SetVolume(volume As Long) SetPan() Setzt einen Panwert, der die Lautstrkebalance der Lautsprecher beschreibt. DirectSoundBuffer.GetPan() object.SetPan(pan As Long) object ein gltiges DirectSoundBuffer-Objekt

296

Ein einfaches Soundbeispiel

SetPan() pan neuer Panoramawert

Gltige Werte liegen im Bereich von DSBPAN_LEFT (-10.000) 100db Abschwchung rechts und DSBPAN_RIGHT (+10.000) 100db Abschwchung links. DSBPAN_CENTER ( 0 ) beschreibt die normale Mittelstellung. GetVolume() Empfngt die aktuelle Lautstrke eines Soundbuffers object.GetVolume() As Long object ein gltiges DirectSoundBuffer-Objekt

ber die Methoden DirectSoundBuffer.GetFrequency() und DirectSound Buffer.SetFrequency() verndern Sie die Geschwindigkeit, mit der DirectSound ein Sample abspielt. Je hher die Abspielgeschwindigkeit, desto hher ist die Tonlage des Sounds und umgekehrt. Sie kennen diesen Effekt von Harmonizern, z.B. die Stimme der Schlmpfe wurde auf diese Weise erzeugt, indem man die Stimmen schneller abspielen lie, als sie aufgenommen wurden. Vernderungen dieses Parameters knnen Sie nur auf dem sekundren Soundbuffer anwenden. Frequenznderungen am primren Soundbuffer bleiben ohne Auswirkung. Mit der DirectSoundBuffer.GetPan()- und DirectSoundBuffer.SetPan()-Methode verndern Sie das Lautstrkeverhltnis der Lautsprecher zueinander. Diese Funktion ist vergleichbar mit dem Panoramaregler an einer normalen Stereoanlage.

4.13

Ein einfaches Soundbeispiel


Dim m_dx As New DirectX7 Dim m_ds As DirectSound Dim m_dsBuffer As DirectSoundBuffer Dim m_bLoaded As Boolean Private Sub Form_Load() Me.Show On Local Error Resume Next

DirectSound-Objekt mit primren Audiotreiber erstellen


Set m_ds = m_dx.DirectSoundCreate("") If Err.Number <> 0 Then MsgBox "Audiohardware nicht gefunden !" End End If

Kapitel 4 DirectSound

297

Zugriff anderer Applikationen auf das Audiogert ber den DirectSound-Cooperative-Level schtzen.
m_ds.SetCooperativeLevel Me.hWnd, DSSCL_PRIORITY End Sub Sub LoadWave(sfile As String) Dim bufferDesc As DSBUFFERDESC Dim waveFormat As WAVEFORMATEX

Zugriff auf Frequenz, Pan, Volumen erlauben und Soundbuffer als Staticbuffer deklarieren.
bufferDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or _ DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME Or DSBCAPS_STATIC

Wellenformformat festlegen
waveFormat.nFormatTag = WAVE_FORMAT_PCM waveFormat.nChannels = 2 waveFormat.lSamplesPerSec = 22050 waveFormat.nBitsPerSample = 16 waveFormat.nBlockAlign = waveFormat.nBitsPerSample / 8 * _ waveFormat.nChannels waveFormat.lAvgBytesPerSec = waveFormat.lSamplesPerSec _ * waveFormat.nBlockAlign Set m_dsBuffer = _ m_ds.CreateSoundBufferFromFile(sfile, bufferDesc,waveFormat) End Sub Private Sub Command1_Click() LoadWave App.Path & "\Test.wav"

Wavefile abspielen
m_dsBuffer.Play DSBPLAY_DEFAULT End Sub

DirectSoundBuffer.Play DirectSoundBuffer.Stop

Zum einfachen Abspielen der geladenen Samples reicht nun der Aufruf m_ds Buffer.play(). Als mgliche bergabeparameter stehen zur Auswahl DSBPLAY_ DEFAULT und DSBPLAY_LOOPING. Der erste Parameter spielt den eingelesenen Sound einmal ab und beendet dann die Playroutine. Der zweite bergabewert setzt die Playroutine in eine Endlosschleife, die nur ber m_dsBuffer.stop() angehalten werden kann. Ein erneutes Aufrufen der Play()-Methode startet das Sample von vorn.
objekt.Play(flags as CONST_DSBPLAYFLAGS)

298

Ein einfaches Soundbeispiel

objekt.Stop()

DirectSoundBuffer.SetVolume() DirectSoundBuffer.GetVolume()

Um die Abspiellautstrke eines Samples zu ndern, wird die SetVolume()Methode bentigt. Diese setzt die Lautstrke in einem gltigen Bereich von -10.000 bis 0 ( in x / 100 db), wobei -10.000 die kleinste und 0 die grte Lautstrke wiedergibt. (Abschwchung von 0 100 db) Zu beachten ist, dass die Lautstrke erst nach dem Laden eines Wavefiles und vor dem Aufruf der Play()-Methode gesetzt wird. Ein Sample wird immer mit der Lautstrke 0 (am lautesten) geladen. Man kann ber die Lautstrkereglung prinzipiell nur eine Abschwchung der Lautstrke erreichen.
objekt.SetVolume(volume as Long) objekt.GetVolume() as Long

DirectSoundBuffer.SetPan DirectSoundBuffer.GetPan

Die Balanceregelung zwischen zwei Lautsprechern wird mit der Methode DirectSoundBuffer.SetPan() verndert. Ein groer negativer Wert bewirkt, dass der Sound nur noch auf dem linken Lautsprecher zu hren ist, wobei hingegen ein groer positiver Wert die Ausgabe auf den rechten Lautsprecher bewirkt. Ein Wert von Null setzt die Ausgabe, linker Kanal zu rechter Kanal, auf ein Verhltnis 1:1. Das Panorama ist stufenlos in einem gltigen Wertebereich von -10.000 bis +10.000 anzugeben (Abschwchung links < > rechts 100 db 0 db / 0 db 100 db).
objekt.SetPan(pan as Long) objekt.GetPan() as Long

DirectSoundBuffer.SetFrequency() DirectSoundBuffer.GetFrequency()

Auch Vernderungen an der Abspielgeschwindigkeit und damit an der Tonhhe des abzuspielenden Samples sind ber die Soundbuffer mglich. Empfehlenswert ist es nach dem Laden einer Wavedatei mit der Methode DirectSoundBuffer.GetFrequency() die original Samplefrequenz auszulesen. Nur ein Abspielen in dieser Frequenz hlt die Original-Tonhhe bei. Wird mit DirectSoundBuffer.Set Frequency() die Geschwindigkeit nicht verndert, so wird DirectSound das Sample in seiner Ursprungsfrequenz abspielen.

Kapitel 4 DirectSound

299

Gltige Breiche fr Frequenznderungen mit SetFrequency() sind 100-100.000 (100 Hz bis 100 kHz). Werte auerhalb dieses Bereichs fhren zu einem Fehler.
objekt.SetFrequency(frequency as Long) objekt.GetFrequency() as Long

DirectSoundBuffer.SetFormat() DirectSoundBuffer.GetFormat()

DirectSoundBuffer.SetFormat() setzt das Waveformat des primren Soundbuffers fr die Applikation. Immer dann, wenn eine Anwendung den Fokus erhlt, setzt DirectSound fr die Anwendung das spezifische Waveformat.
objekt.SetFormat(format as WAVEFORMATEX) objekt.GetFormat(format as WAVEFORMATEX)

DirectSoundBuffer.SetCurrentPosition() DirectSoundBuffer.GetCurrentPosition()

DirectSoundBuffer.SetCurrenPosition() setzt die aktuelle Abspielposition (play cursor) auf den angegebenen Wert. DirectSoundBuffer.GetCurrentPosition() liest die aktuelle Abspielposition und Aufnahmeposition und schreibt sie in den Typenblock DSCURSORS.
objekt.SetCurrentPosition(newPosition as Long) objekt.GetCurrentPosition(cursor as DSCURSORS) Type DSCURSORS lPlay as Long lWrite as Long End Type

4.14

Der PlayCursor
DirectSound setzt zwei Zeiger im Soundbuffer. Zum einen die aktuelle Abspielposition (PlayCursor) und zum anderen die aktuelle Aufnahmeposition (Write Cursor). Diese Werte reprsentieren einen Offsetadresse im Speicher und sind keine absoluten Adressen, sondern die Differenz zwischen aktueller Position und Startadresse des Buffers.
Play() Gibt den Befehl zum Abspielen eines Soundbuffers. object.Play(flags As CONST_DSBPLAYFLAGS)

300

Der PlayCursor

Play() object flags Stop() Gibt den Befehl zum Anhalten eines Soundbuffers. object.Stop() object ein gltiges DirectSoundBuffer-Objekt ein gltiges DirectSoundBuffer-Objekt vom Typ CONST_DSBPLAYFLAGS

GetCurrentPosition() Empfngt die aktuelle Lese- und Schreibeposition des Cursors. DirectSoundBuffer.SetCurrentPosition() object.GetCurrentPosition(cursors As DSCURSORS) object cursors ein gltiges DirectSoundBuffer-Objekt Playcursor vom Typ DSCURSORS

SetCurrentPosition() Setzt den Soundcursor auf die angegebene Position. object.SetCurrentPosition(newPosition As Long) object newPosition ein gltiges DirectSoundBuffer-Objekt neue Position in Bytes vom Anfang des Buffers

Die DirectSoundBuffer.Play()-Methode startet das Abspielen eines Sounds immer ab der aktuellen Abspielposition. Wenn der Soundbuffer gerade erzeugt wurde, steht der PlayCursor auf Position Null. Beim Abspielen des Sounds bewegt sich der PlayCursor stetig von Byte zu Byte und gibt somit die nchste Position der abzuspielenden Daten an. Wird die Ausgabe des Samples gestoppt, bleibt der PlayCursor beim nchsten abzuspielenden Byte stehen. Bei einer Aufnahme luft der PlayCursor leicht versetzt und in der gleichen Geschwindigkeit hinter dem WriteCursor her. Daten die einmal vom WriteCursor geschrieben wurden, werden auf jeden Fall vom PlayCursor abgespielt. Die aktuellen Positionen des PlayCursors und des WriteCursors erhalten Sie ber die Methoden DirectSoundBuffer.GetCurrentPosition() und DirectSoundBuffer. SetCurrentPosition(). Die aktuelle Schreibposition kann nicht verndert werden.

Kapitel 4 DirectSound

301

Um zu garantieren, das die aktuelle Abspielposition richtig ist, setzen Sie beim Erstellen des Buffers das lFlag DSBCAPS_GETCURRENTPOSITION2 in der Bufferbeschreibung DSBUFFERDESC.

4.15

Playbuffer-Benachrichtigungen
Es kann erwnscht sein, dass beim Abspielen von Samples Ihrer Applikation an einer oder mehreren Stellen ber den aktuellen Stand des Soundbuffers informiert werden soll. Mit DirectSoundBuffer.SetNotificationPosition() (setze Benachrichtigungsposition) knnen beliebige Punkte im Soundbuffer als Ereignispunkte gesetzt werden. Das Anlegen dieser Punkte funktioniert nicht, wenn ein Sound abgespielt wird. Um ein Benachrichtigungsereignis im Soundbuffer zu setzen, muss zuerst das DirectXEvent-Objekt implementiert werden. Dann erst knnen Ereignisse ber die DirectX7.CreateEvent()-Methode gesetzt werden.
SetNotificationPositions() Setzt die Notifications Position in einem Soundbuffer. object.SetNotificationPositions(nElements As Long, _ psa() As DSBPOSITIONNOTIFY) object nElements psa() ein gltiges DirectSoundBuffer-Objekt Nummer vom Typ DSBPOSITIONNOTIFY ein Array von DSBPOSITIONNOTIFY

4.16

Direct3DSound
Sicherlich lassen sich mit den Eigenschaften von DirectSound, wie wir sie bisher kennengelernt haben, viele Dinge realisieren. Stellen Sie sich jetzt mal vor, Sie programmieren ein 3D-Abenteuerspiel und wrden nun die Soundeffekte in Ihr Programm einfgen. Ok, Sie knnten zur richtigen Zeit den richtigen Sample abspielen, dieses htte aber den Nachteil, dass ein Gerusch, das vielleicht durch einen Gegner, der in Ihrer 3D-Welt zehn Meter von Ihnen entfernt steht, genauso laut ist wie eine andere Geruschquelle, die direkt vor Ihnen steht. Weiterhin wrden Sie vom Klangbild immer hren, dass der Gegner immer von vorne kommt, obwohl sich Ihre Spielfigur von der Klangquelle wegdreht. Manche werden nun sagen, das macht nichts, dann verndere ich eben die Lautstrke permanent im Verhltnis zur Distanz zu meinem Gegner. Weiterhin regele ich ber die Panoramaregelung die Richtung aus der die Schallwellen zu hren sind. Sie merken schon, dass dieses Verfahren wohl recht umfangreich und kompliziert werden knnte und nicht im Sinne des Erfinders sein kann.

302

Direct3DSound

Glcklicherweise haben uns die Entwickler von DirectSound dieses Problem schon abgenommen. Mit Direct3DSound erhlt der Anwender ein leistungsstarkes Tool zum richtigen Positionieren von Geruschquellen und anderen Soundeffekten im 3D-Raum. Berechnungen ber die Richtung oder Lautstrke, ja selbst mathematische Funktionen, die annhernd das menschliche Hren nachempfinden, sind in DirectSound verwirklicht worden und untersttzen die Entwickler von 3D-Spielen und anderen Anwendungen mit erstklassigen und ausgereiften Funktionen.

4.16.1 Grundlagen
Die DirectSound3DBuffer- und DirectSound3DListener-Schnittstellen arbeiten gemeinsam mit Direct3D. Positionierungsvektoren, die z.B. die Position eines virtuellen Gegners in einem Spiel darstellen, knnen sofort in ein rumliches Klangbild bernommen werden.
GetDistanceFactor() Empfngt den aktuellen Entfernungsfaktor. DirectSound3DListener.SetDistanceFactor() object.GetDistanceFactor() As Single object ein gltiges DirectSound3DListener-Objekt

SetDistanceFactor() Setzt den aktuellen Entfernungsfaktor. DirectSound3DListener.GetDistanceFactor() object.SetDistanceFactor(distanceFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object distanceFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer Entfernungsfaktor Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound unterscheidet zwischen zwei Arten von Soundpositionen im Raum DirectSound3DBuffer DirectSound3DListener

Der DirectSound3DBuffer stellt die Schallquelle da. Diese beinhaltet einen Static Soundbuffer, in dem sich das eigentliche Sample befindet. Sie kann ber dreidimensionale Positionskoordinaten frei im Raum bewegt werden.

Kapitel 4 DirectSound

303

Das DirectSound3DListener-Objekt symbolisiert den Zuhrer. Wie der DirectSound3DBuffer kann auch dieser Buffertype im 3D-Raum eine beliebige Position einnehmen. Die Entfernungen und Positionen werden bei DirectSound in Metern angegeben. Alle Berechnungen, die DirectSound vornimmt, legen diesen Mastab zugrunde. Sollten Sie den Mastab in der grafischen Ebene anders gewhlt haben, knnen sie einen Distanzfaktor angeben. DirectSound wird dann alle akustischen Positionsdaten mit diesem Faktor multiplizieren.

4.16.2 Mono- und Stereo-Soundquellen


Stereo Samples sind nicht besonders ntzlich in einer 3D-Soundumgebung von DirectSound. In der Realitt sind natrliche Schallquellen immer mono. Erst durch die Positionierung im Raum und durch das Verhltnis der Lautstrken, Richtungen und Entfernungen zum Hrer (Listener) und anderen Klangquellen ergibt sich aus der Summe ein realistischer Stereosound. Nicht anders geschieht dies bei DirectSound. Sie positionieren mehrere Soundbuffer die Monosamples enthalten an verschiedenen Stellen im virtuellen 3DRaum. Diese werden dann von DirectSound, je nach Abstand und Ausrichtung zum Listener, dem primren Soundbuffer zugemischt. In der realen Welt hngt das Hren von Geruschen von vielen Faktoren ab. Volume Beschreibt die Abnahme der Lautstrke mit der Entfernung der Schallquelle vom Zuhrer. Die zwei anzugebenden Gren sind die minimale und maximale Distanz. Interaural Intensity Difference Dieses Phnomen beschreibt die Frequenzverschiebung einer Schallwelle, wenn Sender und Empfnger sich relativ zueinander bewegen. Bewegt sich eine Geruschquelle auf einen Zuhrer zu, werden die Schallwellen zusammengestaucht. Dadurch wird der zu hrende Ton in seiner Stimmlage hher. Bewegt er sich vom Zuhrer weg, werden Schallwellen auseinander gezogen und klingen somit tiefer.

Dieser Effekt ist sehr gut bei einem herankommenden Feuerwehrwagen zu erkennen. Die Sirene wird sofort eine Stimmlage tiefer, wenn der Wagen an einem vorbeigefahren ist und sich somit von Ihnen entfernt. Diesen Effekt bezeichnet man auch als Dopplereffekt. Interaural Time Difference Aufgrund des krzeren Weges erreichen Gerusche, die von einer bestimmten Richtung zum Zuhrer kommen, das dieser Richtung zugewandte Ohr (Lautsprecher) frher als das jeweils andere. Diese Laufzeiten sind allerdings sehr gering und bewegen sich im Millisekundenbereich.

304

DirectSound3DBuffer

Muffling Dieser Parameter bestimmt ebenfalls die Lautstrke des Sounds anhand der Richtung, aus der die Schallwellen einfallen. Dabei werden Gerusche, die von hinten zu hren sind, beidseitig, und Schallwellen, die von links oder rechts kommen, jeweils auf der entgegengesetzten Seite mit gedmpfter Lautstrke wiedergegeben.

4.17

DirectSound3DBuffer
Die Methoden von DirectSound3DBuffer bentigen wir zum Einstellen der Parameter fr Positionierung, Ausrichtung und fr die Geruschkulisse im dreidimensionalen Raum. Die Methoden von DirectSound3DBuffer knnen in folgende Gruppen eingeteilt werden:

3D-Ausgabe
Secondary Buffer
Static Streaming Static Streaming Buffer Buffer Buffer Buffer

3D-Buffer

3D-Buffer

Primary Buffer
Streaming Buffer

Listener

Ausgabe
Bild 4.4: 3D-Soundausgabe

Parameter-Manipulation GetAllParameters() SetAllParameters()

Kapitel 4 DirectSound

305

Entfernungen GetMaxDistance() GetMinDistance() SetMaxDistance() SetMinDistance()

Auswhlen von Schallquellen GetDirectSound3Dlistener() GetDirectSoundBuffer()

Operation Modes GetMode() SetMode()

Position GetPosition() SetPosition()

Soundprojektion und -ausrichtung GetConeAngles() GetConeOrientation() GetConeOutsideVolume() SetConeAngles() SetConeOrientation() SetConeOutsideVolume()

Geschwindigkeit GetVelocity() SetVelocity()

4.17.1 Parameter-Manipulation
Mit Hilfe von DirectSound3DBuffer.GetAllParameters() knnen alle relevanten Einstellungen eines 3DBuffer-Objektes ausgelesen werden. DirectSound3DBuffer.SetAllParameters() schreibt einen vordefinierten Buffertypenblock in ein 3DBuffer-Objekt. Hier stehen allerdings zwei Mglichkeiten zur Verfgung, die ber das apply-Flag vom Typ DS3DAPPLYFLAGS unterschieden werden.

306

DirectSound3DBuffer

DS3D_IMMEDIATE schreibt einen kompletten Bufferblock in das 3DBufferObjekt. DS3D_DEFERRED hingegen verndert nur die gesetzten Parameter. Sollten Sie die DS3D_DEFERRED Einstellung verwenden, wird ein Update des 3DBufferObjektes erst ausgefhrt, nachdem die DirectSound3DListener.CommitDeferredSettings() Methode aufgerufen wurde. Hierdurch ist es mglich, mehrere vordefinierten Bufferblcke verschiedenen 3DBuffer-Objekten zuzuweisen und sie gleichzeitig anzupassen.
DirectSound3DBuffer.GetAllParameters (buffer As DS3DBUFFER) DirectSound3DBuffer.SetAllParameters (buffer As DS3DBUFFER, _ applyFlag As DS3DAPPLYFLAGS) GetAllParameters() Empfngt Informationen ber die 3D-Charakteristik eines Soundbuffers zu einer bestimmten Zeit. object.GetAllParameters(buffer As DS3DBUFFER) object buffer ein gltiges DirectSound3DBuffer-Objekt DS3DBUFFER-Typ

SetAllParameters() Setzt Informationen ber die 3D-Charakteristik eines Soundbuffers zu einer bestimmten Zeit. DirectSound3DBuffer.GetAllParameters() object.SetAllParameters(buffer As DS3DBUFFER, _ applyFlag As CONST_DS3DAPPLYFLAGS) object buffer applyFlag ein gltiges DirectSound3DBuffer-Objekt ein gltiges DirectSoundBuffer-Objekt Flag vom Typ CONST_DS3DAPPLYFLAGS

CommitDeferredSettings() bergibt die zuvor eingestellten Werte unter Verwendung des applyFlags CONST_DS3DAPPLYFLAGS object.CommitDeferredSettings() object ein gltiges DirectSound3DListener-Objekt

Kapitel 4 DirectSound

307

4.17.2 Entfernungen
Die DirectSound3DBuffer.GetMaxDistance()-Methode gibt die maximale Entfernung eines 3DBuffer-Objekts zurck. Die maximale und minimale Distanz eines 3DBuffers beschreibt, ab welcher Entfernung ein Gerusch nicht mehr zu hren ist (maximale Distanz) und ab welcher Entfernung die maximale Lautstrke einer Klangquelle erreicht ist (minimale Distanz).
GetMaxDistance() Empfngt die Maximale Entfernung eines 3D-Buffer-Objekts. DirectSound3DBuffer.GetMinDistance(), DirectSound3DBuffer.SetMaxDistance(), DirectSound3DBuffer.SetMinDistance() object.GetMaxDistance() As Single object ein gltiges DirectSound3DBuffer-Objekt

SetMaxDistance() Setzt die Maximale Entfernung eines 3D-Buffer-Objekts. DirectSound3DBuffer.GetMinDistance(), DirectSound3DBuffer.GetMaxDistance(), DirectSound3DBuffer.SetMinDistance() object.SetMaxDistance(maxDistance As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object maxDistance applyFlag ein gltiges DirectSound3DBuffer-Objekt neuer Wert der grten Entfernung Flag vom Typ CONST_DS3DAPPLYFLAGS

GetMinDistance() Empfngt die Minimale Entfernung eines 3D-Buffer-Objekts. DirectSound3DBuffer.GetMaxDistance(), DirectSound3DBuffer.SetMaxDistance(), DirectSound3DBuffer.SetMinDistance() object.GetMinDistance() As Single object ein gltiges DirectSound3DBuffer-Objekt

SetMinDistance() Setzt die Minimale Entfernung eines 3D-Buffer-Objekts. DirectSound3DBuffer.GetMinDistance(), DirectSound3DBuffer.GetMaxDistance(), DirectSound3DBuffer.SetMaxDistance() object.SetMinDistance(minDistance As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS)

308

DirectSound3DBuffer

SetMinDistance() object minDistance applyFlag ein gltiges DirectSound3DBuffer-Objekt neuer Wert der kleinsten Entfernung Flag vom Typ CONST_DS3DAPPLYFLAGS

Stellen Sie sich vor, Sie stehen in einem Garten und eine Biene nhert sich. Sie werden die Biene erst ab ca. 5 Meter hren knnen. Nachdem sie auf 10 cm herangekommen ist, hat das Tierchen seine relative maximale Lautstrke erreicht, da es nicht noch nher an Sie herankommen wird. Pltzlich hren Sie in der Weite einen Dsenjger heranfliegen. Die gleiche Lautstrke, die zuvor die Biene bei 10 Metern hatte, hat nun der Dsenjger bei 10 km. Seine relative maximale Lautstrke wird dieser bei 500 Metern haben, da er nicht nher an Sie herankommen wird. (Es sei denn, er strzte in Ihren Garten, aber dann htte sich fr Sie dieses Problem erledigt.) Um diesen Lautstrkeeffekt nachzuahmen, ist es ntig, jedem 3D-Buffer-Objekt eine minimale und eine maximale Entfernung (Distanz) mitzuteilen. Bentigt werden hierzu die unten beschriebenen Methoden. Fr das Setzen der Distanzen wird, wie schon zuvor beschrieben, das apply-Flag verwendet.
objekt.SetMaxDistance(maxDistance As Single, applyFlag As _ CONST_DS3DAPPLYFLAGS) objekt.GetMaxDistance() As Single objekt.SetMinDistance(minDistance As Single, applyFlag As _ CONST_DS4DAPPLYFLAGS) objekt.GetMinDistance() As Single

4.17.3 Auswhlen von Schallquellen


GetDirectSound3DListener() Gibt ein DirectSound3DListener Objekt zurck. object.GetDirectSound3DListener() As DirectSound3Dlistener object ein gltiges DirectSound3DBuffer-Objekt

GetDirectSoundBuffer() Gibt ein DirectSoundBuffer Objekt zurck. object.GetDirectSoundBuffer() As DirectSoundBuffer object ein gltiges DirectSound3DBuffer-Objekt

Kapitel 4 DirectSound

309

Die DirectSound3DBuffer.GetDirectSound3DListener()-Methode DirectSound3DListener-Objekt zurck.

gibt

das

ber den Aufruf der DirectSound3DBuffer.GetDirectSoundBuffer()-Methode bekommen Sie einen DirectSoundBuffer.


objekt.GetDirectSound3DListener() As DirectSound3DListener objekt.GetDirectSoundBuffer() As DirectSoundBuffer

4.17.4 Operation Mode


ber die Methode DirectSound3DBuffer.SetMode() stehen Ihnen drei Eigenschaften der CONST_DS3DMODEFLAGS zur Verfgung. DS3DMODE_DISABLE schaltet die 3D Soundausgabe aus. Alle nun abgespielten Sounds werden mittig ber die Lautsprecher ausgegeben. Der DS3DMODE_HEADRELATIVE Modus verndert die Soundparameter (Position, Velocity und Ausrichtung) relativ zu den Einstellungen des ListenerObjektes. Bei Bewegung der Schallquelle sowie des Listeners verndern sich alle Daten automatisch. Die Einstellung DS3DMODE_NORMAL setzt den Operationsmode in die Defaulteinstellung zurck. Auch hierbei ist zu beachten, das nderungen an diesen Parameter erst nach einem DirectSound3DListener.CommitDeferredSettings()-Aufruf bergeben werden.
GetMode() Empfngt den Operationsmode des aktuellen 3D-Sound-Prozesses. DirectSound3DBuffer.SetMode() object.GetMode() As CONST_DS3DMODEFLAGS object ein gltiges DirectSound3DBuffer-Objekt

Rckgabewerte vom Typ CONST_DS3DMODEFLAGS SetMode() Setzt den Operationsmode des aktuellen 3D-Sound-Prozesses. DirectSound3DBuffer.GetMode() object.SetMode(mode As CONST_DS3DMODEFLAGS, _ applyFlag As CONST_DS3DAPPLYFLAGS) object mode applyFlag ein gltiges DirectSound3DBuffer-Objekt Wert vom Typ CONST_DS3DMODEFLAGS Flag vom Typ CONST_DS3DAPPLYFLAGS

310

DirectSound3DBuffer

CommitDeferredSettings() bergibt die zuvor eingestellten Werte in Verwendung des applyFlags. CONST_DS3DAPPLYFLAGS object.CommitDeferredSettings() object ein gltiges DirectSound3DListener-Objekt

objekt.DirectSound3DBuffer.SetMode _ (mode As CONST_DS3DMODEFLAGS, _ applyFlag As CONST_DS3DAPPLYFLAGS) objekt.DirectSound3DBuffer.GetMode() as CONST_DS3DMODEFLAGS

4.17.5 Position
Die Position einer Schallquelle (DirectSound3DBufferObjekt) kann beliebig ber die DirectSound3DBuffer.SetPosition()-Methode verndert werden. Somit knnen Bewegungen von grafischen Komponenten im 3D-Raum auch akustisch hrbar gemacht werden. Die Positionen werden in x-, y-, z-Koordinaten angegeben. ber einen Distanzfaktor DirectSound3DListener.SetDistanceFactor() kann die akustische Position der grafischen Komponente angepasst werden. Es empfiehlt sich allerdings, den grafischen Mastab in Metern festzulegen. DirectSound verwendet die metrische Aufteilung, um Laufzeiten von Schallwellen zu berechnen. Auch hierbei gilt die bernahme durch das apply-Flag. Die Rckgabe der Position mit DirectSound3DBuffer.GetPosition() erfolgt in einem Vektor (v.x, v.y, v.z) vom Typ D3DVECTOR.
GetPosition() Empfngt die Position eines 3DSoundBuffers im 3D-Raum. DirectSound3DBuffer.SetPosition() object.GetPosition(position As D3DVECTOR) object position SetPosition() Setzt die Position eines 3DSoundBuffers im 3D-Raum. DirectSound3DBuffer.GetPosition() object.SetPosition(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object ein gltiges DirectSound3DBuffer-Objekt ein gltiges DirectSound3DBuffer-Objekt 3D-Position (x, y, z) in Metern

Kapitel 4 DirectSound

311

SetPosition() x,y,z applyFlag Koordinaten der neuen Position Flag vom Typ CONST_DS3DAPPLYFLAGS

GetDistanceFactor() Empfngt den aktuellen Entfernungsfaktor. DirectSound3DListener.SetDistanceFactor() object.GetDistanceFactor() As Single object ein gltiges DirectSound3DListener-Objekt

SetDistanceFactor() Setzt den aktuellen Entfernungsfaktor. DirectSound3DListener.GetDistanceFactor() object.SetDistanceFactor(distanceFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object distanceFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer Distancefaktor Flag vom Typ CONST_DS3DAPPLYFLAGS

objekt.SetPosition(x As Single, y As Single, z As Single, _ applyFlag as CONST_DS3DAPPLYFLAGS) objekt.GetPosition(position as D3DVECTOR)

4.17.6 Soundprojektion und -ausrichtung


Um eine realistische Soundprojektion zu erhalten, ist es wichtig, dass Parameter wie Abstrahlwinkel und Abstrahlverhalten einer Geruschquelle bercksichtigt werden. DirectSound stellt hierzu mehrere Parameter zur Verfgung. ber einen Trichter, den so genannten Cone, werden Ausbreitung und Richtung einer Schallquelle angegeben.
GetConeAngles() Empfngt die Winkel des inneren und ueren Klangtrichters. DirectSound3DBuffer.SetConeAngles() object.GetConeAngles(inCone As Long, outCone As Long) object inCone outCone ein gltiges DirectSound3Dbuffer-Objekt Winkel des inneren Klangtrichters Winkel des ueren Klangtrichters

312

DirectSound3DBuffer

GetConeOrientation() Empfngt die Ausrichtung des Klangtrichters. DirectSound3DBuffer.SetConeOrientation() object.GetConeOrientation(orientation As D3DVECTOR) object orientation ein gltiges DirectSound3DBuffer-Objekt dieser Vektor stellt die Mitte des Klangtrichters dar

GetConeOutsideVolume() Empfngt die Lautstrke des ueren Klangtrichters. DirectSound3DBuffer.SetConeOutsideVolume() object.GetConeOutsideVolume() As Long object ein gltiges DirectSound3DBuffer-Objekt

Die Lautstrke wird als Abschwchung angegeben. Ein grerer Wert bedeutet grere Abschwchung und somit eine geringere Lautstrke. Gltige Bereiche liegen zwischen DSBVOLUME_MAX (keine Abschwchung) und DSBVOLUME_MIN (grte Abschwchung). Der Standardwert ist DS3D_DEFAULTCONEOUTSIDEVOLUME (keine Abschwchung) SetConeAngles() Setzt die Winkel des inneren und ueren Klangtrichters. DirectSound3DBuffer.GetConeAngles() object.SetConeAngles(inCone As Long, outCone As Long, _ applyFlag As CONST_DS3DAPPLYFLAGS) object inCone outCone applyFlag ein gltiges DirectSound3DBuffer-Objekt Winkel des inneren Klangtrichters Winkel des ueren Klangtrichters Flag vom Typ CONST_DS3DAPPLYFLAGS

SetConeOrientation() Setzt die Ausrichtung des Klangtrichters. DirectSound3DBuffer.GetConeOrientation() object.SetConeOrientation( x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DBuffer-Objekt Koordinaten der neuen Ausrichtung Flag vom Typ CONST_DS3DAPPLYFLAGS

Kapitel 4 DirectSound

313

SetConeOutsideVolume() Setzt die Lautstrke des ueren Klangtrichters. DirectSound3DBuffer.GetConeOutsideVolume() object.SetConeOutsideVolume(coneOutsideVolume As Long, _ applyFlag As CONST_DS3DAPPLYFLAGS) object coneOutsideVolume applyFlag ein gltiges DirectSound3DBuffer-Objekt erlaubte Werte liegen im Bereich von DSBVOLUME_MAX (keine Abschwchung), DSBVOLUME_MIN (grte Abschchung) Flag vom Typ CONST_DS3DAPPLYFLAGS

Wir unterscheiden zwei Arten von Cones: des inneren (Inside Cone) und dem ueren (Outside Cone). Fr das bessere Verstndnis empfiehlt es sich, sich eine Schallquelle als einen Lautsprecher vorzustellen. Sie knnen den Lautsprecher in eine beliebige Richtung drehen, dies hat schon mal den Effekt, dass diejenigen Zuhrer, die Sie direkt anstrahlen, den Ton am lautesten hren werden. Der ffnungswinkel des trichterfrmigen Bereichs, der sich am lautesten ausbreitet, wird als Inside Cone angegeben. Den Schalltrichterbereich um diesen herum bezeichnet man als Outside Cone. Beide Trichtergren werden als Winkelgre definiert. InCone und OutCone werden in Radiant (0 360 Grad) / (180/pi) oder (WinkelInGrad / 57.2957) angegeben und reprsentieren den ffnungswinkel des inneren und ueren Schalltrichters.
objekt.SetConeAngles(inCone As Long, outCone As Long, _ applyFlag as CONST_DS3DAPPLYFLAGS) objekt.GetConeAngles(inCone As Long, outCone As Long)

Die Ausrichtung der Schalltrichter wird ber einen Vektor (x,y,z) angegeben und ber die SetConeOrientation()-Methode bestimmt.
objekt.SetConeOrientation(x As Single, y As Single, z As _ Single, applyFlag as CONST_DS3DAPPLYFLAGS) objekt.GetConeOrientation(orientation as D3DVECTOR)

Die Laustrke auerhalb des ueren Schalltrichters wird ber die Methode SetConeOutsideVolume() beschrieben. Die Lautstrke ist in (x * 100 db) anzugeben. Erlaubte Werte sind DSBVOLUME_MAX (keine Abschwchung laut) und DSBVOLUME_MIN (grte Abschwchung leise)
objekt.SetConeOutsideVolume(coneOutsideVolume As Long, _ applyFlag as CONST_DS3DAPPLYFLAGS) objekt.GetConeOutsideVolume() As Long

314

DirectSound3DBuffer

Sound Cones

Schallquelle

n a t s i

uere Cone

uere Cone

Innere Cone

Inside Volume
Transitional Volume
Bild 4.5: Schallkegel

4.17.7 Geschwindigkeit
ber die SetVelocity()-Methode werden Dopplereffekte erzeugt. Der VelocityWert reprsentiert eine Geschwindigkeit, mit der sich die Schallquelle oder der Zuhrer relativ zu einem Objekt hin- oder fortbewegt. Der Velocity-Wert wird als Vektor angegeben. Die Lnge des Vektors beschreibt die Geschwindigkeit in Meter pro Sekunde, die Richtung des Vektors beschreibt die Bewegungsrichtung der Schallquelle.
GetVelocity() Empfngt die Geschwindigkeit, mit der sich ein 3DBuffer im Raum bewegt. DirectSound3DBuffer.SetVelocity() object.GetVelocity(velocity As D3DVECTOR) object velocity ein gltiges DirectSound3DBuffer-Objekt Wert in Meter pro Sekunde

Velocity wird zum Errechnen des Dopplereffektes bentigt.

Kapitel 4 DirectSound

315

SetVelocity() Empfngt die Geschwindigkeit, mit der sich ein 3DBuffer im Raum bewegt. DirectSound3DBuffer.GetVelocity() object.SetVelocity(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DBuffer-Objekt Koordinaten des Richtungsvektors Flag vom Typ CONST_DS3DAPPLYFLAGS

Velocity wird zum Errechnen des Dopplereffektes bentigt. objekt.SetVelocity (x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) objekt.GetVelocity (velocity As D3DVECTOR)

4.18

DirectSound3DListener
Der DirectSound3DListener reprsentiert in DirectSound den Zuhrer und damit den Anwender, der vor seinem Computer sitzt und das Geschehen auf dem Bildschirm verfolgt. Um ihn nun nicht nur grafisch in eine andere Welt zu versetzen, sondern auch akustisch, simuliert DirectSound einen beweglichen Zuhrer in einem Raum. Man geht sogar noch weiter, als nur die Position des Listeners zu verndern. ber verschiedene Parameter knnen auch die Kopfausrichtung und Kopfneigung sowie die relative Geschwindigkeit bestimmt werden. Weiterhin ist es auch hier wie bei den Soundquellen mglich, einen Distanzfaktor zur Umrechnung des grafischen in den akustischen Mastabes anzugeben. Hierbei sei nochmals erwhnt, dass es sich anbietet, von vornherein den grafischen Mastab in Metern zu whlen, da dieses die Umsetzung in den akustischen Raum wesentlich erleichtert. Fr das DirectSound3DListener-Objekt stehen folgende Klassen zur Verfgung: Parameter-Manipulation GetAllParameters() SetAllParameters()

Verzgerungseinstellungen CommitDeferredSettings()

Entfernungsfaktoren GetDistanceFactor() SetDistanceFactor()

316

DirectSound3DListener

Dopplerfaktoren GetDopplerFactor() SetDopplerFactor()

Auswahlmglichkeiten GetDirectSoundBuffer()

Ausrichtung GetOrientation() SetOrientation()

Position GetPosition() SetPosition()

Abschwchung GetRolloffFactor() SetRolloffFaktor()

Geschwindigkeit GetVelocity() SetVelocity()

4.18.1 Parameter-Manipulation
ber die GetAllParameters()- und SetAllParameters()-Methoden haben Sie die Mglichkeit, dem Listener-Objekt eine Liste vom Typ DS3DLISTENER zu bergeben oder diese zu empfangen.
objekt.GetAllParameters(listener As DS3DLISTENER) objekt.SetAllParameters(listener As DS3DLISTENER, _ applyFlag As CONST_DS3DAPPLYFLAGS) Type DS3DLISTENER distanceFactor As Single dopplerFactor As Single rolloffFactor As Single vOrientFront As D3DVECTOR vOrientTop As D3DVECTOR vPosition As D3DVECTOR vVelocity As D3DVECTOR End Type

Kapitel 4 DirectSound

317

4.18.2 Verzgerungseinstellungen
Die DirectSound3DListener.CommitDeferredSettings()-Methode bermittelt an DirectSound die fr den 3DBuffer und den 3DListener eingestellten oder vernderten Parameter. ber die Art der bergabe entscheidet das zuvor mit dem Aufruf bergebene apply-Flag.
DirectSound3DListener.CommitDeferredSettings()

4.18.3 Entfernungsfaktoren
DirectSound3DListener.SetDistanceFactor() verndert den Faktor mit dem DirectSound Positionsdaten einer Klangquelle im 3D-Raum multipliziert. Diese Methode dient zur Anpassung des grafischen an den akustischen Mastabes. Die DirectSound3DListener.GetDistanceFactor()-Methode liest den aktuellen Distanzfaktor ab.
DirectSound3DListener.SetDistanceFactor(distanceFaktor As _ Single, applyFlag As CONST_DS3DAPPLYFLAGS) DirectSound3DListener.GetDistanceFactor() As Single

4.18.4 Dopplerfaktoren
Die Methoden DirectSound3DListener.GetDopplerFactor() und DirectSound 3DListener.SetDopplerFactor() lesen und setzen den Dopplerfaktor. Dieser Wert bestimmt die Berechnung des Dopplereffektes. Gltige Werte liegen im Bereich von DS3D_MINDOPPLERFACTOR (kein Dopplereffekt) und DS3D_MAX DOPPLERFACTOR (das 10-fache des normalen Wertes, der real herrscht). Die Standardeinstellung liegt bei DS3D_DEFAULTDOPPLERFACTOR (1.0 ).
GetDopplerFactor() Empfngt den aktuellen Wert des Dopplereffektes. DirectSound3DListener.SetDopplerFactor() object.GetDopplerFactor() As Single object ein gltiges DirectSound3DListener-Objekt

Gltige Werte liegen im Bereich DS3D_MINDOPPLERFACTOR (kein Dopplereffekt) und DS3D_MAXDOPPLERFACTOR (maximaler Dopplereffekt); die Grundeinstellung ist DS3D_DEFAULTDOPPLERFACTOR. SetDopplerFactor() Setzt den aktuellen Wert des Dopplereffektes. DirectSound3DListener.GetDopplerFactor()

318

DirectSound3DListener

SetDopplerFactor() object.SetDopplerFactor(dopplerFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object dopplerFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer Dopplerfaktor-Wert Flag vom Typ CONST_DS3DAPPLYFLAGS

4.18.5 Auswahlmglichkeiten
Die DirectSound3DListener.GetDirectSoundBuffer()-Methode gibt ein gltiges Objekt vom Typ DirectSoundBuffer zurck.
DirectSound3DListener.GetDirectSoundBuffer() As _ DirectSoundBuffer

4.18.6 Ausrichtung
Die DirectSound3DListener.SetOrientation()-Methode setzt den Zuhrer auf eine neue aktuelle Ausrichtung anhand zweier Vektoren, dem Frontvektor und dem Topvektor.
GetOrientation() Empfngt die Ausrichtung des Listenerobjektes. DirectSound3DListener.SetOrientation() object.GetOrientation(orientFront As D3DVECTOR, _ orientTop As D3DVECTOR) object orientFront orientTop ein gltiges DirectSound3DListener-Objekt Vektor fr die horizontale Ausrichtung Vektor fr die vertikale Ausrichtung

SetOrientation() Setzt die Ausrichtung des Listenerobjektes DirectSound3DListener.GetOrientation() object.SetOrientation(xFront As Single, yFront As Single, _ zFront As Single, xTop As Single, yTop As Single, zTop As _ Single, applyFlag As CONST_DS3DAPPLYFLAGS) object ein gltiges DirectSound3DListener-Objekt

Kapitel 4 DirectSound

319

SetOrientation() Front x,y,z Top x,y,z applyFlag Vektor der horizontalen Ausrichtung Vektor der vertikalen Ausrichtung Flag vom Typ CONST_DS3DAPPLYFLAGS

Der Frontvektor zeigt in Blickrichtung des Listener, der Topvektor zeigt aus dem Kopf des Listeners senkrecht nach oben. Die Grundeinstellung des Frontvektors betrgt (xyz) (0,0,1) die des Topvektors (0,1,0). Der Topvektor muss im richtigen Verhltnis zum Frontvektor angegeben werden. DirectSound aktualisiert erst den Frontvektor, dann den Topvektor.

Top Vector

Front Vector

Bild 4.6:

Ausrichtung

Der Frontvektor bestimmt die Blickrichtung, der Topvektor die seitliche Schieflage des Kopfes. Beide Vektoren mssen in einem Verhltnis von 90 zueinander ausgerichtet sein.
DirectSound3DListener.SetOrientation(xFront As Single, _ yFront As Single, zFront As Single, xTop As Single, _ yTop As Single, zTop As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) DirectSound3DListener.GetOrientation(orientFront As D3DVECTOR, orientTop As D3DVECTOR)

320

DirectSound3DListener

4.18.7 Position
Die DirectSound3DListener.SetPosition()-Methode setzt fr den Listener (Zuhrer) die aktuelle Position in Metern. Sollte der Mastab vom grafischen abweichen, kann die Position der Schallquelle ber die DirectSound3DListener.Set DistanceFactor()-Methode angepasst werden.
GetPosition() Empfngt die Position des Listenerobjektes. DirectSound3DListener.SetPosition() object.GetPosition(position As D3DVECTOR) object position SetPosition() Setzt die Position des Listenerobjektes. DirectSound3DListener.GetPosition() object.SetPosition(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DListener-Objekt Koordinate der neuen Position Flag vom Typ CONST_DS3DAPPLYFLAGS ein gltiges DirectSound3DListener-Objekt Koordinate der Position im 3D-Raum

DirectSound3DListener.SetPosition(x As Single, _ y As Single, z As Single, applyFlag As CONST_DS3DAPPLYFLAGS) DirectSound3DListener.GetPosition(position as D3DVECTOR)

4.18.8 Abschwchung
Der Rolloff-Faktor beschreibt die Abschwchung eines Sounds in Abhngigkeit der Entfernung der Schallquelle zum Zuhrer. Je grer der Rolloff-Faktor, desto leiser wird ein Gerusch bei einer konstanten Entfernung beim Zuhrer ankommen. Ein Wert von 0.0 verursacht, dass an jedem Punkt im Raum die gleiche Lautstrke herrscht. Der Wert 1.0 ist als Defaulteinstellung vorgegeben und simuliert natrliche Verhltnisse. Der Wertebereich fr den Rolloff-Faktor liegt zwischen DS3D_MINROLLOFFFACTOR (0.0) und DS3D_MAXROLLOFFFACTOR (10.0). Den Defaultwert knnen Sie aus der Konstanten DS3D_ DEFAULTROLLOFFFACTOR (1.0) entnehmen.
GetRolloffFactor() Empfngt den Rolloff-Faktor des Listenerobjektes. DirectSound3DListener.SetRolloffFactor()

Kapitel 4 DirectSound

321

GetRolloffFactor() object.GetRolloffFactor() As Single object ein gltiges DirectSound3DListener-Objekt

Gltige Werte liegen im Bereich von DS3D_MINROLLOFFFACTOR (keinRolloffeffekt) und DS3D_MAXROLLOFFFACTOR (grter Rolloffeffekt); die Grundeinstellung betrgt DS3D_DEFAULTROLLOFFFACTOR SetRolloffFactor() Setzt den Rolloff-Faktor des Listenerobjektes. DirectSound3DListener.GetRolloffFactor() object.SetRolloffFactor(rolloffFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object rolloffFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer RollOff-Faktor Flag vom Typ CONST_DS3DAPPLYFLAGS

Gltige Werte liegen im Bereich von DS3D_MINROLLOFFFACTOR (kein RolloffEffekt) und DS3D_MAXROLLOFFFACTOR (grter Rolloff-Effekt); die Grundeinstellung betrgt DS3D_DEFAULTROLLOFFFACTOR

Rolloff Faktor (0.0)

Lautstrke

(1.0) (5.0) Entfernung

Bild 4.7:

Rolloff

322

DirectSound3DListener

DirectSound3DListener.SetRolloffFactor(rolloffFactor As Single, applyFlag As CONST_DS3DAPPLYFLAGS) DirectSound3DListener.GetRolloffFactor() As Single

4.18.9 Geschwindigkeit
Der Velocity-Vektor stellt anders als die Vektoren zur Positionsbestimmung keine feste Distanz oder Richtungswert da. Er reprsentiert vielmehr eine virtuelle Gre der Geschwindigkeit in Verbindung mit einer Richtung, in die der Vektor zeigt. Der Betrag des Velocity-Vektors ist das quivalent zur Geschwindigkeit, mit der sich der Hrer im Raum in eine bestimmte Richtung bewegt. Diesen Wert bentigt DirectSound, um den Dopplereffekt zu errechnen. Je schneller sich der Zuhrer auf eine Schallquelle hin bewegt, desto grer der Dopplereffekt.
GetVelocity() Empfngt den aktuellen Velocity-Wert des Listenerobjektes. DirectSound3DListener.SetVelocity() object.GetVelocity() As D3DVECTOR object ein gltiges DirectSound3DListener-Objekt

Velocity wird zum Errechnen des Dopplereffektes bentigt. SetVelocity() Setzt den aktuellen Velocity-Wert des Listenerobjektes. DirectSound3DListener.GetVelocity() object.SetVelocity(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DListener-Objekt Neuer Vektor, der die Geschwindigkeit beschreibt. Flag vom Typ CONST_DS3DAPPLYFLAGS

Velocity wird zum Errechnen des Dopplereffektes bentigt. DirectSound3DListener.SetVelocity(x As Single, _ y As Single, z As Single, applyFlag As CONST_DS3DAPPLYFLAGS) DirectSound3DListener.GetVelocity() As D3DVECTOR

Kapitel 4 DirectSound

323

Velocity
(2,0,2) (4,0,4) (7,0,6) (2,0,2)

langsamme Bewegung
Bild 4.8: Velocity

schnelle Bewegung

4.18.10 Beispiel (Klangquellen im 3D-Raum)


Anhand des nachfolgenden Listings zeigen wir die Mglichkeiten einer dreidimensionalen Schallquelle auf. Den Quellcode finden Sie auch auf der beiligenden CD-Rom.
CreateSoundBufferFromFile() Erstellt einen DirectSoundBuffer von einer Wavedatei. object.CreateSoundBufferFromFile(filename As String, _ bufferDesc As DSBUFFERDESC, _ format As WAVEFORMATEX) As DirectSoundBuffer object filename bufferDesc format ein gltiges DirectSound-Objekt Dateiname eines Wavefiles DSBUFFERDESC Typ beinhaltet die Beschreibung zum Erstellen eines Soundbuffers. WAVEFORMATEX Typ beschreibt das Wellenformat der Audiodaten.

CreateSoundBuffer() Erstellt einen DirectSoundBuffer. DSBUFFERDESC, DirectSound.DuplicateSoundBuffer(), DirectSound.SetCooperativeLevel(), DirectSoundBuffer(), DirectSoundBuffer.GetFormat(), DirectSoundBuffer.GetVolume(), DirectSoundBuffer.Play(), DirectSoundBuffer.SetFormat(), DirectSoundBuffer.SetFrequency() object.CreateSoundBuffer(bufferDesc As DSBUFFERDESC, _ format As WAVEFORMATEX) As DirectSoundBuffer

324

DirectSound3DListener

CreateSoundBuffer() Object BufferDesc format ein gltiges DirectSound-Objekt DSBUFFERDESC Typ beinhaltet die Beschreibung zum Erstellen eines Soundbuffers. WAVEFORMATEX Typ beschreibt das Wellenformat der Audiodaten.

GetDirectSound3DBuffer() Gibt ein DirectSound3DBuffer Objekt zurck. object.GetDirectSound3DBuffer() As DirectSound3DBuffer object ein gltiges DirectSoundBuffer-Objekt

Variablendeklaration:
Dim m_dx As New DirectX7 Dim m_ds As DirectSound Dim m_dsBuffer(2) As DirectSoundBuffer Dim m_ds3dBuffer(2) As DirectSound3Dbuffer Dim m_dsPrimaryBuffer As DirectSoundBuffer Dim m_dsListener As DirectSound3Dlistener Dim m_pos(2) As D3DVECTOR Private Sub Form_Load() Dim i As Integer Me.Show DoEvents On Local Error Resume Next Set m_ds = m_dx.DirectSoundCreate("") If Err.Number <> 0 Then MsgBox "DirectSound ist nicht installiert oder Audiogert _ wurde nicht gefunden" End End If m_ds.SetCooperativeLevel Me.hWnd, DSSCL_PRIORITY Dim primDesc As DSBUFFERDESC, format As WAVEFORMATEX

Flags fr primren 3D-Buffer setzen und Listener zuweisen:


primDesc.lFlags = DSBCAPS_CTRL3D Or DSBCAPS_PRIMARYBUFFER Set m_dsPrimaryBuffer = m_ds.CreateSoundBuffer(primDesc, _ format) Set m_dsListener = m_dsPrimaryBuffer.GetDirectSound3DListener()

Zwei Schallquellen laden:


LoadWave 0, App.Path & "\Sound_5.wav" LoadWave 1, App.Path & "\Sound_6.wav"

Kapitel 4 DirectSound

325

Koordinaten im 3D-Raum der beiden Schallquellen festlegen:


m_pos(0).x = 10: m_pos(0).z = 50 m_pos(1).x = -10: m_pos(1).z = 50 HScroll1_Change i Slider1_Change DrawPositions End Sub

Routine zum Einlesen der Sounds:


Sub LoadWave(i As Integer, file As String) Dim bufferDesc1 As DSBUFFERDESC Dim waveFormat1 As WAVEFORMATEX

Flags fr Frequenz, Pan, Lautstrke, statischen Buffertyp und zustzlichen 3DSound setzen:
bufferDesc1.lFlags = (DSBCAPS_CTRL3D Or DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME) Or DSBCAPS_STATIC

Soundbuffer erzeugen und Sounds einlesen. Beim Laden werden die Bufferbeschreibung BufferDesc1 und das Waveformat waveFormat1 gesetzt.
Set m_dsBuffer(i) = m_ds.CreateSoundBufferFromFile (file, _ bufferDesc1, waveFormat1)

Soundbuffer einem 3D-Buffer zuweisen:


Set m_ds3dBuffer(i) = m_dsBuffer(i).GetDirectSound3Dbuffer HScroll1_Change i

Abstrahlrichtung der Soundquelle:


m_ds3dBuffer(i).SetConeAngles DS3D_MINCONEANGLE, 100, _ DS3D_IMMEDIATE m_ds3dBuffer(i).SetConeOutsideVolume -400, DS3D_IMMEDIATE

Position im 3D-Raum setzen:


m_ds3dBuffer(i).SetPosition m_pos(i).x / 50, 0, _ m_pos(i).z / 50, DS3D_IMMEDIATE End Sub

Soundbuffer ber die Play-Methode abspielen:


Private Sub Command1_Click() m_dsBuffer(0).Play 1 m_dsBuffer(1).Play 1 End Sub

326

DirectSound3DListener

Soundbuffer anhalten und Play-Cursor auf Position 0 zurcksetzen:


Private Sub Command3_Click() m_dsBuffer(0).Stop m_dsBuffer(1).Stop m_dsBuffer(0).SetCurrentPosition 0 m_dsBuffer(1).SetCurrentPosition 0 End Sub Private Sub HScroll1_Scroll(Index As Integer) HScroll1_Change Index End Sub Private Sub Slider1_Change() m_dsBuffer(0).SetVolume Slider1.Value m_dsBuffer(1).SetVolume Slider1.Value End Sub

Ausrichtung der Schallquelle errechnen:


Private Sub HScroll1_Change(Index As Integer) Dim x As Single Dim z As Single x = 5 * Cos(3.141 * HScroll1(0).Value / 180) z = 5 * Sin(3.141 * HScroll1(0).Value / 180) DrawPositions m_ds3dBuffer(i).SetConeOrientation x, 0, z, DS3D_IMMEDIATE End Sub Private Sub UpdatePosition(ByVal i As Integer, _ ByVal x As Single, ByVal z As Single) m_pos(i).x = x Picture2.ScaleWidth / 2 m_pos(i).z = z Picture2.ScaleHeight / 2 DrawPositions m_ds3dBuffer(i).SetPosition m_pos(i).x / 50, 0, _ m_pos(i).z / 50, DS3D_IMMEDIATE End Sub Private Sub Picture2_MouseDown(Button As Integer, _ Shift As Integer, x As Single, z As Single) If Button = 2 Then i = 1 UpdatePosition i, x, z End Sub Private Sub Picture2_MouseMove(Button As Integer, _ Shift As Integer, x As Single, z As Single) If Button = 0 Then Exit Sub If Button = 2 Then i = 1

Kapitel 4 DirectSound

327

UpdatePosition i, x, z End Sub Private Sub Picture2_Paint() DrawPositions End Sub Sub DrawPositions() Dim x As Integer Dim z As Integer Picture2.Cls DrawTriangle 0, Picture2.ScaleWidth / 2, _ Picture2.ScaleHeight / 2, 90 x = CInt(m_pos(0).x) + Picture2.ScaleWidth / 2 z = CInt(m_pos(0).z) + Picture2.ScaleHeight / 2 DrawTriangle RGB(255, 0, 0), x, z, HScroll1(0).Value x = CInt(m_pos(1).x) + Picture2.ScaleWidth / 2 z = CInt(m_pos(1).z) + Picture2.ScaleHeight / 2 DrawTriangle RGB(0, 0, 255), x, z, HScroll1(1).Value End Sub Sub DrawTriangle(col As Long, x As Integer, z As Integer, _ ByVal a As Single) Dim x1 As Integer Dim z1 As Integer Dim x2 As Integer Dim z2 As Integer Dim x3 As Integer Dim z3 As Integer Dim q As Integer a = 3.14159 * (a 90) / 180 q = 10 x1 = q * Sin(a) + x z1 = q * Cos(a) + z x2 = q * Sin(a + 3.141 / 1.3) + x z2 = q * Cos(a + 3.141 / 1.3) + z x3 = q * Sin(a 3.141 / 1.3) + x z3 = q * Cos(a 3.141 / 1.3) + z Picture2.Line (x1, z1)-(x2, z2), col Picture2.Line (x1, z1)-(x3, z3), col Picture2.Line (x2, z2)-(x3, z3), col End Sub

328

DirectSound Capture

4.19

DirectSound Capture
DirectSound ist nicht nur in der Lage, Wavedateien und andere Soundfiles abzuspielen, sondern eignet sich auch hervorragend zur Aufnahme von Samples. Die Aufnahme von Geruschen erfolgt ebenso wie das Abspielen ber Bufferobjekte. Allerdings stellt DirectSound fr diesen Zweck eine eigene Bufferart zur Verfgung, den so genannten Capturebuffer. Wie auch der Soundbuffer stellt der Capturebuffer Befehle zur Steuerung und zur Abfrage der Aufnahmeposition sowie Statusinformationen bereit.

4.19.1 Erstellen eines Capturebuffers


Anders als bei DirectSound, wo mehrere Sounds zu einem Mastersound zusammengemischt werden und dann ber die Soundkarte zu hren sind, wird nun vom Eingang der Soundkarte, genauer gesagt vom Ausgang des Windows-Mixers, das Summensignal aufgezeichnet. DirectSoundCapture erlaubt nur die Existenz eines Capturebuffers.
CreateCaptureBuffer() Erstellt einen Capturebuffer der die Sounddaten aufnimmt. object.CreateCaptureBuffer(bufferDesc As DSCBUFFERDESC) _ As DirectSoundCaptureBuffer object bufferDesc GetCaps() Beschreibt die Fhigkeiten des Aufnahmegerts. object.GetCaps(caps As DSCCAPS) object caps ReadBuffer() Liest ein Segment aus einem Soundbuffer und speichert dieses in einer Variablen vom Typ Array. object.ReadBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSBLOCKFLAGS) object start ein gltiges DirectSoundBuffer-Objekt Offset in Bytes (Position, ab der gelesen werden wird) ein gltiges DirectSoundCapture-Objekt vom Typ DSCCAPS ein gltiges DirectSoundCapture-Objekt Bufferbeschreibung vom Typ DSCBUFFERDESC

Kapitel 4 DirectSound

329

ReadBuffer() size buffer flags WriteBuffer() Schreibt ein Segment in einen Soundbuffer. object.WriteBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSBLOCKFLAGS) object start size buffer flags Start() Setzt den Capturebuffer in den Aufnahmezustand und beginnt mit dem Schreiben der ankommenden Sounddaten in den Capturebuffer. Befindet sich der Capturebuffer im Aufnahmezustand, hat diese Methode keine Auswirkung. object.Start(flags As CONST_DSCBSTARTFLAGS) object flags Stop() Setzt den Capturebuffer in den Ruhezustand und hlt die Aufzeichnung der Sounddaten an. Befindet sich der Capturebuffer im Ruhezustand, hat diese Methode keine Auswirkung. object.Stop() object WriteBuffer() Schreibt Sounddaten aus einem Array in ein Segment des Capturebuffers. DirectSoundCaptureBuffer.ReadBuffer() object.WriteBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSCBLOCKFLAGS) object ein gltiges DirectSoundCaptureBuffer-Objekt ein gltiges DirectSoundCaptureBuffer-Objekt ein gltiges DirectSoundCaptureBuffer-Objekt vom Typ CONST_DSCBSTARTFLAGS ein gltiges DirectSoundBuffer-Objekt Offset in Bytes, ab wo geschrieben werden soll. Anzahl der Bytes, die geschrieben werden. Variable die die Sounddaten enthllt. vom Typ CONST_DSBLOCKFLAGS Anzahl der Bytes, die gelesen werden. Variable vom Typ Any, die die Sounddaten aufnimmt. vom Typ CONST_DSBLOCKFLAGS

330

DirectSound Capture

WriteBuffer() start size buffer flags Offset in Bytes (Position, ab der geschrieben wird) Anzahl der Bytes, die geschrieben werden. Variable vom Typ Any, die die Sounddaten enthlt. vom Typ CONST_DSCBLOCKFLAGS

GetCurrentPosition() Empfngt die aktuelle Aufnahme- und Abspielposition im Buffer. object.GetCurrentPosition(cursors As DSCURSORS) object cursors GetStatus() Gibt den aktuellen Zustand eines Capturebuffers zurck. object.GetStatus() As CONST_DSCBSTATUSFLAGS object ein gltiges DirectSoundCaptureBuffer-Objekt ein gltiges DirectSoundCaptureBuffer-Objekt vom Typ DSCURSORS

Ein Capturebuffer wird ber die Methode DirectSoundCapture.CreateCaptureBuffer() erstellt. Mit den zu bergebenden Einstellungen, die in der Bufferbeschreibung DSCBUFFERDESC vordefiniert werden, gibt die CreateCaptureBuffer-Funktion ein gltiges Capturebuffer-Objekt zurck.
objekt.CreateCaptureBuffer(bufferDesc As DSCBUFFERDESC) As DirectSoundCaptureBuffer Type DSCBUFFERDESC fxFormat As WAVEFORMATEX lBufferBytes As Long lFlags As CONST_DSCBCAPSFLAGS End Type

Eigenschaften ber das Aufnahmegert werden mit der DirectSoundCapture.GetCaps()-Methode zurckgegeben. Sie enthalten Informationen ber die eingestellte Kanalzahl, Aufnahmeparameter und das aktuelle Wellenformformat.
DirectSoundCapture.GetCaps(caps As DSCCAPS)

4.19.2 Erluterung zur Aufnahme


Das Beispiel finden Sie auf der CD unter DirectSound Beispiel 7.
Dim dx As New DirectX7 Dim ds As DirectSound

Kapitel 4 DirectSound

331

Dim dsb As DirectSoundBuffer Dim dsd As DSBUFFERDESC Dim dscb As DirectSoundCaptureBuffer Dim dscd As DSCBUFFERDESC Dim CaptureWave As WAVEFORMATEX Dim capCURS As DSCURSORS Dim ByteBuffer() As Integer Dim CNT As Integer Dim cCaps As DSCCAPS Dim gfPlay As Boolean Private Sub Form_Load()

DirectSoundCapture-Objekt erstellen:
Set dsc = dx.DirectSoundCaptureCreate(vbNullString)

DirectSound Objekt erstellen:


Set ds = dx.DirectSoundCreate(vbNullString) gfPlay = True

Zugriff fr andere Anwendungen bestimmen:


ds.SetCooperativeLevel Me.hWnd, DSSCL_NORMAL

Capture initialisieren:
InitCapture

Schaltflchen vorbereiten:
cmdSaveToFile.Enabled = False cmdPlayRec.Enabled = False cmdStopPlaying.Enabled = False cmdStopRec.Enabled = False Label1.Caption = vbNullString End Sub Private Sub cmdSaveToFile_Click() On Error Goto Fehler Dim FileLocal As String

Aufgenommene Daten in Soundbuffer konvertieren:


ConvertToSBuffer CmdStopPlaying.Enabled = False Timer1.Enabled = False Label1.Caption = vbNullString CNT = 0 svFile.Filter = "*.wav"

332

DirectSound Capture

svFile.DialogTitle = "Save Wave File" svFile.ShowSave FileLocal = svFile.filename

Sound abspeichern:
dsb.SaveToFile FileLocal Fehler: End Sub Private Sub cmdPlayRec_Click()

berspielen der Sounddaten vom Capturebuffer in den Soundbuffer:


ConvertToSBuffer dsb.Play DSBPLAY_DEFAULT Timer1.Enabled = True CNT = 0 Label1.Caption = vbNullString If gfPlay Then cmdStopPlaying.Enabled = True End Sub Private Sub cmdStartRec_Click() Set dscb = Nothing

Capturebuffer initialisieren:
Call InitCapture

Aufnahme starten:
dscb.start DSCBSTART_DEFAULT

Schaltflchen einstellen:
Timer1.Interval = 1000 Timer1.Enabled = True cmdStopRec.Enabled = True cmdStartRec.Enabled = False End Sub Private Sub cmdStopPlaying_Click() Dim l_st As Long Dim l_soundStatus As Long

Soundbuffer anhalten und Position zurcksetzen:


dsb.Stop dsb.SetCurrentPosition 0 Timer1.Enabled = False

Kapitel 4 DirectSound

333

CNT = 0 Label1.Caption = vbNullString cmdStopPlaying.Enabled = False End Sub Private Sub cmdStopRec_Click() Dim l_bufferS As Long cmdSaveToFile.Enabled = True

Aufnahme anhalten:
dscb.Stop Timer1.Enabled = False CNT = 0 Label1.Caption = vbNullString cmdStartRec.Enabled = True cmdStopRec.Enabled = False End Sub Private Sub ConvertToSBuffer()

Statischen Soundbuffer erzeugen:


dscb.GetCurrentPosition capCURS dsd.lBufferBytes = capCURS.lWrite * dscd.fxFormat.nBlockAlign dsd.lFlags = DSBCAPS_CTRLVOLUME Or DSBCAPS_STATIC Set dsb = ds.CreateSoundBuffer(dsd, dscd.fxFormat)

Sounddaten von Capture in Soundbuffer berspielen:


ReDim ByteBuffer(capCURS.lWrite * _ dscd.fxFormat.nBlockAlign + 1) dscb.ReadBuffer 0, capCURS.lWrite * _ dscd.fxFormat.nBlockAlign, ByteBuffer(0), DSCBLOCK_DEFAULT dsb.WriteBuffer 0, capCURS.lWrite * _ dscd.fxFormat.nBlockAlign, ByteBuffer(0), DSBLOCK_DEFAULT End Sub Private Function WaveEx(Hz As Long, _ Channels As Integer, BITS As Integer)

Wellenformat einstellen:
With WaveEx .nFormatTag = WAVE_FORMAT_PCM .nChannels = Channels .lSamplesPerSec = Hz .nBitsPerSample = BITS .nBlockAlign = Channels * BITS / 8

334

DirectSound Capture

.lAvgBytesPerSec = WaveEx.lSamplesPerSec *_ .nBlockAlign .nSize = 0 End With End Function Private Sub InitCapture()

Capturebuffer vorbereiten und erzeugen:


dsc.GetCaps cCaps If cCaps.lFormats And WAVE_FORMAT_2M08 Then CaptureWave = WaveEx(22050, 1, 8) ElseIf cCaps.lFormats And WAVE_FORMAT_1M08 Then CaptureWave = WaveEx(11025, 1, 8) Else MsgBox "Aufnahmen sind mit dieser _ Soundkarte nicht mglich!", vbApplicationModal End End If dscd.fxFormat = CaptureWave dscd.lBufferBytes = CaptureWave.lAvgBytesPerSec * 20 dscd.lFlags = DSCBCAPS_WAVEMAPPED Set dscb = dsc.CreateCaptureBuffer(dscd) End Sub Private Sub Form_QueryUnload(Cancel As Integer, _ UnloadMode As Integer) Call CleanUp End End Sub Private Sub CleanUp()

DirectSound Reset:
Set dx = Nothing Set ds = Nothing Set dsb = Nothing Set dsc = Nothing Set dscb = Nothing Erase ByteBuffer End Sub Private Sub mnuExit_Click() Unload Me End Sub Private Sub Timer1_Timer()

Kapitel 4 DirectSound

335

On Error Resume Next CNT = CNT + 1

Abfragen, ob Aufnahmelnge von 19 Sekunden berschritten ist:


If CNT = 19 Then dscb.Stop Label1.Caption = "Full" Form1.Refresh Timer1.Enabled = False cmdSaveToFile.Enabled = True If gfPlay Then cmdPlayRec.Enabled = True If gfPlay Then cmdStopPlaying.Enabled = True Exit Sub End If Label1.Caption = CNT

berprfen des Soundbuffer-Zustandes:


Dim l_sBs As Long If Not (dsb Is Nothing) Then l_sBs = dsb.GetStatus() If (l_sBs And DSBSTATUS_PLAYING) Then Else If cmdStartRec.Enabled = True Then Timer1.Enabled = False CNT = 1 Label1.Caption = vbNullString cmdStopPlaying.Enabled = False End If End If End If End Sub

Kapitel 5
DirectPlay
5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 5.12 DirectPlay-Basis Beispiel (Chatsystem) Kommunikationsmodelle Lobbies Service Provider Sicherheit Nachrichten DirectPlay-Adresse DirectPlay-Protokoll Session Spieler Bienenjagd Multiplayer Demo 341 352 355 357 358 358 359 363 364 365 369 372

338

Mit DirectPlay ist es mglich, Multispieler-Games, Chat Clients, Gameserver und andere Netztwerkanwendungen zu erstellen. Der Programmierer muss sich dabei nicht (oder nur wenig) um die verwendeten bertrgungsprotokolle kmmern, sondern findet durch DirectPlay einen einheitlichen Befehlssatz. Die unterstzten Provider reichen von Internetsystemen ber Modem- oder LAN-Verbindungen bis zu PC-Direktverbindungen.

Anwendung DirectPlay Interface DirectPlay Service Provider TCP/IP Internet


Bild 5.1:

IPX LAN

TAPI Modem

NetX private Netzwerke

DirectPlay im berblick

Mchte man eine DirectX-Anwendung eine Verbindung zu anderen Rechnern aufbauen, um ber diese Verbindung Daten zur Verwaltung und zum Betrieb einer Spielesitzung auszutauschen, so ist nach folgendem Muster vorzugehen: Erzeugung eines DirectPlay-Objekts. Ermittlung der Connection. Dabei handelt es sich um Datenblcke, die Informationen zum Verbindungsaufbau mit einem Service-Provider enthalten. Abschluss der Initialisierung des DirectPlay-Objekts nach erfolgter Auswahl einer bestimmten Verbindung. Bestimmung der bereits existierenden Sessions. Eine solche Sitzung besteht hierbei aus einem oder mehreren Spielern, die ber DirectPlay eine entsprechende Verbindung aufgebaut haben. Eintreten in eine bestehende oder Erzeugung einer neuen Sitzung. Session-Management

Kapitel 5 DirectPlay

339

Bei einer Session handelt es sich, wie bereits gesagt, um eine gewisse Zahl von Spielern, die sich jeweils ber ein eigenes DirectPlay-Objekt einem gemeinsamen Kommunikationskanal angeschlossen haben. Es soll nun in kurzen Worten der Aufbau einer solchen Sitzung beschrieben werden. Nach dem Anlegen eines Spielers in einer bereits bestehenden oder in einer neuen Sitzung kann dieser Nachrichten mit Teilnehmern der Session austauschen. Jede DirectPlay-Sitzung besitzt gewisse Eigenschaften. Um diese zu verwalten, existiert im Allgemeinen ein Besitzer (host) fr jede Session, der als einziger die Einstellungen verndern kann. Verlsst dieser Gastgeber die Sitzung, so gibt es folgende beiden Mglichkeiten: Die Verwaltung der Sitzung geht an einen anderen Rechner ber, der von diesem Zeitpunkt an als Gastgeber fungiert. Welchem Rechner diese neue Aufgabe zugewiesen wird, kann von den Teilnehmern der Session nicht beeinflusst werden. Die Sitzung wird ohne einen definierten host weitergefhrt. Dies hat jedoch zur Folge, dass keine Kommunikationseinstellungen mehr verndert werden und auch keine neuen Teilnehmer mehr in die Sitzung eintreten knnen. Die Session wird nach auen hin unzugnglich/verborgen.
Computer 4

Computer 1 Host

DirectPlay Session

Computer 3

Computer 2

Bild 5.2:

Session

Eine der gerade angesprochenen Einstellungen ist beispielsweise der Schutz der Sitzung. Abgesehen von der nach auen offenen Sitzung existieren noch die Mglichkeiten, Sitzungen mit den Prdikaten wie password protected (dies erfordert ein Passwort fr den Beitritt, die Sitzung ist jedoch nach auen hin sichtbar) oder private (eine solche Sitzung ist von auen nur mit dem gltigen Pawort sichtbar, sodass auch nur nach einer entsprechenden Authentifikation der Anschluss an eine solche Session mglich ist) anzulegen. Spieler & Gruppen

340

DirectPlay kennt nur den Spieler (oder eine Gruppe) als einzelnes Objekt innerhalb einer Session. Die Rechner, auf denen die verschiedenen DirectPlay-Objekte angelegt wurden, sind innerhalb einer Sitzung nicht weiter von Belang. So sind auch die Spieler Ausgangs- und Zielpunkt jedes Nachrichtentransfers. Aus diesem Grund bentigt jedes DirectPlay-Objekt mindestens einen Spieler. Andernfalls wre die entsprechende Instanz innerhalb der Sitzung nicht mehr zu Interaktionen fhig. Lokale Spieler, sind Spieler, die auf dem gerade betrachteten Rechner angesiedelt sind, gibt es also pro Rechner mindestens einen. Entfernte (remote) Spieler, also Spieler, zu denen ber die jeweilige Netzwerkverbindung Kontakt besteht, kann es geben, dies muss aber nicht der Fall sein. Besonders interessant ist die Mglichkeit, mehrere Spieler pro DirectPlay-Objekt anlegen zu knnen. Auf diese Weise knnen Spieler erzeugt werden, die vom Rechner gesteuert werden (Computerspieler). Des Weiteren untersttzt das DirectPlay-Interface den Zusammenschluss einer gewissen Anzahl von Spielern zu Gruppen. Diese Gemeinschaften mssen dabei nicht notwendigerweise disjunkt sein, sodass ein einzelner Spieler Mitglied in mehreren Gruppen sein kann.
Spieler 1 Spieler 2 Spieler 3 Spieler 4 Spieler 5 Spieler 6 Gruppe 2 Gruppe 1 DirectPlay Session

Gruppe 3

Bild 5.3:

Gruppen

Nachrichten- und Datenaustausch: Die Unterscheidung von lokalen und entfernten Spielern sowie der Zusammenschluss verschiedener Spieler zu Gruppen haben unter anderem Einfluss auf den Nachrichtentransport. So werden Informationen zwischen lokalen Spielern nicht ber das Netzwerk weitergeleitet, sondern vor Ort auf dem gemeinsamen Rechner ausgetauscht. Die Bildung von Gruppen bietet ein weiteres Mittel zur Bandbrei-

Kapitel 5 DirectPlay

341

ten-Einsparung. Durch das Verwenden von multicasting kann die Belastung des Netzwerks vermindert werden, falls der Empfnger einer Nachricht eine Gruppe von Spielern ist. Bei einer Nachricht handelt es sich im Kontext von DirectPlay stets um eine der beiden folgenden Arten: custom messages: Dies sind selbstdefinierte Nachrichten mit einer expliziten Lnge. Der bliche Austausch von Informationen zwischen Spielern verwendet diese Nachrichtenart. system messages: Hierbei handelt es sich um Nachrichten ber die Verwaltung der Sitzung, die vom System selbststndig generiert werden. Zum Beispiel bewirkt der Eintritt eines neuen Spielers in eine Session die Benachrichtigung aller bisherigen Mitspieler. Der Austausch von Daten zwischen den einzelnen DirectPlay-Objekten erfolgt ber lokale oder remote shared data areas, wobei eine automatische Propagierung etwaiger Datennderungen an alle Teilnehmer einer Sitzung untersttzt wird. Fr alle Nachrichten knnen noch folgende Optionen ausgewhlt werden: Verschlsselung, Signierung sowie die Einhaltung einer Garantie der Datensicherheit. Diese Option bewirkt, dass nur Daten, deren Integritt sichergestellt wurde, in die entsprechende Warteschlange (queue) aufgenommen werden.

5.1

DirectPlay-Basis
DirectPlayCreate() Erzeugt ein DirectPlay4-Objekt. object. DirectPlayCreate (guid As String) As DirectPlay4 object guid ein gltiges DirectX7-Objekt Identifikationsnummer des Service-Providers, an dem DirectPlay angemeldet wird. Wird ein leerer String bergeben, wird die Verbindung nicht initialisiert und die Applikation muss die DirectPlay4.InitializeConnection()-Methode ausfhren.

In diesem Kapitel wollen wir den Basisweg zum Erstellen einer DirectPlayAnwendung demonstrieren. Wir bentigen acht Schritte fr eine erste Basisanwendung.

342

DirectPlay-Basis

Schritt 1: Erstellen des DirectPlay-Objektes Das DirectPlay-Objekt wird mit der DirectX7.DirectPlayCreate()-Methode erstellt. Diese Methode beinhaltet nur den Parameter guid. ber ihn wird der Provider eindeutig identifiziert. Da man normalerweise noch nicht wei, ber welchen Provider die Verbindung hergestellt werden soll, bergeben wir einen leeren String. Dies hat zur Folge, dass wir spter die Verbindung initialisieren mssen.
Dim Dim Set Set g_dx g_dp g_dx g_dp As DirectX7 As DirectPlay4 = New DirectX7 = g_dx.DirectPlayCreate("")

Schritt 2: Auflisten der Provider


GetDPEnumConnections() Erzeugt eine Liste mit allen registrierten Service sowie Lobby-Providern. object.GetDPEnumConnections(guid As String, flags As CONST_DPENUMCONNECTIONFLAGS) As DirectPlayEnumConnections object guid flags ein gltiges DirectPlay4-Objekt Guid fr die Anwendung DPCONNECTION_DIRECTPLAY Auflistung fr DirectPlay-Service-Provider DPCONNECTION_DIRECTPLAYLOBBY Auflistung fr DirectPlay-Lobby-Provider

GetCount() Ermittelt die Anzahl der Elemente im Auflistungsobjekt. object.GetCount() As Long object GetName() Ermittelt den Namen einer Verbindung aus dem Auflistungsobjekt. object.GetName(index As Long) As String object index ein gltiges DirectPlayEnumConnections-Objekt Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll. ein gltiges DirectPlayEnumConnections-Objekt

Kapitel 5 DirectPlay

343

Der Provider wird durch das DirectPlayEnumConnections-Objekt aufgelistet. Bevor wir an diese Auflistung herankommen, muss dieses Objekt erstellt werden. DirectPlay4.GetDPEnumConnections()-Methode bernimmt diese Aufgabe. Die Methode beinhaltet zwei Parameter. Der erste Parameter guid verlangt einen eindeutige Identifizierung. bergeben wir einen leeren String, so werden alle Provider (Service-Provider und Lobby-Provider) dem DirectPlayEnumConnec tions-Objekt bergeben. Der zweite Parameter flags definiert, welche Art von Provider gesucht werden soll. Diese werden durch die CONST_DPENUMCON NECTIONSFLAGS-Konstantenliste beschrieben.
Enum CONST_DPENUMCONNECTIONFLAGS DPCONNECTION_DIRECTPLAY = 1 DPCONNECTION_DIRECTPLAYLOBBY = 2 End Enum

Nachdem das DirectPlayEnumConnections-Objekt erstellt wurde, knnen wir die durch Windows registrierten Provider auslesen. Unter Windows98 werden Sie im Regelfall folgende Provider erhalten: IPX-Verbindung fr DirectPlay Internet TCP/IP-Verbindung fr DirectPlay Modemverbindung fr DirectPlay Serielle Verbindung fr DirectPlay

Nicht alle aufgelisteten Provider stehen auch zur Verfgung. Das DirectPlayEnumConnections-Objekt liefert alle registrierten Provider. Diese sind aber erst einsatzbereit, wenn Sie die notwendigen bertragungsprotokolle installiert haben. Wir werden vorzugsweise die IPX-Verbindung fr DirectPlay benutzen. Da unsere Beispielanwendungen auf dieser Verbindung basieren, sollten Sie diese Verbindung unbedingt einrichten. Sollten Sie dies nicht wollen, so probieren Sie die Internet-TCP/IP-Verbindung fr DirectPlay. Um das notwendige Protokoll zu installieren, fhren Sie folgende Schritte durch: ffnen Sie den Ordner Systemsteuerung. Doppelklicken Sie auf das Symbol Netzwerk. Whlen Sie Hinzufgen. Selektieren Sie Protokoll und besttigen Sie anschlieend mit Hinzufgen. Auf der linken Seite selektieren Sie Microsoft und auf der rechten Seite IPX/SPX-kompatibles Protokoll. Besttigen Sie mit OK.

344

DirectPlay-Basis

Kehren wir zum Auslesen der Provider zurck. Das folgende Listing bertrgt die Provider an eine Listbox.
Dim DirectPlayEnum As DirectPlayEnumConnections Set DirectPlayEnum = g_dp.GetDPEnumConnections("", _ DPCONNECTION_DIRECTPLAY) For i = 1 To DirectPlayEnum.GetCount List1.AddItem (DirectPlayEnum.GetName(i)) Next i

Schritt 3: Initialisieren der Verbindung


GetAddress() Ermittelt ein Address-Objekt vom Auflistungsobjekt. object.GetAddress(index As Long) As DirectPlayAddress object index ein gltiges DirectPlayEnumConnections-Objekt Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll.

InitializeConnection() Initialisiert eine DirectPlay-Verbindung. DirectPlayAddress object. InitializeConnection (addr As DirectPlayAdress) object addr ein gltiges DirectPlay4-Objekt ein DirectPlayAddress-Objekt Das DirectPlayAddress Objekt wird mit der DirectPlay4.GetDPEnumConnections()-Methode abgefragt.

Mit der DirectPlay4.InitializeConnection()-Methode richten wir die Verbindung ein. Sie verlangt den Parameter addr As DirectPlayAddress. Diesen Parameter erhalten wir von dem DirectPlayEnumConnections-Objekt. Hierzu steht uns die DirectPlayEnumConnections.GetAddress()-Methode bereit.
Dim DirectPlayAdresse As DirectPlayAddress Set DirectPlayAdresse = DirectPlayEnum.GetAddress(i) g_dp.InitializeConnection DirectPlayAdresse

Kapitel 5 DirectPlay

345

Schritt 5: Auflisten der bestehenden Sessions


CreateSessionData() Erzeugt ein DirectPlaySessionData-Objekt object.CreateSessionData() As DirectPlaySessionData object ein gltiges DirectPlay4-Objekt

GetDPEnumSessions() Erzeugt eine Liste mit allen aktiven Sessions. Die Auswahl der Sessions wird durch den Parametern flags eingegrenzt. object.GetDPEnumSessions( sessionDesc As DirectPlaySessionData, _ timeOut As Long, flags As CONST_DPENUMSESSIONFLAGS) _ As DirectPlayEnumSessions object sessionDesc timeOut ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Liste der Sessions aufnimmt. Wartezeit in Millisekunden. Der Parameter kann 0 sein, dann wird die voreingestellte Wartezeit des Service-Providers genommen. Die Wartezeit des Service-Providers kann mit der DirectPlay4.GetCaps()Methode abgefragt werden. eine Konstante aus der CONST_DPENUMSESSIONSFLAGS-Liste

flags GetCount()

Ermittelt die Anzahl der Elemente in dem DirectPlayEnumSessions-Objekt. object.GetType(index As Long) As Long object GetItem() Erzeugt ein DirectPlaySessionData-Objekt, welches mit den reprsentativen Informationen der Session gefllt ist. object.GetType(index As Long) As Long object index ein gltiges DirectPlayEnumSessions-Objekt ein Element aus dem DirectPlayEnumSession-Objekt. ein gltiges DirectPlayEnumSessions-Objekt

In Schritt 6 werden wir entscheiden, ob eine neue Session erstellt werden soll oder ob wir einer bestehenden Session beitreten. Um diese Entscheidung treffen zu knnen, mssen wir in Erfahrung bringen, welche Sessions bereits geffnet sind. Die Informationen ber die bestehenden Sessions werden in dem Direct

346

DirectPlay-Basis

PlayEnumSessions-Objekt erfasst. Um dieses Objekt zu fllen, bentigen wir noch ein DirectPlaySessionData-Objekt. Dieses wird die detaillierteren Informationen einer Session aufnehmen. Zum Erzeugen des DirectPlayEnumSessionsObjekts nutzen wir die DirectPlay4.GetDPEnumSessions()-Methode.
Set SessionData = g_dp.CreateSessionData Set Session = g_dp.GetDPEnumSessions(SessionData, 0,_ DPENUMSESSIONS_ALL) For i = 1 To Session.GetCount List1.AddItem (Session.GetItem(i).GetSessionName) Next i

Schritt 6: Eine Session erzeugen oder einer Session beitreten


Open() Erzeugt oder schliet sich einer Session an. DirectPlay4.Close() object.Open(sessionDesc As DirectPlaySessionData, _ flags As CONST_DPOPENFLAGS) object sessionDesc flags ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Informationen der Session enthlt. Dieses Objekt wird mit der DirectPlay4CreateSessionData()-Methode erzeugt. DPOPEN_CREATE DPOPEN_JOIN DPOPEN_RETURNSTATUS

SetSessionName() Setzt den Sessionnamen. object.SetSessionName(val As String) object val ein gltiges DirectPlaySessionData-Objekt Name der Session

SetMaxPlayers() Setzt die Anzahl der maximal zulssigen Spieler einer Session. object.SetMaxPlayers(val As Long) object val ein gltiges DirectPlaySessionData-Objekt Anzahl der maximal zulssigen Spieler.

Kapitel 5 DirectPlay

347

SetFlags() Setzt die Flags (Kennzeichnungen) einer Session. object.SetFlags(val As CONST_DPSESSIONFLAGS) object val ein gltiges DirectPlaySessionData-Objekt Eine Konstante aus der CONST_DPSESSIONFLAGS-Liste

Fr beide Mglichkeiten steht die DirectPlay4.Open()-Methode bereit. Sie verlangt zwei Parameter. Der erste Parameter sessionDesc ist ein Typenarray vom Typ DierctPlaySessionData. Dieses Typenarray haben wir in Schritt 5 mit der DirectPlay4.CreateSessionData()-Methode erzeugt und mit der DirectPlay4. GetDPEnumSessions()-Methode gefllt. Der zweite Parameter flags kennzeichnet, ob wir einer Session beitreten oder eine neue Session erzeugen wollen. Einer Session beitreten: Um einer Session beizutreten, mssen wir lediglich die DirectPlay4.Open()Methode aufrufen.
g_dp.Open SessionData, DPOPEN_JOIN

Eine Session erzeugen: Bevor wir eine Session erzeugen, knnen wir diese genauer beschreiben. Das DirectPlaySessionData-Objekt wurde bereits in Schritt 5 erzeugt. Diesem Typenarray mssen wir zumindest einen Sessionnamen mitteilen. Weiterhin knnen wir die Anzahl der maximal zulssigen Sessionmitglieder festlegen. ber das Setzen von Flags knnen wir das Verhalten der Session beeinflussen. Das DirectPlaySessionData Objekt werden wir noch genauer beschreiben.
SessionData.SetSessionName Session 1 SessionData.SetMaxPlayers 2 SessionData.SetFlags DPSESSION_MIGRATEHOST

Das Flag DPSESSION_MIGRATEHOST ist recht interessant. Es beeinflusst das Verhalten der Session. Sollte sich der Hostteilnehmer einer Session abmelden, so werden die Sessionmitglieder ber dessen Ausscheiden informiert. Somit ist ein Sessionmitglied in der Lage, die Aufgaben des Hostteilnehmers zu bernehmen.
g_dp.Open SessionData, DPOPEN_CREATE

348

DirectPlay-Basis

Schritt 7: Erzeugen eines Sessionmitglieds (Player)


CreatePlayer() Erzeugt einen lokalen Spieler fr die aktuelle Session. object.CreatePlayer(friendlyName As String, formalName As String, _ receiveEvent As Long, flags As CONST_DPPLAYERFLAGS) As Long object friendlyName formalName receiveEvent flags ein gltiges DirectPlay4-Objekt Rufname Hausname Handle fr ein Ereignis, welches ausgelst wird, wenn eine Nachricht fr diesen Spieler eintrift. DPPLAYER_SERVERPLAYER DPPLAYER_SPECTATOR Defaultwert ist 0 Weder Serverplayer noch Spectator

Anhand der Namensgebung der Sessionmitglieder als Player knnen wir den bevorzugten Anwendungsbereich von DirectPlay erkennen. Es ist konzipiert um Netzwerkspiele zu realisieren. Dies ist kein Nachteil, sondern entspricht der Zielsetzung eines DirectX-Programmierers. Ein Player wird mit der DirectPlay4.CreatePlayer()-Methode erzeugt. Sie verlangt vier Parameter. Die ersten beiden Parameter friendlyName und und formal Name knnen Sie mit dem Rufnamen und dem Hausnamen vergleichen. Beide werden als String bergeben. Der dritte Parameter receiveEvent ist das Handel zu einem Event. Dieses wird immer dann aufgerufen, wenn eine Nachricht nur fr diesen Player eingetroffen ist. Diesen Parameter kann man auf 0 setzten. Den letzten Parameter flags knnen wir ebenfalls auf 0 setzten. Er beschreibt den Playertyp. Zur Auswahl stehen die Konstanten DDPLAYER_SERVERPLAYER oder DPPLAYER_SPECTATOR. Der DDPLAYER_SERVERPLAYER kann nur vom Host eingesetzt werden. Die DirectPlay4.CreatePlayer()-Methode liefert als Rckgabewert eine Player ID. Diese ID ist einmalig in einer Session und wird zur Verwaltung der Teilnehmer verwendet. So knnen mehrere Teilnehmer mit dem gleichen Namen und dem gleichen Rufnamen einer Session beitreten und dennoch knnen Sie ber die ID eindeutig identifiziert werden.
PlayerName = "Player1" PlayerHandle = "HandelPlayer1" PlayerID1 = g_dp.CreatePlayer(PlayerName, PlayerHandle, 0, 0)

Kapitel 5 DirectPlay

349

Schritt 8: Senden und Empfangen von Nachrichten


CreateMessage() Erzeugt ein Message Objekt, welches mit Daten zum Senden gefllt werden kann. DirectPlay4.Send() object.CreateMessage() As DirectPlayMessage object Send() Sendet eine Nachricht an einen Spieler oder eine Gruppe von Spielern oder alle Spieler. DirectPlay4.Receive(), DirectPlay4.SendChatMessage() object.Send(fromPlayerId As Long, toPlayerId As Long, _ flags As CONST_DPSENDFLAGS, msg As DirectPlayMessage) object fromPlayerId toPlayerId flags ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat. Index des Spielers, fr welchen die Nachricht bestimmt ist. DPSEND_ENCRYPTED DPSEND_GUARANTEED DPSEND_SIGNED Ein DirectPlayMessage-Objekt, welches die Nachricht enthlt, die versendet werden soll. ein gltiges DirectPlay4-Objekt

msg

WriteLong() Schreibt ein Long in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteLong(val As Long) object val WriteString() Schreibt eine Zeichenkette in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteString(val As String) object val ein gltiges DirectPlayMessage-Objekt Zeichenkette ein gltiges DirectPlayMessage-Objekt Wert

350

DirectPlay-Basis

GetMessageCount() Ermittelt die Anzahl von Nachrichten in der Nachrichtenwareschlange fr einen definierten lokalen Spieler. DirectPlay4.Receive() object.GetMessageCount(playerId As Long) As Long object playerId Receive() Empfngt Nachrichten aus der Nachrichtenwarteschlange. DirectPlay4.Send() object.Receive(fromPlayerId As Long, toPlayerId As Long, _ flags As CONST_DPRECEIVEFLAGS) As DirectPlayMessage object fromPlayerId toPlayerId flags ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat. Index des Spielers, fr welchen die Nachricht bestimmt ist. DPRECEIVE_ALL DPRECEIVE_PEEK DPRECEIVE_TOPLAYER PRECEIVE_FROMPLAYER ein gltiges DirectPlay4-Objekt Index fr einen Spieler

ReadLong() Liest ein Long von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadLong() As Long object ReadString() Liest ein String von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadString() As String object ein gltiges DirectPlayMessage-Objekt ein gltiges DirectPlayMessage-Objekt

Das Senden von Nachrichten ist recht einfach. Wir werden dabei von den DirectPlay4.Send()- und DirectPlay4.SendEx()-Methoden untersttzt. Dabei ist die DirectPlay4.SendEx()-Methode eine erweiterte Form der DirectPlay4 .Send()-Methode. Die DirectPlay4.Send()-Methode enthlt vier Parameter. Mit den ersten beiden Parametern fromPlayerId und toPlayerId wird angegeben, von

Kapitel 5 DirectPlay

351

wem die Nachricht kommt und an wen die Nachricht gerichtet ist. Die PlayerID wurde in Schritt 7 erzeugt. Der dritte Parameter flags indiziert, wie die Nachricht gesendet werden soll. Zur Auswahl stehen die Konstanten DPSEND_ENCRYPTED, DPSEND_GUARANTEED und DPSEND_SIGNED. Als letzter Parameter msg folgt die eigentliche Nachricht. Diese wird als DirectPlayMessageObjekt bergeben. Dieses wird mit der DirectPlay4.CreateMessage()-Methode erzeugt. Nachdem das Objekt existiert, wird dieses mit den gewnschten Informationen gefllt und dann versandt.
Dim ChatMsg As DirectPlayMessage Set ChatMsg = g_dp.CreateMessage Call ChatMsg.WriteLong(DPSYS_CHAT) Call ChatMsg.WriteString(Testnachricht) Call g_dp.Send(PlayerID1, DPID_ALLPLAYERS, DPSEND_GUARANTEED, _ ChatMsg)

Das Empfangen der Nachrichten kann man auf zwei Arten gestalten. Zum einen kann man ein Event einrichten. Dieses wird dann immer aktiviert, wenn eine neue Nachricht eintrifft. Der andere Weg ist, dass Sie regelmig die Nachrichten abfragen. Diese manuelle Abfrage kann man recht gut mit einer Do...Loop() Schleife verbinden. Die Nachrichten werden in zwei Kategorien eingeteilt. Die erste Kategorie sind die Systemnachrichten. Diese werden ber das Netzwerk versandt, ohne dass Sie dies beeinflussen knnen. Dazu zhlen Informationen wie das Eintreten eines neuen Players in einer Session oder das Ausscheiden des Hostteilnehmers. Die zweite Kategorie sind die Spielernachrichten. Diese werden explizit erzeugt. Die Unterscheidung der beiden Kategorien ist wichtig, da Sie bei der Auswertung der Nachrichten auf die unterschiedlichen Typen unterschiedlich reagieren knnen. Die Abfrage der Nachrichtenwarteschlange erfolgt mit der DirectPlay4.Receive()-Methode. Sie beinhaltet drei Parameter. Die beiden ersten Parameter fromPlayerId und toPlayerId benennen, von wem die Nachricht kommt und an wen die Nachricht gerichtet ist. Hierzu muss als drittes Argument DPRECEIVE_FROMPLAYER bzw. DPRECEIVE_TOPLAYER hinzugefgt werden. Um alle Nachrichten zu empfangen, setzen Sie den dritten Parameter auf DPRECEIVE_ALL.
Public Sub GetMessages() Dim MsgCount As Long Dim MsgType As Long Dim FromPlayerID As Long Dim ToPlayerID As Long Dim dpMsg As DirectPlayMessage MsgCount = g_dp.GetMessageCount(0) For x = 1 To MsgCount Set dpMsg = g_dp.Receive(FromPlayerID, ToPlayerID, _ DPRECEIVE_ALL) MsgType = dpMsg.ReadLong()

352

Beispiel (Chatsystem)

Select Case MsgType Case DPSYS_DESTROYPLAYERORGROUP

Wird ausgelst, wenn ein Player die Session verlsst.


Case DPSYS_CREATEPLAYERORGROUP

Wird ausgelst, wenn ein Player der Session beitritt.


Case DPSYS_HOST

Wird ausgelst bei Nachrichten, welche den Host Teilnehmer betreffen.


Case DPSYS_CHAT

Wird ausgelst bei Nachrichten, welche als Chat deklariert sind. Beim Senden der Nachricht haben wir die Nachricht als Chat definiert.
Call ChatMsg.WriteLong(DPSYS_CHAT).

Jetzt knnen wir die Nachricht spezifisch wieder auslesen.


Dim Nachricht As String Nachricht = dpMsg.ReadString End Select Next x End Sub

5.2

Beispiel (Chatsystem)
Dieses Beispiel richtet ein kleines Netzwerkkommunikationssystem ein. Sie haben die Mglichkeit, eine neue Session zu erstellen oder einer Session beizutreten. Der Hostteilnehmer wird ber das Eintreten oder Ausscheiden eines neuen Teilnehmers informiert. Sollte sich der Hostteilnehmer abmelden, so wird der Gastteilnehmer darber informiert und das Programm beendet. Zum Kommunikationssystem gehrt das Austauschen von Nachrichten. Diese Nachrichten werden als Chatnachrichten deklariert. Das Programm beginnt mit Form2. Hier erhalten Sie eine Auswahl der verfgbaren Provider. Fr die Auflistung der Provider ist die Form_Load()-Subroutine zustndig.
Private Sub Form_Load() Set g_dx = New DirectX7 Set g_dp = g_dx.DirectPlayCreate("")

Direkt zum Anfang des Programms richten wir das DirectX7 sowie das DirectPlay4-Objekt ein.

Kapitel 5 DirectPlay

353

Bild 5.4:

Bildschirmfoto Chatsystem

Set DirectPlayEnum = g_dp.GetDPEnumConnections("", _ DPCONNECTION_DIRECTPLAY) If DirectPlayEnum.GetCount = 0 Then End For i = 1 To DirectPlayEnum.GetCount List1.AddItem (DirectPlayEnum.GetName(i)) Next i

Wir fllen das DirectPlayEnumConnections-Objekt mit Hilfe der Direct Play4.GetDPEnumConnections()-Methode. Nachdem wir die Daten erhalten haben, knnen wir dieses Objekt ber eine kleine For...Next-Schleife auslesen.
Label1(4) = DirectPlayEnum.GetGuid(1) Label1(5) = DirectPlayEnum.GetName(1) Set DirectPlayAdresse = DirectPlayEnum.GetAddress(1)

354

Beispiel (Chatsystem)

Wichtig ist es, dass wir uns die Provideradresse merken. Diese bentigen wir zum Initialisieren der Verbindung.
End Sub

Nachdem wir uns fr einen Provider entschieden haben knnen wir das Programm mit dem weiter-Button fortsetzten. Die Form_Load()-Subroutine von Form1 initialisiert die Verbindung und sammelt Informationen ber die bestehenden Sessions.
Private Sub Form_Load() g_dp.InitializeConnection DirectPlayAdresse

Mit der DirectPlay4.InitializeConnection()-Methode wird die DirectPlay-Verbindung hergestellt. Alle Informationen ber die Verbindung wie Provider, Netzwerkadresse des Servers oder Guid der Session sind in dem DirectPlayAddressObjekt enthalten.
Set SessionData = g_dp.CreateSessionData Set Session = g_dp.GetDPEnumSessions(SessionData, 0, _ DPENUMSESSIONS_ALL)

Nun bentigen wir Informationen ber geffnete Sessions. Hierzu erstellen wir mit der DirectPlay4.CreateSessionData()-Methode eine DirectPlaySessionDataObjekt. Dieses wird mit der DirectPlay4.GetDPEnumSessions()-Methode gefllt. Anschlieend knnen wir uns die geffneten Sessions in der ListBox List1 anzeigen lassen. Je nachdem, ob wir eine offene Session gefunden haben, erlauben wir das Erzeugen einer neuen Session oder lediglich das Eintreten in eine bestehende Session.
List1.Clear For i = 1 To Session.GetCount List1.AddItem (Session.GetItem(i).GetSessionName) Next i If Session.GetCount = 0 Then Command2.Enabled = False Command1.Enabled = True Else Command2.Enabled = True Command1.Enabled = False Text1(0).Enabled = False End If Form1.Visible = True Form1.ZOrder 0 Do While DoEvents() GetMessages Loop

Kapitel 5 DirectPlay

355

Die Do...Loop-Schleife fngt bereits jetzt mit der Abfrage von DirectPlay-Nachrichten an. Sie ist so lange aktiv, bis alle Fenster geschlossen wurden.
End Sub

Sollten wir keine offene Session gefunden haben, knnen Sie eine neue Session erstellen.

5.3
5.3.1

Kommunikationsmodelle
Peer-to-Peer-Session
In einer Peer-to-Peer-Session sind mehrere Computer gleichberechtigt miteinander verbunden. Einer der angeschlossenen Computer bernimmt die Aufgabe des Servers. Gleichzeitig werden diesem Teilnehmer die Aufgaben des Gastgebers einer Session bertragen. Er verwaltet die restlichen Teilnehmer der Session. So vergibt er IDs fr neue Spieler oder Gruppen oder stellt die Sessioninformationen zur Verfgung. Neben den verwaltenden Aufgaben ist der Gastgeber (Host) gleichzeitig ein normales Mitglied der aktuellen Session. Nachrichten mssen nicht ber den Host an andere Mitglieder verteilt werden, sondern knnen direkt von einem Spieler zu einem anderen Spieler geleitet werden. Ebenfalls ist der Host nicht fr alle Systemnachrichten verantwortlich. Jeder an die Session angeschlossene Computer generiert eigene Systemnachrichten, welche (je nach Typ) automatisch verteilt werden.
Anwendung Computer A

Kommunikation
Anwendung Computer B

Anwendung Computer D Host

Anfragen um sich der Session anzuschlieen Sessioninformationen

Anwendung Computer C

Bild 5.5:

Peer-to-Peer

356

Kommunikationsmodelle

In einer Peer-to-Peer DirectPlay Session kommunizieren die einzelnen Computer direkt miteinander. Wenn ein Teilnehmer eine Nachricht an alle Teilnehmer der Session senden mchte, so kann er die Multisendemglichkeiten des Providers nutzen. Sollte der Provider das Versenden von Nachrichten an mehrere oder alle Teilnehmer nicht untersttzen, so muss die Nachricht expliziet an jeden Teilnehmer geleitet werden.
Anwendung Computer A

Anwendung Computer B

Anwendung Computer C

Anwendung Computer D Host


Bild 5.6: Nachrichtenaustausch Peer-to-Peer

5.3.2

Client/Server-Session
Eine Client/Server-Session unterscheidet sich von der Peer-to-Peer-DirectPlaySession. Genauso wie bei der Peer-to-Peer-Session bernimmt ein Computer die Aufgaben des Servers. Im Regelfall luft auf dem Server ein spezielles Serverprogramm. Auf den Clientcomputern laufen spezielle Clientprogramme. Auch in diesem Kommunikationsmodell bernimmt der Server alle verwaltenden Aufgaben. Er vergibt neue IDs fr eintretende Teinehmer oder Gruppen. Die einzelnen Computer stehen in keiner direkten Verbindung zueinander. Alle Nachrichten werden ber den Server geleitet. Wenn ein Teilnehmer eine Nachricht an alle Teilnehmer der Session senden mchte, so wird er die Nachricht zuerst an den Server leiten. Diese Nachricht ist mit der Bitte verbunden, diese an alle Teilnehmer der Session zu leiten. Das spezielle Serverprogramm entscheidet nun, ob es der Bitte nachkommen soll. Wenn dies der Fall ist, so wird jeder Teilnehmer der Session vom Server mit der Nachricht versorgt. Im Regelfall gehrt der Server nicht zu den Spielern einer Session. Es besteht allerdings die Mglichkeit, eine Kombination aus Peer-to-Peer und Client/Server zu erstellen. In dieser Mischform einer Session stehen den Teilnehmern alle Vor-

Kapitel 5 DirectPlay

357

zger der Peer-to-Peer-DirectPlay-Session inklusive eines Serverspielers zur Verfgung. Diese Form unterscheidet sich von einer reinen Peer-to-Peer-Session nur geringfgig. Der Unterschied liegt darin, dass alle Nachrichten ber den Server geleitet werden. In der reinen Client/Server-Session existiert kein Serverspieler. Alle Nachrichten werden an den Server geleitet. Dieser ist dann in der Lage zu entscheiden, was mit den Nachrichten geschehen soll. Nicht nur explizit von den Teilnehmern versendete Nachrichten gelangen zum Server, sondern auch automatisch erstellte Systemnachrichten finden den Weg zum Server.

Anwendung Computer A

Anwendung Computer B

Computer D Server

Anwendung Computer E

Anwendung Computer C
Bild 5.7: Nachrichten Client/Server

5.4

Lobbies
Eine DirectPlay-Lobby ist ein zentraler Platz im Netzwerk. An diesem Ort findet man geffnete Sessions sowie teilnehmende Spieler. Der Teilnehmer kann sich an diesem Ort frei bewegen und wenn etwas sein Interesse erweckt, so kann er der jeweiligen Session betreten. Natrlich kann der Teilnehmer auch eine eigene Session grnden. Die neu gegrndete Session steht fr die Besucher der Lobby dann bereit.

358

Service Provider

Die Architektur der DirectPlay-Lobby sieht so aus:


Lobby Client Anwendung 1 DirectPlay Objekt Lobby Provider

Lobby Server

Lobby Client Anwendung 2

DirectPlay Objekt

Lobby Provider

Bild 5.8:

Lobby-Architektur

5.5

Service Provider
Der Service Provider ist eine gemeinsame Schnittstelle zum managen von Sessions, Spielern und Gruppen. Weiterhin sorgt der Provider fr die Verbreitung von Informationen und organisiert den Service einer Lobby sowie weiterer Spieler im Netzwerk. Direct Play beinhaltet vier generische Service Provider: IPX Internet TCP/IP Serielle Verbindungen Modem-Verbindungen

DirectPlay verbirgt die Komplexitt dieser Verbindungen; so sind die eingesetzten Methoden auf alle Provider anwendbar. Der Programmierer muss sich nicht um das bertragungsprotokoll der Provider kmmern. So wird eine Anwendung, welche fr eine IPX-Verbindung erstellt wurde, auch ber eine TCP/IP-Verbindung funktionieren. Wenn man bercksichtigt, dass die verschiedenen Provider auch verschiedene bertragungsprotokolle nutzen, ist dies ein beachtlicher Service von DirectPlay.

5.6

Sicherheit
Mit DirectPlay ist es mglich eine erhhte Sicherheit fr eine Session zu erzeugen. Fr diesen Zweck werden Secure Sessions eingerichtet. Dabei wird die Sicherheit in das Windowssicherheitssystem (SSPI: Security Support Provider Interface) integriert.

Kapitel 5 DirectPlay

359

Folgende Sicherheitsmerkmale werden von DirectPlay gefrdert. Passwortschutz: Die Identitt eines Teilnehmers kann berprft werden. Erst nach der berprfung der Identitt kann eine Kommunikation zwischen Client und Server stattfinden. Digitale Signaturen fr Systemnachrichten: Anhand der Signatur kann die Identitt des Teilnehmers festgestellt werden. Verschlsselung: Empfindliche Nachrichten knnen verschlsselt und somit vor einem ungewnschten Lesen geschtzt werden.
Anwendung Verschlsselung MS RSA BASE CP CAPI Andere

DirectPlay Objekt Digitale Signatur NTML SSPI Andere

Bild 5.9:

Sicherheit

5.7

Nachrichten
Nachdem eine Anwendung einen Spieler erstellt hat, kann der Spieler mit anderen Spielern Nachrichten austauschen. Neben den eigens vom Spieler erstellten Nachrichten werden vom System die Systemnachrichten erstellt. Dies sind Nachrichten, welche z.B. den Zugang eines Spielers in eine Session signalisieren. Nachrichten knnen vom Spieler an einen speziellen Spieler gesendet werden oder an alle Spieler. Ebenfalls kann er die Nachricht an eine Untergruppe der Session senden. Dann empfangen alle Spieler dieser Gruppe die Nachricht. Systemnachrichten werden an alle Spieler einer Session gesendet. Systemnachrichten haben spezielle Absenderidentifikationen. Diese werden in Form von Konstanten bergeben wie z.B. DPID_SYSMSG. Alle Nachrichten, welche von einer Anwendung empfangen wurden, werden in eine Nachrichtenwarteschlange eingereiht. Die Anwendung muss eigenverantwortlich dafr sorgen, das die Nachrichtenwarteschlange abgefragt wird. Ebenfalls unterliegt es der Anwendung, die empfangenen Nachrichten zu interpretieren.

360

Nachrichten

5.7.1

Nachrichten empfangen
Nachrichten werden mit der DirectPlay4.Receive()-Methode empfangen. Hierzu erzeugt die Methode ein DirectPlayMessage-Objekt, welches mit den relevanten Informationen gefllt wird. Die Methode ist nur in der Lage jeweils eine Nachricht zu empfangen. Um die gesamte Nachrichtenwarteschlange abzuarbeiten, knnen Sie die Anzahl der Nachrichten mit der DirectPlay4.GetMessageCount()Methode abfragen. Das DirectPlayMessage-Objekt beinhaltet eine Vielzahl von bergabepltzen. Unter anderem finden wir dort auch einen Speicherplatz fr Variabeln vom Typ Long. Systemnachrichten werden anhand dieses Typs identifiziert. So ist es allgemein blich, das man auch die Spielernachrichten ber diesen Parameter identifiziert. Das ermglicht eine einheitliche Abarbeitung der Nachrichtenwarteschlange und eine einheitliche Interpretation der empfangenen Daten. Folgendes Listing empfngt alle Nachrichten aus der Nachrichtenwarteschlange:
Dim g_DP As DirectPlay4 is the DirectPlay4 object. Sub Nachrichten_Empfangen() Dim Count as Long Dim Type as Long Dim FromPlayerID As Long Dim ToPlayerID As Long Dim Nachricht as DirectPlayMessage Count = g_DP.GetMessageCount(PlayerId)

PlayerId identifiziert den Spieler, fr den die Nachrichtenwarteschlange abgefragt werden soll. Die Spieleridentifikation erhalten Sie, wenn Sie einen neuen Spieler erzeugen oder ein Spieler sich der Session anschliet.
For X = 1 to Count Set Nachricht = g_DP.Receive(FromPlayerID, _ ToPlayerID, DPRECEIVE_ALL) If FromPlayerID = DPID_SYSMSG Then Type = Nachricht.ReadLong()

Hier knnen Sie die Auswertung der Systemnachrichten vornehmen.


Else

Hier knnen Sie die Auswertung der Spielernachrichten vornehmen.


End If Next X End Sub

Kapitel 5 DirectPlay

361

Systemnachrichten Um Systemnachrichten auszuwerten, werden Konstanten aus der CONST_ DPSYSMSGTYPES-Liste bergeben. Diese werden beim Aufruf der Methode ReadLong() des DirectPlayMessage-Objekts zurckgegeben.
Enum CONST_DPSYSMSGTYPES DPLSYS_APPTERMINATED DPLSYS_CONNECTIONSETTINGSREAD DPLSYS_DPLAYCONNECTFAILED DPLSYS_DPLAYCONNECTSUCCEEDED DPLSYS_GETPROPERTY DPLSYS_GETPROPERTYRESPONSE DPLSYS_NEWCONNECTIONSETTINGS DPLSYS_NEWSESSIONHOST DPLSYS_SETPROPERTY DPLSYS_SETPROPERTYRESPONSE DPSYS_ADDGROUPTOGROUP DPSYS_ADDPLAYERTOGROUP DPSYS_CHAT DPSYS_CREATEPLAYERORGROUP DPSYS_DELETEGROUPFROMGROUP DPSYS_DELETEPLAYERFROMGROUP DPSYS_DESTROYPLAYERORGROUP DPSYS_HOST DPSYS_SECUREMESSAGE DPSYS_SENDCOMPLETE DPSYS_SESSIONLOST DPSYS_SETGROUPOWNER DPSYS_SETPLAYERORGROUPDATA DPSYS_SETPLAYERORGROUPNAME DPSYS_SETSESSIONDESC DPSYS_STARTSESSION End Enum = = = = = = = = = = = = = = = = = = = = = = = = = = 4 1 2 3 7 8 10 9 5 6 261 (&H105) 7 265 (&H109) 3 262 (&H106) 33 (&H21) 5 257 (&H101) 263 (&H107) 269 (&H10D) 49 (&H31) 266 (&H10A) 258 (&H102) 259 (&H103) 260 (&H104) 264 (&H108)

Wie Sie sehen, informiert uns das System bei einer ganzen Reihe von Aktionen. So erhalten wir die DPSYS_CREATEPLAYERORGROUP-Nachricht, wenn ein Spieler oder eine Gruppe der Session beitritt. Zustzlich zu den normalen Mglichkeiten die Daten einer Nachricht zu lesen, bietet DirectPlay folgende Methoden, um Standardsystemnachrichten zu lesen: DirectPlayMessage.MoveToSecureMessage() DirectPlayMessage.ReadSysMsgData() DirectPlayMessage.ReadSysChatString() DirectPlayMessage.ReadSysMsgConnection() DirectPlayMessage.ReadSysMsgSessionDesc()

362

Nachrichten

Spielernachrichten Die Spielernachrichten sind nicht darauf angewiesen, die Auswertung der Nachrichtenart ber den Long-Parameter des DirectPlayMessage-Objekts durchzufhren. Dennoch sollten Sie auch die Spielernachrichten ber diesen Eintrag identifizieren. So knnen Sie z.B. eine eigene Konstantenliste erzeugen und diese fr die Nachrichtenidentifizierung verwenden.
Enum CONST_SpielerNachrichten Spieler_nach_rechts Spieler_nach_links . . . End Enum

Neben dem Beschreiben der einzelnen Elemente des DirectPlayMessage-Objektes kann der Spieler auch einen eigenen Datenblock erstellen und versenden. Die meisten Anwendungen verwenden das Beschreiben der DirectPlayMessage-Elemente. Dies liegt zum einen an der Einfachheit und zum anderen reichen die Mglichkeiten fr fast alle Anwendungen aus. Sollten Sie sich dazu entscheiden, einen eigenen Datenblock zu versenden, so wird dieser Datenblock mit der DirectPlayMessage.SetMessageData()-Methode an das DirectPlayMessageObjekt bergeben. Dazu mssen Sie aber die genaue Gre des Datenblocks kennen. Dies ist nicht immer eine leichte Aufgabe. Die gesendeten Daten knnen dann mit der DirectPlayMessage.GetMessageData()-Methode ausgewertet werden. Auswerten von Nachrichten Das Auswerten von Nachrichten unterliegt einer festen Konvention. Sie mssen die Daten so auslesen, wie sie geschrieben wurden. Verdeutlichen wir uns das an einem Beispiel.
Dim Nachricht As DirectPlayMessage With Nachricht .WriteLong 1 .WriteString Hallo .WriteByte 10 End With

Wir haben das Nachrichtenobjekt mit ein paar Werten gefllt. Wenn die Nachricht beim Empfnger ankommt, muss dieser die Nachrichten in der gleichen Reihenfolge auslesen wie wir es beschrieben haben.
Dim nLong As Long Dim nString As String Dim nByte As Byte With nachricht

Kapitel 5 DirectPlay

363

nLong = .ReadLong nString = .ReadString nByte = .ReadByte End With

Sollten Sie die Nachrichten in einer anderen Reihenfolge auswerten, so werden Sie unsinnige Werte erhalten. Senden und Empfangen mssen synchronisiert sein.

5.7.2

Synchronisation
Nachrichten, welche gesendet wurden, mssen auch gelesen werden. Dazu gibt es zwei Wege. Der eine Weg ist, Sie fragen die Nachrichtenwarteschlange regelmig ab. Das lsst sich mit einer Do...Loop-Schleife gut vereinbaren.
Do While DoEvents() Nachrichten_Empfangen() Loop

Die Alternative ist, Sie erzeugen ein Event. Das Event wird immer dann ausgelst, wenn eine neue Nachricht eintrifft. Wie Sie ein Event einrichten, knnen Sie an den Beispielen fr DirectInput erkennen.

5.8

DirectPlay-Adresse
Eine DirectPlay-Adresse ist eine Datenformat, welches DirectPlay bentigt, um Verbindungen zu Lobby-Servern, Anwendungen oder Service-Providern herzustellen. Das DirectPlayAddress-Objekt wird zur Initialisierung einer DirectPlayAnwendung bentigt. Es beinhaltet Informationen ber den gewhlten Provider. Sie initialisieren eine Verbindung mit der DirectPlay4.InitializeConnection()Methode.
DirectPlay4.InitioalizeConnection(addr As DirectPlayAddress)

Sie knnen die DirectPlay-Adresse manipulieren oder sogar eine eigene Adresse erstellen. Dazu stehen folgende Methoden bereit:
CreateComPortAddress() CreateCustomAddress() CreateINetAddress() CreateLobbyProviderAddress() CreateModemAddress() CreateServiceProviderAddress()

364

DirectPlay-Protokoll

Die Manipulation der DirectPlay-Adresse ist im Regelfall berflssig. Beachten Sie, dass Ihnen die Verbindungsmglichkeiten ber die Netzwerkumgebung des eingesetzten Computersystems zur Verfgung gestellt wird. Dort knnen Sie die Manipulationen wesentlich komfortabler durchfhren. Explizit betrachten wir dabei die Modemverbindungen. Wie Sie sich auch entscheiden, gehen Sie behutsam vor, den jeder Fehler wird mit nicht funktionierenden Verbindungen bestraft. Die Fehlersuche ist dann nicht ganz einfach. Schlielich stehen Sie immer vor dem Problem: Liegt der Fehler am Quellcode oder an falschen Parametern des Providers?

5.9

DirectPlay-Protokoll
Das DirectPlay-Protokoll ist eine Umsetzung fr einen garantierten Nachrichtentransport bei Service-Providern, welche diesen Service eigentlich nicht bieten. Der IPX-Service-Provider untersttzt normalerweise keinen garantierten Nachrichtentransport. Mchten Sie ber diesen Service-Provider einen garantierten Nachrichtentransport umsetzen, so mssen Sie alle Vorkehrungen treffen um dies zu realisieren. Allgemein wird dies mit Handshaking bezeichnet. DirectPlay hilft uns bei diesem Problem aus der Patsche. Um das DirectPlay-Protokoll zu verwenden, mssen Sie beim Erzeugen der Session das DPSESSION_ DIRECTPLAYPROTOCOL-Flag setzen.
SessionData.SetFlags DPSESSION_MIGRATEHOST Or_ DPSESSION_DIRECTPLAYPROTOCOL g_dp.Open SessionData, DPOPEN_CREATE

Systemnachrichten werden jetzt garantiert bermittelt. Fr Nicht-Systemnachrichten mssen Sie jeder Nachricht explizit mitteilen, ob die bermittlung garantiert oder nicht garantiert erfolgen soll. Die garantierte bermittlung erreichen wir mit einem Flag der Sendemethoden.
g_dp.Send PlayerID, DPID_ALLPLAYERS, DPSEND_GUARANTEED, _ ChatMsg

Das DPSEND_GUARANTEED-Flag signalisiert DirectPlay, dass es sich um eine garantierte Nachrichtenbermittlung handeln soll. Weisen Sie beim Erzeugen der Session das DPSESSION_DIRECTPLAY PROTOCOL-Flag nicht ausdrcklich zu, dann knnen Nachrichten nur dann garantiert bermittelt werden, wenn es der Provider untersttzt. Betrachten wir die Fhigkeiten der Provider:

Kapitel 5 DirectPlay

365

Das DPSESSION_DIRECTPLAYPROTOCOL ist nicht gesetzt:


Service Provider IPX TCP/IP Modem garantiert Nein Ja Nein nicht garantiert Ja Ja Ja

Das DPSESSION_DIRECTPLAYPROTOCOL ist gesetzt:


Service Provider IPX TCP/IP Modem garantiert Ja Ja Ja nicht garantiert Ja Ja Ja

Eine garantierte Datenbermittlung dauert lnger als eine nicht garantierte. In vielen Fllen kann man auf eine Garantie verzichten. So z.B. wenn Sie die Position des gegnerischen Spielers in einem Netzwerkspiel bermitteln. Solch eine Information wird im Regelfall mehrmals pro Sekunde bertragen. Geht dabei eine Nachricht verloren, so macht sich das nicht bemerkbar. Nachrichten, die nur einmal gesendet werden, knnen auf eine garantierte bermittlung nicht verzichten. Geht diese Nachricht verloren, so hat das erhebliche Auswirkungen auf die gesamte Anwendung.

5.10

Session
Eine Session ist ein Kommunikationskanal zwischen zwei oder mehr Anwendungen. Dabei ist es nicht notwendig, dass die Anwendungen auf verschiedenen Computern existieren. Mit den IPX- bzw. TCP/IP-Providern knnen Sie auf einem Computer die Verbindung von mehreren Programmen herstellen. Dies ist eine hilfreiche Mglichkeit, die Funktionsweise der eigenen Anwendung zu testen. Wenn Sie eine Netzwerkanwendung starten, stehen Sie immer vor dem Problem, ob Sie sich einer Session anschlieen mchten oder eine neue Session grnden wollen. Um diese Entscheidung treffen zu knnen, mssen Sie darber informiert sein, welche Sessions geffnet sind und welchen Sessions Sie beitreten knnen. Die DirectPlay4.GetDPEnumSessions()-Methode erstellt eine Liste aller Sessions. Mit dem flags-Parameter der Methode knnen Sie die Liste der Sessions eingrenzen. So wird Ihnen die Konstante DPENUMSESSIONS_ALL alle Sessions (unabhngig ob Sie der Session beitreten knnen) auflisten. Die Konstante DPENUMSESSIONS_AVAILABLE begrenzt die Liste auf solche Sessions, welche noch neue Mitglieder akzeptieren. Passwortgeschtzte Sessions werden eben-

366

Session

falls vor den Augen des Anwenders verbogen. Die Kombination DPENUMSESSIONS_AVAILABLE und DPENUMSESSIONS_PASSWORD REQUIRED wird eine Liste aller Sessions erstellen, welche neue Mitglieder zulassen und ein Passwort bentigen. Nachdem Sie ber die existierenden Sessions informiert sind, knnen Sie sich mit der DirectPlay4.Open()-Methode einer Session anschlieen. Die gleiche Methode nutzen Sie, um eine neue Session zu erstellen. Wie sich die Methode verhlt, wird natrlich ber den flags-Parameter entschieden. So wird die Konstante DPOPEN_ CREATE eine neue Session erstellen. Um sich einer Session anzuschlieen, verwenden Sie die DPOPEN_JOIN-Konstante. Beispiel (Session) Auf der CD finden Sie in dem Ordner DirectPlay den Unterordner Sessions. Dort haben wir zwei Miniprogramme abgelegt. Das eine Programm erzeugt eine Session. Nach dem Starten knnen Sie zwischen 1 bis 4 Teilnehmern whlen. Die maximale Anzahl der Teilnehmer in der Session betrgt vier. Nachdem Sie die Session erstellt haben, knnen Sie mit dem zweiten Programm herausfinden, ob die Session offen fr neue Spieler ist oder nicht.

Bild 5.10: Bildschirmfoto Session

Die GetGuid()-Methode verwenden wir, um den richtigen Provider zu ermitteln. Da wir zwei Programme verwenden, ist es notwendig, dass beide Programme ber den gleichen Provider miteinander kommunizieren.

Kapitel 5 DirectPlay

367

GetGuid() Ermittelt die Guid einer Verbindung aus dem Auflistungsobjekt. object.GetGuid(index As Long) as String object index ein gltiges DirectPlayEnumConnections-Objekt Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll.

Session erzeugen:
Private Private Private Private Private Private Private g_dx As DirectX7 g_dp As DirectPlay4 DirectPlayEnum As DirectPlayEnumConnections DirectPlayAdresse As DirectPlayAddress Session As DirectPlayEnumSessions Player As DirectPlayEnumPlayers SessionData As DirectPlaySessionData

Private Sub Form_Load() Set g_dx = New DirectX7 Set g_dp = g_dx.DirectPlayCreate("") Set DirectPlayEnum = g_dp.GetDPEnumConnections("", _ DPCONNECTION_DIRECTPLAY) If DirectPlayEnum.GetCount = 0 Then End For i = 1 To DirectPlayEnum.GetCount If DirectPlayEnum.GetGuid(i) = "DPSPGUID_IPX" Then Exit For Next I Set DirectPlayAdresse = DirectPlayEnum.GetAddress(i) g_dp.InitializeConnection DirectPlayAdresse End Sub

In der Form_Load()-Subroutine initialisieren wir die notwendigen DirectXObjekte und erstellen das DirectPlay-Objekt. Anschlieend whlen wir den Provider und initialisieren die Verbindung. Dabei haben wir den IPX-Provider ausgewhlt. Diesen knnen Sie natrlich ndern.
Private Sub Command1_Click() Set SessionData = g_dp.CreateSessionData SessionData.SetSessionName "Session 1" SessionData.SetMaxPlayers 4 SessionData.SetFlags DPSESSION_DIRECTPLAYPROTOCOL Or _ PSESSION_MIGRATEHOST g_dp.Open SessionData, DPOPEN_CREATE Check1(0).Value = 1

Wir erstellen eine Session mit maximal vier Teilnehmern.

368

Session

PlayerName = "Session1 Spieler 1" PlayerHandle = "S1Spieler1" PlayerID1 = g_dp.CreatePlayer(PlayerName, PlayerHandle, 0, 0)

Mindestens ein Spieler wird erstellt.


If Check1(2).Value = 1 Then PlayerName = "Session1 Spieler 2" PlayerHandle = "S1Spieler2" PlayerID2 = g_dp.CreatePlayer(PlayerName, _ PlayerHandle, 0, 0) End If If Check1(3).Value = 1 Then PlayerName = "Session1 Spieler 3" PlayerHandle = "S1Spieler3" PlayerID3 = g_dp.CreatePlayer(PlayerName, _ PlayerHandle, 0, 0) End If If Check1(4).Value = 1 Then PlayerName = "Session1 Spieler 4" PlayerHandle = "S1Spieler5" PlayerID4 = g_dp.CreatePlayer(PlayerName, _ PlayerHandle, 0, 0) End If

Abhngig von von Ihrer Auswahl werden Spieler zwei, drei und vier erstellt. Erstellen Sie vier Spieler, dann haben Sie die maximal zulssige Anzahl von Spielern erreicht und die Session steht fr weitere Spieler nicht mehr offen.
Check1(5).Value = 1 Command1.Enabled = False End Sub

Das zweite Programm berprft, ob die Session fr zustzliche Spieler offen ist.
Private g_dx As DirectX7 Private g_dp As DirectPlay4 Private DirectPlayEnum As DirectPlayEnumConnections Private DirectPlayAdresse As DirectPlayAddress Private Session As DirectPlayEnumSessions Private SessionData As DirectPlaySessionData Private Sub Form_Load() Set g_dx = New DirectX7 Set g_dp = g_dx.DirectPlayCreate("") Set DirectPlayEnum = g_dp.GetDPEnumConnections("", _ DPCONNECTION_DIRECTPLAY) If DirectPlayEnum.GetCount = 0 Then End For i = 1 To DirectPlayEnum.GetCount If DirectPlayEnum.GetGuid(i) = "DPSPGUID_IPX" Then Exit For

Kapitel 5 DirectPlay

369

Next I Set DirectPlayAdresse = DirectPlayEnum.GetAddress(i) g_dp.InitializeConnection DirectPlayAdresse

Wiederum whlen wir den Provider und initialisieren die Verbindung. Sollte kein Provider gefunden werden, wird das Programm vorzeitig beendet.
Set SessionData = g_dp.CreateSessionData Set Session = g_dp.GetDPEnumSessions(SessionData, 0, _ DPENUMSESSIONS_AVAILABLE) If Session.GetCount <> 0 Then Check1(0).Value = 1 Else _ Check1(1).Value = 1 End Sub

Um zu prfen, ob die Session fr weitere Spieler offen ist, whlen wir das Flag DPENUMSESSIONS_AVAILABLE. Sollten wir bei der anschlieenden Abfrage der verfgbaren Sessions eine 0 erhalten, so wurde keine (fr weitere Spieler) offene Session gefunden.

5.11

Spieler
Aus der Betrachtungsweise einer Session ist ein Spieler ein Objekt, welches Daten sendet oder empfngt. Um die Spieler eindeutig zu identifizieren, vergibt die Session einen eindeutigen Index fr jeden Spieler. Ein Spieler kann ein lokaler oder ein entfernter Spieler sein. Ein lokaler Spieler existiert auf dem Computer, welcher die Session erzeugt hat. Ein entfernter Spieler existiert somit auf einem andern System. Die Systeme sind ber Netzwerkverbindungen verbunden. Jeder Computer bentigt mindestens einen lokalen Spieler, bevor eine Kommunikation mit andern Spielern stattfinden kann. Jedes Computersystem kann mehr als einen Spieler haben. Eine Kommunikation richtet sich immer an einen Spieler, niemals an einen Computer. Dabei stehen dem Sender verschiedene Arten der Nachrichtenverbreitung zur Verfgung. Die Nachricht kann zielgerichtet an einen speziellen Spieler erfolgen oder an eine Gruppe oder an alle anderen Spieler. Das Versenden von Nachrichten an alle Spieler ist vergleichbar mit einer Systemnachricht. Diese wird auch an alle Spieler gesendet. Fr das Verbreiten von Spielerinformationen bietet DirectPlay einige Mglichkeiten. So ist es mglich, einen rein lokalen Spieler zu erzeugen. Dessen Identitt ist fr andere Spieler nicht erkennbar. Natrlich kann auch ein normaler Spieler erzeugt werden, der sich artig bei allen anderen Spielern vorstellt. Mit der DirectPlay4.CreatePlayer()-Methode erzeugen Sie neue Spieler. Diese knnen mit der DirectPlay4.GetDPEnumPlayers()-Methode aus einer Session aufgelistet werden. ber Methoden wie DirectPlay4.SetPlayerName() oder DirectPlay4.SetPlayerData() knnen die Spielerinformationen gendert werden.

370

Spieler

Beispiel (Spieler) Auf der CD finden Sie in dem Ordner DirectPlay den Unterordner Spieler. Dort haben wir wiederum zwei Miniprogramme abgelegt. Das erste Programm ist identisch mit dem Session-Beispiel. Das zweite Programm ermittelt Informationen ber die Spieler der Session.

Bild 5.11: Bildschirmfoto Spieler

Starten Sie zuerst das Programm Session erzeugen. Anschlieend starten Sie das Programm Lesen. Ihnen werden drei Spieler angezeigt. Sie haben jetzt die Mglichkeit einen weiteren Spieler der Session anzuschlieen. Die Informationen ber die Session werden dann aktualisiert.
Private Sub Form_Load() Set g_dx = New DirectX7 Set g_dp = g_dx.DirectPlayCreate("") Set DirectPlayEnum = g_dp.GetDPEnumConnections("", _ DPCONNECTION_DIRECTPLAY) If DirectPlayEnum.GetCount = 0 Then End For i = 1 To DirectPlayEnum.GetCount If DirectPlayEnum.GetGuid(i) = "DPSPGUID_IPX" Then Exit For Next i Set DirectPlayAdresse = DirectPlayEnum.GetAddress(i)

Kapitel 5 DirectPlay

371

g_dp.InitializeConnection DirectPlayAdresse Set SessionData = g_dp.CreateSessionData Set Session = g_dp.GetDPEnumSessions(SessionData, 0, _ DPENUMSESSIONS_AVAILABLE) If Session.GetCount = 0 Then MsgBox "keine offene Session" Check1(1).Value = 1 Check1(0).Value = 0 End Else SessionGuid = Session.GetItem(1).GetGuidInstance Check1(1).Value = 0 Check1(0).Value = 1 Command1.Enabled = True End If

Bis hierher ist alles bekannt. Wir richten die DirectX-Objekte ein und initialisieren die Verbindung. Anschlieend prfen wir, ob eine offene Session existiert. Ist dies der Fall, so merken wir uns die SessionGuid.
Set SessionData = Session.GetItem(1) g_dp.Open SessionData, DPOPEN_JOIN

Um Informationen ber die Spieler zu erhalten, mssen wir uns der Session anschlieen. Dies bernimmt die DirectPlay4.Open()-Methode.
Set Spieler = g_dp.GetDPEnumPlayers(SessionGuid, _ DPENUMPLAYERS_ALL)

Die Informationen ber die Spieler erhalten wir durch die DirectPlay4.GetDP EnumPlayers()-Methode. Fr diese Methode bentigen wir die SessionGuid, die wir uns zuvor gemerkt haben.
List1.Clear For i = 1 To Spieler.GetCount List1.AddItem ("Rufname: " & Spieler.GetShortName(i)) List1.AddItem ("Hausname: " & Spieler.GetLongName(i)) List1.AddItem ("Typ: " & Spieler.GetType(i)) List1.AddItem ("ID: " & Spieler.GetDPID(i)) List1.AddItem ("------------------------------------") Next I

Die Informationen ber die Spieler lassen wir in eine Listbox eintragen.
End Sub

Sie haben die Mglichkeit, einen neuen Spieler hinzuzufgen. Dies bernimmt wiederum die DirectPlay4.CreatePlayer()-Methode. Anschlieend nehmen wir den neuen Spieler in die Listbox auf.

372

Bienenjagd Multiplayer Demo

PlayerName = "entfernter Spieler 1" PlayerHandle = "S1entfernterSpieler1" PlayerID1 = g_dp.CreatePlayer(PlayerName, PlayerHandle, 0, 0) Set Spieler = g_dp.GetDPEnumPlayers(SessionGuid, _ DPENUMPLAYERS_ALL) List1.Clear For i = 1 To Spieler.GetCount List1.AddItem ("Rufname: " & Spieler.GetShortName(i)) List1.AddItem ("Hausname: " & Spieler.GetLongName(i)) List1.AddItem ("Typ: " & Spieler.GetType(i)) List1.AddItem ("ID: " & Spieler.GetDPID(i)) List1.AddItem ("------------------------------------") Next I

5.12

Bienenjagd Multiplayer Demo


Abschlieend mchten wir noch ein kleines Netzwerkspiel vorstellen. Dieses ist Ihnen bereits aus dem DirectDraw-Abschnitt bekannt. Dort konnten Sie das Spiel Bienenjagd bereits im Single-Player-Modus spielen. Den richtige Reiz erhlt das Spiel aber erst im Duell mit einem Freund. Das Spiel ist folgendermaen konzipiert. Wir nutzen zwei Computer. Auf jedem der Computer luft das Spiel autonom. Lediglich wenn ein Spieler eine Biene trifft, wird der andere Computer (Spieler) darber informiert. Die Information wird in eine Aktion umgewandelt und die getroffene Biene verschwindet auf beiden Monitoren. Das Spiel luft autonom! Das bedeutet, dass die Positionen der Bienen auf den Monitoren nicht identisch sind. Jeder Computer berechnet fr sich die Geschwindigkeit und Position der Bienen. Da dies per Zufall entschieden wird, ist es fr beide Spieler gleichermaen gerecht. Das Programm beginnt mit der Auswahl des Providers. Wir whlen im Regelfall das IPX-Protokoll.
Set g_DX = New DirectX7 Set g_DP = g_DX.DirectPlayCreate("") List1.Clear Set DirectPlayEnum = g_DP.GetDPEnumConnections("", _ DPCONNECTION_DIRECTPLAY) If DirectPlayEnum.GetCount = 0 Then End For i = 1 To DirectPlayEnum.GetCount List1.AddItem (DirectPlayEnum.GetName(i)) Next I

Nach der Auswahl des Providers geht es mit der InitDP()-Subroutine in Module2 weiter.

Kapitel 5 DirectPlay

373

Bild 5.12: Bildschirmfoto Bienenjagd Login Public Sub InitDP() g_DP.InitializeConnection DirectPlayAdresse Set SessionData = g_DP.CreateSessionData Set Session = g_DP.GetDPEnumSessions(SessionData, 0, _ DPENUMSESSIONS_ALL) If Session.GetCount = 0 Then Set SessionData = g_DP.CreateSessionData SessionData.SetSessionName "Biene" SessionData.SetGuidApplication AppGuid SessionData.SetMaxPlayers 2 SessionData.SetFlags DPSESSION_MIGRATEHOST g_DP.Open SessionData, DPOPEN_CREATE SessionGuid = SessionData.GetGuidInstance PlayerName = "Host" PlayerHandle = "HandelHost" PlayerID = g_DP.CreatePlayer(PlayerName, _ PlayerHandle, 0, 0) HostIndex = True Waiting = True Unload Form2 Form3.Visible = True Form3.ZOrder 0 Else Set SessionData = Session.GetItem(1) g_DP.Open SessionData, DPOPEN_JOIN PlayerName = "Gast"

374

Bienenjagd Multiplayer Demo

PlayerHandle = "HandleGast" PlayerID = g_DP.CreatePlayer(PlayerName, _ PlayerHandle, 0, 0) Dim PlayerEnum As DirectPlayEnumPlayers Set PlayerEnum = g_DP.GetDPEnumPlayers("", 0) HostIndex = False End If End Sub

Je nachdem ob eine Session existiert, erffnen wir eine neue Session oder schlieen uns einer bestehenden Session an. Die InitDP()-Subroutine sollte fr Sie leicht verstndlich sein. Wenn noch keine Session existiert, dann erstellen wir eine neue Session mit einem Spieler. Die Anwendung wartet nun so lange, bis sich eine Gegenspieler der Session anschliet. Dann geht es los. Wenn eine Biene getroffen wurde, senden wir eine Nachricht. Diese Nachricht wird von Ihrem Gegenspieler empfangen und das Programm reagiert entsprechend. Schauen wir uns zuerst das Senden der Nachricht an.
Public Sub SendMessage(Index As Double) Dim ChatMsg As DirectPlayMessage Set ChatMsg = g_DP.CreateMessage Call ChatMsg.WriteLong(DPSYS_CHAT) Call ChatMsg.WriteDouble(Index) Call g_DP.Send(PlayerID, DPID_ALLPLAYERS, DPSEND_GUARANTEED, _ ChatMsg) End Sub

Wir definieren den Treffer einer Biene als DPSYS_CHAT-Nachricht. Sie knnen natrlich auch eine andere Form der Identifikation whlen. Zum Senden gehrt auch das Empfangen von Nachrichten.
Public Sub GetMessages() Dim MsgCount As Long Dim MsgType As Long Dim FromPlayerID As Long Dim ToPlayerID As Long Dim dpMsg As DirectPlayMessage MsgCount = g_DP.GetMessageCount(0) For x = 1 To MsgCount Set dpMsg = g_DP.Receive(FromPlayerID, ToPlayerID, _ DPRECEIVE_ALL) MsgType = dpMsg.ReadLong() Select Case MsgType Case DPSYS_DESTROYPLAYERORGROUP End Case DPSYS_CREATEPLAYERORGROUP Waiting = False

Kapitel 5 DirectPlay

375

Case DPSYS_HOST End Case DPSYS_CHAT Sprite(dpMsg.ReadDouble).Visible = False If HostIndex = True Then PunkteGast = _ PunkteGast +1 Else PunkteHost = PunkteHost + 1

Wenn die Nachricht eintrifft, dass eine Biene getroffen wurde, wird die VisibleEigenschaft des Sprites auf False gesetzt. Dies ist fr den Computer das Zeichen, die Geschwindigkeit und die Position der Biene neu zu errechnen. Gleichzeitig wird dem entsprechendem Spielerkonto der Treffer gutgeschrieben.
End Select Next X End Sub

Anhang A
Methoden
A.1 A.2 A.3 A.4 A.5 A.6 Globale DirectX7-Methoden DirectDraw-Methoden Direct3D-Methoden DirectSound-Methoden DirectInput DirectPlay-Methoden 378 390 430 457 483 505

378

Globale DirectX7-Methoden

A.1

Globale DirectX7-Methoden
DirectX7.ColorGetAlpha
ColorGetAlpha () Gibt den Alphaanteil eines Farbwertes zurck. DirectX7.ColorGetRed(), DirectX7.ColorGetBlue(), DirectX7.ColorGetGreen() object. ColorGetAlpha (color As Long) As Single object color ein gltiges DirectX7-Objekt Farbe, von der die Alphakomponente zurckgegeben wird, im Bereich von 0-255.

DirectX7.ColorGetBlue
ColorGetBlue() Gibt den Blauanteil eines Farbwertes zurck. DirectX7.ColorGetAlpha(), DirectX7.ColorGetRed(), DirectX7.ColorGetGreen() object. ColorGetBlue (color As Long) As Single object color ein gltiges DirectX7-Objekt Farbe, von der die Alphakomponente zurckgegeben wird, im Bereich von 0-255.

DirectX7.ColorGetGreen
ColorGetGreen() Gibt den Grnanteil eines Farbwertes zurck. DirectX7.ColorGetAlpha(), DirectX7.ColorGetBlue(), DirectX7.ColorGetRed() object. ColorGetGreen (color As Long) As Single object color ein gltiges DirectX7-Objekt Farbe, von der die Alphakomponente zurckgegeben wird, im Bereich von 0-255.

DirectX7.ColorGetRed
ColorGetRed () Gibt den Rotanteil eines Farbwertes zurck. DirectX7.ColorGetAlpha(), DirectX7.ColorGetBlue(), DirectX7.ColorGetGreen() object. ColorGetRed (color As Long) As Single

Anhang A Methoden

379

ColorGetRed () object color ein gltiges DirectX7-Objekt Farbe, von der die Alphacomponente zurckgegeben wird, im Bereich von 0-255.

DirectX7.CopyMatrix
CopyMatrix() Kopiert eine Quellmatrix in eine Zielmatrix. object. CopyMatrix (mDest As D3DMATRIX, mSrc As D3DMATRIX) As String object mDest mSrc ein gltiges DirectX7-Objekt Ziel vom Typ D3DMATRIX Quelle vom Typ D3DMATRIX

DirectX7.CreateColorRGB
CreateColorRGB() Erstellt eine RGB Farbe von den Farbanteilen. Rot, Grn und Blau. DirectX7.CreateColorRGBA() object. CreateColorRGB (r As Single, g As Single, b As Single) As _ Long object r,g,b ein gltiges DirectX7-Objekt Komponenten der RGB-Farbe

DirectX7.CreateColorRGBA
CreateColorRGBA() Erstellt eine RGBA Farbe aus den Farbanteilen. Rot, Grn, Blau und Alpha. DirectX7.CreateColorRGB() object. CreateColorRGBA (r As Single, g As Single, b As Single, _ a As Single) As Long object r,g,b,a ein gltiges DirectX7-Objekt Komponenten der RGBA-Farbe

380

Globale DirectX7-Methoden

DirectX7.CreateD3DLVertex
CreateD3DLVertex() Erstellt einen D3DLVertex und bergibt diesen an v vom Typ D3DLVERTEX. DirectX7.CreateD3DTLVertex(), DirectX7.CreateD3Dvertex() object. CreateD3DLVertex (x As Single, y As Single, z As Single, _ color As Long, specular As Long, tu As Single, tv As Single, _ v As D3DLVERTEX) object x,y,z color, specular tu,tv V ein gltiges DirectX7-Objekt Koordinaten des Vertexes Farbwerte zum Einstellen der RGBA-Farbe des Diffuse- und Specularanteils des Vertexes Texturkoordinaten des Vertexes Variable vom Typ D3DLVERTEX, die die LVertexdaten aufnimmt.

DirectX7.CreateD3DTLVertex
CreateD3DTLVertex() Erstellt einen D3DTLVertex und bergibt diesen an v vom Typ D3DTLVERTEX. DirectX7.CreateD3DLVertex(), DirectX7.CreateD3Dvertex() object. CreateD3DTLVertex (sx As Single, sy As Single, sz As _ Single, rhw As Single, color As Long, specular As Long, tu As _ Single, tv As Single, v As D3DTLVERTEX) object sx,sy,sz rhw color, specular tu,tv v ein gltiges DirectX7-Objekt Koordinaten des Vertexes in Bildschirmkoordinaten Gegenteil des einheitlichen W des Vertex. Farbwerte zum Einstellen der RGBA-Farbe des Diffuse- und Specularanteils des Vertexes. Texturekoordinaten des Vertexes Variable vom Typ D3DTLVERTEX, die die TLVertexdaten aufnimmt.

DirectX7.CreateD3DVertex
CreateD3Dvertex() Erstellt einen D3DVertex und bergibt diesen an v vom Typ D3DVERTEX. DirectX7.CreateD3DLVertex(), DirectX7.CreateD3DTLVertex()

Anhang A Methoden

381

CreateD3Dvertex() object. CreateD3DVertex (x As Single, y As Single, z As Single, nx As Single, _ ny As Single, nz As Single, tu As Single, tv As Single, v As D3DVERTEX) object x,y,z nx,ny,nz tu,tv v ein gltiges DirectX7-Objekt Koordinaten des Vertexes Normalvektorausrichtung fr den Abstrahlwinkel von Diffuse- und Specular-Licht Texturkoordinaten des Vertexes Variable vom Typ D3DVERTEX, die die Vertexdaten aufnimmt.

DirectX7.CreateEvent
CreateEvent() bergibt ein Handle an das Ereignisobjekt, das in einer Form implementiert wurde. DirectX7.SetEvent(), DirectX7.DestroyEvent(), DirectSoundBuffer.SetNotificationPosition(), DirectSoundCaptureBuffer.SetNotificationPosition(), DirectInputDevice.SetEventNotification(), DirectPlayLobby3.SetLobbyMessageEvent(), DirectMusicPerformance.SetNotificationHandle() object.GetDescription(event As DirectXEvent) As Long object event ein gltiges DirectX7-Objekt Ein DirectXEvent-Objekt, das in einer Form implementiert wurde.

DirectX7.CreateNewGuid
CreateNewGuid() Generiert eine global einmalige Indentifizierungskennzahl. object. CreateNewGuid () As String object ein gltiges DirectX7-Objekt

DirectX7.DestroyEvent
DestroyEvent() Lscht ein Eventhandle, das mit der DirectX.CreateEvent()-Methode erzeugt wurde. object. DestroyEvent (eventid As Long) object eventid ein gltiges DirectX7-Objekt Handle des zu lschenden Ereignisses

382

Globale DirectX7-Methoden

DirectX7.Direct3DRMCreate
Direct3DRMCreate() Erzeugt ein Direct3DRM3-Objekt. object. Direct3DRMCreate () As Direct3DRM3 object ein gltiges DirectX7-Objekt

DirectX7.DirectDrawCreate
DirectDrawCreate() Erzeugt ein DirectDraw7-Objekt. object. DirectDrawCreate (guid As String) As DirectDraw7 object guid ein gltiges DirectX7-Objekt Identifikationsnummer des Ausgabegertes. Die bergabe eines leeren Strings setzt den aktiven Displaytreiber als Ausgabegert fr DirectDraw.

DirectX7.DirectInputCreate
DirectInputCreate() Erzeugt ein DirectInput-Objekt. object. DirectInputCreate () As DirectInput object ein gltiges DirectX7-Objekt

DirectX7.DirectMusicComposerCreate
DirectMusicComposerCreate() Erzeugt ein DirectMusicComposer-Objekt. object. DirectMusicComposerCreate () As DirectMusicComposer object ein gltiges DirectX7-Objekt

DirectX7.DirectMusicLoaderCreate
DirectMusicLoaderCreate() Erzeugt ein DirectMusicLoader-Objekt. object. DirectMusicLoaderCreate () As DirectMusicLoader object ein gltiges DirectX7-Objekt

Anhang A Methoden

383

DirectX7.DirectMusicPerformanceCreate
DirectMusicPerformanceCreate() Erzeugt ein DirectMusicPerformance-Objekt. object. DirectMusicPerformanceCreate () As DirectMusicPerformance object ein gltiges DirectX7-Objekt

DirectX7.DirectPlayCreate
DirectPlayCreate() Erzeugt ein DirectPlay4-Objekt. object. DirectPlayCreate (guid As String) As DirectPlay4 object guid ein gltiges DirectX7-Objekt Identifikationsnummer des Service-Providers, an dem DirectPlay angemeldet wird. Wird ein leerer String bergeben, wird die Verbindung nicht initialisiert und die Applikation muss die DirectPlay4.InitializeConnection()-Methode ausfhren.

DirectX7.DirectPlayLobbyCreate
DirectPlayLobbyCreate() Erzeugt ein DirectPlayLobby3-Objekt. object. DirectPlayLobbyCreate () As DirectPlayLobby3 object ein gltiges DirectX7-Objekt

DirectX7.DirectSoundCaptureCreate
DirectSoundCaptureCreate() Erzeugt ein DirectSoundCapture-Objekt. object. DirectSoundCaptureCreate (guid As String) As _ DirectSoundCapture object guid ein gltiges DirectX7-Objekt Identifikationsnummer des Soundaufnahmegertes. Ein leerer String bewirkt, dass das aktuelle Aufnahmegert verwendet wird.

384

Globale DirectX7-Methoden

DirectX7.DirectSoundCreate
DirectSoundCreate() Erzeugt ein DirectSound-Objekt. object. DirectSoundCreate (guid As String) As DirectSound object guid ein gltiges DirectX7-Objekt Identifikationsnummer des Soundausgabegertes. Ein leerer String bewirkt, dass das aktuelle Ausgabegert verwendet wird.

DirectX7.GetDDEnum
GetDDEnum() Erstellt ein DirectDrawEnum-Objekt, welches zum Auslesen der im System installierten primren Bildschirmausgabegerte dient. object. GetDDEnum() As DirectDrawEnum object ein gltiges DirectX7-Objekt

DirectX7.GetDSCaptureEnum
GetDSCaptureEnum() Erzeugt ein DirectSoundEnum-Objekt, welches zum Auslesen der im System installierten Aufnahmegerte dient. object. GetDSCaptureEnum () As DirectSoundEnum object ein gltiges DirectX7-Objekt

DirectX7.GetDSEnum
GetDSEnum() Erzeugt ein DirectSoundEnum-Objekt, welches zum Auslesen der im System installierten Soundausgabegerte dient. object. GetDSEnum () As DirectSoundEnum object ein gltiges DirectX7-Objekt

DirectX7.GetWindowRect
GetWindowRect() bergibt die Position, Hhe und Breite einer grafischen Komponente, deren Handle an die Rotine bergeben wird, an eine Rect-Struktur vom Typ RECT.

Anhang A Methoden

385

GetWindowRect() object.GetWindowRect (hwnd As Long, r As RECT) object hwnd r ein gltiges DirectX7-Objekt Handle der grafischen Komponente Variable vom Typ RECT zum Aufnehmen der Koordinaten.

DirectX7.IdentityMatrix
IdentityMatrix() Fllt eine Variable vom Typ D3DMATRIX mit ihren Grundeinstellungen. Grundeinstellungen einer 4x4 Matrix (1,1) (2,2) (3,3) (4,4) auf Wert 1 object. IdentityMatrix (mDest As D3DMATRIX) object mDest ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die die Werte aufnimmt.

DirectX7.MatrixMultiply
MatrixMultiply() Multipliziert zwei Matrizen miteinander. object. MatrixMultiply (mDest As D3DMATRIX, mA As D3DMATRIX, _ mB As D3DMATRIX) object mDest mA mB ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die die errechneten Werte aufnimmt. Variable vom Typ D3DMATRIX als Multiplikator. Variable vom Typ D3DMATRIX als Multiplikationsfaktor.

mDest = mA * mB

DirectX7.ProjectionMatrix
ProjectionMatrix() Setzt die Koordinaten des nchsten und des am weitesten sichtbaren Vertexes. object. ProjectionMatrix (mDest As D3DMATRIX, _ nearPlane As Single, farPlane As Single, fov As Single) object mDest nearPlane ein gltiges DirectX7-Objekt Variable vom Typ D3DMatrix, die die errechneten Daten aufnimmt. nchster sichtbarer Punkt im 3D-Raum

386

Globale DirectX7-Methoden

ProjectionMatrix() farPlane fov weitester sichtbarer Punkt im 3D-Raum Breite des Sichtfeldes in Radiant [ Winkel /(180/Pi)]

DirectX7.RotateXMatrix
RotateXMatrix() Dreht eine Matrix um die X-Achse. object. RotateXMatrix (mDest As D3DMATRIX, radiant As Single) object mDest radians ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die die Daten aufnimmt. Winkel in Radiant, um den gedreht wird; Radiant=(Winkel / (180 / Pi)).

DirectX7.RotateYMatrix
RotateYMatrix() Dreht eine Matrix um die Y-Achse. object. RotateYMatrix (mDest As D3DMATRIX, radiant As Single) object mDest radians ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die die Daten aufnimmt. Winkel in Radiant, um den gedreht wird; Radiant=(Winkel / (180 / Pi)).

DirectX7.RotateZMatrix
RotateZMatrix() Dreht eine Matrix um die Z-Achse. object. RotateZMatrix (mDest As D3DMATRIX, radiant As Single) object mDest radians ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die die Daten aufnimmt. Winkel in Radiant, um den gedreht wird; Radiant=(Winkel / (180 / Pi)).

DirectX7.SetEvent
SetEvent() Setzt das Eventobjekt auf Signalisieren. object. SetEvent (eventid As Long)

Anhang A Methoden

387

SetEvent() object eventid ein gltiges DirectX7-Objekt Handle des Ereignisses, das auf Signal gesetzt wird.

DirectX7.SystemBpp
SystemBpp() Empfngt die aktuelle Bits pro Pixel-Einstellung des Systems. object. SystemBpp () As Long object ein gltiges DirectX7-Objekt

DirectX7.TickCount
TickCount() Empfngt das System TickCount in Millisekunden. (API: GetTickCount). object. TickCount () As Long object ein gltiges DirectX7-Objekt

DirectX7.VectorAdd
VectorAdd() Addiert zwei Vektoren miteinander. object.VectorAdd (v As D3DVECTOR, vA As D3DVECTOR, _ vB As D3DVECTOR) object v vA, vB ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die Daten aufnimmt. Variablen vomTyp D3DVECTOR, die addiert werden.

DirectX7.VectorCopy
VectorCopy() Erstellt eine Kopie eines Vektors. object. VectorCopy (vDest As D3DVECTOR, vSrc As D3DVECTOR) object VDest vSrc ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die Daten aufnimmt (Ziel). Variable vom Typ D3DVECTOR, die kopiert wird (Quelle).

388

Globale DirectX7-Methoden

DirectX7.VectorCrossProduct
VectorCrossProduct() Erstellt das Kreuzprodukt zweier Vektoren. object. VectorCrossProduct (v As D3DVECTOR, vA As D3DVECTOR, _ vB As D3DVECTOR) object v vA, vB ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die Daten aufnimmt. Variablen vom Typ D3DVECTOR, von denen das Kreuzprodukt berechnet wird.

DirectX7.VectorDotProduct
VectorDotProduct() Erstellt das Skalarprodukt zweier Vektoren. object. VectorDotProduct (vA As D3DVECTOR, _ vB As D3DVECTOR) As Single object vA, vB ein gltiges DirectX7-Objekt Variablen vom Typ D3DVECTOR, von denen das Skalarprodukt berechnet wird.

DirectX7.VectorModulus
VectorModulus() Berechnet die Lnge eines Vektors (Lnge = SQR(x^2+y^2+z^2)). object. VectorModulus (vA As D3DVECTOR) As Single object vA ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, deren Lnge berechnet wird.

DirectX7.VectorNormalize
VectorNormalize() Scaliert einen Vektor soweit bis seine Lnge = 1 ist. object. VectorNormalize (v As D3DVECTOR) object v ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die Daten aufnimmt.

Anhang A Methoden

389

DirectX7.VectorRotate
VectorRotate() Dreht einen Vektor um eine beliebige Achse. object. VectorRotate (vDest As D3DVECTOR, vA As D3DVECTOR, _ vAxis As D3DVECTOR, theta As Single) object vDest vA vAxis theta ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die errechneten Daten aufnimmt. Variable vom Typ D3DVECTOR, die den Originalvektor enthlt. Variable vom Typ D3DVECTOR, die die Drehachse beschreibt. Winkel in Radiant, um den gedreht wird.

DirectX7.VectorScale
VectorScale() Verndert die Lnge eines Vektors in allen drei Achsen. object. VectorScale (vDest As D3DVECTOR, vA As D3DVECTOR, _ factor As Single) object vDest vA factor ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die errechneten Daten aufnimmt. Variable vom Typ D3DVECTOR, die den Originalvektor enthlt. Faktor der Grennderung.

DirectX7.VectorSubtract
VectorSubtract() Subtrahiert zwei Vektoren voneinander. object. VectorSubtract (v As D3DVECTOR, vA As D3DVECTOR, _ vB As D3DVECTOR) object v vA vB ein gltiges DirectX7-Objekt Variable vom Typ D3DVECTOR, die die Daten aufnimmt. Variable vom Typ D3DVECTOR, von der subtrahiert wird. Variable vom Typ D3DVECTOR, die subtrahiert wird.

390

DirectDraw-Methoden

DirectX7.ViewMatrix
ViewMatrix() Erstellt eine Viewmatrix basierend auf der Kameraposition. object. ViewMatrix (mDest As D3DMATRIX, vFrom As D3DVECTOR, vTo As D3DVECTOR, vUp As D3DVECTOR, roll As Single) object mDest vFrom vTo vUp roll ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die die Daten aufnimmt. Variable vom Typ D3DVECTOR, die die Kameraposition angibt. Variable vom Typ D3DVECTOR, die die Sichtposition angibt. Variable vom Typ D3DVECTOR, die die aktuelle Weltmatrix beschreibt (0,1,0). Drehung der Kamera um den Sichtbereich.

DirectX7.ZeroMatrix
ZeroMatrix() Setzt alle Eintrge einer Matrix auf 0. object. ZeroMatrix (mDest As D3DMatrix) Object MDest ein gltiges DirectX7-Objekt Variable vom Typ D3DMATRIX, die auf Null gesetzt wird.

DirectXEvent.DXCallback
DXCallback() Managt die Rckrufroutinen der Ereignisse. object. DXCallback (eventid As Long) Object Eventid ein gltiges DirectXEvent-Objekt Ereignisshandle

A.2
A.2.1

DirectDraw-Methoden
DirectDraw7
Die DirectDraw7-Klasse erzeugt Objekte und arbeitet mit der Systemumgebung. Die Methoden der DirectDraw7-Klasse werden in folgenden Gruppen organisiert:

Anhang A Methoden

391

Cooperative Levels Erzeugen

SetCooperativeLevel TestCooperativeLevel CreateClipper CreatePalette CreateSurface CreateSurfaceFromFile CreateSurfaceFromResource GetDirect3D LoadPaletteFromBitmap GetCaps GetDisplayMode GetDisplayModesEnum GetMonitorFrequency RestoreDisplayMode SetDisplayMode WaitForVerticalBlank GetScanLine GetVerticalBlankStatus GetAvailableTotalMem GetDeviceIdentifier GetFourCCCodes GetFreeMem GetNumFourCCCodes DuplicateSurface FlipToGDISurface GetGDISurface GetSurfaceFromDC GetSurfacesEnum RestoreAllSurfaces

Fhigkeiten Display Modes

Display Zustand Verschiedenes

Oberflchen

DirectDraw7.CreateClipper
CreateClipper() Erzeugt ein DirectDrawClipper-Objekt. DirectDrawSurface7.GetClipper, DirectDrawSurface7.SetClipper object.CreateClipper(flags As Long) As DirectDrawClipper object flags ein gltiges DirectDraw7-Objekt Wird zurzeit nicht verwendet. Muss 0 sein.

392

DirectDraw-Methoden

DirectDraw7.CreatePalette
CreatePalette() Erzeugt ein DirectDrawPalette-Objekt. object.CreatePalette( flags As CONST_DDPCAPSFLAGS, _ pe() As PALETTEENTRY) As DirectDrawPalette object flags pe() ein gltiges DirectDraw7-Objekt CONST_DDPCAPSFLAGS Array von 2, 4, 16 oder 256 vom Typ PALETTEENTRY

DirectDraw7.CreateSurface
CreateSurface() Erzeugt ein DirectDrawSurface-Objekt. object.CreateSurface( dd As DDSURFACEDESC2) As DirectDrawSurface7 object dd ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDSURFACEDESC2; enthlt die Beschreibungen der Surface.

DirectDraw7.CreateSurfaceFromFile
CreateSurfaceFromFile() Erzeugt ein DirectDrawSurface-Objekt von einer Bitmap. object.CreateSurfaceFromFile(dd As DDSURFACEDESC2) _ As DirectDrawSurface7 object dd ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDSURFACEDESC2; enthlt die Beschreibungen der Surface.

Wenn Sie 256 Farben verwenden, sollten Sie zuerst den Displaymode und die Palette setzen. Sonst knnte die Surface mit falschen Farben dargestellt werden.

DirectDraw7.CreateSurfaceFromResource
CreateSurfaceFromResource() Erzeugt ein DirectDrawSurface-Objekt von einer Ressource. object.CreateSurfaceFromResource(file As String, resName As String, _ ddsd As DDSURFACEDESC2) As DirectDrawSurface7 object ein gltiges DirectDraw7-Objekt

Anhang A Methoden

393

CreateSurfaceFromResource() file Filename der Ressource. Ist die Ressource ein Teil des ausfhrbaren Programms, so bleibt dieser Parameter ein leerer String. Dieser Parameter kann auch der Name einer OCX sein. Name der Ressource eine Variable vom Typ DDSURFACEDESC2.

resName ddsd

Wenn Sie einen leeren String als Modulnamen angeben und die Anwendung in der VisualBasic-Umgebung luft, wird die Resource nicht gefunden. Verwenden Sie einen leeren Sting nur bei ausfhrbaren *.exe-Anwendungen.

DirectDraw7.DuplicateSurface
DuplicateSurface() Erzeugt ein genaue Kopie eines DirectDrawSurface-Objekts. object.DuplicateSurface( ddIn As DirectDrawSurface7) _ As DirectDrawSurface7 object ddIn ein gltiges DirectDraw7-Objekt Eine DirectDrawSurface, welche dupliziert werden soll

Die duplizierte Surface verweist auf den gleichen Speicher wie die Orginalsurface. Eine primre oder 3D-Surface kann nicht dupliziert werden.

DirectDraw7.FlipToGDISurface
FlipToGDISurface() Macht die Surface, auf welche das GDI-Grafiksystem schreibt zur primren Surface. DirecDraw7.GetGDISurface object.FlipToGDISurface() object ein gltiges DirectDraw7-Objekt

Um sicherzustellen, dass der vom GDI geschriebene Speicher sichtbar ist, wird diese Methode nach dem Page Flipping aufgerufen.

DirectDraw7.GetAvailableTotalMem
GetAvailableTotalMem() Liest die Gre des verwendeten Videospeichers einer Surface. object.GetAvailableTotalMem( ddsCaps As DDSCAPS2) As Long object ein gltiges DirectDraw7-Objekt

394

DirectDraw-Methoden

GetAvailableTotalMem() ddsCaps Eine Variable vom Typ DDSCAPS2, welche die Leistungsfhigkeit einer Surface beschreibt.

Diese Methode untersttzt lediglich eine Momentaufname des Videospeichers.

DirectDraw7.GetCaps
GetCaps() Liest das Leistungsvermgen einer Grafikkarte (HAL) oder des Hardware Emulators (HEL). object.GetCaps(hwCaps As DDCAPS, helCaps As DDCAPS) object hwCaps helCaps ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDCAPS, welche die Leistungsfhigkeit des Hardwaretreibers aufnimmt. Eine Variable vom Typ DDCAPS, welche die Leistungsfhigkeit des Hardware-Emulations-Treibers aufnimmt.

DirectDraw7.GetDeviceIdentifier
GetDevideIdentifier() Liest die Informationen des DirectDraw-Device-Treibers. object.GetDeviceIdentifier( flags As CONST_DDDEVICEIDFLAGS ) _ As DirectDrawIdentifier object flags ein gltiges DirectDraw7-Objekt eine Variable vom Typ CONST_DDDEVICEIDFLAGS

DirectDraw7.GetDirect3D
GetDirect3D() Erzeugt ein Direct3D7-Objekt. object.GetDirect3D() As Direct3D7 object ein gltiges DirectDraw7-Objekt

Die Methode liefert ein Direct3D7-Objekt. Dieses muss zuvor dimensioniert und zugeordnet sein. Dim Direct3D as Direct3D7 Set Direct3D = object.GetDirect3D()

Anhang A Methoden

395

DirectDraw7.GetDisplayMode
GetDisplayMode() Liest den aktuellen Display Mode. DirectDraw7.SetDisplayMode(), DirectDraw7.RestoreDisplayMode(), DirectDraw7.GetDisplayModesEnum() object.GetDirect3D() As Direct3D7 object surface ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDSURFACEDESC2, welche die Beschreibungen des aktuellen Display Mode aufnimmt.

Benutzen Sie diese Methode nicht, um den Display Mode wiederherzustellen. Dazu verwenden Sie die Methode DirectDraw7.RestoreDisplayMode().

DirectDraw7.GetDisplayModesEnum
GetDisplyModesEnum() Liest die aktuellen Display-Mode-Informationen der Grafikkarte. DirectDraw7.SetDisplayMode(), DirectDraw7.RestoreDisplayMode(), DirectDraw7. GetDisplayModesEnum() object.GetDisplayModesEnum(flags As CONST_DDEDMFLAGS, _ ddsd As DDSURFACEDESC2) As DirectDrawEnumModes object flags ddsd ein gltiges DirectDraw7-Objekt eine Konstante aus der CONST_DDEDMFLAGS-Liste Eine Variable vom Typ DDSURFACEDESC2, welche die mglichen Display Modes der Grafikkarte aufnimmt.

DirectDraw7.GetFourCCCodes
GetFourCCCodes() Liest die FOURCC-Codes, welche vom ausgewhlten DirectDraw Objekt untersttzt werden. object.GetFourCCCodes(ccCodes() As Long) object ccCodes() ein gltiges DirectDraw7-Objekt Ein Array, welches mit den FOURCC-Codes gefllt wird.

Um die Anzahl der unterstzten FOURCC-Codes zu ermitteln, benutzen Sie die DirectDraw7.GetNumFourCCCodes()-Methode.

396

DirectDraw-Methoden

DirectDraw7.GetFreeMem
GetFreeMem() Liest die Gre des zurzeit freien Videospeichers. object.GetFreeMem(ddsCaps As DDSCAPS2) As Long object ddsCaps ein gltiges DirectDraw7-Objekt Eine Variable vom Typ DDSCAPS2, welche die Hardwareeigenschaften einer Surface beschreibt.

Diese Methode liefert lediglich eine Momentaufname des verfgbaren Videospeichers.

DirectDraw7.GetGDISurface
GetGDISurface() Ermittelt die Surface, welche vom GDI-Grafiksystem als primre Surface verwendet wird. DirectDraw7.FlipToGDISurface() object.GetGDISurface() As DirectDrawSurface7 object ein gltiges DirectDraw7-Objekt

DirectDraw7.GetMonitorFrequency
GetMonitorFrequency() Ermittelt die aktuelle Monitorfrequenz in Hz. object.GetGDISurface() As DirectDrawSurface7 object ein gltiges DirectDraw7-Objekt

DirectDraw7.GetNumFourCCCodes
GetNumFourCCCodes() Ermittelt die Anzahl der untersttzten FOURCC-Codes. object.GetGDISurface() As DirectDrawSurface7 object ein gltiges DirectDraw7-Objekt

Diese Methode wird im Regelfall vor der DirectDraw7.GetFourCCodes()-Methode aufgerufen.

Anhang A Methoden

397

DirectDraw7.GetScanLine
GetScanLine() Ermittelt die aktuelle Scanline, welche in diesem Augenblick gezeichnet wird. DirectDraw7.GetVerticalBlankStatus(), DirectDraw7.WaitForVerticalBlank() object.GetScanLine(lines As Long) As Long object lines ein gltiges DirectDraw7-Objekt aktuelle Scanline

DirectDraw7.GetSurfaceFromDC
GetSurfaceFromDC() Ermittelt ein DirectDrawSurface7-Objekt, welches durch das Handle der GDI-Umgebung beschrieben wird. object.GetSurfaceFromDC(hdc As Long) As DirectDrawSurface7 object hdc ein gltiges DirectDraw7-Objekt Handle eines Gertekontexts

DirectDraw7.GetSurfacesEnum
GetSurfacesEnum() Ermittelt ein DirectDrawEnumSurfaces-Objekt, welches die mit einem DirectDraw7Objekt verbundenen Surfaces auflisten kann. object.GetSurfaceFromDC(hdc As Long) As DirectDrawSurface7 object flags desc ein gltiges DirectDraw7-Objekt Eine Konstante aus der CONST_DDENUMSURFACESFLAGS-Liste. Sie beschreibt, wie die Methode nach verbundenen Surfaces suchen soll. Eine Variable vom Typ DDSURFACEDESC2, welche die Suchkriterien festlegt.

DirectDraw7.GetVerticalBlankStatus
GetVerticalBlankStatus() Ermittelt den Status des Vertialleerlaufs. DirectDraw7.GetScanLine(), DirectDraw7.WaitForVerticalBlank() object.GetVerticalBlankStatus() As Long object ein gltiges DirectDraw7-Objekt

398

DirectDraw-Methoden

DirectDraw7.GetWindowsRect
GetWindowsRect() Ermittelt die Eckwerte eines Rechtecks, welches den Clientbereich eines Fensters beschreibt. Call object.GetWindowRect(hwnd As Long, r As RECT) object hwnd r ein gltiges DirectDraw7-Objekt Handle eines Fensters, dessen Clientbereich ermittelt werden soll. Eine Variable vom Typ RECT, welche die ermittelten Werte aufnimmt.

DirectDraw7.LoadPaletteFromBitmap
LoadPaletteFromBitmap() Erzeugt ein DirectDrawPalette-Objekt auf der Basis einer Bitmap. object.GetVerticalBlankStatus() As Long object bName ein gltiges DirectDraw7-Objekt Name der Bitmap

DirectDraw7.RestoreAllSurfaces
RestoreAllSurfaces() Stellt alle Surfaces, welche mit dem DirectDraw7-Objekt erzeugt wurden, wieder her. DirectDrawSurface7.Restore() object.GetVerticalBlankStatus() As Long object ein gltiges DirectDraw7-Objekt

DirectDraw7.RestoreDisplayMode
RestoreDisplyMode() Restauriert den Displaymode der primren Surface auf den Zustand, der vor dem Aufruf der Methode DirectDraw7.SetDisplyMode() herrschte. DirectDraw7.SetDisplayMode(), DirectDrawEnumModes(), DirectDraw7.SetCooperativeLevel() object.RestoreDisplayMode() object ein gltiges DirectDraw7-Objekt

Anhang A Methoden

399

DirectDraw7.SetCooperativeLevel
SetCooperativeLevel() Beschreibt den Toplevel einer Anwendung. Toplevel fr Fensterdarstellung oder Fullscreen. DirectDraw7.SetDisplayMode(), DirectDraw7.GetDisplayModesEnum() object.SetCooperativeLevel(hdl As Long, flags As CONST_DDSCLFLAGS) object hdl ein gltiges DirectDraw7-Objekt Ein Windows-Handle fr die Anwendung. Im Regelfall wird das Handle eines Formobjektes oder eines Pictureobjektes verwendet. Dieser Parameter kann 0 sein, wenn als flags DDSCL_NORMAL gewhlt wird. Eine Konstante aus der CONST_DDSCLFLAGS-Liste. Sie beschreibt den Kooperativlevel an sich.

flags

DirectDraw7.SetDisplayMode
SetDisplayMode() Setzt einen gltigen Displaymode einer Grafikkarte. Der gewhlte Mode muss von der Grafikkarte untersttzt werden. DirectDraw7.RestoreDisplayMode(), DirectDraw7.GetDisplayModesEnum(), DirectDraw7.SetCooperativeLevel() object.SetDisplayMode( w As Long, h As Long, bpp As Long, ref As Long, _ mode As CONST_DDSDMFLAGS) object w und h bpp ref mode ein gltiges DirectDraw7-Objekt Weite und Hhe des neuen Modes Auflsung in Bits per Pixel Wiederholfrequenz. Dieser Wert kann auf 0 gesetzt werden, dann wird die voreingestellte Wiederholfrequenz der Garfikkarte verwendet. Eine Konstant aus der CONST_DDSDMFLAGS-Liste. Zurzeit ist der einzig gltige Eintrag DDSDM_STANDARDVGAMODE.

DirectDraw7.TestCooperativeLevel
TestCooperativeLevel() Ermittelt den aktuellen CooperativeLevelStatus fr eine Fenster- oder FullscreenAnwendung. object.TestCooperativeLevel() As Long object ein gltiges DirectDraw7-Objekt

400

DirectDraw-Methoden

TestCooperativeLevel() Die Methode liefert ein DD_Ok, wenn alles in Ordnung ist.

DirectDraw7.WaitForVerticalBlank
WaitForVerticalBlank() Diese Methode wartet auf den vertikalen Leerlauf des Monitorrasterstrahls. DirectDraw7.GetVerticalBlankStatus(), DirectDraw7.GetScanLine() object.WaitForVerticalBlank( flags As CONST_DDWAITVBFLAGS, _ handle As Long) As Long object flags handle ein gltiges DirectDraw7-Objekt Eine Konstante aus der CONST_DDWAITVBFLAGS-Liste, welche die Wartezeit auf den vertikalen Leerlauf festlegt. Handle eines Ereignisses. Dieser Parameter ist optional.

A.2.2

DirectDrawClipper
Die DirectDrawClipper-Klasse handelt die Clipliste. Die DirectDrawClipper-Methoden sind in folgende Klassen organisiert:
Clipliste GetClipList GetClipListSize IsClipListChanged SetClipList GetHWnd SetHWnd

Handles

DirectDrawClipper.GetClipList
GetClipList() Ermittelt die Clipliste, welche mit dem Clipper-Objekt verbunden ist. DirectDrawClipper.SetClipList() object.GetClipList(rects() As RECT) object rects() ein gltiges DirectDrawClipper-Objekt Ein Array, welches die Clipliste aufnimmt.

Anhang A Methoden

401

DirectDrawClipper.GetClipListSize
GetClipListSize() Ermittelt die Cliplistengre in Bytes. object.GetClipList(rects() As RECT) object ein gltiges DirectDrawClipper-Objekt

DirectDrawClipper.GetHWnd
GetHWnd() Ermittelt das Windows-Handle, welches mit dem Clipper-Objekt verbunden ist. DirectDrawClipper.SetHWnd() object.GetHWnd() As Long object ein gltiges DirectDrawClipper-Objekt

DirectDrawClipper.IsClipListChanged
IsClipListChanged() Ermittelt den Status der Clipliste, wenn sie mit dem Clipper-Objekt verbunden ist. object.IsClipListChanged() As Long object ein gltiges DirectDrawClipper-Objekt

Ist das Ergebnis =0, so wurde die Clipliste nicht verndert.

DirectDrawClipper.SetClipList
SetClipList() Setzt oder lscht eine Clipliste. DirectDrawClipper.GetClipList(), DirectDrawSurface7.Blt(), DirectDrawSurface7.BltFast() object.SetClipList( count As Long, rects() as RECT object count rects() ein gltiges DirectDrawClipper-Objekt die Anzahl der RECT-Strukturen in dem rects() Array Array mit RECT-Strukturen, welche die Clipliste beschreiben.

Die Clipliste kann nicht gesetzt werden, wenn das Windows-Handle mit dem ClipperObjekt verbunden ist. Die DirectDraw7.BltFast()-Methode kann nicht clippen.

402

DirectDraw-Methoden

DirectDrawClipper.SetHWnd
SetHWnd() Setzt das Windows-Handle, welches die Clippinginformationen enthlt. DirectDrawClipper.GetHWnd() object.SetHWnd(hdl As Long) object hdl ein gltiges DirectDrawClipper-Objekt Windows-Handle

A.2.3

DirectDrawColorControl
Die DirectDrawColorControl-Klasse erlaubt es, auf das Farbkontrollelement zuzugreifen. Die DirectDrawColorControl-Methoden sind in folgende Klassen organisiert:
Color controls GetColorControls SetColorControls

DirectDrawColorControl.GetColorControls
GetColoControl() Ermittelt die aktuellen Color-Control-Einstellungen, welche mit einer Overlay- oder primren Surface verbunden sind. DirectDrawColorControl.SetColorControls() object.GetColorControls(colorControl As DDCOLORCONTROL) object ColorControl ein gltiges DirectDrawColorControl-Objekt Eine Variable vom Typ DDCOLORCONTROL, welche die Informationen aufnimmt.

Die Methode verursacht einen Fehler, wenn das Gafikgert Color Control nicht untersttzt.

DirectDrawColorControl.SetColorControls
SetColorControl() Setzt die aktuellen Color-Control-Einstellungen, welche mit einer Overlay- oder primren Surface verbunden sind. DirectDrawColorControl.GetColorControls() object.SetColorControls(colorControl As DDCOLORCONTROL) object ein gltiges DirectDrawColorControl-Objekt

Anhang A Methoden

403

SetColorControl() colorControl Eine Variable vom Typ DDCOLORCONTROL, welche die Informationen enthlt.

A.2.4

DirectDrawEnum
Die DirectDrawEnum Klasse liefert Informationen ber die installierten Grafikkarten. Das DirectDrawEnum-Objekt wird mit der DirectX7.GetDDEnum()-Methode erzeugt. Folgende Methoden gehren zu der DirectDrawEnum-Klasse:
Gerte GetCount GetDescription GetGuid GetMonitorHandle GetName

DirectDrawEnum.GetCount
GetCount() Emittelt die Anzahl der installierten DirectDraw-Treiber. object.GetCount() As Long object ein gltiges DirectDrawEnum-Objekt

DirectDrawEnum.GetDescription
GetDescription() Ermittelt die Gertebeschreibung des selektierten DirectDraw-Gertes. object.GetDescription(index As Long) As String object index ein gltiges DirectDrawEnum-Objekt ein DirectDraw-Gert im DirectDrawEnum-Objekt

DirectDrawEnum.GetGuid
GetGuid() Ermittelt den Guid des selektierten DirectDraw-Gertes. object.GetGuid(index As Long) As String

404

DirectDraw-Methoden

GetGuid() object index ein gltiges DirectDrawEnum-Objekt ein DirectDraw-Gert im DirectDrawEnum-Objekt

DirectDrawEnum.GetMonitorHandle
GetMonitorHandle() Ermittelt das Monitor-Handle des selektierten DirectDraw Gertes. object.GetName(index As Long) As Long object index ein gltiges DirectDrawEnum-Objekt ein DirectDraw-Gert im DirectDrawEnum-Objekt

DirectDrawEnum.GetName
GetName() Ermittelt den Namen des selektierten DirectDraw-Gertes. object.GetName(index As Long) As String object index ein gltiges DirectDrawEnum-Objekt ein DirectDraw-Gert im DirectDrawEnum-Objekt

A.2.5

DirectDrawEnumModes
Die DirectDrawEnumModes-Klasse erzeugt eine Liste mit verfgbaren Videomodes fr ein System. Das DirectDrawEnumModes-Objekt wird mit der DiretDraw7.GetDisplayModesEnum()-Methode erzeugt. Folgende Methoden gehren zu der DirectDrawEnumModes-Klasse:
Display Mode GetCount GetItem

DirectDrawEnumModes.GetCount
GetCount() Ermittelt die Anzahl der verfgbaren Videomodes. object.GetCount() As Long object ein gltiges DirectDrawEnumModes-Objekt

Anhang A Methoden

405

DirectDrawEnumModes.GetItem
GetItem() Ermittelt die Beschreibung des selektierten Videomodes. object.GetItem(index As Long, info As DDSURFACEDESC2) object index info ein gltiges DirectDrawEnumModes-Objekt ein Element aus dem DirectDrawEnumModes-Objekt Eine Variable vom Typ DDSURFACEDESC2, welche die Informationen des Videomodes aufnimmt.

A.2.6

DirectDrawEnumSurfaces
Die Methode DirectDrawEnumSurfaces() erstellt eine Liste mit allen erzeugten Surfaces. Das DirectDrawEnumSurfaces-Objekt wird mit der DirectDraw7.GetAttachedSurfaceEum()-Methode erzeugt. Folgende Methoden gehren zu der DirectDrawEnumSurfaces-Klasse:
Oberflchen GetCount GetItem

DirectDrawEnumSurfaces.GetCount
GetCount() Ermittelt die Anzahl der erzeugten Surfaces. object.GetCount() As Long object ein gltiges DirectDrawEnumSurfaces-Objekt

DirectDrawEnumSurfaces.GetItem
GetItem() Ermittelt die Surfacebeschreibungen der selektierten Surface. object.GetItem(index As Long) As DirectDrawSurface7 object index ein gltiges DirectDrawEnumSurfaces-Objekt ein Element aus dem DirectDrawEnumSurfaces-Objekt

406

DirectDraw-Methoden

A.2.7

DirectDrawGammaControl
Anwendungen nutzen die Methoden der DirectDrawGamaControl-Klasse um die Rot-, Grn- und Blaulevel der primren Surface einzustellen. Das DirectDrawGammaControl-Objekt wird mit der DiretDrawSurface7.GetDirectDrawGammaControl()-Methode erzeugt. Folgende Methoden gehren zu der DirectDrawGammaControl-Klasse:
Gamma-Kontroll-Element GetGammaRamp SetGammaRamp

DirectDrawGammaControl.GetGammaRamp
GetGamaRamp() Ermittelt die Rot-, Grn- und Blaulevel der primren Surface. DirectDrawGammaControl.SetGammaRamp() object.GetGammaRamp( flags As CONST_DDSGRFLAGS, _ gammaRamp As DDGAMMARAMP) object flags gammaRamp ein gltiges DirectDrawGammaControl-Objekt eine Konstante der CONST_DDSGRFLAGS-Liste Eine Variable vom Typ DDGAMMARAMP, welche die ermittelten Informationen aufnimmt.

DirectDrawGammaControl.SetGammaRamp
SetGammaRamp() Setzt die Rot-, Grn- und Blaulevel der primren Surface. DirectDrawGammaControl.GetGammaRamp() object.GetGammaRamp( flags As CONST_DDSGRFLAGS, _ gammaRamp As DDGAMMARAMP) object flags gammaRamp ein gltiges DirectDrawGammaControl-Objekt eine Konstante der CONST_DDSGRFLAGS-Liste Eine Variable vom Typ DDGAMMARAMP, welche die ermittelten Informationen aufnimmt.

A.2.8

DirectDrawIdentifier
Anwendungen verwenden die Methoden der DirectDrawIdentifier-Klasse, um Informationen ber den DirectDraw-Treiber zu erhalten.

Anhang A Methoden

407

Das DirectDrawIdentifier-Objekt wird mit der DirectDraw7.GetDrviceIdentifier()-Methode erzeugt. Folgende Methoden gehren zu der DirectDrawIdentifier-Klasse:
Treiberinformation GetDescription GetDeviceId GetDeviceIdentifier GetDriver GetDriverSubVersion GetDriverVersion GetRevision GetSubSysId GetVendorId GetWHQLLevel

DirectDrawIdentifier.GetDescription
GetDescription() Ermittelt die Treiberbeschreibung. object.GetDescription() As String object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetDeviceId
GetDeviceId() Ermittelt die Treiber ID. object.GetDeviceId() As Long object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetDeviceIdentifier
GetDeviceIdentifier() Ermittelt eine eindeutige Identifizierung des Treibers. object.GetDeviceIndentifier() As String object ein gltiges DirectDrawIdentifier-Objekt

408

DirectDraw-Methoden

DirectDrawIdentifier.GetDriver
GetDriver() Ermittelt den Namen des Treibers. object.GetDriver() As String object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetDriverVersion
GetDriverVersion() Ermittelt den ersten Teil (high) der Treiberversion. object.GetDriverVersion() As Long object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetDriverSubVersion
GetDriverSubVersion() Ermittelt den zweiten Teil (low) der Treiberversion. object.GetDriverSubVersion() As Long object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetRevision
GetRevision() Ermittelt die Revisionsnummer des Treibers. object.GetRevision() As Long object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetSubSysId
GetSubSysId() Ermittelt die ID des Treibersubsystems. object.GetSubSysId() As Long object ein gltiges DirectDrawIdentifier-Objekt

Anhang A Methoden

409

DirectDrawIdentifier.GetVendorId
GetVendorld() Ermittelt den Hersteller des Treibers. object.GetVendorId() As Long object ein gltiges DirectDrawIdentifier-Objekt

DirectDrawIdentifier.GetWHQLLevel
GetWHQLLevel() Ermittelt den Hardwarequalittslevel. object.GetWHQLLevel() As Long object ein gltiges DirectDrawIdentifier-Objekt

A.2.9

DirectDrawPalette
Die DirectDrawPalette-Klasse behandelt den Umgang mit der Systempalette. Das DirectDrawPalette-Objekt wird mit der DirectDrawSurface7.GetPalette()Methode erzeugt. Folgende Methoden gehren zu der DirectDrawPalette-Klasse:
Palette capabilities Palette entries GetCaps GetEntries SetEntries

DirectDrawPalette.GetCaps
GetCaps() Ermittelt die Eigenschaften des Palette-Objekts. object.GetCaps() As CONST_DDPCAPSFLAGS object ein gltiges DirectDrawPalette-Objekt

DirectDrawPalette.GetEntries
GetEntries() Ermittelt die einzelnen Werte eines Palette-Objekts. DirectDrawPalette.SetEntries()

410

DirectDraw-Methoden

GetEntries() object.GetEntries( start As Long, count As Long, val() As PALETTEENTRY) object start count val() ein gltiges DirectDrawPalette-Objekt ab wo die Eintrge gelesen werden sollen wie viele Eintrge gelesen werden sollen. Ein Array vom Typ PALETTEENTRY, welches die Informationen aufnimmt.

Haben Sie eine 8-Bit-Palette mit der DirectDraw7.CreatePalette()-Methode erzeugt, sind die Paletteneintrge 1 Byte gro, andererseits sind die Eintrge 4 Byte gro.

DirectDrawPalette.SetEntries
SetEntries() Setzt die einzelnen Werte eines Palette Objekts. DirectDrawPalette.GetEntries(), DirectDrawSurface7.SetPalette() object.GetEntries( start As Long, count As Long, val() As _ PALETTEENTRY) object start count val() ein gltiges DirectDrawPalette-Objekt ab wo die Eintrge gesetzt werden sollen wie viele Eintrge gesetzt werden sollen. Ein Array vom Typ PALETTEENTRY, welches die Informationen enthlt.

A.2.10 DirectDrawSurface7
Die DirectDrawSurface7-Klasse verwaltet den Umgang mit Surfaces. Folgende Methoden gehren zu der DirectDrawSurface7-Klasse:
Speicher Surfaces verbinden IsLost Restore AddAttachedSurface DeleteAttachedSurface GetAttachedSurface GetAttachedSurfaceEnum

Anhang A Methoden

411

Blitting

Blt BltColorFill BltFast BltFx BltToDC GetBltStatus GetColorKey SetColorKey GetDC ReleaseDC DrawBox DrawCircle DrawEllipse DrawLine DrawRoundedBox DrawText GetDrawStyle GetDrawWidth GetFillColor GetFillStyle GetFontBackColor GetFontTransparency GetForeColor SetDrawStyle SetDrawWidth SetFillColor SetFillStyle SetFont SetFontBackColor SetFontTransparency SetForeColor Flip GetFlipStatus GetLockedArray GetLockedPixel Lock SetLockedPixel Unlock GetDirectDraw GetDirectDrawColorControl GetDirectDrawGammaControl

Farbschlssel Gerteumgebung Zeichnen und Text

Flipping Locking

Verschiedenes

412

DirectDraw-Methoden

Overlays

GetOverlayPosition GetOverlayZOrdersEnum SetOverlayPosition UpdateOverlay UpdateOverlayFx UpdateOverlayZOrder GetCaps GetClipper SetClipper ChangeUniquenessValue GetPixelFormat GetSurfaceDesc GetUniquenessValue GetPalette SetPalette GetLOD GetPriority SetLOD SetPriority

Surface Fhigkeiten Clipper Surface Merkmale

Surface Paletten Texturen

DirectDrawSurface7.AddAttachedSurface
AddAttachedSurface() Verbindet die spezifizierte Surface mit dieser Surface. object.AddAttachedSurface(ddS As DirectDrawSurface7) object dds ein gltiges DirectDrawSurface7-Objekt die zu verbindende Surface

DirectDrawSurface7.Blt
Blt() Kopiert Daten per Bit-Block-Transfer aus einem Speicherbereich in einen anderen. object.Blt(destRect As RECT, ddS As DirectDrawSurface7, _ srcRect As RECT, flags As CONST_DDBLTFLAGS) As Long object destRect ein gltiges DirectDrawSurface7-Objekt Variablen vom Typ RECT, welche die Punkte oben links und unten rechts eines Rechtecks beschreiben. Wird dieser Wert nicht angegeben oder sind die Werte der Variablen leer, so wird der gesamte Bereicht der Ziel-Surface angenommen. Ein gltiges Surface-Objekt, welches die Daten aufnehmen soll.

dds

Anhang A Methoden

413

Blt() srcRect Variablen vom Typ RECT, welche die Punkte oben links und unten rechts eines Rechtecks beschreiben. Wird dieser Wert nicht angegeben oder sind die Werte der Variablen leer, so wird der gesamte Bereicht der Quell-Surface angenommen. Eine Kombination von Argumenten aus der CONST_DDBLTFLAGSListe.

Flags

DirectDrawSurface7.BltColorFill
BltColorFill() Fllt einen rechteckigen Bereich mit einer Farbe. object.BltColorFill( destRect As RECT, fillvalue As Long) As Long object destRect fillvalue ein gltiges DirectDrawSurface7-Objekt Ein rechteckiger Bereich, welcher mit einer Farbe gefllt werden soll. Farbe

DirectDrawSurface7.BltFast
BltFast() Kopiert Daten per Bit-Block-Transfer aus einem Speicherbereich in einen anderen. Diese Methode kann nicht auf einen Clipper-Bereich zugreifen. Siehe die Blt()Methode. object.BltFast( dx As Long, dy As Long, ddS As DirectDrawSurface7, _ srcRect As RECT, trans As CONST_DDBLTFASTFLAGS) As Long object dx, dy dds srcRect trans ein gltiges DirectDrawSurface7-Objekt Koordinatenpaar auf der Ziel-Surface Quell-Surface -> von wo die Grafik kopiert werden soll Eine gltige RECT-Struktur, welche den Bereich auf der Quell-Surface beschreibt, von der die Grafikdaten kopiert werden sollen. DDBLTFAST_DESTCOLORKEY = 2 transparentes Blit unter Verwendung des Ziel-Farbschlssels DDBLTFAST_DONOTWAIT = 32 Wartet nicht, bis der Blitter fertig ist. DDBLTFAST_NOCOLORKEY = 0

414

DirectDraw-Methoden

BltFast() normales Blit ohne Farbschlssel ohne Transparenz DDBLTFAST_SRCCOLORKEY = 1 transparentes Blit unter Verwendung des Source-Farbschlssel DDBLTFAST_WAIT = 16 Wartet bis der Blitter fertig ist.

DirectDrawSurface7.BltFx
BltFx() Kopiert Daten per Bit-Block-Transfer aus einem Speicherbereich in einen anderen. Dabei knnen erweiterte Effekte genutzt werden. object.BltFx( destRect As RECT, ddS As DirectDrawSurface7, _ srcRect As RECT, flags As CONST_DDBLTFLAGS, _ BltFx As DDBLTFX) As Long object destRect ddS srcRect flags BltFx ein gltiges DirectDrawSurface7-Objekt Eine RECT-Struktur, in welche die Daten kopiert werden soll. Eine Surface, welche als Quelle fr den Blitvorgang dient. eine RECT-Struktur auf der Quellsurface CONST_DDBLTFLAGS DDBLTFX Typen-Array, welches den Effekt beschreibt, der beim Kopieren der Daten bercksichtigt werden soll.

DirectDrawSurface7.BltToDC
BltToDC() Kopiert Daten per Bit-Block-Transfer aus einem Speicherbereich in einen anderen. Die Ziel-Surface wird durch den hdc-Parameter identifiziert. object.BltToDC( hdc As LONG, srcRect As RECT, destRect As RECT) object hdc srcRect destRect ein gltiges DirectDrawSurface7-Objekt Handle eines Device eine RECT-Struktur auf der Quellsurface eine RECT-Struktur auf der Zielsurface

Anhang A Methoden

415

DirectDrawSurface7.ChangeUniquenessValue
ChangeUniquenessValue() Manuelle Aktualisierung der Surface-Werte object.ChangeUniquenessValue() object ein gltiges DirectDrawSurface7-Objekt

DirectDraw aktualisiert die Surface-Werte automatisch immer dann, wenn sich der Inhalt ndert.

DirectDrawSurface7.DeleteAttachedSurface
DeleteAttachedSurface() Trennt zwei miteinander verbundene Surfaces. object.DeleteAttachedSurface(ddS As DirectDrawSurface7) object ddS ein gltiges DirectDrawSurface7-Objekt Surface, welche von der aktuellen Surface getrennt werden soll.

DirectDrawSurface7.DrawBox
DrawBox() Zeichnet ein Rechteck auf eine Surface. object.DrawBox(x1 As Long, y1 As Long, x2 As Long, y2 As Long) object x1, y1 x2, y2 ein gltiges DirectDrawSurface7-Objekt Legt die linke obere Ecke des Rechtecks fest. Legt die rechte untere Ecke des Rechtecks fest.

DirectDrawSurface7.DrawCircle
DrawCircle() Zeichnet einen Kreis auf eine Surface. object.DrawCircle(x1 As Long, y1 As Long, r As Long) object x1, y1 r ein gltiges DirectDrawSurface7-Objekt Legt den Mittelpunkt des Kreises fest. Bestimmt den Radius des Kreises in Pixel.

416

DirectDraw-Methoden

DirectDrawSurface7.DrawEllipse
DrawEllipse() Zeichnet ein Oval auf eine Surface. Die Parameter x1,y1 sowie x2,y2 legen ein Rechteck fest, dieses wird zu einem Oval umgeformt. object.DrawEllipse(x1 As Long, y1 As Long, x2 As Long, y2 As Long) object x1, y1 x2, y2 ein gltiges DirectDrawSurface7-Objekt Legt die linke obere Ecke fest. Legt die rechte untere Ecke fest.

DirectDrawSurface7.DrawLine
DrawLine() Zeichnet ein Linie auf eine Surface. object.DrawLine(x1 As Long, y1 As Long, x2 As Long, y2 As Long) object x1, y1 x2, y2 ein gltiges DirectDrawSurface7-Objekt Legt ein Koordinatenpaar fest, ab wo die Linie gezeichnet werden soll. Legt ein Koordinatenpaar fest, bis wohin die Linie gezeichnet werden soll.

DirectDrawSurface7.DrawRoundedBox
DrawRoundedBox() Zeichnet ein Rechteck mit abgerundeten Ecken auf eine Surface. object.DrawLine(x1 As Long, y1 As Long, x2 As Long, y2 As Long, _ rw As Long, rh As Long) object x1, y1 x2, y2 rw rh ein gltiges DirectDrawSurface7-Objekt Legt die linke obere Ecke fest. Legt die rechte untere Ecke fest. Bestimmt die horizontale Gre der Rundung. Bestimmt die vertikale Gre der Rundung.

DirectDrawSurface7.DrawText
DrawText() Zeichnet einen String auf eine Surface. object.DrawLine(x As Long, y As Long, text As Long, b As Long,)

Anhang A Methoden

417

DrawText() object x, y text b ein gltiges DirectDrawSurface7-Objekt Bestimmt ein Koordinatenpaar, an dem der Text gezeichnet werden soll. Der Text der gezeichnet werden soll. Sie knnen eine Variable vom Typ Sring bergeben oder direkt einen Text in Hochkommata angeben. True Der Text wird an der aktuellen Cursorposition gezeichnet. Die Parameter x,y werden ignoriert. False Der Text wird an dem Koordinatenpaar gezeichnet, welches durch die Parameter x,y beschrieben wurde.

DirectDrawSurface7.Flip
Flip() Wechselt den Backbufferspeicher zum Frontbufferspeicher. object.Flip( ddS As DirectDrawSurface7, flags As CONST_DDFLIPFLAGS) object dds ein gltiges DirectDrawSurface7-Objekt Dieser stellt die Verbindung zu einer beliebigen Suface aus der FlippingKette her. Die Defaulteinstellung ist Nothing. In diesem Fall wrde DirectDraw in der Reihenfolge der einzelnen Kettenglieder die Surfaces flippen. Ist dieser Wert nicht Nothing, so flippt DirectDraw zu der angegeben Surface. Eine Konstante aus der CONST_DDFLIPFLAGS-Konstantenliste

flags

DirectDrawSurface7.GetAttachedSurface
GetAttachedSurface() Liest die Surface-Eigenschaften aus. object.GetAttachedSurface( caps As DDSCAPS2) As object caps ein gltiges DirectDrawSurface7-Objekt Eine Variable vom Typ DDSCAPS2, welche als Empfnger der Surfaceeigenschaften dient. DirectDrawSurface7

418

DirectDraw-Methoden

DirectDrawSurface7.GetAttachedSurfaceEnum
GetAttachedSurfaceEnum() Erstellt eine Liste von allen Surfaces, welche mit der aktuellen Surface verbunden sind. object.GetAttachedSurfaceEnum() As DirectDrawEnumSurfaces object ein gltiges DirectDrawSurface7-Objekt Dim SurfaceEnum as DirectDrawEnumSurfaces Set SurfaceEnum = object.GetAttachedSurfacesEnum()

DirectDrawSurface7.GetBltStatus
GetBltStatus() Ermittelt den aktuellen Blitter-Status. object.GetBltStatus(flags As CONST_DDGBSFLAGS) As Long object flags ein gltiges DirectDrawSurface7-Objekt eine Konstante aus der CONST_DDGBSFLAGS-Liste

DirectDrawSurface7.GetCaps
GetCaps() Ermittelt die Leistungsfhigkeit einer Surface. object.GetCaps(caps As DDSCAPS2) object caps ein gltiges DirectDrawSurface7-Objekt DDSCAPS2 Typen-Array, welches die Informationen der Surface aufnimmt.

DirectDrawSurface7.GetClipper
GetClipper() Ermittelt den DirectDrawClipper, welcher mit der Surface verbunden ist. object.GetClipper() As DirectDrawClipper object ein gltiges DirectDrawSurface7-Objekt

Dim Clipper as DirectDrawClipper Set Clipper = object.GetClipper()

Anhang A Methoden

419

DirectDrawSurface7.GetColorKey
GetColorKey() Ermittelt den Farbschlssel, welcher mit der Surface verbunden ist. DirectDrawSurface7.SetColorKey() object.GetColorKey(flags As Long, val As DDCOLORKEY) object flags ein gltiges DirectDrawSurface7-Objekt Beschreibt, welcher Farbschlssel ermittelt werden soll. DDCKEY_DESTBLT DDCKEY_DESTOVERLAY DDCKEY_SRCBLT DDCKEY_SRCOVERLAY Farbschlssel, welcher die Informationen aufnimmt.

val

DirectDrawSurface7.GetDC
GetDC() Erzeugt ein GDI-kompatibeles Handle fr die Surface. DirectDrawSurface7.Lock() object.GetDC() As Long object ein gltiges DirectDrawSurface7-Objekt

Diese Methode benutzt eine interne Variante der DirectDraw7.Lock()-Methode. Die Surface bleibt solange geschtzt, bis die DirectDraw7.ReleaseDC()-Methode aufgerufen wird.

DirectDrawSurface7.GetDirectDraw
GetDirectDraw() Ermittelt das DirectDraw-Objekt, welches benutzt wurde, um die Surface zu erstellen. object.GetDirectDraw() As DirectDraw7 object ein gltiges DirectDrawSurface7-Objekt

Dim DDrawObject as DirectDraw7 Set DDrawObject = object.GetDDInterface()

DirectDrawSurface7.GetDirectDrawColorControl
GetDirectDrawColorControl() Ermittelt das DirectDrawColor-Objekt, welches von der Surface benutzt wird.

420

DirectDraw-Methoden

GetDirectDrawColorControl() object.GetDirectDrawColorControl() As DirectDrawColorControl object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetDirectDrawGammaControl
GetDirectDrawGammaControl() Ermittelt das DirectDrawGammaControl-Objekt, welches von der Surface benutzt wird. object.GetDirectDrawGammaControl() As DirectDrawGammaControl object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetDrawStyle
GetDrawStyle() Ermittelt den Zeichenstil, welcher durch die DirectDraw7.SetDrawStyle()-Methode gesetzt wurde. object.GetDrawStyle() As Long object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetDrawWidth
GetDrawWidth() Ermittelt die Stiftbreite, welche durch die DirectDraw7.SetDrawWidth()-Methode gesetzt wurde. Die voreingestellte Stiftbreite ist 1. object.GetDrawWidth() As Long object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetFillColor
GetFillColor() Ermittelt die Fllfarbe, welche durch die DirectDraw7.SetFillColor()-Methode gesetzt wurde. Die voreingestellte Fllfarbe ist schwarz. object.GetFillColor() As Long object ein gltiges DirectDrawSurface7-Objekt

Anhang A Methoden

421

DirectDrawSurface7.GetFillStyle
GetFillStyle() Ermittelt das Fllmuster, welches durch die DirectDraw7.SetFillStyle()-Methode gesetzt wurde. Der voreingestellte Wert ist transparent. object.GetFillStyle() As Long object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetFlipStatus
GetFlipStatus() Ermittelt den aktuellen Flippstatus. object.GetFlipStatus(flags As CONST_DDGFSFLAGS) As Long object flags ein gltiges DirectDrawSurface7-Objekt DDGFS_CANFLIP DDGFS_ISFLIPDONE

DirectDrawSurface7.GetFontBackColor
GetFontBackColor() Ermittelt die Hintergrundfarbe des Zeichensatz. DirectDrawSurface7.SetFontBackColor() object.GetFontBackColor() As Long object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetFontTransparency
GetFontTransparency() Ermittelt, ob der Hintergrund des Zeichensatzes transparent ist. Die Transparenz wurde durch die directDrawSurface7.SetFontTransparency()-Methode zugeordnet. object.GetFontTransparency() As Boolean object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetForeColor
GetForeColor() Ermittelt die Vordergrundfarbe des Zeichensatzes. object.GetForeColor() As Long

422

DirectDraw-Methoden

GetForeColor() object ein gltiges DirectDrawSurface7-Objekt

DirectDrawSurface7.GetLockedArray
GetLockedArray() Ermittelt einen Zeiger auf Surfacepixel, welche durch die DirectDrawSurface7.Lock() Methode geschtzt wurden. object.GetLockedArray( array() As Byte) object array() ein gltiges DirectDrawSurface7-Objekt Feld von geschtzten Pixeln in Byte

Diese Methode darf nur zwischen den DirectDrawSurface7.Lock()- und DirectDrawSurface7.Unlock()-Methoden aufgerufen werden. Stellen Sie sicher, dass Sie nicht in ungeschtzte Speicherbereiche schreiben.

DirectDrawSurface7.GetLockedPixel
GetLockedPixel() Ermittelt ein Pixel, welches mit der DirectDrawSurface7.SetLockedPixel()-Methode gesetzt wurde. object.GetLockedPixel( x As Long, y As Long) As Long object x, y ein gltiges DirectDrawSurface7-Objekt Koordinaten des geschtzten Pixels

DirectDrawSurface7.GetLOD
GetLOD() Ermittelt den Detailevel einer MipMap-Surface. DirectDrawSurface7.SetLOD() object.GetLOD() As Long object ein gltiges DirectDrawSurface7-Objekt Diese Methode kann nur fr Managed-Texturen (DDSCAPS_TEXTUREMANAGE) aufgerufen werden. Gehen wir von dem Beispiel aus, dass eine Mipmap-Surface erstellt wurde. Die grte Textur-Surface hat die Dimensionen von 256x256. Sie erhalten von der GetLOD()-Methode den Index 2 zurck. Dieser besagt, dass nur Texturen mit einer maximalen Gre von 64x64 im lokalen Videospeicher abgelegt werden.

Anhang A Methoden

423

DirectDrawSurface7.GetOverlayPosition
GetOverlayPosition() Ermittelt die Bildschirmkoordinaten einer existierenden Overlay-Surface. object.GetOverlayPosition(x As Long, y As Long) object x, y ein gltiges DirectDrawSurface7-Objekt Koordinaten der Surface auf dem Bildschirm

DirectDrawSurface7.GetOverlayZOrdersEnum
GetOverlayZOrdersEnum() Erstellt eine Liste aller Overlay-Surfaces entweder in der Reihenfolge front-to-back oder back-to-front. object.(flags As CONST_DDENUMOVERLAYZFLAGS) _ As DirectDrawEnumSurfaces object flags ein gltiges DirectDrawSurface-Objekt DDENUMOVERLAYZ_BACKTOFRONT DDENUMOVERLAYZ_FRONTTOBACK

DirectDrawSurface7.GetPalette
GetPalette() Ermittelt das DirectDrawPalette-Objekt, welches mit der Surface verbunden ist. DirectDrawSurface7.SetPalette() object.GetPalette() As DirectDrawPalette object ein gltiges DirectDrawSurface-Objekt Dim DDPalette as DirectDrawPalette Set DDPalette = object.GetPalette()

DirectDrawSurface7.GetPixelFormat
GetPixelFormat() Ermittelt das Pixelformat. object.GetPixelFormat(pf As DDPIXELFORMAT) object pf ein gltiges DirectDrawSurface-Objekt Wird mit detaillierten Informationen ber das Pixelformat gefllt.

424

DirectDraw-Methoden

DirectDrawSurface7.GetPriority
GetPriority() Ermittelt die Texturemanaged-Stufe einer Textursurface. object.GetPriority() As Long object ein gltiges DirectDrawSurface-Objekt

DirectDrawSurface7.GetSurfaceDesc
GetSurfaceDesc() Liest die Surface-Beschreibungen aus. object.GetSurfaceDesc(surface As DDSURFACEDESC2) object surface ein gltiges DirectDrawSurface7-Objekt Eine Variable vom Typ DDSURFACEDESC2, welche als Empfnger der Surfacebeschreibungen dient.

DirectDrawSurface7.IsLost
IsLost() Ermittelt, ob der Surfacespeicher freigegeben wurde. object.IsLost() As Long object ein gltiges DirectDrawSurface-Objekt

DirectDrawSurface7.Lock
Lock() Erstellt einen Zeiger auf den Surfacespeicher. Gleichzeitig wird der Speicherbereich geschtzt. object.Lock(r As RECT, desc As DDSURFACEDESC2, _ flags As CONST_DDLOCKFLAGS, hnd As Long) object r desc flags hnd ein gltiges DirectDrawSurface7-Objekt Eine RECT-Struktur, welche den Speicherbereich beschreibt. Wird eine leere RECT-Struktur bergeben, so wird die gesamte Surface geschtzt. Eine Variable vom Typ DDSURFACEDESC2, welche mit den relevanten Details der Surface gefllt wird. Eine Konstante aus der CONST_DDLOCKFLAGS-Liste. Sie beschreibt, in welcher Art der Speicherbereich gesperrt werden soll. Wird zurzeit nicht genutzt. Muss auf 0 gesetzt werden.

Anhang A Methoden

425

DirectDrawSurface7.ReleaseDC
ReleaseDC() Gibt das Handle einer Surface frei. object.ReleaseDC(hdc As Long) object hdc ein gltiges DirectDrawSurface-Objekt Handle des Gertes

DirectDrawSurface7.SetClipper
SetClipper() Setzt das Clipper-Objekt. object.SetClipper(val As DirectDrawClipper) object val ein gltiges DirectDrawSurface-Objekt DirectDrawClipper-Objekt

DirectDrawSurface7.SetColorKey
SetColorKey() Setzt den Farbschlssel. object.SetColorKey( flags As CONST_DDCKEYFLAGS, _ val As DDCOLORKEY) object flags val ein gltiges DirectDrawSurface-Objekt eine Variable aus der CONST_DDCKEYFLAGS-Liste Farbschlssel

DirectDrawSurface7.SetDrawStyle
SetDrawStyle() Setzt den Zeichenstil . object.SetDrawStyle(drawStyle As Long) object ein gltiges DirectDrawSurface7-Objekt

426

DirectDraw-Methoden

SetDrawStyle() drawStyle 0 1 2 3 4 5 6 voll (solid), massiv gestrichelt gepunktet Strich und Punkt wechseln sich ab erst ein Strich, dann zwei Punkte durchsichtig gefllt (bei einem Rechteck wird nicht nur der Rahmen gezeichnet, sondern das Rechteck wird gefllt. Gleiches gilt bei einem Kreis, Oval oder abgerundeten Rechteck.

DirectDrawSurface7.SetDrawWidth
SetDrawWidth() Setzt die Strichbreite fr Zeichenmethoden. object.SetDrawWidth(drawWidth As Long) object drawWidth ein gltiges DirectDrawSurface7-Objekt Strichbreite in Pixeln. Der voreingestellte Wert ist 1. Der erlaubte Wertebereiche liegt zwischen 1 und 32,767.

DirectDrawSurface7.SetFillColor
SetFillColor() Setzt die Fllfarbe fr Zeichenmethoden. object.SetFillColor(color As Long) object color ein gltiges DirectDrawSurface7-Objekt Farbe. Der voreingestellte Wert ist Schwarz (&H00000000)

DirectDrawSurface7.SetFillStyle
SetFillStyle() Setzt das Fllmuster fr Zeichenmethoden. object.SetFillStyle(fillStyle As Long) object ein gltiges DirectDrawSurface7-Objekt

Anhang A Methoden

427

SetFillStyle() fillStyle 0 1 2 3 4 5 6 7 voll (solid), massiv durchsichtig horizontale Linien vertikale Linien diagonal aufwrts diagonal abwrts horizontale und vertikale Linien diagonale horizontale und diagonale vertikale Linien

DirectDrawSurface7.SetFont
SetFont() Setzt einen neuen Zeichensatz fr die DrawText()-Methode. object.SetFont(font As IFont) object font ein gltiges DirectDrawSurface7-Objekt Zeichensatz

DirectDrawSurface7.SetFontBackColor
SetFontBackColor() Setzt eine Hintergrundfarbe fr einen Zeichensatz. object.SetFontBackColor(color As Long) object color ein gltiges DirectDrawSurface7-Objekt Farbe

DirectDrawSurface7.SetFontTransparency
SetFontTransparency() Legt fest, ob der aktuelle Zeichensatz transparent sein soll. object.SetFontTransparency(b As Boolean) object b ein gltiges DirectDrawSurface7-Objekt True transparent False nicht transparent

428

DirectDraw-Methoden

DirectDrawSurface7.SetForeColor
SetForeColor() Setzt die Zeichenfarbe, welche von den Zeichenmethoden verwendet wird. object.SetForeColor(color As Long) object color ein gltiges DirectDrawSurface7-Objekt Farbe

DirectDrawSurface7.SetLockedPixel
SetLockedPixel() Setzt ein einzelnes Pixel auf die spezifizierte Farbe. object.SetLockedPixel( x As Long, y As Long, col As Long) object x, y col ein gltiges DirectDrawSurface7-Objekt Koordinaten des Pixel Farbe

DirectDrawSurface7.SetLOD
SetLOD() Setzt die Detailstufe einer Managed-Mipmap-Surface. object.SetLOD(lod As Long) object lod ein gltiges DirectDrawSurface7-Objekt Detailstufe

Diese Methode kann nur fr Managed-Texturen (DDSCAPS_TEXTUREMANAGE) aufgerufen werden. Gehen wir von dem Beispiel aus, dass eine Mipmap-Surface erstellt wurde. Die grte Surface hat die Dimensionen von 256x256. Sie setzen mit der SetLOD()-Methode den Index 2. Dieser besagt, dass nur Texturen mit einer maximalen Gre von 64x64 im lokalen Videospeicher abgelegt werden.

DirectDrawSurface7.SetOverlayPosition
SetOverlayPosition() Setzt die Bildschirmkoordinaten fr eine Overlay-Surface. object.SetOverlayPosition(x As Long, y As Long) object x, y ein gltiges DirectDrawSurface7-Objekt Koordinaten auf dem Bildschirm in Pixeln

Anhang A Methoden

429

DirectDrawSurface7.SetPalette
SetPalette() Verbindet oder entfernt eine Palette-Objekt von einer Surface. Die Surface wird ohne Wartezeit oder Refreshzeit die neue Palette nutzen. DirectDrawSurface7.GetPalette, DirectDraw7.CreatePalette object.SetPalette(ddp As DirectDrawPalette) object ddp ein gltiges DirectDrawSurface7-Objekt Eine Palette, welche gesetzt werden soll.

DirectDrawSurface7.Unlock
Unlock() Hebt die Lock()-Methode wieder auf. Sie signalisiert DirectDraw, dass die Surfacemanipulationen abgeschlossen sind. object.Unlock(r As RECT) object r ein gltiges DirectDrawSurface7-Objekt Eine RECT-Struktur, welche den Speicherbereich beschreibt. Dieser Parameter kann nur dann leer (Nothing) sein, wenn zuvor mit der Lock()-Methode die gesamte Surface geschtzt wurde.

DirectDrawSurface7.UpdateOverlay
UpdateOverlay() Repositioniert oder modifiziert die sichtbaren Attribute einer Overlay-Surface. Der Overlay-Surface muss das DDSCAPS_OVERLAY-Flag zugewiesen sein. object.UpdateOverlay(RECT As RECT, ddS As DirectDrawSurface7, _ rectD As RECT, flags As CONST_DDOVERFLAGS) object rect ddS rectD flags ein gltiges DirectDrawSurface7-Objekt Definiert eine RECT-Struktur auf der Surface, welche von der OverlaySurface genutzt wird. Surface, welche von der Overlay-Surface berlagert wird. Definiert eine RECT-Struktur auf der Overlay-Surface, welche aktualisiert werden soll. Eine Konstante aus der CONST_DDOVERFLAGS-Liste

430

Direct3D-Methoden

DirectDrawSurface7.UpdateOverlayFx
UpdateOverlayFx() Repositioniert oder modifiziert die sichtbaren Attribute einer Overlay-Surface mit speziellen Effekten. Der Overlay-Surface muss das DDSCAPS_OVERLAY-Flag zugewiesen sein. object.UpdateOverlayFx(RECT As RECT, ddS As DirectDrawSurface7, _ rectD As RECT, flags As CONST_DDOVERFLAGS object rect ddS rectD flags ddoverfx ein gltiges DirectDrawSurface-Objekt Definiert eine RECT-Struktur auf der Surface, welche von der OverlaySurface genutzt wird. Surface, welche von der Overlay-Surface berlagert wird. Definiert eine RECT-Struktur auf der Overlay Surface, welche aktualisiert werden soll. eine Konstante aus der CONST_DDOVERFLAGS-Liste Definiert den anzuwendenden Effekt. DDOVERLAYFX Typen-Array.

DirectDrawSurface7.UpdateOverlayZOrder
UpdateOverlayZOrder() Setzt die Tiefenreihenfolge der Overlay-Surface. object.UpdateOverlayZOrder( flags As CONST_DDOVERZFLAGS, _ ddS As DirectDrawSurface7) object flags ein gltiges DirectDrawSurface-Objekt

DDOVERZ_INSERTINBACKOF DDOVERZ_INSERTINFRONTOF DDOVERZ_MOVEBACKWARD DDOVERZ_MOVEFORWARD DDOVERZ_SENDTOBACK DDOVERZ_SENDTOFRONT


Definiert die Surface, deren Tiefenreihenfolge gendert werden soll.

ddS

A.3
A.3.1

Direct3D-Methoden
Direct3D7
Anwendungen verwenden die Direct3D7-Klasse, um Direct3D-Objekte zu erzeugen.

Anhang A Methoden

431

Das Direct3D7-Objekt wird mit der DirectDraw7.GetDirect3D()-Methode erzeugt. Folgende Methoden gehren zu der Direct3D7-Klasse:
Erzeugen Listen Verschiedenes CreateDevice CreateVertexbuffer GetDevicesEnum GetEnumZBufferFormats EvictManagedTextures GetDirectDraw

Direct3D7.CreateDevice
CreateDevice() Erzeugt ein Direct3D-Device, welches von der DrawPrimitive()-Methode genutzt wird. object.CreateDevice( guid As String, surf As DirectDrawSurface7) _ As Direct3DDevice7 Object Guid Surf ein gltiges Direct3D7-Objekt IID_Direct3DHALDevice IID_Direct3DRGBDevice Eine Surface, welche als Renderziel verwendet wird. Die Surface muss mit dem DDSCAPS_3DDEVICE-Flag indiziert sein.

Direct3D7.CreateVertexbuffer
CreateVertexBuffer() Erstellt ein Vertexbuffer-Objekt. object.CreateVertexbuffer( desc As D3DVERTEXBUFFERDESC, _ flags As CONST_D3DDPFLAGS) As Direct3DVertexbuffer7 object desc flags ein gltiges Direct3D7-Objekt D3DVERTEXBUFFERDESC Typen-Array, welches das Format und die Anzahl der Vertexe des Vertexbuffers enthlt. eine Konstante aus der CONST_D3DDPFLAGS-Liste

Direct3D7.EvictManagedTextures
EvictManagedTextures() Lscht alle Managed-Texturen aus dem lokalen Videospeicher.

432

Direct3D-Methoden

EvictManagedTextures() object.EvictManagedTextures() object ein gltiges Direct3D7-Objekt

Entfernt alle Texturen aus dem lokalen Videospeicher, welche mit dem DDSCAPS2_ TEXTUREMANAGE- oder DDSCAPS2_D3DTEXTUREMANAGE-Flag erstellt wurden.

Direct3D7.GetDevicesEnum
GetDevicesEnum() Erzeugt ein Direct3DenumDevices-Objekt. object.GetDevicesEnum() As Direct3DenumDevices object ein gltiges Direct3D7-Objekt

Direct3D7.GetDirectDraw
GetDirctDraw() Ermittelt das DirectDraw-Objekt, welches mit dem Direct3D-Objekt verbunden ist. object.GetDirectDraw() As DirectDraw7 object ein gltiges Direct3D7-Objekt

Direct3D7.GetEnumZBufferFormats
GetEnumZBufferFormats() Erzeugt ein Direct3DenumPixelFormats-Objekt. object.GetEnumZBufferFormats( guid As String) As Direct3DenumPixelFormats object guid ein gltiges Direct3D7-Objekt Eine global eindeutige Identifizierung fr das Device, fr welches das Objekt erstellt werden soll.

A.3.2

Direct3DDevice7
Die Direct3DDevice7-Klasse ermglicht das Rendern einer Szene. Das Direct3DDevice7 wird mit der Direct3D.CreateDevice()-Methode erstellt. Folgende Methoden gehren zu der Direct3DDevice7-Klasse:

Anhang A Methoden

433

Information

GetCaps GetDirect3D GetInfo GetDeviceGuid ApplyStateBlock BeginStateBlock CaptureStateBlock CreateStateBlock DeleteStateBlock EndStateBlock GetClipStatus GetRenderState GetRenderStateSingle GetRenderTarget GetTransform SetClipStatus SetRenderState SetRenderStateSingle SetRenderTarget SetTransform GetMaterial GetLight GetLightEnable LightEnable SetMaterial SetLight ComputeSphereVisibility MultiplyTransform DrawIndexedPrimitive DrawIndexedPrimitiveVB DrawPrimitive DrawPrimitiveVB BeginScene EndScene GetTexture GetTextureFormatsEnum GetTextureStageState GetTextureStageStateSingle Load PreLoad SetTexture SetTextureStageState SetTextureStageStateSingle ValidateDevice

Gertezustand

Lighting and Materials

Verschiedenes Rendering

Szenen Texturen

434

Direct3D-Methoden

ClipPlanes Viewport

GetClipPlane SetClipPlane Clear GetViewport SetViewport

Direct3DDevice7.ApplyStateBlock
ApplyStateBlock() Setzt einen existierenden Stateblock ein. Direct3DDevice7.BeginStateBlock(), Direct3DDevice7.CaptureStateBlock(), Direct3DDevice7.CreateStateBlock(), Direct3DDevice7.DeleteStateBlock(), Direct3DDevice7.EndStateBlock() object.ApplyStateBlock( blockHandle As Long) object blockHandle ein gltiges Direct3DDevice7-Objekt Handle des StateBlocks

Ein Stateblock kann nicht eingesetzt werden, solange ein anderer Stateblock aufgezeichnet wird.

Direct3DDevice7.BeginScene
BeginScene() Signalisiert den Anfang einer Szene. Direct3Ddevice7.EndScene() object.BeginScene() object ein gltiges Direct3DDevice7-Objekt

Vor einem erneuten Aufruf der Direct3Ddevice7.BeginScene()-Methode muss die Direct3Ddevice7.EndScene()-Methode aufgerufen worden sein.

Direct3DDevice7.BeginStateBlock
BeginStateBlock() Signalisiert, dass die Aufzeichnung eines Stateblocks beginnt. Direct3DDevice7.BeginStateBlock(), Direct3DDevice7.CaptureStateBlock(), Direct3DDevice7.CreateStateBlock(), Direct3DDevice7.DeleteStateBlock(), Direct3DDevice7.EndStateBlock() object.BeginStateBlock() object ein gltiges Direct3DDevice7-Objekt

Anhang A Methoden

435

BeginStateBlock() Folgende Methoden knnen in einem StateBlock aufgezeichnet werden: Direct3DDevice7.LightEnable() Direct3DDevice7.SetClipPlane() Direct3DDevice7.SetLight() Direct3DDevice7.SetMaterial() Direct3DDevice7.SetRenderState() Direct3DDevice7.SetTexture() Direct3DDevice7.SetTextureStageState() Direct3DDevice7.SetTransform() Direct3DDevice7.SetViewport()

Direct3DDevice7.CaptureStateBlock
CaptureStateBlock() Aktualisiert die Werte eines Stateblock auf die fr ein Device zurzeit gltigen Werte. Direct3DDevice7.BeginStateBlock(), Direct3DDevice7.CaptureStateBlock(), Direct3DDevice7.CreateStateBlock(), Direct3DDevice7.DeleteStateBlock(), Direct3DDevice7.EndStateBlock() object.CaptureStateBlock( blockHandle As Long) object blockHandle ein gltiges Direct3DDevice7-Objekt Handle fr einen Stateblock

Direct3DDevice7.CreateStateBlock
CreateStateBlock() Erzeugt einen Stateblock mit den aktuellen Werten eines Devices. Die bergebenen Werte knnen durch den d3dsbType Parameter eingeschrnkt werden. Direct3DDevice7.BeginStateBlock(), Direct3DDevice7.CaptureStateBlock(), Direct3DDevice7.CreateStateBlock(), Direct3DDevice7.DeleteStateBlock(), Direct3DDevice7.EndStateBlock() object.CreateStateBlock( d3dsbType As CONST_D3DSTATEBLOCKTYPE, _ blockHandle As Long) object d3sbType blockHandle ein gltiges Direct3DDevice7-Objekt eine Konstate aus der CONST_D3DSTATEBLOCKTYPE-Liste Handle fr einen Stateblock

436

Direct3D-Methoden

Direct3DDevice7.Clear
Clear() Lscht den Viewport oder eine Gruppe von RECT-Strukturen in dem Viewport mit einer definierten Farbe oder lscht den Z-Buffer oder lscht den Stencilbuffer object.Clear( count As Long, recs() As D3DRECT, _ flags As CONST_D3DCLEARFLAGS, color As Long, z As Single, _ stencil As Long) object count recs() flags ein gltiges Direct3DDevice7-Objekt Anzahl der RECT Strukturen in dem recs()-Parameter ein Array mit RECT-Strukturen, welche rechteckige Bereiche auf dem Viewport beschreiben. D3DCLEAR_TARGET D3DCLEAR_STENCIL D3DCLEAR_ZBUFFER Farbe Neuer Tiefenwerte, welcher im Z-Buffer gespeichert wird. Der Wertebereich liegt zwischen 0.0 und 1.0. Der Wert 0.0 ist die krzeste Entfernung zum Betrachter. Neuer Stencilbuffer-Wert, welcher in jedem Element des Stencilbuffer eingetragen wird. Der Wertebereich liegt zwischen 0.0 und 2n-1.

color z

stencil

Die Methode fhrt zu einem Fehler, wenn beim flags-Parameter die Eintrge D3DCLEAR_STENCIL oder D3DCLEAR_ZBUFFER verwendet werden, ohne dass diese Flags beim Renderziel gesetzt wurden.

Direct3DDevice7.ComputeSphereVisibility
ComputeSphereVisibility() berprft die Sichtbarkeit eines Bereiches auf dem Viewport. object.ComputeSphereVisibility( center As D3DVECTOR, _ radius As Single) As Long object center radius ein gltiges Direct3DDevice7-Objekt Mittelpunkt Radius

Sie knnen diese Methode einsetzen, um zu prfen, ob Objekte oder Vertexe im sichtbaren Bereich des Betrachters liegen. Ist dies nicht der Fall, so brauchen die Objekte oder Vertexe nicht gerendert zu werden. Eine hilfreiche Methode, um eine Performancesteigerung zu erlangen.

Anhang A Methoden

437

Direct3DDevice7.DeleteStateBlock
DeleteStateBlock() Lscht einen zuvor aufgezeichneten Stateblock. Direct3DDevice7.BeginStateBlock(), Direct3DDevice7.CaptureStateBlock(), Direct3DDevice7.CreateStateBlock(), Direct3DDevice7.DeleteStateBlock(), Direct3DDevice7.EndStateBlock() object.DeleteStateBlock(blockHandle As Long) object blockHandle ein gltiges Direct3DDevice7-Objekt Handle eines Stateblocks

Direct3DDevice7.DrawIndexedPrimitive
DrawIndexedPrimitive() Rendert ein Array von Vertexen. Direct3DDevice7.DrawPrimitive(), Direct3DDevice7.DrawPrimitiveVB(), Direct3DDevice7.DrawIndexedPrimitiveVB() object.DrawIndexedPrimitive( d3Dpt As CONST_D3DPRIMITIVETYPE, _ d3dfvf As CONST_D3DFVFFLAGS, vertices As Any, vertexCount As _ Long, indices() As Integer, IndicesCount As Long, _ flags As CONST_D3DDPFLAGS) object d3Dpt d3dfvf ein gltiges Direct3DDevice7-Objekt eine Konstante aus der CONST_D3DPRIMITIVETYPE-Liste Eine Kombination aus: D3DFVF_DIFFUSE D3DFVF_LVERTEX D3DFVF_NORMAL D3DFVF_SPECULAR D3DFVF_TLVERTEX D3DFVF_VERTEX D3DFVF_XYZ D3DFVF_XYZRHW D3DFVF_XYZB1 bis D3DFVF_XYZB5 D3DFVF_TEX0 bis D3DFVF_TEX8 das erste Element aus einem Vertex-Array Anzahl der Vertexe, die gerendert werden sollen. Ein Array, welches zum Indizieren der Vertexe verwendet wird. Anzahl der Indexe im indices()-Parameter Eine Konstante aus der CONST_D3DDPFLAGS-Liste

vertices vertexCount indices() IndicesCount flags

438

Direct3D-Methoden

Direct3DDevice7.DrawIndexedPrimitiveVB
DrawIndexedPrimitiveVB() Rendert ein Array von Vertexen mit einem Vertexbuffer. Direct3DDevice7.DrawPrimitive(), Direct3DDevice7.DrawPrimitiveVB(), Direct3DDevice7.DrawIndexedPrimitiveVB() object.DrawIndexedPrimitiveVB( d3Dpt As CONST_D3DPRIMITIVETYPE, _ vertexBuffer As Direct3DVertexbuffer7, StartVertex As Long, _ NumVertices As Long, indexArray() As Integer, indexcount _ As Long, flags As CONST_D3DDPFLAGS) object d3Dpt vertexBuffer StartVertex NumVertices indexArray() indexcount flags ein gltiges Direct3DDevice7 Objekt eine Konstante aus der CONST_D3DPRIMITIVETYPE-Liste. ein Direct3DVertexBuffer7-Objekt Index des ersten Vertex im Vertexbuffer Anzahl der Vertexe, die gerendert werden sollen. Ein Array, welches zum Indizieren der Vertexe verwendet wird. Anzahl der Indexe in dem indexArray()-Parameter Eine Konstante aus der CONST_D3DDPFLAGS-Liste

Direct3DDevice7.DrawPrimitive
DrawPrimitive() Rendert ein Array von Vertexen. Direct3DDevice7.DrawPrimitiveVB(), Direct3DDevice7.DrawIndexedPrimitive(), Direct3DDevice7.DrawIndexedPrimitiveVB() object.DrawPrimitive( d3Dpt As CONST_D3DPRIMITIVETYPE, _ d3dfvf As CONST_D3DFVFFLAGS, vertices As Any, vertexCount As _ Long, flags As CONST_D3DDPFLAGS) object d3Dpt ein gltiges Direct3DDevice7-Objekt eine Konstante aus der CONST_D3DPRIMITIVETYPE-Liste

Anhang A Methoden

439

DrawPrimitive() d3dfvf Eine Kombination aus: D3DFVF_DIFFUSE D3DFVF_LVERTEX D3DFVF_NORMAL D3DFVF_SPECULAR D3DFVF_TLVERTEX D3DFVF_VERTEX D3DFVF_XYZ D3DFVF_XYZRHW D3DFVF_XYZB1 bis D3DFVF_XYZB5 D3DFVF_TEX0 bis D3DFVF_TEX8 das erste Element aus dem Array mit Vertexen Anzahl der Vertexe, die gerendert werden sollen. eine Konstante aus der CONST_D3DDPFLAGS-Liste

vertices vertexCount flags

Direct3DDevice7.DrawPrimitiveVB
DrawPrimitiveVB() Rendert ein Array von Vertexen in einem Vertexbuffer Direct3DDevice7.DrawPrimitiveVB(), Direct3DDevice7.DrawIndexedPrimitive(), Direct3DDevice7.DrawIndexedPrimitiveVB() object.DrawPrimitiveVB( d3dpt As CONST_D3DPRIMITIVETYPE, _ vertexBuffer As Direct3DVertexbuffer7, startVertex As Long, _ numVertices As Long, flags As CONST_D3DDPFLAGS) object d3dpt vertexBuffer startVertex numVertices flags ein gltiges Direct3DDevice7-Objekt eine Konstante aus der CONST_D3DPRIMITIVETYPE Liste ein Direct3DVertexBuffer7-Objekt Index des ersten Vertex, das gerendert werden soll. Anzahl der Vertexe, die gerendert werden sollen. eine Konstante aus der CONST_D3DDPFLAGS-Liste

440

Direct3D-Methoden

Direct3DDevice7.EndScene
EndScene() Signalisiert das Ende einer Szene. Direct3Ddevice7.BeginScene() object.EndScene() object ein gltiges Direct3DDevice7-Objekt

Direct3DDevice7.EndStateBlock
EndStateBlock() Signalisiert das Ender einer Aufzeichnung fr einen Stateblock. Direct3DDevice7.BeginStateBlock(), Direct3DDevice7.CaptureStateBlock(), Direct3DDevice7.CreateStateBlock(), Direct3DDevice7.DeleteStateBlock(), Direct3DDevice7.EndStateBlock() object.EndStateBlock( blockHandle As Long) object blockHandle ein gltiges Direct3DDevice7-Objekt Handle des Stateblocks

Direct3DDevice7.GetCaps
GetCaps() Ermittelt die Fhigkeiten eines Direct3D-Devices. object.GetCaps( desc As D3DDEVICEDESC7) object desc ein gltiges Direct3DDevice7-Objekt D3DDEVICEDESC7 Typen-Array, welches die Informationen aufnimmt.

Direct3DDevice7.GetClipPlane
GetClipPlane() Ermittelt die Koeffizienten der Benutzer-definierten Clippingplane. Direct3DDevice7.SetClipPlane() object.GetClipPlane( Index As Long, a As Single, b As Single, c As Single, _ d As Single) object ein gltiges Direct3DDevice7-Objekt

Anhang A Methoden

441

GetClipPlane() Index a, b, c, d Index der Clippingplane nehmen die ermittelten Werte auf.

Direct3DDevice7.GetClipStatus
GetClipStatus() Ermittelt den aktuellen Clipstatus. Direct3DDevice7.SetClipsStatus() object.GetClipStatus(clipStatus As D3DCLIPSTATUS) object clipStatus ein gltiges Direct3DDevice7-Objekt D3DCLIPSTATUS Typen-Array, welches den Clipstatus aufnimmt.

Direct3DDevice7.GetDeviceGuid
GetDeviceGuid() Ermittelt die Guid fr das Device. object.GetDeviceGuid() As String object ein gltiges Direct3DDevice7-Objekt

Direct3DDevice7.GetDirect3D
GetDirect3D() Ermittelt das Direct3D Objekt fr das Device. object.GetDirect3D() As Direct3D7 object ein gltiges Direct3DDevice7-Objekt

Direct3DDevice7.GetInfo
GetInfo() Ermittelt Informationen ber das Renderdevice. D3DDEVINFO_TEXTUREMANAGER() object.GetInfo( lDevInfoID As CONST_D3DDEVINFOID, _ DevInfoType As Any, lSize As Long) object ein gltiges Direct3DDevice7-Objekt

442

Direct3D-Methoden

GetInfo() lDevInfoID D3DDEVINFOID_D3DTEXTUREMANAGER D3DDEVINFOID_TEXTUREMANAGER D3DDEVINFOID_TEXTURING Eine Variable, welche die ermittelten Informationen aufnimmt. Gre des DevInfoType-Parameters. Diese kann mit der VisualBasic-Funktion Len() ermittelt werden.

DevInfoType lSize

Direct3DDevice7.GetLight
GetLight() Ermittelt die Eigenschaften eines Lichtobjektes. Direct3DDevice7.SetLight(), Direct3DDevice7.GetLightEnable(),

Direct3D, Device7.LightEnable()
object.GetLight( LightIndex As Long, Light As D3DLIGHT7) object LightIndex Light ein gltiges Direct3DDevice7-Objekt Index der Lichtquelle D3DLIGHT Typen-Array, welches die ermittelten Werte aufnimmt.

Direct3DDevice7.GetLightEnable
GetLightEnable() Ermittelt, ob eine Lichtquelle verfgbar ist. Direct3DDevice7.SetLight(), Direct3DDevice7.GetLightEnable(), Direct3DDevice7.LightEnable() object.GetLightEnable( LightIndex As Long) As Boolean object LightIndex ein gltiges Direct3DDevice7-Objekt Index der Lichtquelle

Direct3DDevice7.GetMaterial
GetMaterial() Ermittelt die aktuellen Materialeigenschaften fr das Device. Direct3Ddevice7.SetMaterial() object.GetMaterial( Material As D3DMATERIAL7)

Anhang A Methoden

443

GetMaterial() object Material ein gltiges Direct3DDevice7-Objekt D3DMATERIAL7-Typen-Array, welches die Informationen aufnimmt.

Direct3DDevice7.GetRenderState
GetRenderState() Ermittelt den aktuellen Renderzustand des Devices. Direct3DDevice7.SetRenderState() object.GetRenderState( state As CONST_D3DRENDERSTATETYPE) As Long object state ein gltiges Direct3DDevice7-Objekt eine Konstante aus der CONST_D3DRENDERSTATETYPE-Liste

Direct3DDevice7.GetRenderStateSingle
GetRenderStateSingle() Ermittelt den aktuellen Renderzustand des Devices. Direct3DDevice7.SetRenderState(), Direct3DDevice7.SetRenderStateSingle() object.GetRenderStateSingle( _ state As CONST_D3DRENDERSTATESINGLE) As Single object state ein gltiges Direct3DDevice7-Objekt D3DRENDERSTATE_FOGDENSITY D3DRENDERSTATE_ FOGEND D3DRENDERSTATE_FOGSTART

Direct3DDevice7.GetRenderTarget
GetRenderTarget() Ermittelt die DirectDraw7-Surface, welche als Renderziel dient. Direct3DDevice7.SetRenderTarget() object.GetRenderTarget() As DirectDrawSurface7 object ein gltiges Direct3DDevice7-Objekt

444

Direct3D-Methoden

Direct3DDevice7.GetTexture
GetTexture() Ermittelt die Textur, welche mit einer gegebenen Texturstufe verbunden ist, fr das Device. Direct3DDevice7.SetTexture(), Direct3DDevice7.GetTextureStageState(), Direct3DDevice7.SetTextureStageState() object.GetTexture(stage As Long) As DirectDrawSurface7 object stage ein gltiges Direct3DDevice7-Objekt Texturestufe zwischen 0 und 7.

Direct3DDevice7.GetTextureFormatsEnum
GetTextureFormatsEnum() Ermittelt das Pixelformat fr das Device. object.GetTextureFormatsEnum() As Direct3DEnumPixelFormats object ein gltiges Direct3DDevice7-Objekt

Direct3DDevice7.GetTextureStageState
GetTextureStageState() Ermittelt den Zustand fr die aktuelle Textur. Direct3DDevice7.SetTextureStageState(), Direct3DDevice7.GetTexture(), Direct3DDevice7.SetTexture() object.GetTextureStageState( stage As Long, _ state As CONST_D3DTEXTURESTAGESTATETYPE) As Long object stage state ein gltiges Direct3DDevice7-Objekt Texturstufe, fr welche der Zustand ermittelt werden soll. eine Konstante aus der CONST_D3DTEXTURESTAGESTATE TYPE- Liste

Direct3DDevice7.GetTextureStageStateSingle
GetTextureStageSingle() Ermittelt den Zustand fr die aktuelle Textur. Direct3DDevice7.SetTextureStageState(), Direct3DDevice7.GetTexture(), Direct3DDevice7.SetTexture() object.GetTextureStageStateSingle( stage As Long, _ state As CONST_D3DTEXTURESTAGESINGLE) As Single

Anhang A Methoden

445

GetTextureStageSingle() object stage state ein gltiges Direct3DDevice7-Objekt Texturstufe, fr welche der Zustand ermittelt werden soll. eine Konstante aus der CONST_D3DTEXTURESTAGESTATE TYPE-Liste

Direct3DDevice7.GetTransform
GetTransform() Ermittelt die Matrixbeschreibung einer Transformationsart. Direct3DDevice7.SetTransform() object.GetTransform( _ transformType As CONST_D3DTRANSFORMSTATETYPE, _ matrix As D3DMATRIX) object transformType ein gltiges Direct3DDevice7-Objekt D3DTRANSFORMSTATE_WORLD D3DTRANSFORMSTATE_WORLD1 D3DTRANSFORMSTATE_WORLD2 D3DTRANSFORMSTATE_WORLD3 D3DTRANSFORMSTATE_VIEW D3DTRANSFORMSTATE_PROJECTION D3DTRANSFORMSTATE_TEXTURE0 D3DTRANSFORMSTATE_TEXTURE1 D3DTRANSFORMSTATE_TEXTURE2 D3DTRANSFORMSTATE_TEXTURE3 D3DTRANSFORMSTATE_TEXTURE4 D3DTRANSFORMSTATE_TEXTURE5 D3DTRANSFORMSTATE_TEXTURE6 D3DTRANSFORMSTATE_TEXTURE7 D3DMATRIX-Typen-Array, welches die Beschreibung aufnimmt.

matrix

Direct3DDevice7.GetViewport
GetViewport() Ermittelt die Viewport-Parameter fr den Viewport, der aktuell fr das Device gesetzt ist. Direct3DDevice7.SetViewport() object.GetViewport( Viewport As D3DVIEWPORT7) object Viewport ein gltiges Direct3DDevice7-Objekt D3DVIEWPORT7-Typen-Array, welches die Informationen aufnimmt.

446

Direct3D-Methoden

Direct3DDevice7.LightEnable
LightEnable() Aktiviert oder deaktiviert eine Lichtquelle. Direct3DDevice7.GetLight(), Direct3DDevice7.GetLightEnable(), Direct3DDevice7.SetLight() object.LightEnable( LightIndex As Long, bEnable As Boolean) object LightIndex bEnable ein gltiges Direct3DDevice7-Objekt Index der Lichtquelle True oder False

Wird eine Lichtquelle eingeschaltet, ohne dass zuvor die Parameter bestimmt wurden, werden die voreingestellten Werte verwendet. dltType = D3DLIGHT_DIRECTIONAL dcvDiffuse (R:1, G:1, B:1, A:0) dcvSpecular (R:0, G:0, B:0, A:0) dcvAmbient (R:0, G:0, B:0, A:0) dvPosition (0, 0, 0) dvDirection (0, 0, 1) dvRange = 0 dvFalloff = 0 dvAttenuation0 = 0 dvAttenuation1 = 0 dvAttenuation2 = 0 dvTheta = 0 dvPhi = 0

Direct3DDevice7.Load
Load() Ldt eine RECT-Struktur der Quelltexture in einen definierten Punkt der Zielsurface. object.Load( DestTex As DirectDrawSurface7, xDest As Long, _ yDest As Long, SrcTex As DirectDrawSurface7, rcSrcRect As RECT, _ flags As Long) object DestTex xDest, yDest SrcTex rcSrcRect ein gltiges Direct3DDevice7-Objekt Zielsurface Koordinaten auf der Zielsurface Quellsurface RECT-Struktur auf der Quellsurface

Anhang A Methoden

447

Load() flags 0 bentigt eine gemanagte Textur DDSCAPS2_CUBEMAP_ALLFACES DDSCAPS2_CUBEMAP_NEGATIVEX DSCAPS2_CUBEMAP_NEGATIVEY DSCAPS2_CUBEMAP_NEGATIVEZ DDSCAPS2_CUBEMAP_POSITIVEX DSCAPS2_CUBEMAP_POSITIVEY DSCAPS2_CUBEMAP_POSITIVEZ

Direct3DDevice7.MultiplyTransform
MultiplyTransform() Mulitpliziert die World-, View- oder Projektionsmatrix mit dem Matrix-Parameter. Direct3DDevice7.DrawPrimitive(), Direct3DDevice7.SetTransform() object.MultiplyTransform( _ dstTransformStateType As CONST_D3DTRANSFORMSTATETYPE, _ matrix As D3DMATRIX) object destTransformStateType matrix ein gltiges Direct3DDevice7-Objekt eine Konstante aus der CONST_ D3DTRANSFORMSTATETYPE-Liste Matrix, mit der multipliziert wird.

Direct3DDevice7.PreLoad
PreLoad() Weist Direct3D an, eine verwaltete Textur in den Videospeicher zu laden. object.PreLoad(Texture As DirectDrawSurface7) object Texture ein gltiges Direct3DDevice7-Objekt Verweis auf die Surface, welche in den Speicher geladen werden soll.

Direct3DDevice7.SetClipPlane
SetClipPlane() Setzt die Koeffizienten fr eine benutzerdefinierte Clippingplane. object.SetClipPlane( Index As Long, a As Single, b As Single, c As Single, _ d As Single)

448

Direct3D-Methoden

SetClipPlane() object Index a, b, c, d ein gltiges Direct3DDevice7-Objekt Index der Clippingplane Werte, die gesetzt werden.

Direct3DDevice7.SetClipStatus
SetClipStatus() Setzt den aktuellen Clipstatus. Direct3DDevice7.GetClipStatus() object.SetClipStatus(clipStatus As D3DCLIPSTATUS) object clipStatus ein gltiges Direct3DDevice7-Objekt D3DCLIPSTATUS-Typen-Array, welches die Informationen fr den Clipstatus enthlt.

Direct3DDevice7.SetLight
SetLight() Setzt die Eigenschaften einer Lichtquelle. Direct3DDevice7.GetLight(), Direct3DDevice7.GetLightEnable(), Direct3DDevice7.LightEnable() object.SetLight(LightIndex As Long, Light As D3DLIGHT7) object LightIndex Light ein gltiges Direct3DDevice7-Objekt Index der Lichtquelle D3DLIGHT7 Typen-Array, welches die Eigenschaften der Lichtquelle speichert.

Direct3DDevice7.SetMaterial
SetMaterial() Setzt die Materialeigenschaften des Devices. Direct3DDevice7.GetMaterial() object.SetMaterial(mat As D3DMATERIAL7) object mat ein gltiges Direct3DDevice7-Objekt D3DMATERIAL7-Typen-Array, welches die Materialeigenschaften enthlt.

Anhang A Methoden

449

Direct3DDevice7.SetRenderState
SetRenderState() Setzt den Renderzustand des Devices. Direct3Ddevice7.GetRenderState(), Direct3DDevice7.SetTransform() object.SetRenderState(state As CONST_D3DRENDERSTATETYPE, _ renderstate As Long) object state renderstate ein gltiges Direct3DDevice7-Objekt eine Konstante der CONST_D3DRENDERSTATETYPE-Liste eine Konstante der CONST_D3DSHADEMODE-Liste

Direct3DDevice7.SetRenderStateSingle
SetRenderStateSingle() Setzt den Renderzustand des Devices. Direct3DDevice7.GetRenderState(), Direct3DDevice7.GetRenderStateSingle(), Direct3DDevice7.SetTransform() object.SetRenderStateSingle( state As CONST_D3DRENDERSTATESINGLE, _ renderstate As Single) object state renderstate ein gltiges Direct3DDevice7-Objekt eine Konstante der CONST_D3DRENDERSTATESINGLE-Liste eine Konstante der CONST_D3DSHADEMODE-Liste

Direct3DDevice7.SetRenderTarget
SetRenderTarget() Setzt ein neue Renderziel. Direct3DDevice7.GetRenderTarget() object.SetRenderTarget(surface As DirectDrawSurface7) object surface ein gltiges Direct3DDevice7-Objekt Surface, welche das neue Renderziel sein soll.

450

Direct3D-Methoden

Direct3DDevice7.SetTexture
SetTexture() Setzt die Textur fr eine Texturstufe fr das Device. Direct3DDevice7.GetTexture(), Direct3DDevice7.GetTextureStageState(), Direct3DDevice7.SetTextureStageState() object.SetTexture( stage As Long, texture As DirectDrawSurface7) object stage texture ein gltiges Direct3DDevice7-Objekt Texturstufe Textursurface

Wenn die Texture nicht lnger bentigt wird, dann setzen Sie die Texture auf Nothing. Tun Sie dies nicht, so verlieren Sie den Speicher der Surface, wenn Sie das Programm schlieen.

Direct3DDevice7.SetTextureStageState
SetTextureStageState() Setzt den Texturzustand der zugewiesenen Textur. Direct3DDevice7.GetTextureStageState(), Direct3DDevice7.GetTexture(), Direct3DDevice7.SetTexture() object.SetTextureStageState( stage As Long, _ state As CONST_D3DTEXTURESTAGESTATETYPE, value As Long) object stage state value ein gltiges Direct3DDevice7-Objekt Texturstufe eine Konstante aus der CONST_D3DTEXTURESTAGESTATE TYPE-Liste Wert

Direct3DDevice7.SetTextureStageStateSingle
SetTextureStageStateSingle() Setzt den Texturzustand der zugewiesenen Textur. Direct3DDevice7.GetTextureStageStateSingle(), Direct3DDevice7.GetTextureStageState(), Direct3DDevice7.GetTexture(), Direct3DDevice7.SetTexture() object.SetTextureStageStateSingle( stage As Long, _ state As CONST_D3DTEXTURESTAGESINGLE, value As Single) object stage ein gltiges Direct3DDevice7-Objekt Texturstufe

Anhang A Methoden

451

SetTextureStageStateSingle() state value eine Konstante aus der CONST_D3DTEXTURESTAGESINGLE-Liste Wert

Direct3DDevice7.SetTransform
SetTransform() Setzt einen einzelnen Transformationszustand. Direct3DDevice7.GetTransform(), Direct3DDevice7.SetRenderState() object.SetTransform( _ transformType As CONST_D3DTRANSFORMSTATETYPE, _ matrix As D3DMATRIX) object transformType matrix ein gltiges Direct3DDevice7-Objekt eine Konstante aus der CONST_D3DTRANSFORMSTATETYPEListe Matrix, welche die aktuelle Transformation modifiziert.

Direct3DDevice7.SetViewport
SetViewport() Setzt den Viewport fr das Device. Direct3DDevice7.GetViewport() object.SetViewport( viewport As D3DVIEWPORT7) object viewport ein gltiges Direct3DDevice7-Objekt D3DVIEWPORT7-Typen-Array, welches die Informationen ber den Viewport enthlt.

Direct3DDevice7.ValidateDevice
ValidateDevice() Prft, ob das Device in der Lage ist, die aktuellen Textureblending-Parameter in einem Durchgang zu rendern. Direct3DDevice7.GetTextureStageState(), Direct3DDevice7.SetTextureStageState() object.ValidateDevice() As Long object ein gltiges Direct3DDevice7-Objekt

452

Direct3D-Methoden

A.3.3

Direct3DEnumDevices
Die Direct3DEnumDevices-Klasse ermittelt Informationen ber die installierten 3D-Gerte. Das Direct3DEnumDevices-Objekt wird mit der Direct3D7.GetDevicesEnum()Methode erzeugt. Folgende Methoden gehren zu der Direct3DEnumDevices-Klasse:
Device count Device information GetCount GetDescription GetGuid GetDesc GetName

Direct3DEnumDevices.GetCount
GetCount() Ermittelt die Anzahl der Direct3D-Devices, welche auf dem aktuellen System installiert sind. object.GetCount() As Long object ein gltiges Direct3DEnumDevices-Objekt

Direct3DEnumDevices.GetDesc
GetDesc() Ermittelt die Fhigkeiten eines gewnschten Direct3D-Devices. object.GetDesc(index As Long, hwDesc As D3DDEVICEDESC7) object index hwDesc ein gltiges Direct3DEnumDevices-Objekt Identifiziert das installierte Direct3D-Device. D3DDEVICEDESC7-Typen-Array, welches die ermittelten Werte aufnimmt.

Direct3DEnumDevices.GetDescription
GetDescription() Ermittelt eine allgemein verstndliche Beschreibung des Direct3D-Devices. object.GetDescription(index As Long) As String object ein gltiges Direct3DenumDevices-Objekt

Anhang A Methoden

453

GetDescription() index Identifiziert das installierte Direct3D-Device.

Direct3DEnumDevices.GetGuid
GetGuid() Ermittelt den Guid eines Direct3D-Devices. object.GetGuid(index As Long) As String object index ein gltiges Direct3DenumDevices-Objekt Identifiziert das installierte Direct3D-Device.

Die mglichen Rckgabewerte sind: IID_IDirect3DHALDevice IID_IDirect3DtnLHalDevice IID_IDirect3DRGBDevice

Direct3DEnumDevices.GetName
GetName() Ermittelt einen allgemein verstndlichen Namen des Direct3D-Devices. object.GetName(index As Long) As String object index ein gltiges Direct3DenumDevices-Objekt Identifiziert das installierte Direct3D-Device.

A.3.4

Direct3DEnumPixelFormats
Die Direct3DEnumPixelFormats-Klasse liefert Informationen ber die Pixelformate, welche von dem 3D-Gert untersttzt werden. Das Direct3DEnumPixelFormats-Objekt wird mit den Direct3DDevice7. GetTextureFormatsEnum()- und Direct3D7.GetEnumZBufferFormats()-Methoden erzeugt. Folgende Methoden gehren zu der Direct3DEnumPixelFormats-Klasse: Information GetCount GetItem

454

Direct3D-Methoden

Direct3DEnumPixelFormats.GetCount
GetCount() Ermittelt die Anzahl der untersttzten Pixelformate des Direct3D-Devices. object.GetCount() As Long object ein gltiges Direct3DEnumPixelFormats-Objekt

Direct3DenumPixelFormats.GetItem
GetItem() Ermittelt die Beschreibung eines Pixelformats. object.GetCount() As Long Object Desc ein gltiges Direct3DEnumPixelFormats-Objekt DDPIXELFORMAT Typen-Array, welches die ermittelte Beschreibung aufnimmt.

A.3.5

Direct3DVertexBuffer7
Die Direct3DVertexbuffer7-Klasse wird verwendet, um eine Sammlung von Vertexen zu manipulieren. Die Vertexe werden von der Direct3DDevice7.DrawPrimitiveVB()- und Direct3DDevice7.DrawIndexedPrimitiveVB()-Methode verwendet. Folgende Methoden gehren zu der Direct3DVertexbuffer7-Klasse:
Information Vertex data GetVertexBufferDesc GetVertices Lock Optimize ProcessVertices SetVertices Unlock

Direct3DVertexBuffer7.GetVertexbufferDesc
GetVertexbufferDesc() Ermittelt die Beschreibung eines Vertexbuffers. object.GetVertexbufferDesc(desc As D3DVERTEXBUFFERDESC) Object ein gltiges Direct3DVertexBuffer7-Objekt

Anhang A Methoden

455

GetVertexbufferDesc() Desc D3DVERTEXBUFFERDESC Typen-Array, welches die ermittelte Beschreibung aufnimmt.

Direct3DVertexBuffer7.GetVertices
GetVertices() Ermittelt die Vertexe in einem Vertexbuffer. object.GetVertices(startIndex As Long, count As Long, verts As Any) Object startIndex Count Verts ein gltiges Direct3DVertexBuffer7-Objekt das erste Element in einem Vertexbuffer Anzahl der zu ermittelnden Vertexe. Erstes Element eines Arrays, welches mit den Informationen gefllt werden soll.

Direct3DVertexBuffer7.Lock
Lock() Schtzt einen Vertex-Buffer. Direct3DVertexbuffer7.Unlock() object.Lock(flags As CONST_DDLOCKFLAGS) object flags ein gltiges Direct3DVertexBuffer7-Objekt DDLOCK_NOSYSLOCK DDLOCK_READONLY DDLOCK_WAIT DDLOCK_WRITEONLY DDLOCK_DISCARDCONTENTS DDLOCK_NOOVERWRITE

Solange der Vertexbuffer geschtzt ist, knnen Sie die Vertexe in dem Buffer manipulieren. Hierzu verwenden Sie die Methoden: Direct3DVertexBuffer7.GetVertices und Direct3DVertexBuffer7.SetVertices(). Aus einen geschtzten Vertexbuffer knnen Sie nicht rendern.

Direct3DVertexBuffer7.Optimize
Optimize() Konvertiert einen nichtoptimierten Vertexbuffer in einen optimierten Vertexbuffer. object.Optimize(dev As Direct3DDevice7) object ein gltiges Direct3DVertexBuffer7-Objekt

456

Direct3D-Methoden

Optimize() dev ein Direct3DDevice7-Objekt fr welches der Vertexbuffer optimiert werden soll.

Direct3DVertexBuffer7.ProcessVertices
ProcessVertices() Wandelt untransformierte Vertexe in einen transformierten oder optimierten Vertexbuffer. object.ProcessVertices( vertexOp As CONST_D3DVOPFLAGS, _ destIndex As Long, count As Long, srcBuffer As Direct3DVertexbuffer7, _ srcIndex As Long, dev As Direct3DDevice7, _ flags As CONST_D3DPROCESSVERTICESFLAGS) object vertexOp ein gltiges Direct3DVertexBuffer7-Objekt D3DVOP_CLIP D3DVOP_EXTENTS D3DVOP_LIGHT D3DVOP_TRANSFORM Index im Ziel-Vertexbuffer, in dem die Vertexe nach der Transformation untergebracht werden. Anzahl der Vertexe im Quell-Vertexbuffer ein Direct3DVertexBuffer7-Objekt Index des ersten Vertex im Quell-Vertexbuffer Ein Direct3DDevice7-Objekt, welches die transformierten Vertexe verwendet. D3DPV_DEFAULT D3DPV_DONOTCOPYDATA

destIndex count srcBuffer srcIndex dev flags

Direct3DVertexBuffer7.SetVertices
SetVertices() Setzt die Vertexe in einen geschtzen Vertexbuffer. Direct3DVertexbuffer7.GetVertices(), Direct3DVertexbuffer7.Lock() object.SetVertices(startIndex As Long, count As Long, verts As Any) object startIndex ein gltiges Direct3DVertexBuffer7-Objekt Index des ersten Vertex, welches gesetzt werden soll.

Anhang A Methoden

457

SetVertices() count verts Anzahl der Vertexe, die gesetzt werden sollen. erstes Element der Vertexdaten

Direct3DVertexBuffer7.Unlock
Unlock() Hebt den Schutz des Vertexbuffers auf. object.Unlock() object ein gltiges Direct3DVertexBuffer7-Objekt

A.4
A.4.1

DirectSound-Methoden
DirectSound
Programme benutzen die Methoden der DirectSound-Klasse zum Erstellen von DirectSound-Objekten und zum Einstellen der Umgebungskonfiguration. Das DirectSound-Objekt wird mit der DirectX7.DirectSoundCreate()-Methode erzeugt. Die Methoden der DirectSound-Klasse knnen in folgende Gruppen unterteilt werden:
Initialisierung Erstellen von Bufferobjekten SetCooperativeLevel CreateSoundBuffer CreateSoundBufferFromFile CreateSoundBufferFromResource DuplicateSoundBuffer GetCaps GetSpeakerConfig SetSpeakerConfig

Device-Beschreibungen Lautsprecherkonfiguration

458

DirectSound-Methoden

DirectSound.CreateSoundBuffer
CreateSoundBuffer() Erstellt einen DirectSoundBuffer. DirectSound.DuplicateSoundBuffer(), DirectSound.SetCooperativeLevel(), DirectSoundBuffer(), DirectSoundBuffer.GetFormat(), DirectSoundBuffer. GetVolume(), DirectSoundBuffer.Play(), DirectSoundBuffer.SetFormat(), DirectSoundBuffer.SetFrequency() object.CreateSoundBuffer(bufferDesc As DSBUFFERDESC, _ format As WAVEFORMATEX) As DirectSoundBuffer Object BufferDesc format ein gltiges DirectSound-Objekt DSBUFFERDESC Typ beinhaltet die Beschreibung zum Erstellen eines Soundbuffers. WAVEFORMATEX Typ beschreibt das Wellenformat der Audiodaten.

DirectSound.CreateSoundBufferFromFile
CreateSoundBufferFromFile() Erstellt einen DirectSoundBuffer aus einer Wavedatei. object.CreateSoundBufferFromFile(filename As String, _ bufferDesc As DSBUFFERDESC, _ format As WAVEFORMATEX) As DirectSoundBuffer object filename bufferDesc format ein gltiges DirectSound-Objekt Dateiname eines Wavefiles DSBUFFERDESC Typ beinhaltet die Beschreibung zum Erstellen eines Soundbuffers. WAVEFORMATEX Typ beschreibt das Wellenformat der Audiodaten.

DirectSound.CreateSoundBufferFromResource
CreateSoundBufferFromResource() Erstellt einen DirectSoundBuffer von einer Ressource. object.CreateSoundBufferFromResource( dll As String, _ resourceName As String, bufferDesc As DSBUFFERDESC, _ format As WAVEFORMATEX) As DirectSoundBuffer object dll ein gltiges DirectSound-Objekt Name der dll, die die Ressource beinhaltet.

Anhang A Methoden

459

CreateSoundBufferFromResource() resourceName bufferDesc format Name der Ressource DSBUFFERDESC Typ beinhaltet die Beschreibung zum Erstellen eines Soundbuffers. WAVEFORMATEX Typ beschreibt das Wellenformat der Audiodaten.

DirectSound.DuplicateSoundBuffer
DuplicateSoundBuffer() Erstellt ein neues DirectSoundBuffer-Objekt, das den gleichen Speicherbereich wie das Originalobjekt benutzt. object.DuplicateSoundBuffer( original As DirectSoundBuffer) _ As DirectSoundBuffer object original ein gltiges DirectSound-Objekt DirectSoundBuffer, von dem eine Kopie angefertigt werden soll.

Das Original sowie die Kopie knnen autonom gesteuert werden. nderungen an den Sound-Daten wirken sich auf beide Bufferobjekte aus.

DirectSound.GetCaps
GetCaps() Gibt die Fhigkeiten der Soundhardware zurck. object.GetCaps(caps As DSCAPS) object caps ein gltiges DirectSound-Objekt ein DSCAPS Typ, der die Beschreibung aufnimmt.

Der DSCAPS-Typ beinhaltet alle Fhigkeiten der Soundhardware, die zur Verfgung stehen, die Anzahl der Sound-Mischkanle sowie die Gre des Soundkartenspeichers.

DirectSound.GetSpeakerConfig
GetSpeakerConfig() Gibt die Lautsprecherkonfiguration zurck. object.GetSpeakerConfig() As CONST_DSSPEAKERFLAGS object ein gltiges DirectSound-Objekt

460

DirectSound-Methoden

DirectSound.SetCooperativeLevel
SetCooperativeLevel() Setzt den CooperativeLevel der Applikation auf die Soundkarte. object.SetCooperativeLevel(hwnd As Long, _ level As CONST_DSSCLFLAGS) object hwnd level ein gltiges DirectSound-Objekt Windows-Handle der Applikation Priorittsstufe CONST_DSSCLFLAGS

DirectSound.SetSpeakerConfig
SetSpeakerConfig() Stellt die Lautsprecherkonfiguration des DirectSound-Objekts ein. object.SetSpeakerConfig( speakerConfig As CONST_DSSPEAKERFLAGS) object speakerConfig ein gltiges DirectSound-Objekt Lautsprecherkonfiguration aus CONST_DSSPEAKERFLAGS

A.4.2

DirectSound3DBuffer
Die Methoden der DirectSound3DBuffer-Klasse empfngt und setzt die Parameter zum Positionieren und Ausrichten eines Sounds im 3D-Raum. Das DirectSound3DBuffer-Objekt wird mit der DirectSoundBuffer.Query Interface()-Methode erzeugt. Die Methoden der DirectSound3DBuffer-Klasse werden in folgende Gruppen unterteilt.
Parametervernderung Entfernung GetAllParameters SetAllParameters GetMaxDistance GetMinDistance SetMaxDistance SetMinDistance GetDirectSound3Dlistener GetDirectSoundBuffer GetMode SetMode

Objekte Operatonsmodus

Anhang A Methoden

461

Position Klangprojektion und Abstrahlung

GetPosition SetPosition GetConeAngles GetConeOrientation GetConeOutsideVolume SetConeAngles SetConeOrientation SetConeOutsideVolume GetVelocity SetVelocity

Geschwindigkeit

DirectSound3DBuffer.GetAllParameters
GetAllParameters() Empfngt Informationen ber die 3D-Charakterristik eines Soundbuffers zu einer bestimmten Zeit. object.GetAllParameters(buffer As DS3DBUFFER) object buffer ein gltiges DirectSound3DBuffer-Objekt DS3DBUFFER-Typ

DirectSound3DBuffer.GetConeAngles
GetConeAngles() Empfngt die Winkel des inneren und ueren Klangtrichters. DirectSound3DBuffer.SetConeAngles() object.GetConeAngles(inCone As Long, outCone As Long) object inCone outCone ein gltiges DirectSound3Dbuffer-Objekt Winkel des inneren Klangtrichters Winkel des ueren Klangtrichters

DirectSound3DBuffer.GetConeOrientation
GetConeOrientation() Empfngt die Ausrichtung des Klangtrichters. DirectSound3DBuffer.SetConeOrientation() object.GetConeOrientation(orientation As D3DVECTOR) object orientation ein gltiges DirectSound3DBuffer-Objekt Dieser Vektor stellt die Mitte des Klangtrichters dar.

462

DirectSound-Methoden

DirectSound3DBuffer.GetConeOutsideVolume
GetConeOutsideVolume() Empfngt die Lautstrke des ueren Klangtrichters. DirectSound3DBuffer.SetConeOutsideVolume() object.GetConeOutsideVolume() As Long object ein gltiges DirectSound3DBuffer-Objekt

Die Lautstrke wird als Abschwchung angegeben. Ein grerer Wert bedeutet grere Abschwchung und somit eine geringere Lautstrke. Gltige Bereiche liegen zwischen DSBVOLUME_MAX (keine Abschwchung) und DSBVOLUME_MIN (grte Abschwchung). Der Standardwert ist DS3D_DEFAULTCONEOUTSIDEVOLUME (keine Abschwchung).

DirectSound3DBuffer.GetDirectSound3DListener
GetDirectSound3DListener() Gibt ein DirectSound3DListener-Objekt zurck. object.GetDirectSound3DListener() As DirectSound3DListener object ein gltiges DirectSound3DBuffer-Objekt

DirectSound3DBuffer.GetDirectSoundBuffer
GetDirectSoundBuffer() Gibt ein DirectSoundBuffer Objekt zurck. object.GetDirectSoundBuffer() As DirectSoundBuffer object ein gltiges DirectSound3DBuffer-Objekt

DirectSound3DBuffer.GetMaxDistance
GetMaxDistance() Empfngt die maximale Entfernung eines 3D-Buffer-Objekts. DirectSound3DBuffer.GetMinDistance(), DirectSound3DBuffer.SetMaxDistance(), DirectSound3DBuffer.SetMinDistance() object.GetMaxDistance() As Single object ein gltiges DirectSound3DBuffer-Objekt

Anhang A Methoden

463

DirectSound3DBuffer.GetMinDistance
GetMinDistance() Empfngt die minimale Entfernung eines 3D-Buffer-Objekts. DirectSound3DBuffer.GetMaxDistance(), DirectSound3DBuffer.SetMaxDistance(), DirectSound3DBuffer.SetMinDistance() object.GetMinDistance() As Single object ein gltiges DirectSound3DBuffer-Objekt

DirectSound3DBuffer.GetMode
GetMode() Empfngt den Operationsmode des aktuellen 3D-Soundprozesses. DirectSound3DBuffer.SetMode object.GetMode() As CONST_DS3DMODEFLAGS object ein gltiges DirectSound3DBuffer-Objekt

Rckgabewerte vom Typ CONST_DS3DMODEFLAGS

DirectSound3DBuffer.GetPosition
GetPosition() Empfngt die Position eines 3DSoundBuffers im 3D-Raum. DirectSound3DBuffer.SetPosition() object.GetPosition(position As D3DVECTOR) object position ein gltiges DirectSound3DBuffer-Objekt 3D-Position (xyz) in Metern

DirectSound3DBuffer.GetVelocity
GetVelocity() Empfngt die Geschwindigkeit, mit der sich ein 3D-Buffer im Raum bewegt. DirectSound3DBuffer.SetVelocity() object.GetVelocity(velocity As D3DVECTOR) object velocity ein gltiges DirectSound3DBuffer-Objekt Wert in Meter pro Sekunde

Velocity wird zum Errechnen des Dopplereffektes bentigt.

464

DirectSound-Methoden

DirectSound3DBuffer.SetAllParameters
SetAllParameters() Setzt Informationen ber die 3D-Charakteristik eines Soundbuffers zu einer bestimmten Zeit. DirectSound3DBuffer.GetAllParameters() object.SetAllParameters(buffer As DS3DBUFFER, _ applyFlag As CONST_DS3DAPPLYFLAGS) object buffer applyFlag ein gltiges DirectSound3DBuffer-Objekt ein gltiges DirectSoundBuffer-Objekt Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DBuffer.SetConeAngles
SetConeAngles() Setzt die Winkel des inneren und ueren Klangtrichters. DirectSound3DBuffer.GetConeAngles() object.SetConeAngles(inCone As Long, outCone As Long, _ applyFlag As CONST_DS3DAPPLYFLAGS) object inCone outCone applyFlag ein gltiges DirectSound3DBuffer-Objekt Winkel des inneren Klangtrichters Winkel des ueren Klangtrichters Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DBuffer.SetConeOrientation
SetConeOrientation() Setzt die Ausrichtung des Klangtrichters. DirectSound3DBuffer.GetConeOrientation() object.SetConeOrientation( x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DBuffer-Objekt Koordinaten der neuen Ausrichtung Flag vom Typ CONST_DS3DAPPLYFLAGS

Anhang A Methoden

465

DirectSound3DBuffer.SetConeOutsideVolume
SetConeOutsideVolume() Setzt die Lautstrke des ueren Klangtrichters. DirectSound3DBuffer.GetConeOutsideVolume() object.SetConeOutsideVolume(coneOutsideVolume As Long, _ applyFlag As CONST_DS3DAPPLYFLAGS) object coneOutsideVolume ein gltiges DirectSound3DBuffer-Objekt erlaubte Werte liegen im Bereich von DSBVOLUME_MAX (keine Abschwchung), DSBVOLUME_MIN (grte Abschwchung) Flag vom Typ CONST_DS3DAPPLYFLAGS

applyFlag

DirectSound3DBuffer.SetMaxDistance
SetMaxDistance() Setzt die maximale Entfernung eines 3D-Buffer Objekts. DirectSound3DBuffer.GetMinDistance(), DirectSound3DBuffer.GetMaxDistance(), DirectSound3DBuffer.SetMinDistance() object.SetMaxDistance(maxDistance As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object maxDistance applyFlag ein gltiges DirectSound3DBuffer-Objekt neuer Wert der grten Entfernung Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DBuffer.SetMinDistance
SetMinDistance() Setzt die minimale Entfernung eines 3D-Buffer Objekts. DirectSound3DBuffer.GetMinDistance(), DirectSound3DBuffer.GetMaxDistance(), DirectSound3DBuffer.SetMaxDistance() object.SetMinDistance(minDistance As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object minDistance applyFlag ein gltiges DirectSound3DBuffer-Objekt neuer Wert der kleinsten Entfernung Flag vom Typ CONST_DS3DAPPLYFLAGS

466

DirectSound-Methoden

DirectSound3DBuffer.SetMode
SetMode() Setzt den Operationsmodus des aktuellen 3D-Sound-Prozesses. DirectSound3DBuffer.GetMode() object.SetMode(mode As CONST_DS3DMODEFLAGS, _ applyFlag As CONST_DS3DAPPLYFLAGS) object mode applyFlag ein gltiges DirectSound3DBuffer-Objekt Wert vom Typ CONST_DS3DMODEFLAGS Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DBuffer.SetPosition
SetPosition() Setzt die Position eines 3D-Soundbuffers im 3D-Raum. DirectSound3DBuffer.GetPosition() object.SetPosition(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DBuffer-Objekt Koordinaten der neuen Position Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DBuffer.SetVelocity
SetVelocity() Empfngt die Geschwindigkeit, mit der sich ein 3D-Buffer im Raum bewegt. DirectSound3DBuffer.GetVelocity() object.SetVelocity(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DBuffer-Objekt Koordinaten des Richtungsvektors Flag vom Typ CONST_DS3DAPPLYFLAGS

Velocity wird zum Errechnen des Dopplereffektes bentigt.

A.4.3

DirectSound3DListener
Programme benutzen die Methoden der DirectSound3DListener-Klasse zum Empfangen und Setzen der Position und Ausrichtung des Listeners im 3D-Raum.

Anhang A Methoden

467

Das DirectSound3DListener-Objekt wird mit der DiertsSoundBuffer.GetDirectSound3DListener()-Methode erzeugt. Die Methoden der DirectSound3DListener-Klasse organisieren sich in folgenden Gruppen:
Batch parameters Verzgerung Entfernungsfaktoren Dopplereffekt Objekte Ausrichtung Position Neigung Geschwindigkeit GetAllParameters SetAllParameters CommitDeferredSettings GetDistanceFactor SetDistanceFactor GetDopplerFactor SetDopplerFactor GetDirectSoundBuffer GetOrientation SetOrientation GetPosition SetPosition GetRolloffFactor SetRolloffFactor GetVelocity SetVelocity

DirectSound3DListener.CommitDeferredSettings
CommitDeferredSettings() bergibt die zuvor eingestellten Werte unter Verwendung des Applyflags. object.CommitDeferredSettings() object ein gltiges DirectSound3DListener-Objekt

DirectSound3DListener.GetAllParameters
GetAllParameters() Empfngt alle Einstellungen des Listenerobjekts. DirectSound3DListener.SetAllParameters() object.GetAllParameters(listener As DS3DLISTENER) object listener ein gltiges DirectSound3DListener-Objekt ein gltiges DS3DLISTENER-Objekt

468

DirectSound-Methoden

DirectSound3DListener.GetDirectSoundBuffer
GetDirectSoundBuffer() Empfngt ein DirectSoundBuffer und bergibt diesen dem Listenerobjekt. object.GetDirectSoundBuffer() As DirectSoundBuffer object ein gltiges DirectSound3DListener-Objekt

DirectSound3DListener.GetDistanceFactor
GetDistanceFactor() Empfngt den aktuellen Entfernungsfaktor. DirectSound3DListener.SetDistanceFactor() object.GetDistanceFactor() As Single object ein gltiges DirectSound3DListener-Objekt

DirectSound3DListener.GetDopplerFactor
GetDopplerFactor() Empfngt den aktuellen Wert des Doppler-Effektes. DirectSound3DListener.SetDopplerFactor() object.GetDopplerFactor() As Single object ein gltiges DirectSound3DListener-Objekt

Gltige Werte liegen im Bereich DS3D_MINDOPPLERFACTOR (kein Dopplereffekt) und DS3D_MAXDOPPLERFACTOR (maximaler Dopplereffekt) die Grundeinstellung ist DS3D_DEFAULTDOPPLERFACTOR.

DirectSound3DListener.GetOrientation
GetOrientation() Empfngt die Ausrichtung des Listenerobjektes. DirectSound3DListener.SetOrientation() object.GetOrientation(orientFront As D3DVECTOR, _ orientTop As D3DVECTOR) object orientFront orientTop ein gltiges DirectSound3DListener-Objekt Vektor fr die horizontale Ausrichtung Vektor fr die vertikale Ausrichtung

Anhang A Methoden

469

DirectSound3DListener.GetPosition
GetPosition() Empfngt die Position des Listenerobjektes. DirectSound3DListener.SetPosition() object.GetPosition(position As D3DVECTOR) object position ein gltiges DirectSound3DListener-Objekt Koordinate der Position im 3D-Raum

DirectSound3DListener.GetRolloffFactor
GetRolloffFactor() Empfngt den Rolloff -Faktor des Listenerobjektes. DirectSound3DListener.SetRolloffFactor() object.GetRolloffFactor() As Single object ein gltiges DirectSound3DListener-Objekt

Gltige Werte liegen im Bereich von DS3D_MINROLLOFFFACTOR (keinRolloffEffekt) und DS3D_MAXROLLOFFFACTOR (grter Rolloff-Effekt) die Grundeinstellung betrgt DS3D_DEFAULTROLLOFFFACTOR.

DirectSound3DListener.GetVelocity
GetVelocity() Empfngt den aktuellen Velocitywert des Listenerobjektes. DirectSound3DListener.SetVelocity() object.GetVelocity() As D3DVECTOR object ein gltiges DirectSound3DListener-Objekt

Velocity wird zum Errechnen des Dopplereffektes bentigt.

DirectSound3DListener.SetAllParameters
SetAllParameters() Setzt alle Einstellungen des Listenerobjekts. DirectSound3DListener.GetAllParameters() object.SetAllParameters(listener As DS3DLISTENER, _ applyFlag As CONST_DS3DAPPLYFLAGS) object listener ein gltiges DirectSound3DListener-Objekt vom Typ DS3DLISTENER

470

DirectSound-Methoden

SetAllParameters() applyFlag Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DListener.SetDistanceFactor
SetDistanceFactor() Setzt den aktuellen Entfernungsfaktor. DirectSound3DListener.GetDistanceFactor() object.SetDistanceFactor(distanceFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object distanceFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer Distancefaktor Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DListener.SetDopplerFactor
SetDopplerFactor() Setzt den aktuellen Wert des Dopplereffektes. DirectSound3DListener.GetDopplerFactor() object.SetDopplerFactor(dopplerFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object dopplerFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer Dopplerfaktor-Wert Flag vom Typ CONST_DS3DAPPLYFLAGS

Gltige Werte liegen im Bereich DS3D_MINDOPPLERFACTOR (kein Dopplereffekt) und DS3D_MAXDOPPLERFACTOR (maximaler Dopplereffekt); die Grundeinstellung ist DS3D_DEFAULTDOPPLERFACTOR.

DirectSound3DListener.SetOrientation
SetOrientation() Setzt die Ausrichtung des Listenerobjektes. DirectSound3DListener.GetOrientation() object.SetOrientation(xFront As Single, yFront As Single, _ zFront As Single, xTop As Single, yTop As Single, zTop As _ Single, applyFlag As CONST_DS3DAPPLYFLAGS)

Anhang A Methoden

471

SetOrientation() object Front x,y,z Top x,y,z applyFlag ein gltiges DirectSound3DListener-Objekt Vektor der horizontalen Ausrichtung Vektor der vertikalen Ausrichtung Flag vom Typ CONST_DS3DAPPLYFLAGS

Der Front-Vektor zeigt in Blickrichtung des Listeners, der Top-Vektor zeigt aus dem Kopf des Listeners senkrecht nach oben. Die Grundeinstellung des Front-Vektors betrgt (xyz) 0,0,1, die des Top-Vektors 0,1,0. Der Top-Vektor muss im richtigen Verhltnis zum Front-Vektor angegeben werden. DirectSound aktualisiert erst den FrontVektor, dann den Top-Vektor.

DirectSound3DListener.SetPosition
SetPosition() Setzt die Position des Listenerobjektes. DirectSound3DListener.GetPosition() object.SetPosition(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DListener-Objekt Koordinate der neuen Position Flag vom Typ CONST_DS3DAPPLYFLAGS

DirectSound3DListener.SetRolloffFactor
SetRolloffFactor() Setzt den Rolloff Faktor des Listenerobjektes. DirectSound3DListener.GetRolloffFactor() object.SetRolloffFactor(rolloffFactor As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object rolloffFactor applyFlag ein gltiges DirectSound3DListener-Objekt neuer Rolloff-Faktor Flag vom Typ CONST_DS3DAPPLYFLAGS

Gltige Werte liegen im Bereich von DS3D_MINROLLOFFFACTOR (kein RolloffEffekt) und DS3D_MAXROLLOFFFACTOR (grter Rolloff-Effekt); die Grundeinstellung betrgt DS3D_DEFAULTROLLOFFFACTOR.

472

DirectSound-Methoden

DirectSound3DListener.SetVelocity
SetVelocity() Setzt den aktuellen Velocitywert des Listenerobjektes. DirectSound3DListener.GetVelocity() object.SetVelocity(x As Single, y As Single, z As Single, _ applyFlag As CONST_DS3DAPPLYFLAGS) object x,y,z applyFlag ein gltiges DirectSound3DListener-Objekt Neuer Vektor, der die Geschwindigkeit beschreibt. Flag vom Typ CONST_DS3DAPPLYFLAGS

Velocity wird zum Errechnen des Dopplereffektes bentigt.

A.4.4

DirectSoundBuffer
Die Methoden der DirectSoundBuffer-Klasse werden zum Erstellen von DirectSoundBuffer-Objekten bentigt. Das DirectSoundBuffer-Objekt wird mit der DirectSound.CreateSoundBuffer()Methode erzeugt. Die DirectSoundBuffer-Methoden unterteilen sich in folgende Gruppen:
Information GetCaps GetFormat GetStatus SetFormat Restore SaveToFile GetDirectSound3Dbuffer GetDirectSound3Dlistener GetCurrentPosition Play ReadBuffer SetCurrentPosition SetNotificationPositions Stop WriteBuffer

Speichermanagement Verschiedenes Erhalten von Objekten Steuerung

Anhang A Methoden

473

Soundmanagement

GetFrequency GetPan GetVolume SetFrequency SetPan SetVolume

DirectSoundBuffer.GetCaps
GetCaps() Empfngt die Fhigkeiten des DirectSoundBuffers. object.GetCaps(caps As DSBCAPS) object caps ein gltiges DirectSoundBuffer-Objekt vom Typ DSBCAPS

DirectSoundBuffer.GetCurrentPosition
GetCurrentPosition() Empfngt die aktuelle Lese- und Schreibe-Position des Cursors. DirectSoundBuffer.SetCurrentPosition() object.GetCurrentPosition(cursors As DSCURSORS) object cursors ein gltiges DirectSoundBuffer-Objekt Playcursor vom Typ DSCURSORS

DirectSoundBuffer.GetDirectSound3DBuffer
GetDirectSound3DBuffer() Gibt ein DirectSound3DBuffer-Objekt zurck. object.GetDirectSound3DBuffer() As DirectSound3DBuffer object ein gltiges DirectSoundBuffer-Objekt

DirectSoundBuffer.GetDirectSound3DListener
GetDirectSound3DListener() Gibt ein DirectSound3DListener-Objekt zurck. object.GetDirectSound3DListener() As DirectSound3DListener object ein gltiges DirectSoundBuffer-Objekt

474

DirectSound-Methoden

DirectSoundBuffer.GetFormat
GetFormat() Empngt die Formatbeschreibung der Sounddaten im Soundbuffer. DirectSoundBuffer.SetFormat() object.GetFormat(format As WAVEFORMATEX) object format ein gltiges DirectSoundBuffer-Objekt vom Typ WAVEFORMATEX

DirectSoundBuffer.GetFrequency
GetFrequency() Empfngt die Frequenz in Samples pro Sekunde. DirectSoundBuffer.SetFrequency() object.GetFrequency() As Long object ein gltiges DirectSoundBuffer-Objekt

Gltige Werte liegen im Bereich von DSBFREQUENCY_MIN und DSBFREQUENCY_MAX (100 100.000 Samples pro Sekunde)

DirectSoundBuffer.GetPan
GetPan() Empfngt einen Panwert, der die Lautstrkebalance der Lautsprecher beschreibt. DirectSoundBuffer.SetPan() object.GetPan() As Long object ein gltiges DirectSoundBuffer-Objekt

Gltige Werte liegen im Bereich von DSBPAN_LEFT (-10.000) 100db Abschwchung rechts und DSBPAN_RIGHT (+10.000) 100db Abschwchung links. DSBPAN_CENTER ( 0 ) beschreibt die normale Mittelstellung.

DirectSoundBuffer.GetStatus
GetStatus() Empfngt den aktuellen Zustand eines DirectSoundBuffers. object.GetStatus() As CONST_DSBSTATUSFLAGS object Rckgabe ein gltiges DirectSoundBuffer-Objekt vom Typ CONST_DSBSTATUSFLAGS

Anhang A Methoden

475

DirectSoundBuffer.GetVolume
GetVolume() Empfngt die aktuelle Lautstrke eines Soundbuffers. object.GetVolume() As Long object ein gltiges DirectSoundBuffer-Objekt

Gltige Werte liegen im Bereich von DSBVOLUME_MIN (keine Abschwchung 0db) und DSBVOLUME_MAX (grte Abschwchung 100db).

DirectSoundBuffer.Play
Play() Gibt den Befehl zum Abspielen eines Soundbuffers. object.Play(flags As CONST_DSBPLAYFLAGS) object flags ein gltiges DirectSoundBuffer-Objekt vom Typ CONST_DSBPLAYFLAGS

DirectSoundBuffer.ReadBuffer
ReadBuffer() Liest ein Segment aus einem Soundbuffer und speichert dieses in einer Variablen vom Typ Array. object.ReadBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSBLOCKFLAGS) object start size buffer flags ein gltiges DirectSoundBuffer-Objekt Offset in Bytes (Position, ab der gelesen werden wird) Anzahl der Bytes, die gelesen werden. Variable vom Typ Any, die die Sounddaten aufnimmt. vom Typ CONST_DSBLOCKFLAGS

DirectSoundBuffer.Restore
Restore() Stellt einen verlorenen Speicherbereich wieder her. object.Restore() object ein gltiges DirectSoundBuffer-Objekt

476

DirectSound-Methoden

DirectSoundBuffer.SaveToFile
SaveToFile() Speichert die Eintrge eines DirectSoundBuffers in eine Datei. object.SaveToFile(filename As String) object filename ein gltiges DirectSoundBuffer-Objekt Filename

DirectSoundBuffer.SetCurrentPosition
SetCurrentPosition() Setzt die Soundcursor auf die angegebene Position. object.SetCurrentPosition(newPosition As Long) object newPosition ein gltiges DirectSoundBuffer-Objekt neue Position in Bytes vom Anfang des Buffers

DirectSoundBuffer.SetFormat
SetFormat() Setzt das Format des primren Soundbuffers der Anwendung. object.SetFormat(format As WAVEFORMATEX) object format ein gltiges DirectSoundBuffer-Objekt vom Typ WAVEFORMATEX

DirectSoundBuffer.SetFrequency
SetFrequency() Setzt die Frequenz, in der Audiosamples abgespielt werden. object.SetFrequency(frequency As Long) object frequency ein gltiges DirectSoundBuffer-Objekt neue Frequenz in Hertz (Hz)

Gltige Werte liegen im Bereich von DSBFREQUENCY_MIN und DSBFREQUENCY_MAX (100 100.000 Samples pro Sekunde).

Anhang A Methoden

477

DirectSoundBuffer.SetNotificationPositions
SetNotificationPositions() Setzt die Notifications-Position in einem Soundbuffer. object.SetNotificationPositions(nElements As Long, _ psa() As DSBPOSITIONNOTIFY) object nElements psa() ein gltiges DirectSoundBuffer-Objekt Nummer vom Typ DSBPOSITIONNOTIFY Ein Array von DSBPOSITIONNOTIFY

DirectSoundBuffer.SetPan
SetPan() Setzt einen Panwert, der die Lautstrkebalance der Lautsprecher beschreibt. DirectSoundBuffer.GetPan() object.SetPan(pan As Long) object pan ein gltiges DirectSoundBuffer-Objekt neuer Panoramawert

Gltige Werte liegen im Bereich von DSBPAN_LEFT (-10.000) 100db Abschwchung rechts und DSBPAN_RIGHT (+10.000) 100db Abschwchung links. DSBPAN_CENTER ( 0 ) beschreibt die normale Mittelstellung.

DirectSoundBuffer.SetVolume
SetVolume() Setzt die aktuelle Lautstrke eines Soundbuffers. object.SetVolume(volume As Long) object volume ein gltiges DirectSoundBuffer-Objekt neuer Lautstrkewert

Gltige Werte liegen im Bereich von DSBVOLUME_MIN (keine Abschwchung 0db) und DSBVOLUME_MAX (grte Abschwchung 100db)

DirectSoundBuffer.Stop
Stop() Gibt den Befehl zum Anhalten eines Soundbuffers. object.Stop()

478

DirectSound-Methoden

Stop() object ein gltiges DirectSoundBuffer-Objekt

DirectSoundBuffer.WriteBuffer
WriteBuffer() Schreibt ein Segment in einen Soundbuffer. object.WriteBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSBLOCKFLAGS) object start size buffer flags ein gltiges DirectSoundBuffer-Objekt Offset in Bytes, ab wo geschrieben werden soll. Anzahl der Bytes, die geschrieben werden. Variable, die die Sounddaten enthlt. vom Typ CONST_DSBLOCKFLAGS

A.4.5

DirectSoundCapture
Die Methoden der DirectSoundCapture-Klasse werden zum Erstellen von Capturebuffern bentigt. Das DirectSoundCapture-Objekt wird mit der DirectX7.DirectSoundCaptureCreate()-Methode erzeugt. Folgende Methoden gehren zu der DirectSoundCapture-Klasse:
Erzeugen Eigenschaften CreateCaptureBuffer GetCaps

DirectSoundCapture.CreateCaptureBuffer
CreateCaptureBuffer() Erstellt einen Capturebuffer, der die Sounddaten aufnimmt. object.CreateCaptureBuffer(bufferDesc As DSCBUFFERDESC) _ As DirectSoundCaptureBuffer object bufferDesc ein gltiges DirectSoundCapture-Objekt Bufferbeschreibung vom Typ DSCBUFFERDESC

Anhang A Methoden

479

DirectSoundCapture.GetCaps
GetCaps() Beschreibt die Fhigkeiten des Aufnahmegerts. object.GetCaps(caps As DSCCAPS) object caps ein gltiges DirectSoundCapture-Objekt vom Typ DSCCAPS

A.4.6

DirectSoundCaptureBuffer
Die Methoden der DirectSoundCaptureBuffer-Klasse werden fr die Manipulation der CaptureBuffer eingesetzt. Das DirectSoundCaptureBuffer-Objekt wird mit der DirectSoundCaputer.CreateCaptureBuffer()-Methode erzeugt. Folgende Methoden gehren zu der DierctSoundCaptureBuffer-Klasse:
Informationen GetCaps GetCurrentPosition GetFormat GetStatus ReadBuffer WriteBuffer SetNotificationPositions Start Stop

Speichermanagement Ereignissteuerung Aufnahmemanagement

DirectSoundCaptureBuffer.GetCaps
GetCaps() Empfngt die Eigenschaften eines Capturebuffers. object.GetCaps(caps As DSCBCAPS) object caps ein gltiges DirectSoundCaptureBuffer-Objekt vom Typ DSCBCAPS

DirectSoundCaptureBuffer.GetCurrentPosition
GetCurrentPosition() Empfngt die aktuelle Aufnahme und Abspielposition im Buffer.

480

DirectSound-Methoden

GetCurrentPosition() object.GetCurrentPosition(cursors As DSCURSORS) object cursors ein gltiges DirectSoundCaptureBuffer-Objekt vom Typ DSCURSORS

DirectSoundCaptureBuffer.GetFormat
GetFormat() Gibt das aktuelle Waveformat eines Capturebuffers zurck. object.GetFormat(waveformat As WAVEFORMATEX) object waveformat ein gltiges DirectSoundCaptureBuffer-Objekt vom Typ WAVEFORMATEX

DirectSoundCaptureBuffer.GetStatus
GetStatus() Gibt den aktuellen Zustand eines Capturebuffers zurck. object.GetStatus() As CONST_DSCBSTATUSFLAGS object ein gltiges DirectSoundCaptureBuffer-Objekt

DirectSoundCaptureBuffer.ReadBuffer
ReadBuffer() Liest ein Segment aus dem Capturebuffer und speichert dieses in einer Variablen vom Typ Array. DirectSoundCaptureBuffer.WriteBuffer() object.ReadBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSCBLOCKFLAGS) object start size buffer flags ein gltiges DirectSoundCaptureBuffer-Objekt Offset in Bytes (Position, ab der gelesen wird). Anzahl der Bytes, die gelesen werden. Variable vom Typ Any, die die Sounddaten aufnimmt. vom Typ CONST_DSCBLOCKFLAGS

Anhang A Methoden

481

DirectSoundCaptureBuffer.SetNotificationPositions
SetNotificationPositions() Setzt die Notifikations-Position in einem SoundCaptureBuffer. object.SetNotificationPositions(nElements As Long, _ psa() As DSBPOSITIONNOTIFY) object nElements psa() ein gltiges DirectSoundCaptureBuffer-Objekt Nummer vom Typ DSBPOSITIONNOTIFY ein Array vom Typ DSBPOSITIONNOTIFY

DirectSoundCaptureBuffer.Start
Start() Setzt den CaptureBuffer in den Aufnahmezustand und beginnt mit dem Schreiben der ankommenden Sounddaten in den Capturebuffer. Befindet sich der Capturebuffer im Aufnahmezustand, hat diese Methode keine Auswirkung. object.Start(flags As CONST_DSCBSTARTFLAGS) object flags ein gltiges DirectSoundCaptureBuffer-Objekt vom Typ CONST_DSCBSTARTFLAGS

DirectSoundCaptureBuffer.Stop
Stop() Setzt den Capturebuffer in den Ruhezustand und hlt die Aufzeichnung der Sounddaten an. Befindet sich der Capturebuffer im Ruhezustand, hat diese Methode keine Auswirkung. object.Stop() object ein gltiges DirectSoundCaptureBuffer Objekt

DirectSoundCaptureBuffer.WriteBuffer
WriteBuffer() Schreibt von die Sounddaten aus einem Array in ein Segment des Capturebuffers. DirectSoundCaptureBuffer.ReadBuffer() object.WriteBuffer(start As Long, size As Long, buffer As Any, _ flags As CONST_DSCBLOCKFLAGS) object start ein gltiges DirectSoundCaptureBuffer Objekt Offset in Bytes (Position, ab der geschrieben wird)

482

DirectSound-Methoden

WriteBuffer() size buffer flags Anzahl der Bytes, die geschrieben werden. Variable vom Typ Any, die die Sounddaten enthllt. vom Typ CONST_DSCBLOCKFLAGS

A.4.7

DirectSoundEnum
Die Methoden der DirectSoundEnum-Klasse beinhalten eine Auflistung der im System installierten DirectSound-Treiber. Folgende Methoden gehren zu der DirectSoundEnum-Klasse:
DirectSoundEnum GetCount GetDescription GetGuid GetName

DirectSoundEnum.GetCount
GetCount() Gibt die Anzahl der Eintrge im Enumeration-Objekt zurck. object.GetCount() As Long object ein gltiges DirectSoundEnum-Objekt

DirectSoundEnum.GetDescription
GetDescription() Gibt die Treiberbeschreibung des ausgewhlten DirectSound-Gertes zurck. object.GetDescription(index As Long) As String object index ein gltiges DirectSoundEnum-Objekt Index des DirectSound-Gertes in der Aufzhlung.

DirectSoundEnum.GetGuid
GetGuid() Gibt die Identifikationsnummer des DirectSound-Gertes zurck. object.GetGuid(index As Long) As String object ein gltiges DirectSoundEnum-Objekt

Anhang A Methoden

483

GetGuid() index Index des DirectSound-Gertes in der Aufzhlung.

DirectSoundEnum.GetName
GetName() Gibt die Bezeichnung des DirectSound Gertes zurck. object.GetName(index As Long) As String object index ein gltiges DirectSoundEnum-Objekt Index des DirectSound-Gertes in der Aufzhlung.

A.5
A.5.1

DirectInput
DirectInput
Die DirectInput-Klasse reprsentiert das DirectInput-System. Die Klasse wird benutzt, um verfgbare Gerte aufzulisten, Gerte zu erzeugen oder den Status der Gerte zu erfragen. Das DirectInput-Objekt wird mit der DirectX7.DirectInputCreate()-Methode erzeugt. Folgenden Methoden gehhren zu der DirectInput-Klasse:
Gerteorganisation CreateDevice GetDeviceStatus GetDIEnumDevices RunControlPanel

Verschiedenes

DirectInput.CreateDevice
CreateDevice() Erzeugt ein DirectInputDevice. object.CreateDevice(guid As String) As DirectInputDevice object guid ein gltiges DirectInput-Objekt Guid fr das Gert

484

DirectInput

DirectInput.GetDeviceStatus
GetDeviceStatus() Prft ob ein Gert mit dem System verbunden ist. object.GetDeviceStatus(guid As String) As Boolean object guid ein gltiges DirectInput-Objekt Guid fr das Gert.

DirectInput.GetDIEnumDevices
GetDIEnumDevices() Erzeugt eine Liste mit Inputgerten. Dazu wird ein DirectInputEnumDevices-Objekt mit den Informationen gefllt. object.GetDIEnumDevices( deviceType As CONST_DIDEVICETYPE, _ flags As CONST_DIENUMDEVICESFLAGS) _ As DirectInputEnumDevices object deviceType ein gltiges DirectInput-Objekt Beschreibt, fr welche Art von Gerten die Liste erzeugt werden soll. DIDEVTYPE_MOUSE DIDEVTYPE_KEYBOARD DIDEVTYPE_JOYSTICK DIDEVTYPE_DEVICE DIEDFL_ALLDEVICES DIEDFL_ATTACHEDONLY

flags

DirectInput.RunControlPanel
RunControlPanel() Startet das Windows-Kontrollelement. object.RunControlPanel(hwndOwner As Long) object hwndOwner ein gltiges DirectInput Objekt Handle zu dem Windows-Fenster, auf dem das Windows-Kontrollelement angezeigt werden soll. Diese Parameter kann 0 sein.

A.5.2

DirectInputDevice
Die DirectInputDevice-Klasse handelt den Zugriff auf ein Inputgert. Sie managt die Deviceeigenschaften und initialisiert die Gerte.

Anhang A Methoden

485

Das DirectInputDevice-Objekt wird mit der DirectInputCreatDevice()-Methode erzeugt. Folgende Methoden gehren zu der DirectInputDevice-Klasse:
Zugriff Acquire SetCooperativeLevel Unacquire GetDeviceObjectsEnum GetObjectInfo GetCapabilities GetDeviceInfo GetProperty SetCommonDataFormat SetDataFormat SetProperty GetDeviceData GetDeviceState GetDeviceStateJoystick GetDeviceStateJoystick2 GetDeviceStateKeyboard GetDeviceStateMouse Poll SetEventNotification CreateCustomEffect CreateEffect GetEffectsEnum GetForceFeedbackState SendForceFeedbackCommand RunControlPanel SendDeviceData

Objekte Eigenschaften

Daten empfangen

Force-Feedback

Verschiedenes

DirectInputDevice.Acquire
Acquire() Stellt die Verbindung zum Inputgert her. DirectInputDevice.Unacquire() object.Acquire() object ein gltiges DirectInputDevice-Objekt

486

DirectInput

DirectInputDevice.CreateCustomEffect
CreateCustomEffect() Erzeugt einen Force-Feedback-Effekt. object.CreateCustomEffect(effectinfo As DIEFFECT, channels As Long, _ samplePeriod As Long, nSamples As Long, sampledata() As Long) _ As DirectInputEffect object effectinfo channels samplePeriod nSamples sampledata ein gltiges DirectInputDevice-Objekt Ein DIEDDECT Typen-Array, welches die Effektparameter beschreibt. Anzahl der Kanle (Achsen), die von dem Effekt betroffen sind. Effektdauer in Millisekunden Anzahl der Elemente in dem sampledata-Parameter Array vom Typ Long

DirectInputDevice.CreateEffect
CreateEffect() Erzeugt einen Force-Feedback-Effekt. DirectInputEffect.Download(), DirectInputEffect.Start() object.CreateEffect(effectGuid As String, _ effectinfo As DIEFFECT) As DirectInputEffect object effectGuid ein gltiges DirectInputDevice-Objekt GUID_ConstantForce GUID_RampForce GUID_Square GUID_Sine GUID_Triangle GUID_SawtoothUp GUID_SawtoothDown GUID_Spring GUID_Damper GUID_Inertia GUID_Friction Ein DIEDDECT Typen-Array, welches die Effektparameter beschreibt.

effectinfo

Anhang A Methoden

487

DirectInputDevice.GetCapabilities
GetCapabilities() Ermittelt die Fhigkeiten eines DirectInputDevice-Objekts. object.GetCapabilities(caps As DIDEVCAPS) object caps ein gltiges DirectInputDevice-Objekt Ein DIDEVCAPS-Typen-Array, welches mit den Fhigkeiten des Inputgertes gefllt wird

DirectInputDevice.GetDeviceData
GetDeviceData() Ermittelt die gespeicherten Daten eines Inputgertes. object.GetDeviceData(deviceObjectDataArray() As DIDEVICEOBJECTDATA,_ flags As CONST_DIDGDDFLAGS) As Long object deviceObject DataArray flags ein gltiges DirectInputDevice-Objekt Ein Array von DIDEVICEOBJECTDATA-Typen-Arrays, welches die Daten empfngt. DIGDD_DEFAULT DIGDD_PEEK

DirectInputDevice.GetDeviceInfo
GetDeviceInfo() Ermittelt Informationen ber die Identitt des Inputgerts. object.GetDeviceInfo() As DirectInputDeviceInstance object ein gltiges DirectInputDevice-Objekt

DirectInputDevice.GetDeviceObjectsEnum
GetDeviceObjectsEnum() Ermittelt die Objekte eines Gertes. Typische Objekte sind Achsen oder Knpfe. object.GetDeviceObjectsEnum( flags As CONST_DIDFTFLAGS) _ As DirectInputEnumDeviceObjects object flags ein gltiges DirectInputDevice-Objekt Eine Konstante aus der CONST_DIDFTFLAGS-Liste, welche die zu ermittelnden Objekte einschrnkt.

488

DirectInput

DirectInputDevice.GetDeviceState
GetDeviceState() Ermittelt den augenblicklichen Zustand eines Gertes. DirectInputDevice.GetDeviceStateJoystick(), DirectInputDevice.GetDeviceStateJoystick2(), DirectInputDevice.GetDeviceStateKeyboard(), DirectInputDevice.GetDeviceStateMouse(), DirectInputDevice.SetDataFormat() object.GetDeviceState(cb As Long, state As Any) object cb state ein gltiges DirectInputDevice-Objekt Gre des Arrays Erstes Element von einem Array, welches die Daten empfngt.

DirectInputDevice.GetDeviceStateJoystick
GetDeviceStateJoystick() Ermittelt Informationen ber die Objekte von einem Joystick. object.GetDeviceStateJoystick(state As DIJOYSTATE) object state ein gltiges DirectInputDevice-Objekt buttons (0 To 31) POV (0 To 3) rx ry rz slider (0 To 1) x y z

DirectInputDevice.GetDeviceStateJoystick2
GetDeviceStateJoystick2() Ermittelt Informationen ber die Objekte von einem Joystick mit erweiterten Funktionen. DirectInputDevice.Poll() object.GetDeviceStateJoystick2(state As DIJOYSTATE2) object ein gltiges DirectInputDevice-Objekt

Anhang A Methoden

489

GetDeviceStateJoystick2() state buttons (0 To 31) frx fry frz fslider (0 To 1) fx fy fz POV (0 To 3) rx ry rz slider (0 To 1) vrx vry vrz vslider (0 To 1) vx vy vz x y z

DirectInputDevice.GetDeviceStateKeyboard
GetDeviceStateKeyboard() Ermittelt Informationen ber die Objekte von einer Tastatur. object.GetDeviceStateKeyboard(state As DIKEYBOARDSTATE) object state ein gltiges DirectInputDevice-Objekt key(0 to 255)

Dim keyState as DIKEYBOARDSTATE Call diDevice.GetDeviceStateKeyboard(keyState) If (keyState.key(DIK_ESCAPE) And &H80) Then ' Escape-Taste ist gedrckt End If

490

DirectInput

DirectInputDevice.GetDeviceStateMouse
GetDeviceStateMouse() Ermittelt Informationen ber die Objekte von einer Maus. DirectInputDevice.Poll() object.GetDeviceStateMouse(state As DIMOUSESTATE) object state ein gltiges DirectInputDevice-Objekt buttons (0 To 3) x y z

DirectInputDevice.GetEffectsEnum
GetEffectsEnum() Erstellt eine Liste mit Force-Feedback-Effekten, welche von dem Gert untersttzt werden. object.GetEffectsEnum( _ effType As CONST_DIEFTFLAGS) As DirectInputEnumEffects object effType ein gltiges DirectInputDevice-Objekt Begrenzt die Liste. DIEFT_ALL DIEFT_CONDITION DIEFT_CONSTANTFORCE DIEFT_CUSTOMFORCE DIEFT_HARDWARE DIEFT_PERIODIC DIEFT_RAMPFORCE

DirectInputDevice.GetForceFeedbackState
GetForceFeedbackState() Ermittelt den Zustand eines Force-Feedback-Gertesystems. object.GetForceFeedbackState() As CONST_DIGFFSFLAGS object ein gltiges DirectInputDevice-Objekt

Anhang A Methoden

491

DirectInputDevice.GetObjectInfo
GetObjectInfo() Ermittelt Informationen ber ein Gerteobjekt wie Knpfe oder Achsen. object.GetObjectInfo( Obj As Long, how As CONST_DIPHFLAGS) _ As DirectInputDeviceObjectInstance object Obj how ein gltiges DirectInputDevice-Objekt Kennung fr das Objekt DIPH_DEVICE DIPH_BYID DIPH_BYOFFSET

DirectInputDevice.GetProperty
GetProperty() Ermittelt Informationen ber das Inputgert. DirectInputDevice.SetProperty() object.GetProperty( object guid guid As String, propertyInfo As Any) ein gltiges DirectInputDevice-Objekt DIPROP_AUTOCENTER DIPROP_AXISMODE DIPROP_BUFFERSIZE DIPROP_DEADZONE DIPROP_FFGAIN DIPROP_FFLOAD DIPROP_GRANULARITY DIPROP_RANGE DIPROP_SATURATION Ein DIPROPLONG-Typen-Array oder ein DIPROPRANGE-TypenArray fr die lObj-, lHow- und lSize-Mitglieder.

property Info

DirectInputDevice.Poll
Poll() Macht Daten von einem Poll-Objekt eines Gertes verfgbar. object.Poll() object ein gltiges DirectInputDevice-Objekt

492

DirectInput

DirectInputDevice.RunControlPanel
RunControlPanel() ffnet die Control-Panel Eigenschaftenseite fr das Gert. object.RunControlPanel(hwnd As Long) object hwnd ein gltiges DirectInputDevice-Objekt Handle zu dem Fenster, auf dem das Control-Panal dargestellt werden soll. Dieser Parameter kann 0 sein.

DirectInputDevice.SendDeviceData
SendDeviceData() Sendet Daten an ein Gert, welches dies erlaubt. object.SendDeviceData(count As Long, data() As DIDEVICEOBJECTDATA, _ flags As CONST_DESDDFLAGS) As Long object count data() flags ein gltiges DirectInputDevice-Objekt Anzahl der Elemente in dem data()-Array Daten 0 oder DISDD_CONTINUE

Wenn die Daten gesendet werden, muss das Gert im Acquired-Zustand sein.

DirectInputDevice.SendForceFeedbackCommand
SendForceFeedbackCommand() Sendet einen Befehl an ein Force-Feedback-Gertesystem. object.SendForceFeedbackCommand(flags As Long) object flags ein gltiges DirectInputDevice-Objekt DISFFC_CONTINUE DISFFC_PAUSE DISFFC_RESET DISFFC_SETACTUATORSOFF DISFFC_SETACTUATORSON DISFFC_STOPALL

DirectInputDevice.SetCommonDataFormat
SendCommonDataFormat() Setzt das Standardinputformat fr ein Gert.

Anhang A Methoden

493

SendCommonDataFormat() object.SetCommonDataFormat( _ format As CONST_DICOMMONDATAFORMATS) object format ein gltiges DirectInputDevice-Objekt DIFORMAT_JOYSTICK DIFORMAT_JOYSTICK2 DIFORMAT_KEYBOARD DIFORMAT_MOUSE

DirectInputDevice.SetCooperativeLevel
SendCooperativeLevel() Setzt den Cooperative Level des Gertes. object.SetCooperativeLevel(hwnd As Long, _ flags As CONST_DISCLFLAGS) object hwnd flags ein gltiges DirectInputDevice-Objekt Ein Windowshandle, welches mit dem Gert verbunden wird. DISCL_BACKGROUND DISCL_EXCLUSIVE DISCL_FOREGROUND DISCL_NONEXCLUSIVE

DirectInputDevice.SetDataFormat
SetDataFormat() Setzt ein Datenformat fr ein Gert, welches von den Standardformaten abweicht. DirectInputDevice.SetCommonDataFormat() object.SetDataFormat(format As DIDATAFORMAT, _ formatArray() As DIOBJECTDATAFORMAT)) object format formatArray() ein gltiges DirectInputDevice-Objekt Ein DIDATAFORMAT Typen-Array, welches das Datenformat beschreibt. Ein Array von DIOBJECTDATAFORMAT-Typen-Arrays, welches die Formate der Gerteobjekte beschreiben.

494

DirectInput

DirectInputDevice.SetEventNotification
SetEventNotification() Setzt den Benachrichtigungszustand. Das gesetzte Event wird immer dann aufgerufen, wenn sich der Gertezustand ndert. object.SetEventNotification(hEvent As Long) object hEvent ein gltiges DirectInputDevice-Objekt Handle fr ein Event

DirectInputDevice.SetProperty
SetProperty() Setzt die Gerteeigenschaften, die das Verhalten der Gertes beschreiben. object.SetProperty( guid As String, propertyInfo As Any) object guid ein gltiges DirectInputDevice-Objekt DIPROP_AXISMODE DIPROP_BUFFERSIZE DIPROP_CALIBRATIONMODE DIPROP_DEADZONE DIPROP_RANGE DIPROP_SATURATION Ein DIPROPLONG Typen-Array oder ein DIPROPRANGE-TypenArray fr die lObj-, lHow- und lSize-Mitglieder.

properyInfo

DirectInputDevice.Unacquire
Unacquire() Lst die Verbindung zu einem Gert. DirectInputDevice.Acquire() object.Unacquire() object ein gltiges DirectInputDevice-Objekt

A.5.3

DirectInputDeviceInstance
Die DirectInputDeviceInstance-Klasse beinhaltet Informationen ber die Gerteinstanz. Das DirectInputDeviceInstance-Objekt wird mit den DirectInputDevice.GetDeviceInfo()- oder DirectInputEnumDevices.GetItem()-Methoden erzeugt.

Anhang A Methoden

495

Folgende Methoden gehren zu der DirectInputDeviceInstance-Klasse:


Information GetDevType GetGuidFFDriver GetGuidInstance GetGuidProduct GetInstanceName GetProductName GetUsage GetUsagePage

DirectInputDeviceInstance.GetDevType
GetDevType() Ermittelt den Gertetyp. object.GetDevType() As Long object ein gltiges DirectInputDeviceInstance-Objekt

DirectInputDeviceInstance.GetGuidFFDriver
GetGuidFFDriver() Ermittelt die einmalige Kennung des Force-Feedback Treibers. object.GetGuidFFDriver() As String object ein gltiges DirectInputDeviceInstance-Objekt

DirectInputDeviceInstance.GetGuidInstance
GetGuidInstance() Ermittelt die einmalige Kennung der Gerteinstanz. object.GetGuidInstance() As String object ein gltiges DirectInputDeviceInstance-Objekt

DirectInputDeviceInstance.GetGuidProduct
GetGuidProduct() Ermittelt die Herstellerkennung fr ein Gert. object.GetGuidProduct() As String object ein gltiges DirectInputDeviceInstance-Objekt

496

DirectInput

DirectInputDeviceInstance.GetInstanceName
GetInstanceName() Ermittelt den Instanznamen eines Gertes. object.GetInstanceName() As String object ein gltiges DirectInputDeviceInstance-Objekt

DirectInputDeviceInstance.GetProductName
GetProductName() Ermittelt den Produktnamen eines Gertes. object.GetProductName() As String object ein gltiges DirectInputDeviceInstance-Objekt

DirectInputDeviceInstance.GetUsage
GetUsage() Ermittelt den Verwendungscode eines Human Interface Device. object.GetUsage() As Integer object ein gltiges DirectInputDeviceInstance-Objekt

DirectInputDeviceInstance.GetUsagePage
GetUsagePage() Ermittelt die Verwendungsseite eines Human Interface Device. object.GetUsagePage() As Integer object ein gltiges DirectInputDeviceInstance-Objekt

A.5.4

DirectInputDeviceObjectInstance
Die DirectInputDeviceObjectInstance-Klasse reprsentiert die DirectInput-Gerte. Das DirectInputDeviceObjectInstance-Objekt wird durch die DirectInputDevice. GetObjectInfo()- oder DirectInputEnumDeviceObjects.GetItem()-Methoden erzeugt.

Anhang A Methoden

497

Folgende Methoden gehren zu der DirectInputDeviceObjectInstance-Klasse:


Information GetCollectionNumber GetDesignatorIndex GetDimension GetExponent GetFlags GetGuidType GetName GetOfs GetType GetUsage GetUsagePage

DirectInputDeviceObjectInstance.GetCollectionNumber
GetCollectionNumber() Ermittelt die Anzahl der Human-Interface-Devices- (HID-) Verweise. object.GetCollectionNumber() As Integer object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetDesignatorIndex
GetDesignatorIndex() Ermittelt die Kennzeichnung eines Objektes auf einem HID-Device. object.GetDesignatorIndex() As Integer object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetDimension
GetDimension() Ermittelt den Code fr die Einheitendimension eines Objektes in der es berichtet wird. DirectInputDeviceObjectInstance.GetExponent() object.GetDimension() As Long object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetExponent
GetExponent() Ermittelt den Exponenten.

498

DirectInput

GetExponent() object.GetExponent() As Integer object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetFlags
GetFlags() Ermittelt die Kennzeichnungen (Flags) eines Gertes. object.GetFlags() As CONST_DIDEVICEOBJINSTANCEFLAGS object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetGuidType
GetGuidType() Ermittet die Guid eines Objekttyps. object.GetGuidType() As String object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetName
GetName() Ermittelt den Rufnamen eines Gerteobjektes. object.GetName() As String object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetOfs
GetOfs() Ermittelt den Offset eines Gertes. object.GetOfs() As Long object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetType
GetType() Ermittelt den Typ eines Gerteobjekts. object.GetType() As Long

Anhang A Methoden

499

GetType() object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetUsage
GetUsage() Ermittelt den HID Verwendungscode fr ein Gerteobjekt. object.GetUsage() As Integer object ein gltiges DirectInputDeviceObjectInstance-Objekt

DirectInputDeviceObjectInstance.GetUsagePage
GetUsagePage() Ermittelt die HID Verwendungsseite fr ein Gerteobjekt. object.GetUsagePage() As Integer object ein gltiges DirectInputDeviceObjectInstance-Objekt

A.5.5

DirectInputEffect
Die DirectInputEffect-Klasse reprsentiert die Force-Feedback-Effekte, welche durch die Anwendung erstellt werden. Das DirectInputEffect-Objekt wird mit der DirectInputDevice.CreateEffect()Methode erzeugt. Folgende Methoden gehren zu der DirectInputEffect-Klasse:
Information GetEffectGuid GetEffectStatus GetParameters Download SetParameters Start Stop Unload

Manipulation

DirectInputEffect.Download
Download() Platziert einen Effekt auf einem Gert.

500

DirectInput

Download() object.Download() object ein gltiges DirectInputEffect-Objekt

DirectInputEffect.GetEffectGuid
GetEffectGuid() Ermittelt die Guid von einem Effekt. Der Effekt wird von dem DirectInputEffect Objekt reprsentiert. object.GetEffectGuid() As String object ein gltiges DirectInputEffect-Objekt

DirectInputEffect.GetEffectStatus
GetEffectStatus() Ermittelt den Status von einem Effekt. object.GetEffectStatus() As Long object ein gltiges DirectInputEffect-Objekt

DirectInputEffect.GetParameters
GetParameters() Ermittelt die Parameter von einem Effekt. object.GetParameters(effectinfo As DIEFFECT) object effectinfo ein gltiges DirectInputEffect-Objekt Ein DIEFFECT-Typen-Array, welches die Informationen aufnimmt.

DirectInputEffect.SetParameters
SetParameters() Setzt die Effektparameter fr einen Effekt. object.SetParameters(effectinfo As DIEFFECT, flags As CONST_DIEPFLAGS) object effectinfo ein gltiges DirectInputEffect-Objekt Ein DIEFFECT-Typen-Array, welches die Parameter fr den Effekt enthlt.

Anhang A Methoden

501

SetParameters() flags eine Konstante aus der CONST_DIEPFLAGS-Liste

DirectInputEffect.Start
Start() Startet einen Effekt. Ist der Effekt bereits gestartet, so wird der Effekt erneut gestartet. object.Start(iterations As Long, flags As Long) object iterations flags ein gltiges DirectInputEffect-Objekt Zeit, die der Effekt dauern soll. DIES_SOLO DIES_NODOWNLOAD

DirectInputEffect.Stop
Stop() Hlt einen Effekt an. object.Stop() object ein gltiges DirectInputEffect-Objekt

DirectInputEffect.Unload
Unload() Entfernt einen Effekt von einem Gert. object.Unload() object ein gltiges DirectInputEffect-Objekt

A.5.6

DirectInputEnumDeviceObjects
Die DirectinputEnumDeviceObjects-Klasse ermittelt die installierten Gerteobjekte. Das DirectInputEnumDeviceObjects-Objekt wird mit der DirectInputDevice.GetDeviceObjectsEnum()-Methode erzeugt. Folgende Methoden gehren zu der DirectInputEnumDeviceObjects-Klasse:
Information GetCount GetItem

502

DirectInput

DirectInputEnumDeviceObjects.GetCount
GetCount() Ermittelt die Anzahl von Elementen in dem DirectInputEnumDeviceObjects-Objekt. object.GetCount() As Long object ein gltiges DirectInputEnumDeviceObjects-Objekt

DirectInputEnumDeviceObjects.GetItem
GetItem() Ermittelt die Objektbeschreibung von einem Element aus dem DirectInputEnumDevice Objects-Objekt. object.GetItem(index As Long) As DirectInputDeviceObjectInstance object index ein gltiges DirectInputEnumDeviceObjects-Objekt Element

A.5.7

DirectInputEnumDevices
Die DirectInputEnumDevices-Klasse beinhaltet Informationen ber die installierten Inputgerte. Das DirectInputEnumDevices-Objekt wird mit der DirectInput.GetDirectInput EnumDevices()-Methode erzeugt. Folgende Methoden gehren zu der DirectInputEnumDevices-Klasse:
Information GetCount GetItem

DirectInputEnumDevices.GetCount
GetCount() Ermittelt die Anzahl der Elemente in dem DirectInputEnumDevices-Objekt. object.GetCount() As Long object ein gltiges DirectInputEnumDevices-Objekt

DirectInputEnumDevices.GetItem
GetItem() Ermittelt Informationen ber ein Element aus dem DirectInputEnumDevices-Objekt.

Anhang A Methoden

503

GetItem() object.GetItem(index As Long) As DirectInputDeviceInstance object index ein gltiges DirectInputEnumDevices-Objekt Element

A.5.8

DirectInputEnumEffects
Die DirectInputEnumEffects-Klasse reprsentiert die Force-Feedback-Effekte eines Gertes. Sie liefert Informationen ber die einzelnen Effekte. Das DirectInputEnumEffects-Objekt wird mit der DirectInputDevices.GetEffects Enum()-Methode erzeugt. Folgende Methoden gehren zu der DirectInputEnumEffects-Klasse:
Information GetCount GetDynamicParams GetEffectGuid GetName GetStaticParams GetType

DirectInputEnumEffects.GetCount
GetCount() Ermittelt die Anzahl der Elemente in dem DirectInputEnumEffects-Objekt. object.GetCount() As Long object ein gltiges DirectInputEnumEffects-Objekt

DirectInputEnumEffects.GetDynamicParams
GetDynamicParams() Ermittelt die Effekte, deren Parameter gendert werden knnen, ohne den Effekt zuvor anzuhalten. DirectInputEffect.SetParameters() object.GetDynamicParams(i As Long) As CONST_DIEPFLAGS object i ein gltiges DirectInputEnumEffects-Objekt Effekt

504

DirectInput

DirectInputEnumEffects.GetEffectGuid
GetEffectGuid() Ermittelt die Guid eines Effekts. object.GetEffectGuid(i As Long) As String object i ein gltiges DirectInputEnumEffects-Objekt Effekt

DirectInputEnumEffects.GetName
GetName() Ermittelt den Namen eines Effekts. object.GetName(i As Long) As String object i ein gltiges DirectInputEnumEffects-Objekt Effekt

DirectInputEnumEffects.GetStaticParams
GetStaticParams() Ermittelt die Parameter, welche ein Gert fr einen Effekt untersttzt. object.GetStaticParams(i As Long) As CONST_DIEPFLAGS object i ein gltiges DirectInputEnumEffects-Objekt Effekt

DirectInputEnumEffects.GetType
GetType() Ermittelt den Typ und die Fhigkeiten eines Effekts. object.GetType(i As Long) As CONST_DIEFTFLAGS object i ein gltiges DirectInputEnumEffects-Objekt Effekt

Anhang A Methoden

505

A.6
A.6.1

DirectPlay-Methoden
DirectPlay4-Methoden
Anwendungen nutzen die Methoden der DirectPlay4-Klasse, um DirectPlay4Objekte zu erzeugen, Informationslisten zu erstellen, Verbindungen einzurichten oder um Sessions, Player und Gruppen zu organisieren. Ein einzelnes DirectPlay4-Objekt wird mit der DirectX7.DirectPlayCreate()Methode erzeugt. Die DirectPlay4-Klasse ist in folgenden Gruppen organisiert:
Verbindung GetDPEnumConnections InitializeConnection SetGroupConnectionSettings Close CreateSessionData GetDPEnumSessions GetCaps GetSessionDesc Open SecureOpen SetSessionDesc StartSession CreatePlayer DestroyPlayer GetDPEnumPlayers GetPlayerAccountId GetPlayerAddress GetPlayerCaps GetPlayerData GetPlayerFlags GetPlayerFormalName GetPlayerFriendlyName SetPlayerData SetPlayerName CancelMessage CancelPriority CreateMessage GetMessageCount GetMessageQueue Receive Send SendChatMessage SendEx

Sessions

Spieler

Nachrichten

506

DirectPlay-Methoden

Gruppen

AddGroupToGroup AddPlayerToGroup CreateGroup CreateGroupInGroup DeleteGroupFromGroup

GetDPEnumConnections
GetDPEnumConnections() Erzeugt eine Liste mit allen registrierten Service-Providern sowie Lobby-Providern. object.GetDPEnumConnections(guid As String, flags As CONST_DPENUMCONNECTIONFLAGS) As DirectPlayEnumConnections object guid flags ein gltiges DirectPlay4-Objekt Guid fr die Anwendung DPCONNECTION_DIRECTPLAY Auflistung fr DirectPlay-Service-Provider. DPCONNECTION_DIRECTPLAYLOBBY Auflistung fr DirectPlay-Lobby-Provider.

InitializeConnection
InitializeConnection() Initialisiert eine DirectPlay-Verbindung. object. InitializeConnection (addr As DirectPlayAdress) Object Addr Ein gltiges DirectPlay4-Objekt. Ein DirectPlayAddress-Objekt. Das DirectPlayAddress-Objekt wird mit der DirectPlay4.GetDPEnum Connections()-Methode abgefragt.

SetGroupConnectionSettings
SetGroupConnectionSettings() Setzt die Verbindungsparameter fr eine Session, welche von einer Gruppe gestartet werden soll. Diese Methode kann nur in einer Lobbysession eingesetzt werden. DirectPlayLobby3.RunApplication() object.SetGroupConnectionSettings(id As Long, _ connection As DirectPlayLobbyConnection) object id ein gltiges DirectPlay4-Objekt ID der Gruppe

Anhang A Methoden

507

SetGroupConnectionSettings() connection ein DirectPlayLobbyConnection-Objekt

Close
Close() Schliet eine zuvor geffnete Session. DirectPlay4.DestroyPlayer(), DirectPlay4.Open() object.Close() object ein gltiges DirectPlay4-Objekt

CreateSessionData
CreateSessionData() Erzeugt ein DirectPlaySessionData-Objekt. object.CreateSessionData() As DirectPlaySessionData object ein gltiges DirectPlay4-Objekt

GetDPEnumSessions
GetDPEnumSessions() Erzeugt eine Liste mit allen aktiven Sessions. Die Auswahl der Sessions wird durch den flags-Parameter eingegrenzt. object.GetDPEnumSessions( sessionDesc As DirectPlaySessionData, _ timeOut As Long, flags As CONST_DPENUMSESSIONFLAGS) _ As DirectPlayEnumSessions Object Session Desc TimeOut ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Liste der Sessions aufnimmt. Wartezeit in Millisekunden. Der Parameter kann 0 sein, dann wird die voreingestellte Wartezeit des Service-Providers genommen. Die Wartezeit des Service-Providers kann mit der DirectPlay4.GetCaps()-Methode abgefragt werden. Eine Konstante aus der CONST_DPENUMSESSIONSFLAGSListe

Flags

508

DirectPlay-Methoden

GetCaps
GetCaps() Fragt die Leistungsfhigkeit der aktuellen DirectPlay Verbindung und Session ab. DirectPlay4.GetPlayerCaps(), DirectPlay4.InitializeConnection() object.GetCaps(caps As DPCAPS, flags As CONST_DPGETCAPSFLAGS) As DirectPlayEnumSessions object caps flags ein gltiges DirectPlay4-Objekt Ein DPCAPS Typen-Array, welches die ermitteltetn Merkmale aufnimmt. eine Konstante aus der CONST_DPGETCAPSFLAGS-Liste

GetSessionDesc
GetSessionDesc() Erfragt die Eigenschaften der aktuell geffneten Session. object.GetSessionDesc(sessionDesc As DirectPlaySessionData) Object Session Desc ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Informationen aufnimmt. Dieses Objekt wird mit der DirectPlay4CreateSessionData()Methode erzeugt

Open
Open() Erzeugt oder schliet sich einer Session an. DirectPlay4.Close() object.Open(sessionDesc As DirectPlaySessionData, _ flags As CONST_DPOPENFLAGS) Object Session Desc Flags ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Informationen der Sessinon enthlt. Dieses Objekt wird mit der DirectPlay4CreateSessionData()-Methode erzeugt. DPOPEN_CREATE DPOPEN_JOIN DPOPEN_RETURNSTATUS

Anhang A Methoden

509

SecureOpen
SecureOpen() Erzeugt oder schliet sich einer Sicherheits-Session an. object.SecureOpen(sessionDesc DirectPlaySessionData, _ flags As CONST_DPOPENFLAGS, security As DPSECURITYDESC, _ credentials As DPCREDENTIALS)) Object SessionDesc ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Informationen der Sessinon enthlt. Dieses Objekt wird mit der DirectPlay4CreateSession-Data()-Methode erzeugt. eine Konstante aus der CONST_DPOPENFLAGS-Liste Ein DPSECURITYDESC Typen-Array, welches die Sicherheitsinformationen enthlt. Ein DPCREDENTIALS Typen-Array, welches LogOn-Name, Passwort und die Domne enthlt. Diese werden bentigt, um vom Server initialisiert zu werden.

Flags Security Credentials

SetSessionDesc
SetSessionDesc() ndert die Eigenschaften der aktuellen Session. Nur der Host-Teilnehmer einer Session kann dies tun. DirectPlay4.GetSessionDesc() object.SetSessionDesc(sessionDesc As DirectPlaySessionData) object sessionDesc ein gltiges DirectPlay4-Objekt Ein DirectPlaySessionData-Objekt, welches die Informationen der Sessinon enthlt. Dieses Objekt wird mit der DirectPlay4CreateSession-Data()-Methode erzeugt.

StartSession
StartSession() Startet eine DirectPlay4 Session von einer Startebene aus. object.StartSession(id As Long) Object Id ein gltiges DirectPlay4-Objekt Kennung einer Gruppe. Die Gruppe muss der Veranstalter der Session sein.

510

DirectPlay-Methoden

CreatePlayer
CreatePlayer() Erzeugt einen lokalen Spieler fr die aktuelle Session. object.CreatePlayer(friendlyName As String, formalName As String, _ receiveEvent As Long, flags As CONST_DPPLAYERFLAGS) As Long Object Friendly Name Formal Name Receive Event Flags ein gltiges DirectPlay4-Objekt Rufname Hausname Handle fr ein Ereignis, welches ausgelst wird, wenn eine Nachricht fr diesen Spieler eintrifft. DPPLAYER_SERVERPLAYER DPPLAYER_SPECTATOR Defaultwert ist 0 nonserverplayer und nonspectator.

DestroyPlayer
DestroyPlayer() Lscht einen lokalen Spieler aus einer Session. object.DestroyPlayer(playerId As Long) Object PlayerId ein gltiges DirectPlay4-Objekt Kennung des Spielers

GetDPEnumPlayers
GetDPEnumPlayers() Erstellt eine Liste aller Spieler oder / und Gruppen in der aktuellen geffneten Session. object.GetDPEnumPlayers(sessionGuid As String, _ flags As CONST_DPENUMPLAYERFLAGS) As DirectPlayEnumPlayers Object Session Guid Flags ein gltiges DirectPlay4-Objekt Der Parameter muss eine leere Zeichenkette sein, um die Spieler der aktuellen geffneten Session aufzulisten. Eine Konstante aus der CONST_DPENUMPLAYERFLAGS-Liste. Sie nimmt Einschrnkungen an der Auflistung vor.

Anhang A Methoden

511

GetPlayerAccountId
GetPlayerAccountId() Liest die Account-Identifizierung eines Spielers. object.GetPlayerAccountId(playerId As Long) As String Object PlayerId ein gltiges DirectPlay4-Objekt Kennung des Spielers, von dem die Information ermittelt werden soll.

GetPlayerAddress
GetPlayerAddress() Liest die Adresse eines Spielers. object.GetPlayerAddress(playerId As Long) As String Object PlayerId ein gltiges DirectPlay4-Objekt Kennung des Spielers, von dem die Information ermittelt werden soll.

GetPlayerCaps
GetPlayerCaps() Ermittelt die aktuellen Eigenschaften eines Spielers. DirectPlay4.GetCaps(), DirectPlay4.Send() object.GetPlayerCaps(playerId As Long, caps As DPCAPS, _ flags As CONST_DPGETCAPSFLAGS) object playerId caps flags ein gltiges DirectPlay4-Objekt Kennung des Spielers, von dem die Information ermittelt werden soll. Ein DPCAPS Typen-Array, welches die Informationen aufnimmt. eine Konstante aus der CONST_DPGETCAPSFLAGS-Liste.

GetPlayerData
GetPlayerData() Ermittelt die aktuellen Informationen ber einen Spieler. Diese Informationen sind anwendungsspezifisch und werden mit der DirectPlay4.SetPlayerData()-Methode gesetzt. Der Rckgabewert ist ein Datenblock in Form einer Zeichenkette. object.GetPlayerData(playerId As Long, flags As CONST_DPGETFLAGS) _ As String Object ein gltiges DirectPlay4-Objekt

512

DirectPlay-Methoden

GetPlayerData() PlayerId Flags Kennung des Spielers, von dem die Information ermittelt werden soll. Eine Konstante aus der CONST_DPGETFLAGS-Liste.

GetPlayerFlags
GetPlayerFlags() Ermittelt die Flags, welche zur Beschreibung des Spielers verwendet wurden, als der Spieler erstellt wurde. Mgliche Rckgabewerte sind: DPPLAYER_LOCAL DPPLAYER_SERVERPLAYER DPPLAYER_SPECTATOR object.GetPlayerFlags(id As Long) As CONST_DPPLAYERFLAGS Object Id ein gltiges DirectPlay4-Objekt Kennung des Spielers, von dem die Information ermittelt werden soll.

GetPlayerFormalName
GetPlayerFormalName() Ermittelt den Hausnamen des Spielers. object.GetPlayerFormalName(playerId As Long) As String Object PlayerId ein gltiges DirectPlay4-Objekt Kennung des Spielers, von dem die Information ermittelt werden soll.

GetPlayerFriendlyName
GetPlayerFriendlyName() Ermittelt den Rufnamen des Spielers. object.GetPlayerFriendlyName(playerId As Long) As String Object PlayerId ein gltiges DirectPlay4-Objekt Kennung des Spielers, von dem die Information ermittelt werden soll.

SetPlayerData
SetPlayerData() Setzt einen anwendungsspezifischen Datenblock fr einen Spieler.

Anhang A Methoden

513

SetPlayerData() object.SetPlayerData(playerId As Long, data As String, _ flags As CONST_DPSETFLAGS) Object PlayerId Data Flags ein gltiges DirectPlay4-Objekt Kennung des Spielers, dem die Information zugeordnet werden soll. Dieser Datenblock kann eine leere Zeichenkette sein, dann werden alle Daten gelscht. eine Konstante aus der CONST_DPSETFLAGS-Liste

SetPlayerName
SetPlayerData() Setzt einen anwendungsspezifischen Datenblock fr einen Spieler. object.SetPlayerName(playerId As Long, friendlyName As String, _ formalName As String, flags As CONST_DPSETFLAGS) Object PlayerId Friendly Name Formal Name Flags ein gltiges DirectPlay4-Objekt Kennung des Spielers, dem die Information zugeordnet werden soll. Rufname Hausname Eine Konstante aus der CONST_DPSETFLAGS-Liste, welche beschreibt, wie die Informationen verbreitet werden sollen.

CancelMessage
CancelMessage() Lscht eine spezifische oder alle Nachrichten der Nachrichtenwarteschlange. Um diese Nachricht / Nachrichten zu lschen, muss die Nachrichten-ID gespeichert worden sein. Dies ist Aufgabe der Anwendung. object.CancelMessage(msgid As Long) Object Msgid ein gltiges DirectPlay4-Objekt Kennung der Nachricht, welche gelscht werden soll.

CancelPriority
CancelPriority() Lscht alle Nachrichten einer definierten Prioritt bzw. eines Bereichs von Prioritten.

514

DirectPlay-Methoden

CancelPriority() object.CancelPriority(minPriority As Long, Object MinPriority MaxPriority ein gltiges DirectPlay4-Objekt unterer Wert fr einen Priorittenbereich oberer Wert fr einen Priorittenbereich maxPriority As Long)

CreateMessage
CreateMessage() Erzeugt ein Message-Objekt, welches mit Daten zum Senden gefllt werden kann. DirectPlay4.Send() object.CreateMessage() As DirectPlayMessage Object ein gltiges DirectPlay4-Objekt

GetMessageCount
GetMessageCount() Ermittelt die Anzahl von Nachrichten in der Nachrichtenwarteschlange fr einen definierten lokalen Spieler. DirectPlay4.Receive() object.GetMessageCount(playerId As Long) As Long Object PlayerId ein gltiges DirectPlay4-Objekt Index fr einen Spieler

GetMessageQueue
GetMessageQueue() Ermittelt Informationen ber die gesendeten oder empfangenen Nachrichten aus der Nachrichtenwarteschlange fr einen lokalen Spieler. object.GetMessageQueue(from As Long, to As Long, _ flags As CONST_DPMESSAGEQUEUEFLAGS, nMessage As Long, _ nBytes As Long) Object From To ein gltiges DirectPlay4-Objekt Index des Spielers, der Nachrichten sendet. Index des Spielers, der Nachrichten empfngt.

Anhang A Methoden

515

GetMessageQueue() Flags NMessage NBytes DPMESSAGEQUEUE_SEND DPMESSAGEQUEUE_RECEIVE Nimmt die Anzahl der Nachrichten in der Nachrichtenwarteschlange auf. Nimmt die Anzahl der Bytes aller Nachrichten in der Nachrichtenwarteschlange auf.

Diese Methode ist hervorragend dazu geeignet, den Nachrichtenfluss zu regulieren.

Receive
Receive() Empfngt Nachrichten aus der Nachrichtenwarteschlange. DirectPlay4.Send() object.Receive(fromPlayerId As Long, toPlayerId As Long, _ flags As CONST_DPRECEIVEFLAGS) As DirectPlayMessage Object From PlayerId ToPlayer Id Flags ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat. Index des Spielers, fr welchen die Nachricht bestimmt ist. DPRECEIVE_ALL DPRECEIVE_PEEK DPRECEIVE_TOPLAYER PRECEIVE_FROMPLAYER

Send
Send() Sendet eine Nachricht an einen Spieler oder eine Gruppe von Spielern oder allen Spielern. DirectPlay4.Receive(), DirectPlay4.SendChatMessage() object.Send(fromPlayerId As Long, toPlayerId As Long, _ flags As CONST_DPSENDFLAGS, msg As DirectPlayMessage) object from PlayerId toPlayer Id ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat. Index des Spielers, fr welchen die Nachricht bestimmt ist.

516

DirectPlay-Methoden

Send() flags DPSEND_ENCRYPTED DPSEND_GUARANTEED DPSEND_SIGNED Ein DirectPlayMessage Objekt, welches die Nachricht enthlt, die versendet werden soll.

msg

SendChatMessage
SendChatMessage() Sendet eine Textnachricht an einen Spieler oder einer Gruppe von Spielern oder allen Spielern. object.SendChatMessage(fromPlayerId As Long, toPlayerId As Long, _ flags As CONST_DPSENDFLAGS, message As String) Object From PlayerId ToPlayer Id Flags ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat. Index des Spielers, fr welchen die Nachricht bestimmt ist. DPSEND_GUARANTEED Ist dieser Parameter 0, so ist das Ankommen der Nachricht nicht garantiert. Nachricht die gesendet werden soll.

Msg

SendEx
SendEx() Sendet eine Textnachricht an einen Spieler oder einer Gruppe von Spielern oder allen Spielern. SendEx() ist eine erweiterte Version der Send()-Methode. object.SendEx(fromPlayerId As Long, toPlayerId As Long, _ flags As CONST_DPSENDFLAGS, msg As DirectPlayMessage, _ priority As Long, timeOut As Long, context As Long) As Long Object fromPlayerId toPlayerId ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat. Index des Spielers, fr welchen die Nachricht bestimmt ist.

Anhang A Methoden

517

SendEx() Flags DPSEND_ASYNC DPSEND_ENCRYPTED DPSEND_GUARANTEED DPSEND_NOSENDCOMPLETEMSG DPSEND_SIGNED Ein DirectPlayMessage-Objekt, welches die Nachricht enthlt, die versendet werden soll. Prioritt der Nachricht. Liegt im Wertebereich zwischen 0 und 65535. Zeit in Millisekunden, die gewartet wird, bis die Nachricht abgeliefert wurde. Anwendungsbezogener Kontex, welcher zur Vervollstndigung der Nachricht gehrt. Kann 0 sein.

Msg Priority timeOut Context

AddGroupToGroup
AddGroupToGroup() Addiert eine Gruppe zu einer anderen Gruppe. DirectPlay4.CreateGroupInGroup() object.AddGroupToGroup(ParentGroupId As Long, GroupId As Long) object Parent GroupId GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, in die eine Gruppe eingefgt werden soll. Index der Gruppe, welche in eine Gruppe eingefgt werden soll.

Die Systemnachricht DPSYS_ADDGROUPTOGROUP wird erzeugt, um die anderen Spieler von diesem Wechsel in Kenntnis zu setzen.

AddPlayerToGroup
AddPlayerToGroup() Integriert einen Spieler in eine bestehende Gruppe. DirectPlay4.CreateGroup(), DirectPlay4.DeletePlayerFromGroup() object.AddPlayerToGroup(GroupId As Long, playerId As Long) object ParentGroupId playerId ein gltiges DirectPlay4-Objekt Index der Gruppe, in die ein Spieler eintreten mchte. Index des Spielers, welcher der Gruppe beitreten mchte.

Ein Spieler kann Mitglied in mehreren Gruppen sein. Dabei muss der Spieler nicht unbedingt ein lokaler Spieler sein.

518

DirectPlay-Methoden

CreateGroup
CreateGroup() Erzeugt eine Gruppe in der aktuellen Session. DirectPlay4.AddGroupToGroup(), DirectPlay4.DestroyGroup(), DirectPlay4.GetDPEnumGroupPlayers(), DirectPlay4.GetGroupFlags(), DirectPlay4.SetGroupData(), DirectPlay4.SetGroupName() object.CreateGroup(friendlyName As String, formalName As String, _ flags As CONST_DPGROUPFLAGS) As Long object friendly Name formal Name flags ein gltiges DirectPlay4-Objekt Rufname Hausname DPGROUP_DEFAULT DPGROUP_HIDDEN DPGROUP_STAGINGAREA

Ist die Gruppe in einer Client/Server-Session erzeugt worden, werden keine Gruppeninformationsnachrichten erzeugt. Gruppen sind nur auf dem Computer sichtbar, auf dem sie erzeugt wurden, unabhngig davon, ob es sich um den Client, oder Host-Rechner handelt. In einer Peer-to-Peer Session wird die Nachricht DPSYS_CREATEPLAYERORGROUP erzeugt und an alle Spieler der Session gesendet.

CreateGroupInGroup
CreateGroupInGroup() Erzeugt eine Gruppe in einer existierenden Gruppe. object.CreateGroupInGroup(parentid As Long, friendlyName As String, _ formalName As String, flags As CONST_DPGROUPFLAGS) As Long Object Parentid Friendly Name Formal Name Flags ein gltiges DirectPlay4-Objekt Index der Gruppe, in der eine Gruppe erzeugt werden soll. Rufname Hausname DPGROUP_LOCAL DPGROUP_STAGINGAREA

Anhang A Methoden

519

CreateGroupInGroup() Um sich die erzeugten Gruppen in einer Gruppe anzeigen zu lassen, muss die DirectPlay4.GetDPEnumGroupsInGroup()-Methode verwendet werden. Ist die Gruppe in einer Client/Server-Session erzeugt worden, werden keine Gruppeninformations Nachrichten erzeugt. Gruppen sind nur auf dem Computer sichtbar, auf dem sie erzeugt wurden, unabhngig davon, ob es sich um den Client- oder Host-Rechner handelt. In einer Peer-to-Peer Session wird die Nachricht DPSYS_CREATEPLAYEROR GROUP erzeugt und an alle Spieler der Session gesendet.

DeleteGroupFromGroup
DeleteGroupFromGroup() Entfernt eine Gruppe aus einer bestehenden Gruppe. Die Gruppe wurde zuvor mit der DirectPlay4.AddGroupToGroup()-Methode eingefgt. object. DeleteGroupFromGroup(ParentGroupId As Long, GroupId As Long) Object Parent GroupId GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, aus der eine Gruppe entfernt werden soll. Index der Gruppe, die entfernt werden soll.

Die DPSYS_DELETEGROUPFROMGROUP-Systemnachricht wird erzeugt und informiert alle Spieler ber den Wechsel.

DeletePlayerFromGroup
DeletePlayerFromGroup() Entfernt einen Spieler aus einer Gruppe. DirectPlay4.AddPlayerToGroup() object.DeletePlayerFromGroup(GroupId As Long, playerId As Long) Object GroupId playerId ein gltiges DirectPlay4-Objekt Index der Gruppe, aus der ein Spieler entfernt werden soll. Index des Spielers, der entfernt werden soll.

Die DPSYS_DELETEPLAYERFROMGROUP-Systemnachricht wird erzeugt und informiert alle Spieler ber den Wechsel.

DestroyGroup
DestroyGroup() Lscht eine Gruppe aus einer Session. DirectPlay4.CreateGroup()

520

DirectPlay-Methoden

DestroyGroup() object.DestroyGroup(GroupId As Long) object GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, die gelscht werden soll.

Die DPSYS_DELETEPLAYERFROMGROUP-Systemnachricht wird fr jeden Spieler aus der Gruppe erzeugt. Anschlieend wird die DPSYS_DESTROYPLAYEROR GROUP-Systemnachricht erzeugt.

GetDPEnumGroupPlayers
GetDPEnumGroupPlayers() Erzeugt eine Liste von allen Spielern in einer definierten Gruppe in einer geffneten Session. DirectPlay4.CreatePlayer(), DirectPlay4.DestroyPlayer(), DirectPlay4.AddPlayerToGroup(), DirectPlay4.DeletePlayerFromGroup() GetDPEnumGroupPlayers(GroupId As Long, sessionGuid As String, _ flags As CONST_DPENUMPLAYERFLAGS) As DirectPlayEnumPlayers object GroupId session Guid flags ein gltiges DirectPlay4-Objekt Index der Gruppe, aus der die Spieler ermittelt werden sollen. Eine Guid, welche die Session eindeutig identifiziert. Definiert, welche Spieler aufgelistet werden sollen. DPENUMPLAYERS_LOCAL DPENUMPLAYERS_OWNER DPENUMPLAYERS_REMOTE DPENUMPLAYERS_SERVERPLAYER DPENUMPLAYERS_SESSION DPENUMPLAYERS_SPECTATOR

GetDPEnumGroups
GetDPEnumGroups() Erzeugt eine Liste aller Gruppen einer Session. Die Gruppen mssen mit der DirectPlay4.CreateGroup()-Methode erzeugt worden sein. Gruppen in Gruppen werden nicht aufgelistet. DirectPlay4.DestroyGroup(), DirectPlay4.GetDPEnumSessions() object.GetDPEnumGroups(sessionGuid As String, _ flags As CONST_DPENUMGROUPFLAGS) As DirectPlayEnumPlayers object ein gltiges DirectPlay4-Objekt

Anhang A Methoden

521

GetDPEnumGroups() session Guid flags Eine Guid, welche die Session eindeutig identifiziert. DPENUMGROUPS_ALL DPENUMGROUPS_LOCAL DPENUMGROUPS_REMOTE DPENUMGROUPS_SESSION DPENUMGROUPS_STAGINGAREA

GetDPEnumGroupsInGroup
GetDPEnumGroupsInGroup() Erzeugt eine Liste aller Second-Level-Gruppen. Damit sind Gruppen gemeint, die in einer Top-Level-Gruppe existieren. Diese Gruppen wurden mit den DirectPlay4.CreateGroupInGroup()- oder DirectPlay4.AddGroupToGroup()-Methoden erzeugt. DirectPlay4.DeleteGroupFromGroup(), DirectPlay4.DestroyGroup() object.GetDPEnumGroupsInGroup(GroupId As Long, sessionGuid As String, _ flags As CONST_DPENUMGROUPFLAGS) As DirectPlayEnumPlayers object GroupId session Guid flags ein gltiges DirectPlay4-Objekt Index der Gruppe, aus der die Second-Level-Gruppen aufgelistet werden sollen. Eine Guid, welche die Session eindeutig identifiziert. DPENUMGROUPS_ALL DPENUMGROUPS_HIDDEN DPENUMGROUPS_LOCAL DPENUMGROUPS_REMOTE DPENUMGROUPS_SESSION DPENUMGROUPS_SHORTCUT DPENUMGROUPS_STAGINGAREA

GetGroupData
GetGroupData() Ermittelt eine anwendungsspezifische Zeichenkette, welche mit der Gruppe verknpft ist. object.GetGroupData(GroupId As Long, flags As CONST_DPGETFLAGS) _ As String Object GroupId ein gltiges DirectPlay4-Objekt Index des Spielers, welcher die Nachricht gesendet hat.

522

DirectPlay-Methoden

GetGroupData() Flags DPGET_LOCAL DPGET_REMOTE

GetGroupFlags
GetGroupFlags() Ermittelt die Flag-Beschreibungen einer definierten Gruppe. DirectPlay4.CreateGroup() object.GetGroupFlags(GroupId As Long) As Long Object ein gltiges DirectPlay4-Objekt

GetGroupLongName
GetGroupLongName() Ermittelt den Long-Namen (Hausnamen) einer Gruppe. object.GetGroupLongName(GroupId As Long) As String Object GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, von welcher der Name ermittelt werden soll.

GetGroupShortName
GetGroupLongName() Ermittelt den Short-Namen (Rufnamen) einer Gruppe. object.GetGroupShortName(GroupId As Long) As String Object GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, von welcher der Name ermittelt werden soll.

GetGroupOwner
GetGroupOwner() Ermittelt den Eigentmer einer definierten Gruppe. Der Eigentmer einer Gruppe wurde mit der DirectPlay4.SetGroupOwner()-Methode gesetzt. object.GetGroupOwner(GroupId As Long) As Long Object GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, von welcher der Eigentmer ermittelt werden soll.

Die Methode ist nur fr eine Lobby-Session gltig.

Anhang A Methoden

523

GetGroupParent
GetGroupParent() Ermittelt die Kennung einer Gruppe, welche die definierte Gruppe beinhaltet. DirectPlay4.CreateGroupInGroup() object.GetGroupParent(GroupId As Long) As Long object GroupId ein gltiges DirectPlay4-Objekt Index der Gruppe, fr welche die Top-Level-Gruppe ermittelt werden soll.

SetGroupData
SetGroupData() Setzt einen spezifizierten Datenblock fr eine Gruppe. Nur der Computer der die Gruppe erzeugt hat, kann den Datenblock ndern. DirectPlay4.GetGroupData() object.SetGroupData(GroupId As Long, data As String, _ flags As CONST_DPSETFLAGS) object GroupId data ein gltiges DirectPlay4-Objekt Index der Gruppe, von welcher der Datenblock gendert werden soll. Datenblock der gesetzt werden soll. DPGETCAPS_DEFAULT DPGETCAPS_GUARANTEED Ist der Data-Parameter eine leere Zeichenkette, so wird der Datenblock der Gruppe gelscht.

SetGroupName
SetGroupName() Setzt den Rufnamen sowie den Hausnamen einer Gruppe. Die Gruppe muss zuvor erzeugt worden sein. DirectPlay4.GetGroupLongName(), DirectPlay4.GetGroupShortName(), DirectPlay4.Send() object.SetGroupName(GroupId As Long, friendlyName As String, _ formalName As String, flags As CONST_DPSETFLAGS) Object GroupId Friendly Name ein gltiges DirectPlay4-Objekt Index der Gruppe, deren Namen gendert werden sollen. Rufname

524

DirectPlay-Methoden

SetGroupName() FormalName Flags Hausname DPSET_GUARANTEED DPSET_LOCAL DPSET_REMOTE

SetGroupOwner
SetGroupOwner() Setzt den Eigentmer einer Gruppe. Dies Methode kann nur in einer Lobby-Session eingesetzt werden. DirectPlay4.GetGroupOwner() object.SetGroupOwner(GroupId As Long, ownerId As Long) object GroupId ownerId ein gltiges DirectPlay4-Objekt Index der Gruppe, fr welche ein neuer Eigentmer festgelegt werden soll. Index des Spielers, der als neuer Eigentmer der Gruppe gltig sein soll.

A.6.2

DirectPlayEnumConnections
Die DirectPlayEnumConnections-Klasse erzeugt Listen ber die bestehenden Verbindungen. Anwendungen nutzen diese Klasse, um Informationen ber die Verbindungen zu erhalten. Das DirectPlayEnumConnections-Objekt wird mit der DirectPlay4.GetDPEnumConnections()-Methode erzeugt. Folgende Methoden gehren zu der DirectPlayEnumConnections-Klasse:
Auflistung GetAddress GetCount GetFlags GetGuid GetName

GetAddress
GetAddress() Ermittelt ein Address-Objekt vom Auflistungsobjekt. object.GetAddress(index As Long) As DirectPlayAddress Object ein gltiges DirectPlayEnumConnections-Objekt

Anhang A Methoden

525

GetAddress() Index Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll.

GetCount
GetCount() Ermittelt die Anzahl der Elemente im Auflistungsobjekt. object.GetCount() As Long Object ein gltiges DirectPlayEnumConnections-Objekt

GetFlags
GetFlags() Ermittelt die Flags fr eine aufgelistete Verbindung aus dem Auflistungsobjekt. object.GetFlags(index As Long) As Long Object Index ein gltiges DirectPlayEnumConnections-Objekt Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll.

Der Rckgabewert ist identisch mit den Flags, die zusammen mit der DirectPlay4.GetDPEnumConnections()-Methode bergeben wurden.

GetGuid
GetGuid() Ermittelt die Guid einer Verbindung aus dem Auflistungsobjekt. object.GetGuid(index As Long) as String Object Index ein gltiges DirectPlayEnumConnections-Objekt Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll.

GetName
GetName() Ermittelt den Namen einer Verbindung aus dem Auflistungsobjekt. object.GetName(index As Long) As String Object ein gltiges DirectPlayEnumConnections-Objekt

526

DirectPlay-Methoden

GetName() Index Element aus dem Auflistungsobjekt, von welchem die Information ermittelt werden soll.

A.6.3

DirectPlayEnumLocalApplications
Die DirectPlayEnumLocalApplications-Klasse erzeugt eine Liste mit lokalen Anwendungen. Anwendungen nutzen diese Klasse, um Informationen ber die lokalen Anwendungen zu erhalten. Das DirectPlayEnumLocalApplications-Objekt wird mit der DirectPlay-Lobby3. GetDPEnumLocalApplications()-Methode erzeugt. Folgende Methoden gehren zu der DirectPlayEnumLocalApplications-Klasse:
Auflistung GetCount GetGuid GetName

GetCount
GetCount() Ermittelt die Anzahl der Elemente im DirectPlayEnumLocalApplications-Objekt. object.GetCount() As Long Object ein gltiges DirectPlayEnumLocalApplications-Objekt

GetGuid
GetGuid() Ermittelt die Guid eines definierten Elementes aus dem DirectPlayEnumLocalApplications-Objekt. object.GetItem(index As Long) as String Object Index ein gltiges DirectPlayEnumLocalApplications-Objekt Element aus dem DirectPlayEnumLocalApplications-Objekt, von welchem die Guid ermittelt werden soll.

Anhang A Methoden

527

GetName
GetName() Ermittelt den Namen eines definierten Elementen aus dem DirectPlayEnumLocalApplications-Objekt. object.GetItem(index As Long) as String Object Index ein gltiges DirectPlayEnumLocalApplications-Objekt Element aus dem DirectPlayEnumLocalApplications-Objekt, von welchem die Information ermittelt werden soll.

A.6.4

DirectPlayEnumPlayers
Die DirectPlayEnumPlayers-Klasse erzeugt eine Liste mit Spielern oder Gruppen einer Session oder Gruppe. Anwendungen nutzen diese Klasse, um Informationen ber Spieler oder Gruppen zu erhalten. Das DirectPlayEnumPlayer-Objekt wird von folgenden Methoden erzeugt:
DirectPlay4.GetDPEnumGroups() DirectPlay4.GetDPEnumGroupsInGroup() DirectPlay4.GetDPEnumGroupPlayers() DirectPlay4.GetDPEnumPlayers()

Folgende Methoden gehren zu der DirectPlayEnumPlayers-Klasse: Auflistung


GetCount GetDPID GetFlags GetLongName GetShortName GetType

GetCount
GetCount() Ermittelt die Anzahl der Elemente in dem DirectPlayEnumPlayer-Objekt. object.GetCount() As Long Object ein gltiges DirectPlayEnumPlayers-Objekt

528

DirectPlay-Methoden

GetDPID
GetDPID() Ermittelt eine numerische Identifizierung eines Spielers oder einer Gruppe. object.GetDPID(index As Long) As Long Object Index ein gltiges DirectPlayEnumPlayers-Objekt ein Element aus dem DirectPlayEnumPlayer-Objekt

GetFlags
GetFlags() Ermittelt unterschiedlichste Informationen ber einen gelisteten Spieler oder Gruppe. DirectPlay4.GetDPEnumGroups(), DirectPlay4.GetDPEnumGroupsInGroup(), DirectPlay4.GetDPEnumPlayers(), DirectPlay4.GetDPEnumGroupPlayers() object.GetFlags(index As Long) As Long object index ein gltiges DirectPlayEnumPlayers-Objekt ein Element aus dem DirectPlayEnumPlayer-Objekt

GetLongName
GetLongName() Ermittelt den Hausnamen (Long) von einem Spieler oder einer Gruppe. object.GetLongName(index As Long) As String Object Index ein gltiges DirectPlayEnumPlayers-Objekt ein Element aus dem DirectPlayEnumPlayer-Objekt

GetShortName
GetShortName() Ermittelt den Rufnamen (Short) von einem Spieler oder einer Gruppe. object.GetShortName(index As Long) As String Object Index ein gltiges DirectPlayEnumPlayers-Objekt ein Element aus dem DirectPlayEnumPlayer-Objekt

Anhang A Methoden

529

GetType
GetType() Prft, ob ein Element aus dem DirectPlayEnumPlayer-Objekt ein Spieler oder eine Gruppe ist. object.GetType(index As Long) As Long Object Index ein gltiges DirectPlayEnumPlayers-Objekt ein Element aus dem DirectPlayEnumPlayer-Objekt

Ist der Rckgabewert DPPLAYERTYPE_GROUP handelt es sich um eine Gruppe. Bei einem Spieler ist der Rckgabewert DPPLAYERTYPE_PLAYER

A.6.5

DirectPlayEnumSessions
Die DirectPlayEnumSession-Klasse erzeugt eine Liste mit alle aktiven Sessions. Anwendungen nutzen diese Klasse, um Informationen ber die Sessions zu erhalten. Das DirectPlayEnumSessions-Objekt wird mit der DirectPlay4.GetDPEnum Sessions()-Methode erzeugt. Folgende Methoden gehren zu der DirectPlayEnumSessions-Klasse:
Auflistung GetCount GetItem

GetCount
GetCount() Ermittelt die Anzahl der Elemente in dem DirectPlayEnumSessions-Objekt. object.GetType(index As Long) As Long Object ein gltiges DirectPlayEnumSessions-Objekt

GetItem
GetItem() Erzeugt ein DirectPlaySessionData Objekt, welches mit den reprsentativen Informationen der Session gefllt ist. object.GetType(index As Long) As Long Object Index ein gltiges DirectPlayEnumSessions-Objekt ein Element aus dem DirectPlayEnumSession-Objekt

530

DirectPlay-Methoden

A.6.6

DirectPlayLobby3
Anwendungen nutzen die Methoden der DirectPlayLobby3-Klasse, um Anwendungen und deren Daten zu managen. Das DirectPlayLobby3 Objekt wird mit der DirectX7.DirectPlayLobbyCreate()Methode erzeugt. Folgende Methoden gehren zu der DirectPlayEnumSessions-Klasse:
Adresse CreateComPortAddress CreateCustomAddress CreateInetAddress CreateIPXAddress CreateLobbyProviderAddress CreateModemAddress CreateServiceProviderAddress GetModemCount GetModemName Connect GetDPEnumLocalApplications RegisterApplication RunApplication UnregisterApplication WaitForConnectionSettings CreateMessage ReceiveLobbyMessage SendLobbyMessage SetLobbyMessageEvent CreateConnectionData GetConnectionSettings SetConnectionSettings

Anwendung

Nachrichten

Verbindung

CreateComPortAdress
CreateComPortAdress() Erzeugt eine DirectPlay-Adresse fr den Com Port. object.CreateComPortAddress(port As Long, baudRate As Long, _ stopBits As Long, parity As Long, flowcontrol As Long) As DirectPlayAddress Object Port ein gltiges DirectPlayLobby3-Objekt Nummer des Com-Ports: 1, 2, 3 oder 4

Anhang A Methoden

531

CreateComPortAdress() baudRate Mgliche Werte: 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000 Anzahl der Stop-Bits 0 (1 Stop-Bit), 1 (1,5 Stop-Bits), 2 (2 Stop-Bits) 0 1 2 3 0 1 2 3 4 No parity Odd parity Even parity Mark parity No flow control Software flow control (xon/xoff) Hardware flow control mit RTS Hardware flow control mit DTR Hardware flow control mit RTS und DTR

StopBits Parity

flow control

CreateCustomAddress
CreateCustomAddress() Erzeugt eine DirectPlay-Adresse fr eine von anderen Modellen nicht untersttztes Format. object.CreateCustomAddress(size As Long, data As Any) As DirectPlayAddress Object Size Data ein gltiges DirectPlayLobby3-Objekt Gre der Daten Daten fr das DirectPlayAddress-Objekt

CreateInetAddress
CreateInetAddress() Erzeugt eine DirectPlay-Adresse fr eine Internetadresse. object.CreateINetAddress(addr As String, port As Long) As DirectPlayAddress Object Addr Port ein gltiges DirectPlayLobby3-Objekt IP-Adresse (z.B. 193.168.0.1) oder (LightDesk.de) Tor fr die Verbindung. Der voreingestellte Port ist TCP/IP mit dem Wert 0.

532

DirectPlay-Methoden

CreateIPXAddress
CreateIPXAddress() Erzeugt eine DirectPlay-Adresse fr einen IPX-Service Provider. object.CreateIPXAddress() As DirectPlayAddress Object ein gltiges DirectPlayLobby3-Objekt

CreateLobbyProviderAddress
CreateLobbyProviderAddress() Erzeugt eine DirectPlay-Adresse fr einen Lobby Provider. object.CreateLobbyProviderAddress( guid As String) As DirectPlay Address Object Guid ein gltiges DirectPlayLobby3-Objekt Kennung fr den Lobby-Provider.

CreateModemAddress
CreateModemAddress() Erzeugt eine DirectPlay-Adresse fr ein Modem. object.CreateModemAddress( modem As String, _ phone as String) As DirectPlayAddress Object Modem Phone ein gltiges DirectPlayLobby3-Objekt Name des Modems Telefonnummer

Der Name des Modems kann mit der DirectPlayLobby3.GetModemName()-Methode ermittelt werden.

CreateServiceProviderAddress
CreateServiceProviderAddress() Erzeugt eine DirectPlay-Adresse fr einen Service-Provider. object.CreateServiceProviderAddress( guid as String) As _ DirectPlayAddress Object Guid ein gltiges DirectPlayLobby3-Objekt Kennung fr den Service-Provider

Anhang A Methoden

533

GetModemCount
GetModemCount() Ermittelt die Anzahl der Modems, welche fr das System zur Verfgung steht. object.GetModemCount() As Long Object ein gltiges DirectPlayLobby3-Objekt

GetModemName
GetModemName() Ermittelt den Namen eines Modems. object.GetModemName(index As Long) As String Object Index ein gltiges DirectPlayLobby3-Objekt Index fr ein Modem. Der Wertebereich liegt zwischen 1 und DirectPlayLobby3.GetModemCount().

Connect
Connect() Verbindet eine Anwendung mit einer Session. object.Connect(flags As Long) As DirectPlay4 Object Flags ein gltiges DirectPlayLobby3-Objekt eine Konstante aus der CONST_DPCONNECTFLAGS-Liste

GetDPEnumLocalApplications
GetDPEnumLocalApplications() Erzeugt eine Liste von Anwendungen, die mit DirectPlay registriert sind. object.GetDPEnumLocalApplications() As _ DirectPlayEnumLocalApplications Object ein gltiges DirectPlayLobby3-Objekt

RegisterApplication
RegisterApplication() Registriert eine Lobby-Aware-Anwendung mit DirectPlay. DirectPlayLobby3.UnregisterApplication()

534

DirectPlay-Methoden

RegisterApplication() object.RegisterApplication( ApplicationInfo As DPAPPLICATIONDESC2) Object ApplicationInfo ein gltiges DirectPlayLobby3-Objekt Ein DPAPPLICATIONDESC2 Typen-Array, welches die Anwendung beschreibt, die registriert werden soll.

Eine Anwendung muss registriert sein, damit sie von einer DirectPlay-Lobby gestartet werden kann. Eine Anwendung muss nur einmal registriert werden. Wenn die Anwendung deinstalliert wird, so muss die Registrierung der Anwedung gelscht werden.

RunApplication
RunApplication() Startet eine registrierte Anwendung und bermittelt alle Informationen, welche bentigt werden, um die Verbindung zu einer Session herzustellen. DirectPlayLobby3.GetConnectionSettings(), DirectX7.CreateEvent() object.RunApplication( connection As DirectPlayLobbyConnection, _ receiveEvent As Long) As Long object connection ein gltiges DirectPlayLobby3 Objekt Ein Interface, welches alle Informationen definiert, die die Anwendung bentigt, um eine Verbindung zu einer Session herzustellen. Handle zu einem Event

receive Event

UnregisterApplication
UnregisterApplication() Lscht die Registrierungseintrge von einer DirectPlay-Anwendung. DirectPlayLobby3.RegisterApplication() object.UnregisterApplication(GuidApplication As String) object Guid Application ein gltiges DirectPlayLobby3-Objekt Kennung der Anwendung, deren Registrierung gelscht werden soll.

WaitForConnectionsSettings
WaitForConnectionsSettings() Setzt eine Anwendung in den Wartezustand. object.WaitForConnectionSettings(flags As CONST_DPLWAIT)

Anhang A Methoden

535

WaitForConnectionsSettings() object flags ein gltiges DirectPlayLobby3-Objekt DPLWAIT_CANCEL DPLWAIT_DEFAULT

CreateMessage
CreateMessage() Erzeugt eine Lobby-Nachricht. object.CreateMessage() As DirectPlayMessage object ein gltiges DirectPlayLobby3-Objekt

ReceiveLobbyMessage
ReceiveLobbyMessage() Empfngt Lobby-Nachrichten, welche zwischen den Lobby-Clients versendet werden. DirectPlayLobby3.ReceiveLobbyMessage(), DirectPlayLobby3.SendLobbyMessage() object.ReceiveLobbyMessage(applicationId As Long, _ messageFlags As Long) As DirectPlayMessage object applicationId messageFlags ein gltiges DirectPlayLobby3-Objekt Kennung der Anwendung, von welcher die Nachricht gesendet wurde. DPLMSG_STANDARD DPLMSG_SYSTEM DPLMSG_USERDEFINED

SendLobbyMessage
SendLobbyMessage() Sendet eine Lobby-Nachricht zwischen der Anwendung und den Lobby-Clients. DirectPlayLobby3.ReceiveLobbyMessage() object.SendLobbyMessage(flags As CONST_DPLMSG, _ applicationId As Long, msg As DirectPlayMessage) object flags ein gltiges DirectPlayLobby3-Objekt DPLMSG_STANDARD DPLMSG_SYSTEM DPLMSG_USERDEFINED

536

DirectPlay-Methoden

SendLobbyMessage() applicationId msg Kennung der Anwendung, welche die Nachricht sendet. Nachricht

SetLobbyMessageEvent
SetLobbyMessageEvent() Registriert ein Event-Handling, welches gesetzt wird, wenn die Lobby-Nachricht eintrifft. DirectPlayLobby3.ReceiveLobbyMessage(), DirectPlayLobby3.SendLobbyMessage(), DirectX7.CreateEvent() object.SetLobbyMessageEvent(applicationId As Long, receiveEvent As Long) object applicationId receiveEvent ein gltiges DirectPlayLobby3-Objekt Kennung der Anwendung, welche die Nachricht sendet. Handle des Events, welches gesetzt wird, wenn die Nachricht eintrifft.

CreateConnectionData
CreateConnectionData() Erzeugt ein DirectPlayLobbyConnection-Objekt. object.CreateConnectionData() As DirectPlayLobbyConnection object ein gltiges DirectPlayLobby3-Objekt

GetConnectionSettings
GetConnectionSettings () Empfngt ein DirectPlayLobbyConnection-Objekt, welches die Informationen beinhaltet, die zum Starten und zum Verbinden der Anwendung bentigt werden. DirectPlayLobby3.WaitForConnectionSettings() object.GetConnectionSettings(applicationId As Long) _ As DirectPlayLobbyConnection object applicationId ein gltiges DirectPlayLobby3-Objekt Identifikation, von welcher Anwendung die Informationen sind.

Anhang A Methoden

537

SetConnectionSettings
SetConnectionSettings () Modifiziert die Verbindungsinformationen einer Anwendung. object.SetConnectionSettings(applicationId As Long, _ connection As DirectPlayLobbyConnection) object applicationId connection ein gltiges DirectPlayLobby3-Objekt Kennung der Anwendung modifizierte Daten

A.6.7

DirectPlayLobbyConnection
Anwendungen nutzen die Methoden der DirectPlayLobbyConnection-Klasse um Informationen zu managen, welche fr die Verbindung einer Anwendung mit einer Session bentigt werden. Das DirectPlayLobbyConnection-Objekt wird mit den DirectPlayLobby3.CreateConnectionData()- und DirectPlayLobby3.GetConnectionSettings()-Methoden erzeugt. Folgende Methoden gehren zu der DirectPlayLobbyConnection-Klasse:
Erhalten GetAddress GetFlags GetGuidSP GetPlayerLongName GetPlayerShortName GetSessionDesc SetAddress SetFlags SetGuidSP SetPlayerLongName SetPlayerShortName SetSessionDesc

Setzen

GetAddress
GetAddress() Ermittelt DirectPlay Adresse. object.GetAddress() As DirectPlayAddress

538

DirectPlay-Methoden

GetAddress() object ein gltiges DirectPlayLobbyConnection-Objekt

GetFlags
GetFlags() Ermittelt Informationen, wie die Session geffnet wurde. object.GetFlags() As Long object ein gltiges DirectPlayLobbyConnection-Objekt

Die Rckgabewerte knnen sein: DPLCONNECTION_CREATESESSION DPLCONNECTION_JOINSESSION

GetGuidSP
GetGuidSP() Ermittelt die Guid des Service Providers, welcher fr die Verbindung mit der Session verwendet wurde. object.GetGuidSP() As String object ein gltiges DirectPlayLobbyConnection-Objekt

GetPlayerLongName
GetPlayerLongName() Ermittelt den Hausnamen (Long) eines Spielers. DirectPlayLobbyConnection.SetPlayerLongName() object.GetPlayerLongName() As String object ein gltiges DirectPlayLobbyConnection-Objekt

GetPlayerShortName
GetPlayerShortName() Ermittelt den Rufnamen (Short) eines Spielers. DirectPlayLobbyConnection.SetPlayerShortName() object.GetPlayerShortName() As String object ein gltiges DirectPlayLobbyConnection-Objekt

Anhang A Methoden

539

GetSessionDesc
GetSessionDesc() Ermittelt die Beschreibung einer Session. DirectPlay4.Open(), DirectPlay4.SecureOpen(), DirectPlay4.SetSessionDesc() object.GetSessionDesc() As DirectPlaySessionData object ein gltiges DirectPlayLobbyConnection-Objekt

SetAddress
SetAddress() Setzt die DirectPlay Adresse, welche der Service Provider bentigt, um eine Verbindung mit der Session herzustellen. object.SetAddress(address As DirectPlayAddress) object address ein gltiges DirectPlayLobbyConnection-Objekt DirectPlayAddress-Objekt

SetFlags
SetFlags() Indiziert, wie eine Session geffnet werden soll. object.SetFlags(flags As CONST_DPLCONNECTIONFLAGS) object flags ein gltiges DirectPlayLobbyConnection-Objekt DPLCONNECTION_CREATESESSION DPLCONNECTION_JOINSESSION

SetGuidSP
SetGuidSP() Setzt die Guid fr den Service Provider. object.SetGuidSP(guid As String) object guid ein gltiges DirectPlayLobbyConnection-Objekt DPSPGUID_IPX DPSPGUID_TCPIP DPSPGUID_SERIAL DPSPGUID_MODEM

540

DirectPlay-Methoden

SetPlayerLongName
SetPlayerLongName() Setzt den Hausnamen (Long) fr einen Spieler. DirectPlayLobbyConnection.SetPlayerShortName() object.SetPlayerLongName(name As String) object name ein gltiges DirectPlayLobbyConnection-Objekt Hausname

SetPlayerShortName
SetPlayerShortName() Setzt den Rufnamen (Short) fr einen Spieler. DirectPlayLobbyConnection.SetPlayerLongName() object.SetPlayerShortName(name As String) object name ein gltiges DirectPlayLobbyConnection-Objekt Rufname

SetSessionDesc
SetSessionDesc() Setzt die Informationen einer Session, welche bentigt werden um eine Session zu erstellen oder sich einer Session anzuschlieen. object.SetSessionDesc(sessionDesc As DirectPlaySessionData) object sessionDesc ein gltiges DirectPlayLobbyConnection-Objekt Beschreibung der Session

A.6.8

DirectPlayMessage
Anwendungen nutzen die Methoden der DirectPlayMessage-Klasse, um Daten in eine Nachricht zu schreiben oder Daten aus einer Nachricht zu lesen. Das DirectPlayMessage-Objekt wird mit der DirectPlay4.CreateMessage()Methode erzeugt. Das DirectPlayMessage-Objekt wird mit der DirectPlay4. Receive()- oder DirectPlayLobby3.ReceiveLobbyMessage()-Methode empfangen. Alle Systemnachrichten beinhalten als erstes Element einen Long-Eintrag. Dieser dient zur Identifizierung des Nachrichtentyps.

Anhang A Methoden

541

Folgende Methoden gehren zu der DirectPlayMessage-Klasse:


Daten lesen GetMessageData MoveToSecureMessage MoveToTop ReadByte ReadDouble ReadGuid ReadLong ReadShort ReadSingle ReadString ReadSysChatString ReadSysMsgConnection ReadSysMsgData ReadSysMsgSessionDesc SetMessageData WriteByte WriteDouble WriteGuid WriteLong WriteShort WriteSingle WriteString Clear GetMessageSize

Daten schreiben

Verschiedenes

GetMessageData
GetMessageData() Ermittelt unformatierte (raw) Daten einer Nachricht. object.GetMessageData(userDefinedType As Any) object userDefined Type ein gltiges DirectPlayMessage-Objekt Definition, wie die Daten interpretiert werden sollen.

MoveToSecureMessage
MoveToSecureMessage() Setzt den Lesezeiger an den Anfang der gesicherten Nachrichten. object.MoveToSecureMessage() object ein gltiges DirectPlayMessage-Objekt

542

DirectPlay-Methoden

MoveToTop
MoveToTop() Setzt den Lesezeiger an den Anfang der Nachrichtenwarteschlange. object.MoveToTop() object ein gltiges DirectPlayMessage-Objekt

ReadByte
ReadByte() Liest ein Byte von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadByte() As Byte object ein gltiges DirectPlayMessage-Objekt

ReadDouble
ReadDouble() Liest ein Double von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadDouble() As Double object ein gltiges DirectPlayMessage-Objekt

ReadGuid
ReadGuid() Liest die Guid von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadGuid() As String object ein gltiges DirectPlayMessage-Objekt

ReadLong
ReadLong() Liest einen Long von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadLong() As Long object ein gltiges DirectPlayMessage-Objekt

Anhang A Methoden

543

ReadShort
ReadShort() Liest einen Short von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadShort() As Integer object ein gltiges DirectPlayMessage-Objekt

ReadSingle
ReadSingle() Liest einen Single von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadSingle() As Single object ein gltiges DirectPlayMessage-Objekt

ReadString
ReadString() Liest einen String von der Nachricht und setzt den Lesezeiger auf den nchsten Eintrag. object.ReadString() As String object ein gltiges DirectPlayMessage-Objekt

ReadSysChatString
ReadSysChatString() Liest einen String der DPSYS_CHAT-Nachricht. object.ReadSysChatString() As String object ein gltiges DirectPlayMessage-Objekt

ReadSysMsgConnection
ReadSysMsgConnection() Fllt ein DirectPlayLobbyConnections-Objekt von einer DPSYS_STARTSESSION Nachricht. object.ReadSysMsgConnection() As DirectPlayLobbyConnection object ein gltiges DirectPlayMessage-Objekt

544

DirectPlay-Methoden

ReadSysMsgData
ReadMsgData() Empfngt einen String von der DPSYS_CREATEPLAYERORGROUP- oder DPSYS_ DESTROYPLAYERORGROUP- oder DPSYS_SETPLAYERORGROUPDATANachricht. object.ReadSysMsgData() As String object ein gltiges DirectPlayMessage-Objekt

ReadSysMsgSessionDesc
ReadSysMsgSessionDesc() Fllt ein DirectPlaySessionData-Objekt mit Informationen aus einer DPSYS_SETSESSIONDESC-Systemnachricht. object.ReadSysMsgSessionDesc() As DirectPlaySessionData object ein gltiges DirectPlayMessage-Objekt

SetMessageData
SetMessageData() Schreibt einen selbst definierten Datenblock in das DirectPlayMessage-Objekt. object.SetMessageData(userDefinedType As Any, size As Long) object user DefinedType size ein gltiges DirectPlayMessage-Objekt Datenblock Gre des Datenblocks

WriteByte
WriteByte() Schreibt ein Byte in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteByte(val As Byte) object val ein gltiges DirectPlayMessage-Objekt Wert

Anhang A Methoden

545

WriteDouble
WriteDouble() Schreibt einen Double in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteDouble(val As Double) object val ein gltiges DirectPlayMessage-Objekt Wert

WriteGuid
WriteGuid() Schreibt die Guid in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteGUID(val As String) object val ein gltiges DirectPlayMessage-Objekt Guid

WriteLong
WriteLong() Schreibt einen Long in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteLong(val As Long) object val ein gltiges DirectPlayMessage-Objekt Wert

WriteShort
WriteShort() Schreibt einen Short in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteShort(val As Integer) object val ein gltiges DirectPlayMessage-Objekt Wert

546

DirectPlay-Methoden

WriteSingle
WriteSingle() Schreibt einen Single in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteSingle(val As Single) object val ein gltiges DirectPlayMessage-Objekt Wert

WriteString
WriteString() Schreibt eine Zeichenkette in das DirectPlayMessage-Objekt und setzt den Schreibpositonszeiger auf den nchsten Eintrag. object.WriteString(val As String) object val ein gltiges DirectPlayMessage-Objekt Zeichenkette

Clear
Clear() Lscht alle Daten aus dem DirectPlayMessage-Objekt. object.Clear() object ein gltiges DirectPlayMessage-Objekt

GetMessageSize
GetMessageSize() Ermittelt die Gre einer Nachricht. object.GetMessageSize() As Long object ein gltiges DirectPlayMessage-Objekt

A.6.9

DirectPlaySessionData
Die Methoden der DiretPlaySessionData-Klasse enthalten beschreibende Daten, welche mit einer Session verbunden sind.

Anhang A Methoden

547

Das DirectPlaySessionData Objekt wird mit der DirectPlay4.CreateSessionData()-Methode erzeugt und wird an die DirectPlay4.Open()- sowie Direct Play4.SecureOpen()-Methode bergeben. Folgende Methoden gehren zu der DirectPlayMessage-Klasse:
Daten ermitteln GetCurrentPlayers GetFlags GetGuidApplication GetGuidInstance GetMaxPlayers GetSessionName GetSessionPassword GetUser1 GetUser2 GetUser3 GetUser4 SetFlags SetGuidApplication SetGuidInstance SetMaxPlayers SetSessionName SetSessionPassword SetUser1 SetUser2 SetUser3 SetUser4

Daten setzen

GetCurrentPlayers
GetCurrentPlayers() Ermittelt die Anzahl der Spieler in der aktuellen Session. object.GetCurrentPlayers() As Long object ein gltiges DirectPlaySessionData-Objekt

GetFlags
GetFlags() Ermittelt die Flags (Kennzeichnungen) der aktuellen Session. object.GetFlags() As Long object ein gltiges DirectPlaySessionData-Objekt

548

DirectPlay-Methoden

GetGuidApplication
GetGuidApplication() Ermitttelt die Guid der Anwendung, welche die Session erzeugt hat. object.GetGuidApplication() As String object ein gltiges DirectPlaySessionData-Objekt

GetGuidInstance
GetGuidInstance() Ermittelt die Guid einer Session. object.GetGuidInstance() As String object ein gltiges DirectPlaySessionData-Objekt

GetMaxPlayers
GetMaxPlayers() Ermittelt die Anzahl der maximal zulssigen Spieler einer Session. object.GetMaxPlayers() As Long object ein gltiges DirectPlaySessionData-Objekt

GetSessionName
GetSessionName() Ermittelt den Namen einer Session. object.GetSessionName() As String object ein gltiges DirectPlaySessionData-Objekt

GetSessionPassword
GetSessionPassword() Ermittelt das Passwort einer Session. object.GetSessionPassword() As String object ein gltiges DirectPlaySessionData-Objekt

Das Passwort wird bentigt, um sich der Session anzuschlieen.

Anhang A Methoden

549

GetUser1
GetUser1() Ermittelt anwendungsbezogene Daten einer Session. object.GetUser1() As Long object ein gltiges DirectPlaySessionData-Objekt

GetUser2
GetUser2() Ermittelt anwendungsbezogene Daten einer Session. object.GetUser2() As Long object ein gltiges DirectPlaySessionData-Objekt

GetUser3
GetUser3() Ermittelt anwendungsbezogene Daten einer Session. object.GetUser3() As Long object ein gltiges DirectPlaySessionData-Objekt

GetUser4
GetUser4() Ermittelt anwendungsbezogene Daten einer Session. object.GetUser4() As Long object ein gltiges DirectPlaySessionData-Objekt

SetFlags
SetFlags() Setzt die Flags (Kennzeichnungen) einer Session. object.SetFlags(val As CONST_DPSESSIONFLAGS) object val ein gltiges DirectPlaySessionData-Objekt Eine Konstante aus der CONST_DPSESSIONFLAGS-Liste

550

DirectPlay-Methoden

SetGuidApplication
SetGuidApplication() Setzt die Guid der Anwendung in die Sessionbeschreibung. object.SetGuidApplication(guid As String) object guid ein gltiges DirectPlaySessionData-Objekt Guid der Anwendung

SetGuidInstance
SetGuidInstance() Setzt die Guid der Session. object.SetGuidInstance(guid As String) object guid ein gltiges DirectPlaySessionData-Objekt Guid der Session

SetMaxPlayers
SetMaxPlayers() Setzt die Anzahl der maximal zulssigen Spieler einer Session. object.SetMaxPlayers(val As Long) object val ein gltiges DirectPlaySessionData-Objekt Anzahl der maximal zulssigen Spieler.

SetSessionName
SetSessionName() Setzt den Session-Namen. object.SetSessionName(val As String) object val ein gltiges DirectPlaySessionData-Objekt Name der Session

SetSessionPassword
SetSessionPassword() Setzt das Session-Passwort. object.SetSessionPassword(val As String)

Anhang A Methoden

551

SetSessionPassword() object val ein gltiges DirectPlaySessionData-Objekt Passwort

SetUser1
SetUser1() Setzt anwendungsbezogene Daten einer Session. object.SetUser1(val As Long) object val ein gltiges DirectPlaySessionData-Objekt Wert

SetUser2
SetUser2() Setzt anwendungsbezogene Daten einer Session. object.SetUser2(val As Long) object val ein gltiges DirectPlaySessionData-Objekt Wert

SetUser3
SetUser3() Setzt anwendungsbezogene Daten einer Session. object.SetUser3(val As Long) object val ein gltiges DirectPlaySessionData-Objekt Wert

SetUser4
SetUser4() Setzt anwendungsbezogene Daten einer Session. object.SetUser4(val As Long) object val ein gltiges DirectPlaySessionData-Objekt Wert

Anhang B
Konstanten
B.1 B.2 B.3 B.4 B.5 DirectDraw Enum Direct3DEnum DirectSoundEnum DirectInput Enum DirectPlay Enum 554 565 583 588 595

554

DirectDraw Enum

B.1
B.1.1

DirectDraw Enum
CONST_DDBITDEPTHFLAGS
Enum CONST_DDBITDEPTHFLAGS DDBD_1 DDBD_16 DDBD_2 DDBD_24 DDBD_32 DDBD_4 DDBD_8 End Enum = = = = = = = 16384 1024 8192 512 256 4096 2048

B.1.2

CONST_DDBLTFASTFLAGS
Verwendung in: DirectDrawSurface7.BltFast()
Enum CONST_DDBLTFASTFLAGS DDBLTFAST_DESTCOLORKEY DDBLTFAST_DONOTWAIT DDBLTFAST_NOCOLORKEY DDBLTFAST_SRCCOLORKEY DDBLTFAST_WAIT End Enum = = = = = 2 32 0 1 16

B.1.3

CONST_DDBLTFLAGS
Verwendung in: DirectDrawSurface7.Blt(), DirectDrawSurface7.BltFx()
Enum CONST_DDBLTFLAGS DDBLT_ASYNC DDBLT_COLORFILL DDBLT_DDFX DDBLT_DDROPS DDBLT_DEPTHFILL DDBLT_DONOTWAIT DDBLT_KEYDEST DDBLT_KEYDESTOVERRIDE DDBLT_KEYSRC DDBLT_KEYSRCOVERRIDE DDBLT_ROP DDBLT_ROTATIONANGLE DDBLT_WAIT End Enum = = = = = = = = = = = = = 512 1024 2048 4096 33554432 134217728 8192 16384 32768 65536 131072 262144 16777216

Anhang B Konstanten

555

B.1.4

CONST_DDBLTFXFLAGS
Verwendung in: DDBLTFX lDDFX
Enum CONST_DDBLTFXFLAGS DDBLTFX_ARITHSTRETCHY DDBLTFX_MIRRORLEFTRIGHT DDBLTFX_MIRRORUPDOWN DDBLTFX_NOTEARING DDBLTFX_ROTATE180 DDBLTFX_ROTATE270 DDBLTFX_ROTATE90 DDBLTFX_ZBUFFERBASEDEST DDBLTFX_ZBUFFERRANGE End Enum = = = = = = = = = 1 2 4 8 16 32 64 256 128

B.1.5

CONST_DDCAPS1FLAGS
Verwendung in: DDCAPS lCaps, lNLVBCaps, lSSBCaps, lSVBCaps, IVSBCaps
Enum CONST_DDCAPS1FLAGS DDCAPS_3D DDCAPS_ALIGNBOUNDARYDEST DDCAPS_ALIGNBOUNDARYSRC DDCAPS_ALIGNSIZEDEST DDCAPS_ALIGNSIZESRC DDCAPS_ALIGNSTRIDE DDCAPS_ALPHA DDCAPS_BANKSWITCHED DDCAPS_BLT DDCAPS_BLTCOLORFILL DDCAPS_BLTDEPTHFILL DDCAPS_BLTFOURCC DDCAPS_BLTQUEUE DDCAPS_BLTSTRETCH DDCAPS_CANBLTSYSMEM DDCAPS_CANCLIP DDCAPS_CANCLIPSTRETCHED DDCAPS_COLORKEY DDCAPS_COLORKEYHWASSIST DDCAPS_GDI DDCAPS_NOHARDWARE DDCAPS_OVERLAY DDCAPS_OVERLAYCANTCLIP DDCAPS_OVERLAYFOURCC DDCAPS_OVERLAYSTRETCH DDCAPS_PALETTE = = = = = = = = = = = = = = = = = = = = = = = = = = 1 2 8 4 16 32 8388608 134217728 64 67108864 268435456 256 128 512 -2147483648 536870912 1073741824 4194304 16777216 1024 33554432 2048 4096 8192 16384 32768

556

DirectDraw Enum

DDCAPS_PALETTEVSYNC DDCAPS_READSCANLINE DDCAPS_VBI DDCAPS_ZBLTS DDCAPS_ZOVERLAYS End Enum

= = = = =

65536 131072 524288 1048576 2097152

B.1.6

CONST_DDCAPS2FLAGS
Enum CONST_DDCAPS2FLAGS DDCAPS2_AUTOFLIPOVERLAY DDCAPS2_CANBOBHARDWARE DDCAPS2_CANBOBINTERLEAVED DDCAPS2_CANBOBNONINTERLEAVED DDCAPS2_CANCALIBRATEGAMMA DDCAPS2_CANDROPZ16BIT DDCAPS2_CANFLIPODDEVEN DDCAPS2_CANMANAGETEXTURE DDCAPS2_CANRENDERWINDOWED DDCAPS2_CERTIFIED DDCAPS2_COLORCONTROLOVERLAY DDCAPS2_COLORCONTROLPRIMARY DDCAPS2_COPYFOURCC DDCAPS2_FLIPINTERVAL DDCAPS2_FLIPNOVSYNC DDCAPS2_NO2DDURING3DSCENE DDCAPS2_NONLOCALVIDMEM DDCAPS2_NONLOCALVIDMEMCAPS DDCAPS2_NOPAGELOCKREQUIRED DDCAPS2_PRIMARYGAMMA DDCAPS2_STEREO DDCAPS2_VIDEOPORT DDCAPS2_WIDESURFACES End Enum = = = = = = = = = = = = = = = = = = = = = = = 8 16384 16 32 1048576 256 8192 8388608 524288 1 64 128 32768 2097152 4194304 2 512 1024 2048 131072 33554432 4 4096

B.1.7

CONST_DDCKEYCAPSFLAGS
Enum CONST_DDCKEYCAPSFLAGS DDCKEYCAPS_DESTBLT DDCKEYCAPS_DESTBLTCLRSPACE DDCKEYCAPS_DESTBLTCLRSPACEYUV DDCKEYCAPS_DESTBLTYUV DDCKEYCAPS_DESTOVERLAY DDCKEYCAPS_DESTOVERLAYCLRSPACE DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV DDCKEYCAPS_DESTOVERLAYONEACTIVE = = = = = = = = 1 2 4 8 16 32 64 128

Anhang B Konstanten

557

DDCKEYCAPS_DESTOVERLAYYUV DDCKEYCAPS_SRCBLT DDCKEYCAPS_SRCBLTCLRSPACE DDCKEYCAPS_SRCBLTCLRSPACEYUV DDCKEYCAPS_SRCBLTYUV DDCKEYCAPS_SRCOVERLAY DDCKEYCAPS_SRCOVERLAYCLRSPACE DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV DDCKEYCAPS_SRCOVERLAYONEACTIVE DDCKEYCAPS_SRCOVERLAYYUV End Enum

= = = = = = = = = =

262144 512 1024 2048 4096 8192 16384 32768 65536 131072

B.1.8

CONST_DDCKEYFLAGS
Enum CONST_DDCKEYFLAGS DDCKEY_COLORSPACE DDCKEY_DESTBLT DDCKEY_DESTOVERLAY DDCKEY_SRCBLT DDCKEY_SRCOVERLAY End Enum = = = = = 1 2 4 8 16

B.1.9

CONST_DDCOLORFLAGS
Enum CONST_DDCOLORFLAGS DDCOLOR_BRIGHTNESS DDCOLOR_COLORENABLE DDCOLOR_CONTRAST DDCOLOR_GAMMA DDCOLOR_HUE DDCOLOR_SATURATION DDCOLOR_SHARPNESS End Enum = = = = = = = 1 64 2 32 4 8 16

B.1.10 CONST_DDDEVICEIDFLAGS
Verwendung in: DirectDraw7.GetDeviceIdentifier()
Enum CONST_DDDEVICEIDFLAGS DDGDI_DEFAULT DDGDI_GETHOSTIDENTIFIER End Enum = 0 = 1

B.1.11 CONST_DDEDMFLAGS
Verwendung in: DirectDraw7.GetDisplayModesEnum()

558

DirectDraw Enum

Enum CONST_DDEDMFLAGS DDEDM_DEFAULT DDEDM_REFRESHRATES DDEDM_STANDARDVGAMODES End Enum

= 0 = 1 = 2

B.1.12 CONST_DDENUMOVERLAYZFLAGS
Verwendung in: DirectDrawSurface7.GetOverlayZOrdersEnum()
Enum CONST_DDENUMSURFACESFLAGS DDENUMOVERLAYZ_BACKTOFRONT DDENUMOVERLAYZ_FRONTTOBACK End Enum = 0 = 1

B.1.13 CONST_DDENUMSURFACESFLAGS
Verwendung in: DirectDraw7.GetSurfacesEnum()
Enum CONST_DDENUMSURFACESFLAGS DDENUMSURFACES_ALL DDENUMSURFACES_CANBECREATED DDENUMSURFACES_DOESEXIST DDENUMSURFACES_MATCH DDENUMSURFACES_NOMATCH End Enum = = = = = 1 8 16 2 4

B.1.14 CONST_DDFLIPFLAGS
Verwendung in: DirectDrawSurface7.Flip()
Enum CONST_DDFLIPFLAGS DDFLIP_DONOTWAIT DDFLIP_EVEN DDFLIP_INTERFVAL2 DDFLIP_INTERFVAL3 DDFLIP_INTERFVAL4 DDFLIP_NOVSYNC DDFLIP_ODD DDFLIP_WAIT DDFLIP_STEREO End Enum = = = = = = = = = 32 2 536870912 805306368 1073741824 8 4 1 16

B.1.15 ONST_DDFXCAPSFLAGS
Verwendung in: DDCAPS lFXCaps, lNLVBFXCaps, lSSBFXCaps, lSVBFXCaps, lVSBFXCaps

Anhang B Konstanten

559

Enum CONST_DDFXCAPSFLAGS DDFXCAPS_BLTALPHA DDFXCAPS_BLTARITHSTRETCHY DDFXCAPS_BLTARITHSTRETCHYN DDFXCAPS_BLTFILTER DDFXCAPS_BLTMIRRORLEFTRIGHT DDFXCAPS_BLTMIRRORUPDOWN DDFXCAPS_BLTROTATION DDFXCAPS_BLTROTATION90 DDFXCAPS_BLTSHRINKX DDFXCAPS_BLTSHRINKXN DDFXCAPS_BLTSHRINKY DDFXCAPS_BLTSHRINKYN DDFXCAPS_BLTSTRETCHX DDFXCAPS_BLTSTRETCHXN DDFXCAPS_BLTSTRETCHY DDFXCAPS_BLTSTRETCHYN DDFXCAPS_BLTTRANSFORM DDFXCAPS_OVERLAYALPHA DDFXCAPS_OVERLAYARITHSTRETCHY DDFXCAPS_OVERLAYARITHSTRETCHYN DDFXCAPS_OVERLAYFILTER DDFXCAPS_OVERLAYMIRRORLEFTRIGHT DDFXCAPS_OVERLAYMIRRORUPDOWN DDFXCAPS_OVERLAYSHRINKX DDFXCAPS_OVERLAYSHRINKXN DDFXCAPS_OVERLAYSHRINKY DDFXCAPS_OVERLAYSHRINKYN DDFXCAPS_OVERLAYSTRETCHX DDFXCAPS_OVERLAYSTRETCHXN DDFXCAPS_OVERLAYSTRETCHY DDFXCAPS_OVERLAYSTRETCHYN DDFXCAPS_OVERLAYTRANSFORM End Enum

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

1 32 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 2 4 262144 8 262144 134217728 268435456 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864 536870912

B.1.16 CONST_DDGBSFLAGS
Verwendung in: DirectDrawSurface7.GetBltStatus()
Enum CONST_DDGBSFLAGS DDGBS_CANBLT DDGBS_ISBLTDONE End Enum = 1 = 2

B.1.17 CONST_DDGFSFLAGS
Verwendung in: DirectDrawSurface7.GetFlipStatus()

560

DirectDraw Enum

Enum CONST_DDGFSFLAGS DDGFS_CANFLIP DDGFS_ISFLIPDONE End Enum

= 1 = 2

B.1.18 CONST_DDLOCKFLAGS
Verwendung in: DirectDrawSurface7.Lock(), Direct3DVertexBuffer7.Lock()
Enum CONST_DDLOCKFLAGS DDLOCK_DONOTWAIT DDLOCK_EVENT DDLOCK_NOSYSLOCK DDLOCK_READONLY DDLOCK_SURFACEMEMORYPTR DDLOCK_WAIT DDLOCK_WRITEONLY End Enum = = = = = = = 16384 2 2048 16 0 1 32

B.1.19 CONST_DDOVERFLAGS
Verwendung in: DirectDrawSurface7.UpdateOverlay()
Enum CONST_DDOVERFLAGS DDOVER_ADDDIRTYRECT DDOVER_ALPHADEST DDOVER_ALPHADESTCONSTOVERRIDE DDOVER_ALPHADESTNEG DDOVER_ALPHADESTSURFACEOVERRIDE DDOVER_ALPHAEDGEBLEND DDOVER_ALPHASRC DDOVER_ALPHASRCCONSTOVERRIDE DDOVER_ALPHASRCNEG DDOVER_ALPHASRCSURFACEOVERRIDE DDOVER_ARGBSCALEFACTORS DDOVER_AUTOFLIP DDOVER_BOB DDOVER_DDFX DDOVER_DEGRADEARGBSCALING DDOVER_HIDE DDOVER_INTERLEAVED DDOVER_KEYDEST DDOVER_KEYDESTOVERRIDE DDOVER_KEYSRC DDOVER_KEYSRCOVERRIDE DDOVER_OVERRIDEBOBWEAVE DDOVER_REFRESHALL DDOVER_REFRESHDIRTYRECTS = = = = = = = = = = = = = = = = = = = = = = = = 32768 1 2 4 8 16 32 64 128 256 33554432 1048576 2097152 524288 67108864 512 8388608 1024 2048 4096 8192 4194304 131072 65536

Anhang B Konstanten

561

DDOVER_SHOW End Enum

= 16384

B.1.20 CONST_DDOVERFXFLAGS
Verwendung in: DDOVERLAYFX
Enum CONST_DDPALFLAGS DDOVERFX_ARITHSTRETCHY DDOVERFX_MIRRORLEFTRIGHT DDOVERFX_MIRRORUPDOWN End Enum = 1 = 2 = 4

B.1.21 CONST_DDOVERZFLAGS
Verwendung in: DirectDrawSurface7.UpdateOverlayZOrder()
Enum CONST_DDPALFLAGS DDOVERZ_INSERTINBACKOF DDOVERZ_INSERTINFRONTOF DDOVERZ_MOVEBACKWARD DDOVERZ_MOVEFORWARD DDOVERZ_SENDTOBACK DDOVERZ_SENDTOFRONT End Enum = = = = = = 5 4 3 2 1 0

B.1.22 CONST_DDPALFLAGS
Verwendung in: PALETTEENTRY
Enum CONST_DDPALFLAGS PC_DEFAULT PC_EXPLICIT PC_NOCOLLAPSE PC_RESERVED End Enum = = = = 0 2 4 1

B.1.23 CONST_DDPCAPSFLAGS
Verwendung in: DirectDraw7.CreatePalette(), DirectDrawPalette.GetCaps(), DCAPS lPalCaps
Enum CONST_DDPCAPSFLAGS DDPCAPS_1BIT DDPCAPS_2BIT DDPCAPS_4BIT DDPCAPS_8BIT = = = = 256 512 1 4

562

DirectDraw Enum

DDPCAPS_8BITENTRIES DDPCAPS_ALLOW256 DDPCAPS_ALPHA DDPCAPS_INITIALIZE DDPCAPS_PRIMARYSURFACE DDPCAPS_PRIMARYSURFACELEFT DDPCAPS_VSYNC End Enum

= = = = = = =

2 64 1024 8 16 32 128

B.1.24 CONST_DDPIXELFORMATFLAGS
Verwendung in: DDPIXELFORMAT
Enum CONST_DDPIXELFORMATFLAGS DDPF_ALPHA DDPF_ALPHAPIXELS DDPF_ALPHAPREMULT DDPF_BUMPDUDV DDPF_BUMPLUMINANCE DDPF_COMPRESSED DDPF_FOURCC DDPF_LUMINANCE DDPF_PALETTEINDEXED1 DDPF_PALETTEINDEXED2 DDPF_PALETTEINDEXED4 DDPF_PALETTEINDEXED8 DDPF_PALETTEINDEXEDTO8 DDPF_RGB DDPF_RGBTOYUV DDPF_STENCILBUFFER DDPF_YUV DDPF_ZBUFFER DDPF_ZPIXELS End Enum = = = = = = = = = = = = = = = = = = = 2 1 32768 524288 262144 128 4 131072 2048 4096 8 32 16 64 256 16384 512 1024 8192

B.1.25 CONST_DDRAW
Enum CONST_DDRAW DD_ROP_SPACE End Enum = 8

B.1.26 CONST_DDSCLFLAGS
Verwendung in: DirectDraw7.SetCooperativeLevel()
Enum CONST_DDSCLFLAGS

Anhang B Konstanten

563

DDSCL_ALLOWMODEX DDSCL_ALLOWREBOOT DDSCL_CREATEDEVICEWINDOW DDSCL_EXCLUSIVE DDSCL_FULLSCREEN DDSCL_MULTITHREADED DDSCL_NORMAL DDSCL_NOWINDOWCHANGES DDSCL_SETDEVICEWINDOW DDSCL_SETFOCUSWINDOW End Enum

= = = = = = = = = =

64 2 512 16 1 1024 8 4 256 128

B.1.27 CONST_DDSDMFLAGS
Verwendung in: DirectDraw7.SetDisplayMode()
Enum CONST_DDSDMFLAGS DDSDM_DEFAULT DDSDM_STANDARDVGAMODE End Enum = 0 = 1

B.1.28 CONST_DDSGRFLAGS
Verwendung in: DirectDrawGammaControl.SetGammaRamp()
Enum CONST_DDSGRFLAGS DDSGR_CALIBRATE DDSGR_DEFAULT End Enum = 1 = 0

B.1.29 CONST_DDSTEREOCAPSFLAGS
Verwendung in: DDCAPS lSVCaps
Enum CONST_DDSTEREOCAPSFLAGS DDSVCAPS_ENIGMA DDSVCAPS_FLICKER DDSVCAPS_REDBLUE DDSVCAPS_SPLIT DDSVCAPS_STEREOSEQUENTIAL End Enum = = = = = 1 2 4 8 16

B.1.30 CONST_DDSURFACECAPS2FLAGS
Verwendung in: DDSCAPS2 lCaps2
Enum CONST_DDSURFACECAPS2FLAGS DDSCAPS2_CUBEMAP = 512

564

DirectDraw Enum

DDSCAPS2_CUBEMAP_ALLFACES DDSCAPS2_CUBEMAP_NEGATIVEX DDSCAPS2_CUBEMAP_NEGATIVEY DDSCAPS2_CUBEMAP_NEGATIVEZ DDSCAPS2_CUBEMAP_POSITIVEX DDSCAPS2_CUBEMAP_POSITIVEY DDSCAPS2_CUBEMAP_POSITIVEZ DDSCAPS2_D3DTEXTUREMANAGE DDSCAPS2_HARDWAREDEINTERLACE DDSCAPS2_HINTANTIALIASING DDSCAPS2_HINTDYNAMIC DDSCAPS2_HINTSTATIC DDSCAPS2_MIPMAPSUBLEVEL DDSCAPS2_OPAQUE DDSCAPS2_STEREOSURFACELEFT DDSCAPS2_TEXTUREMANAGE End Enum

= = = = = = = = = = = = = = = =

65024 2048 8192 32768 1024 4096 16384 131072 2 256 4 8 65536 128 524288 16

B.1.31 CONST_DDSURFACECAPSFLAGS
Verwendung in: DDSCAPS2 lCaps
Enum CONST_DDSURFACECAPSFLAGS DDSCAPS_3DDEVICE DDSCAPS_ALLOCONLOAD DDSCAPS_ALPHA DDSCAPS_BACKBUFFER DDSCAPS_COMPLEX DDSCAPS_FLIP DDSCAPS_FRONTBUFFER DDSCAPS_HWCODEC DDSCAPS_LIVEVIDEO DDSCAPS_LOCALVIDMEM DDSCAPS_MIPMAP DDSCAPS_MODEX DDSCAPS_NONLOCALVIDMEM DDSCAPS_OFFSCREENPLAIN DDSCAPS_OPTIMIZED DDSCAPS_OVERLAY DDSCAPS_OWNDC DDSCAPS_PALETTE DDSCAPS_PRIMARYSURFACE DDSCAPS_RESERVED2 DDSCAPS_STANDARDVGAMODE DDSCAPS_SYSTEMMEMORY DDSCAPS_TEXTURE DDSCAPS_VIDEOMEMORY = = = = = = = = = = = = = = = = = = = = = = = = 8192 67108864 2 4 8 16 32 1048576 524288 268435456 4194304 2097152 536870912 64 -2147483648 128 262144 256 512 8388608 1073741824 2048 4096 16384

Anhang B Konstanten

565

DDSCAPS_VIDEOPORT DDSCAPS_VISIBLE DDSCAPS_WRITEONLY DDSCAPS_ZBUFFER End Enum

= = = =

134217728 32768 65536 131072

B.1.32 CONST_DDSURFACEDESCFLAGS
Verwendung in: DDSURFACEDESC2 lFlags
DDSD_ALL DDSD_ALPHABITDEPTH DDSD_BACKBUFFERCOUNT DDSD_CAPS DDSD_CKDESTBLT DDSD_CKDESTOVERLAY DDSD_CKSRCBLT DDSD_CKSRCOVERLAY DDSD_HEIGHT DDSD_LINEARSIZE DDSD_LPSURFACE DDSD_MIPMAPCOUNT DDSD_PITCH DDSD_PIXELFORMAT DDSD_REFRESHRATE DDSD_TEXTURESTAGE DDSD_WIDTH DDSD_ZBUFFERBITDEPTH End Enum = = = = = = = = = = = = = = = = = = 1047022 128 32 1 16384 8192 65536 32768 2 524288 2048 131072 8 4096 262144 1048576 4 64

B.1.33 CONST_DDWAITVBFLAGS
Verwendung in: DirectDraw7.WaitForVerticalBlank()
Enum CONST_DDWAITVBFLAGS DDWAITVB_BLOCKBEGIN DDWAITVB_BLOCKBEGINEVENT DDWAITVB_BLOCKEND End Enum = 1 = 2 = 4

B.2
B.2.1

Direct3DEnum
CONST_D3D
Enum CONST_D3D D3DDP_MAXTEXCOORD = 8

566

Direct3DEnum

D3DRENDERSTATE_WRAPBIAS D3DWRAPCOORD_0 D3DWRAPCOORD_1 D3DWRAPCOORD_2 D3DWRAPCOORD_3 End Enum

= = = = =

128 1 2 4 8

B.2.2

CONST_D3DANTIALIASMODE
Enum CONST_D3DANTIALIASMODE D3DANTIALIAS_NONE D3DANTIALIAS_SORTDEPENDENT D3DANTIALIAS_SORTINDEPENDENT End Enum = 0 = 1 = 2

B.2.3

CONST_D3DBLEND
Verwendung in: CONST_D3DRENDERSTATETYPE
Enum CONST_D3DBLEND D3DBLEND_ZERO D3DBLEND_ONE D3DBLEND_SRCCOLOR D3DBLEND_INVSRCCOLOR D3DBLEND_SRCALPHA D3DBLEND_INVSRCALPHA D3DBLEND_DESTALPHA D3DBLEND_INVDESTALPHA D3DBLEND_DESTCOLOR D3DBLEND_INVDESTCOLOR D3DBLEND_SRCALPHASAT D3DBLEND_BOTHSRCALPHA D3DBLEND_BOTHINVSRCALPHA End Enum = = = = = = = = = = = = = 1 2 3 4 5 6 7 8 9 10 11 12 13

B.2.4

CONST_D3DCAPSBLEND
Verwendung in: D3DPRIMCAPS lSrcBlendCaps und lDestBlendCaps
Enum CONST_D3DCAPSBLEND D3DPBLENDCAPS_BOTHINVSRCALPHA D3DPBLENDCAPS_BOTHSRCALPHA D3DPBLENDCAPS_DESTALPHA D3DPBLENDCAPS_DESTCOLOR D3DPBLENDCAPS_INVDESTALPHA D3DPBLENDCAPS_INVDESTCOLOR D3DPBLENDCAPS_INVSRCALPHA = = = = = = = 4096 2048 64 256 128 512 32

Anhang B Konstanten

567

D3DPBLENDCAPS_INVSRCCOLOR D3DPBLENDCAPS_ONE D3DPBLENDCAPS_SRCALPHA D3DPBLENDCAPS_SRCALPHASAT D3DPBLENDCAPS_SRCCOLOR D3DPBLENDCAPS_ZERO End Enum

= = = = = =

8 2 16 1024 4 1

B.2.5

CONST_D3DCAPSCMP
Verwendung in: D3DPRIMCAPS lZCmpCaps und lAlphaCmpCaps
Enum CONST_D3DCAPSCMP D3DPCMPCAPS_ALWAYS D3DPCMPCAPS_EQUAL D3DPCMPCAPS_GREATER D3DPCMPCAPS_GREATEREQUAL D3DPCMPCAPS_LESS D3DPCMPCAPS_LESSEQUAL D3DPCMPCAPS_NEVER D3DPCMPCAPS_NOTEQUAL End Enum = = = = = = = = 128 4 16 64 2 8 1 32

B.2.6

CONST_D3DCAPSMISC
Verwendung in: D3DPRIMCAPS lMiscCaps
Enum CONST_D3DCAPSMISC D3DPMISCCAPS_CONFORMANT D3DPMISCCAPS_CULLCCW D3DPMISCCAPS_CULLCW D3DPMISCCAPS_CULLNONE D3DPMISCCAPS_LINEPATTERNREP D3DPMISCCAPS_MASKPLANES D3DPMISCCAPS_MASKZ End Enum = = = = = = = 8 64 32 16 4 1 2

B.2.7

CONST_D3DCAPSRASTER
Verwendung in: D3DPRIMCAPS lRasterCaps
Enum CONST_D3DCAPSRASTER D3DPRASTERCAPS_ANISOTROPY D3DPRASTERCAPS_ANTIALIASEDGES D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT D3DPRASTERCAPS_DITHER D3DPRASTERCAPS_FOGRANGE D3DPRASTERCAPS_FOGTABLE = = = = = = 131072 4096 1024 1 65536 256

568

Direct3DEnum

D3DPRASTERCAPS_FOGVERTEX D3DPRASTERCAPS_MIPMAPLODBIAS D3DPRASTERCAPS_PAT D3DPRASTERCAPS_ROP2 D3DPRASTERCAPS_STIPPLE D3DPRASTERCAPS_SUBPIXEL D3DPRASTERCAPS_SUBPIXELX D3DPRASTERCAPS_XOR D3DPRASTERCAPS_ZBIAS D3DPRASTERCAPS_ZBUFFERLESSHSR D3DPRASTERCAPS_ZTEST End Enum

= = = = = = = = = = =

128 8192 8 2 512 32 64 4 16384 32768 16

B.2.8

CONST_D3DCAPSSHADE
Verwendung in: D3DPRIMCAPS lShadeCaps
Enum CONST_D3DCAPSSHADE D3DPSHADECAPS_ALPHAFLATBLEND D3DPSHADECAPS_ALPHAFLATSTIPPLED D3DPSHADECAPS_ALPHAGOURAUDBLEND D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED D3DPSHADECAPS_ALPHAPHONGBLEND D3DPSHADECAPS_ALPHAPHONGSTIPPLED D3DPSHADECAPS_COLORFLATMONO D3DPSHADECAPS_COLORFLATRGB D3DPSHADECAPS_COLORGOURAUDMONO D3DPSHADECAPS_COLORGOURAUDRGB D3DPSHADECAPS_COLORPHONGMONO D3DPSHADECAPS_COLORPHONGRGB D3DPSHADECAPS_FOGFLAT D3DPSHADECAPS_FOGGOURAUD D3DPSHADECAPS_FOGPHONG D3DPSHADECAPS_SPECULARFLATMONO D3DPSHADECAPS_SPECULARFLATRGB D3DPSHADECAPS_SPECULARGOURAUDMONO D3DPSHADECAPS_SPECULARGOURAUDRGB D3DPSHADECAPS_SPECULARPHONGMONO D3DPSHADECAPS_SPECULARPHONGRGB End Enum = = = = = = = = = = = = = = = = = = = = = 4096 8192 16384 32768 65536 131072 1 2 4 8 16 32 262144 524288 1048576 64 128 256 512 1024 2048

B.2.9

CONST_D3DCAPSTEXTURE
Verwendung in: D3DPRIMCAPS lTextureCaps
Enum CONST_D3DCAPSTEXTURE D3DPTEXTURECAPS_ALPHA D3DPTEXTURECAPS_BORDER = 4 = 16

Anhang B Konstanten

569

D3DPTEXTURECAPS_COLORKEYBLEND D3DPTEXTURECAPS_CUBEMAP D3DPTEXTURECAPS_NONPOW2CONDITIONAL D3DPTEXTURECAPS_PERSPECTIVE D3DPTEXTURECAPS_POW2 D3DPTEXTURECAPS_SQUAREONLY D3DPTEXTURECAPS_TRANSPARENCY End Enum

= = = = = = =

4096 1024 256 1 2 32 8

B.2.10 CONST_D3DCAPSTEXTUREADDRESS
Verwendung in: D3DPRIMCAPS lTextureAddressCaps
Enum CONST_D3DCAPSTEXTUREADDRESS D3DPTADDRESSCAPS_BORDER D3DPTADDRESSCAPS_CLAMP D3DPTADDRESSCAPS_INDEPENDENTUV D3DPTADDRESSCAPS_MIRROR D3DPTADDRESSCAPS_WRAP End Enum = = = = = 8 4 16 2 1

B.2.11 CONST_D3DCAPSTEXTUREFILTER
Verwendung in: D3DPRIMCAPS lTextureFilterCaps
Enum CONST_D3DCAPSTEXTUREFILTER D3DPTFILTERCAPS_LINEAR D3DPTFILTERCAPS_LINEARMIPLINEAR D3DPTFILTERCAPS_LINEARMIPNEAREST D3DPTFILTERCAPS_MAGFAFLATCUBIC D3DPTFILTERCAPS_MAGFANISOTROPIC D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC D3DPTFILTERCAPS_MAGFLINEAR D3DPTFILTERCAPS_MAGFPOINT D3DPTFILTERCAPS_MINFANISOTROPIC D3DPTFILTERCAPS_MINFLINEAR D3DPTFILTERCAPS_MINFPOINT D3DPTFILTERCAPS_MIPFLINEAR D3DPTFILTERCAPS_MIPFPOINT D3DPTFILTERCAPS_MIPLINEAR D3DPTFILTERCAPS_MIPNEAREST D3DPTFILTERCAPS_NEAREST End Enum = = = = = = = = = = = = = = = = 2 32 16 134217728 67108864 268435456 16777216 8388608 1024 512 256 131072 65536 8 4 1

B.2.12 CONST_D3DCLEARFLAGS
Verwendung in: Direct3DDevice7.Clear()

570

Direct3DEnum

Enum CONST_D3DCLEARFLAGS D3DCLEAR_ALL D3DCLEAR_STENCIL D3DCLEAR_TARGET D3DCLEAR_ZBUFFER End Enum

= = = =

7 4 1 2

B.2.13 CONST_D3DCLIPFLAGS
Verwendung in: Direct3DDevice7.ComputeSphereVisibility()
Enum CONST_D3DCLIPFLAGS D3DSTATUS_CLIPINTERSECTIONALL D3DSTATUS_CLIPUNIONALL D3DSTATUS_DEFAULT D3DSTATUS_ZNOTVISIBLE 'Clip Schnittpunkt Flags D3DSTATUS_CLIPINTERSECTIONBACK D3DSTATUS_CLIPINTERSECTIONBOTTOM D3DSTATUS_CLIPINTERSECTIONFRONT D3DSTATUS_CLIPINTERSECTIONGEN0 D3DSTATUS_CLIPINTERSECTIONGEN5 D3DSTATUS_CLIPINTERSECTIONLEFT D3DSTATUS_CLIPINTERSECTIONRIGHT D3DSTATUS_CLIPINTERSECTIONTOP 'Clip Vereinigung Flags D3DSTATUS_CLIPUNIONBACK D3DSTATUS_CLIPUNIONBOTTOM D3DSTATUS_CLIP