437 101 3MB
English Pages 479 Year 2001
DirectX 8 and Visual Basic Development Keith Sink
800 East 96th Street, Indianapolis, Indiana, 46240 USA
ASSOCIATE PUBLISHER
DirectX 8 and Visual Basic Development
Linda Engelman
ACQUISITIONS EDITOR Sondra Scott
Copyright © 2002 by Sams Publishing All rights reserved. No part of this book shall be reproduced, stored in a retrieval system, or transmitted by any means, electronic, mechanical, photocopying, recording, or otherwise, without written permission from the publisher. No patent liability is assumed with respect to the use of the information contained herein. Although every precaution has been taken in the preparation of this book, the publisher and author assume no responsibility for errors or omissions. Nor is any liability assumed for damages resulting from the use of the information contained herein.
DEVELOPMENT EDITOR Nancy E. Sixsmith
MANAGING EDITOR Charlotte Clapp
PROJECT EDITOR Heather McNeill
COPY EDITOR
International Standard Book Number: 0-672-32225-0
Lisa M. Lord
Library of Congress Catalog Card Number: 10-89223
INDEXER
Printed in the United States of America
Sandy Henselmeier
First Printing: November 2001
PROOFREADER
04
03
02
01
4
3
2
1
Andrea Dugan
TECHNICAL EDITORS
Trademarks
Andrew Indovina
All terms mentioned in this book that are known to be trademarks or service marks have been appropriately capitalized. Sams Publishing cannot attest to the accuracy of this information. Use of a term in this book should not be regarded as affecting the validity of any trademark or service mark.
Joe Johnston
DirectX, DirectDraw, DirectShow, DirectSound, DirectMusic, DirectPlay, DirectInput, Direct3D, DirectGraphics, Microsoft, Microsoft Visual Basic, and Windows are registered trademarks of Microsoft Corporation.
Warning and Disclaimer Every effort has been made to make this book as complete and as accurate as possible, but no warranty or fitness is implied. The information provided is on an “as is” basis. The author and the publisher shall have neither liability nor responsibility to any person or entity with respect to any loss or damages arising from the information contained in this book or programs accompanying it.
William McLoughlin
TEAM COORDINATOR Lynne Williams
MEDIA DEVELOPER Dan Scherf
INTERIOR DESIGNER Anne Jones
COVER DESIGNER Gary Adair
PAGE LAYOUT Octal Publishing, Inc.
Contents at a Glance Introduction Part I
Visual Basic and DirectX Development
1
Fundamentals of DirectX Programming
2
Multimedia Programming in the Visual Basic Environment
3
Animation Techniques
Part II
DirectX Graphics Programming
4
Creating Graphics with the DirectX Graphics Object
5
Creating Basic Animations with Surface Objects
6
Palettes and Palette Animation
7
3D Geometry
8
Direct3D
9
Using Direct3D
Part III
Monitoring User Input with DirectInput
10
Using DirectInput to Manage User Interactions
11
Action Mapping
12
The Keyboard
13
The Joystick
14
The Mouse
Part IV
Adding Music and Sounds with DirectAudio
15
DirectX Audio—DirectMusic and DirectSound
16
Composing Music
17
Adding Sounds to Your Application with DirectSound
Part V
Streaming Media with DirectShow
18
Introduction to DirectShow
19
Using DirectShow for Digital Editing
20
Multimedia Players
Part VI
Multiuser Strategies with DirectPlay
21
Using DirectPlay to Create Multiplayer Games
22
Using Lobbies to Create Player Interactions
23
Managing Games with DirectPlay
24
Using DirectPlay Voice in Your Application
Part VII
Finishing Touches
25
DirectSetup
Part VII
Appendix
A
VB .NET and DirectX Index
Table of Contents Introduction 1 Who This Book Is For? ..........................................................................1 What You Need to Know ........................................................................1 What Hardware and Software You Need ................................................1 How This Book Is Organized ................................................................2 Conventions Used in This Book ............................................................3
PART I
VB and DirectX Development
5
1
Introduction to DirectX Programming 7 What Is DirectX? ..................................................................................8 A History ................................................................................................8 The Early Days ..................................................................................8 The DOS Days ..................................................................................9 Along Came Windows ......................................................................9 Then There Was DirectX ................................................................10 Why Visual Basic and DirectX? ..........................................................12 The Evolution of Visual Basic ........................................................12 DirectX for the Masses ....................................................................12 Putting DirectX to Work ......................................................................13 Showcasing Products ......................................................................13 Music and Sound ............................................................................13 User Interactions ..............................................................................14 Screensavers and Multimedia ..........................................................15 Game Programming ........................................................................15 Synchronizing Data ........................................................................15 The DirectX Components ....................................................................16 Summary ..............................................................................................18
2
Multimedia Programming in the Visual Basic Environment 19 Installing DirectX ................................................................................20 Setting Up DirectX for Use in Visual Basic ........................................20 Creating a Reference to the DirectX 8.0 type Library ....................21 Classes and Objects ..............................................................................22 COM ..............................................................................................23 Creating DirectX Objects ................................................................23 Programming Tips to Improve Animation ............................................25 Timers ..............................................................................................25 Execution Loops ..............................................................................27 Error Trapping ................................................................................29 Debugging ......................................................................................30
vi
DIRECTX 8
AND
VISUAL BASIC DEVELOPMENT DirectX Utilities ....................................................................................31 DirectX Caps Viewer ......................................................................31 DirectX Error Lookup ....................................................................31 DirectX Texture Tool ......................................................................32 DMO Test Tool ................................................................................32 Force Feedback Editor ....................................................................33 GraphEdit Tool ................................................................................34 Kill Help Utility ..............................................................................35 Mesh Viewer Tool ............................................................................35 Compiling for Speed: Tips and Tricks ..................................................35 Remove Unused Subroutines ..........................................................36 Remove Unused Variables ..............................................................36 Reduce Access Times ......................................................................36 Destroy All Objects ........................................................................36 Remove Debug Statements ..............................................................36 Add DoEvents ................................................................................37 Summary ..............................................................................................37
3
Animation Techniques 39 The Basics ............................................................................................40 The Model Sheet ............................................................................40 The Frame ........................................................................................40 The Cycle ........................................................................................41 Storyboards ......................................................................................41 Keyframes ........................................................................................42 Backgrounds ....................................................................................42 DirectX Objects ....................................................................................43 Frame Rates ....................................................................................43 Blits ..................................................................................................43 Sprites ..............................................................................................44 Drawing Surfaces ............................................................................45 Palettes ............................................................................................45 Rectangles ........................................................................................46 Clippers ............................................................................................46 Billboards ........................................................................................47 Techniques ............................................................................................48 Blitting ............................................................................................48 Page Flipping and Back Buffering ..................................................48 Palette Cycling ................................................................................49 Summary ..............................................................................................50
CONTENTS
PART II
DirectX Graphics Programming
51
4
Creating Graphics with DirectDraw 53 Creating Graphics with DirectDraw Classes ........................................54 What Is DirectDraw? ......................................................................54 DirectDraw Architectural Overview ................................................55 HAL Versus HEL ..................................................................................62 Display Modes ......................................................................................63 Standard Display Modes ................................................................64 An Example Using the DirectDraw Class ............................................65 Summary ..............................................................................................68
5
Creating Basic Animations 71 Surfaces ................................................................................................72 Creating Surfaces ............................................................................72 Creating Surfaces from Files ..........................................................74 Surface Descriptions ........................................................................75 Flipping Surfaces ............................................................................77 Blitting to a Surface ........................................................................79 The Many Forms of the BLIT Routine ..........................................79 Gamma and Color Controls ..................................................................82 Overlay Surfaces ..................................................................................83 A DirectDrawSurface Example ............................................................85 Summary ..............................................................................................88
6
Palettes and Palette Animation 91 Palettes ................................................................................................92 Palette Types ....................................................................................92 Palette Entries ..................................................................................92 Sharing Palettes ..............................................................................93 Palette Animation ..................................................................................95 Modifying the Palette ......................................................................96 Switching Palettes ..........................................................................97 A DirectDrawPalette Example ..........................................................100 Summary ............................................................................................101
7
3D Geometry 103 3D Space Coordinate System ............................................................104 3D Objects ..........................................................................................105 Vertices ..........................................................................................106 Polygons ........................................................................................106 Faces ..............................................................................................107 Mesh ..............................................................................................107 Texture ..........................................................................................109
vii
viii
DIRECTX 8
AND
VISUAL BASIC DEVELOPMENT Lights ............................................................................................109 Materials ........................................................................................109 Matrices ..............................................................................................111 Projection Matrix ..........................................................................112 View Matrix ..................................................................................112 World Matrix (World Transformation) ..........................................112 Summary ............................................................................................112
8
Direct3D 115 Direct3D Objects ................................................................................116 The Direct3D8 Class ....................................................................116 The Direct3DBaseTexture8 Class ................................................117 The Direct3DCubeTexture8 Class ................................................118 The Direct3DDevice8 Class ..........................................................119 The Direct3DIndexBuffer8 Class ..................................................123 The Direct3DResource8 Class ......................................................124 The Direct3DSurface8 Class ........................................................125 The Direct3DSwapChain8 Class ..................................................126 The Direct3DTexture8 Class ........................................................126 The Direct3DVertexBuffer8 Class ................................................127 The Direct3DVolume8 Class ........................................................127 The Direct3DVolumeTexture8 Class ............................................128 Creating 3D Applications ..................................................................129 Creating a Direct3D Application ..................................................129 Working with Vertices ..................................................................133 Working with Matrices ..................................................................137 Working with Lights ......................................................................142 Working with Textures ..................................................................146 Working with Meshes ....................................................................149 Summary ............................................................................................153
9
Using Direct3D 155 2D Graphics with Direct3D ................................................................156 Declaring the Objects ....................................................................156 Initializing the Environment ..........................................................157 Creating the Background Vertices ................................................159 Drawing to the Screen ..................................................................161 Updating the Bee’s Coordinates ....................................................162 Creating a Billboard Application ........................................................163 Declaring the Objects ....................................................................163 Initializing the Environment ..........................................................165 Rendering the Scene ......................................................................168 Manipulating Vectors and Vertices ................................................171 Summary ............................................................................................173
CONTENTS
PART III
Monitoring User Input with DirectInput
175
10
Using DirectInput to Manage User Interactions 177 Obtaining User Input from DirectInput ..............................................178 Objects in DirectInput ..................................................................179 Cooperative Levels ......................................................................180 DirectInput Architectural Overview ..................................................180 The DirectInput Class ....................................................................181 The DirectInputDevice Class ........................................................183 The DirectInputDeviceObjectInstance Class ................................185 The DirectInputDeviceInstance Class ..........................................186 The DirectInputEffect Class ..........................................................187 The DirectInputEnumEffects Class ..............................................189 DirectInput Technologies and Components ......................................190 Action Mapping ............................................................................190 Force Feedback ..............................................................................190 The Keyboard Component ............................................................191 Joysticks, Yokes, and Steering Wheels ..........................................191 The Mouse Component ................................................................191 Summary ............................................................................................191
11
Action Mapping 193 Managing User Input with Action Maps ............................................194 Preparing the Action Map ............................................................195 Configuring the Action Map ........................................................200 Summary ............................................................................................204
12
The Keyboard 205 Retrieving User Input from the Keyboard ..........................................206 Creating Your Objects ..................................................................206 Setting the Keyboard Parameters ..................................................206 Accessing the Keyboard ................................................................207 Retrieving Immediate Data from the Keyboard ............................207 Two Methods of Analysis ..............................................................214 The Keyboard Example ......................................................................215 Summary ............................................................................................217
13
The Joystick 219 Retrieving User Input from the Joystick ............................................220 Creating Your Objects ..................................................................220 Getting the Joystick Capabilities ..................................................222 Setting Joystick Device Properties ................................................223 Dead Zones ....................................................................................224 Using the Joystick ........................................................................225
ix
Force Feedback ..................................................................................227 Force-Feedback Effects ................................................................228 Force Feedback Properties ............................................................228 The Joystick Example ........................................................................228 Summary ............................................................................................236 14
PART IV
The Mouse 237 Retrieving User Input from the Mouse ..............................................238 Creating Your Objects ..................................................................238 Setting the Buffer Size ..................................................................239 Event Notification ........................................................................239 Considerations for DirectInput Use of the Mouse ............................240 Retrieving the Mouse Data ............................................................241 Analyzing the DIDEVICEOBJECTDATA Variable ....................241 Immediate Data ..................................................................................244 Summary ............................................................................................244
Adding Music and Sounds with DirectAudio
245
15
DirectX Audio—DirectMusic and DirectSound 247 What Is DirectMusic? ........................................................................248 DirectMusic Architectural Overview ............................................248 DirectMusic Classes ......................................................................249 What Is DirectSound? ........................................................................250 DirectSound Architectural Overview ............................................251 DirectSound Classes ......................................................................252 Objects for Sound Effects ............................................................253 Sound Buffers ................................................................................254 DirectSound 3D ............................................................................254 When Should I Use DirectSound Versus DirectMusic? ....................256 Summary ............................................................................................256
16
Composing Music 257 The Loader Object ..............................................................................258 Using the DirectMusic Loader Object ..........................................258 The Performance Object ....................................................................259 Using the DirectMusic Performance Object ................................259 The Segment Object ..........................................................................263 Using the DirectMusic Segment Object ........................................263 The Audio Parameter Structure ..........................................................264 Using the DirectMusic Audio Parameter Type ............................264 The Band Object ................................................................................265 Using the DirectMusic Band Object ............................................265
Modifying the Performance ................................................................265 Volume ..........................................................................................266 Tempo ............................................................................................266 A DirectMusic Example ....................................................................266 Declaring the Variables ..................................................................267 Initializing the Performance ..........................................................267 Using the Loader Object ..............................................................267 Using the Segment Object ............................................................268 Using the Performance Object ......................................................268 DirectMusic Producer ........................................................................268 Summary ............................................................................................269 17
Adding Sounds to Your Application with DirectSound 271 The DirectSound8 Object ..................................................................272 Using the DirectSound8 Object ....................................................272 Buffers ................................................................................................273 Primary Sound Buffer ..................................................................273 Secondary Sound Buffer ..............................................................273 The DirectSound Buffer Descriptor ..................................................274 Buffer Descriptor Members ..........................................................275 Creating the DirectSound Buffer Descriptor (DSBUFFERDESC) ..................................................................275 Using the Sound Buffers ....................................................................277 Enumerating the Sound Driver ......................................................277 Creating the Sound Buffer ............................................................277 Loading the Buffer ........................................................................278 Playing the Buffer ........................................................................278 Modifying the Sound Buffer ..............................................................279 Frequency ......................................................................................279 Panning ..........................................................................................279 Volume ..........................................................................................279 Example ........................................................................................279 Recording ............................................................................................280 Creating the Capture Object ..........................................................280 Creating the Capture Buffer ..........................................................280 Recording ......................................................................................281 Converting the Buffer ....................................................................282 Saving the File ..............................................................................283 DirectSound3D ..................................................................................283 Coordinates ....................................................................................283 Distances ........................................................................................284 The 3D Buffer ..............................................................................284 The 3D Listener ............................................................................285 Summary ............................................................................................286
PART V
Streaming Media with DirectShow
287
18
Introduction to DirectShow 289 Uses for DirectShow ..........................................................................290 Objects in DirectShow ........................................................................290 Filter ..............................................................................................290 Filter Graph ..................................................................................291 Pin ..................................................................................................291 DirectShow Architecture ....................................................................291 Supported Media Formats and Codecs ..............................................293 Creating a Reference to the ActiveMovie Type Library ....................295 Summary ............................................................................................296
19
Using DirectShow for Digital Editing 297 DirectShow Editing Services (DES) ..................................................298 The AMTimeLine Class ................................................................298 The AMTimelineComp Class ........................................................299 The AMTimelineEffect Class ........................................................300 The AMTimelineGroup Class ......................................................300 The AMTimelineObj Class ..........................................................301 The AMTimelineSrc Class ............................................................302 The AMTimelineTrack Class ........................................................303 The AMTimelineTrans Class ........................................................303 The IAMErrorLog Class ..............................................................304 The IAMSetErrorLog Class ..........................................................304 The IAMTimelineEffectable Class ................................................304 The IAMTimelineSplittable Class ................................................305 The IAMTimelineTransable Class ................................................305 The IAMTimelineVirtualTrack Class ............................................306 The IEnumFilters Class ................................................................306 The IEnumMediaTypes Class ......................................................306 The IEnumPins Class ....................................................................306 The IErrorLog Class ......................................................................306 The IFilterGraph Class ..................................................................307 The IGraphBuilder Class ..............................................................307 The IMediaFilter Class ..................................................................308 The IMediaSample Class ..............................................................309 The IPersistStream Class ..............................................................309 The IPin Class ..............................................................................310 The IReferenceClock Class ..........................................................310 The ISmartRenderEngine Class ....................................................311 The MediaDet Class ......................................................................311 The MediaLocator Class ..............................................................312
The RenderEngine Class ..............................................................312 The SmartRenderEngine Class ......................................................313 The Xml2Dex Class ......................................................................313 Summary ............................................................................................313 20
PART VI 21
Multimedia Players 315 The ActiveMovie DLL ........................................................................316 The FilgraphManager Object ........................................................316 The IAMCollection Class ..............................................................316 The IAMStats Class ......................................................................317 The IBasicAudio Class ..................................................................317 The IBasicVideo Class ..................................................................317 The IBasicVideo2 Class ................................................................319 The IDeferredCommand Class ......................................................319 The IFilterInfo Object ..................................................................319 The IMediaEvent Object ..............................................................320 The IMediaEventEx Object ..........................................................320 The IMediaPosition Object ..........................................................321 The IMediaTypeInfo Object ..........................................................321 The IPinInfo Object ......................................................................321 The IQueueCommand Class ..........................................................322 The IRegFilterInfo Object ............................................................322 The IVideoWindow Class ..............................................................323 An Example Using the ActiveMovie DLL ........................................324 Microsoft Web DVD Control ............................................................330 The DVDRect Class ......................................................................330 The MSDVDAdm Class ................................................................331 The MSWebDVD Class ................................................................332 Summary ............................................................................................336
Multiuser Strategies with DirectPlay
337
Using DirectPlay to Create Multiplayer Games 339 A DirectPlay Primer ..........................................................................340 Service Provider ............................................................................340 Connection ....................................................................................341 Session ..........................................................................................341 Player ............................................................................................341 Group ............................................................................................341 Host ................................................................................................341 Message ........................................................................................342 Network Providers ........................................................................342 System Messages ..........................................................................343
xiv
DIRECTX 8
AND
VISUAL BASIC DEVELOPMENT Lobby ............................................................................................343 GUID ............................................................................................343 Communication Models ......................................................................344 Peer-to-Peer ..................................................................................344 Client/Server ..................................................................................344 DirectPlay Events ..............................................................................346 A DirectPlay Peer-to-Peer Client ......................................................346 Assigning a GUID ........................................................................346 Initializing the DirectPlay Peer-to-Peer Client ............................346 Finding the Available Service Providers ......................................347 Finding the Game Host ................................................................347 Connecting to the Session ............................................................347 Managing the Session ....................................................................348 Sending Messages ........................................................................348 Closing the Session ......................................................................348 A DirectPlay Client/Server Connection ............................................349 Assigning a GUID ........................................................................349 Initializing the DirectPlay Client/Server Client ............................349 Finding the Available Service Providers ......................................349 Finding the Game Host ................................................................350 Connecting to the Session ............................................................350 Managing the Session ....................................................................350 Sending Messages ........................................................................351 Closing the Session ......................................................................351 Summary ............................................................................................351
22
Using Lobbies to Create Player Interaction 353 Lobby Architecture ............................................................................354 Lobby Servers ....................................................................................355 Lobby Clients ......................................................................................356 The DirectPlay8LobbyClient Class ..............................................357 DirectPlay Lobbied Application ........................................................357 The DirectPlay8LobbiedApplication Class ..................................358 DirectPlay Lobby Event ....................................................................358 The DirectPlay8LobbyEvent Class ..............................................359 Summary ............................................................................................359
23
Managing Games with DirectPlay 361 DirectPlay Concepts ..........................................................................362 DirectPlay Architecture ......................................................................363 Using the DirectPlay8Address Class ............................................363 Using the DirectPlay8Client Class ................................................366
CONTENTS Using the DirectPlay8Event Class ................................................367 Using the DirectPlay8Peer Class ..................................................369 Using the DirectPlay8Server Class ..............................................371 Summary ............................................................................................373 24
PART VII 25
PART VIII A
Using DirectPlay Voice in Your Application 375 DirectPlay Concepts ..........................................................................376 Voice Session ................................................................................376 Transmission Target ......................................................................376 DirectPlay Voice Architecture ............................................................377 Using the DirectPlayVoiceClient8 Class ......................................378 Using the DirectPlayVoiceEvent8 Class ......................................379 Using the DirectPlayVoiceServer8 Class ......................................380 Using the DirectPlayVoiceTest8 Class ..........................................381 Using DirectPlay Voice ......................................................................381 DirectPlay Voice on a Peer-to-Peer Connection ............................381 DirectPlay Voice on a Forwarding Server Connection ................382 DirectPlay Voice on a Mixing Server Session ..............................382 Summary ............................................................................................382
Finishing Touches
383
DirectSetup 385 Working with the DirectXSetup Libraries ..........................................386 Initializing the DirectXSetup Functions ........................................386 Using the DirectXSetupGetVersion Function ..............................387 Using the DirectXSetup Function ................................................388 Using the Package and Deployment Wizard ......................................389 Creating the Setup Package ..........................................................389 A Little Voodoo ............................................................................393 Deploying the Setup ......................................................................394 Alternatives to the Package and Deployment Wizard ........................395 Summary ............................................................................................395
Appendix
397
VB .NET and DirectX 399 Setting Up DirectX for Use in VB .NET ..........................................400 Converting the DirectX DLLs to VB .NET Format ......................400 Creating a Reference to the DirectX 8 Type Library ....................400 Debugging Your Code in VB .NET ....................................................403 Error Trapping in VB .NET ..........................................................403 New Debugging Features of VB .NET ........................................404 Index
405
xv
About the Author Keith Sink is a Senior Technical Engineer for Capital Stream, a financial software company in Seattle, WA, where he has been involved in the design, development, and architecture of a number of successful applications. Keith has been a professional software developer for six years and an MCP since 1994, has taught numerous VB training courses, and has beta-tested Microsoft’s DirectX since version 2.0. Keith has been animating and writing video games since the TRS-80 programming days in the early 1980s, and enjoys restoring classic video games. While working with Microsoft, Keith contributed to Office 97 Help content as well as content for the Word and PowerPoint Answer Wizards.
About the Technical Editors Andrew J. Indovina is currently a software developer living in Rochester, NY. With a degree in computer science, he has a wide programming background. Andy has co-authored two books based on Visual Basic 6 and Visual C++, respectively. Joseph Johnston is currently a technical specialist for Cendant Corporation. He uses VB, VFP5 and 6, SQL Server, MTS/COM+, and VC++ on a daily basis. Joe also creates solutions or utilities for acute issues with data and software systems using the tool that makes the most sense. William McLoughlin is currently a software developer for a major pharmaceutical company. Bill has a degree in computer information systems technologies. He lives in Long Valley, NJ with his wife Jennifer and their sons Liam and Owen.
Dedication In memory of my parents: Wade and Janet. And to the woman who always inspires me: Michelle.
Acknowledgments I want to thank Dwayne Gifford and Mary Hutson for their support and advice on doing this book. I would also like to thank my friend and favorite critic Jeff Lemkin, for his incredible help with my initial edits. To my family and friends who supported me in this endeavor, thank you for your patience and your encouraging words. Thank you Mike, Kim, and Stacy. No book can be completed without the support of a great supporting staff. And that’s exactly what I had. Sondra Scott, Nancy Sixsmith, Heather McNeill, Lisa Lord, Linda Engelman, Andrew Indovina, Joe Johnston, William McLoughlin, and the rest of the Sams editors and staff: Thank you. I would also like to thank the support that I received from the DirectX beta team and the Yahoo! VB and DirectX support group. Thanks also to the following people who reviewed the original table of contents and proposal: Joel Rosenblatt, Columbia University, Manager Mainframe Systems, AcIS; Eric Smith, Owner, Northstar Computer Systems; Mike Snell, Chief Software Architect, Acclarant, Inc.; and Larry Wall, Team Leader Microsoft Group, Synapse Technology.
Tell Us What You Think! As the reader of this book, you are our most important critic and commentator. We value your opinion and want to know what we’re doing right, what we could do better, what areas you’d like to see us publish in, and any other words of wisdom you’re willing to pass our way. As an associate publisher for Sams, I welcome your comments. You can e-mail or write me directly to let me know what you did or didn’t like about this book—as well as what we can do to make our books stronger. Please note that I cannot help you with technical problems related to the topic of this book, and that due to the high volume of mail I receive, I might not be able to reply to every message. When you write, please be sure to include this book’s title and author as well as your name and phone or fax number. I will carefully review your comments and share them with the author and editors who worked on the book.
E-mail:
[email protected]
Mail: Sams Publishing 800 East 96th Street Indianapolis, IN 46240 USA
Introduction DirectX and the graphics SDKs, which were its foundation, have been around since the early days of Windows in one form or another. However, most of us have not been exposed to their fantastic capabilities. Under the shroud of secrecy, Windows game programmers have carefully guarded their secrets to protect their investments. This shroud has become transparent in recent years, though, and now the advanced libraries that used to belong to a select few are available in a universal library called DirectX. For some years, DirectX was accessible only to C programmers, but not anymore. DirectX is now available to Visual Basic programmers, and more and more of them are creating games and multimedia applications. This world can be quite complex, but also quite exciting. With the ease of use of Visual Basic and the powerful libraries in DirectX, this combination is a natural marriage of technologies. This book will take you through understanding DirectX concepts and show you how to create applications that can make use of this technology. This book will introduce you to what you need to know, but as with all languages and libraries, practice makes perfect.
Who This Book Is For? This book is intended for Visual Basic users who have mastered all the basic functionality this language provides and now want to venture into multimedia programming. This book is not a game-programming book. It is intended for a much broader audience: the multimedia programmer. If you have already read some game programming books and want to know how to use DirectX to create games in Visual Basic, this book is for you. If you want a book that does not assume you are a game programmer, this book is for you. If you are a non-multimedia programmer and just want to know how to use the features of DirectX in your everyday applications, this book is for you. This book is intended to show how DirectX can be used in the broad multimedia market, not just with games.
What You Need to Know You need to have a basic understanding of COM programming in Visual Basic. You also must understand how to create standard Visual Basic programs. The rest you will learn in this book.
What Hardware and Software You Need To compile and run the samples in this book and those on the Sams Web site, you will need the following software programs: • Windows 2000 or XP • Visual Basic 6.0 • DirectX 8.1 SDK (this is a free download from Microsoft’s Web site)
2
DIRECTX 8
AND
VISUAL BASIC DEVELOPMENT
Most of the standard hardware on the market will run the programs in this book. The only exception is Direct3D applications. If you are going to develop Direct3D applications, you will need a 3D graphics card.
How This Book Is Organized This book is organized into easy-to-follow parts, which follow the organization of the Microsoft DirectX object model. These parts encapsulate the whole DirectX object model into an easy to read reference. In Part I, you will learn about the basics of programming in the DirectX and Visual Basic environments. You will learn about the basics of DirectX and multimedia programming and how animation is achieved by using DirectX. Part II will take you into the details of creating DirectDraw and Direct3D applications. In this part of the book, you will learn about 2D and 3D graphics and how they can be used in your applications. Part III introduces you to DirectInput and explains how joysticks, keyboards, mice and other input devices are used with DirectX and Visual Basic. Part IV explains DirectMusic and how it can be used to add sound and music to your applications. You will learn how DirectSound can add sound effects and voice to your applications. You will also experience DirectMusic, and learn how it can add a heart-pounding musical score to your applications. Part V exposes you to the DirectShow libraries and explains how to create media players and converters. You will learn how to create a MP3 media player to listen to audio files. You will also learn how DirectShow can be used to create DVD players and other applications. Part VI delves into the area of network games. In this part, you will learn about DirectPlay. You will learn how DirectPlay can be used to add network capabilities to your games and applications and expand the experience for the user. Part VII explains how to distribute DirectX through the DirectSetup library. It also explains how to package and distribute your final application. Part VIII is the appendix section of the book. Here you will learn about how DirectX 7 and DirectX 8 can be used with VB .NET and how to take advantages of the debugging capabilities of VB .NET.
INTRODUCTION
Conventions Used in This Book The following typographic conventions are used in this book: • Code lines, commands, statements, variables, and any text you type or see onscreen appears in a mono typeface. Bold mono typeface is often used to represent the user’s input. • Placeholders in syntax descriptions appear in an italic mono typeface. Replace the placeholder with the actual filename, parameter, or whatever element it represents. • Italics highlight technical terms and terms used for the first time, and are sometimes used for emphasis. • The ➥ icon is used before a line of code that is really a continuation of the preceding line. Sometimes a line of code is too long to fit as a single line on the page. If you see ➥ before a line of code, remember that it’s part of the line immediately above it. • The book also contains Notes, Tips, and Cautions to help you spot important or useful information more quickly:
NOTE
Notes present interesting pieces of information related to the discussion at hand.
TIP
Tips offer advice or teach an easier way to do something.
CAUTION
Cautions advise you about potential problems and help you steer clear of disaster.
3
VB and DirectX Development
This section focuses on what DirectX and VB offer the development community. Chapter 1, “Fundamentals of DirectX Programming,” discusses the basis of DirectX and what it offers and explains multimedia programming with DirectX in the VB environment. Finally, this section introduces animation techniques that are vital to understanding multimedia programming in DirectX.
IN THIS PART 1 Introduction to DirectX Programming
7
2 Multimedia Programming in the Visual Basic Environment 19 3 Animation Techniques
39
PART
I
CHAPTER
Fundamentals of DirectX Programming
1
IN THIS CHAPTER • What Is DirectX? • A History
8
8
• Why Visual Basic and DirectX? • Putting DirectX to Work • The DirectX Components • Summary
18
13 16
12
8
VB.NET and DirectX Development PART I
Welcome to the great world of game and multimedia programming. This chapter will introduce you to the history of multimedia and game programming on the PC. You will learn about the exciting world of DirectX and how Visual Basic can be used to program it. Throughout this book you will also see samples of how much of the same Visual Basic code can be converted to work with Visual Basic.NET(VB.NET). You will also learn what this technology can be used for. Finally, you’ll take a look at all the major components that make up the DirectX library.
What Is DirectX? DirectX is the building block used to create many of the Windows-based video games and multimedia applications we all enjoy today. It is a collection of COM objects that encompass many of the elements used in video game and multimedia development. DirectX provides graphics support for animation, music and sound effects support for game excitement, and multiplayer support for network games. It also contains libraries that access the game devices and gives you the ability to work in 3D graphics. In a nutshell, DirectX is a collection of technologies designed to encapsulate much of multimedia development.
A History To better understand the architecture of DirectX, you need to understand how it came about and why it was needed.
The Early Days Since the early days of video game development, game developers had to rely on detailed knowledge of the hardware they were working with. This knowledge came from lots of experimentation and electronics know-how. For example, to create some of the earliest games, such as Pong or Asteroids, game designers had to have a good understanding of what each chip on the game motherboard could give them. They needed to know how much memory they had to work with, what colors were available, and how to produce them. In some cases, they had to go to manufacturers and ask for help designing chips to achieve what they wanted to accomplish. Sound and graphics capabilities were primitive at best, but they managed. Because these early games were truly a pioneering endeavor, they also had to create new user controls to work with. These efforts resulted into unique developers: part designer, part engineer. Because of the advanced knowledge needed to create arcade games in this environment, there were very few game designers.
Fundamentals of DirectX Programming CHAPTER 1
The DOS Days
Early DOS games required knowledge of machine and assembly languages to access the operating system’s lower levels. As time went on, more user-friendly languages were created, such as BASIC and LOGO; however, they didn’t have the power of assembly language. Then came such languages as Pascal and C. With C, game developers could write advanced code routines without having to write tons of assembly code, thus making development efforts easier. C soon became the preferred language of game developers. Through all these language changes, one problem remained. To write good games, developers still needed an in-depth knowledge of the hardware they were working with. They no longer had to know each chip’s capabilities, but they had to understand things such as video cards, sound cards, and input devices. They also had to deal with memory constraints, which were becoming a hindrance to game development.
Along Came Windows With the development of Microsoft Windows and other operating systems, creating standards in the computer industry became much easier. These standards included hardware interfaces, video memory standards, sound standards, and CPU memory specifications. However, there was still a lot of dissension in the industry, and not all hardware behaved as advertised on the Windows operating system. As a result, many games written in Windows had problems and suffered from performance hits. Microsoft realized this problem early on and focused its efforts on standardizing its environment and working to increase performance for the parts of the operating system that pertain to game and multimedia needs. These efforts were demonstrated in Windows 95, one of the first operating systems that made consistent hardware-software interaction a reality. Because all hardware manufacturers had to meet a similar standard and Microsoft controlled how its operating system communicated to the hardware, development became standard as well. In the DOS days, you had to create your own drivers for each
1 FUNDAMENTALS OF DIRECTX PROGRAMMING
From the early technologies of arcade game developers and computer scientists arose the personal computer. With this invention, the need to know the chips was replaced with the need to know a programming language. As computers and programming languages evolved, more and more software people turned to game development. Some of the early computer games were very simple. They relied heavily on text and rudimentary graphics, much like the early arcade days. Some of the earliest hits in the PC game market were actually text-based adventure games. During this time, writers at Infocom wrote such classic games as “Hitchhikers Guide to the Galaxy” and “Zork”. This new medium thrilled users, who didn’t seem to mind that there were only words on the screen. These early game developers were actually a combination of game developers and literary writers who came together to produce classics. As computers developed in their capabilities, so did the games.
9
10
VB.NET and DirectX Development PART I
type of video card, but with Windows, you had to develop to only one standard. Instead of spending time creating and understanding so many hardware specifications, developers relied on Microsoft to do all that for them and package it for their use in the OS. Microsoft was on the right track, but it wasn’t quite there yet. Windows was originally designed for the home and office, not for multimedia development. It lacked a few essential items that had become standard in the multimedia market—particularly graphics speed, which could no longer be achieved in the Windows environment as it had been in DOS. It was the same hardware, but there were many more layers between the developer’s code and the hardware they wanted to control. The result was that many developers abandoned the idea of Windows game development and relied on the Windows ability to shell out to DOS.
Then There Was DirectX After Microsoft realized that game developers agreed with its concepts but weren’t willing to give up the performance they had become accustomed to in DOS, Microsoft began researching ways to enable developers to get to that hardware layer. Some of the early attempts included WinG, WinToon, and OpenGL. WinG came into the software spotlight around the time of Windows 3.1 and Windows for WorkGroups. WinG was the first attempt at a full-blown graphics API (Application Programming Interface) library to overcome the limitations of the Windows API. WinG supported high-performance graphics techniques that opened up the Windows game development world to those people who worked exclusively in DOS. Figure 1.1 shows the WinG “Doggie” demo that was part of the WinG SDK.
FIGURE 1.1 WinG Doggie demo.
Fundamentals of DirectX Programming CHAPTER 1
FIGURE 1.2 WinToon Jump Start demo
OpenGL is a powerful set of APIs that allowed developers to cut through the Windows red tape to get to some of the hardware capabilities of 2D and 3D animation. Surprisingly, OpenGL was not created by Microsoft, but by Silicon Graphics, Inc. Silicon Graphics is one of the pioneers in 3D special effects, however, so it’s not that surprising. Several games today still use OpenGL as well as DirectX because many video cards support both these technologies. These technologies were a great boost, but ultimately came up short. As the game market exploded and the need for more games on the Windows 95 platform increased, developers at Microsoft went back to the drawing board. What they came up with was the Windows 95 Game Software Developer’s Kit (SDK), which contained the first version of DirectX. DirectX was initially just for the computer game industry but has evolved to include other areas, such as innovations in the arcade industry and handheld Windows CE devices. As DirectX has developed, Microsoft has added network support, force feedback support, and 3D graphics capabilities. When innovations are needed, the DirectX team has continued to increase the capabilities of this remarkable software library. Microsoft has also made it easier for DirectX to be used by more than one language. C and C++ had become the game developer’s language of choice, so DirectX and the examples
1 FUNDAMENTALS OF DIRECTX PROGRAMMING
WinToon was an early API for Windows 95 that provided the capability of easy animation playback. On top of full-screen playback capabilities, this API also offered quicker performance than existing Windows 95 APIs did. This technology helped improve the multimedia playback capabilities of animation programs such as kids’ games and teaching programs. Figure 1.2 shows the WinToon “Jump Start” demo that was included with the WinToon SDK.
11
12
VB.NET and DirectX Development PART I
included with the SDK were designed with C developers in mind. As DirectX has become more accepted, and Visual Basic (VB) taken more seriously as a programming language, DirectX and Visual Basic have finally come together. It also hasn’t hurt that Microsoft has been encouraging VB users to start using DirectX in their applications.
Why Visual Basic and DirectX? So we come down to the question of why DirectX is now available to Visual Basic developers but wasn’t available before. To understand this issue, you need to see how VB has evolved as a viable programming language.
The Evolution of Visual Basic Visual Basic is an offshoot of an early programming language: BASIC. Personal computer users have always used BASIC and other languages like Pascal to create their own simple, personal games. However, BASIC was not widely accepted as an efficient enough language to create serious, mass-produced video games. After the creation of the Windows OS, most developers still found themselves confined to lowlevel languages such as C to create applications for this new platform. Microsoft, seeing that it needed as many developers on its side as possible, invested in a new language called Visual Basic. Visual Basic offered an easy-to-use interface, a language that was simple for first-time programmers to grasp, and the ability to create Windows programs quickly. Although early versions of Visual Basic were not respected in the programming industry, VB soon found its own niche. After outside companies began making new controls and add-on modules for the VB environment, Visual Basic developers became more in demand. They could create a Windows application in half the time a C developer could. The Visual Basic environment, however, was too slow to handle graphics-intensive programming such as games. Early VB game programmers had to rely on puzzle games and card games. Until recently, VB didn’t have anywhere near C’s speed or reliability, but that has changed. With VB6, programmers have finally been able to produce faster applications that can now take advantage of the DirectX libraries. And soon a new Visual Basic language, VB.NET will be released to the public.
DirectX for the Masses The next step for DirectX was to create libraries that were accessible to VB developers. The bottom line is that the more people use DirectX, the more popular it will be and the quicker it will become the industry standard. DirectX came home to Visual Basic in the form of DirectX 7. First with DirectX 7 and now with version 8, Microsoft has continued and enhanced its commitment to the VB community. DirectX 8 now includes a DirectX type library for VB users
Fundamentals of DirectX Programming CHAPTER 1
Putting DirectX to Work DirectX has the power to create and manipulate complex images and sounds. These features, combined with the ability to register user input and its network capabilities, make it a powerful library. With this library, you can create kiosks that show off your latest products, games that have surround sound and stereo audio effects, and many other multimedia applications. The possibilities are limited only by your imagination.
Showcasing Products One of the best uses of the DirectX object model is to create applications that can show off your products. For example, you could create a fully interactive demonstration to showcase a product such as a new computer monitor. You could change the colors or rotate it.. Figure 1.3 shows how DirectX could be used to showcase a flatscreen monitor.
FIGURE 1.3 Showcasing a product.
Music and Sound With DirectX, you could allow users to turn on a virtual stereo and listen to the difference in the types of sound systems your company offers. Figure 1.4 shows an example of a music selection program.
1 FUNDAMENTALS OF DIRECTX PROGRAMMING
and ActiveX-compliant programs to access the advanced graphics, sound, and multiplayer technologies reserved for the C developers. This addition has opened the floodgates for DirectX development. With DirectX, VB developers can now create the games they always wanted, the multimedia projects they had to rely on C++ for, and much more.
13
14
VB.NET and DirectX Development PART I
FIGURE 1.4 Music and sound.
User Interactions What good is a program if users can’t interact with it? One of the foundations of multimedia is the process of incorporating users’ input into the experience. This feature draws users into your application and lets them decide the course of action. They can choose what doors to open on a virtual car, or they can move a joystick to defend the galaxy from its worst enemies. Through multimedia interaction, you can pull the user into your application. In Figure 1.5, the user interface allows the user to choose an answer to a trivia question.
FIGURE 1.5 Trivia question user interaction.
Fundamentals of DirectX Programming CHAPTER 1
Screensavers and Multimedia
FIGURE 1.6 Screensavers.
Game Programming Game programming, of course, is a big part of the DirectX experience. With DirectX, games can be created for the Windows platform with less code. Because DirectX uses standard hardware drivers, there is better control over the hardware itself, which results in better hardware performance. Figure 1.7 showcases a simple game with a snowman as the main character.
Synchronizing Data One of the really remarkable features of DirectX is its ability to synchronize data across modems, a network, or even the Internet. With this feature, it’s possible for developers to make complex programs that send and receive transmission packets across the great divide. A good example of synchronizing data can be seen in Figure 1.8, which shows an application that allows users to talk with each other instantly across the Net.
1 FUNDAMENTALS OF DIRECTX PROGRAMMING
One of the fascinating things that can be done with DirectX is creating screensavers. Through Visual Basic, screensavers and similar multimedia applications have been around for some time. The advantage of DirectX coming onto the scene is that the graphics are much faster and smoother, the sound quality is much better, and the overall experience is much more enjoyable. Figure 1.6 shows a simple screensaver with animated bouncing balls.
15
16
VB.NET and DirectX Development PART I
FIGURE 1.7 Snowman game.
FIGURE 1.8 Synchronizing data.
The DirectX Components The DirectX architecture is made up of many components. You can work with 3D graphics by way of Direct3D. DirectDraw gives you access to many of the animation technologies used in the game industry for decades. DirectInput enables you to understand user input from the keyboard, mouse, and joystick devices. DirectMusic and DirectSound give you access to the sound used in games today. Network capabilities, which are popular in many of today’s games, come to you in DirectPlay. DirectX has not forgotten about ease of setup, either, so DirectSetup, which supplies an easy-to-install interface for DirectX, is included with the other DirectX components. Figure 1.9 shows a hierarchical layout of all the components that make up DirectX.
Direct3D For those of you who love 3D animations, Direct3D is a fantastic addition to DirectX. With Direct3D, you can use DirectX to create complex 3D graphics on hardware that supports 3D rendering. The Direct3D component includes lighting effects, materials, and shading. Direct3D is also referred to as the DirectX Graphics component.
Fundamentals of DirectX Programming CHAPTER 1
1
DirectX
Direct3D (DirectX Graphics)
DirectInput
DirectAudio
DirectMusic
Direct Show
Direct Play
DirectSetup
DirectSound
FIGURE 1.9 An architectural overview of the DirectX object model.
DirectDraw DirectDraw is the heart and soul of DirectX 2D graphics, giving you many of the features needed for basic animation, such as blitting, clipping, and flipping. These techniques of DirectDraw animation are discussed in more detail in Chapter 3, “Animation Techniques.” DirectDraw provides the methods for developers to talk directly to the graphics hardware without having to learn how each piece of hardware works. It allows for complete hardware independence.
DirectInput DirectInput enables the developer to open up communication with the input devices needed in computer games and multimedia. DirectInput supports keyboard, mouse, and joystick devices. DirectInput can also control the features of ForceFeedback devices, such as the Microsoft SideWinder Force Feedback game controller.
DirectMusic If your program needs music, then DirectMusic is for you. DirectMusic offers complex composition abilities as well as complete playback for multimedia applications. You can also add Direct Music soundtracks to multimedia applications to make them more appealing to users. DirectMusic is a subcomponent of the DirectAudio library.
DirectPlay Network games and applications are becoming an essential part of the game genre. To that end, DirectX has a component called DirectPlay that provides easy network access to your games. DirectPlay supports Lobbies, Messaging, and management of network traffic. It also supports TCP/IP, internetwork packet exchange (IPX), modems, and serial connections. With this technology, developers can take their games to the Net quickly and easily. This technology can also be used to create messaging applications similar to MSN Messenger Service or AOL’s Instant Messenger. Some companies are rumored to have used this technology in their airline ticketing programs.
FUNDAMENTALS OF DIRECTX PROGRAMMING
DirectDraw
17
18
VB.NET and DirectX Development PART I
DirectSetup DirectSetup enables you to easily distribute DirectX with your application. With this component, your application can be packaged into a nice neat setup; when it’s installed, all the libraries and support files are there where the user needs them.
DirectShow DirectShowoffers you some interesting capabilities. With DirectShow, you can create presentations much like PowerPoint slides with interesting effects, sound, and video combinations. You can also use this technology in creating DVD playback utilities for kiosks and other applications.
DirectSound Sound is what makes a game seem more realistic, so the more realistic the sound, the better the game. DirectSound provides mixing, hardware acceleration, and direct access to the sound device. You can use this component to make car doors slam, horns honk, and birds chirp. DirectSound is a subcomponent of the DirectAudio library.
Summary This chapter has given you an overview of the history of DirectX. You have taken a look at the early days of programming for multimedia and seen how the need for faster graphics and better-quality games and multimedia helped drive the creation of DirectX. To help you understand why Visual Basic is currently the language of choice and why DirectX is now available, this chapter has discussed the reasons multimedia and games were developed in languages besides Visual Basic for many years. You have also briefly explored the common uses of DirectX, such as showcasing products with kiosks with information for consumers; incorporating user interaction; creating screensavers, games, and other multimedia applications; and synchronizing data. You’ve also learned about the DirectX features available for multimedia development. The DirectX components enable you to incorporate 3D features with Direct3D; use the animation capabilities inherent in DirectDraw; register user input with DirectInput; add soundtracks to your application with DirectMusic; create a multiuser application with the network and modem capabilities of DirectPlay; package your DirectX application with DirectSetup; add DVD and slide effects with DirectShow; and use sound effects with DirectSound. This chapter concludes your evaluation of DirectX from a bird’s-eye view. In the next chapter, you will see how Visual Basic and DirectX work together.
CHAPTER
Multimedia Programming in the Visual Basic Environment
2
IN THIS CHAPTER • Installing DirectX
20
• Setting Up DirectX for Use in Visual Basic • Classes and Objects
22
• Programming Tips to Improve Animation • DirectX Utilities
31
• Compiling for Speed: Tips and Tricks • Summary
37
20
35
25
20
VB.NET and DirectX Development PART I
This chapter focuses on how the Visual Basicenvironment needs to be set up to take advantage of the DirectX libraries. In this chapter, you will learn how to install DirectX and add references to the DirectX libraries in VB. You will look at common multimedia design considerations, such as timers, execution loops, and error trapping. You will also learn about the DirectX utilities that are installed with DirectX. Finally, this chapter will focus on compiling your DirectX code for optimal performance.
Installing DirectX The DirectX SDK can be downloaded from Microsoft’s DirectX Web site. The setup is very easy and allows you to install two versions: DirectX runtime or debug (shown in Figure 2.1).
FIGURE 2.1 Selecting the DirectX installation version.
For the projects you will be looking at in this book, it’s advised that you use the debug version. You can change from the debug to the release version of DirectX at a later time by using the DirectX console, which is described later in this chapter. After you have finished installing the DirectX SDK, you can begin setting up the files to be used with the VB environment.
Setting Up DirectX for Use in Visual Basic Before you can begin working with DirectX in the VB environment, you should understand some of the necessary items to make this transition easier. Among them is the ability to create a reference to DirectX within VB. You will also need to understand how to reference the DirectX objects. Finally, this chapter gives you some tips on performance enhancement to help your applications run more efficiently.
Multimedia Programming in the Visual Basic Environment CHAPTER 2
21
Creating a Reference to the DirectX 8.0 type Library For DirectX to work in a VB application, you need to create a reference to the DirectX 8 type library. This reference tells the VB project where to find information on the DirectX objects you’ll be using in your program. Without this reference, VB would have no idea what you were talking about, resulting in runtime errors when you try to compile your program. To create a reference to the DirectX type library for VB, you must have the DirectX 8 SDK installed. All the examples used in the book text and on the net require the DirectX 8 SDK to be installed. You can get the DirectX 8 SDK from Microsoft’s Web site. To create the reference, follow these steps: 2. Click the Standard EXE icon on the New section (shown in Figure 2.2), and click OK.
FIGURE 2.2 The VB New Project Dialog.
3. Choose Project, References from the menu in the project window to open the Reference dialog box, shown in Figure 2.3. 4. Look for the components labeled DirectX 7 for Visual Basic Type Library and DirectX 8 for Visual Basic Type Library. Check each component to add it to the project (see Figure 2.4), and click OK.
NOTE If you are not going to be using the DirectDraw capabilities of DirectX in your application, there’s no need to reference the DirectX 7 type library. DirectDraw is discussed in detail in Chapter 4, “Creating Graphics with DirectDraw.”
MULTIMEDIA PROGRAMMING
1. Open Visual Basic 6.
2
22
VB.NET and DirectX Development PART I
FIGURE 2.3 The References dialog box.
FIGURE 2.4 The DirectX type libraries.
Classes and Objects Classes are basically user-defined types that can be created and managed very easily. They give you the advantage of objectivizing your program into smaller components. For example, if I had a game that included small alien craft coming down on an unsuspecting settlement, I could create a class called alien. Then by using the alien class, I create an army of aliens. Using classes simplifies my development work because any time I need a new alien, I just create an instance of the class and change the parameters I need. Instant aliens! By using classes, I can also create objects that represent every aspect of the game. I can create a player object, an alien object, a missile object, and so on. Then my game development
Multimedia Programming in the Visual Basic Environment CHAPTER 2
23
simply becomes a process of organizing when each object shows up and how it reacts to other objects. This same principle can be used in any kind of development effort. Of course, you have to be able to access DirectX before you can create classes from the DirectX objects. To do that, you need the help of COM.
COM COM, which stands for Component Object Model, is a binary-level specification that describes how a series of components can communicate. At the binary level, COM components can be written in any language that supports its standard. This makes COM a universal format.
For example, by using COM you can use much of the functionality of Microsoft Word in your program. In the following code sample, you’re actually creating a Word document in memory. With your new mWord object, you can access all the features of Microsoft Word. Does anyone need a spellchecker? Dim mWord as Word.Application Set mWord = New Word.Application
You’ll hear more about COM because you’ll be using it to reference DirectX objects and gain access to their libraries.
Creating DirectX Objects Creating the DirectX object is the first part of developing in VB. After creating DirectX COM objects, you can then use their methods, properties, and attributes. First, however, you must create a reference to the DirectX type library for your project.
Declaring the DirectX Object The first thing to do in your development code is create an instance of your DirectX object. To do this, type the following code in the VB code window: ‘’’ This line declares your DirectX8 COM object Dim oDX As New DirectX8
2 MULTIMEDIA PROGRAMMING
COM gives you the power to use the functionality found in type libraries and other programs. To do that, you simply declare a COM component whose libraries you can reference and then assign an object variable to that declared COM component. This method enables you to reuse code that the DirectX developers created, without having to do everything from scratch.
24
VB.NET and DirectX Development PART I
Declaring a DirectX8 object in VB.NET This same code can be used in VB.NET. The code below shows how you would declare a DirectX COM object: ‘’’ This line declares your DirectX8 COM object Dim oDX As DxVBLibA.DirectX8 = New DXVBLIBA.DirectX8()
After creating the parent object, you can then create the child objects by simply declaring the object you want to work with. In the code snippet below, we are declaring a Direct3D object. ‘’’ This line declares your DirectX8s Direct3D object Dim oD3D As Direct3D8
Declaring a Direct3D object in VB.NET This same code can be used in VB.NET. The code below shows how you would declare a Direct3D COM object: ‘’’ This line declares your DirectX8s Direct3D object Dim oD3D As DxVBLibA.Direct3D8
Accessing the Object Attributes To use all the features of DirectX, it’s a good idea to become familiar with the major components and their supporting subcomponents. You’ll find that a few DirectX components, such as Direct3D8, have only one subcomponent that needs to be declared. However, other components, such as the DirectPlay component, have many subcomponents that represent different pieces of functionality available to their parent object. Refer to Chapter 1, “Fundamentals of DirectX,” for a full overview of the DirectX components and their major relationships. Table 2.1 shows all the creation methods for each of the DirectX components. TABLE 2.1
DirectX Components and Subcomponents
Component
Subcomponents
DirectX Creation Method
DirectDraw Direct3D DirectInput DirectMusic
DirectDraw7 Direct3D8 DirectInput8 DirectMusicComposer8 DirectMusicLoader8 DirectMusicPerformance8
DirectDrawCreate Direct3DCreate DirectInputCreate DirectMusicComposerCreate DirectMusicLoaderCreate DirectMusicPerformanceCreate
Multimedia Programming in the Visual Basic Environment CHAPTER 2
TABLE 2.1
25
Continued
Component
Subcomponents
DirectX Creation Method
DirectPlay
DirectPlay8Address DirectPlay8Client DirectPlay8LobbiedApplication DirectPlay8LobbyClient DirectPlay8Peer DirectPlay8Server DirectPlay8VoiceClient DirectPlay8VoiceServer DirectPlay8VoiceTest DirectSound8 DirectSoundCapture
DirectPlayAddressCreate
DirectPlayLobbyApplicationCreate DirectPlayLobbyClientCreate DirectPlayPeerCreate DirectPlayServerCreate DirectPlayVoiceClientCreate DirectPlayVoiceServerCreate DirectPlayVoiceTestCreate DirectSoundCreate
DirectSoundCaptureCreate
For example, if I wanted to create a DirectDraw object, I would use the method DirectDrawCreate in my code to create one.
Programming Tips to Improve Animation Programming for animation is not an easy task. To animate well, you must always be aware of factors such as timing, execution flow, and proper handling of errors in all phases of execution. With this in mind, you will need to learn to use timers to control the animation speed of your code. You also need to learn to create an easy-to-follow execution loop and to understand how to trap errors in your code as they occur. Finally, to help with the whole DirectX development process, understanding all your debugging tools in VB is imperative.
Timers Timers, which are used to create consistent display rates, increment at set intervals. You then check these intervals to determine what action needs to be take place next. The most common use for timers is to animate screen objects. Imagine that you’re creating an animation of a dog running across the screen. Every 1/24th of a second, you want to display one frame of animation. You accomplish that by checking to see whether the interval (1/24th of a second) has passed and displaying the next frame. Of course, you could just use a loop and display the frames one at a time, but you don’t have any control over exactly when the frames are displayed. The other advantage you get from timers is the ability to place your programs on fast computers or slow ones and still have a consistent frame rate. Instead of being dependent on how fast
2 MULTIMEDIA PROGRAMMING
DirectSound
DirectPlayClientCreate
26
VB.NET and DirectX Development PART I
your loop runs, you’re depending on a timer function to tell you when the next animated frame should be displayed. DirectX supplies a timer function called TickCount. Tickcount can be used for many purposes, but for high-speed animations, it’s not sufficient. Therefore, I’m going to introduce you to a Windows API function called GetTickCount. In the following example, GetTickCount checks to see whether 100ms of time have passed since you last checked the time. If it has, then you know that one second of time has passed, and you can draw your next frame of animation. If not, you loop and begin the time-checking process all over again. Because GetTickCount is more accurate than TickCount, you achieve a much smoother-looking animation. ‘’’ Declare the GetTickCount function that you are accessing Private Declare Function GetTickCount Lib “kernel32” () As Long ‘’’ Start your loop Private Sub AnimationLoop() Dim lTickCount As Long Dim lLastTickCount As Long Dim bComplete as Boolean Do While Not bComplete lTickCount = GetTickCount() If (lTickCount - lLastTickCount) >= 100 Then ‘’’ Draw a frame of animation DoEvents ‘’’ Forces the program to finish what it’s doing ‘’’ Reset your counter lLastTickCount = lTickCount End If Loop End Sub
Using the GetTickCount function in VB.NET This same code can be used in VB.NET. The code below shows how you would declare and use the GetTickCount function. ‘’’ Declare the GetTickCount function that you are accessing Private Declare Function GetTickCount Lib “kernel32” () As Long ‘’’ Start your loop Private Sub AnimationLoop() Dim lTickCount As Integer Dim lLastTickCount As Integer
Multimedia Programming in the Visual Basic Environment CHAPTER 2
27
Dim bComplete As Boolean Do While Not bComplete lTickCount = GetTickCount() If (lTickCount - lLastTickCount) >= 100 Then ‘’’ Draw a frame of animation ‘’’ Forces the program to finish what it’s doing System.Windows.Forms.Application.DoEvents()
Execution Loops Most games and some multimedia applications have execution loops, which provide a way for an application to continue until a certain event happens. The event could be the player’s character dying, or the player deciding to quit the application. For whatever reason, you must create a loop that continues collecting user input, processing that input, and displaying information until a specific set of conditions is met. The execution loop usually starts after some initialization has taken place. For example, if you want to allow users to choose a name for their characters and the level of play, this process could be in its own loop. When the selection is finished and all the variables set, you would exit that loop. When the user says to continue, you could start your execution loop with all the variables for game play set. Execution of the game would continue with drawing, sound, music, and input detection going on in every cycle of the loop. At the end of the loop, you would probably check for any problems, such as players deciding to quit or their ship blowing up. Then you would exit the loop. This process is the same one you would use if you were making a multimedia kiosk showing off sports car models or selling movie tickets. Figure 2.5 shows a typical execution loop that first initializes the information you are going to work with, and then it monitors for input, animates the objects, processes the input, and produces sound effects.
2 MULTIMEDIA PROGRAMMING
‘’’ Reset your counter lLastTickCount = lTickCount End If Loop End Sub
28
VB.NET and DirectX Development PART I
Initialization Screen
Is Application Over?
Yes
End
No
Monitor Input
Animate Objects
Process Input
Activate Sound
FIGURE 2.5 An execution loop.
The following subroutine shows how an execution loop would be coded: Private Sub ExecutionLoop() gbGameOver = False ‘’’Process the execution loop until the gbGameOver ‘’’variable is set to True. ‘’’-----------------------------------------------Do ‘’’Call function to monitor the user input ‘’’-----------------------------------Call MonitorInput ‘’’Call function to move ships ‘’’--------------------------Call MoveShips
Multimedia Programming in the Visual Basic Environment CHAPTER 2
29
‘’’Call function to draw the ships on the screen ‘’’--------------------------------------------Call DrawShips ‘’’Call function to activate sounds such as explosions ‘’’--------------------------------------------------Call ActivateSound Loop Until gbGameOver End Sub
2
Error Trapping
MULTIMEDIA PROGRAMMING
As in most programs, error handling is key to a good program. If you are unable to create a DirectX object, your code should stop execution and handle the problem correctly. Failure to do that properly can cause unpredictable behavior in DirectX. It can also give your users the opinion that the program is inferior. To this end, it is a good idea to incorporate a general error handling subroutine. This subroutine can be accessed inside of your other subs and functions. When an error is encountered within the bad function, it will call the error handling subroutine and pass it data about the error and where it was discovered. The following example shows how to trap an error in the Form_Load subroutine. When an error is encountered, the Form_Load subroutine will pass the error information to a generalpurpose error module that can then decide what to do about the error. The current resolution in this code sample is to simply display the error. To call the subroutine: Private Sub Form_Load() On Error GoTo Err_Form_Load ‘’’ ‘’’ Your code goes here. ‘’’ Exit Sub Err_Form_Load: ‘’’ If the error is not handled in here then ‘’’ pass it to the DisplayError subroutine DisplayError “Form_Load” End Sub
30
VB.NET and DirectX Development PART I
This is saved in a module with the project: Public Sub DisplayError(szLocation As String) MsgBox “Method:” & vbTab & vbTab & szLocation & _ vbCrLf & “Source:” & vbTab & vbTab & Err.Source & _ vbCrLf & “Error:” & vbTab & vbTab & Hex(Err.Number) & _ “h (“ & CStr(Err.Number) & “)” & vbCrLf & _ “Description:” & vbTab & Err.Description, vbCritical, “” End Sub
NOTE It’s essential to trap for errors in every major function or subroutine in your code. This prevents the error from getting away from you and causing bigger trouble in another subroutine.
Debugging Knowing your debugger can help you out of many tough spots in VB. When developing with DirectX, it’s helpful to be able to see what the objects are doing, so you need to understand all the debugging options available to you in VB. Some of the most common debugging tools available are explained in the following sections.
Output Window The Output window allows you to view debug output from your application as well as enter code to run during a break. With this window, you can change variables, view data in variables and objects, and run additional lines of code as necessary.
Watch Window You can use the Watch window to see all the properties of currently active objects. You can see what each of the parameters are set to at the exact instant that code execution pauses. This feature helps you determine when a problem has occurred.
Step Over/Into During the debugging process, sometimes you need to step through your code. With the Step Over debugging tool, the developer can skip functions that don’t have to be stepped through. Step Into gives the developer the opportunity to step into a subroutine or function and continue execution within that portion of the code.
Breakpoints Breakpoints are stop signs in code that allow the developer to stop execution at the exact moment a specific line of code is called. They are helpful when your code gets very large, and
Multimedia Programming in the Visual Basic Environment CHAPTER 2
31
you’re trying to find out where the problem is occurring. You can move the breakpoints up the code tree until you get near the problem area, making it easier to get to the broken area during execution.
DirectX Utilities The DirectX 8 SDK provides many utilities that can be used in testing and configuring your DirectX application. They are located under DirectX Utilities on the Microsoft DirectX 8 SDK menu (see Figure 2.6).
2 MULTIMEDIA PROGRAMMING
FIGURE 2.6 Finding the DirectX utilities.
These utilities can come in handy during the development and testing phases of a project. The following sections explain how each of these utilities work.
DirectX Caps Viewer The DirectX Caps Viewer displays information about the current machine’s DirectX capabilities. With this tool, you can see whether your video card can support certain features of DirectDraw, DirectSound, and so forth. All the capabilities (Caps, for short) are displayed for the installed DirectX compatible components. This utility gives the developer detailed information on the video cards, sound cards, network connections, and input devices of the current machine. Figure 2.7 shows the DirectX Caps Viewer supplying information for a machine with a Riva TNT video card.
DirectX Error Lookup DirectX Error Lookup is a simple utility designed to quickly give you information about an error that may be returned in your DirectX code. By simply copying the error’s binary number into this program, you can then look up the description of what it means. Figure 2.8 shows the DirectX Error Lookup utility.
32
VB.NET and DirectX Development PART I
FIGURE 2.7 The DirectX Caps Viewer.
FIGURE 2.8 The DirectX Error Lookup utility.
DirectX Texture Tool The DirectX Texture Tool lets you experiment with textures you want to use in your application. With this tool, you can load a texture and then apply filters to see the visual effects you can get with your texture. This utility is a great way to experiment with textures before writing a bunch of code to manipulate them. Textures are used extensively in Direct3D. See Chapter 9, “Advanced Direct3D Features,” for more information on using textures. Figure 2.9 shows the DirectX Texture Tool with a speckled background being viewed.
DMO Test Tool With the DMO Test tool, you can run a series of predefined tests against a DirectX Media Object (DMO). DMOs are primarily used for effects with DirectAudio (see Chapter 15, “DirectX Audio—DirectMusic and DirectSound”). With a DMO you can set specific effects such as “gargle” to a sound buffer. This tool’s primary function is to verify that a DMO meets strict standards before you distribute it. Figure 2.10 shows the DMO Test tool.
Multimedia Programming in the Visual Basic Environment CHAPTER 2
33
2
The DirectX Texture Tool.
FIGURE 2.10 The DMO Test tool.
Force Feedback Editor With the Force Feedback Editor, you can test many force feedback configurations so that you can develop a scenario for your application. This tool acts as a special-effects studio where you can try out force feedback effects before writing the code to implement them. Chapter 13, “The Joystick,” explains force feedback in more detail. Figure 2.11 shows the DirectX Force Feedback Editor.
MULTIMEDIA PROGRAMMING
FIGURE 2.9
34
VB.NET and DirectX Development PART I
FIGURE 2.11 The Force Feedback Editor.
GraphEdit Tool The GraphEdit tool is a utility designed to give you a testing resource for your filter graphs. With this tool, you can open supported graph files and run them through filters to test their final results. For example, using this tool you can add the “gargle” effect mentioned previously to an audio stream and hear the results immediately in this unique UI. Graph filters are discussed more in Chapter 18, “Introduction to DirectShow.” Figure 2.12 shows the GraphEdit tool.
FIGURE 2.12 The GraphEdit tool.
Multimedia Programming in the Visual Basic Environment CHAPTER 2
35
Kill Help Utility The Kill Help utility is used in those cases when the ddhelp process might become hung. On Windows 9x machines, this problem sometimes occurs while debugging DirectX applications. If that happens, you can simply select this tool and it will unload the process for you. Do not look for a screen to appear when you use this utility. It works completely in the background and takes only about a second to complete.
Mesh Viewer Tool
Figure 2.13 shows the Mesh Viewer tool with a mesh of a dolphin.
FIGURE 2.13 The Mesh Viewer tool.
Compiling for Speed: Tips and Tricks Speed in multimedia applications is one of the most important elements. You may have a greatlooking kiosk, but if it’s too slow, people might not use it again. To avoid that problem, you can use optimization techniques to speed up your program’s performance. In the following sections, I offer a list of suggestions to keep in mind while creating your DirectX application. Use these suggestions as a checklist to help you optimize the speed of your multimedia applications.
2 MULTIMEDIA PROGRAMMING
With the Mesh Viewer, you can load different meshes and manipulate their attributes to see their effects on your mesh. A mesh is a geometric representation of an object through numbers. Meshes are discussed in Chapter 9.
36
VB.NET and DirectX Development PART I
Remove Unused Subroutines Functions and subroutines that are not being used can slow down performance. It’s always a good idea to see whether all the subroutines in your code are being used; if they’re not, comment them out or remove them. In other programming efforts, it doesn’t really hurt to leave unused subroutines and functions. With DirectX, however, you want everything to be at its most optimized state.
Remove Unused Variables Variables that are not being used in code still take up memory and cause your code to run inefficiently. It’s always wise to check your subroutines for variables that are not being used. A simple search of global variables and a quick search in each of your subroutines and functions should reveal any orphaned variables.
Reduce Access Times Keep the number of times you are reading from slow data sources down to a minimum. The main culprits are CD-ROMs and databases. Load as much of your graphics and data into RAM as possible at the start of your program. This method creates a slow initial load time that can be covered up with a splash screen, but the execution time will be much faster overall.
Destroy All Objects After your program finishes with an object such as the DirectDraw object, you need to make sure it has been destroyed completely by using the Set = Nothing syntax = Nothing syntax> = Nothing syntax>. Failure to do this can cause memory leaks and unstable behavior.
Remove Debug Statements A statement such as Debug.Print slows down execution in VB significantly. Contrary to popular belief, Debug.Print statements don’t get removed at compile time. When debug statements are not needed any more, remove them.
If you want to try some of this code in VB.NET VB.NET provides a migration tool that converts VB6 code to VB.NET. To use it, simply open your VB6 program with the VB.NET interface. If you are porting VB6 DirectX code to VB.NET, it’s wise to keep in mind that the migration tool might not always create the most efficient code. Check it carefully. For example, during the conversion, VB.NET might use VB6() functions to keep some backward-compatibility instead of formatting the line of code in the new VB.NET standard.
Multimedia Programming in the Visual Basic Environment CHAPTER 2
37
Add DoEvents The DoEvents method is used extensively in VB and DirectX to enforce smooth animations. DoEvents forces windows to finish processing all messages in the queue before it continues on to the next line of code. Keep in mind that if you see jerky movements, try using an DoEvents method before and/or after the statement that’s giving you a problem.
Summary In this chapter, you have seen how to configure DirectX environment for use with VB, including how to make the necessary references for your code to recognize DirectX commands.
In the course of this chapter, you learned some programming techniques to improve animations, such as timers for creating a smooth animation and execution loops for ensuring a logical flow to your program. The chapter also explained error trapping, along with a code example of how to accomplish good error trapping; the debugging tools available in VB; and the DirectX utilities. With these utilities, you can view the capabilities of your DirectX hardware and software, get a preview of your 3D textures, test force-feedback routines, and examine the drivers on your system. Finally, you learned some VB optimization techniques to aid in the speed and efficiency of your code. In the next chapter, you will take a look at animation techniques and how to incorporate those techniques into your DirectX programs.
MULTIMEDIA PROGRAMMING
Some common programming conventions, such as classes and objects, were reviewed to show you how to organize programs for more reusable code and cleaner execution. You also had an overview of COM and ActiveX and how they enable DirectX and VB to communicate. To round out the overview of multimedia programming, you learned how each of the major DirectX subcomponents are created.
2
Animation Techniques
IN THIS CHAPTER • The Basics
40
• DirectX Objects • Techniques • Summary
48 50
43
CHAPTER
3
40
VB.NET and DirectX Development PART I
Many of us grew up watching cartoon characters every Saturday morning, but we never really appreciated the work that went into making them. In this section of the book, you’ll be looking at animation techniques that have been around for many years. These techniques gave birth to talking rabbits, wacky ducks, and a mouse named Mickey. Animation is the art of creating the illusion of movement from inanimate objects. Before we had full-motion moving pictures, there was animation. Flipbooks were small books with pages where small caricatures were drawn. As you flipped the books from front to back, the drawings looked as though they were animated. Some flipbooks came empty, and you could add your own drawings. Flipbooks gave the illusion that the cartoon character in the pages was actually moving before our eyes. This illusion is the cornerstone of animation. With some simple animation techniques, you can add impressive flare or sex appeal to your multimedia applications.
The Basics In this section, you’ll be looking at the basics of traditional animation—how animators have been able to achieve lifelike expressions of many different objects. This is by no means a thorough explanation of animation, only an introduction to make DirectX easier to understand.
The Model Sheet If you’re going to create a character to animate, it usually helps to have a model sheet, which is a series of poses of the character to refer to when you’re animating. The sheet could include poses of the character standing still, bouncing a ball, smiling, jumping, and running, for example. The idea is to draw the emotions and actions that would be expected from the character. If your animations are going to be much simpler than an animated person or animal, however, a model sheet might not be necessary.
The Frame A frame is a snapshot in time. If you were to take your favorite animated movie and pause the playback for a split second, you would see one frame of animation. Imagine a bird in flight. If you could stop this bird while it was flying along its course, you might see the wings folded slightly. Maybe its eyelids are opening or closing, and maybe the beak is slightly open. If you paused the playback a second later, the next frame would look different. Figure 3.1 shows a single frame of animation in which a spinning donut is frozen in time.
Animation Techniques CHAPTER 3
41
FIGURE 3.1 A frame of animation.
The Cycle Animation moves in cycles, and a cycle is a series of frames that make up an action. For example, the cycle of walking can be made up of about eight frames. This cycle begins with the character picking up his right foot with his right shoulder raised slightly. The cycle continues until frame 4, where the right foot is back on the ground. Then the same process happens with the left foot. Finally, frame 8 ends with the left foot being put back on the ground. Cycles can be repeated, if necessary, thus reducing the need for creating the animated frames from scratch. When frame 8 of the walking cycle is finished, for example, just start over with frame 1. The character can walk on forever, if you want.
FIGURE 3.2 An animation cycle.
Storyboards I’ve talked about how to go from an individual split second in time into a cycle. Now comes the question “How do I decide what I need and how it’s organized?” This is where the storyboard comes in. Storyboards are a series of small panels showing major scenes of action in the animation. Storyboards were brought into the mainstream of animation with the Walt Disney studios, which perfected their use. Through the use of a storyboard, lead animators could create sample drawings of the scenes as they imagined them and write in the dialogue just
3 ANIMATION TECHNIQUES
A complex animation, such as those seen in cartoons, is made up of many individual cycles. For example, the character moves to a specific spot (cycle 1). The character stands and acts as though he or she is thinking about something (cycle 2). The character suddenly does an aboutface (cycle 3). Finally, the character walks back the way he or she came (cycle 4). Figure 3.2 shows four cycles of a character walking in four different directions. Each cycle in the figure is made up of three frames.
42
VB.NET and DirectX Development PART I
below the storyboard panes. Today developers of multimedia applications use similar processes to organize the action before they begin actual development. Figure 3.3 shows a section of a much larger storyboard used to explain the action of a scene. 19
20
A ball bounces into the scene.
Calvin points at the ball. Calvin: What's that doing here? I thought I got rid of it.
21
The ball gently sways back and forth in the wind. George: Mabe it just came back because it missed you. [George snickers]
FIGURE 3.3 A storyboard.
Keyframes Lead animators would then take these storyboard scenes and create individual frames of the animation at specific pivot points in the action. These points are called keyframes. Keyframes are drawn where parts of the character’s body reach their full range of motion. For example, an arm can bend only so far back before it breaks. If the character has reached that point in the animation, then that frame of animation should be a keyframe. The same goes for head movements and any body appendages. These drawings create the templates from which other animators can create the finished frames of the cartoon.
Backgrounds So you’ve created an animation. It looks fantastic, but it’s just bouncing around on a blank screen. Now you need to create a background, which is the environment you want to add to your scene that helps set the mood for the animation. Backgrounds were painted in most earlier animated cartoons, but more and more of them have moved to using computer-generated backgrounds. This type of background is very similar to what you’ll be working with in DirectX. You can create backgrounds with many different paint programs because DirectX can use almost any popular graphics format.
Animation Techniques CHAPTER 3
43
DirectX Objects DirectX makes use of early animation technologies, but has added a few tricks of its own. This section describes DirectX objects and concepts used throughout the computer animation community.
Frame Rates Frame rates are basically the speed at which frames or cels of animation are shown, expressed in number of frames per second of time. A normal frame rate for animated motion pictures is 24 frames per second (fps). With computer animation, frame rates look much better at about 40fps–50fps. When working with DirectX programming, frame rates are one of the most important factors to keep in mind. If the frame rate of the animation you’re producing is too slow, the user will be bored by your animation. If it’s too fast, it will look unnatural, perhaps making the user think something is wrong with the machine. Therefore, you need to make sure the frame rate is a constant one that’s pleasing to the eye.
Blits Blit, an acronym for “bit block transfer,” is the process of moving sections of data from one memory space into another. After you assemble the frame of animation you want to show, you must then move it from the back drawing surface to the front drawing surface, where the user can see it. To do that, you use blits. Blits can transfer a full screen of information from one memory buffer to the other. They can also transfer a small rectangle of information. After the information is blitted to a surface, the surface can be flipped with another surface to change the image the user sees. Figure 3.4 shows how Blits are performed on an offscreen drawing sur-
3 ANIMATION TECHNIQUES
Frame rates are implemented in DirectX by how you send data to the video card. You want to make sure you send enough frames of your animation to the card to give you the results you need. However, not all video cards have the same capabilities, so you need to make sure you don’t overload the card. For example, if you know that your frame rate is going to be 50fps, but the average card specification for your users doesn’t support more than 30fps under this load, you could have a problem. A good rule of thumb when working with video cards is to look at trade magazines and online sites to determine what video cards are popular. Then you can choose from the bottom and top of that price range to determine the cards you should test. Also, using programs such as 3D Mark can help you determine the capabilities of various video cards. 3D Mark can be found at http://MadOnion.com. Using timers can help regulate frame rates. Chapter 2, “Multimedia Programming in the Visual Basic Environment,” discusses using timers to control frame rates.
44
VB.NET and DirectX Development PART I
face. The blit process and surfaces are explained in more detail in Chapter 5, “Creating Basic Animations with Surface Objects.”
Player Sprites (Surface 1)
Secondary Surface
Background (Surface 2)
Primary Surface
Scenary (Surface 3)
Flip
FIGURE 3.4 Blits being performed on an offscreen drawing surface.
Sprites Sprites are rectangles of data that contain an image. These small portions of the overall image are used to create the animation effect. Sprites can be used in the foreground to give you animation. For example, if you have a kiosk program that shows animated tickets moving across the screen, you would need to create a series of images for each unique frame of the animation. You could then save all the sprite images as one image, which is called a sprite strip. The sprite strip in Figure 3.5 shows a spinning donut in all four possible poses. You would then move the sprite around the screen by changing its coordinates and loading a different image every frame. Chapter 5 discusses sprites and how they are animated in a DirectDraw application.
FIGURE 3.5 A sprite strip.
Animation Techniques CHAPTER 3
45
Drawing Surfaces The drawing surface is where you assemble your picture for blitting; it can be thought of as the staging area for each frame of animation. The drawing surface can be made up of a background image and one or more sprites. During the process of blitting the image, this surface is transferred from the back buffer to the front buffer. Buffers and surfaces are explained in more detail in Chapter 5. There are three types of drawing surfaces used in animation: • Primary: The primary drawing surface is the one currently displayed on the screen. It’s what the user sees at all times. • Secondary: The secondary drawing surface is where you set up for the next frame of animation. When it’s time for the next animation frame to be displayed, it becomes the primary surface and the old primary surface becomes the new secondary. In essence, you force them to switch identities. • Offscreen: The offscreen drawing surface is where you assemble the content for the primary and secondary surfaces. This part of DirectDraw is always working to keep the primary and secondary surfaces full of information.
NOTE
Palettes Palettes are simply a list of colors available for the display, and you choose from this list when rendering the animation. The color depth required for your application determines the number of colors available in a palette. Just as it does for a painter, the palette defines the colors you have to work with in your project. When working with palettes, it’s a good idea to choose a color depth that gives you the best results for your animation work. It’s possible to change the palette at runtime when producing animations, however. This animation technique is good for full-screen animations that require fading, such as a sunset scene or movie credits.
ANIMATION TECHNIQUES
An offscreen surface is used only if your design for flipping uses three surfaces. Three surfaces are used in more complex animations, especially since the memory on the video card can help speed this process up. However, for simple animations you need to use only a primary and secondary surface.
3
46
VB.NET and DirectX Development PART I
Rectangles Rectangles are square areas of the screen that you define with an x1, y1, x2, y2 coordinate system. Many of the methods in DirectX need to know the area of the display that’s being modified. This is accomplished by passing a rectangle object that provides the coordinates of these areas. For example, if you have a small bug on the screen and you want to change its color, it’s easier to just pass in a rectangle object with the bug’s dimensions and location on your screen. You can tell the DirectDraw object where the bug is by passing in the Rectangle object that contains the location of the rectangle and its dimensions. In Microsoft Visual Basic, the RECT type has the following definition: Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type
‘ ‘ ‘ ‘
Top-left. X coordinate. Top-left. Y coordinate. Bottom-right. X coordinate. Bottom-right. Y coordinate.
In the preceding example, the Left and Top members are the x- and y-coordinates of a bounding rectangle’s top-left corner. Similarly, the Right and Bottom members make up the coordinates of the bottom-right corner. The following diagram in Figure 3.6 illustrates how you can visualize these values by showing how a rectangle (RECT) is measured on the screen.
x,y start
Rectangle x, end
Screen
FIGURE 3.6 A rectangle.
Clippers Clipping is the process of defining areas of the display that will show the animation. By marking off these areas, you are designating where it is okay for DirectDraw to write(or blit) on the
Animation Techniques CHAPTER 3
47
destination surface. An example of this technique can be seen in a shooting gallery. The duck targets move from one side of the screen to the other; however, you don’t want them to appear on the left and right sides of the shooting area because that would ruin the effect of your shooting gallery. You would need to define a clipper rectangle that encompasses the “shooting area” of the display. This technique gives the illusion that the ducks are going behind the curtain. Figure 3.7 shows a screen made up of clipper rectangles. Each of the four rectangles is part of a clipper list. The clipper list is associated with a clipper object, which in turn defines the area that can be used for animation. Any blitting that occurs outside this area will not show up on the screen. If a sprite crosses this boundary, only the part of the sprite that is within the clipper area is displayed. In the previous example of the shooting gallery, you would want the ducks to appear only in the “shooting area,” not in front of the curtains.
Clipping Rectangle | Clipping Rectangle 2 Area where no blitting can occur Clipping Rectangle 4
FIGURE 3.7 A screen with clipper rectangles.
Billboards Billboards are objects used to create the illusion of 3D objects without having to spend the resources on creating complex objects. This effect is accomplished by creating a plane object that’s moved in relation to the person viewing it, which produces the illusion that the object has many sides, even though it actually has only one side. The one side keeps moving in relation to the person viewing it. For example, if you were creating a driving game that had many trees along the sides of the course, you don’t want to create complex trees made up of thousands of polygons. The memory needed for that operation would be enormous, and your program’s performance would suffer. So you simply create a 2D image of a tree, attach it to a billboard, and move the billboard in relation to the user. The user doesn’t know the difference, and you save on performance. Figure 3.8 shows how billboards work.
ANIMATION TECHNIQUES
Clipping Rectangle 3
3
VB.NET and DirectX Development PART I
Frame 1
Travel
Bil lb
oa
rd
Billboard Travel
48
Frame 2
FIGURE 3.8 A billboard animation.
NOTE Billboards work well with objects that have a vertical nature, such as trees and signs. Make sure your users can’t view the objects from the top, however; otherwise, they’ll see that the objects are a facade, and your illusion will be ruined.
Techniques To understand how to use the objects you’ve been reading about, you need to look at the techniques used in DirectX to create animations. The techniques include blitting, page flipping, back buffering, and palette cycling.
Blitting Blitting is the process of taking rectangles from offscreen drawing surfaces and copying them onto primary or secondary drawing surfaces. Blitting is much like taking pieces of a jigsaw puzzle and assembling the finished product on a table.
Page Flipping and Back Buffering Page flipping is the process of cycling through the drawing surfaces, or pages. In back buffering, you populate these surfaces with new frames of information. With these two techniques, you can create true animation by creating a frame, displaying the frame, creating the secondary surface, and then displaying it. Figure 3.9 shows how page flipping occurs.
Animation Techniques CHAPTER 3
49
Page Flipping Before Flip Frame N
Person Sees
Primary Surface
Secondary Surface
Back Buffer
After Flip Frame N + 1
Person Sees
Primary Surface
Secondary Surface
Back Buffer
FIGURE 3.9
3
Page flipping.
Palette Cycling Palette cycling can best be visualized by imagining a painter’s palette. Painters use a palette of colors to create their paintings. Just imagine what would happen if they changed a few of the colors on their palettes to new colors, and that change resulted in the colors in their painting automatically changing, too. You would have the same painting, but with a few colors changed. If you continued to do that, some of the images in the painting would look animated, simply because you had changed their colors over and over. This effect is called palette animation, and this technique can be used to create psychedelic effects such as those popular in the ‘70s. You can also use it to create fading effects on objects and text to give the impression that they are appearing or disappearing.
ANIMATION TECHNIQUES
Before the flip occurs, users see a single vehicle going east. What they are seeing at that point is the primary surface. While this is going on, the secondary surface is being redrawn with an additional vehicle, a little bit larger, going west. When the flip occurs, the users’ view is changed to the secondary surface. In essence, the secondary surface in the previous frame is now the primary surface, and vice versa. Users now see both vehicles. Because the car going east will have traveled off the screen in the next frame, you remove it from the secondary surface. The secondary surface is now redrawn to get ready for the next flip.
50
VB.NET and DirectX Development PART I
Summary In this chapter, you have traveled through a brief history of animation, examining the tools of the trade: model sheets, frames, cycles, storyboards, keyframes, and backgrounds. You have also seen how blits and sprites are used to transfer and store images, learned how drawing surfaces are used to produce real-time animation through primary, secondary, and offscreen surfaces. You also saw how backgrounds and palettes can be useful for creating full-screen scenery and fading effects. Rectangles, you learned, are the foundation of measurements in DirectX, and are used to define the position of images and maintain their animations. Clippers are useful in restricting areas of the screen so that animations can appear to have depth to them. With billboards, you can create the illusion of large complex items, such as trees, without actually having to use the enormous processing power needed for high-end graphics. Finally, you got an overview of the three main techniques in DirectX animation: blitting, the process of placing sprites or images on the surface you’re assembling for display; page flipping (with the help of back buffers), used to move surfaces from front to back in rapid succession to create fast animation effects; and palette cycling, used to animate backgrounds for fading and psychedelic effects.
DirectX Graphics Programming
DirectX graphics programming uses the DirectX graphics object and DirectDraw object to create 2D and 3D graphics. This section focuses on all the major aspects of DirectX graphics, including palettes, basic animation, and 3D graphics. This chapter focuses on the most widely used of the DirectX objects: Direct Graphics.
IN THIS PART 4 Creating Graphics with the DirectX Graphics Object 53 5 Creating Basic Animations with Surface Objects 71 6 Palettes and Palette Animation 7 3D Geometry 8 Direct3D
101
113
9 Using Direct3D
153
89
PART
II
CHAPTER
Creating Graphics with DirectDraw
4
IN THIS CHAPTER • Creating Graphics with DirectDraw Classes 54 • HAL Versus HEL • Display Modes
62 63
• An Example Using the DirectDraw Class • Summary
69
65
54
DirectX Graphics Programming PART II
DirectDraw is the foundation of 2D graphics in DirectX. This chapter will introduce you to DirectDraw and how to use it to initialize the DirectDraw methods, the DirectDrawSurface class, the DirectDrawPalette class, and the DirectDrawClipper class. This chapter also discusses the Hardware Abstraction Layer and the Hardware Emulation Layer and how they can be used to overcome limitations with a video card. And finally, you will look at an example of DirectDraw code.
Creating Graphics with DirectDraw Classes DirectDraw is the oldest component of DirectX. Since the first version, animators have needed to create two-dimensional animations similar to those described in Chapter 3, “Animation Techniques.” Microsoft developers saw the need for fast-drawing animations in games and multimedia in the Windows future, so they developed an ever-increasing library of classes to DirectX called DirectDraw. This chapter gives you an overview of DirectDraw, with a focus on some of the video modes that DirectDraw supports. You’ll also look at the major DirectDraw classes that round out your 2D animating world.
What Is DirectDraw? DirectDraw is a technology that was the cornerstone of DirectX for most of its life. In DirectX 8, DirectDraw has taken a back seat, however, and much of its functionality has been absorbed into DirectGraphics. DirectDraw is accessible as part of the DirectX 7 DLL only. However, when you install DirectX 8, you will also get the DirectX 7 DLLs, so you still have access to these great libraries. For the purposes of the next few chapters, you’ll be looking at DirectDraw. Although most of its functionality has been put into Direct Graphics, you still have access to it because DirectX 8 is compatible with previous versions. There are many reasons to discuss DirectDraw, including the following: • DirectDraw can be used with standard VGA graphics cards. You do not need an accelerated 3D card. • Not all the DirectDraw features have been rolled into Direct Graphics, so there are some advantages to using DirectDraw. • DirectDraw is easier to use if you want to work with 2D graphics only, and you can get up to speed on basic animation techniques much more quickly with DirectDraw.
Creating Graphics with DirectDraw CHAPTER 4
55
NOTE DirectX 8 has a new technology called DirectGraphics, a combination of DirectDraw and Direct3D technologies all rolled up into one class. For those people concerned about DirectGraphics and how 2D animation can be done with it, don’t worry. You’ll see how that can be done in Chapter 5, “Creating Basic Animations with Surface Objects.”
DirectDraw Architectural Overview DirectDraw is made up of the DirectDraw class and its associated classes and methods that allow you to create related DirectX classes. These classes include palettes, clippers, and surfaces. Palettes are created by using the DirectDrawPalette class, surfaces by using the DirectDrawSurface class, and clippers by the DirectDrawClipper class. Figure 4.1 shows the relationship between these classes and DirectDraw.
DirectDraw
DirectDrawSurface
DirectDrawPalette
FIGURE 4.1 DirectDraw and its supporting classes.
The DirectDraw Class is the core class of DirectX. After declaring a DirectX class, you can then obtain a class. With this class, you can then obtain its subclasses, such as DirectDrawSurface and DirectDrawPalette. DirectDraw DirectDraw
CREATING GRAPHICS WITH DIRECTDRAW
DirectDrawClipper
4
56
DirectX Graphics Programming PART II
The following code syntax is an example of declaring and using the DirectDraw class: Dim oDD As DirectDraw7
This is how the code would look when included with the DirectX declaration: Dim oDX As New DirectX7 Dim oDD As DirectDraw7
Declaring a DirectDraw object in VB.NET This same code can be used in VB.NET. The code below shows how you would declare a DirectDraw object: Dim oDX As DxVBLib.DirectX7 = New DxVBLib.DirectX7() Dim oDD As DxVBLib.DirectDraw7
NOTE As you might have noticed in the previous example, I declared the DirectDraw class as DirectDraw7 because DirectDraw is no longer being updated in DirectX 8. For compatibility reasons, the class is always called DirectDraw7.
The DirectDraw Methods The DirectDraw class gives you access to many methods. The most commonly used methods are detailed in Table 4.1. TABLE 4.1
The Most Commonly Used DirectDraw Methods
Method
Syntax
Purpose
CreateClipper
DirectDraw7.CreateClipper
CreatePalette
DirectDraw7.CreatePalette
CreateSurface
DirectDraw7.CreateSurface
Creates a DirectDrawClipper class Creates a DirectDrawPalette class Creates a DirectDrawSurface class Creates a DirectDrawSurface class and attaches the specified bitmap image to this new class Finds the current display mode settings
CreateSurfaceFromFile DirectDraw7.CreateSurface FromFile GetDisplayMode
DirectDraw7.GetDisplayMode
Creating Graphics with DirectDraw CHAPTER 4
TABLE 4.1
57
Continued
Method
Syntax
LoadPaletteFromBitmap DirectDraw7.LoadPalette FromBitmap
RestoreAllSurfaces
DirectDraw7.RestoreAll Surfaces
SetDisplayMode
DirectDraw7.SetDisplayMode
Purpose Creates a DirectDrawPalette class, based on the palette of the specified bitmap for this DirectDraw class Restores all the surfaces created for the DirectDraw class Sets the display mode of the video card
The DirectDrawSurface Class is like your canvas; it’s the surface you use to assemble your animation frames on. You can have multiple surfaces to create the illusion of animation through page flipping. You can then flip each page in succession and assemble a back buffer surface in the background.
DirectDrawSurface
The following code syntax is an example of declaring and using the DirectDrawSurface class: Dim oDDPrimSurf As DxVBLib.DirectDrawSurface7
This is what the code would look like when included with the DirectX and DirectDraw declarations: ‘’’First you need to access the DirectX7 COM class Dim oDX As DirectX7
4 CREATING GRAPHICS WITH DIRECTDRAW
‘’’Next you need to create a DirectDraw class Dim oDD As DirectDraw7 ‘’’Then you need to create a DirectDrawSurface class Dim oDDPS As DirectDrawSurface7
Declaring a DirectDrawSurface object in VB.NET This same code can be used in VB.NET. The code below shows how you would declare a DirectDrawSurface object: ‘’’First you need to access the DirectX7 COM class Dim oDX As DxVBLib.DirectX7 = New DxVBLib.DirectX7() continues
58
DirectX Graphics Programming PART II
‘’’Next you need to create a DirectDraw class Dim oDD As DxVBLib.DirectDraw7 ‘’’Then you need to create a DirectDrawSurface class Dim oDDPS As DxVBLib.DirectDrawSurface7
DirectDrawSurface gives you access to many methods. Table 4.2 outlines some of the more commonly used ones.
TABLE 4.2
The Most Commonly Used DirectDrawSurface Methods
Method
Syntax
Purpose
AddAttachedSurface
DirectDrawSurface7.Add AttachedSurface
Blt
DirectDrawSurface7.Blt
BltColorFill
DirectDrawSurface7.Blt ColorFill
BltFast
DirectDrawSurface7.Blt Fast
BltFx
DirectDrawSurface7.BltFx
DrawText
DirectDrawSurface7.DrawText
Flip
DirectDrawSurface7.Flip
GetCaps
DirectDrawSurface7.GetCaps
GetClipper
DirectDrawSurface7.Get Clipper
GetColorKey
DirectDrawSurface7.Get ColorKey
GetDirectDraw
DirectDrawSurface7.Get DirectDraw
Attaches a specified surface to the current surface. Performs a bit block transfer (blit). Performs a bit block transfer (blit) of a single color to the specified destination rectangle. Performs a source copy blit or transparent blit by using a source color key or destination color key. Performs a bit block transfer with additional blit effects. Draws text on the current surface. Performs a memory swap with the back buffer surface and the front buffer surface. Finds out the capabilities of the current surface. Retrieves the DirectDraw Clipper class associated with the current surface. Retrieves the color key value for the current surface. Retrieves the DirectDraw class used to create the surface.
Creating Graphics with DirectDraw CHAPTER 4
TABLE 4.2
59
Continued
Syntax
Purpose
GetDirectDrawGamma Control
DirectDrawSurface7.Get DirectDrawGammaControl GetPalette
Returns the DirectDrawGamma Control class used with the surface. Retrieves the DirectDraw Palette class associated with this surface. Determines whether the surface memory allocated to a Direct DrawSurface has been released. Restores a surface that has been lost, which occurs when the surface memory associated with the DirectDrawSurface class has been released. Attaches a clipper class to, or deletes one from, a surface Sets the color key value for the DirectDrawSurface class if the hardware supports color keys on a per-surface basis. Specifies the font to be used in DirectDrawSurface7.DrawText. Attaches a palette class to (or detaches one from) a surface. The surface uses this palette for all subsequent operations. The palette change takes place immediately, without regard to refresh timing.
DirectDrawSurface7.Get Palette IsLost
DirectDrawSurface7.IsLost
Restore
DirectDrawSurface7.Restore
SetClipper
DirectDrawSurface7.Set Clipper
SetColorKey
DirectDrawSurface7.Set ColorKey
SetFont
DirectDrawSurface7.SetFont
SetPalette
DirectDrawSurface7.Set Palette
The DirectDrawPalette Class The DirectDrawPalette class is special in that it handles the color palette you use for your animations. With the palette, you can control what happens to the colors on the screen. You can cause classes to flash and change colors by changing the associated colors in the DirectDrawPalette class.
4 CREATING GRAPHICS WITH DIRECTDRAW
Method
60
DirectX Graphics Programming PART II
The following code syntax is an example of declaring and using the DirectDrawPalette class: Dim oDDP As DirectDrawPalette
This is what the code would look like when included with the DirectX and DirectDraw declarations: ‘’’First you need to access the DirectX 7 COM class Dim oDX As DirectX7 ‘’’Next you need to create a DirectDraw class Dim oDD As DirectDraw7 ‘’’Then you need to create a DirectDrawPalette class Dim oDDP As DirectDrawPalette
Declaring a DirectDrawPalette object in VB.NET This same code can be used in VB.NET. The code below shows how you would declare a DirectDrawPalette object: ‘’’First you need to access the DirectX 7 COM class Dim oDX As DxVBLib.DirectX7 = New DxVBLib.DirectX7() ‘’’Next you need to create a DirectDraw class Dim oDD As DxVBLib.DirectDraw7 ‘’’Then you need to create a DirectDrawPalette class Dim oDDP As DxVBLib.DirectDrawPalette
A DirectDrawPalette class is created by calling the DirectDraw.CreatePalette method, as shown in this example: Set oDDP = oDD.CreatePalette
Table 4.3 outlines some of the more commonly used DirectDrawPalette methods. TABLE 4.3
The Most Commonly Used DirectDrawPalette Methods
Method
Syntax
Purpose
GetCaps
DirectDrawPalette.GetCaps
Retrieves the capabilities of the DirectDrawPalette class. In essence, it tells the program which video capabilities are available with the video card.
Creating Graphics with DirectDraw CHAPTER 4
TABLE 4.3
Continued
Method
Syntax
Purpose
GetEntries
DirectDrawPalette.GetEntries
SetEntries
DirectDrawPalette.SetEntries
Queries palette values from a DirectDrawPalette class. Changes entries in a DirectDrawPalette class immediately.
61
The DirectDrawClipper Class Clipping is important for controlling what areas of the screen are being animated, and the DirectDrawClipper class is the mechanism by which you accomplish that task. The DirectDrawClipper class uses a clipper list to determine the areas that “hide” the animated action from the viewer. Let’s look at the most common use for clippers: handling animation in windows. When you begin work with DirectDraw sprites, you’ll notice that if the sprite nears the edge of the screen, it just suddenly disappears, which might not be quite the effect you’re looking for. Most of us would expect the sprite to gradually move off the screen, and this behavior can be enforced through clippers. By assigning the complete window as the clipper area for your surface, you can control how your sprites disappear off the edges of the screen. The following code syntax is an example of declaring and using the DirectDrawClipper class: Dim oDDC As DirectDrawClipper
In DirectX and DirectDraw declarations, the code would look like this: ‘’’First you need to access the DirectX 7 COM class Dim oDX As DirectX7
4 CREATING GRAPHICS WITH DIRECTDRAW
‘’’Next you need to create a DirectDraw class Dim oDD As DirectDraw ‘’’Then you need to create a DirectDrawClipper class Dim oDDClipper As DirectDrawClipper
Declaring a DirectDrawClipper object in VB.NET This same code can be used in VB.NET. The code below shows how you would declare a DirectDrawClipper object: ‘’’First you need to access the DirectX 7 COM class Dim oDX As DxVBLib.DirectX7 continues
62
DirectX Graphics Programming PART II
‘’’Next you need to create a DirectDraw class Dim oDD As DxVBLib.DirectDraw7 ‘’’Then you need to create a DirectDrawClipper class Dim oDDC As DxVBLib.DirectDrawClipper
Table 4.4 shows the most commonly used DirectDrawClipper methods. TABLE 4.4
The Most Commonly Used DirectDrawClipper Methods
Method
Syntax
Purpose
GetClipList
DirectDrawClipper.Get ClipList
IsClipListChanged
DirectDrawClipper.Is ClipListChanged
SetClipList
DirectDrawClipper.Set ClipList
GetHWnd
DirectDrawClipper.Get HWnd
SetHWnd
DirectDrawClipper.Set HWnd
Retrieves a copy of the clipper list associated with a DirectDrawClipper class Monitors the status of the clipper list of a DirectDrawClipper class Sets or deletes the clipper list used by the DirectDrawSurface7.Blt method on surfaces that the parent DirectDraw Clipper class is attached to Retrieves the window handle previously associated with this DirectDrawClipper class by the DirectDrawClipper.SetHWnd method Sets the window handle to retrieve the clipping information
To use the graphics capabilities of a video card, you need to be able to access the hardware and software abstraction layers of DirectDraw. This is done through the HAL and HEL.
HAL Versus HEL Communication with the graphics card is done using one of two channels: the Hardware Abstraction Layer (HAL) and Hardware Emulation Layer (HEL). The HAL provides access directly to the video card’s capabilities. If the video card can perform a complex graphics process that DirectX supports, it will have a HAL interface that DirectX detects and uses. If, however, the video card does not have the capability you’re trying to work with, it tries to emulate the behavior by using the HEL. The HEL can emulate much of the video behavior now
Creating Graphics with DirectDraw CHAPTER 4
63
available in high-end video cards by using software routines to do all the work, instead of relying on the video card to do it. In a nutshell, these two channels allow you to create applications that are independent of the video card in the users’ machines. If their video card has the necessary hardware, the HAL layer will access its functionality. If the video card doesn’t have the necessary capabilities, the HEL layer will emulate the behaviour. Figure 4.2 shows the relationship between DirectX and the HAL and HEL layers.
DirectX
HAL (Hardware Abstraction Layer)
HEL (Hardware Emulation Layer)
Video Card
FIGURE 4.2 The HAL and HEL layers.
In the diagram, the video card uses the HAL to accomplish all the tasks it was designed to accomodate. If the programmer tries to do a graphic routine that the video card can’t handle, it’s passed to the HEL, where it then simulates the process in PC memory and displays it to the video card, using the HAL methods available to it.
In addition to HAL and HEL capabilities, video cards also have display modes that can vary from manufacturer to manufacturer.
Display Modes An application can be displayed in multiple modes. DirectX can be used in a full-screen mode, similar to most DOS games and multimedia applications. You can also use DirectDraw in Windows mode, which allows DirectX applications to work within a normal Microsoft window.
CREATING GRAPHICS WITH DIRECTDRAW
In most 2D applications, the HEL is able to compensate for decreased functionality in the video card by emulation. However, because of the complexity of 3D graphics work, the HEL can get quite bogged down in calculations, resulting in poor graphical performance. Keep this in mind when you write your application. You should also strongly recommend a 3D graphics card for those using your program, if you are using 3D classes.
4
64
DirectX Graphics Programming PART II
Full-screen mode can be in many different formats, depending on the video card. The most commonly used formats for speed and performance of most lower-end video cards are Mode X and Mode 13. These formats come from early DOS game programming, when there was a need to make maximum use of the video architecture. Through trial and error, graphics programmers learned to take advantage of these modes or formats. Figure 4.3 shows the difference between the look of a Windows display mode and a full-screen display mode.
Windows mode
Full-screen mode
FIGURE 4.3 Windows versus full-screen display modes.
Standard Display Modes Depending on your video card, you could have many different video modes available. The best way to look at modes is to compare them to having many different sizes of canvas and associated palettes. Table 4.5 gives an example of the display settings available for a Riva TNT card. All measurements for screen size are in pixels. The table shows the typical screen dimensions, palette ranges, and refresh rates of an average graphics card. Measurements for refresh rates are in Hertz. TABLE 4.5
Typical Display Modes for a Graphics Card
Screen Dimensions (pixels)
Palette Range
Refresh Rates (Hz)
640 × 480 800 × 600 1024 × 768 1152 × 864 1280 × 1024 1600 × 1024 1920 × 1080
256 colors to 32-bit true color 256 colors to 32-bit true color 256 colors to 32-bit true color 256 colors to 32-bit true color 256 colors to 32-bit true color 256 colors to 32-bit true color 256 colors to 32-bit true color
60–120 60–120 60–75 60–75 60–75 60–75 60–75
Creating Graphics with DirectDraw CHAPTER 4
65
An Example Using the DirectDraw Class Listing 4.1 is a portion of a program called Shooting Gallery that uses DirectDraw to move ducks across the screen. The subroutine in the listing handles the creation of all the DirectDraw classes used in the Shooting Gallery program. The comments in the code explain how and why each component and method is being used. The complete code for this example can be found on the net. LISTING 4.1 Dim Dim Dim Dim Dim Dim Dim Dim Dim
Creating the DirectDraw Classes for the Shooting Gallery
oDX oDD oDDGallerySurf oDDSpriteSurf oDDSpriteSurf2 oDDSpriteSurf3 oDDScreen oDDBackBuffer oDDClip
As As As As As As As As As
New DirectX7 DirectDraw7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawClipper
4 CREATING GRAPHICS WITH DIRECTDRAW
Dim ddsdGallery As DDSURFACEDESC2 Dim ddsdSprite As DDSURFACEDESC2 Dim ddsdSprite2 As DDSURFACEDESC2 Dim ddsdSprite3 As DDSURFACEDESC2 Dim ddsdScreen As DDSURFACEDESC2 Dim ddsdBackBuffer As DDSURFACEDESC2 ‘************************************************************************ ‘** ObjectName: InitializeEnvironment ‘** ‘** Description: This subroutine does the following: ‘** 1. Assigns the DirectDraw class to the active display ‘** 2. Set up a surface descriptor for the screen surface. ‘** 3. Get the surface rect and assign a clipper to it. ‘** 4. Assign the picture handle to the clipper rect. ‘** 5. Set up a surface descriptor for the back buffer ‘** surface. ‘** 6. Get the surface rect. ‘** 7. Call the InitializeSurfaces ‘** 8. Define the rectangles for the background and ‘** sprites. ‘** 9. Call the RepaintEntireBackground subroutine ‘** 10. Start the animation loop ‘** ‘************************************************************************
66
DirectX Graphics Programming PART II
LISTING 4.1
Continued
Sub InitializeEnvironment() bFirstTime = True Dim file As String ‘’’ Pass an empty string here signifying that ‘’’ you want the active display Set oDD = oDX.DirectDrawCreate(“”) ‘’’ This is required, it prevents some erratic behavior ‘’’ with DirectX Me.Show ‘’’ This tells DirectX what kind of window you ‘’’ are going to use. Call oDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL) ‘’’ ******** Create your screen surface (primary) ********* ‘’’ Indicate that the ddsCaps member is valid ddsdScreen.lFlags = DDSD_CAPS ‘’’ Request primary surface ddsdScreen.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE ‘’’ Create the primary surface object Set oDDScreen = oDD.CreateSurface(ddsdScreen) ‘’’ Create a clipper so that you can define the writable ‘’’ portion of the screen Set oDDClip = oDD.CreateClipper(0) ‘’’ Associate your picture control with the clipper you ‘’’ just made oDDClip.SetHWnd Picture1.hWnd ‘’’ Now assign this defined clipper to its ‘’’ screen surface (primary) oDDScreen.SetClipper oDDClip ‘’’ ******* End of creating your screen surface (primary) ‘’’ ******* Create your back buffer where you can assemble your screens
Creating Graphics with DirectDraw CHAPTER 4
LISTING 4.1
67
Continued
‘’’ Here you set the flags for your DirectDraw surface ‘’’ descriptor. You are telling it to use the capabilities ‘’’ of the video card, and allow you to set the height and width ‘’’ of the surface ddsdBackBuffer.lFlags = DDSD_CAPS Or DDSD_HEIGHT Or DDSD_WIDTH ‘’’ These flags tell your surface descriptor that you want to use ‘’’ an offscreen surface and you want to use system memory. ddsdBackBuffer.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN Or _ ➥DDSCAPS_SYSTEMMEMORY ‘’’ Assign the same dimensions that the picture box has ‘’’ to the back buffer ddsdBackBuffer.lWidth = Picture1.Width ddsdBackBuffer.lHeight = Picture1.Height ‘’’ Create the back buffer surface Set oDDBackBuffer = oDD.CreateSurface(ddsdBackBuffer) ‘’’ ******** End of creating your back buffer where you can ‘’’ assemble your screens ‘’’ ******** ‘’’ Find sMedia = ‘’’ ********
Find out what the path to your data is ******** the path to the background GetDataDirectory(“Gallery.bmp”) End of finding out what the path to your data is
‘’’ Put together the initial values for each surface InitializeSurfaces
‘’’ Define the are you will be blitting to rGallery.Bottom = ddsdGallery.lHeight rGallery.Right = ddsdGallery.lWidth ‘’’ Assign dimensions to a rectangle for the sprite dimensioned. rSprite.Bottom = ddsdSprite.lHeight rSprite.Right = ddsdSprite.lWidth
CREATING GRAPHICS WITH DIRECTDRAW
‘’’ Define the rectangle area for your back buffer based on the ‘’’ surface descriptor rBackBuffer.Bottom = ddsdBackBuffer.lHeight rBackBuffer.Right = ddsdBackBuffer.lWidth
4
68
DirectX Graphics Programming PART II
LISTING 4.1
Continued
‘’’ Repaint the entire background image onto the back buffer surface RepaintEntireBackground ‘’’ ******** Execution Loop begins here ******** ‘’’ The Execution Loop continues until the person closes ‘’’ the application running = True Do While running DoFrame DoEvents ‘’’ Do Events is used throughout DirectX code to ‘’’ force the program to wait for commands ‘’’ to finish executing. Loop ‘’’ ******** End Execution Loop ******** End Sub
Figure 4.4 shows a flowchart of how the previous code is organized.
Summary This chapter centered on how you create animations with DirectDraw, once the cornerstone of DirectX and still one of the most useful parts of DirectX for standard two-dimensional graphics. You learned how DirectDraw relates to its subcomponents, such as DirectDrawSurface, and DirectDrawClipper, saw how to declare commonly used methods in the DirectDraw class.
DirectDrawPalette,
In the section on DirectDrawSurface classes, you learned how to declare and use a class to create surfaces, the canvas you use to create your animation frames. The DirectDrawSurface methods provide additional functional support to the class. DirectDrawSurface
In the section on DirectDrawPalette classes, you learned how to declare and use a DirectDrawPalette class, which is used to hold information vital to the colors used by each of the surfaces in your program. The DirectDrawPalette methods offer extra functional support to the class. In the section on DirectDrawClipper classes, you learned how to declare and use a DirectDrawClipper class, which defines the usable area of your DirectDrawSurface, and saw how the DirectDrawClipper methods give the class additional functional support.
Creating Graphics with DirectDraw CHAPTER 4
69
Loop until program ends Assign DirectDraw to active display Start Animation Loop Set up a surface descriptor for Screen Surface
Get surface rectangle and assign cliper
Repaint entire background
Assign picture handle to cliper rectangle
Define rectangle for background and sprites
Setup surface descriptor for the back buffer
Initialize the Surfaces
Get Surface Rectangle
Initialize the Surfaces
FIGURE 4.4
4
DirectDraw sample code flowchart.
You also saw a comparison of the Windows screen mode and the full-screen mode and a comparison of the standard display modes available in a typical video card. The DirectDraw code example at the end of the chapter incorporated many of the techniques you learned in the chapter.
CREATING GRAPHICS WITH DIRECTDRAW
In the HAL versus HEL discussion, you learned how the HAL communication channel enables you to connect directly to the DirectX-supported hardware. Conversely, the HEL communication channel is used to emulate capabilities not normally found in DirectX-supported hardware.
Creating Basic Animations
IN THIS CHAPTER • Surfaces
72
• Gamma and Color Controls • Overlay Surfaces
72
83
• A DirectDrawSurface Example • Summary
88
85
CHAPTER
5
72
DirectX Graphics Programming PART II
This chapter will introduce you to the nuts and bolts of how to do standard 2D animations through techniques such as page flipping, blitting, gamma and color controls, and overlay surfaces. By using these techniques, you can move surfaces in memory, paste to surfaces, change the attributes of colors on surfaces, and add additional surface objects to animations. The rest of this chapter describes these techniques in detail. To better understand these concepts, you need to begin with a few definitions: Page flipping is the process of changing pages of graphics that the user sees. This process is done at a high rate of speed, producing an animated effect similar to cartoon animation. Blitting is the process of pasting a rectangle of an image on top of a background image. This process is used to build the pages for the page-flipping process. Gamma controls are filters that modify the red, green, and blue (RGB) values of images. An image is modified by passing it through these filters. Color controls are filters very similar to gamma controls. However, they have many more parameters for adjusting images’ hue, saturation, contrast, and brightness. Overlay surfaces are rectangular areas of the screen that can be used to draw over other graphics. These areas are used for video playback and still images. Overlays are enabled through the hardware in most video cards.
Surfaces Surfaces are memory allocations used to hold the canvas for your animation. If you imagine an animation as a steady stream of pictures being displayed one after the other, you can see that you need a lot of surfaces: one for each picture. This, of course, would eat up tons of memory if you had to hold on to all those pictures in memory. So instead of working with a lot of canvases, you work with a few and show only the ones that are ready. You then work on the ones that aren’t currently in view and show them when it’s time for them to be displayed. DirectX basically builds the movie or animation on-the-fly. To create a DirectDraw surface, you use the DirectDrawSurface command. This command creates the surface that you can then use to paint a picture.
Creating Surfaces You must first initialize a surface through the DirectDrawSurface class by using the DirectDraw7.CreateSurface command. Then the value for the surface is assigned to a variable that has been declared as type DirectDrawSurface7. The steps to create the surface are shown in the following lines.
Creating Basic Animations CHAPTER 5
73
Syntax: object.CreateSurface( dd As DDSURFACEDESC2) As DirectDrawSurface7
Example: The following code snippet shows how the CreateSurface method can be used to create a primary surface: Dim Dim Dim Dim
oDX As DirectX7 oDD As DirectDraw7 surfPrimary As DirectDrawSurface7 oDDSD As DDSURFACEDESC2
Set oDX = New DirectX7 Set oDD = oDX.DirectDrawCreate(“”) With oDDSD .lFlags = DDSD_CAPS Or _ ➥ DDSD_BACKBUFFERCOUNT .ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or _ ➥ DDSCAPS_FLIP Or _ ➥ DDSCAPS_COMPLEX .ddpfPixelFormat.lFlags = _ ➥ DDPF_PALETTEINDEXED8 .lBackBufferCount = 1 End With Set surfPrimary = oDD.CreateSurface(oDDSD)
Declaring and Using the CreateSurface method in VB.NET This same code can be used in VB.NET. The code below shows how you would use the CreateSurface method: Dim Dim Dim Dim
oDX As DxVBLib.DirectX7 oDD as DxVBLib.DirectDraw7 surfPrimary as DxVBLib.DirectDrawSurface7 oDDSD as DxVBLib.DDSURFACEDESC2
oDX = New DxVBLib.DirectX7 oDD = oDX.DirectDrawCreate(“”)
5
continues
CREATING BASIC ANIMATIONS
With oDDSD .lFlags = DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_CAPS Or _
74
DirectX Graphics Programming PART II
DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_BACKBUFFERCOUNT .ddsCaps.lCaps = DxVBLib.CONST_DDSURFACECAPSFLAGS. _ ➥ DDSCAPS_PRIMARYSURFACE Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_FLIP Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_COMPLEX .ddpfPixelFormat.lFlags = _ ➥ DxVBLib.CONST_DDPIXELFORMATFLAGS.DDPF_PALETTEINDEXED8 .lBackBufferCount = 1 End With ➥
surfPrimary = oDD.CreateSurface(oDDSD)
Creating Surfaces from Files One way to create surfaces is by assigning a file to them. The attributes of this file become the attributes of the surface, thus reducing the amount of work needed to define the surface. Assigning a file actually means opening a previously saved file to use as your DirectDraw surface. This file must be a bitmap (.bmp) file. This process is most commonly used when dealing with background images in DirectDraw. A background image has its own palette, dimensions, and image ready to become a new surface. You simply have to assign it to the surface by using the DirectDraw7.CreateSurfaceFromFile method. This method is shown as follows. Syntax: object.CreateSurfaceFromFile( file As String, dd As DDSURFACEDESC2) As DirectDrawSurface7
Example: The following code snippet shows how the CreateSurfaceFromFile method can be used to create a DirectDraw surface: Dim Dim Dim Dim
oDX As DirectX7 oDD As DirectDraw7 oDDS As DirectDrawSurface7 oDDSD As DDSURFACEDESC2
Set oDX = New DirectX7 Set oDD = oDX.DirectDrawCreate(“”) With oDDSD .lFlags = DDSD_CAPS Or _ ➥ DDSD_WIDTH Or _ ➥ DDSD_HEIGHT
Creating Basic Animations CHAPTER 5
75
.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN .lWidth = Picture1.Width .lHeight = Picture1.Height End With oDDS = oDD.CreateSurfaceFromFile( _ ➥ “c:\windows\background.bmp”, oDDSD)
Using the CreateSurfaceFromFile method in VB.NET This same code can be used in VB.NET. The code below shows how you would use the CreateSufraceFromFile method: Dim Dim Dim Dim
oDX As DxVBLib.DirectX7 oDD as DxVBLib.DirectDraw7 oDDS As DxVBLib.DirectDrawSurface7 oDDSD as DxVBLib.DDSURFACEDESC2
oDX = New DxVBLib.DirectX7 oDD = oDX.DirectDrawCreate(“”) With oDDSD .lFlags = DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_CAPS Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_WIDTH Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_HEIGHT .ddsCaps.lCaps = DxVBLib.CONST_DDSURFACECAPSFLAGS. _ ➥ DDSCAPS_OFFSCREENPLAIN .lWidth = Picture1.Width .lHeight = Picture1.Height End With oDDS = oDD.CreateSurfaceFromFile( _ ➥ “c:\windows\background.bmp”, oDDSD)
Surface Descriptions To create a surface, you must also supply information that’s not always accessible to the and CreateSurfaceFromFile methods. That responsibility falls on the surface description. This data type is declared by the DDSURFACEDESC2 declaration. This descriptor defines the following information for the surface: height and width, unique flags, corresponding color keys, DirectDraw capabilities, and much more. All of the surfaces in this chapter’s examples use surface descriptions of varying complexity. Following is an example of using surface descriptors.
CreateSurface
5 CREATING BASIC ANIMATIONS
76
DirectX Graphics Programming PART II
Syntax: Type DDSURFACEDESC2 ddckCKDestBlt As DDCOLORKEY ddckCKDestOverlay As DDCOLORKEY ddckCKSrcBlt As DDCOLORKEY ddckCKSrcOverlay As DDCOLORKEY ddpfPixelFormat As DDPIXELFORMAT ddsCaps As DDSCAPS2 lAlphaBitDepth As Long lBackBufferCount As Long lFlags As CONST_DDSURFACEDESCFLAGS lHeight As Long lLinearSize As Long lMipMapCount As Long lPitch As Long lRefreshRate As Long lTextureStage As Long lWidth As Long lZBufferBitDepth As Long End Type
Example: The following code snippet shows how the DDSURFACEDESC2 descriptor can be used to set up the capabilities of a surface: Dim Dim Dim Dim
oDX As DirectX7 oDD As DirectDraw7 surfPrimary As DirectDrawSurface7 oDDSDAs DDSURFACEDESC2
Set oDX = New DirectX7 Set oDD = oDX.DirectDrawCreate(“”) ‘’’ You need to set up the surface descriptor for ‘’’ the back buffer surface With oDDSD .lFlags = DDSD_CAPS Or _ ➥ DDSD_BACKBUFFERCOUNT .ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE Or _ ➥ DDSCAPS_FLIP Or _ ➥ DDSCAPS_COMPLEX .ddpfPixelFormat.lFlags = _ ➥ DDPF_PALETTEINDEXED8 .lBackBufferCount = 1 End With
Creating Basic Animations CHAPTER 5
77
‘’’ Create the primary surface using the ‘’’ surface descriptor you just created Set surfPrimary = oDD.CreateSurface(oDDSD)
Using the DDSURFACEDESC2 surface descriptor in VB.NET This same code can be used in VB.NET. The code below shows how you would use the DDSURFACEDESC2 surface descriptor: Dim Dim Dim Dim
oDX As DxVBLib.DirectX7 oDD As DxVBLib.DirectDraw7 surfPrimary As DxVBLib.DirectDrawSurface7 oDDSD As DxVBLib.DDSURFACEDESC2
oDX = New DxVBLib.DirectX7 oDD = oDX.DirectDrawCreate(“”) ‘’’ You need to set up the surface descriptor for ‘’’ the back buffer surface With oDDSD .lFlags = DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_CAPS Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_BACKBUFFERCOUNT .ddsCaps.lCaps = DxVBLib.CONST_DDSURFACECAPSFLAGS. _ ➥ DDSCAPS_PRIMARYSURFACE Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_FLIP Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_COMPLEX .ddpfPixelFormat.lFlags = _ ➥ DxVBLib.CONST_DDPIXELFORMATFLAGS.DDPF_PALETTEINDEXED8 .lBackBufferCount = 1 End With ‘’’ Create the primary surface using the ‘’’ surface descriptor you just created surfPrimary = oDD.CreateSurface(oDDSD)
Flipping Surfaces 5 CREATING BASIC ANIMATIONS
The process of deciding which surface is being shown to the user is called page flipping, and you use the DirectDrawSurface.Flip method to accomplish this. Flipping takes the supplied surface and changes its memory location with that of the other supplied surface, essentially changing their positions in the order of display.
78
DirectX Graphics Programming PART II
In Figure 5.1 you can see how this process works. Surface A is the first in line for display, and surfaces B and C are waiting in order behind surface A. After the first “flip” is called, surface B becomes the primary surface, surface C becomes the back buffer, and surface A becomes the new secondary surface. This flipping cycle continues, producing frame after frame of animation. Chapter 3, “Animation Techniques,” also provides a discussion of this technique. Surfaces Primary
Back Buffer
Secondary
Frame1
A
B
C
Frame2
B
C
A
Frame3
C
A
B
FIGURE 5.1 Flipping surfaces.
The following code shows how DirectDrawSurface.Flip is implemented. Syntax: object.Flip( ddS As DirectDrawSurface7, flags As CONST_DDFLIPFLAGS)
Example: The following code snippet shows how the Flip method of the DirectDrawSurface7 object can be used to flip a surface: Dim Dim Dim Dim
oDX As DirectX7 oDD As DirectDraw7 surfPrimary As DirectDrawSurface7 surfSecondary As DirectDrawSurface7
‘’’Flip the primary surface to the screen surfPrimary.Flip(surfSecondary, DDFLIP_WAIT)
Creating Basic Animations CHAPTER 5
79
Using the Flip method in VB.NET This same code can be used in VB.NET. The code below shows how you would use the Flip method: Dim Dim Dim Dim
oDX As DxVBLib.DirectX7 oDD As DxVBLib.DirectDraw7 surfPrimary As DxVBLib.DirectDrawSurface7 surfSecondary As DxVBLib.DirectDrawSurface7
‘’’Flip the primary surface to the screen surfPrimary.Flip(surfSecondary, _ ➥ DxVBLib.CONST_DDFLIPFLAGS.DDFLIP_WAIT)
Blitting to a Surface Blitting to a surface is the process that takes an image from another surface and copies it to the surface you want to create. Another way to look at blitting is to compare it to a collage, which is an image made up of many smaller pictures pasted on one page. This is what blitting is doing: assembling copies of several small images into one large image on a drawing surface (usually the back buffer). In Figure 5.2 you can see how blitting works. Three objects from three surfaces labeled Surface 1, Surface 2, and Surface 3 are being blitted to an empty surface (the back buffer). The final result of this process is the image at the bottom of Figure 5.2.
The Many Forms of the BLIT Routine Blitting is so important to DirectDraw that Microsoft has given us five versions to use. Each version has its benefits and downfalls, which are explained in the following sections. When you create your application, it is wise to use the most efficient BLIT routine for the task. Blt Blt, the old tried-and-true version of BLIT, gives you the luxury of being able to apply surfaces of one size to surface rectangles of another size. In essence, you are allowed to stretch graphics as you paste them on the new surface. The downfall of this method is that it’s much slower than its counterparts. The following code lines show how Blt is used. Syntax:
CREATING BASIC ANIMATIONS
object.Blt( destRect As RECT, ddS As DirectDrawSurface7, srcRect As RECT _ ➥, flags As CONST_DDBLTFLAGS) As Long
5
80
DirectX Graphics Programming PART II
Surface 1
Surface 2 Back Buffer Surface
Surface 3
Final Result
FIGURE 5.2 Blitting to a surface.
Example: The following code snippet shows how the Blt method can be used to paint a rectangle of data to a back buffer surface: objDDrval = surfBackBuffer.Blt(rBack, surfMain, rSource, DDBLT_DONOTWAIT)
BltColorFill This BLIT function simply fills a rectangle with the color you select. BltColorFill, demonstrated in the following code lines, is useful for creating filled rectangles as part of your animation.
Creating Basic Animations CHAPTER 5
81
Syntax: object.BltColorFill( destRect As RECT, fillvalue As Long) As Long
Example: The following code snippet shows how the BltColorFill method can be used to fill a rectangle area with the color black: objDDrval = surfBackBuffer.BltColorFill(rBack, RGB(0, 0, 0))
BltFast The BltFast method is the most widely used blitting method in DirectDraw, simply because of its speed. BltFast is the fastest of the BLIT methods. It requires fewer parameters than Blt, so of course it’s faster, but at a cost: The downfall of this method is that you lose the ability to resize the blit. The following code lines show how to use BltFast. Syntax: object.BltFast( dx As Long, dy As Long, _ ➥ddS As DirectDrawSurface7, srcRect As RECT, _ ➥trans As CONST_DDBLTFASTFLAGS) As Long
Example: The following code snippet shows how the BltFast method can be used to blit a main surface with the contents of a rectangle object: objDDrval = surfBackBuffer.BltFast(0, 0, surfMain, rBack, DDBLTFAST_WAIT)
BltFx BltFx gives you the most customization options for the blitted image. The BltFx process allows for alpha-blending, flipping of images (mirroring), stretching, and Z-buffering. To understand what this method does, take a closer look at these terms: • Alpha-blending: This process allows irregular objects to be placed on backgrounds. By specifying the alpha color(or transparency color), you can blend the rectangular image with a background. This results in the alpha color on the source rectangle taking on the colors of the background it’s placed on. • Mirroring: In most paint programs you can rotate the image along the x-axis, which is the same as mirroring. You are basically creating a mirror image of the current image. • Stretching: This process is used to resize the image that you blit to the screen.
CREATING BASIC ANIMATIONS
• Z-buffering: This process is basically the same as layers. You can decide on which plane (or layer) you want to place an image rectangle, which can provide the illusion of depth in the image.
5
82
DirectX Graphics Programming PART II
This method, shown in the following lines, is similar to the Blt method but with some added functionality. Syntax: class.BltFx( destRect As RECT, ddS As DirectDrawSurface7, _ ➥srcRect As RECT, flags As CONST_DDBLTFLAGS, BltFx As _ ➥DDBLTFX) As Long
Example: The following code snippet shows how the BltFx method can be used to blit a rectangle from a source surface to a back buffer surface: objDDrval = surfBackBuffer.BltFx(rBack, surfMain, rSource, _ ➥ DDBLT_DONOTWAIT, oBltFX)
BltToDC This method enables DirectDraw to talk directly to the Windows graphics functions and write directly to the device context (DC). In Windows, a device context is analogous to a surface. Therefore, a DirectDraw surface can be copied to a Windows DC. BltToDC, shown in the following lines, allows for backward-compatibility with graphics methods used by the Windows API before DirectX was created. If you are migrating older VB multimedia code to DirectDraw, this method could come in handy. Syntax: class.BltToDC(hdc As LONG, srcRect As RECT, destRect As RECT)
Example: The following code snippet shows how the BltToDC method can be used to blit a rectangle to a device context handle: objDDrval = surfBackBuffer.BltToDC(Me.hWnd, rSource, rBack)
Gamma and Color Controls Gamma and color controls are used to create filters on a surface’s colors. Using these filters, a programmer can control what the output colors look like. For example, if you were to tweak the little knobs in the back of your TV to fix the picture, you would change the colors, modify the intensity, alter the brightness, and so forth. These effects are what the gamma and color controls are all about. Gamma controls allow you to change red, green, and blue (RGB) values in a surface. Because you have to deal with a range of color settings for only three colors, this control is much more widely used in game development. The most common use of gamma controls is for flashing
Creating Basic Animations CHAPTER 5
83
certain colors on the screen, often to indicate damage to characters or emphasize important objects in the game. Following is an example of how a gamma control is used. Syntax: object.GetDirectDrawGammaControl() As DirectDrawGammaControl
Example: The following code snippet shows how the GetDirectDrawGammaControl method can be used to create a gamma control object: Dim objDDGC As DirectDrawGammaControl objDDGC = surfPrimary.GetDirectDrawGammaControl
Conversely, color controls allow you to change hue, saturation, contrast, brightness, gamma, and sharpness. These settings are similar to what you see on your standard TV. The color controls give you greater control over the final output than gamma controls do; however, they are much more complicated. Following is an example of how a color control is used. Syntax: object.GetDirectDrawColorControl() As DirectDrawColorControl
Example: The following code snippet shows how the GetDirectDrawColorControl method can be used to create a color control: Dim objDDCC as DirectDrawColorControl objDDCC = surfPrimary.GetDirectDrawColorControl
Overlay Surfaces With overlay surfaces, full-motion video or still images can be placed on top of existing surfaces without disturbing the background image. One way to look at an overlay surface (usually referred to as just an overlay) is to think of it as a rectangle layer that resides on top of the surface you are working with. Any image or video can be placed on this layer for display.
5 CREATING BASIC ANIMATIONS
One limitation of overlays is that the hardware on the machine where you are using overlays must support this feature in the video card. In other words, there is no HEL support for overlays. Because of the hardware acceleration required, using this feature does not noticeably decrease performance.
84
DirectX Graphics Programming PART II
Figure 5.3 shows an example of the use of an overlay. If you wanted to create a program that shows a surveillance camera output on a display that was surrounded by graphics, you can use overlays for that purpose. Surveillance Camera #1
Overlay Primary Surface
FIGURE 5.3 Creating an application with an overlay.
The DirectDraw method CreateSurface is used to create an overlay. When using this method, you must use the DDSCAPS_OVERLAY and DDSCAPS_VIDEOMEMORY flags in the associated DDSURFACEDESC2 type. Example: The following code snippet shows how the CreateSurface method can use a DDSURFACEDESC2 to define a surface that can be used as an overlay. Notice the DDSCAPS_OVERLAY flag used in this example to specify that this surface is an overlay. Dim Dim Dim Dim
oDX As DirectX7 oDD As DirectDraw7 surfPrimary As DirectDrawSurface7 oDDSD2 As DDSURFACEDESC2
Set oDX = New DirectX7 Set oDD = oDX.DirectDrawCreate(“”) ‘’’ Define the surface descriptor for the primary surface With oDDSD2 .lFlags = DDSD_CAPS Or _ ➥ DDSD_HEIGHT Or _ ➥ DDSD_WIDTH Or _ ➥ DDSD_BACKBUFFERCOUNT Or _ ➥ DDSD_PIXELFORMAT .ddsCaps.lCaps = DDSCAPS_OVERLAY Or _ ➥ DDSCAPS_FLIP Or _ ➥ DDSCAPS_COMPLEX Or _ ➥ DDSCAPS_VIDEOMEMORY
Creating Basic Animations CHAPTER 5
85
.lWidth = 320 .lHeight = 240 .lBackBufferCount = 2 End With ‘’’ Assign the previously defined descriptor to the surface and create it. Set surfPrimary = oDD.CreateSurface(oDDSD2)
Creating an overlay in VB.NET This same code can be used in VB.NET. The code below shows how you would use the CreateSurface method to create an overlay: Dim Dim Dim Dim
oDX As DxVBLib.DirectX7() oDD As DxVBLib.DirectDraw7 surfPrimary As DxVBLib.DirectDrawSurface7 oDDSD2 As DxVBLib.DDSURFACEDESC2
oDX = New DxVBLib.DirectX7 oDD = oDX.DirectDrawCreate(“”) ‘’’ Define the surface descriptor for the primary surface With oDDSD2 .lFlags = DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_CAPS Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_HEIGHT Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_WIDTH Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_BACKBUFFERCOUNT Or _ ➥ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_PIXELFORMAT .ddsCaps.lCaps = DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_OVERLAY Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_FLIP Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_COMPLEX Or _ ➥ DxVBLib.CONST_DDSURFACECAPSFLAGS.DDSCAPS_VIDEOMEMORY .lWidth = 320 .lHeight = 240 .lBackBufferCount = 2 End With ‘’’ Assign the previously defined descriptor to the surface and create it. surfPrimary = oDD.CreateSurface(oDDSD2)
5 Listing 5.1 is a portion of a program called Shooting Gallery that uses DirectDrawSurface to move ducks across the screen. The subroutine in the listing handles the creation of all the DirectDrawSurface classes that will be used in the Shooting Gallery program. The comments
CREATING BASIC ANIMATIONS
A DirectDrawSurface Example
86
DirectX Graphics Programming PART II
in the code explain how and why each component and method is being used. This listing shows the InitializeSurfaces subroutine, which creates all the surfaces used to draw and animate the Shooting Gallery program. This subroutine is called from the Initialize Environment subroutine that is outlined at the end of Chapter 4, “Creating Graphics with DirectDraw.” The complete code for this example can be found on the net. LISTING 5.1
Creating Surfaces for the Shooting Gallery Program
Dim Dim Dim Dim Dim Dim Dim Dim Dim
oDX oDD oDDGallerySurf oDDSpriteSurf oDDSpriteSurf2 oDDSpriteSurf3 oDDScreen oDDBackBuffer oDDClip
As As As As As As As As As
New DirectX7 DirectDraw7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawSurface7 DirectDrawClipper
‘’’ Dim Dim Dim Dim Dim Dim
Define some surface descriptors ddsdGallery As DDSURFACEDESC2 ddsdSprite As DDSURFACEDESC2 ddsdSprite2 As DDSURFACEDESC2 ddsdSprite3 As DDSURFACEDESC2 ddsdScreen As DDSURFACEDESC2 ddsdBackBuffer As DDSURFACEDESC2
‘***************************************************************************** ‘** ObjectName: InitializeSurfaces ‘** ‘** Description: This subroutine does the following: ‘** 1. Creates the surface descriptor for the Primary Surface ‘** 2. Creates the primary surface from the file “gallery.bmp” ‘** 3. Calls the RepaintBackground routine to refresh the ‘** gallery picture. ‘** 4. Creates the surface descriptor for the Secondary Surface. ‘** 5. Creates three individual surfaces to hold each of ‘** your sprites. ‘** 6. Sets the transparent color keys for each of your ‘** sprite surfaces. ‘** ‘***************************************************************************** Private Sub InitializeSurfaces() Dim key As DDCOLORKEY
Creating Basic Animations CHAPTER 5
LISTING 5.1
87
Continued
‘’’ Creating an offscreen surface to hold the untouched background image
➥ ➥
ddsdGallery.lFlags = DDSD_CAPS Or _ DDSD_WIDTH Or _ DDSD_HEIGHT ddsdGallery.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN ddsdGallery.lWidth = Picture1.Width ddsdGallery.lHeight = Picture1.Height
‘’’ Create the surface by using the “gallery.bmp” image file Set oDDGallerySurf = oDD.CreateSurfaceFromFile(sMedia & _ ➥”Gallery.bmp”, ddsdGallery) ‘’’ Copy the untouched background image to the back buffer ‘’’ for assembly RepaintEntireBackground ‘’’ *** End of creation of offscreen surface *** ‘’’ *** Load all of your sprites into memory ***
➥ ➥
➥ ➥
➥ ➥
‘’’ Here you set the flags for the DirectDraw surface descriptor ‘’’ You are telling it to use the capabilities of the video card, ‘’’ and allow you to set the height and width of the surface ddsdSprite.lFlags = DDSD_CAPS Or _ DDSD_WIDTH Or _ DDSD_HEIGHT ddsdSprite.lWidth = 64 ddsdSprite.lHeight = 64 ddsdSprite2.lFlags = DDSD_CAPS Or _ DDSD_WIDTH Or _ DxVBLib.CONST_DDSURFACEDESCFLAGS.DDSD_HEIGHT ddsdSprite2.lWidth = 64 ddsdSprite2.lHeight = 64 ddsdSprite3.lFlags = DDSD_CAPS Or _ DDSD_WIDTH Or _ DDSD_HEIGHT ddsdSprite3.lWidth = 64 ddsdSprite3.lHeight = 64
CREATING BASIC ANIMATIONS
‘’’ Define the capabilities of each of the sprite surfaces to offscreen ‘’’ and invisible. ddsdSprite.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN ddsdSprite2.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN ddsdSprite3.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN
5
88
DirectX Graphics Programming PART II
LISTING 5.1
Continued
‘’’ Create 3 offscreen surfaces that will be the same size as the ‘’’ bitmap sprite. Set oDDSpriteSurf = oDD.CreateSurfaceFromFile(sMedia & “duck_left.bmp”, ➥ddsdSprite) Set oDDSpriteSurf2 = oDD.CreateSurfaceFromFile(sMedia & “duck_left.bmp”, ➥ddsdSprite2) Set oDDSpriteSurf3 = oDD.CreateSurfaceFromFile(sMedia & “duck_left.bmp”, ➥ddsdSprite3) ‘’’ *** Define the transparent color for your sprites *** ‘’’ You are setting the low range to 0(black) and the ‘’’ high range to 0(black) key.low = 0 key.high = 0 ‘’’Assign a color to the color key property of each sprite surface. oDDSpriteSurf.SetColorKey DDCKEY_SRCBLT, key oDDSpriteSurf2.SetColorKey DDCKEY_SRCBLT, key oDDSpriteSurf3.SetColorKey DDCKEY_SRCBLT, key End Sub
Figure 5.4 shows what the Shooting Gallery example looks like. The ducks are actually individual rectangles that are blitted onto the background surface.
FIGURE 5.4 The “Shooting Gallery” example.
Summary This chapter has focused on DirectDraw surfaces, and you have seen how surfaces are created through the use of the DirectDraw7.CreateSurface or DirectDraw7.CreateSurfaceFromFile method. You have also learned how surfaces are manipulated by page flipping.
Creating Basic Animations CHAPTER 5
89
Then you reviewed the all-important process of blitting. You have seen how the BLIT routine, which comes in five flavors, is used to copy surfaces, or rectangles of surfaces, to another surface. This technique is the most important part of DirectDraw functionality. You also learned that gamma controls are useful for changing colors all at once on a surface by manipulating the red, green, and blue attributes of each pixel. Color controls can be used to achieve the same result as gamma controls, but with a more complex set of options. The color control offers more flexibility by allowing you to change the hue, saturation, brightness, and many other attributes associated with the surface. You then learned about overlays, and saw an example of how they are defined and used with a surface. And finally, you saw an example of how surfaces can be initialized in your programs. In the next chapter, you will discover how animations can be accomplished by simply modifying palettes of color.
5 CREATING BASIC ANIMATIONS
Palettes and Palette Animation
IN THIS CHAPTER • Palettes
92
• Palette Animation
95
• A DirectDrawPalette Example • Summary
101
100
CHAPTER
6
92
DirectX Graphics Programming PART II
In this chapter we are going to look at one of the least talked-about animation techniques in DirectX: palette animation. The reason it’s not talked about as much is that it’s considered a “poor man’s” animation technique. This method of animation is accomplished by switching colors on the screen in rapid succession to simulate animation; in other words, there’s no actual movement. To understand how this method works, you first need to understand how palettes are created and manipulated in DirectX.
Palettes As described in Chapter 3, “Animation Techniques,” palettes are arrays of data that define what colors are available in the DirectDrawSurface class. For example, your palette could be made up of 30 shades of yellow for a sunset in the image, 10 shades of blue for the water, and 5 shades of green for the palm trees on a little island. All these colors are stored in your DirectDrawSurface class.
Palette Types Palettes come in four sizes, with each size being represented by a power of two. The smallest is the 1-bit palette (21 = 2 entries). Next come the 2-bit palette (22 = 4 entries), 4-bit palette (24 = 16 entries), and 8-bit palette (28 = 256 entries). The number of colors in a palette must match the number of colors in the surface it is attached to. For example, a 2-bit palette cannot be used with a surface defined as an 8-bit surface. Table 6.1 shows the four palette types and how many colors each type represents. TABLE 6.1
Palette Types and Number of Colors
Palette Type
Number of Colors
1-bit 2-bit 4-bit 8-bit
2 colors 4 colors 16 colors 256 colors
Palette Entries Since a palette is made up of individual entries, you need a data type to handle these entries. This data type is called PALETTEENTRY, and is made up of three members (or attributes): red, blue, and green. Each of these members represents the red, blue, and green values for each entry in the PALETTEENTRY type. The PALETTEENTRY data type also includes a fourth member called flags, which specify how the palette entry should be used; however, this member is not required.
Palettes and Palette Animation CHAPTER 6
The following code snippet shows the syntax for using PALETTEENTRY:
Type PALETTEENTRY blue As Byte flags As Byte green As Byte red As Byte End Type
Let’s look at an example. If you wanted to set palette entry 1 to black, you would set its red, green, and blue attributes to 0. The following code example shows how this is done Dim PalArray As PALETTEENTRY With PalArray(1) .red = 0 .green = 0 .blue = 0 End With
Using the PALETTEENTRY type in VB.NET This same code can be used in VB.NET. The code below shows how you would use the PALETTEENTRY type: Dim PalArray As DxVBLib.PALETTEENTRY With PalArray(1) .red = 0 .green = 0 .blue = 0 End With
Sharing Palettes Palettes can be shared among multiple surfaces. The same palette can be attached to the front buffer and the back buffer of a flipping chain or shared among multiple texture surfaces. By sharing a palette, you can minimize the access time needed for your program to load and run. Also, if you need to make changes to your palettes, you have to do it only once. When sharing palettes, keep in mind that you must create the surfaces before assigning palettes to them. Figure 6.1 shows two surfaces (primary surface and secondary surface) that are sharing the same palette.
6 PALETTES AND PALETTE ANIMATION
Syntax:
93
94
DirectX Graphics Programming PART II
Primary Surface
Secondary Surface
FIGURE 6.1 Sharing a palette between surfaces.
Here is a code snippet showing how two surfaces can be programmed to use the same palette: Dim Dim Dim Dim Dim Dim
oDX oDD surfPrimary surfSecondary PalArray(255) oDDP
As As As As As As
DirectX7 DirectDraw7 DirectDrawSurface7 DirectDrawSurface7 PALETTEENTRY DirectDrawPalette
Set oDX = New DirectX7 Set oDD = oDX.DirectDrawCreate(“”) Dim I As Integer ‘’’ Populate the palette array. For I = 0 To 255 PalArray(I).red = I PalArray(I).green = I PalArray(I).blue = I Next I ‘’’ Create the palette with your new entries Set oDDP = oDD.CreatePalette(DDPCAPS_8BIT Or DDPCAPS_ALLOW256, PalArray) ‘’’ Apply the palette to both surfaces surfPrimary.SetPalette oDDP surfSecondary.SetPalette oDDP
Creating two surfaces that use the same palette in VB.NET This same code can be used in VB.NET. The code below shows how you would create two surfaces that use the same palette: Dim oDX Dim oDD Dim surfPrimary
As DxVBLib.DirectX7() As DxVBLib.DirectDraw7 As DxVBLib.DirectDrawSurface7
Palettes and Palette Animation CHAPTER 6
As DxVBLib.DirectDrawSurface7 As DxVBLib.PALETTEENTRY As DxVBLib.DirectDrawPalette
oDX = New DxVBLib.DirectX7 oDD = oDX.DirectDrawCreate(“”) Dim I As Integer ‘’’ Populate the palette array. For I = 0 To 255 PalArray(I).red = I PalArray(I).green = I PalArray(I).blue = I Next I ‘’’ Create the palette with your new entries oDDP = oDD.CreatePalette( _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_8BIT _ ➥ Or DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_ALLOW256, ➥ PalArray) ‘’’ Apply the palette to both surfaces surfPrimary.SetPalette(oDDP) surfSecondary.SetPalette(oDDP)
Palette Animation Palette animation refers to the process of modifying a surface’s palette to change how the surface itself looks when displayed. By repeatedly changing the palette, the surface appears to change without actually modifying its contents. To this end, palette animation gives you a way to modify a surface’s appearance without changing its contents and with very little overhead. A good example of using palette animation is a kiosk that shows car models. By changing the palette, you can very quickly offer the user an example of a different color for the car without having to redraw the car. Figure 6.2 shows two versions of the same car. By simply changing the palette, the person sees a completely different-looking car.
Palette
FIGURE 6.2 Changing the colors of a car by changing the palette.
6 PALETTES AND PALETTE ANIMATION
Dim surfSecondary Dim PalArray(255) Dim oDDP
95
96
DirectX Graphics Programming PART II
There are two methods for providing straightforward palette animation: modifying palette entries within a single palette and switching between multiple palettes.
Modifying the Palette This palette animation method involves changing individual entries in the palette by using the DirectDrawPalette.SetEntries method. For example, you can change a palette’s bright blue entry to white, and this change will instantly ripple down to the attached surface and be displayed. If you need to modify only some of the colors in the palette, modifying the palette is a much better method than the “switching palette” technique outlined in the following section. The reason is that you are not modifying a whole palette and then attaching it to the surface; you are changing only some index entries in the existing palette, so this process is quicker. Figure 6.3 shows a surface attached to a palette that’s being modified. These changes will instantly be carried out in the attached surface.
Primary Surface
Change Palette Indexes Palette
FIGURE 6.3 Manipulating a palette connected to a surface.
This is a code snippet showing how the palette attached to a surface can be manipulated: Dim Dim Dim Dim Dim
oDX oDD surfPrimary PalArray(255) oDDP
As As As As As
DirectX7 DirectDraw7 DirectDrawSurface7 PALETTEENTRY DirectDrawPalette
Set oDX = New DirectX7 Set oDD = oDX.DirectDrawCreate(“”) ‘’’ Create the palette with your new entries
Palettes and Palette Animation CHAPTER 6 oDDP = oDD.CreatePalette(DDPCAPS_8BIT Or DDPCAPS_ALLOW256, PalArray()
‘’’ Modify the palette entries oDDP.SetEntries 0, 255, PalArray
Modifying a palette that’s attached to a suface in VB.NET This same code can be used in VB.NET. The code below shows how you would modify a palette that’s attached to a surface: Dim Dim Dim Dim Dim
oDX objDD surfPrimary PalArray(255) oDDP
As As As As As
DxVBLib.DirectX7 DxVBLib.DirectDraw7 DxVBLib.DirectDrawSurface7 DxVBLib.PALETTEENTRY DxVBLib.DirectDrawPalette
oDX = New DxVBLib.DirectX7 oDD = oDX.DirectDrawCreate(“”) ‘’’ Create the palette with your new entries oDDP = oDD.CreatePalette( _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_8BIT Or _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_ALLOW256, _ ➥ PalArray) ‘’’ Apply the palette to the surface surfPrimary.SetPalette(oDDP) ‘’’ Modify the palette entries oDDP.SetEntries(0, 255, PalArray)
Switching Palettes The second method for palette animation is to use two or more palettes and attach a new palette for every frame of animation. This technique has the result of changing a much larger amount of data at one time than you can with the “modifying the palette” technique. The method used to accomplish it is DirectDrawSurface7.SetPalette. A good use for this technique is when you want to create fading effects. By simply modifying another palette and then attaching it to the surface, you can fade all the colors on the screen at once.
6 PALETTES AND PALETTE ANIMATION
‘’’ Apply the palette to the surface surfPrimary.SetPalette oDDP
97
98
DirectX Graphics Programming PART II
Figure 6.4 shows a surface that is attached to one palette and then switched to another by using the DirectDrawSurface7.SetPalette method. Here is a code snippet showing how a surface can be programmed to use two different palettes: Dim Dim Dim Dim Dim Dim Dim
oDX oDD surfPrimary PalArray1(255) PalArray2(255) oDDPalette1 oDDPalette2
As As As As As As As
New DirectX7 DirectDraw7 DirectDrawSurface7 PALETTEENTRY PALETTEENTRY DirectDrawPalette DirectDrawPalette
Dim I As Integer ‘’’ Populate both palette arrays. For I = 0 To 255 PalArray1(I).red = I PalArray1(I).green = I PalArray1(I).blue = I PalArray2(I).red = I PalArray2(I).green = I PalArray2(I).blue = I Next I ‘’’ Create the palettes with your new entries oDDPalette1 = oDD.CreatePalette(DDPCAPS_8BIT Or DDPCAPS_ALLOW256, _ ➥ PalArray1()) oDDPalette2 = oDD.CreatePalette(DDPCAPS_8BIT Or DDPCAPS_ALLOW256, _ ➥ PalArray2()) ‘’’ Cycle through the two palettes in rapid succession. While Not exitloop ‘’’ Apply palette1 to the surface surfPrimary.SetPalette oDDPalette1 ‘’’ Apply palette2 to the surface surfPrimary.SetPalette oDDPalette2 End While
Palettes and Palette Animation CHAPTER 6
99
6
Palette #1
PALETTES AND PALETTE ANIMATION
Primary Surface
Palette #2
FIGURE 6.4 Changing the palette of a surface.
Creating a surface that uses two palettes in VB.NET This same code can be used in VB.NET. The code below shows how you would create a surface that uses two palettes: Dim Dim Dim Dim Dim Dim Dim
oDX oDD surfPrimary PalArray1(255) PalArray2(255) oDDPalette1 oDDPalette2
As As As As As As As
New DxVBLib.DirectX7 DxVBLib.DirectDraw7 DxVBLib.DirectDrawSurface7 DxVBLib.PALETTEENTRY DxVBLib.PALETTEENTRY DxVBLib.DirectDrawPalette DxVBLib.DirectDrawPalette
Dim I As Integer ‘’’ Populate both palette arrays. For I = 0 To 255 PalArray1(I).red = I PalArray1(I).green = I PalArray1(I).blue = I PalArray2(I).red = I PalArray2(I).green = I PalArray2(I).blue = I Next I continues
100
DirectX Graphics Programming PART II
‘’’ Create the palettes with your new entries oDDPalette1 = oDD.CreatePalette( _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_8BIT Or _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_ALLOW256, _ ➥ PalArray1) oDDPalette2 = oDD.CreatePalette( _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_8BIT Or _ ➥ DxVBLib.CONST_DDPCAPSFLAGS.DDPCAPS_ALLOW256, _ ➥ PalArray2) ‘’’ Cycle through the two palettes in rapid succession. While Not exitloop ‘’’ Apply palette1 to the surface surfPrimary.SetPalette(oDDPalette1) ‘’’ Apply palette2 to the surface surfPrimary.SetPalette(oDDPalette2) End While
A DirectDrawPalette Example Listing 6.1 is a portion of a program called Palette Animation that uses DirectDrawPalette to create an effect similar to movie credits appearing and then fading off the screen. The subroutine in the listing handles the creation of all the DirectDrawPalette classes. The comments in the code explain how and why each component and method is being used. The complete code for this example can be found on the net. LISTING 6.1
Palette Animation Example
‘’’ Palette Variables Dim PalArray(255)
As PALETTEENTRY
‘’’ This is the palette object; it is created by DirectDraw based ‘’’ on the entries in the above array. Dim oDDP As DirectDrawPalette ‘***************************************************************************** ‘** ObjectName: SetupPalette ‘** ‘** Description: This subroutine does the following: ‘** 1. Creates a palette array with default entries ‘** 2. Creates a palette ‘** 3. Assigns the palette to a surface ‘** ‘*****************************************************************************
Palettes and Palette Animation CHAPTER 6
LISTING 6.1
Continued
Dim I As Integer ‘’’ Populate the palette array. For I = 0 To 255 PalArray(I).red = I PalArray(I).green = I PalArray(I).blue = I Next I ‘’’ Create the palette with your new entries set oDDP = oDD.CreatePalette(DDPCAPS_8BIT Or DDPCAPS_ALLOW256, PalArray) ‘’’ Assign the palette to the surface surfPrimary.SetPaletteoDDP End Sub
Summary In this chapter, you have learned that palettes are indexes of colors used in the creation of surfaces and images. Each palette is made up of palette entries that define each item in the palette, such as defining the intensity of red, green, and blue in each entry. By assigning these palettes to an existing surface, you can manipulate the color scheme to anything you want. Palettes can produce wonderful animated effects, such as fading text or flashing screens. You have also learned how many colors each palette has available to it. A single palette can be used by more than one surface. The converse is also true; you can use more than one palette to control the colors of a surface. To use palette animation, you learned that you can use two techniques: modifying palette entries within a single palette and switching between multiple palettes. Finally, you reviewed a code example that showed you how a subroutine accomplishes palette animation in code. In the next chapter, you will learn about 3D graphics and the terms used in DirectGraphics.
6 PALETTES AND PALETTE ANIMATION
Sub SetupPalette()
101
CHAPTER
3D Geometry
7
IN THIS CHAPTER • 3D Space Coordinate System • 3D Objects • Matrices • Summary
105 111 112
104
104
DirectX Graphics Programming PART II
To understand 3D graphics programming, you must first become familiar with the terms and concepts involved. This can become intimidating if you haven’t had advanced math courses such as Matrices and Linear Algebra. However, all you really need to know is covered in this chapter. This is the basics, but if you want to learn more, I would recommend looking for some advanced 3D graphics theory books. A few of the best books are listed below: “Graphic Gems I” by Andrew S. Glassner, ISBN: 0122861663 “Advanced Animation and Rendering Techniques: Theory and Practice” by Mark Watt and Alan Watt, ISBN: 0201544121 From this point on, the discussion focuses on 3D graphics, which is the foundation of DirectGraphics. DirectGraphics is how Microsoft is organizing its entire graphics-programming library. Since DirectDraw is no longer part of DirectX 8, Direct3D is the only library left. Therefore you can use Direct3D and DirectGraphics interchangeably.
3D Space Coordinate System The coordinate system used in Direct3D is called a left-handed Cartesian coordinate system. In the graphics community, we refer to objects having coordinates in one of three directions: x, y, and z. In a left-handed Cartesian coordinate system, the x direction denotes horizontal dimensions, the y direction represents the vertical direction, and, finally, the z direction is the depth. The reason this layout is called a left-handed Cartesian coordinate system can be seen if you take your left hand and make a slight cupping motion in front of you, with the palm up. The thumb on your left hand would represent the Z direction, which is travelling away from the body. The fingertips that are pointed upward represent the Y plane that goes upward. Your palm represents the X plane that goes left and right. The reverse of the left-handed Cartesian coordinate system is a right-handed Cartesian coordinate system that uses the same points of reference for X and Y, however the Z direction is now coming toward the viewer instead of away from the viewer. This basically represents the fact that if you hold your right hand up the same way you did for the left hand, the only thing that would change is the side that the thumb is on(which represents the Z axis). Figure 7.1 is a diagram of a left-handed Cartesian coordinate system. Y
Z
X
FIGURE 7.1 Left-handed Cartesian coordinate system.
3D Geometry CHAPTER 7
105
With the left-handed Cartesian coordinate system, you can position 3D objects in one of three different types of space coordinates: 3D world space, model space, and camera space, as discussed in the following bullets). • 3D World Space—In 3D world space, coordinates are used in relation to a world origin. All coordinates in the 3D world are referenced from the world’s origin point, which is used for all objects you are trying to render. • Model Space—Model space is a coordinate system based on a specific object or model. The origin is unique to that model and might not be the same as the 3D world space.
Now, let’s try to bring all three of these spaces together. A good example for this would be a scene that you could make that consists of a spinning cube. The first thing you would do is create the world space to hold all the objects we are going to look at. Then you would want to place the cube in the world space. To do this, you would give the cube a model space. By modifying the model space for the cube you can then rotate the cube without having to rotate the whole world. Then, we need to look at this scene by using a camera space. This allows us to manipulate the camera independently of the world space or the model space of the cube. With the camera space, we can zoom in and out of our scene and not affect the spinning cube, or the world itself. Figure 7.2 shows the three coordinate spaces in relation to each other. Y
Y
Z
X 3D World Space
Y
Z
Z
X Model Space
X Camera Space
FIGURE 7.2 Comparing the three coordinate spaces.
3D Objects Direct3D requires knowledge of the basic 3D objects. These objects are responsible for defining where each point is in 3D space. The following section explains how to link these objects, what to put on them, and how to arrange them in 3D space.
7 3D GEOMETRY
• Camera Space (View Space)—This view of the world places the viewer (user) at the origin and faces him or her in the direction of the positive Z-axis. It helps to imagine you have a camera and are pointing it out into space to look at the objects. The camera or viewer would be at the origin or viewpoint, looking out into space.
106
DirectX Graphics Programming PART II
Vertices A vertex (plural: vertices) is a point in 3D space made up of three coordinates: x, y, and z. Each polygon in 3D space is made up of a series of vertices. With a set of vertices, you can understand where each corner of an object is in relation to every other object. This information helps the graphic card determine how to draw 3D objects. By combining vertices, you can create complex shapes. By connecting these vertices with straight lines, you can create simple shapes. The shapes are kind of blocky at first, but that’s okay. As you add more and more vertices, the connecting lines become smaller because the distance between vertices is decreasing, which results in more refined curves. Figure 7.3 shows a curve with 4 vertices becoming more refined when it has 10 vertices.
FIGURE 7.3 Comparison between a simple and a complex curve.
Polygons A polygon is composed of two things: vertices and lines. Polygons are composed of three or more vertices with lines connecting the vertices to form an object that is completely enclosed. A triangle is the most common polygon. Polygons can be combined to form simple shapes, such as balls, cylinders, and boxes. They can also be combined to form more complex shapes such as machinery. With enough polygons you can create organic shapes such as apples, trees, and fish. When you look at 3D video cards in the store, you will notice that they mention polygon count, which indicates how many polygons can be drawn every second. This rate is constantly rising because of advances in 3D graphic chip technology. Early video cards could produce polygons
3D Geometry CHAPTER 7
107
in only the few thousands per second range, but today’s cards can produce millions of polygons per second. With this advance in the power of video cards, modern video games have become more realistic with smoother, more highly detailed graphics. Figure 7.4 shows the difference between a ball created with a few polygons versus one with many more polygons. The ball on the left has 32 polygons. The one on the right has 128 polygons. Which one do you think would bounce better?
7 3D GEOMETRY
FIGURE 7.4 A ball with different polygon counts.
Faces Faces are polygons used to create a mesh for an object. A mesh is a surface that is the covering that makes an object solid. Therefore, when you see reference to a face in DirectX documentation, just think of an individual polygon used to create a more complex object. By combining faces, you can create the surface (or mesh) of an apple or other object. Figure 7.5 shows a mesh and its supporting faces.
Mesh A mesh is a collection of vertices and faces that describe an object. Another term for a mesh is a wireframe. Wireframes have been used by 3D artists for many years, so they should be familiar to everyone. A mesh can be a simple object, such as a ball, or a more complex object, such
108
DirectX Graphics Programming PART II
as a dolphin. By placing meshes of trees all over your 3D environment, you can produce a forest. When you are creating a 3D environment, you need a variety of meshes. Figure 7.6 shows a mesh of a mustard bottle. By applying a texture with a yellow tint and a material that reflects like plastic, I’ll have a nice-looking mustard bottle. Mesh
Face
FIGURE 7.5 A mesh and its supporting faces.
FIGURE 7.6 A mustard bottle mesh.
3D Geometry CHAPTER 7
109
Texture A texture is a rectangular bitmap image that can be stretched over a surface. For example, if you created a mesh of a tree but didn’t want just a plain brown color for the bark, you could add a texture. By simply scanning a close-up picture of your favorite tree bark, you could then apply that image as a texture to your mesh. This technique is used in the game and multimedia industry to create the look and feel of complex objects without the headaches. Figure 7.7 shows the difference between three balls, each with a different texture. The first one is covered with a marble texture, the second with burlap, and the third with brick.
7 3D GEOMETRY
FIGURE 7.7 Three different textures: marble, burlap, and brick.
Lights If you have used lights in any of the popular 3D modeling programs, you undoubtedly realize the importance of light effects. Light can put focus on specific areas of your image and de-emphasizes other areas and can also set the mood and character of a scene. With the right light applied, a scene can change drastically from mediocre to spectacular. With the lights in Direct3D, you can change the light type and its color, direction, and position. In Figure 7.8, you can see three different lighting effects created by changing the lights used in the scene.
Materials Materials are attributes of a polygon that define their reflective property when light is assigned to them. For example, if you want your sphere to be shiny, like a marble, you would set up the material properties of all the polygons (faces) of the mesh that makes up the sphere. When light is applied to the scene, the materials properties tell the graphics engine how the light should reflect off its surface. Materials can be used to change the reflection intensity and to make the polygons actually appear to produce light. Figure 7.9 shows how a material can be used to a reflect the light of an object in 3D space.
110
DirectX Graphics Programming PART II
FIGURE 7.8 Three different lighting effects.
FIGURE 7.9 A reflective ball.
3D Geometry CHAPTER 7
111
Matrices
M11 M12 M13 M14 M21 M22 M23 M24 M31 M32 M33 M34 M41 M42 M43 M44
FIGURE 7.10 A basic 4×4 matrix. The main advantage of using matrices is that you can transform an object quickly by passing it through a matrix. This process is much quicker than using algorithms because all the calculations have been condensed into a simple grid that can be used like a lookup table. This reduces processing power considerably and produces graphics much faster. Matrices can also be combined with one another to come up with new matrices that complete multiple transformations all at once. Figure 7.11 shows a scaling matrix. This figure represents the fact that to scale your object you simply need to change the S values to the number you want to scale by. For example, if you wanted to scale your object by 5 times, you would pass the object through the scaling matrix and change all the S values to 5, therefore producing new vertices for your object that represent the scaling of the object. The 0’s in the matrix mean that these values don’t need to be modified. The 1 represents a value that needs to be set to 1 for this matrix to function correctly.
FIGURE 7.11 A scaling matrix.
S
0
0
0
S
0
0 0
0
0
S
0
0
0
0
1
7 3D GEOMETRY
A matrix (plural: matrices) a is basically a simple table used to modify values quickly. Using matrices is a very advanced topic that is usually taught only in advanced computer courses. Figure 7.10 shows the standard layout of a 4×4 matrix. In this figure, the letter M represents an element in the matrix, similar to elements in a two dimensional array. The numbers below and to the right of each member represent its position in the matrix. The first number represents the row, and the second represents the column. In many advanced graphics programming books, you will see matrices explained in this format. By knowing where the numbers need to be changed in the matrix to produce the desired effect, you can easily convert a matrix to DirectX code.
112
DirectX Graphics Programming PART II
The following code creates a subroutine that can be used to change the scale of a matrix. You will notice that it corresponds to the same values shown in Figure 7.11. For example, the line that says m3DMatrix.m44 is referencing the fourth column over and the fourth column down and setting its value to 1. By changing the value of the Scale value, you can scale your object proportionally by simply calling this subroutine and passing the original matrix and the amount you want to scale it by. Sub ScaleMatrix(m3DMatrix As D3DMATRIX, sScale As Single) m3DMatrix.m11 = sScale m3DMatrix.m22 = sScale m3DMatrix.m33 = sScale m3DMatrix.m44 = 1 End Sub
There are three types of matrices—projection matrix, view matrix, and world matrix—that can be used to resize, move, and rotate objects in 3D space.
Projection Matrix The projection matrix is used to control what users see when they are looking at the 3D world. This matrix affects the image’s scale and perspective.
View Matrix The view matrix is designed to transform vertices from world space into camera space. After conversion to camera space, the camera is positioned at the origin looking in the positive-z direction.
World Matrix (World Transformation) A world matrix can be used to transform a model’s vertices from model space to world space. When this is done, all the models in the 3D environment share the same origin.
Summary In this chapter, you have focused on 3D terms and techniques. You learned the differences in the three types of 3D space coordinate systems: 3D world space coordinates correspond to the world’s origin, model space coordinates correspond to the model’s origin, and camera space coordinates correspond to the positioning of camera or user in 3D space. You also learned about 3D objects and how they work to create 3D effects. Vertices are points in 3D space; when connected with lines, they form polygons that are made up of areas called faces. These faces can be grouped to produce meshes. Textures are bitmap images stretched
3D Geometry CHAPTER 7
113
over meshes or polygons, lights are used to emphasize objects, and materials determine a texture’s reflective nature when light is applied to it. Although matrices are a complex topic, you learned that they are used to shrink, expand, move, and rotate objects in 3D space. By passing a vertex through a projection, view, or world matrix, you can transform it very quickly. By using matrices in your 3D programming, you can make 3D calculations fast and efficient. In Chapter 8, “Direct3D,” you will learn about basic Direct3D graphics programming.
7 3D GEOMETRY
CHAPTER
Direct3D
8
IN THIS CHAPTER • Direct3D Objects
116
• Creating 3D Applications • Summary
152
129
116
DirectX Graphics Programming PART II
In this chapter, you will begin taking a look at how to build basic Direct3D applications. This chapter focuses on the basics and builds a little more each time, until you have created applications that use texture, material, and lights to show your 3D environment.
Direct3D Objects This section details the objects that are available in Direct3D. You will learn about the Direct3D8 base class before examining the Direct3DBaseTexture8, Direct3DTexture8, and Direct3DCubeTexture8 classes for creating and maintaining textures. The Direct3DDevice8 class handles all device-related issues, and the Direct3DIndexBuffer8 and Direct3DVertex Buffer8 classes maintain index and vertex buffers. Surfaces, you will learn, are maintained by the Direct3DSurface8 class, and resources are controlled by the Direct3DResource8 class. You will also learn about swap chains and how the Direct3DSwapChain8 class maintains pageflipping techniques as well as volumes and how the Direct3DVolume8 and Direct3DVolumeTexture8 classes can be used to control them. Finally, you will take a look at how to use these classes to create an evolving series of applications. These applications range from simple triangles to more complex lighting, material, and mesh techniques.
The Direct3D8 Class The Direct3D8 class, the foundation on which all Direct3D applications must be built, is used to create a Direct3DDevice8 object. It also has methods that help determine the capabilities of 3D video cards on the machine. Before any other Direct3D object can be used, a Direct3D8 class must be declared and invoked. Table 8.1 shows the methods of the Direct3D8 class. TABLE 8.1
The Direct3D8 Methods
Method
Description
CheckDepthStencilMatch
Checks whether a supported depth-stencil format is compatible with the render target format in the display mode. This is important if a depth format must be equal to the render target format. Checks for devices that match a specified format. Checks to see whether multisampling techniques are available on the current device. Checks to see whether the required hardware and drivers are present on the system. This method is valuable for verifying whether the video card will be able to work with your program.
CheckDeviceFormat CheckDeviceMultiSampleType CheckDeviceType
Direct3D CHAPTER 8
TABLE 8.1
117
Continued
Description
CreateDevice
Creates a video card device that can be manipulated through code. Creates an enumerated list of all the display modes supported by a specified video card. Gets the number of video cards available on your system. Gets the current display mode of the video card on your system. Gets a list of the video cards on the machine and a D3DADAPTER_IDENTIFIER8 type that contains information about each video card. Gets a count of the display modes available on your machine. Gets a handle to the monitor being used by Direct3D. Gets a D3DCAPS8 type that provides information about the capabilities of the rendering device. Some video card vendors provide pluggable software devices that can be accessed by DirectX to help render parts of Direct3D objects. This method registers these pluggable software devices with the Direct3D environment.
EnumAdapterModes GetAdapterCount GetAdapterDisplayMode GetAdapterIdentifier
GetAdapterModeCount GetAdapterMonitor GetDeviceCaps RegisterSoftwareDevice
The Direct3DBaseTexture8 Class The Direct3DBaseTexture class has methods designed to maintain and create Direct3D texture objects. It also maintains the level of detail (LOD) for a texture. Level of detail refers to how many times you can reduce the image size before it becomes unrecognizable. For example, if the texture you are working with is a 512×512 image, setting the maximum LOD to 0 would mean that 512×512 is the smallest size you want this image reduced to. If you set the maximum LOD to 1, the lowest resolution displayed would be 256×256. If you chose 2 as the LOD, the lowest resolution would be 128×128. The larger the original texture, the higher your LOD number can be because there will be very little loss in the image when its dimensions shrink. also implements the following methods: FreePrivateData, and SetPrivateData. Descriptions of these methods can be found in the section on Direct3DResource8 methods later in this chapter.
Direct3DBaseTexture8
GetDevice, GetType, GetPriority, GetPrivateData, PreLoad, SetPriority,
8 DIRECT3D
Method
118
DirectX Graphics Programming PART II
Table 8.2 shows the methods of the Direct3DBaseTexture8 class. TABLE 8.2
The Direct3DBaseTexture8 Methods
Method
Description
GetLevelCount
Gets the number of texture levels in a multilevel texture. Gets the maximum LOD number. Sets the maximum LOD number.
GetLOD SetLOD
The Direct3DCubeTexture8 Class The Direct3DCubeTexture8 class is used to maintain a cube resource. With this class, you have access to “dirty” rectangle methods. Dirty rectangles are regions of a rectangle that have changes on them and/or need to be repainted. Imagine a kid making smudges on your wall— hence the term dirty. By specifying a “dirty” area, you know exactly where you need to paint, and you can save time by not having to repaint the whole wall. You just repaint where the smudge is. also implements the following methods: FreePrivateData, GetDevice, and SetPrivateData. Descriptions of these methods can be found in the section on Direct3DResource8 methods later in this chapter. Direct3DBaseTexture also implements the following methods: GetLevelCount, GetLOD, and SetLOD. Descriptions of these methods can be found in the preceding section on Direct3DBaseTexture8 methods. Direct3DCubeTexture
GetType, GetPriority, GetPrivateData, PreLoad, SetPriority,
Table 8.3 shows the methods of the Direct3DCubeTexture8 class. TABLE 8.3
The Direct3DCubeTexture8 Methods
Method
Description
AddDirtyRect
Adds a dirty rectangle to a cube map. Gets a cube map surface. Gets a D3DSURFACE_DESC type that contains a description of the specified cube texture level. Locks the rectangle on a cube texture. Unlocks the rectangle on a cube texture.
GetCubeMapSurface GetLevelDesc LockRect UnlockRect
Direct3D CHAPTER 8
119
The Direct3DDevice8 Class The Direct3DDevice8 class has the most methods of any of the Direct3D classes. It is responsible for managing the scene by determining when rendering begins and ends on a device. It also maintains a device’s lights, materials, and textures. Basically, any object that relates to a device has a matching method in the Direct3DDevice8 class to make information about it available. Table 8.4 shows the methods of the Direct3DDevice8 class. TABLE 8.4
The Direct3DDevice8 Methods
Description
ApplyStateBlock
Applies a device-state block to the rendering device. Begins processing the back buffer screen. This method must be called before any processing begins on a scene. Starts the recording of a device-state block. Updates the existing state block with parameters used in the device. Clears the viewport or rectangle with a specified color. This must be done before rendering the scene. Copies a rectangle of pixels from one surface to another. Creates an additional swap chain for animation. Creates a cube texture. Creates a depth-stencil surface by specifying the height, width, and format of the surface. Creates an image surface. Creates an index buffer. Creates a pixel shader from this device. Creates a render target surface. Used to create a new device-state block that contains the values for all device states, vertex-related states, or pixel-related states. Used to create a Direct3DTexture8 object. Used to create a Direct3DVertexBuffer8 object. Creates and sets a vertex shader to the default shader for this device. Used to create a Direct3DVolumeTexture8 object.
BeginScene BeginStateBlock CaptureStateBlock Clear CopyRects CreateAdditionalSwapChain CreateCubeTexture CreateDepthStencilSurface CreateImageSurface CreateIndexBuffer CreatePixelShader CreateRenderTarget CreateStateBlock
CreateTexture CreateVertexBuffer CreateVertexShader CreateVolumeTexture
8 DIRECT3D
Method
120
DirectX Graphics Programming PART II
TABLE 8.4
Continued
Method
Description
DeletePatch
Deletes a high-order patch. Used to delete a pixel shader from this device. Deletes a device-state block. Deletes a specific vertex shader. Draws a primitive by indexing an array of vertices. Draws a primitive by accessing indexed data in a user’s memory array. Draws a primitive from the current input stream data. Draws a primitive from the current data in a user’s memory array. Draws a high-order patch in the shape of a rectangle, using the current stream. Draws a high-order patch in the shape of a triangle, using the current stream. Ends the processing of the back buffer screen. This is the last method called after you are finished drawing to the back buffer. Stops the recording of a device-state block. Gets data on the available texture memory in the current device. Gets a Direct3DSurface8 object that represents the indexed back buffer surface from this device. Gets the coefficients of a clipping plane for this Direct3D device. Gets a D3DCLIPSTATUS8 type that describes the clip status of a Direct3D device. Gets the creation parameters of a device by retrieving a D3DDEVICE_CREATION_PARAMETERS type. Gets the texture palette currently being used by this device. Gets the depth-stencil surface of this device. Gets the capabilities of the rendering device by using the D3DCAPS8 type. Gets a reference to the Direct3D object used to create this Direct3D device.
DeletePixelShader DeleteStateBlock DeleteVertexShader DrawIndexedPrimitive DrawIndexedPrimitiveUP DrawPrimitive DrawPrimitiveUP DrawRectPatch DrawTriPatch EndScene
EndStateBlock GetAvailableTextureMem GetBackBuffer GetClipPlane GetClipStatus GetCreationParameters GetCurrentTexturePalette GetDepthStencilSurface GetDeviceCaps GetDirect3D
Direct3D CHAPTER 8
TABLE 8.4
121
Continued
Description
GetDisplayMode
Gets the current display mode’s resolution, color depth, and refresh rate. Gets the front buffer of this device and places a copy in a Direct3DSurface8 object. Gets the gamma correction ramp for the swap chain. Gets index data about a Direct3DIndexBuffer8 object. This method returns debugging information about the Direct3D device. Gets a D3DLIGHT8 type that contains information about a specific light associated with this device. Gets the status (enabled/disabled) of a light in this device. Gets the D3DMATERIAL8 type, which holds the material properties for this device. Gets the palette entries from a specified palette. The values are returned in a PALETTEENTRY type. Gets a handle to the current pixel shader. Gets the parameters from the pixel constant array. Gets the pixel shader function used to specify blending operations. Gets information about the raster of the monitor using the swap chain. Raster-drawing capabilities are capabilities such as fog, antialiasing, LOD adjustments, and depth buffering, supported by many of today’s 3D video cards. Gets the render-state for a device. Gets the render target for a device. A render target is the surface being rendered to. Gets a vertex buffer that’s attached to a data stream. Gets a Direct3DBasTexture8 object from this device. Gets a state value for an assigned texture. Gets a transformation matrix. Gets a handle to the current vertex shader for this device.
GetFrontBuffer GetGammaRamp GetIndices GetInfo GetLight GetLightEnable GetMaterial GetPaletteEntries GetPixelShader GetPixelShaderConstant GetPixelShaderFunction GetRasterStatus
GetRenderState GetRenderTarget GetStreamSource GetTexture GetTextureStageState GetTransform GetVertexShader
8 DIRECT3D
Method
122
DirectX Graphics Programming PART II
TABLE 8.4
Continued
Method
Description
GetVertexShaderConstant
Gets the values in the vertex constant array. Gets the vertex shader’s declaration token array. Gets the vertex shader function to define the operation to apply to each vertex. Gets the D3DVIEWPORT8 type, which represents the viewport properties currently set for this device. Enables or disables a set of lights in this device. Takes this device’s matrixes and multiplies them by another matrix. This can be used with all three transform types: world, view, or projection. Presents the next back buffer to the user. This is the main method for displaying the completed image. Takes the vertex processing from the vertex shader to the input data streams. This results in a single stream of interleaved vertex data to a destination vertex buffer. Modifies the D3DPRESENT_PARAMETERS type, which changes the type, size, and format of the this device’s swap chain. Causes the resource manager to free a specified amount of memory (in bytes) or all memory from the Direct3D device. Sets the coefficients of a clipping plane for this Direct3D device. Using a D3DCLIPSTATUS8 type, this method sets the clip status. Sets the texture palette for this device. Sets the cursor to an x and y screen-space coordinate. This position is used to determine the placement of a cursor image that you want to draw. Sets the properties of the cursor, including the x and y hot spots. A hot spot is an x, y coordinate within the cursor that denotes the center of the cursor. There is also a cursor surface property used to associate a Direct3D surface with the cursor. Sets a gamma correction ramp for the swap chain.
GetVertexShaderDeclaration GetVertexShaderFunction GetViewport LightEnable MultiplyTransform
Present ProcessVertices
Reset
ResourceManagerDiscardBytes
SetClipPlane SetClipStatus SetCurrentTexturePalette SetCursorPosition
SetCursorProperties
SetGammaRamp
Direct3D CHAPTER 8
TABLE 8.4
123
Continued
Description
SetIndices
Sets index data for a Direct3DIndexBuffer8 object. Sets the light properties for this device. Sets the material properties for this device. Sets an array of palette entries all at once by supplying an array of entries and a palette number to populate. Sets the current pixel shader to another pixel shader. Sets the parameters in the pixel constant array. Sets a device render-state parameter. Sets a color buffer and/or depth-stencil buffer for a Direct3D device. Sets the stream source for a vertex buffer. Sets a texture to a specified state value in this device. Sets a state value for an assigned texture. Sets a device transformation-related state. Sets the current vertex shader to a previously created vertex shader. Sets the values in the vertex constant array. Sets the viewport parameters by passing a D3DVIEWPORT8 type to the device. Shows or hides the cursor. Gets the current cooperative level for this device. Updates a dirty texture rectangle with another texture from a second texture source. Returns the number of rendering passes that were needed to complete the current effect.
SetLight SetMaterial SetPaletteEntries SetPixelShader SetPixelShaderConstant SetRenderState SetRenderTarget SetStreamSource SetTexture SetTextureStageState SetTransform SetVertexShader SetVertexShaderConstant SetViewport ShowCursor TestCooperativeLevel UpdateTexture ValidateDevice
The Direct3DIndexBuffer8 Class The Direct3DIndexBuffer8 class is responsible for locking and unlocking the index buffer for writing. It’s also responsible for maintaining the index buffer, which is a memory buffer that contains index data that is an offset into a vertex buffer. The Direct3DIndexBuffer also implements the following methods: FreePrivateData, and
GetDevice, GetType, GetPriority, GetPrivateData, PreLoad, SetPriority,
8 DIRECT3D
Method
124
DirectX Graphics Programming PART II SetPrivateData.
Descriptions of these methods can be found in the section on Direct3DResource8 methods later in this chapter. Table 8.5 shows the methods of the Direct3DIndexBuffer8 class. TABLE 8.5
The Direct3DIndexBuffer8 Methods
Method
Description
GetDesc
Gets a D3DINDEXBUFFER_DESC type that contains a description of this index buffer. Locks a series of index data and allows access to the memory in the index buffer. Unlocks the index data. At this time, no more index buffer memory can be accessed.
Lock Unlock
The Direct3DResource8 Class The Direct3DResource8 class is used to create and maintain multiple resources, including textures, vertex buffers, and index buffers. It also maintains the priority of a resource, specifies which device it is attached to, and releases data allocated to this resource. The Direct3DResource8 class is a subset of many of the other classes, including Direct3DBaseTexture8, Direct3DCubeTexture8, Direct3DIndexBuffer8, Direct3DTexture8, Direct3DVertexBuffer8, and Direct3DVolumeTexture8. All of these classes can call the same methods that Direct3DResource8 makes available. Table 8.6 shows the methods of the Direct3DResource8 class. TABLE 8.6
The Direct3DResource8 Methods
Method
Description
FreePrivateData
Releases any private data that has been associated with this resource. Gets the Direct3D device that is associated with this Direct3D resource. Gets the priority of the resource. The priority determines in what order resources are removed from memory. Lower numbered resources are removed first. Gets the private data from a resource and transfers it to a buffer for storage.
GetDevice GetPriority
GetPrivateData
Direct3D CHAPTER 8
TABLE 8.6
125
Continued
Method
Description
GetType
Gets a CONST_D3DRESOURCETYPE that identifies the resource’s type. The types can be surface, volume, texture, volume texture, cube texture, vertex buffer, or index buffer. Notifies the Direct3DResource8 that a managed resource will be needed very soon. Sets the priority of the resource. Stores a buffer of private data in a resource.
PreLoad SetPriority SetPrivateData
The Direct3DSurface8 Class The Direct3DSurface8 class is used to maintain a Direct3D surface. It is responsible for locking/unlocking rectangles on the surface, finding the associated device of a surface, and finding the cube texture or texture of a surface. Table 8.7 shows the methods of the Direct3DSurface8 class. TABLE 8.7 Method
Description
FreePrivateData
Frees this surface’s private data that is passed in by a DXGUID type, which identifies where the private data resides. Gets a container object (of type unknown) that can be used to provide access to the parent cube texture or texture object, if this surface is a child of a cube texture or texture object. Gets a description of this surface that is returned in a D3DSURFACE_DESC type. Gets a Direct3DDevice8 object that is associated with this surface. Gets the private data for this surface and copies it to a buffer. Locks a rectangular area of the surface so that it can be drawn to. Sets a reference from private data to this surface. Unlocks a specific rectangular area of the surface after it has been locked and drawn to.
GetContainer
GetDesc GetDevice GetPrivateData LockRect SetPrivateData UnlockRect
DIRECT3D
The Direct3DSurface8 Methods
8
126
DirectX Graphics Programming PART II
Private data is data managed by the user. It is referenced by a DXGUID type, which identifies where the data resides. Because this data is not managed by Direct3D, you are responsible for making sure it’s released after you are finished with it.
The Direct3DSwapChain8 Class A swap chain is a collection of back buffers assigned to a device. When the back buffers are flipped to the front buffer, the device checks for the next back buffer in the swap chain and brings it forward. A swap chain must have at least one back buffer, but can have as many as memory allows. There is always a minimum of one swap chain per device; however, more can be added by using the CreateAdditionalSwapChain method of the Direct3DDevice8 class. Table 8.8 shows the methods of the Direct3DSwapChain8 class. TABLE 8.8
The Direct3DSwapChain8 Methods
Method
Description
GetBackBuffer
Returns a surface object that represents a specified back buffer from the swap chain. Brings the next back buffer in the swap chain to a specified rectangular area on the screen. Basically, this routine shows the contents of the next back buffer to the user.
Present
The Direct3DTexture8 Class The Direct3DTexture class maintains the Direct3D textures. It’s responsible for creating rectangles on the texture, finding the surface level, and locking/unlocking rectangles on a texture. implements the following methods: FreePrivateData, GetDevice, GetType, and SetPrivateData. Descriptions of these methods can be found in the section on Direct3DResource8 methods earlier in this chapter. Direct3DTexture also implements the following methods: GetLOD, GetLevelCount, and SetLOD, which are described in the earlier section on Direct3DBaseTexture8 methods. Direct3DTexture
GetPriority, GetPrivateData, PreLoad, SetPriority,
Table 8.9 shows the methods of the Direct3DTexture8 class. TABLE 8.9
The Direct3DTexture8 Methods
Method
Description
AddDirtyRect
This method adds a specified dirty region to a DirectX3D texture. Gets a level description of a volume texture. The description comes to us through the D3DVOLUME_DESC type.
GetLevelDesc
Direct3D CHAPTER 8
TABLE 8.9
127
Continued
Method
Description
GetSurfaceLevel
Gets a specified surface level from a texture and assigns it to a Direct3DSurface object. Locks a predefined rectangle on a texture. Locks and unlocks are specified by supplying a level value. Unlocks a predefined rectangle on a texture.
LockRect UnlockRect
The Direct3DVertexBuffer8 Class The Direct3DVertexBuffer8 class is used to maintain the vertex buffers. It’s responsible for providing a description of the vertex buffer and locking/unlocking the buffer when necessary. Buffers cannot be used while they are unlocked for editing. Therefore, it’s important to remember to lock the buffer after you are finished editing it. also implements the following methods: FreePrivateData, and SetPrivateData. Descriptions of these methods can be found in the previous section on Direct3DResource8 methods.
Direct3DVertexBuffer8
GetDevice, GetType, GetPriority, GetPrivateData, PreLoad, SetPriority,
TABLE 8.10
The Direct3DVertexBuffer8 Methods
Method
Description
GetDesc
Gets a description of the vertex buffer and places it in a D3DVERTEX BUFFER_DESC type. Locks a specified range of vertex data and opens the vertex buffer for writing in that area. Unlocks all locks so that no more writing of data to the vertex buffer can occur.
Lock Unlock
The Direct3DVolume8 Class The Direct3DVolume8 class is used to maintain volume resources. A volume can be visualized as a stack of 2D surfaces, with each one having height and width. These surfaces are then layered one on top of the other to produce a third measurement: depth. This three-dimensional object is what’s called a volume.
DIRECT3D
Table 8.10 shows the methods of the Direct3DVertexBuffer8 class.
8
128
DirectX Graphics Programming PART II
Table 8.11 shows the methods of the Direct3DVolume8 class. TABLE 8.11
The Direct3DVolume8 Methods
Method
Description
FreePrivateData
Releases private data from a volume. Gets a pointer to a volume texture object if this volume texture is a child of another. This allows children to find their parent objects. Gets a D3DVOLUME_DESC type that describes this Direct3DVolume8 object. Gets the Direct3DDevice associated with this volume. Gets private data that is stored in a volume. Locks the volume for writing. Box is another name for volume. Sets the private data for a volume. This data is not destroyed by Direct3D when DirectX is set to nothing; therefore, you must remember to use the FreePrivateData method. Unlocks the volume for writing.
GetContainer GetDesc GetDevice GetPrivateData LockBox SetPrivateData
UnlockBox
The Direct3DVolumeTexture8 Class The Direct3DVolumeTexture8 class is used to maintain a volume texture, which is a texture resource designed to work with a volume (or box). Volume textures are 3D textures such as fog, smoke, and explosions. Unlike regular textures that have only height and width, a volume texture has depth as well. Table 8.12 shows the methods of the Direct3DVolumeTexture8 class. TABLE 8.12
The Direct3DVolumeTexture8 Methods
Method
Description
GetLevelDesc
Gets a D3DVOLUME_DESC type for the level specified. Locks the volume texture for writing. Unlocks the volume texture for writing. Adds a dirty region to this volume texture. Gets a Direct3DVolume8 object that is related to this Direct3DVolumeTexture8 object.
LockBox UnlockBox AddDirtyBox GetVolumeLevel
Direct3D CHAPTER 8
129
Creating 3D Applications To better understand how to work in a Direct3D environment, you need to understand how each part of the Direct3D engine works with the others. The purpose of this section is to discuss the intricate details involved in setting up Direct3D, creating vertices, manipulating vertices with matrices, setting up lights, applying textures to objects, and applying meshes.
Creating a Direct3D Application To create a basic 3D application, all you need to know will be discussed in the following sections. By adding the following components to your application, you can build a rudimentary Direct3D application. After you create this application, you can then work on adding more complex features, such as vertices, matrices, lights, and meshes. Figure 8.1 shows the steps involved in creating a Direct3D application.
Initializing the Objects
8
Rendering the Scene
Cleanup
FIGURE 8.1 Steps in creating a Direct3D application.
Initializing the Objects As with all DirectX applications, you must first declare the core DirectX classes. Then you can create new objects based on those classes. In this case, you need to create Direct3D objects, so
DIRECT3D
Environmental Setup
130
DirectX Graphics Programming PART II
your code reflects this. The following code shows the declaration of all your Direct3D variables: ‘’’ Dim Dim Dim
Create the variables to hold your DirectX objects oDX As New DirectX8 oD3D As Direct3D8 oD3DD As Direct3DDevice8
After you have created your variables, you need to initialize them with values. To do this, you will need to create a Direct3D object from the Direct3DCreate method of the DirectX8 class, as shown here: ‘’’ Create the Direct3D object by calling the DirectX ‘’’ Direct3DCreate method. Set oD3D = oDX.Direct3DCreate
Environment Setup After you have initialized all the variables, you need to tell DirectX about the environment. Included in this list are the screen resolution, the handle to use for drawing, and the color depth. Next you set the display mode for Direct3D by using the GetAdapterDisplayMode method of the Direct3D class. In the following code snippet, you’re using the primary display adapter (this is all you need unless you have multiple video cards). You also use a D3DDISPLAYMODE structure to hold information about your current display adapter. ‘’’ Set the display mode to the same mode that ‘’’ Windows is currently using. Dim oD3DM As D3DDISPLAYMODE oD3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, oD3DM
Next, you need to set up the Direct3D presentation parameters, which are used by the CreateDevice method of the Direct3D class to define how the device is set up. These parameters come from a structure called D3DPRESENT_PARAMETERS and include whether the animations are done in a window or full screen, the display mode format used for the back buffer, how many back buffers will be used, and many other optional parameters. Dim oD3DPP As D3DPRESENT_PARAMETERS With oD3DPP .Windowed = 1 ‘’’ Run in full screen (0) or window mode (1) .SwapEffect = D3DSWAPEFFECT_COPY_VSYNC .BackBufferFormat = oD3DM.Format ‘’’ What kind of video mode for ‘’’ the back buffer End With
Direct3D CHAPTER 8
131
There is only one more thing that needs to be done to complete the initialization of your Direct3D application: You have to create the device. In the past few paragraphs you have been concerned with declaring objects and assigning values to parameters. Now you can wrap all that information into a single call: CreateDevice. The CreateDevice method of Direct3D is responsible for taking the parameters you’ve defined and finalizing the creation of the Direct3D device. Then it assigns the device it has created to a Direct3D device object, which you declared earlier in this section. The following code snippet shows how to use the CreateDevice method: ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ Set
Create the Direct3D device by using the CreateDevice method of the Direct3D class. Note the picDisplay.hwnd parameter is a handle to a picture box on the main form of the application. This parameter simply denotes where the drawing will occur. oD3DD = oD3D.CreateDevice(D3DADAPTER_DEFAULT, _ ➥D3DDEVTYPE_HAL, picDisplay.hwnd, _ ➥D3DCREATE_HARDWARE_VERTEXPROCESSING, oD3DPP)
Second, in the previous example, you used the D3DCREATE_HARDWARE_VERTEXPROCESSING constant. This parameter in the CreateDevice method can be replaced with D3DCREATE_SOFTWARE_VERTEXPROCESSING if you want to process vertices by using the power of your operating system instead of the 3D graphics card. This alternative could be helpful if your video card has a hard time processing images.
Rendering the Scene To render the scene to the device you made earlier, you can use the Clear, BeginScene, EndScene, and Present methods of the Direct3D device. The Clear method is used to clear the device before it is drawn to and should be called every time a frame of animation is created for display. During the rendering process, the BeginScene and EndScene methods surround the code that renders to the screen. All rendering of scene objects must occur between the BeginScene and EndScene methods. After the scene is assembled, the Direct3D device then calls the Present method, which takes the back buffer scene and puts it on the screen. The Present method also enables you to specify a source rectangle, a destination rectangle, a new window’s handle, and a dirty region. In the following example, you set these values to 0 because you want to use the defaults.
8 DIRECT3D
There are a few things to note in the previous piece of code. The first is the use of the D3DDEVTYPE_HAL constant. D3DDEVTYPE_HAL tells Direct3D to create a device that uses the Hardware Abstraction Layer for processing. This is, of course, great for most recent 3D cards; however, if you have a card that might not handle 3D graphics well, you should try replacing this constant with the constant D3DDEVTYPE_REF. D3DDEVTYPE_REF tells the CreateDevice method to use software emulation for rendering.
132
DirectX Graphics Programming PART II
This code snippet shows an example of using the Clear, BeginScene, EndScene, and Present methods of the Direct3DDevice class: ‘’’ Work through the Direct3DDevice object With oD3DD ‘’’ Clear the back buffer with blue (&HFF&) as the background color .Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 ‘’’ Begin creating the scene .BeginScene ‘’’ All rendering code goes here. ‘’’ Finish up the creation of the scene .EndScene ‘’’ Copy the entire back buffer contents on the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With
NOTE Notice that some of the parameters you use in Direct3D require a ByVal declaration with the value you are using. This is necessary because these parameters have been declared as type Any. This has become a serious stumbling block for VB .NET programmers who want to use Direct3D; however, by simply using the ByVal declaration with these values, Visual Basic 6 programmers are able to use these methods.
Cleanup One of the most overlooked tasks in DirectX programming is the proper disposal of DirectX objects. In most cases, when your application ends processing, it destroys all leftover objects. However, that doesn’t always happen, so you must remember to destroy all DirectX objects when you are finished with them. This process should occur just before the application is completely unloaded, and destroying your objects in the reverse of the order in which they were created is a good idea. Destroying objects in the reverse order of creating them causes VB to destroy subcomponents before destroying their parent components. This makes it easier for VB to clean up memory and produces fewer errors. In the following code snippet, you’re destroying all the objects you have been working with: ‘’’ Destroy all the objects you used. Set oD3DD = Nothing Set oD3D = Nothing
Direct3D CHAPTER 8
133
Working with Vertices When you’re putting together an environment and creating a polygon on the screen, you must use vertices to represent the polygon and position it onscreen. Working with vertices is a simple extension of creating a Direct3D environment. Figure 8.2 shows the steps involved in creating a Direct3D vertex application. The highlighted box in the figure represents a change from the previous example.
Initializing the Objects
Environmental Setup
Creating the Vertices
Cleanup
FIGURE 8.2 Steps in creating a vertex application.
Initializing the Objects To start with, you have to declare your old friends: DirectX8, Direct3D8, and Direct3D Device8. In addition to those basic classes, you’ll need a Direct3DVertexBuffer8 class, which is used to define the vertex of the object you are trying to create. To make things easier and more readable, you can create structures for common tasks. In the following example, you create a type called MYCUSTOMVERTEX to define a vertex’s parameters, such as x, y, and z coordinates and its color. By using this type, you can simplify your code.
DIRECT3D
Rendering the Scene
8
134
DirectX Graphics Programming PART II ‘’’ Dim Dim Dim Dim
Create your variables oDX As New DirectX8 oD3D As Direct3D8 oD3DD As Direct3DDevice8 oD3DVB As Direct3DVertexBuffer8
‘’’ ‘’’ ‘’’ ‘’’
Core DirectX object Direct 3D object Rendering device Vertex buffer
‘’’ You will need this structure for all your vertices ‘’’ This helps make the code simpler to understand and write. Private Type MYCUSTOMVERTEX x As Single ‘’’ y As Single ‘’’ z As Single ‘’’ rhw As Single ‘’’ color As Long ‘’’ End Type
x-coordinate y-coordinate z-coordinate Normalized z rhw Vertex color
Environment Setup The environment for a vertex buffer is no different from the default Direct3D setup. The following code example shows how to set up the environment for rendering. For an explanation of all these methods and objects, see “Environment Setup” under the “Creating a Direct3D Application” section earlier in this chapter. ‘’’ Set the display mode to the same mode that ‘’’ Windows is currently using. Dim g_DisplayMode As D3DDISPLAYMODE oD3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, g_DisplayMode Dim oD3DPP As D3DPRESENT_PARAMETERS With oD3DPP .Windowed = 1 ‘’’ Can be run in full screen (0) or window mode (1) .SwapEffect = D3DSWAPEFFECT_COPY_VSYNC .BackBufferFormat = g_DisplayMode.Format ‘’’ What kind of video mode for ‘’’ the back buffer End With ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ Set
Create the Direct3D device by using the CreateDevice method of the Direct3D class. Note the picDisplay.hwnd parameter is a handle to a picture box on the main form of the application. This parameter simply denotes where the drawing will occur. oD3DD = oD3D.CreateDevice(D3DADAPTER_DEFAULT, _ ➥D3DDEVTYPE_HAL, picDisplay.hwnd, _ ➥D3DCREATE_HARDWARE_VERTEXPROCESSING, oD3DPP)
Direct3D CHAPTER 8
135
Creating the Vertices Before you can render the polygons to the screen, you must first define where they are and their attributes. Creating an array of type MYCUSTOMVERTEX does this. It quickly produces an array of vertices, with each element of the array containing its own parameters for x, y, z and color requirements. The following code shows this process: ‘’’ Create an array of vertices from your MYCUSTOMVERTEX type Dim Vertices(2) As MYCUSTOMVERTEX ‘’’ Create a variable to hold how many bytes are in the vertices Dim lVertexBytes As Long lVertexBytes = Len(Vertices(0)) ‘’’ Define vertex #1 With Vertices(0) .x = 150 .y = 50 .z = 0.5 .rhw = 1 .color = &HFFFF0000 ‘’’ Red End With
‘’’ Define vertex #3 With Vertices(2) .x = 50 .y = 250 .z = 0.5 .rhw = 1 .color = &HFFFF0000 ‘’’ Red End With
After you have defined where each vertex is supposed to go and what color is assigned to each vertex, you need to create the vertex buffer. Creating a vertex buffer can be done by using the CreateVertexBuffer method of the Direct3DDevice class. CreateVertexBuffer needs to have the size of the three vertices you are adding to the vertex buffer. It must also have the flags telling it what kind of custom vertex is being created. To do that, you use the D3DFVF_XYZRHW
DIRECT3D
‘’’ Define vertex #2 With Vertices(1) .x = 250 .y = 250 .z = 0.5 .rhw = 1 .color = &HFFFF0000 ‘’’ Red End With
8
136
DirectX Graphics Programming PART II
and D3DFVF_DIFFUSE constants. Finally, you specify what kind of memory pool will be used to create the vertex buffers. In the sample, you are using the D3DPOOL_DEFAULT, which is the default pool of memory. The following code snippet details how this is done: ‘’’ Create the vertex buffer Set oD3DVB = oD3DD.CreateVertexBuffer(lVertexBytes * 3, 0, _ ➥D3DFVF_XYZRHW Or D3DFVF_DIFFUSE, _ ➥D3DPOOL_DEFAULT)
The next process involves copying the vertex information into the vertex buffer. To do this, you must first unlock the vertex buffer, write your information to it, and then lock it again. This can all be accomplished by one call to the D3DVertexBuffer8SetData function. To use this function, you need to specify the vertex you need to open, where in the vertex to begin writing, the size (in bytes) of the vertices you are copying, any special flags, and the actual data in the array of vertices you created earlier. The following code shows how this is done: ‘’’ Open, copy the data to the vertex buffer, and then lock it. D3DVertexBuffer8SetData oD3DVB, 0, lVertexBytes * 3, 0, Vertices(0)
Rendering the Scene Rendering the vertices is very similar to the basics discussed in the previous “Rendering the Scene” section under “Creating a Direct3D Application.” In addition to the Clear, BeginScene, EndScene, and Present methods of the Direct3DDevice class, you must use the SetStream Source, SetVertexShader, and DrawPrimitive methods. The SetStreamSource method is used to bind the vertex buffer you created earlier to a device data stream for processing, and SetVertexShader sets the vertex shader to your custom vertex shader. DrawPrimitive is the final method you’ll be using to render the vertices. It creates a primitive drawing based on the vertices supplied in the data stream. In this case, you are using the D3DPT_TRIANGLELIST constant to specify that every three vertices in the stream represent a triangle. ‘’’ Declare some variables you need. Dim vVertexDefinition As MYCUSTOMVERTEX ‘’’ Work through the Direct3DDevice object With oD3DD ‘’’ Clear the back buffer with blue (&HFF&) as the background color .Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 ‘’’ Begin creating the scene .BeginScene ‘’’ All rendering code goes here. .SetStreamSource 0, g_VB, Len(vVertexDefinition) .SetVertexShader D3DFVF_CUSTOMVERTEX .DrawPrimitive D3DPT_TRIANGLELIST, 0, 1
Direct3D CHAPTER 8
137
‘’’ Finish up the creation of the scene .EndScene ‘’’ Copy the entire back buffer contents on the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With
Working with Matrices Now that you know how to create a Direct3D environment and use vertices to draw in that environment, it’s time to learn about matrices. As described in Chapter 7, “3D Geometry,” matrices are mathematical grids that are used to move, rotate, and scale 3D objects. You can also use matrices to rotate or position a camera so that you can control what the user sees. The example you’re going to work on details how this is done. Figure 8.3 shows the steps to create a Direct3D application with matrices. The highlighted box in the figure represents a change from the previous example.
Initializing the Objects
Creating the Matrices
Rendering the Scene
Cleanup
FIGURE 8.3 Steps in creating a matrix application.
DIRECT3D
Environmental Setup
8
138
DirectX Graphics Programming PART II
Initializing the Objects On top of the standard declarations for DirectX8, Direct3D8, and Direct3DDevice8, you also have to declare a vertex buffer. The Direct3DVertexBuffer8 class is used to define the vertex of the object you are trying to create. To make things easier and more readable, you can create structures for common tasks. In this example, you’re creating a type called MYCUSTOMVERTEX to define a vertex’s parameters, such as x, y, and z coordinates and its color. This simplifies your code. You also use a constant to represent pi (3.1415) in your code. ‘’’ Dim Dim Dim Dim
Create your variables oDX As New DirectX8 oD3D As Direct3D8 oD3DD As Direct3DDevice8 oD3DVB As Direct3DVertexBuffer8
‘’’ ‘’’ ‘’’ ‘’’
Core DirectX object Direct 3D object Rendering device Vertex buffer
‘’’ You will need this structure for all your vertices ‘’’ This helps make the code simpler to understand and write. Private Type MYCUSTOMVERTEX x As Single ‘’’ y As Single ‘’’ z As Single ‘’’ rhw As Single ‘’’ color As Long ‘’’ End Type
X-coordinate Y-coordinate Z-coordinate Normalized z rhw Vertex color
Const PI = 3.1415 ‘’’ Created to estimate pi
Environment Setup The environment for a matrix is the same as a vertex buffer and, therefore, no different from the default Direct3D setup. The following code shows how to set up the environment for rendering. For an explanation of all these methods and objects, see the “Environment Setup” subsection of the “Creating a Direct3D Application” section earlier in this chapter. ‘’’ Set the display mode to the same mode that ‘’’ Windows is currently using. Dim g_DisplayMode As D3DDISPLAYMODE oD3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, g_DisplayMode Dim oD3DPP As D3DPRESENT_PARAMETERS With oD3DPP .Windowed = 1 ‘’’ Can be run in full screen (0) or window mode (1) .SwapEffect = D3DSWAPEFFECT_COPY_VSYNC .BackBufferFormat = g_DisplayMode.Format ‘’’ What kind of video mode for ‘’’ the back buffer
Direct3D CHAPTER 8
139
.BackBufferCount = 1 .EnableAutoDepthStencil = 1 .AutoDepthStencilFormat = D3DFMT_D16 End With ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ Set
Create the Direct3D device by using the CreateDevice method of the Direct3D class. Note the picDisplay.hwnd parameter is a handle to a picture box on the main form of the application. This parameter simply denotes where the drawing will occur. oD3DD = oD3D.CreateDevice(D3DADAPTER_DEFAULT, _ ➥D3DDEVTYPE_HAL, picDisplay.hwnd, _ ➥D3DCREATE_HARDWARE_VERTEXPROCESSING, oD3DPP)
‘’’ Set up the device state ‘’’ Turn off culling oD3DD.SetRenderState D3DRS_CULLMODE, D3DCULL_NONE ‘’’ Turn off Direct3D lighting oD3DD.SetRenderState D3DRS_LIGHTING, 0
Creating the Matrices To work with matrices, first you need to have an understanding of them. You’ll be working with three matrices: transform, view, and projection. The transform matrix works with the world view and is responsible for positioning, scaling, or rotating the object in the world view. For this example, you’ll just be rotating the object. Then you’ll use the view matrix to position the camera in relationship to the objects you are drawing. Finally, you’ll use the projection matrix to set up your camera’s lens. (For more information about matrices, see Chapter 7.) The following code shows how you would use three different matrices to set up the scene to render. All of this code is encapsulated into a subroutine called CreateMatrices. ‘***************************************************************************** ‘ Name: CreateMatrices ‘ ‘ Purpose: Sets up the world matrix, view matrix, and projection matrix ‘ for your scene. ‘ ‘*****************************************************************************
8 DIRECT3D
You will notice that a few lines were added at the end of this sample code that were not in the “Working with Vertices” example. These lines use the SetRenderState method of the Direct3DDevice8 class. SetRenderState is used to set up the parameters that guide how the image will be displayed on the device. The parameters that can be modified include many of the advanced features of a 3D video card, such as culling, lighting, alpha blending, and fog.
140
DirectX Graphics Programming PART II Sub CreateMatrices() ‘’’ Rotate around the y axis by using the D3DXMatrixRotationY method ‘’’ Create the World Matrix Dim oWorldMatrix As D3DMATRIX D3DXMatrixRotationY oWorldMatrix, Timer * 4 ‘’’ Apply the matrix oD3DD.SetTransform D3DTS_WORLD, oWorldMatrix ‘’’ Define where the camera will be and where it is pointing. ‘’’ The first parameter is the view matrix. ‘’’ The second is the eye point. This is where the camera is placed in ‘’’ relation to the object ‘’’ The third is the point you want to look at. ‘’’ The fourth is the direction that is up (x, y, or z). ‘’’ In this case, you are setting up the camera to move 10 units back ‘’’ in the z axis. Y has also been set as the up reference. Dim oViewMatrix As D3DMATRIX D3DXMatrixLookAtLH oViewMatrix, GetVector(0#, 0#, -10#), _ GetVector(0#, 0#, 0#), _ GetVector(0#, 1#, 0#) ‘’’ Apply the matrix oD3DD.SetTransform D3DTS_VIEW, oViewMatrix ‘’’ Set up the projection matrix ‘’’ The first parameter is the matrix that is being modified. ‘’’ The second parameter is the field of view. ‘’’ The third parameter is the aspect ratio. ‘’’ The fourth parameter is the Z value of the near view pane. ‘’’ The fifth parameter is the Z value of the far view pane. Dim oProjectionMatrix As D3DMATRIX D3DXMatrixPerspectiveFovLH oProjectionMatrix, (PI / 4), 1, 1, 1000 ‘’’ Apply the matrix oD3DD.SetTransform D3DTS_PROJECTION, oProjectionMatrix End Sub
Notice that you’re using a function called GetVector to create vectors for the function. The GetVector custom function simplifies the task of creating a vector. It’s a good idea to create custom functions for tasks that are repeated frequently in your code. You could even bundle them up into a module or class and include them with all your DirectX projects. The GetVector function looks like this: D3DXMatrixLookAtLH
Direct3D CHAPTER 8
141
‘----------------------------------------------------------------------------‘ Name: GetVector ‘ Desc: Populates a D3DVector type with values supplied. ‘ Return Value: D3DVector ‘----------------------------------------------------------------------------Function GetVector(x As Single, y As Single, z As Single) As D3DVECTOR GetVector.x = x GetVector.y = y GetVector.z = z End Function
Rendering the Scene
‘’’ Declare some variables you need. Dim vVertexDefinition As MYCUSTOMVERTEX ‘’’ Work through the Direct3DDevice object With oD3DD ‘’’ Clear the back buffer with blue (&HFF&) as the background color .Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 ‘’’ Begin creating the scene .BeginScene ‘’’ Set up the world, view, and projection matrices CreateMatrices ‘’’ All rendering code goes here. .SetStreamSource 0, g_VB, Len(vVertexDefinition)
8 DIRECT3D
Rendering with matrices is the same as rendering vertices, except for one difference: The matrices are implemented to rotate, resize, and position the camera in relation to the scene through your CreateMatrices function. CreateMatrices is used to rotate, resize, and position the camera in relation to your objects in 3D space. In addition to the Clear, BeginScene, EndScene, and Present methods of the Direct3DDevice8 class, you must use the SetStreamSource, SetVertexShader, and DrawPrimitive methods. The SetStreamSource method is used to bind the vertex buffer you created earlier to a device data stream for processing, and SetVertexShader sets the vertex shader to your custom vertex shader. DrawPrimitive creates a primitive drawing based on the vertices supplied in the data stream. In this case, you’re using the D3DPT_TRIANGLELIST constant to specify that every three vertices in the stream represent a triangle. In addition to these methods, you also implement a custom subroutine: CreateMatrices.
142
DirectX Graphics Programming PART II .SetVertexShader D3DFVF_CUSTOMVERTEX .DrawPrimitive D3DPT_TRIANGLELIST, 0, 1 ‘’’ Finish up the creation of the scene .EndScene ‘’’ Copy the entire back buffer contents on the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With
Working with Lights So you’ve made your 3D application. The triangles are spinning, and the camera is in position, but something’s missing. Oh, yeah—lights. You need lights to accentuate portions of your objects and to change their look and feel. They also work with materials to define how the light reacts when it bounces off the object and hits the camera. The example you are going to work on explains how this is done. Figure 8.4 shows the steps involved in creating a Direct3D application with lights. The highlighted box in the figure represents a change from the previous example.
Initializing the Objects
Environmental Setup
Creating the Lights
Rendering the Scene
Cleanup
FIGURE 8.4 Steps in creating an application with lights.
Direct3D CHAPTER 8
143
Initializing the Objects The standard declarations for DirectX8, Direct3D8, Direct3DDevice8, and are implemented as usual. To make things easier and more readable, you’ll create a type called MYVERTEX to define a vertex’s two vectors: Position and Normal. By using this type, you can simplify your code. A constant is used to represent pi.
Direct3DVertexBuffer8
‘’’ Dim Dim Dim Dim
Create your variables oDX As New DirectX8 oD3D As Direct3D8 oD3DD As Direct3DDevice8 oD3DVB As Direct3DVertexBuffer8
‘’’ ‘’’ ‘’’ ‘’’
Core DirectX object Direct 3D object Rendering device Vertex buffer
‘’’ You will need this structure for all your vertices ‘’’ This helps make the code simpler to understand ‘’’ and write. Private Type MYVERTEX Position As D3DVECTOR ‘’’ 3D position for vertex Normal As D3DVECTOR ‘’’ Surface normal for vertex End Type
8
Const PI = 3.1415 ‘’’ Created to estimate pi
The environment for lights is the same as the previous environments you’ve set up in this chapter. The following code shows how to set up the environment for rendering. For an explanation of all these methods and objects, see the “Environment Setup” section under “Creating a Direct3D Application” earlier in this chapter. ‘’’ Set the display mode to the same mode that ‘’’ Windows is currently using. Dim g_DisplayMode As D3DDISPLAYMODE oD3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, g_DisplayMode Dim oD3DPP As D3DPRESENT_PARAMETERS With oD3DPP .Windowed = 1 ‘’’ Can be run in full screen (0) or window mode (1) .SwapEffect = D3DSWAPEFFECT_COPY_VSYNC .BackBufferFormat = g_DisplayMode.Format ‘’’ What kind of video mode for ‘’’ the back buffer .BackBufferCount = 1 .EnableAutoDepthStencil = 1 .AutoDepthStencilFormat = D3DFMT_D16 End With
DIRECT3D
Environment Setup
144
DirectX Graphics Programming PART II ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ Set
Create the Direct3D device by using the CreateDevice method of the Direct3D class. Note the picDisplay.hwnd parameter is a handle to a picture box on the main form of the application. This parameter simply denotes where the drawing will occur. oD3DD = oD3D.CreateDevice(D3DADAPTER_DEFAULT, _ ➥D3DDEVTYPE_HAL, picDisplay.hwnd, _ ➥D3DCREATE_HARDWARE_VERTEXPROCESSING, oD3DPP)
‘’’ Set up the device state ‘’’ Turn off culling oD3DD.SetRenderState D3DRS_CULLMODE, D3DCULL_NONE ‘’’ Turn on Direct3D lighting oD3DD.SetRenderState D3DRS_LIGHTING, 1
This code uses the SetRenderState method that was used in the “Working with Matrices” example. This method of the Direct3DDevice8 class is used to set up the parameters that guide how the image will be displayed on the device. These parameters include many of the advanced features of a 3D video card, such as culling, lighting, alpha blending, and fog. Also, the D3DRS_LIGHTING value has been set to 1, which turns on lighting for this device.
Creating the Lights Lights can be used to create focus on objects as well as add ambience to a scene. This example sets up a directional light that will shine on your object. You can define the light’s color and direction. Be warned that lights take up a lot of processing power on your 3D video card. Therefore, it is wise to use them sparingly. (For more information about lights, see Chapter 7.) The following code shows how you would use materials and lights to illuminate a scene. All of this code is encapsulated into a subroutine called CreateLights. ‘’’************************************************************************** ‘’’ Name: CreateLights ‘’’ ‘’’ Purpose: Sets up the material light settings and the spot lights that ‘’’ will shine on the objects. ‘’’ ‘’’************************************************************************** Sub CreateLights() ‘’’ Create a variable to hold the data on the color. Dim oD3DCV As D3DCOLORVALUE ‘’’ Create a material with settings for diffuse and ambient light Dim oD3DM As D3DMATERIAL8
Direct3D CHAPTER 8
145
‘’’ Define the Red, Green, and Blue values of your color value ‘’’ Color values can only be between 0 and 1. With oD3DCV .r = 1 .g = 1 .b = 0 .a = 1 End With ‘’’ Assign these color values to the diffuse and ambient settings ‘’’ of the Direct3D material. With oD3DM .diffuse = oD3DCV .Ambient = oD3DCV End With ‘’’ Assign the material to the Direct3D Device object. oD3DD.SetMaterial oD3DM
oD3DD.SetLight 0, oD3DL
‘’’ Associate the new light with this Direct3D ‘’’ device. oD3DD.LightEnable 0, 1 ‘’’ Turn on the light oD3DD.SetRenderState D3DRS_LIGHTING, 1 ‘’’ Turn on light rendering ‘ Finally, turn on some ambient light. ‘ Ambient light is light that scatters and lights all objects evenly oD3DD.SetRenderState D3DRS_AMBIENT, &H202020 End Sub
Rendering the Scene In this lights example, you modify the Render subroutine by adding a CreateLights subroutine, which defines and positions the light sources for the scene. In addition to the Clear,
8 DIRECT3D
‘’’ Set up a white, directional light, with range of 1000 units. Dim oD3DL As D3DLIGHT8 With oD3DL .Type = D3DLIGHT_DIRECTIONAL .diffuse.r = 1# .diffuse.g = 1# .diffuse.b = 1# .Direction.x = 1# .Direction.y = 1# .Direction.z = 1# .Range = 1000# End With
146
DirectX Graphics Programming PART II BeginScene, EndScene,
and Present methods of the Direct3DDevice8 class, you use the SetStreamSource, SetVertexShader, and DrawPrimitive methods (explained in the previous “Rendering the Scene” sections). In addition to all the above, you also implement a custom subroutine: CreateLights.
‘’’ Declare some variables you need. Dim vVertexDefinition As MYCUSTOMVERTEX ‘’’ Work through the Direct3DDevice object With oD3DD ‘’’ Clear the back buffer with blue (&HFF&) as the background color .Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 ‘’’ Begin creating the scene .BeginScene ‘’’ Reset the light during the render process. CreateLights ‘’’ Set up the world, view, and projection matrices CreateMatrices ‘’’ All rendering code goes here. .SetStreamSource 0, g_VB, Len(vVertexDefinition) .SetVertexShader D3DFVF_CUSTOMVERTEX .DrawPrimitive D3DPT_TRIANGLELIST, 0, 1 ‘’’ Finish up the creation of the scene .EndScene ‘’’ Copy the entire back buffer contents on the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With
Working with Textures By applying textures, you can make a barrel look like a an actual wooden barrel instead of just a cylinder. Simply wrapping an object with a bitmap gives you an easy level of detail. The example in this section shows you how to take an object and apply a texture to it. Figure 8.5 shows the steps to create a Direct3D application with textures. The highlighted box in the figure represents a change from the previous example.
Direct3D CHAPTER 8
147
Initializing the Objects
Loading the Texture
Environmental Setup
Rendering the Scene
8 Cleanup
DIRECT3D
FIGURE 8.5 Steps in creating an application with textures.
Initializing the Objects The standard declarations for DirectX8, Direct3D8, Direct3DDevice8, and are implemented as usual. Again, you’ll create a structure to make things easier and more readable. In this example, you create a type called MYVERTEX to define a vertex’s vector, color, and two map coordinates. By using this type, you can simplify your code. Again, a constant is used to represent pi.
Direct3DVertexBuffer8
‘’’ Dim Dim Dim Dim Dim
Create your variables oDX As New DirectX8 oD3D As Direct3D8 oD3DD As Direct3DDevice8 oD3DVB As Direct3DVertexBuffer8 oD3DT As Direct3DTexture8
‘’’ ‘’’ ‘’’ ‘’’ ‘’’
Core DirectX object Direct 3D object Rendering device Vertex buffer Texture
‘’’ You will need this structure for all your vertices ‘’’ This helps make the code simpler to understand and write. Private Type MYVERTEX
148
DirectX Graphics Programming PART II Position As D3DVECTOR ‘’’ 3D vector for vertex Color As Long ‘’’ Vertex color TU as Single ‘’’ Texture map coordinate TV as Single ‘’’ Texture map coordinate End Type Const PI = 3.1415 ‘’’ Created to estimate pi
Loading the Texture To work with a texture, you must first load it into the Direct3DTexture object you created earlier. This is done by calling the Direct3D method CreateTextureFromFile. This method needs to know the Direct3DDevice being used for this texture as well as the path to the texture. The following code shows how this method is used in a project: ‘’’ Create a texture by loading a local bitmap and specifying the device. Set oD3DT = oD3D.CreateTextureFromFile(oD3DD, App.Path + “\OakTexture.bmp”)
Environment Setup The environment for a texture is no different from the default Direct3D setup. The only new code that needs to be added is a SetRenderState method call that enables the Z buffer, shown in the following code snippet. For a complete listing of the environment setup, see the “Environment Setup” subsection of the “Creating a Matrix” section earlier in this chapter. ‘’’ Turn on the Z buffer oD3DD.SetRenderState D3DRS_ZENABLE, 1
Rendering the Scene For this texture example, you’ll modify the Render subroutine by adding a few new methods of the Direct3DDevice8 class. The first is SetTexture, designed to assign a texture object to a stage within the Direct3DDevice8 object. A stage is a holding place for a texture. There are a maximum of eight stages (numbered 0 to 7) for each device. SetTextureStageState, the other method used in rendering a texture application, sets the states of the texture stages. In this example, you’re using only one texture with a stage value of 0. Therefore, all the SetTexture StateState methods use 0 as their first parameter. The second parameter is the stage state, which defines how the texture will be used and which abilities of the 3D video card specific to textures are to be used. The third parameter is the value to set the stage state to. In the following code, you are using DirectX constants to provide the values. ‘’’ Declare some variables you need. Dim vVertexDefinition As MYCUSTOMVERTEX ‘’’ Work through the Direct3DDevice object With oD3DD
Direct3D CHAPTER 8
149
‘’’ Clear the back buffer with blue(&HFF&) as the background color .Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 ‘’’ Begin creating the scene .BeginScene ‘’’ Using the texture stage states, you need to blend the texture ‘’’ with the diffuse color of the vertices. .SetTexture 0, oD3DT .SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_MODULATE .SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE .SetTextureStageState 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE .SetTextureStageState 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ‘’’ Set up the world, view, and projection matrices CreateMatrices ‘’’ All rendering code goes here. .SetStreamSource 0, g_VB, Len(vVertexDefinition) .SetVertexShader D3DFVF_CUSTOMVERTEX .DrawPrimitive D3DPT_TRIANGLELIST, 0, 1
‘’’ Copy the entire back buffer contents on the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With
Working with Meshes Meshes are 3D objects made up of complex calculations. These objects can represent animals, people, machinery, or any other complex entity. For example, you could have a database of machine parts; a user could open your client application, have it query the database, and return a complex 3D representation of the machine part. The user can then move the part around to see all sides and even change its color if your application enables that feature. Figure 8.6 shows the steps involved in creating a Direct3D application with meshes. The highlighted box in the figure represents a change from the previous example.
Initializing the Objects The standard declarations for DirectX8, Direct3D8, and Direct3DDevice8 are implemented as usual. You must also declare a D3DX8, Direct3DXMesh, D3DMATERIAL8, and Direct3dTexture8 object.
DIRECT3D
‘’’ Finish up the creation of the scene .EndScene
8
150
DirectX Graphics Programming PART II ‘’’ Dim Dim Dim Dim Dim Dim Dim Dim
Create your variables oDX As New DirectX8 oD3DX As New D3DX8 oD3D As Direct3D8 oD3DD As Direct3DDevice8 oD3DVB As Direct3DVertexBuffer8 oD3DT As Direct3DTexture8 oD3DM As D3DMATERIAL8 oD3DMesh As D3DXMesh
‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’
Core DirectX object Helper functions Direct 3D object Rendering device Vertex buffer Texture Material Mesh object
Const PI = 3.1415 ‘’’ Created to estimate pi
Initializing the Objects
Loading the Mesh
Environmental Setup
Rendering the Scene
Cleanup
FIGURE 8.6 Steps in creating an application with meshes.
Loading the Mesh To work with a mesh, you must first load it into the D3DXMesh object you created earlier by calling the Direct3D method LoadMeshFromX. LoadMeshFromX needs to know the Direct3DDevice being used for this mesh as well as the path to the X file and where the memory is coming from to manage this mesh. An X file is a DirectX-specific format that defines
Direct3D CHAPTER 8
151
instructions on how to rebuild an object. X files can be created from most of today’s 3D modeling programs, such as trueSpace or Lightwave. You must also determine how many materials are in the X file that you load. You then cycle through all the subsets of the X file, pull out each texture’s name and a copy of the material, and load the actual texture from disk. The following code shows how this process works: ‘’’ Load the “male” mesh from an X file called “male.x” Set oD3DMesh = oD3D.LoadMeshFromX(App.Path + “\male.x”, D3DXMESH_MANAGED, _ oD3DD, Nothing, oMatBuffer, lNumMaterials) ‘’’ Then you need to allocate space for your materials and textures ReDim oD3DT(lNumMaterials - 1) ReDim oD3DM(lNumMaterials - 1) Dim iCount As Integer Dim sTextureName As String ‘’’ You need to extract the material properties and texture names ‘’’ from the Material Buffer (oMatBuffer) For iCount = 0 To lNumMaterials - 1 ‘’’ Copy the material oD3DX.BufferGetMaterial oMatBuffer, iCount, oD3DM(iCount)
Next Set oMatBuffer = Nothing
Environment Setup The environment for a mesh is the same as the previous environments you’ve set up in this chapter. The only new code that needs to be added is a SetRenderState method call that enables the Z buffer, shown in the following code snippet. For a complete listing of the environment setup, see the “Environment Setup” subsection of the “Creating a Matrix” section earlier in this chapter. ‘’’ Turn on the Z buffer oD3DD.SetRenderState D3DRS_ZENABLE, 1
DIRECT3D
‘’’ Create the texture sTextureName = oD3DX.BufferGetTextureName(oMatBuffer, iCount) If sTextureName “” Then Set oD3DT(iCount) = oD3DX.CreateTextureFromFile(oD3DD, App.Path + “\” + sTextureName) End If
8
152
DirectX Graphics Programming PART II
Rendering the Scene Because meshes can be divided into subsets, you must use a loop to go through all the subsets of your mesh and place the correct material with the correct subset. For this loop you use the SetMaterial and SetTexture methods of Direct3DDevice8 to set each subset’s materials and textures. Then you use the DrawSubset method of the D3DXMesh type to draw the current subset. Basically, what you do is work on one subset of the mesh at a time, making sure you set the material and texture before you render that subset. The following code shows how this is used in a project: ‘’’ Declare some variables you need. Dim vVertexDefinition As MYCUSTOMVERTEX Dim iCount As Integer ‘’’ Work through your Direct3DDevice object With oD3DD ‘’’ Clear the back buffer with blue (&HFF&) as the background color .Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 ‘’’ Begin creating the scene .BeginScene ‘ Meshes are divided into subsets, one for each material. ‘ Render them in a loop For iCount = 0 To lNumMaterials - 1 .SetMaterial oD3DM(iCount) ‘’’ Set the material .SetTexture 0, oD3DT(iCount) ‘’’ Set the texture ‘’’ Draw this mesh subset oD3DMesh.DrawSubset iCount Next ‘’’ Set up the world, view, and projection matrices CreateMatrices ‘’’ All rendering code goes here. .SetStreamSource 0, g_VB, Len(vVertexDefinition) .SetVertexShader D3DFVF_CUSTOMVERTEX .DrawPrimitive D3DPT_TRIANGLELIST, 0, 1 ‘’’ Finish up the creation of the scene .EndScene
Direct3D CHAPTER 8
153
‘’’ Copy the entire back buffer contents on the screen .Present ByVal 0, ByVal 0, 0, ByVal 0 End With
Summary This chapter takes an in-depth look at the Direct3D classes. You learned that the Direct3D8 class is the base class that provides much of the framework for the rest of Direct3D functionality. You also learned about textures and how they are supported by the Direct3DTexture8, Direct3DBaseTexture8, Direct3DCubeTexture8, and Direct3DVolumeTexture8 classes. This chapter has also shown you how to manage devices with the Direct3DDevice8 class, Direct3D resources with the Direct3DResource8 class, Direct3D animation with the Direct3DSwapChain8 class,, vertex buffers with the Direct3DVertexBuffer8 class, and index buffers with the Direct3DIndexBuffer8 class. You learned how to set up a Direct3D program by implementing the Direct3D objects and how to set up the environment to handle the Direct3D objects. Then you learned how to render the Direct3D scene and destroy DirectX objects to keep your application Windows friendly. You also learned how to program vertices, matrices, lights, textures, and meshes.
8
In the next chapter, you will learn about advanced Direct3D graphics programming techniques. DIRECT3D
CHAPTER
Using Direct3D
9
IN THIS CHAPTER • 2D Graphics with Direct3D
156
• Creating a Billboard Application • Summary
173
163
156
DirectX Graphics Programming PART II
In this chapter, you’ll take what you have learned in Chapter 8, “Direct3D,” about the basics of Direct3D and actually use it to create two types of applications. The first example will use Direct3D to simulate a 2D environment, which enables you to use the DirectX 8 type library to create fast 2D graphics with today’s accelerated graphics cards. The second example shows you how to create billboards with Direct3D. This example builds on your knowledge of the Direct3D architecture and concepts.
2D Graphics with Direct3D The main reason you would want to create 2D graphics in DirectX is that not every situation needs 3D graphics. Some applications simply need the old standby of a sprite floating over a background. For example, you can create a great-looking CD player using 2D graphics created in a nice graphics program like Photoshop. There’s no need to create it in a CGI application, and then shade and color it in Direct3D. DirectDraw is dated technology that will eventually be eliminated, so that’s why you need to learn to create 2D graphics applications in Direct3D instead of DirectDraw. Direct3D is the technology of the future and will be around for awhile, so keep this in mind when you are creating your applications. The application you will be examining is called Beeze, a simple application that uses Direct3D to place a background of a hive on the screen. On the hive is a sprite of a bee that can be moved around by the mouse. Although the example is relatively simple, it illustrates the major concepts of creating 2D graphics in Direct3D.
Declaring the Objects To begin working with this application, you need to start by declaring all the objects you will need to complete the application. You will notice in Listing 9.1 that you start by declaring the core DirectX objects: DirectX8, Direct3D8, Direct3DDevice8, D3DX8, and Direct3DTexture8. We also create a custom vertex type that will help later with creating vertices for our background and our bee. The background and bee are each made up of four custom vertices that define the four coordinates that make up the screen and the rectangle for the bee. LISTING 9.1 Dim Dim Dim Dim Dim Dim Dim
Declaring the DirectX Objects for the Beeze Application
oDX As DirectX8 oD3D As Direct3D8 oD3DDevice As Direct3DDevice8 oD3DX As D3DX8 oD3DT As Direct3DTexture8 oD3DT2 As Direct3DTexture8 bRunning As Boolean
‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’
The core DirectX object The core Direct3D object This initializes the 3D video card. Additional Direct3D class libraries Background (hive) texture Bee texture Controls the execution loop
Using Direct3D CHAPTER 9
LISTING 9.1
157
Continued
‘This structure describes a custom vertex. Private Type CUSTOMVERTEX X As Single Y As Single Z As Single rhw As Single color As Long specular As Long tu As Single tv As Single End Type ‘’’Creates your two objects: The bee and the background. Dim TriStrip(0 To 3) As CUSTOMVERTEX ‘’’ Background Dim TrisStrip2(0 To 3) As CUSTOMVERTEX ‘’’ Bee
Initializing the Environment After you have declared all the objects, you need to begin setting up the screen environment you will be using to display the application. In the Beeze application, this is done in the InitializeEnvironment method. This method is responsible for initializing the DirectX8, Direct3D8, and D3DX8 objects. It also sets the display to a 640×480 24-bit display, loads the bee and background bitmap files into texture objects, and sets the device’s render state and vertex shader. Listing 9.2 shows the complete method that handles all these processes. LISTING 9.2
Using the InitializeEnvironment Method to Initialize the Beeze
Application
USING DIRECT3D
‘***************************************************************************** ‘** ObjectName: InitializeEnvironment ‘** ‘** Description: This function does the following: ‘** 1. Initializes the DirectX8, Direct3D8, and D3DX8 objects. ‘** 2. Initializes and defines the transparency color. ‘** 3. Sets up a 640x480 24-bit display mode. ‘** 4. Sets up the Direct3D present parameters. ‘** 5. Creates and sets up a Direct3D device. ‘** 6. Sets up the render state and vertex shader of the device. ‘** 7. Creates the background and bee textures from files. ‘** 8. Calls the InitializeVertices function. ‘** ‘*****************************************************************************
9
158
DirectX Graphics Programming PART II
LISTING 9.2
Continued
Public Function InitializeEnvironment() As Boolean On Error GoTo Err_InitializeEnvironment: Dim DispMode As D3DDISPLAYMODE ‘’’ Display mode descriptor Dim oD3DWindow As D3DPRESENT_PARAMETERS ‘’’ Window or viewport that will ‘’’ be used to display images. Dim lColorKeyVal As Long ‘’’Colorkey for transparency Set oDX = New DirectX8 Set oD3D = oDX.Direct3DCreate() Set oD3DX = New D3DX8
lColorKeyVal = &HFFFF0000 With DispMode .Format = D3DFMT_R5G6B5 .Width = 640 .Height = 480 End With With oD3DWindow .SwapEffect = D3DSWAPEFFECT_FLIP .BackBufferCount = 1 .BackBufferFormat = DispMode.Format .BackBufferHeight = 480 .BackBufferWidth = 640 .hDeviceWindow = frmMain.hWnd
‘’’ ‘’’ ‘’’ ‘’’ ‘’’
Create the DirectX object Create the Direct3D object from the DX object. Additional Direct3D class libraries
‘’’ Red is the transparency color
‘’’24-bit RGB pixel format
‘’’ Type of flipping to use. ‘’’ 1 backbuffer ‘’’ Display format
‘’’ Where to display the finished ‘’’ product.
End With ‘’’ Creates the Direct3D hardware device Set oD3DDevice = oD3D.CreateDevice(D3DADAPTER_DEFAULT, _ D3DDEVTYPE_HAL, _ frmMain.hWnd, _ D3DCREATE_SOFTWARE_VERTEXPROCESSING, _ oD3DWindow) With oD3DDevice ‘’’ Setup the vertex shader .SetVertexShader D3DFVF_XYZRHW Or D3DFVF_TEX1 Or _ D3DFVF_DIFFUSE Or D3DFVF_SPECULAR
Using Direct3D CHAPTER 9
LISTING 9.2
159
Continued
‘’’ Set render states for the device ‘’’ Source blend .SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ‘’’ Destination blend .SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ‘’’ Alpha blending .SetRenderState D3DRS_ALPHABLENDENABLE, True End With ‘’’ Load the background (hive) texture Set oD3DT = oD3DX.CreateTextureFromFile(oD3DDevice, _ App.Path & “\hive.bmp”) ‘’’ Load the bee texture Set oD3DT2 = oD3DX.CreateTextureFromFileEx(oD3DDevice, _ App.Path & “\bee.bmp”, 72, 67, _ D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, _ D3DPOOL_MANAGED, D3DX_FILTER_POINT, _ D3DX_FILTER_POINT, lColorKeyVal, _ ByVal 0, ByVal 0) ‘’’Make sure the background vertices were created. If nitializeInitializeVertices() = True Then InitializeEnvironment = True Exit Function End If
Creating the Background Vertices Both the background and the bee in the Beeze application are made up of vertices. These vertices define the coordinates of the triangles that form a rectangle representing the background and the bee. Listing 9.3 shows how to use the nitalizeInitializeVertices function to define the vertices for each of the four points of the background. In this example, you also make use of a function called CreateVertex that wraps the properties of the CUSTOMVERTEX object into an easy-to-use function. As in all programming, creating reusable routines can be helpful.
9 USING DIRECT3D
Err_InitializeEnvironment: MsgBox “Error Number Returned: “ & Err.Number & “ Error Message: “ & _ Err.Description InitializeEnvironment = False End Function
160
DirectX Graphics Programming PART II
LISTING 9.3
Using the InitializeVertices Function to Initialize the Background Vertices in the Beeze Application ‘***************************************************************************** ‘** ObjectName: nitializeInitializeVertices ‘** ‘** Description: This function creates the vertices for the background. ‘** ‘***************************************************************************** Private Function nitializeInitializeVertices() As Boolean On Error GoTo Err_nitializeInitializeVertices: ‘’’ The vertex is layed out to encompass the whole 640x480 screen ‘’’ (0)-------------(1) ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ / ‘’’ (2)-------------(3) TriStrip(0) TriStrip(1) TriStrip(2) TriStrip(3)
= = = =
CreateVertex(10, 10, 0, 1, RGB(255, 255, 255), 0, 0, 0) CreateVertex(640, 10, 0, 1, RGB(255, 255, 255), 0, 1, 0) CreateVertex(10, 480, 0, 1, RGB(255, 255, 255), 0, 0, 1) CreateVertex(640, 480, 0, 1, RGB(255, 255, 255), 0, 1, 1)
nitializeInitializeVertices = True Exit Function Err_nitializeInitializeVertices: nitializeInitializeVertices = False End Function ‘***************************************************************************** ‘** ObjectName: CreateVertex ‘**
Using Direct3D CHAPTER 9
LISTING 9.3
161
Continued
‘** Description: This function wraps the properties of the CUSTOMVERTEX object ‘** so that you can quickly populate it. ‘** ‘***************************************************************************** Private Function CreateVertex(X As Single, Y As Single, Z As Single, ➥rhw As Single, color As Long, specular As Long, tu As Single, ➥tv As Single) As CUSTOMVERTEX With CreateVertex .X = X .Y = Y .Z = Z .rhw = rhw .color = color .specular = specular .tu = tu .tv = tv End With End Function
Drawing to the Screen
LISTING 9.4
Using the Draw3D Subroutine to Draw to the Screen in the Beeze Application
‘***************************************************************************** ‘** ObjectName: Draw3D ‘** ‘** Description: This subroutine does the following: ‘** 1. Clears the Direct3DDevice8 object. ‘** 2. Begins the render of the scene.
9 USING DIRECT3D
After initializing all the objects and loading all your textures, you can begin drawing the screen one frame at a time. Like render routines in DirectDraw, Draw3D is a custom routine that handles drawing your animation. The first thing this method does is clear the Direct3DDevice8 object. Then it draws the screen in between the BeginScene and EndScene methods of the Direct3DDevice8 object. To draw the screen, you use the SetTexture method to change the current texture. Then you use the DrawPrimitiveUP method to assign your texture to a triangle strip: one for the bee and one for the background. The final step is using the Present method to display what you have created between the BeginScene and EndScene methods. Listing 9.4 shows the Draw3D subroutine.
162
DirectX Graphics Programming PART II
LISTING 9.4
Continued
‘** 3. Assigns a texture to the Direct3DDevice object ‘** (background). ‘** 4. Draws the triangle strip for your background. ‘** 5. Assigns a texture to the Direct3DDevice object (bee). ‘** 6. Draws the triangle strip for our bee. ‘** 7. Ends the render of the scene. ‘** 8. Presents this frame of animation to the screen. ‘** ‘***************************************************************************** Public Sub Draw3D() With oD3DDevice .Clear 0, ByVal 0, D3DCLEAR_TARGET, 0, 1#, 0 ‘//Clear the screen black .BeginScene ‘’’ Start drawing ‘’’ Draw background .SetTexture 0, oD3DT ‘’’ Use the background texture .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TriStrip(0), Len(TriStrip(0)) ‘’’ Draw the bee .SetTexture 0, oD3DT2 ‘’’ Use the bee texture .DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, TrisStrip2(0), _ ➥Len(TrisStrip2(0)) .EndScene ‘’’ End drawing .Present ByVal 0, ByVal 0, 0, ByVal 0 End With End Sub
Updating the Bee’s Coordinates Each time the bee moves, you need to re-create its vertices. To do this, you place code in the form’s MouseMove event. Every time the user moves the mouse, this event is then called. Inside the MouseMove event, you redefine the array for TrisStrip2 with new vertices that you acquire from the CreateVertex function that was mentioned previously for Listing 9.3. Listing 9.5 shows the Form_MouseMove event and the update process performed on the bee. LISTING 9.5
Modifying the Form_MouseMove Event in the Beeze Application
‘***************************************************************************** ‘** ObjectName: Form_MouseMove ‘**
Using Direct3D CHAPTER 9
LISTING 9.5
163
Continued
‘** Description: Every time the user moves the mouse, you need to redraw the ‘** bee. This routine resets the vertices for the bee. ‘***************************************************************************** Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, _ ➥Y As Single)
➥ ➥ ➥ ➥
‘’’ Bee vertices TrisStrip2(0) = CreateVertex(X - 50, Y RGB(255, 255, 255), 0, TrisStrip2(1) = CreateVertex(X + 50, Y RGB(255, 255, 255), 0, TrisStrip2(2) = CreateVertex(X - 50, Y + RGB(255, 255, 255), 0, TrisStrip2(3) = CreateVertex(X + 50, Y + RGB(255, 255, 255), 0,
50, 0, 0, 0) 50, 0, 1, 0) 50, 0, 0, 1) 50, 0, 1, 1)
1, _ 1, _ 1, _ 1, _
End Sub
The complete listing for the Beeze example can be found on the Sams Web site.
Creating a Billboard Application
In the next example you will learn how to create a billboard application.
Declaring the Objects As in other examples, you must declare DirectX objects that will be used in this application. In Listing 9.6 you begin this process by creating DirectX8, Direct3D8, Direct3DDevice8, and D3DVECTOR objects. You also create two custom types to simplify your code. You also create an
9 USING DIRECT3D
One of the best tricks of the video game industry has been the use of billboards. Billboards are polygons that are developed to position themselves in a certain direction in relation to the camera in 3D geometry. Billboards can be used to simulate objects such as signs, clouds, distant mountains, trees, fires, and explosions. The basis of the billboard is that some of the these objects are too complex to render in 3D; the polygon count required would bring most video cards to their knees. Therefore, game developers had to come up with alternatives. Billboards enable you to place a picture or series of animations of an object on a flat polygon surface. By always positioning the surface in the path of the camera, you create the illusion that you are looking at all sides of a much more complex object. For example, a tree is a very complex object, but by placing a bitmap of a tree on a flat polygon surface and then rotating it in relation to the user, you can create the illusion of traveling around a three-dimensional tree. This method speeds up rendering and makes the tree look like it’s a real 3D object.
164
DirectX Graphics Programming PART II
array to keep track of the two objects (the bee billboard and the tree billboard) translation vectors. You will also see how to declare the GetTickCount method from the Kernel32.dll to keep track of the time in your animations. In addition to all these objects, you also create a few constants for math calculations. LISTING 9.6 ‘’’ Dim Dim Dim Dim Dim Dim
Declaring the DirectX Objects and Constants
Declare our core objects for DirectX oDX As DirectX8 ‘’’ oD3D As Direct3D8 ‘’’ oD3DD As Direct3DDevice8 ‘’’ oD3DX As D3DX8 ‘’’ oBeeTexture As Direct3DTexture8 ‘’’ oTreeTexture As Direct3DTexture8 ‘’’
Dim bRunning As Boolean
The core DirectX8 object Direct3D8 core object Direct3D hardware devices Direct3D helper library Bee texture Tree texture
‘’’ Running flag used to determine if the ‘’’ execution loop is still running.
Dim aTranslate(0 To 1) As D3DVECTOR
‘’’ Vector array
Private Const PI As Single = 3.1415 Private Const RADIANS As Single = PI / 180 Private Const CAMERA_DISTANCE As Single = 50 origin Private matWorld As D3DMATRIX Private matView As D3DMATRIX Private matProj As D3DMATRIX
‘’’ Approximate Pi Value ‘’’ Radians ‘’’ Distance from camera to
‘’’ World Matrix ‘’’ View Matrix ‘’’ Project Matrix
‘’’ Declare the GetTickCount function that comes from the kernel32 api. ‘’’ This is used to handle animation Private Declare Function GetTickCount Lib “kernel32” () As Long ‘’’ Type declarations Private Type LitVertex P As D3DVECTOR C As Long ‘’’ Color T As D3DVECTOR2 ‘’’ Texture End Type ‘’’ Transformation and Lit Vertex Private Type TLVertex P As D3DVECTOR4 C As Long ‘’’ Color T As D3DVECTOR2 ‘’’ Texture End Type
Using Direct3D CHAPTER 9
165
Initializing the Environment After declaring your objects, you need to set up the environment and load the texture files for your objects (as shown in Listing 9.7). To begin, you call the nitializeInitialize function, which is responsible for creating the DirectX and Direct3D8 objects and the D3DX8 helper object. You also need to define the Direct3DWindow8 by setting the parameters because you are going to do the animation. Then you create a Direct3DDevice8 object by using the CreateDevice method of the Direct3D8 class, and set the render states for this object. Next, load the bitmap files into texture objects, and then set up the transformation for your projector so that everything is positioned correctly in 3D space. Finally, you update the array with information on the world position of each object. LISTING 9.7
The Initialize Procedure
Initialize = False Dim oD3DDMode As D3DDISPLAYMODE ‘’’ Display Mode Dim oD3DPresent As D3DPRESENT_PARAMETERS ‘’’ Presentation parameters for ‘’’ the display window Set oDX = New DirectX8 Set oD3D = oDX.Direct3DCreate() Set oD3DX = New D3DX8
‘’’ Create the DirectX object ‘’’ Create the Direct3D object ‘’’ Create the Direct3D Helper object
9 USING DIRECT3D
‘’’*************************************************************************** ‘’’ Name: Initialize ‘’’ ‘’’ Purpose: This function does the following: ‘’’ 1. Creates the DirectX, Direct3D, and Direct3D helper objects. ‘’’ 2. Sets the display mode for the application. ‘’’ 3. Sets up the window size and attributes. ‘’’ 4. Creates the Direct3DDevice and sets its parameters. ‘’’ 5. Loads the textures from files. ‘’’ 6. Sets the camera(view) matrix, projection matrix, and ‘’’ world matrix. ‘’’ ‘’’ Args: N/A ‘’’ ‘’’ Return: Boolean value that signifies if the initialization completed or ‘’’ not. ‘’’ ‘’’*************************************************************************** Public Function Initialize() As Boolean On Error GoTo Err_Initialize:
166
DirectX Graphics Programming PART II
LISTING 9.7
Continued
‘’’ Sometimes one of these format values will not work. If that happens, ‘’’ try using the other value. ‘’’oD3DDMode.Format = D3DFMT_X8R8G8B8 oD3DDMode.Format = D3DFMT_R5G6B5 ‘’’ Full screen oD3DDMode.Width = 640 oD3DDMode.Height = 480 ‘’’ Setup the dimensions of the screen, and how many buffers there are. ‘’’ and what kind of flipping will be done. With oD3DPresent .SwapEffect = D3DSWAPEFFECT_FLIP .BackBufferCount = 1 .BackBufferFormat = oD3DDMode.Format .BackBufferHeight = oD3DDMode.Height .BackBufferWidth = oD3DDMode.Width .hDeviceWindow = frmMain.hWnd .AutoDepthStencilFormat = D3DFMT_D16 .EnableAutoDepthStencil = 1 End With ‘’’ Create a Direct3D device Set oD3DD = oD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, _ frmMain.hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, oD3DPresent) With oD3DD ‘’’ Setup the vertex shader .SetVertexShader (D3DFVF_XYZ Or D3DFVF_DIFFUSE Or D3DFVF_TEX1) ‘’’ Set up the render state parameters .SetRenderState D3DRS_LIGHTING, False ‘’’ Disable lighting .SetRenderState D3DRS_ZENABLE, 1 .SetRenderState D3DRS_SRCBLEND, D3DBLEND_SRCALPHA .SetRenderState D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA .SetRenderState D3DRS_ALPHABLENDENABLE, 1 .SetTextureStageState 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR .SetTextureStageState 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR End With
➥
‘’’ Load the textures based on the display type currently being used If oD3D.CheckDeviceFormat(0, D3DDEVTYPE_HAL, oD3DDMode.Format, 0, _ D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) = D3D_OK Then
Using Direct3D CHAPTER 9
LISTING 9.7
167
Continued
Set oBeeTexture = oD3DX.CreateTextureFromFileEx(oD3DD, App.Path & _ ➥”\bee.bmp”, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, _ ➥D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0) Set oTreeTexture = oD3DX.CreateTextureFromFileEx(oD3DD, App.Path & _ ➥”\tree.bmp”, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, _ ➥D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0) ElseIf oD3D.CheckDeviceFormat(0, D3DDEVTYPE_HAL, oD3DDMode.Format, 0, _ ➥D3DRTYPE_TEXTURE, D3DFMT_A4R4G4B4) = D3D_OK Then Set oBeeTexture = oD3DX.CreateTextureFromFileEx(oD3DD, App.Path & _ ➥”\bee.bmp”, 64, 64, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, _ ➥D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0) Set oTreeTexture = oD3DX.CreateTextureFromFileEx(oD3DD, App.Path & _ ➥”\tree.bmp”, 64, 64, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, _ ➥D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0) ElseIf oD3D.CheckDeviceFormat(0, D3DDEVTYPE_HAL, oD3DDMode.Format, 0, _ ➥D3DRTYPE_TEXTURE, D3DFMT_A1R5G5B5) = D3D_OK Then Set oBeeTexture = oD3DX.CreateTextureFromFileEx(oD3DD, App.Path & _ ➥”\bee.bmp”, 64, 64, 1, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, _ ➥D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0) Set oTreeTexture = oD3DX.CreateTextureFromFileEx(oD3DD, App.Path & _ ➥”\tree.bmp”, 64, 64, 1, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, _ ➥D3DX_FILTER_LINEAR, D3DX_FILTER_LINEAR, 0, ByVal 0, ByVal 0) Else Initialize = False Exit Function End If
‘’’ Build a left handed projection matrix and store in your ‘’’ projection matrix. D3DXMatrixPerspectiveFovLH matProj, PI / 3, 1, 0.1, 100 oD3DD.SetTransform D3DTS_PROJECTION, matProj ‘’’ Apply the transformation ‘’’ Set the world position of each billboard. aTranslate(0) = CreateVector(0, 0, 0) aTranslate(1) = CreateVector(3, 0, -4) Initialize = True Exit Function
9 USING DIRECT3D
‘’’ Build a left handed look at matrix and store in your view matrix. D3DXMatrixLookAtLH matView, CreateVector(0, 0, 20), _ ➥CreateVector(0, 0, 0), CreateVector(0, 0, 1) oD3DD.SetTransform D3DTS_VIEW, matView ‘’’ Apply the transformation
168
DirectX Graphics Programming PART II
LISTING 9.7
Continued
Err_Initialize: ‘’’ Not able to initialize. Set initialse flag to false, so program ends. Initialize = False End Function
Rendering the Scene To render a scene with a billboard in it is a little more difficult than a regular 3D scene. For one thing, you have to keep track of the camera angle and where it is facing at all times. If the camera adjusts its angle in the world, you need to make sure that all the billboards also change their rotation so that they are always facing the camera. In the Render subroutine in Listing 9.8, you first reposition the camera in the world. Then, you transform the vertices of the billboards by using a transformation matrix. For each billboard, you assemble the scene with your images and then present it to the user. LISTING 9.8
The Render Procedure
‘’’*************************************************************************** ‘’’ Name: Render ‘’’ ‘’’ Purpose: This subroutine is responsible for wrapping all the functions ‘’’ and methods to do the rendering of the scene. The camera is ‘’’ being rotated around the origin. ‘’’ ‘’’ Args: sAngle - New angle for the camera to reference. ‘’’ ‘’’ Return: N/A ‘’’ ‘’’*************************************************************************** Public Sub Render(sAngle As Single) Dim CamPos As D3DVECTOR Dim D3DDevVP As D3DVIEWPORT8 ‘’’ Clear out the render device oD3DD.Clear 0, ByVal 0, D3DCLEAR_TARGET Or D3DCLEAR_ZBUFFER, 0, 1#, 0 ‘’’ Rotate the camera at With CamPos .X = CAMERA_DISTANCE .Y = CAMERA_DISTANCE .Z = CAMERA_DISTANCE End With
a distance of 50m * Cos(sAngle * RADIANS * 2) * Sin(sAngle * RADIANS * 2) * Cos(sAngle * RADIANS)
Using Direct3D CHAPTER 9
LISTING 9.8
169
Continued
D3DXMatrixLookAtLH matView, CamPos, CreateVector(0, 0, 0), _ ➥CreateVector(0, 0, 1) oD3DD.SetTransform D3DTS_VIEW, matView oD3DD.GetViewport D3DDevVP oD3DD.BeginScene
‘’’ Starts the drawing of the scene
Dim I As Long Dim Dim Dim Dim
v2D(0 To 1) As D3DVECTOR Vertices(0 To 3) As TLVertex Ref(0 To 1) As Long Depths(0 To 1) As Single
D3DXMatrixIdentity matWorld ‘’’ Configure the Direct3D Device. With oD3DD .SetRenderState D3DRS_ALPHATESTENABLE, 1 .SetRenderState D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL .SetRenderState D3DRS_ALPHAREF, 50 .SetRenderState D3DRS_ZWRITEENABLE, 0 .SetVertexShader (D3DFVF_XYZRHW Or D3DFVF_DIFFUSE Or D3DFVF_TEX1) End With
‘’’ Change the depth of the billboards ‘’’ Paint the further away ones first, then the closer ones. Dim sHold As Single, lHold As Long If Depths(1) > Depths(0) Then ‘’’ Bubblesort the Depth sHold = Depths(0): Depths(0) = Depths(1): Depths(1) = sHold ‘’’ Bubblesort the reference lHold = Ref(0): Ref(0) = Ref(1): Ref(1) = lHold End If
9 USING DIRECT3D
‘’’ Transform to screen space For I = 0 To 1 D3DXVec3Project v2D(I), aTranslate(I), D3DDevVP, matProj, matView _ ➥, matWorld Ref(I) = I Depths(I) = v2D(I).Z Next I
170
DirectX Graphics Programming PART II
LISTING 9.8
Continued
‘’’ Render each billboard For I = 0 To 1 If I = 0 Then ‘’’ Tree goes first and then the bee oD3DD.SetTexture 0, oTreeTexture ‘’’ Create the vertices for the billboard(a rectangular surface) Vertices(0) = CreateTLV(v2D(Ref(I)).X - 100, _ ➥v2D(Ref(I)).Y - 100, v2D(Ref(I)).Z, 1, &HFFFFFF, 0, 0) Vertices(1) = CreateTLV(v2D(Ref(I)).X + 100, _ ➥v2D(Ref(I)).Y - 100, v2D(Ref(I)).Z, 1, &HFFFFFF, 1, 0) Vertices(2) = CreateTLV(v2D(Ref(I)).X - 100, _ ➥v2D(Ref(I)).Y + 100, v2D(Ref(I)).Z, 1, &HFFFFFF, 0, 1) Vertices(3) = CreateTLV(v2D(Ref(I)).X + 100, _ ➥v2D(Ref(I)).Y + 100, v2D(Ref(I)).Z, 1, &HFFFFFF, 1, 1) Else oD3DD.SetTexture 0, oBeeTexture ‘’’ Create the vertices for the billboard(a Vertices(0) = CreateTLV(v2D(Ref(I)).X - 30, ➥v2D(Ref(I)).Z, 1, &HFFFFFF, 0, 0) Vertices(1) = CreateTLV(v2D(Ref(I)).X + 30, ➥v2D(Ref(I)).Z, 1, &HFFFFFF, 1, 0) Vertices(2) = CreateTLV(v2D(Ref(I)).X - 30, ➥v2D(Ref(I)).Z, 1, &HFFFFFF, 0, 1) Vertices(3) = CreateTLV(v2D(Ref(I)).X + 30, ➥v2D(Ref(I)).Z, 1, &HFFFFFF, 1, 1)
rectangular surface) v2D(Ref(I)).Y - 30, _ v2D(Ref(I)).Y - 30, _ v2D(Ref(I)).Y + 30, _ v2D(Ref(I)).Y + 30, _
End If ‘’’ Define where on your texture bitmap, you should pickup the ‘’’ next image. Vertices(0).T.X = 0 Vertices(0).T.Y = 0 Vertices(1).T.X = 1 Vertices(1).T.Y = 0 Vertices(2).T.X = 0 Vertices(2).T.Y = 1 Vertices(3).T.X = 1 Vertices(3).T.Y = 1
Using Direct3D CHAPTER 9
LISTING 9.8
171
Continued
‘’’ Draw the primitive and pass in the array of vertices oD3DD.DrawPrimitiveUP D3DPT_TRIANGLESTRIP, 2, Vertices(0), _ ➥Len(Vertices(0)) Next I ‘’’ Device cleanup oD3DD.SetRenderState D3DRS_ALPHATESTENABLE, 0 oD3DD.SetRenderState D3DRS_ZWRITEENABLE, 1 oD3DD.EndScene ‘’’ Display the completed screen oD3DD.Present ByVal 0, ByVal 0, 0, ByVal 0 End Sub
The full billboard application can be found on the Sams Web site.
Manipulating Vectors and Vertices In Direct3D programming, vectors and vertices are very important for defining where objects are and how they should be assembled. With this in mind, it’s a good idea to take advantage of some functions that make this process much easier. The functions in Listing 9.9 are used in the billboard example to create and manipulate vectors and vertices. LISTING 9.9
The Vector and Vertex Functions
9 USING DIRECT3D
‘’’*************************************************************************** ‘’’ Name: CreateVector ‘’’ ‘’’ Purpose: Creates a vector object based on the parameters passed into it. ‘’’ ‘’’ Args: X - X-coordinate of the vector ‘’’ Y - Y-coordinate of the vector ‘’’ Z - Z-coordinate of the vector ‘’’ ‘’’ Return: D3DVECTOR ‘’’ ‘’’*************************************************************************** Private Function CreateVector(X As Single, Y As Single, Z As Single) As ➥D3DVECTOR
172
DirectX Graphics Programming PART II
LISTING 9.9
Continued
With CreateVector .X = X .Y = Y .Z = Z End With End Function ‘’’*************************************************************************** ‘’’ Name: CreateLV ‘’’ ‘’’ Purpose: Creates a Lit Vertex from the provided parameters. ‘’’ ‘’’ Args: pX - X-Screen position ‘’’ pY - Y-Screen position ‘’’ pZ - Z-Screen position ‘’’ C - Vertex color ‘’’ tU - Texture coordinate ‘’’ tV - Texture coordinate ‘’’ ‘’’ Return: LitVertex ‘’’ ‘’’*************************************************************************** Private Function CreateLV(pX As Single, pY As Single, pZ As Single, C As Long, ➥ tU As Single, tV As Single) As LitVertex Dim oD3DV2 As D3DVECTOR2 With oD3DV2 .X = tU .Y = tV End With With CreateLV .P = CreateVector(pX, pY, pZ) .C = C .T = oD3DV2 End With End Function ‘’’*************************************************************************** ‘’’ Name: CreateTLV ‘’’
Using Direct3D CHAPTER 9
LISTING 9.9
173
Continued
‘’’ Purpose: Creates a transformation and lit vertex from specified ‘’’ parameters. ‘’’ ‘’’ Args: pX - X-Screen position ‘’’ pY - Y-Screen position ‘’’ pZ - Z-Screen position ‘’’ RHW - Normalized Z screen position ‘’’ C - Vertex color ‘’’ tU - Texture coordinate ‘’’ tV - Texture coordinate ‘’’ ‘’’ Return: TLVertex ‘’’ ‘’’*************************************************************************** Private Function CreateTLV(pX As Single, pY As Single, pZ As Single, RHW As ➥Single, C As Long, tU As Single, tV As Single) As TLVertex With CreateTLV .P.X = pX .P.Y = pY .P.Z = pZ .P.w = RHW .C = C .T.X = tU .T.Y = tV End With End Function
9 In this chapter, you have learned about two uses for Direct3D. In the first example, you looked at how to do 2D graphics programming with Direct3D. In the second example, you looked at how to create and manipulate billboards in Direct3D. By using the techniques and examples in this chapter, you will have a much better understanding of Direct3D. In the next chapter, you will be learning about DirectInput to capture and manage the users’ commands.
USING DIRECT3D
Summary
Monitoring User Input with DirectInput
DirectInput is responsible for all the input libraries available to DirectX. Included are the three main objects: keyboards, mice, and joysticks. This section explains all three of these objects as well as the new DirectInput technology: action mapping. This section also includes a detailed overview of the DirectInput object.
IN THIS PART 10 Using DirectInput to Manage User Interactions 177 11 Action Mapping 12 The Keyboard 13 The Joystick 14 The Mouse
193 205
219 237
PART
III
Using DirectInput to Manage User Interactions
IN THIS CHAPTER • Obtaining User Input from DirectInput • DirectInput Architectural Overview • DirectInput Technologies and Components 190 • Summary
191
178
180
CHAPTER
10
178
Monitoring User Input with DirectInput PART III
When you create computer applications, it’s always useful for those applications to be capable of discerning what the user wants them to do next. By using DirectInput in your programs, you give them the capability to understand which input device is being used and how the user is utilizing that device . This chapter focuses on the broad uses of DirectInput. You will learn how to access the main DirectInput objects and interpret the data. DirectInput is a collection of classes that receives input from many different outside interfaces. These interfaces include keyboards, mice, joysticks, yokes, force feedback devices, and even devices that haven’t been invented yet. That’s right—DirectInput is designed to accommodate future input devices. For example, if you were to create a kiosk program for users to view car models they were interested in, you would want them to be able to navigate easily through the application. To do that, you could just assign the mouse or a trackball to the program through DirectInput. If you wanted to change the input device to a touch screen later, you could simply change a few DirectInput routines and you’re in business. Here are some common uses for DirectInput: • Game controls • Kiosk navigation • Simulations
Obtaining User Input from DirectInput DirectInput offers many features that give it an advantage over standard forms of user input services. The following is a list of its major features: • DirectInput provides accessibility to input devices that are not supported by the Win32 API. • DirectInput gives you faster response times by communicating directly with the hardware drivers. • DirectInput supplies a complete support library for all input devices. • DirectInput provides access to device input regardless of whether the application is in the foreground or background. • DirectInput can remain extensible and versatile through the use of application mapping. It is important to note that DirectInput is not always the correct input API to use. When simple text boxes are being used and/or standard Windows navigation is going on, there is no noticeable benefit to using DirectInput. In VB, you have access to some very good events that can be used to monitor user input, such as Form_KeyUp, Form_KeyDown, Form_KeyPress, Form_MouseMove, Form_MouseUp, and Form_MouseDown. All of these events are perfectly fine when you are working with Windows forms in DirectX, so unless you are really in need of speed, you can use the default VB events to handle your simpler needs.
Using DirectInput to Manage User Interactions CHAPTER 10
179
Objects in DirectInput DirectInput uses objects to manage all the input devices and enumerate them for use. Enumeration is the process of creating a collection of devices from data retrieved from the machine. For example, if I were to enumerate the devices on my machine, I would find that I have a mouse, a keyboard, and a four-way joystick. With this information at your disposal, you can then determine which input device best suits your program’s needs. The following sections cover the major objects of DirectInput and explain how they relate to each other.
The DirectInput Object is the main object for DirectInput usage. Whenever the DirectInput classes are used, it is the first object that must be created. From the DirectInput object, you can find out which input devices exist on the user’s PC. DirectInput
The Device Object You use the Device object in DirectInput to designate the actual hardware being used for input. Figure 10.1 shows the three most common input devices: keyboard, mouse, and joystick.
FIGURE 10.1 The three main device types.
A device can be as simple as a keyboard or as complex as a flight stick. Devices can include any of the following: • Joystick: Usually a four-way or eight-way device that has a stick in the middle of a square base. • Yoke: A Y-shaped device similar to the steering column on a commercial airplane. • Steering wheel: A car steering wheel or similar device used primarily in racing games. • Gas pedal: A hinged pedal placed on the floor. This device is exactly like a car’s gas pedal. • Keyboard: A standard computer keyboard.
10 MANAGING USER INTERACTIONS
• Mouse: An optical or a mechanical device that measures the movement of a base across a hard surface. This is done by measuring the movement over time of a ball inside the device. On optical mice, this is done by measuring how fast the light bouncing off the surface changes.
180
Monitoring User Input with DirectInput PART III
• Trackball: Similar to a mouse, this device has a much larger ball mounted on the top that can be rolled to produce movement. • Graphics tablet: Used primarily in the graphics world to create complex models. This device is a flat tablet that can be drawn on with a pen. The resulting drawing is translated to the screen. • Virtual reality gloves: A set of gloves with wires that measure pressure in all parts of the gloves. The gloves can measure movement in 3D space, flexing of the glove, and pressure at certain points on the glove.
The Buttons and Axes Objects Buttons and axes are device objects. Basically, they represent the buttons and movement capabilities of input devices; the axis object is used when an input device is capable of having an axis, or direction of movement. For example, if a joystick has two buttons and a stick, then you can enumerate that this device has six device objects: The stick produces four device objects, one for each axis of movement (north, south, east, and west), and the joystick’s two buttons represent the other two device objects. All of these device objects(both buttons and axes) are basically micro switches with an on and off state. You look for the axis device object when you want to know which direction was specified, and look at the button device object when you’re interested in whether a button was chosen.
Cooperative Levels Cooperative levels provide a way to define how the device input is handled by the application and by Windows. By using cooperative levels, you can tell the DirectInput classes to receive data only from foreground applications, or enable the application to receive input even when it’s hidden behind another window (running as a background application). You can also specify whether the input device is exclusive or nonexclusive. An exclusive device means that only the program you create the device in has control over the input coming from the device. Nonexclusive means that no restrictions have been put on access to the device. Therefore, any other program can try to take control of the device at the same time. For example, if you have two games running, which game has control of the input? Well, that depends on whether the programmers set an exclusive cooperative level on their programs. If neither one of the programs has this setting, then the program in the forefront of the screen has control of all the input devices.
DirectInput Architectural Overview DirectInput is made up of the DirectInput (DI) class and its associated classes and methods that allow you to manage user input. The DirectInput classes include classes that create DI
Using DirectInput to Manage User Interactions CHAPTER 10
181
objects, enumerate them, create devices for each object, set up cooperative levels with other Windows programs, acquire the devices, retrieve the input messages, and respond to the data. Figure 10.2 shows DirectInput and all its subclasses with their DirectX formal names. These names include an 8 to signify that they are new for DirectX 8.
DirectX 8
Directlnput8
DirectlnputDevice8
DirectInputDevice ObjectInstance8
DirectInputDevice Instance8
DirectInputEffect
DirectInputEnumEffect
FIGURE 10.2 DirectInput and its subclasses.
The DirectInput Class
10 MANAGING USER INTERACTIONS
is the core class of all input functionality in DirectX. After declaring a DirectX class, you can then obtain a DirectInput class, which you use to acquire its subclasses, such as DirectInputDevice, DirectInputDeviceInstance, DirectInputEffect, and DirectInputEnumEffect. DirectInput
182
Monitoring User Input with DirectInput PART III
This is what the code looks like when included with the DirectX declaration: ‘’’First you need to access the DirectX 8 class Dim oDX As New DirectX8 ‘’’Next you need to create a DirectInput class Dim oDI As DirectInput8
Using the DirectInput Class in VB.NET This same code can be used in VB.NET. The DirectInput class would look like this: ‘’’First you need to access the DirectX 8 class Dim oDX As DxVBLibA.DirectX8 = New _ ➥DxVBLib.DirectX8() ‘’’Next you need to create a DirectInput class Dim oDI As DxVBLibA.DirectInput8
Now that you have created the DirectX class and the DirectInput class, you are ready to gather information about all the devices connected to the computer through the other DirectInput classes. The DirectInput class gives you access to many methods, listed in Table 10.1. TABLE 10.1
The DirectInput Methods
Method
Purpose
ConfigureDevices
Shows property pages for the input devices and allows the user to map program actions to particular devices (an action map). Finds or enumerates devices that closely match the action map. Creates a DirectInputDevice class. Returns a Boolean value to let you know whether the specified device is attached. Finds or enumerates all devices that are attached to the machine. Calls the Microsoft Windows Control Panel.
GetDevicesBySemantics CreateDevice GetDeviceStatus GetDIDevices RunControlPanel
Using DirectInput to Manage User Interactions CHAPTER 10
183
The DirectInputDevice Class is a device object managed by DirectX. You use the DirectInputDevice class to create devices (joysticks, keyboards, or mice), manage them, and set their attributes.
DirectInputDevice
This is what the code looks like when included with the DirectX and DirectInput declarations: ‘’’First you need to access the DirectX 8 class Dim oDX As DirectX8 = New DirectX8() ‘’’Next you need to create a DirectInput class Dim oDI As DirectInput8 ‘’’Then you need to create a DirectInputDevice class Dim oDID As DirectInputDevice8
Using the DirectInputDevice Class in VB.NET The DirectInputDevice class would look like this in VB.NET: ‘’’First you need to access the DirectX 8 class Dim oDX As DxVBLibA.DirectX8 = New _ ➥DxVBLib.DirectX8() ‘’’Next you need to create a DirectInput class Dim oDI As DxVBLibA.DirectInput8 ‘’’Then you need to create a DirectInputDevice class Dim oDID As DxVBLibA.DirectInputDevice8
DirectInputDevice gives you access to many methods. Table 10.2 outlines some of the most commonly used ones.
TABLE 10.2
The Most Commonly Used DirectInputDevice Methods
Description
Acquire
Acquires a DirectInputDevice. Builds an action map. Creates a custom force feedback effect. Creates an effect based on the built-in device’s supported effects. Creates an effect stored in a file.
BuildActionmap CreateCustomEffect CreateEffect CreateEffectFromFile
10 MANAGING USER INTERACTIONS
Method
184
Monitoring User Input with DirectInput PART III
TABLE 10.2
Continued
Method
Description
GetCapabilities
Gets capabilities of a device, such as the number of axes and buttons, and the driver and hardware version. Gets buffered data from a device. Gets information on a device’s identity. Creates an enumeration on the input and output objects available with a device. Gets immediate data from a device. Gets immediate data from a joystick device. Gets immediate data from an extended joystick device. Gets immediate data from a keyboard device. Gets immediate data from a mouse device. Gets immediate data from a mouse device with up to eight buttons. Enumerates all the effects available to a force feedback device. Gets the current state of the force feedback device. Gets information about a device image. Gets information on device objects such as buttons. Gets information on a specific property for a given device. Properties that are supported include autocenter, deadzone, and granularity. Forces information to be returned from DirectInput devices that don’t generate their own events. Opens the DirectInput control panel, which shows the settings for the current DirectInput device, such as the mouse, keyboard, or joystick. Sends data to an acquired device. Sends a command to the force feedback device. Sets up the data and format for the action map. Sets up the data format to be used by a DirectInput device other than a standard keyboard, mouse, or joystick. The data format defines how the data is returned from the device to an application.
GetDeviceData GetDeviceInfo GetDeviceObjectsEnum GetDeviceState GetDeviceStateJoystick GetDeviceStateJoystick2 GetDeviceStateKeyboard GetDeviceStateMouse GetDeviceStateMouse2 GetEffectsEnum GetForceFeedbackState GetImageInfo GetObjectInfo GetProperty
Poll RunControlPanel
SendDeviceData SendForceFeedbackCommand SetActionMap SetCommonDataFormat
Using DirectInput to Manage User Interactions CHAPTER 10
TABLE 10.2
Continued
Method
Description
SetCooperativeLevel
Sets up the cooperative level information for the device. Sets the property behavior of the device. Deallocates the DirectInputDevice.
SetProperty Unacquire
185
Some of these methods refer to immediate and buffered data. Immediate data is data sent to your program through an exposed event. It basically occurs immediately and can be processed almost as fast. Buffered data is retrieved through a loop process. When your program loops around and checks the buffer, then it knows which key was pressed.
The DirectInputDeviceObjectInstance Class The DirectInputDeviceObjectInstance class represents a device object, such as a button or an axis on a device. With this object, you can retrieve information about the button or axis being used; these items are referenced in code as Human Interface Devices (HIDs). This is what the code would look like when included with the DirectX and DirectInput class declarations: ‘’’First you need to access the DirectX 8 class Dim oDX AsNew DirectX8 ‘’’Next you need to create a DirectInput class Dim oDI AsDirectInput8 ‘’’Then you need to create a DirectInputDeviceObjectInstance class Dim oDIDOI AsDirectInputDeviceObjectInstance
Using the DirectInputDeviceObjectInstance Class in VB.NET The DirectInputDeviceObject class would look like this in VB.NET: ‘’’First you need to access the DirectX 8 class Dim oDX As DxVBLibA.DirectX8 = New _ ➥DxVBLib.DirectX8()
‘’’Then you need to create a DirectInputDeviceObjectInstance class Dim oDIDOI As _ ➥DxVBLibA.DirectInputDeviceObjectInstance
10 MANAGING USER INTERACTIONS
‘’’Next you need to create a DirectInput class Dim oDI As DxVBLibA.DirectInput8
186
Monitoring User Input with DirectInput PART III
has many methods. Table 10.3 outlines some of the more commonly used DirectInputDeviceObjectInstance methods that provide information about the DirectInputDevice. DirectInputDeviceObjectInstance
TABLE 10.3
The Most Commonly Used DirectInputDeviceObjectInstance Methods
Method
Description
GetCollectionNumber
Gets the number for the HID link collection that the current device belongs to. Gets the designator index for an object on an HID. This value is an integer that references a designator in the HID physical descriptor. Gets an HID for the dimensional units used by the device. Gets the flags associated with the device object. Gets the globally unique identifier (GUID) type associated with the device object. Gets the friendly name associated with the device object. Gets the flags associated with the device object that tell the type of object. Gets the HID for the device object.
GetDesignatorIndex
GetDimension GetFlags GetGuidType GetName GetType GetUsage
The DirectInputDeviceInstance Class The DirectInputDeviceInstance class is special in that it gets information about a specific instance of a DirectInput device. This class is used to get the device type, device name, manufacturer’s name, and any GUIDS associated with the device. This is what the code looks like when included with the DirectX and DirectInput class declarations: ‘’’First you need to access the DirectX 8 class Dim oDX AsNew DirectX8 ‘’’Next you need to create a DirectInput class Dim oDI AsDirectInput8 ‘’’Then you need to create a DirectInputDeviceInstance class Dim oDIDOI As DirectInputDeviceInstance8
Using DirectInput to Manage User Interactions CHAPTER 10
187
Using the DirectInputDeviceInstance Class in VB.NET The DirectInputDeviceInstance class would look like this in VB.NET: ‘’’First you need to access the DirectX 8 class Dim oDX As DxVBLibA.DirectX8 = New _ ➥DxVBLib.DirectX8() ‘’’Next you need to create a DirectInput class Dim oDI As DxVBLibA.DirectInput8 ‘’’Then you need to create a DirectInputDeviceInstance class Dim oDIDOI As DxVBLibA. _ ➥DirectInputDeviceInstance8
A DirectInputDeviceInstance class is created by calling the DirectInputDevice8.Get DeviceInfo or the DirectInputEnumDevices8.GetItem method, as shown in these examples: oDIDOI = oDID.GetDeviceInfo
or oDIDOI = oDIED.GetItem
Table 10.4 outlines some of the most commonly used DirectInputDeviceInstance methods. TABLE 10.4
The Most Commonly Used DirectInputDeviceInstance Methods
Method
Description
GetDevType
Gets the device type and subtype. Gets a GUID for a force feedback device. Gets a GUID for an input device. Gets the GUID supplied by the device’s manufacturer. Gets the name of the instance of the device. Gets the product name of the device. Gets the HID for the device object.
GetGuidFFDriver GetGuidInstance GetGuidProduct GetInstanceName GetProductName GetUsage
The DirectInputEffect Class
MANAGING USER INTERACTIONS
The DirectInputEffect class references a force-feedback effect created by an application. These effects are used only by force feedback devices, such as Microsoft’s Force Feedback 2 joystick and the Force Feedback Wheel. To become a force feedback device, the hardware
10
188
Monitoring User Input with DirectInput PART III
must be designed to respond to DirectX force feedback commands. Most force feedback devices are simply made up of a shell, an actuator (joystick shaft or steering wheel), buttons, and one or more motors. The motors are what make the vibrations inside the device, which gives force feedback its unique abilities. When included with the DirectX and DirectInput declarations, the code looks like this: ‘’’First you need to access the DirectX 8 class Dim oDX As New DirectX8 ‘’’Next you need to create a DirectInput class Dim oDI AsDirectInput8 ‘’’Then you need to create a DirectInputEffect class Dim oDIE AsDirectInputEffect
Using the DirectInputEffect Class in VB.NET The DirectInputEffect class would look like this in VB.NET: ‘’’First you need to access the DirectX 8 class Dim oDX As DxVBLibA.DirectX8 = New _ ➥DxVBLib.DirectX8() ‘’’Next you need to create a DirectInput class Dim oDI As DxVBLibA.DirectInput8 ‘’’Then you need to create a DirectInputEffect class Dim oDIE As DxVBLibA.DirectInputEffect
A DirectInputEffect class is created by calling the DirectInputDevice8.CreateEffect method, as shown in the following line: oDIE = oDID.CreateEffect
Table 10.5 lists some of the most commonly used DirectInputEffect methods. TABLE 10.5
The Most Commonly Used DirectInputEffect Methods
Method
Description
Download
Downloads an effect to the specified device. Sets the parameters of an effect. Starts playing an effect. Stops playing an effect.
SetParameters Start Stop
Using DirectInput to Manage User Interactions CHAPTER 10
TABLE 10.5
189
Continued
Method
Description
Unload
Unloads an effect from the specified device. Gets the GUID for an effect. Gets the status for an effect. Gets the parameters for an effect.
GetEffectGuid GetEffectStatus GetParameters
The DirectInputEnumEffects Class The DirectInputEnumEffects class retrieves information about all the effects available for a specified device. The following lines show what the code would look like when included with the DirectX and DirectInput declarations: ‘’’First you need to access the DirectX 8 COM class Dim oDX AsNew DirectX8 ‘’’Next you need to create a DirectInput class Dim oDI AsDirectInput8 ‘’’Then you need to create a DirectInputEnumEffects class Dim oDIEE As DirectInputEnumEffects
Using the DirectInputEnumEffects Class in VB.NET The DirectInputEnumEffects class would look like this in VB.NET: ‘’’First you need to access the DirectX 8 COM class Dim oDX As DxVBLibA.DirectX8 = New _ ➥DxVBLib.DirectX8() ‘’’Next you need to create a DirectInput class Dim oDI As DxVBLibA.DirectInput8 ‘’’Then you need to create a DirectInputEnumEffects class Dim oDIEE As DxVBLibA. DirectInputEnumEffects
10
ODIEE = oDID.GetEffectsEnum
MANAGING USER INTERACTIONS
To create a DirectInputEnumEffects class, you need to call the DirectInputDevice8.Get method, as shown here:
EffectsEnum
190
Monitoring User Input with DirectInput PART III
Table 10.6 outlines all the DirectInputEnumEffects methods. TABLE 10.6
The DirectInputEnumEffects Methods
Method
Description
GetCount
Gets the number of enumerated effects. Gets information about the effect parameters while the device is being used. Gets the GUID for the effect. Gets the name of the effect. Gets information on the parameters of an effect. Gets information about the type of the effect.
GetDynamicParams GetEffectGuid GetName GetStaticParams GetType
DirectInput Technologies and Components Now that you understand some of the methods of the major DirectInput classes, it’s a good idea to look at the technologies and components offered in DirectInput. One of the newest technologies to come out of DirectInput has been that of action mapping, which enables you to create a template of actions that are later mapped to specific controls. Also new to DirectX is force feedback, a DirectInput library that tells force feedback devices to vibrate, knock, and resist at specific times. There are also three major components used in DirectInput. The first is the joystick, which also encompasses the wheel, flight stick, and many other game-specific devices. The next one is the keyboard, which has become a standard part of computers over the years. The last DirectInput component discussed in this chapter is the mouse.
Action Mapping Action mapping is a new technology for DirectX that allows you to program input for many different devices at one time. Instead of having to plan ahead for future devices, you can specify the function of each device object by using built-in DirectX virtual controls. DirectX then chooses the best match with the existing devices on the user’s machine. Chapter 11, “Action Mapping,” provides more information on action maps.
Force Feedback Force feedback is the technology in DirectX that makes it possible for applications to provide physical feedback to users through their input devices. For example, if you wanted a flight stick to shake around when a ship is hit, you could assign a force feedback effect to shake the
Using DirectInput to Manage User Interactions CHAPTER 10
191
control. By defining a set of effects to use in your application, and implementing these effects at certain points in your application, you can give the user some impressive feedback. Chapter 13, “The Joystick,” provides much more detail on force feedback devices.
The Keyboard Component The keyboard is the oldest part of the modern computer. It’s what allows you to supply specific user input for a variety of applications. Before the advent of the mouse and joystick, the only method of communicating the users’ wishes for multimedia applications was through the use of a keyboard.
Joysticks, Yokes, and Steering Wheels Joysticks and their cousins have a history that started in the video game market in the 1970s and 1980s. Because of their success in these markets, they were moved into the home market and eventually to the PC market. Through the years, they have evolved from their early fourposition and two-button design to complex devices that can actually provide physical feedback to the user. Among the more common joystick devices currently on the market, the traditional joystick still reigns supreme. However, other types have developed that give a very realistic feel. Among them is the yoke, a Y-shaped device similar to the steering column in a professional airplane. This device can be used with games such as Microsoft Flight Simulator to give users a more realistic experience. In the racing realm, racing simulators can benefit from the use of steering wheel and pedal devices to mimic control over a speeding car.
The Mouse Component The mouse has been around for a long time. Its early use in computers made it easier for users to graphically select information. It has now become an essential device in the Windows environment.
Summary DirectInput is the DirectX component that handles user input. DirectInput provides support for keyboards, mice, joysticks, and all variations on these devices. DirectInput also includes the new feature called action mapping, which enables future device capabilities to be accounted for today. Joysticks with force feedback capabilities are also fully supported in DirectInput.
10 MANAGING USER INTERACTIONS
In Chapter 11, you will learn about action mapping and how it can be used to create templates for DirectInput.
CHAPTER
Action Mapping
11
IN THIS CHAPTER • Managing User Input with Action Maps • Summary
204
194
194
Monitoring User Input with DirectInput PART III
In the past, we as developers had to make assumptions about what controls were available on the average user’s machine. This wasn’t much of a problem because most users had at least one of the following three devices: a keyboard, mouse, or joystick. The developer was covered as long as he or she coded for each of these devices. However, times have changed, and now there are more devices on the market than we can predict will be on an average user’s computer. And if new devices come out, your program might not be compatible with them. This is where action mapping comes in. Action mapping is a new feature of DirectX 8 that makes compatibility with a large number of devices easier to manage.
Managing User Input with Action Maps An action map is like a middleman. It sits between the devices and the program and decides which device is the best match on the user’s machine for a given program. The action map also provides a way for device drivers to logically map themselves to a specific type of action. Therefore, the programmer only has to define what kind of actions need to be performed by the input devices. At this point, the devices and DirectX decide how to match them up. This feature takes care of an important task for the developer and also enables new devices to be installed on the machine and used with the software as though the device were made specifically for the program. Figure 11.1 shows the relationship between the action map, the DirectInput class, and the device.
Joystick
FlightStick
Action Map
Main Program
Gamepad
FIGURE 11.1 The action map.
Action map features can be summed up into three main advantages: • Action mapping provides for future device capabilities today. • Action mapping provides multiple device accessibility with very little code. • By using action mapping, more than one device can provide similar commands.
Action Mapping CHAPTER 11
Preparing the Action Map The following sections explain how an action map is initialized for use with an application.
Application Actions The first task in preparing the action map is to define the application actions you’re going to need in your program. You do that by creating an enumeration type. With this enumeration, you can then define all the actions you expect for your application or game. Microsoft uses the convention of eA for an action and eB for a button. This is a good convention for easily identifying actions, so I’ve used it in the following example, which enumerates a flight simulator combat game. Notice that all the actions you need the user to acknowledge are being defined in this enumeration. Enum eCombatGameActions eA_BANK eA_ACCELERATE eB_CHAFE eB_CHANGEVIEW eB_VIEW_COCKPIT eB_VIEW_CHASE eB_VIEW_LEFT eB_VIEW_RIGHT eA_RUDDER eB_RUDDER_RAISE eB_RUDDER_LOWER eB_TOGGLE_LANDINGGEAR eB_EJECT End Enum
‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’ ‘’’
Turn the plane Modify the speed Fire a chafe flare Change the user’s view Change to cockpit view Change to chase view Change to left view Change to right view Manipulate the rudders Raise the rudder Lower the rudder Raise/Lower the landing gear Eject the pilot
To finish creating the enumeration, you need to create a constant defining how many commands you’re allowing. This can be done with the following line that shows the number of commands you are using: Const NUM_COMBAT_ACTIONS = 14 ‘’’ 14 actions available
The Genre Action mapping includes a set of genres that allow you to quickly define a set of virtual devices. By using genres, you can take advantage of DirectInput capabilities that are beneficial to your
11 ACTION MAPPING
It is important to keep in mind that if your application is going into a kiosk or similar venue, you might not need to use action mapping. Game developers should always consider using an action map in their programs. However, if you are not sure about the devices that are going to be used with your program, and you want the benefits that action mapping offers, it is wise to incorporate it into your code.
195
196
Monitoring User Input with DirectInput PART III
specific task. A genre is analogous to an application-type template. Table 11.1 shows all the available genres. TABLE 11.1
Genres and Their Constants
Genre Type
Constant Used
Genre Category
Hand-To-Hand Shooting Third-Person Action Platform Side-to-side 2D Object 3D Model 3D Navigation 3D Object Browser Remote Control Combat Racing Mechanical Fighting Racing Tank Air Combat Civilian Flight Helicopter Combat Space Combat Baseball Batting Baseball Fielding Baseball Pitching Basketball Defense Basketball Offense Fishing Football Defense Football Offense Football Play Football Quarterback
DIVIRTUAL_FIGHTING_HAND2HAND
Action Action Action Arcade Arcade Computer Graphics Computer Graphics Computer Graphics Computer Graphics Control Control Driving Driving Driving Driving Flying Flying Flying Flying Sports Sports Sports Sports Sports Sports Sports Sports Sports Sports
DIVIRTUAL_FIGHTING_FPS DIVIRTUAL_FIGHTING_THIRDPERSON DIVIRTUAL_ARCADE_PLATFORM DIVIRTUAL_ARCADE_SIDE2SIDE DIVIRTUAL_CAD_2DCONTROL DIVIRTUAL_CAD_MODEL DIVIRTUAL_CAD_FLYBY DIVIRTUAL_CAD_3DCONTROL DIVIRTUAL_BROWSER_CONTROL DIVIRTUAL_REMOTE_CONTROL DIVIRTUAL_DRIVING_COMBAT DIVIRTUAL_DRIVING_MECHA DIVIRTUAL_DRIVING_RACE DIVIRTUAL_DRIVING_TANK DIVIRTUAL_FLYING_MILITARY DIVIRTUAL_FLYING_CIVILIAN DIVIRTUAL_FLYING_HELICOPTER DIVIRTUAL_SPACESIM DIVIRTUAL_SPORTS_BASEBALL_BAT DIVIRTUAL_SPORTS_BASEBALL_FIELD DIVIRTUAL_SPORTS_BASEBALL_PITCH DIVIRTUAL_SPORTS_BASKETBALL_DEFENSE DIVIRTUAL_SPORTS_BASKETBALL_OFFENSE DIVIRTUAL_SPORTS_FISHING DIVIRTUAL_SPORTS_FOOTBALL_DEFENSE DIVIRTUAL_SPORTS_FOOTBALL_OFFENSE DIVIRTUAL_SPORTS_FOOTBALL_FIELD DIVIRTUAL_SPORTS_FOOTBALL_QBCK
Action Mapping CHAPTER 11
TABLE 11.1
Continued
197
11 Constant Used
Genre Category
Golf Hockey Defense Hockey Goalie Hockey Offense Hunting Mountain Biking Racquet Skiing Soccer Defense Soccer Offense Role-Playing Turn-Based
DIVIRTUAL_SPORTS_GOLF
Sports Sports Sports Sports Sports Sports Sports Sports Sports Sports Strategy Strategy
DIVIRTUAL_SPORTS_HOCKEY_DEFENSE DIVIRTUAL_SPORTS_HOCKEY_GOALIE DIVIRTUAL_SPORTS_HOCKEY_OFFENSE DIVIRTUAL_SPORTS_HUNTING DIVIRTUAL_SPORTS_BIKING_MOUNTAIN DIVIRTUAL_SPORTS_RACQUET DIVIRTUAL_SPORTS_SKIING DIVIRTUAL_SPORTS_SOCCER_DEFENSE DIVIRTUAL_SPORTS_SOCCER_OFFENSE DIVIRTUAL_STRATEGY_ROLEPLAYING DIVIRTUAL_STRATEGY_TURN
Priorities DirectInput divides controls into two priorities to distinguish them. Priority 1 controls are those that are accessible by the majority of hardware on the market. The priority 2 controls are more likely accessible only by specific controls. For example, an average joystick would probably support all of the priority 1 controls; however, a high-grade flight stick would support both priority 1 and priority 2 controls. In this chapter’s example, you are trying to build a flight simulator. By examining the available genre in Table 11.1, you will notice that four genre are designed for “flying” applications: Air Combat, Civilian Flight, Helicopter Combat, and Space Combat. Because the application you are trying to build is going to be used by people who want to practice their peacetime flying abilities, you should go with the Civilian Flight genre, which uses the constant DIVIRTUAL_FLYING_CIVILIAN to specify its genre. Each of these genres has a set of control constants associated with it. For the flight simulator, you are using the DIVIRTUAL_FLYING_CIVILIAN constant, so you have access to the following controls: Priority 1 Controls DIAXIS_FLYINGC_BANK DIAXIS_FLYINGC_PITCH DIAXIS_FLYINGC_THROTTLE
ACTION MAPPING
Genre Type
198
Monitoring User Input with DirectInput PART III DIBUTTON_FLYINGC_DISPLAY DIBUTTON_FLYINGC_GEAR DIBUTTON_FLYINGC_MENU DIBUTTON_FLYINGC_VIEW
Priority 2 Controls DIAXIS_FLYINGC_BRAKE DIAXIS_FLYINGC_FLAPS DIAXIS_FLYINGC_RUDDER DIBUTTON_FLYINGC_BRAKE_LINK DIBUTTON_FLYINGC_DEVICE DIBUTTON_FLYINGC_FASTER_LINK DIBUTTON_FLYINGC_FLAPSDOWN DIBUTTON_FLYINGC_FLAPSUP DIBUTTON_FLYINGC_GLANCE_DOWN_LINK DIBUTTON_FLYINGC_GLANCE_LEFT_LINK DIBUTTON_FLYINGC_GLANCE_RIGHT_LINK DIBUTTON_FLYINGC_GLANCE_UP_LINK DIBUTTON_FLYINGC_PAUSE DIBUTTON_FLYINGC_SLOWER_LINK DIHATSWITCH_FLYINGC_GLANCE
Assigning Actions to Controls or Device Objects The next step is to associate the application action with all the virtual controls that are defined for the genre you’ve chosen. The term virtual controls means that these controls don’t really exist; they are just conduits to actual controls that are mapped to later. You can think of them as placeholders for real controls. To associate actions with virtual controls, you declare an array of DIACTION types and initialize them for each virtual device, as shown in the following example for the actions “banking” and “throttling”: Dim aGameActions(10) As DIACTION ‘’’ Define the Flight genre With aGameActions (0) .lAppData = eA_BANK .lSemantic = DIAXIS_FLYINGC_BANK .lFlags = 0 .ActionName = “Bank” End With
Action Mapping CHAPTER 11
Defining the Action Map Genre in VB.NET This same code can be used in VB.NET. The following lines show how you would define a flight genre: Dim aGameActions(10) As DxVBLibA.DIACTION ‘’’ Define the Flight genre With aGameActions(0) .lAppData = eA_BANK .lSemantic = DxVBLibA.CONST_DIGENRE.DIAXIS_FLYINGC_BANK .lFlags = 0 .ActionName = “Bank” End With With aGameActions(1) .lAppData = eA_ACCELERATE .lSemantic = DxVBLibA.CONST_DIGENRE.DIAXIS_FLYINGC_THROTTLE .lFlags = 0 .ActionName = “Throttle” End With
You continue this process until you have associated all the virtual controls with real-world controls.
Finding Matching Devices The next step in the process of using action maps is to enumerate your devices so that you can determine which devices are compatible with your virtual controls. Not only do you need to find compatible devices, but you also need to make the best match for the available devices. To do that, you need to pass the DIACTIONFORMAT type to the DirectInput8.GetDevicesBy method. Controls that the user configures to match certain controls get priority over any other control.
Semantics
DirectInput then enumerates all the other controls in order of their possible match with virtual controls. After you have the list of enumerated controls (devices), you can get the default action mapping for all the devices. Finally, you can then change any of the mappings or offer the users the choice of changing their device configurations.
11 ACTION MAPPING
With aGameActions (1) .lAppData = eA_ACCELERATE .lSemantic = DIAXIS_FLYINGC_THROTTLE .lFlags = 0 .ActionName = “Throttle” End With
199
200
Monitoring User Input with DirectInput PART III
Configuring the Action Map After you create each action map, you can configure and apply it. The following sections show how this is done.
Obtaining the Device To obtain the device, you must accomplish these three steps: 1. Obtain the device: Requires that you obtain the device by using the DirectInputEnumDevices8.GetItem method. GetItem obtains an instance of the DirectInputDeviceInstance8 class. 2. Create the device: You then use that instance to call the method GetGuidInstance of the DirectInputDeviceInstance8 class. This step gives you a GUID that you can use with the DirectInput8.CreateDevice method to create the device. Here is an example of how this process works: ‘’’ Dim Dim Dim Dim
Declare the variables you need oDI as DirectInput8 oDID as DirectInputDevice8 oDIGuid as String oDIDIControl as DirectInputDeviceInstance8
‘’’ Retrieve a device instance for enumerated device 1 oDIDIControl = DirectInputEnumDevice8.GetItem(1) ‘’’ Retrieve the GUID for this device instance oDIGuid = oDIDIControl.GetGuidinstance() ‘’’ Create the DirectInputDevice based on the GUID you passed in. oDID = oDI.CreateDevice(oDIGuid)
Creating the Device in VB.NET This same code can be used in VB.NET, as shown in the following lines: ‘’’ Declare the variables you need Dim oDI As DxVBLibA.DirectInput8 Dim oDID As DxVBLibA.DirectInputDevice8 Dim oDIGuid As String Dim oDIDI As DxVBLibA.DirectInputDeviceInstance8 Dim oDIED As DxVBLibA.DirectInputEnumDevices8 ‘’’ Retrieve a device instance for enumerated device 1 oDIDI = oDIED.GetItem(1)
Action Mapping CHAPTER 11
‘’’ Create the DirectInputDevice based on the GUID you passed in. oDID = oDI.CreateDevice(oDIGuid)
3. Get the default action map: The last step is to get the default action map for the device you have acquired in the previous steps. You do that by using the BuildActionMap method of the DirectInputDevice8 class. The first parameter of this method is the DIACTIONFORMAT type, representing the current action map. The BuildActionMap method takes this DIACTIONFORMAT type value and tries to map each virtual control to a physical device object.
The SetActionMap Method is a method of the DirectInputDevice8 class. It makes the connection between the device objects and your application-based actions. A username is used to differentiate this action map from any other action maps that may be available in the program. The following code sample uses the SetActionMap method to map the DIAF action format object to a user named “Bobby”. You also specify that it is a default mapping. SetActionMap
‘’’ Declare the variables you need Dim oDID as DirectInputDevice8 Dim oDIAF as DIACTIONFORMAT ‘’’ Call the SetActionMap method to make the connection ‘’’ between the device(oDID) and the action map(“Bobby”) oDID.SetActionMap oDIAF, “Bobby”, DIDSAM_DEFAULT
Calling the SetActionMap Method in VB.NET The same code can be used in VB.NET, as shown in the following lines: ‘’’ Declare the variables you need Dim oDID as DxVBLibA.DirectInputDevice8 Dim oDIAF as DxVBLibA.DIACTIONFORMAT ‘’’ Call the SetActionMap method to make the connection ‘’’ between the device(oDID) and the action map(“Bobby”) oDID.SetActionMap oDIAF, “Bobby”, DxVBLibA.CONST_DIDSAMFLAGS. _ ➥DIDSAM_DEFAULT
11 ACTION MAPPING
‘’’ Retrieve the GUID for this device instance oDIGuid = oDIDI.GetGuidInstance()
201
202
Monitoring User Input with DirectInput PART III
The ConfigureDevices Method The DirectInput8 class has a unique method called ConfigureDevices, which enables a developer to display a property sheet that shows a visual representation of the device being configured. The device manufacturers create the property sheets and include them on the machine when they install their drivers. By using ConfigureDevices, you can let the user open the property sheet to make custom configurations. Figure 11.2 shows a property sheet for the keyboard.
FIGURE 11.2 The keyboard property sheet.
Figure 11.3 shows a property sheet for a Microsoft SideWinder game pad. This example shows how to display the property sheet and set it for editing: ‘’’ Declare the variables you need Dim oDI as DirectInput8 Dim oCDP As DICONFIGUREDEVICESPARAMS ‘’’ Call the ConfigureDevices method to call ‘’’ the property sheet for editing oDI.ConfigureDevices 0, oCDP, DICD_EDIT
Action Mapping CHAPTER 11
203
11 ACTION MAPPING
FIGURE 11.3 A Microsoft SideWinder game pad property sheet.
Calling the Property Sheet in VB.NET The ConfigureDevices method of the DirectInput class would look like this in VB.NET: ‘’’ Declare the variables you need Dim oDI as DxVBLibA.DirectInput8 Dim oCDP As DxVBLibA.DICONFIGUREDEVICESPARAMS ‘’’ Call the ConfigureDevices method to call ‘’’ the property sheet for editing oDI.ConfigureDevices(0, oCDP, DxVBLibA.CONST_DICDFLAGS. _ ➥DICD_EDIT)
The GetDeviceData Method To get data back from an action-mapped device, you simply need to use the GetDeviceData method of the DirectInputDevice8 class. Simply check the lUserData member of the DIDEVICEOBJECTDATA type that is used within the GetDeviceData method. The lData member of the DIDEVICEOBJECTDATA type contains the device object’s data.
204
Monitoring User Input with DirectInput PART III
Summary Action mapping is the process of intercepting device input from the user and deciding how the application should handle it. This process defines how the input should be mapped by using application actions to define each specific action the program is expecting. It also defines the application’s genre so that DirectX-compatible devices can interpret how they can work with the application. Action mapping gives you the ability to leave the hard work of deciding how to map each expected action to DirectX. It also eliminates the need to worry about what direction the future joystick market might take. You don’t have to worry about it because action mapping will be there to handle it for you. In the next chapter, you will learn about using DirectInput with keyboards, such as detecting when a key is pressed, identifying what the key was, and more.
CHAPTER
The Keyboard
12
IN THIS CHAPTER • Retrieving User Input from the Keyboard 206 • The Keyboard Example • Summary
217
215
206
Monitoring User Input with DirectInput PART III
Before the mouse and joystick became popular in the computer environment, all interaction between users and programs occurred through the keyboard. Games, applications, utilities, and many other programs all understood what the user wanted through the keyboard. The keyboard is still a major part of applications today. Therefore, DirectInput has included keyboard support to accommodate this most widely used computer device.
Retrieving User Input from the Keyboard To use the keyboard in your DirectX applications, you need to begin by creating your DirectInput object. You can then set the keyboard parameters, access the keyboard, and finally retrieve immediate data from the keyboard.
Creating Your Objects To access the input data from the keyboard, you must declare your DirectInput class. After initializing the DirectInput class, you can then access the DirectInputDevice class, which is then associated with your keyboard on the application computer. Begin by creating a DirectX object, a DirectInput object, and a DirectInputDevice object. These three objects are the basis for monitoring keyboard input. The following sample shows how these three objects are created. Note that a default GUID called GUID_SysKeyboard is used in the CreateDevice method to assign the keyboard input to your DirectInputDevice object. ‘’’ Dim Dim Dim
Create your objects oDX As New DirectX8 oDI As DirectInput8 oDID As DirectInputDevice8
‘’’ Initialize your DirectInput object oDI = oDX.DirectInputCreate() ‘’’ Initialize your DirectInputDevice and assign ‘’’ the keyboard to the device. oDID = oDI.CreateDevice(“GUID_SysKeyboard”)
Setting the Keyboard Parameters After you have created the DirectInput object, you must specify the parameters that tell your program you want to look at keyboard input. The first parameter you need to set is the data format, which indicates that you are looking for keyboard input from the user. The second parameter you need to set up is the cooperative level; it defines which application (yours or someone else’s) has exclusive control over all keyboard input.
The Keyboard CHAPTER 12
207
Data Format The data format tells DirectX what type of data will be coming from the DirectInput methods and events. Without this parameter, DirectInput won’t know if it is supposed to be waiting for a mouse, joystick, or keyboard. To make sure the device’s data format is set to the keyboard, use the SetCommonDataFormat method and give it the DIFORMAT_KEYBOARD constant. The following line is an example of how it would work with the ongoing example: oDID.SetCommonDataFormat(DIFORMAT_KEYBOARD)
Cooperative Level
‘’’ Set the cooperative level to NonExclusive and Foreground. oDID.SetCooperativeLevel Me.HWnd, DISCL_NONEXCLUSIVE Or DISCL_FOREGROUND
In the previous sample, NONEXCLUSIVE means this program won’t hold exclusive control over the keyboard input. FOREGROUND means this program will register input only when it’s the topmost (active) window.
NOTE DirectInput does not support the exclusive cooperative level when defining a keyboard device. Therefore, always use DISCL_NONEXCLUSIVE instead of DISCL_EXCLUSIVE.
Accessing the Keyboard Your program needs to acquire the device before it can start receiving data from it. For all DirectInput devices, you use the DirectInputDevice8.Acquire method to acquire access to the device. To use this method, you simply have to write a line of code similar to this: oDID.Acquire
Retrieving Immediate Data from the Keyboard After you have acquired the keyboard device, you need to set up the program to retrieve data as it’s entered. The easiest way to do this is to use the DirectInputDevice8.GetDevice
12 THE KEYBOARD
You must also set the keyboard’s cooperative level to define how the input is received. If you aren’t specific about how input will be handled in your program, there could be problems when other programs are brought into focus while your application is running. (To review settings for cooperative levels, refer to the “Cooperative Levels” section in Chapter 10, “Using DirectInput to Manage User Interactions.”) To do that, you use the SetCooperativeLevel method. The choices for cooperative levels are FOREGROUND or BACKGROUND and EXCLUSIVE or NONEXCLUSIVE. If you want to set the cooperative level to NONEXCLUSIVE and FOREGROUND, for example, you would use the following code:
208
Monitoring User Input with DirectInput PART III
method, which takes a snapshot of the device’s state at the time it’s called. This method looks for immediate data that comes from the DirectInputEvent. This data is produced as soon as the key is pressed on the user’s keyboard, as opposed to being placed in a buffer for pickup at a later time.
StateKeyboard
Interpreting the Keyboard Data DirectInput applications read the keyboard device as individual and specific keystrokes. This behavior is different from the way Windows normally behaves. For example, with DirectInput, the 2 key at the top of the keyboard registers as a DIK_2 constant, and the 2 key on the number pad registers as a DIK_NUMPAD2 constant. In Windows applications that are not using DirectInput, the 2 key on the keyboard and the 2 key on the number pad are both considered to be the same key. It’s important to keep this distinction in mind. If you forget that the DIK_NUMPAD2 key is equivalent to the DIK_2 key in your program, you could have some holes in your input algorithm. Data is retrieved from the keyboard by using one of the following methods: •
This method retrieves immediate data from a nonstandard keyboard, using the following syntax:
GetDeviceState
object.GetDeviceState(cb As Long, state As Any)
A nonstandard keyboard has additional keys, such as e-mail, Web, and other custom buttons. •
This method retrieves buffered data from the keyboard device, using the following syntax: GetDeviceData
object.GetDeviceData( _ deviceObjectDataArray() As DIDEVICEOBJECTDATA, _ flags As CONST_DIDGDDFLAGS) As Long
Buffered data is held in a cache until you want to process it. In most cases, you want to capture each input from the keyboard as soon as it occurs, so you would use immediate data to accomplish that. Sometimes, however, you want to reduce your application’s processing time, meaning you’d check the input only at set times on a regular loop cycle. To do that, you’d use the buffered data mode. For example, a highly graphical application can check the buffered data when it’s ready for an input change, instead of getting messages continually from the immediate mode. This setup helps make the graphic move faster because nothing is interfering with its processing. The following code snippet shows how to declare a DirectInputDevice8 object: Dim oDID As DirectInputDevice8
The Keyboard CHAPTER 12
209
Keyboard Constants DirectInput provides 256 keyboard constants, which reference all the possible keyboard strokes that can be registered on a keyboard. Some of the constant values are the same because in some instances, more than one constant name can be used to identify the same key. Table 12.1 lists all the keyboard constants provided with CONST_DIKEYFLAGS. It also lists their actual values and any specific information about them. TABLE 12.1
CONST_DIKEYFLAGS Constant Values
Value
Note
DIK_0
11 2 3 4 5 6 7 8 9 10 30 115 126 78 40 221 145 150 48 14 43 14 46 161
Main keyboard Main keyboard Main keyboard Main keyboard Main keyboard Main keyboard Main keyboard Main keyboard Main keyboard Main keyboard
DIK_1 DIK_2 DIK_3 DIK_4 DIK_5 DIK_6 DIK_7 DIK_8 DIK_9 DIK_A DIK_ABNT_C1 DIK_ABNT_C2 DIK_ADD DIK_APOSTROPHE DIK_APPS DIK_AT DIK_AX DIK_B DIK_BACK DIK_BACKSLASH DIK_BACKSPACE DIK_C DIK_CALCULATOR
Numeric pad of Brazilian keyboard Numeric pad of Brazilian keyboard + on numeric keypad Application key Japanese keyboard Japanese keyboard Backspace key
THE KEYBOARD
Constant
12
210
Monitoring User Input with DirectInput PART III
TABLE 12.1
Continued
Constant
Value
Note
DIK_CAPITAL
58 58 144 146 51 121 32 83 211 181 208 208 18 207 13 1 33 59 68 87 88 100 101 102 60 61 62 63 64 65 66
Caps Lock key
DIK_CAPSLOCK DIK_CIRCUMFLEX DIK_COLON DIK_COMMA DIK_CONVERT DIK_D DIK_DECIMAL DIK_DELETE DIK_DIVIDE DIK_DOWN DIK_DOWNARROW DIK_E DIK_END DIK_EQUALS DIK_ESCAPE DIK_F DIK_F1 DIK_F10 DIK_F11 DIK_F12 DIK_F13 DIK_F14 DIK_F15 DIK_F2 DIK_F3 DIK_F4 DIK_F5 DIK_F6 DIK_F7 DIK_F8
Japanese keyboard Japanese keyboard Period (decimal point) on numeric keypad Forward slash (/) on numeric keypad Down arrow key
Main keyboard
The Keyboard CHAPTER 12
TABLE 12.1
211
Continued
Value
DIK_F9
67 34 41 35 199 23 210 36 37 112 148 38 56 26 29 203 203 56 42 219 50 236 237 164 12 55 160 235 49 209 153
DIK_G DIK_GRAVE DIK_H DIK_HOME DIK_I DIK_INSERT DIK_J DIK_K DIK_KANA DIK_KANJI DIK_L DIK_LALT DIK_LBRACKET DIK_LCONTROL DIK_LEFT DIK_LARROW DIK_LMENU DIK_LSHIFT DIK_LWIN DIK_M DIK_MAIL DIK_MEDIASELECT DIK_MEDIASTOP DIK_MINUS DIK_MULTIPLY DIK_MUTE DIK_MYCOMPUTER DIK_N DIK_NEXT DIK_NEXTTRACK
Note
Grave accent (`)
12
Japanese keyboard Japanese keyboard
Left square bracket ([) Ctrl key on left-hand side Left arrow key Alt key on left-hand side Shift key on left-hand side Windows key
Main keyboard Asterisk on numeric keypad
Page Down key Next track
THE KEYBOARD
Constant
212
Monitoring User Input with DirectInput PART III
TABLE 12.1
Continued
Constant
Value
Note
DIK_NOCONVERT
Japanese keyboard
DIK_PREVTRACK
123 69 82 79 80 81 75 76 77 71 72 73 179 156 141 74 83 78 181 55 24 86 25 197 52 209 201 162 222 144
DIK_PRIOR
201
DIK_NUMLOCK DIK_NUMPAD0 DIK_NUMPAD1 DIK_NUMPAD2 DIK_NUMPAD3 DIK_NUMPAD4 DIK_NUMPAD5 DIK_NUMPAD6 DIK_NUMPAD7 DIK_NUMPAD8 DIK_NUMPAD9 DIK_NUMPADCOMMA DIK_NUMPADENTER DIK_NUMPADEQUALS DIK_NUMPADMINUS DIK_NUMPADPERIOD DIK_NUMPADPLUS DIK_NUMPADSLASH DIK_NUMPADSTAR DIK_O DIK_OEM_102 DIK_P DIK_PAUSE DIK_PERIOD DIK_PGDN DIK_PGUP DIK_PLAYPAUSE DIK_POWER
Comma on NEC PC98 numeric keypad Numeric keypad (NEC PC98)
British and German keyboards
Previous track; circumflex (^) on Japanese keyboard Page Up key
The Keyboard CHAPTER 12
TABLE 12.1
Continued
Value
DIK_Q
16 19 184 27 157 28 205 205 184 54 220 31 70 39 53 223 57 149 74 183 20 15 22 147 151 200 200 47 174 176 17
DIK_R DIK_RALT DIK_RBRACKET DIK_RCONTROL DIK_RETURN DIK_RIGHT DIK_RIGHTARROW DIK_RMENU DIK_RSHIFT DIK_RWIN DIK_S DIK_SCROLL DIK_SEMICOLON DIK_SLASH DIK_SLEEP DIK_SPACE DIK_STOP DIK_SUBTRACT DIK_SYSRQ DIK_T DIK_TAB DIK_U DIK_UNDERLINE DIK_UNLABELED DIK_UP DIK_UPARROW DIK_V DIK_VOLUMEDOWN DIK_VOLUMEUP
Note
Right square bracket (]) Ctrl key on right-hand side Enter key on main keyboard Right arrow key Alt key on right-hand side Shift key on right-hand side Windows logo key on right-hand side Scroll Lock key Forward slash (/) on main keyboard Spacebar Japanese keyboard Minus sign on numeric keypad
Japanese keyboard Japanese keyboard Up arrow key
12 THE KEYBOARD
Constant
DIK_W
213
214
Monitoring User Input with DirectInput PART III
TABLE 12.1
Continued
Constant
Value
Note
DIK_WAKE
227 234 230 233 178 231 229 232 45 21 125 44
Japanese keyboard Note
DIK_WEBBACK DIK_WEBFAVORITES DIK_WEBFORWARD DIK_WEBHOME DIK_WEBREFRESH DIK_WEBSEARCH DIK_WEBSTOP DIK_X DIK_Y DIK_YEN DIK_Z
Two Methods of Analysis Two methods, explained in the following sections, can be used to analyze the keyboard data that comes back from the keyboard device.
The DirectXEvent Class The DirectXEvent class gives your code a way to be notified every time the user presses a key. During execution, this event fires only if a key is pressed. At all other times, it’s dormant. As a programmer, this class gives you the luxury of having to determine which action to take only when users tell you they are doing something. This class has the following benefits: • Key presses are processed only when they occur, reducing the chance of missing a key press. • This class is also much more processor-independent, so it has a wide range of uses across machines.
The Looping Method Looping is how games were created before the advent of Windows. It works like this: The program loops through its processes over and over until something triggers the game to stop. Each time the loop runs, the program queries the keyboard to see whether anything has changed. Has the user pressed the up key or the down key, for example? If so, then you need to perform a certain task. Because early programs were pretty linear, this looping method worked fine.
The Keyboard CHAPTER 12
215
Nowadays, this process is less desirable for two main reasons: • Cycling through the loop and processing the keyboard device only when the loop gets to it can cause unreliable execution. If the loop misses by a split second, it could result in the key press never getting recognized by the program. This unreliability increases if the machine the program is running on is slower than your test machine. You are basically at the mercy of the machine’s processor speed.
The Keyboard Example Listing 12.1 is a portion of a program, called Keyboard, that uses DirectInput to read data from the keyboard. It then translates this information into commands. It responds to key presses by displaying the key in a pressed-down position on the keyboard image on the screen. The user interface for the Keyboard program is shown in Figure 12.1.
FIGURE 12.1 The Keyboard example.
The complete code for the Keyboard program is at http: //www.samspublishing.com/detail_sams.cfm?item=0672322250.
LISTING 12.1 ‘’’ Dim Dim Dim Dim Dim
The Keyboard Example
Declare your variables oDX As New DirectX8 oDI As DirectInput8 oDIDEV As DirectInputDevice8 oDIState As DIKEYBOARDSTATE iKeyCounter As Integer
‘’’ Implement your event to get the keyboard messages
12 THE KEYBOARD
• The process of analyzing a key press in every loop also wastes processing time, which can result in slow performance. For example, if the user doesn’t hit any keys for a few seconds, it doesn’t matter to the program. It continues to analyze the keyboard whether or not anything has happened on it. This is very wasteful and can slow down your code tremendously.
216
Monitoring User Input with DirectInput PART III
LISTING 12.1
Continued
Implements DirectXEvent8 Dim DXEvent As Long Private Sub DirectXEvent8_DXCallback(ByVal eventid As Long) If oDIDEV Is Nothing Then Exit Sub On Local Error Resume Next ‘’’ Check to see if you still own the keyboard device. ‘’’ If not, then you need to reacquire it. oDIDEV.GetDeviceStateKeyboard oDIState If Err.Number = DIERR_NOTACQUIRED Then oDIDEV.Acquire End If ‘’’ ‘’’ ‘’’ Dim
Parse through all the possiblities and match up the key state By using the &H80 value, you can determine if the key is down (true) or up (false) iKey As Integer
For iKey = 0 To 255 If (oDIState.Key(iKey) And &H80) Then btnKey(iKey).Value = True Else btnKey(iKey).Value = False End If Next iKey DoEvents End Sub Private Sub Form_Load() Set oDI = oDX.DirectInputCreate
➥
‘’’ Any errors yet? If Err.Number 0 Then MsgBox “Error starting DirectX 8. Please check your installation.”, _ vbApplicationModal End End If ‘’’ Create a keyboard device
The Keyboard CHAPTER 12
LISTING 12.1
217
Continued
Set oDIDEV = oDI.CreateDevice(“GUID_SysKeyboard”) ‘’’ Set the Common Data Format to keyboard oDIDEV.SetCommonDataFormat DIFORMAT_KEYBOARD ‘’’ Set the cooperative level to Background and NonExclusive oDIDEV.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE Me.Show
‘’’ You must do this in all DirectX applications with forms.
oDIDEV.Acquire End Sub Private Sub Form_Unload(Cancel As Integer) If DXEvent 0 Then oDX.DestroyEvent (DXEvent) oDIDEV.Unacquire End Sub Private Sub tmrKeyTimer_Timer() ‘’’ You are checking things in a loop, basically every time the timer ‘’’ counts. oDX.SetEvent DXEvent End Sub
Summary Of all the devices on a computer, the keyboard is perhaps the most widely used. It was the first input device used and is still in use today. As you’ve seen in this chapter, not only can DirectInput be used to monitor a keyboard device, but it can also determine the exact key that was pressed. DirectInput gives you the ability to monitor the keyboard, create a device object, set your keyboard parameters, access your new object, and acquire the data from each key press. In the next chapter, you will learn about the joystick and how it has evolved to include the new force feedback models.
12 THE KEYBOARD
‘’’ Create an event object to capture messages about the keyboard DXEvent = oDX.CreateEvent(Me) oDIDEV.SetEventNotification DXEvent
CHAPTER
The Joystick
13
IN THIS CHAPTER • Retrieving User Input from the Joystick • Force Feedback
227
• The Joystick Example • Summary
236
228
220
220
Monitoring User Input with DirectInput PART III
As video games became more popular, many developers began to ask, “How do we make our games more realistic?” From this question came such devices as the joystick, yoke, steering wheel, and other gaming devices for the computer. These devices give users a greater ability to immerse themselves into their favorite games. Because games and similar applications are an important product of DirectX, support for joysticks and their offspring has always been available. Naturally, as joystick devices improve, so does the support from DirectX. In this chapter, you will be learning about one of these improvements: force feedback. To better understand what we are talking about when we say “joystick,” we need to use the term in its broadest sense. A joystick is an input device primarily designed for games. The most common joysticks on the market include flight sticks, game pads, and standard eight-way joysticks.
Retrieving User Input from the Joystick To begin working with joysticks, you need to specify that you want data from DirectInput related to the joystick device on the user’s machine. This process starts with retrieving a DirectInput object. To use the joystick in your DirectX applications, you begin by creating the DirectInput object, and then setting the joystick parameters, accessing the joystick, and finally retrieving immediate data from the joystick. Be warned that these steps might seem very detailed. But don’t worry, as we’re supplying you with all of the details for the first time. It will be much more simple after you try it a few times.
Creating Your Objects To access the input data from the joystick, you must declare your DirectInput class. After the DirectInput class is initialized, you can then access the DirectInputDevice class. This can then be attached to the joystick on the application computer. Begin by creating a DirectX object, DirectInput object, and DirectInputDevice object. These three objects are the basis for monitoring the keyboard input; their relationship is shown in Figure 13.1. The following code sample shows how these three objects are created. Note that a default GUID called GUID_SysKeyboard is used in the CreateDevice method to assign the keyboard input to DirectInputDevice: ‘’’ Dim Dim Dim
Create your objects oDX As New DirectX8 oDI As DirectInput8 oDID As DirectInputDevice8
‘’’ Initialize your DirectInput object oDI = oDX.DirectInputCreate()
The Joystick CHAPTER 13
221
DirectX8
DirectInput8
DirectInputDevice8
FIGURE 13.1 Relationships between DirectX, DirectInput, and DirectInputDevice.
Enumerating Joysticks
To enumerate the joystick devices, you use the GetDIDevices method of DirectInput. By using the two flags DI8DEVCLASS_GAMECTRL and DIEDFL_ATTACHEDONLY, you can tell the GetDIDevices method that you are looking for joysticks (game controllers) that are attached to the system. The following example shows how this is done: Dim oDIEnumDev As DirectInputEnumDevices8 oDIEnumDev = oDI.GetDIDevices(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY)
If the enumeration is successful, you can find out how many devices match your criteria by using the GetCount method of the DirectInputEnumDevices8 class, as shown in this example: If oDIEnumDev.GetCount = 0 Then Msgbox “No joystick devices were found on this machine.” End If
The joystick device does not have a standard GUID to identify to DirectInput what kind of device you’re dealing with, as there are unlimited possibilities for types of joystick devices. Therefore, to determine the GUID, you must use the GetGuidInstance method from the DirectInputDeviceInstance8 object. You then supply this GUID to the DirectInput
13 THE JOYSTICK
For keyboards and mice, you know to expect only one of each. However, you can have more than one joystick, so you can’t simply say, “Give me the joystick device.” Instead, you have to enumerate all the joystick devices and pick the one you want to work with.
222
Monitoring User Input with DirectInput PART III
method, which then creates the DirectInput device. The following example shows how to retrieve the GUID for enumerated device number 1:
CreateDevice
oDID = oDI.CreateDevice(oDIEnumDev.GetItem(1).GetGuidInstance)
Setting the Cooperative Level To define how input is received, you need to set the joystick’s cooperative level by using the SetCooperativeLevel method. The choices for cooperative levels are FOREGROUND or BACKGROUND and EXCLUSIVE or NONEXCLUSIVE. If you wanted to set your cooperative level to EXCLUSIVE and FOREGROUND, you would use the following code line: oDID.SetCooperativeLevel Me.hWnd, DISCL_FOREGROUND Or DISCL_EXCLUSIVE
By setting the previous cooperative level to FOREGROUND, you’re specifying that you will be looking for input from the user’s joystick only when the program is the topmost (active) window. The EXCLUSIVE parameter tells the DirectInputDevice that you want exclusive rights to handle all joystick input, which would exclude any other program on the machine from getting input from the joystick.
Defining the Data Format The final task in initializing your objects is to define the data format. With joysticks, the data format can be either DIFORMAT_JOYSTICK or DIFORMAT_JOYSTICK2. The DIFORMAT_JOYSTICK data format is used for normal joysticks, such as game pads and standard eight-way joysticks. DIFORMAT_JOYSTICK2 signifies complex joysticks with many buttons. The most common example of this type of joystick is a flight stick, such as the ones used with simulator programs. The one you choose to use depends on which type of joystick device is connected to your computer. The following example shows how to use the SetCommonDataFormat method of DirectInput to set the data format of the joystick device: oDID.SetCommonDataFormat DIFORMAT_JOYSTICK
Getting the Joystick Capabilities To use the joystick in your application, you must understand its capabilities. This is easy to do if you know that you’ll always be using one specific model of joystick. In the real world, things are not so easy. To determine the joystick’s capabilities, you must first create a capabilities object for the DirectInputDevice object by using the GetCapabilities method from the DirectInputDevice8 object, as shown in the following code sample: Dim oDIDCaps As DIDEVCAPS oDID.GetCapabilities oDIDCaps
The Joystick CHAPTER 13
223
Setting Joystick Device Properties Before you actually acquire the joystick, it’s important to set all the remaining properties to define how the joystick will be assessed in your application. To set these properties, use a method from the DirectInputDevice8 class called SetProperty. This method and its sister, GetProperty, are explained in the following sections.
The SetProperty Method enables you to access a specific property key by specifying its unique GUID and the value you want to change it to. The most common use of the SetProperty method with joysticks is in defining axis ranges. For an axis on a joystick to function correctly, you need to be able to fine-tune its settings to get the responsiveness you need from your application. SetProperty has the following syntax: SetProperty
object.SetProperty(guid As String, propertyInfo As Any)
For example, the following code sets the specified joystick device to “autocentering on”: Dim oDID as DirectInputDevice8 Dim DIProp As DIPROPLONG
oDID.SetProperty “DIPROP_AUTOCENTER”, DIProp
The SetProperty GUID parameter can accept any of the following flags described in Table 13.1. TABLE 13.1
GUID Flags for SetProperty
GUID Flag
Description
DIPROP_AUTOCENTER
Turns the joystick’s autocentering capabilities on or off. Sets relative or absolute axis mode for the device. Absolute position means the measurements of where the x and y coordinates are in relation to where the joystick started when the device was created. Relative refers to a change in coordinates from the last time the joystick device was checked for position. Applies a buffer size to the whole device. The buffer is where input is stored for processing by your application. This applies only to buffered data, not immediate data.
DIPROP_AXISMODE
DIPROP_BUFFERSIZE
13 THE JOYSTICK
With DIProp .lData = 0 .lHow = DIPH_DEVICE .lObj = 0 End With
224
Monitoring User Input with DirectInput PART III
TABLE 13.1
Continued
GUID Flag
Description
DIPROP_CALIBRATIONMODE
Sets the calibration mode. If the mode is set to cooked, the data should be returned only after it has been calibrated. Raw is the other setting, which means to send uncalibrated data to the application. Cooked refers to calibrated data, meaning the data from the joystick comes from a device that has been calibrated. Sets the dead zone, or center settings, of the joystick (see “Dead Zones” later in this chapter). Sets the minimum and maximum range of values that a device can report to the application. Specifies the saturation zone, in which the device is at its maximum value.
DIPROP_DEADZONE DIPROP_RANGE DIPROP_SATURATION
The GetProperty Method GetProperty,
the sister method to SetProperty, accesses the same information using the same GUIDs listed in Table 13.1; however, it can also find out range information and a few other things. Table 13.2 details these flags and what they do. TABLE 13.2
GetProperty-Specific GUID Flags
GUID Flag
Description
DIPROP_FFGAIN
Retrieves the gain of the device. The value is an integer in the range of 0 to 10,000. A value of 10,000 would represent an unchanged effect magnitude, and 5,000 would represent modifying the specified effect by 50%. Obtains the device’s memory load. This helps determine whether the device is maxed out with memory. Retrieves information on the offsets used when measuring the distance a device has DIPROP_SATURATION traveled.
DIPROP_FFLOAD DIPROP_GRANULARITY
Dead Zones Dead zones are the areas in a joystick’s range of motion that you don’t want to register. This zone is in the center of the joystick. Using a dead zone allows you to ignore those areas of the joystick that could register slight movement when the joystick is barely touched.
The Joystick CHAPTER 13
225
If your application is more sensitive to movement, you might not want to use a dead zone. For example, dead zones typically aren’t used in flight simulators. Because you want the joystick to react just like a real flight stick in a plane, the slightest movement of the device should register with the program. The following code example shows how to set the dead zones of your joystick: ‘’’ Create a DIPROPLONG object to hold your dead zone settings. Dim oDIProp_DeadZone as DIPROPLONG With oDIProp_DeadZone .lData = 500 .lHow = DIPH_BYOFFSET End With ‘’’ With your dead zone settings, let’s apply them to the x-axis offset oDIProp_DeadZone.lObj = DIJOFS_X oDID.SetProperty “DIPROP_DEADZONE”, oDIProp_DeadZone ‘’’ Now for the y-axis oDIProp_DeadZone.lObj = DIJOFS_Y oDID.SetProperty “DIPROP_DEADZONE”, oDIProp_DeadZone
Using the Joystick We’ve spent a lot of time defining what the joystick can and can’t do. Now it’s time to actually acquire the joystick and put it to work. To acquire the joystick, it’s a simple matter of using the Acquire method from the DirectInputDevice8 object. The method looks like this: oDID.Acquire
After the joystick has been acquired, you can then begin looking for data from the joystick.
Handling Joystick Data Data from a joystick can be handled in one of two ways. You can set up a DXCallback method event with the DirectXEvent8 object or you can poll the DirectXInputDevice8 object by using an execution loop. The traditional method has been to use the execution loop, which basically loops through your code. Every time the code gets to your routines for polling, it checks the status of the input device by calling the DirectInputDevice8.Poll method.
THE JOYSTICK
The previous code used a value of 500 in the lData member of the DIPROPLONG type to specify that you want movements on the joystick’s x and y axes to be registered only after the movement passes over 500 units in either direction. Anything below 500 will not be registered as an x or y movement.
13
226
Monitoring User Input with DirectInput PART III
Retrieving Joystick Data Data can be retrieved by using one of two methods. The GetDeviceData method of DirectInputDevice8 retrieves any axis changes or button events that have occurred. The DirectInputDevice8.GetDeviceStateJoystick method uses the DIJOYSTATE type to get information on all the joystick’s device objects.
Analyzing Joystick Data There are two methods you can use to analyze the data that comes back from the joystick device. The first is using events and the second is looping. The DirectXEvent Class Using the DirectXEvent class notifies your code each time users move their joysticks or press a button. During execution, this event fires only if the joystick device reports that something has happened. At all other times, it’s dormant. As a programmer, using events gives you the luxury of having to determine which action to take only when users tell you they are doing something. This class has the following advantages: • Joystick movements and button presses are processed only when they occur, reducing the chance of missing the message. • This process is much more processor-independent, so it has a wide range of uses across machines. Figure 13.2 shows how DirectXEvent works.
Joystick Status Change?
Yes
Process Input
FIGURE 13.2 DirectXEvent
in action.
Looping Before the advent of Windows, looping was the method used to create games. Looping works like this: The program loops through its processes over and over until something triggers the game to stop. Each time the loop runs, the program queries the joystick to see whether anything has changed. Has the user pushed the joystick to the left or right? If so, then you need to perform a specific task. Because early programs were very linear, this process worked fine. Nowadays, this process is less desirable for two main reasons:
The Joystick CHAPTER 13
227
• Cycling through the loop and processing the joystick device only when the loop gets to it can cause unreliable execution. If the loop misses by a split second, it could result in the movement never getting recognized by the program. This unreliability increases if the machine the program is running on is slower than your test machine. You are basically at the mercy of the machine’s processor speed. • The process of analyzing a joystick movement in every loop also wastes processing time, resulting in slow performance. For example, if the user doesn’t hit any buttons for a few seconds, it doesn’t matter to the program. It continues to analyze the joystick device whether or not anything has happened on it. This wasteful processing can slow down your code tremendously. Figure 13.3 shows how looping works.
Program Housekeeping
13 No
Yes
Process Input
FIGURE 13.3 Looping.
For these reasons, it is a better program design to use the DirectXEvent class to analyze joystick data.
Force Feedback One of the greatest advancements in DirectX has been force feedback, which allows the developer to add to the excitement of the game or multimedia application by incorporating physical feedback into the input device. The most familiar force feedback device today is the Microsoft Force Feedback Joystick. It has a small motor inside the device that causes a wide range of vibrations and movements based on commands given through DirectInput.
THE JOYSTICK
Joystick Status Change?
228
Monitoring User Input with DirectInput PART III
For example, if you wanted a user to know that his or her fighter jet had been damaged, you could cause a sharp jerky motion to simulate the impact. To simulate gravity, you could add more resistance to the joystick’s pull. These force-feedback effects can create a much more realistic experience for the user.
Force-Feedback Effects Force-feedback effects are basically the specific types of action you can program for the force feedback device. These effects are categorized into the following four areas: • Condition: This effect is in response to an action that the user takes. The most common condition effect is a joystick returning to the center position after being released. This effect is used with flight simulators, where you would expect the joystick to return to center. • Constant force: This effect produces a steady force (or push) in a single vector (or direction). If an obstacle is in the way of your car in a racing game, you would expect to feel a counter force pushing back from the direction of the obstacle. • Periodic effect: This is a pulsing effect, most widely used for reactions involving intense feedback to the user, such as simulating gun fire recoil or a plane being hit. • Ramp force: This effect produces a steady rise or decrease in force, and can be used to simulate speed increase or decrease in a racing car, for example.
Force Feedback Properties A force feedback effect has three main properties: magnitude, direction, and duration. These three properties combine to control how an effect is produced on the user’s device. • Magnitude: This property indicates the strength of force applied to the effect. The range of magnitude for a force feedback device is 0 to 10,000. • Direction: In the force feedback world, this property specifies the direction of the effect, allowing you to determine exactly where the effect should be directed in response to your code. • Duration: This property defines how long the effect should last. Duration is measured in microseconds.
The Joystick Example To better understand how the joystick device is created and monitored, I’ve included an example in Listing 13.1. In this example, you will be able to move a bee around the window in response to movements on the default joystick attached to the machine. Figure 13.4 shows what the program looks like when compiled.
The Joystick CHAPTER 13
229
FIGURE 13.4 Joystick example.
LISTING 13.1
Code for the Joystick Example
‘***************************************************************************** ‘** ProjectName: Joystick Example ‘** ‘** Description: This program shows how to use DirectInput to gather ‘** information about the joystick attached to this machine. ‘** ‘** Revision History: ‘** ‘** -------------------------------------------------------------------------‘** Date Name Description ‘** 08/17/2001 Keith Sink Creation ‘** -------------------------------------------------------------------------‘***************************************************************************** Option Explicit Implements DirectXEvent8 ‘’’ DirectX and DirectInput core objects Dim oDX As New DirectX8 Dim oDI As DirectInput8
13 THE JOYSTICK
Listing 13.1 is a portion of a program that uses DirectInput to read data from a joystick device. It then translates this information into commands. The comments in the code explain how and why each component and method is being used. The complete code for this example can be found at http://www.samspublishing.com/detail_sams.cfm?item=0672322250.
230
Monitoring User Input with DirectInput PART III
LISTING 13.1
Continued
Dim oDID As DirectInputDevice8 Dim oDIED As DirectInputEnumDevices8 ‘’’ Handler for joystick events Dim EventHandle As Long ‘’’ Capabilities and state of the joystick Dim oDIDC As DIDEVCAPS Dim oDIJS As DIJOYSTATE ‘’’ Dim Dim Dim
Properties oDIProp_Dead As DIPROPLONG oDIProp_Range As DIPROPRANGE oDIProp_Saturation As DIPROPLONG
Dim IsAxisPresent(1 To 2) As Boolean Dim Running As Boolean ‘***************************************************************************** ‘** ObjectName: Init ‘** ‘** Description: This subroutine does the following: ‘** 1. Create the DirectInput object ‘** 2. Enumerate all the devices ‘** 3. Create a DirectInput event ‘** ‘***************************************************************************** Sub Init() ‘’’ Create the DirectInput object Set oDI = oDX.DirectInputCreate() ‘’’ Create an enumerated list of all the joystick devices attached to ‘’’ this machine. Set oDIED = oDI.GetDIDevices(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY) ‘’’ Find out if GetDIDevices found any joysticks attached. If oDIED.GetCount = 0 Then MsgBox “No joystick are attached to the machine.” Unload Me End If
The Joystick CHAPTER 13
LISTING 13.1
231
Continued
‘’’ Create an event handle for this joystick EventHandle = oDX.CreateEvent(Me) Exit Sub Error_Out: MsgBox “There was a problem initializing DirectInput.” Unload Me End Sub Private Sub cmdGetJoystick_Click() GetJoystick End Sub
Dim i As Integer ‘’’ Is there a device created yet? If not, then exit. If oDID Is Nothing Then Exit Sub ‘’’ Retrieve state information about the joystick device On Local Error Resume Next oDID.GetDeviceStateJoystick oDIJS ‘’’ If the device is no longer available or input was lost, then ‘’’ reacquire the device and exit the sub. The next input from the ‘’’ joystick will call this event again. If Err.Number = DIERR_NOTACQUIRED Or Err.Number = DIERR_INPUTLOST Then oDID.Acquire Exit Sub End If
13 THE JOYSTICK
‘***************************************************************************** ‘** ObjectName: DirectXEvent8_DXCallback ‘** ‘** Description: This is the callback function that is called every time an ‘** event occurs in DirectX. This allows you to check the status ‘** of any changes with the joystick, and then react. ‘** ‘***************************************************************************** Private Sub DirectXEvent8_DXCallback(ByVal eventid As Long)
232
Monitoring User Input with DirectInput PART III
LISTING 13.1
Continued
‘’’ Resume normal error handling On Error GoTo err_DXCallBack ‘’’ Check each axis to see if they are available. ‘’’ Then, if the axis is available, move the bee appropriately. For i = 1 To 2 If IsAxisPresent(i) Then Select Case i ‘’’ oDIJS.x = 0 is left ‘’’ oDIJS.x = 5000 is centered ‘’’ oDIJS.x = 10000 is right Case 1 If oDIJS.x < 5000 Then imgBee.Left = imgBee.Left - 50 ElseIf oDIJS.x > 5000 Then imgBee.Left = imgBee.Left + 50 End If Case 2 If oDIJS.y < 5000 Then imgBee.Top = imgBee.Top - 50 ElseIf oDIJS.y > 5000 Then imgBee.Top = imgBee.Top + 50 End If End Select End If Next Exit Sub err_DXCallBack: MsgBox Err.Description & “ : “ & Err.Number, vbApplicationModal End End Sub
Private Sub Form_Load() Running = True Init End Sub
Private Sub Form_Unload(cancel As Integer)
The Joystick CHAPTER 13
LISTING 13.1
233
Continued
On Local Error Resume Next ‘’’ You need to remove the event handling, since you are shutting down. If EventHandle 0 Then oDX.DestroyEvent EventHandle ‘’’ Turn off the boolean loop value Running = False ‘’’ Remove the handle to the device, if it still exists If Not oDID Is Nothing Then oDID.Unacquire End If DoEvents End End Sub
‘’’ This is good to use to make sure tasks are done in DirectX
On Local Error Resume Next ‘’’ Drop any current devices If Not oDID Is Nothing Then oDID.Unacquire End If ‘’’ Create the DirectInput joystick devices, and retrieve the first joystick Set oDID = Nothing Set oDID = oDI.CreateDevice(oDIED.GetItem(1).GetGuidInstance) oDID.SetCommonDataFormat DIFORMAT_JOYSTICK oDID.SetCooperativeLevel Me.hWnd, DISCL_BACKGROUND Or DISCL_NONEXCLUSIVE
13 THE JOYSTICK
‘***************************************************************************** ‘** ObjectName: GetJoystick ‘** ‘** Description: This subroutine is responsible for creating a ‘** DirectInputDevice, getting its capabilities, turning on the ‘** event handler, and setting up the dead zone, range, and ‘** saturation. ‘** ‘***************************************************************************** Private Sub GetJoystick()
234
Monitoring User Input with DirectInput PART III
LISTING 13.1
Continued
‘’’ Get the capabilities of this device oDID.GetCapabilities oDIDC ‘’’ Find out what axes this device uses GetAxes oDID ‘’’ Ask for notification of events Call oDID.SetEventNotification(EventHandle) ‘’’ Set the dead zone With oDIProp_Dead .lData = 1000 .lHow = DIPH_BYOFFSET .lObj = DIJOFS_X oDID.SetProperty “DIPROP_DEADZONE”, oDIProp_Dead .lObj = DIJOFS_Y oDID.SetProperty “DIPROP_DEADZONE”, oDIProp_Dead End With ‘’’ Set the saturation zones With oDIProp_Saturation .lData = 9500 .lHow = DIPH_BYOFFSET .lObj = DIJOFS_X oDID.SetProperty “DIPROP_SATURATION”, oDIProp_Saturation .lObj = DIJOFS_Y oDID.SetProperty “DIPROP_SATURATION”, oDIProp_Saturation End With On Local Error Resume Next ‘’’ Set the range for all axes With oDIProp_Range .lHow = DIPH_DEVICE .lMin = 0 .lMax = 10000 End With oDID.SetProperty “DIPROP_RANGE”, oDIProp_Range
The Joystick CHAPTER 13
LISTING 13.1
235
Continued
‘’’ Acquire the device. oDID.Acquire ‘’’ Calling the callback event is not required but it helps ‘’’ with USB joysticks. DirectXEvent8_DXCallback 0 ‘’’ Poll the device While Running = True DoEvents oDID.Poll Wend End Sub
Dim oDIEDO As DirectInputEnumDeviceObjects Dim oDIDOI As DirectInputDeviceObjectInstance Dim i As Integer For i = 1 To 2 IsAxisPresent(i) = False Next ‘’’ Find out all the available axes Set oDIEDO = oDID.GetDeviceObjectsEnum(DIDFT_AXIS) ‘’’ Check data offset of each axis Dim sGuid As String For i = 1 To oDIEDO.GetCount Set oDIDOI = oDIEDO.GetItem(i)
13 THE JOYSTICK
‘***************************************************************************** ‘** ObjectName: GetAxes ‘** ‘** Description: This subroutine is responsible for creating a ‘** DirectInputDevice, getting its capabilities, turning on the ‘** event handler, and setting up the dead zone, range, and saturation; ‘** ‘***************************************************************************** Sub GetAxes(oDID As DirectInputDevice8)
236
Monitoring User Input with DirectInput PART III
LISTING 13.1
Continued
‘’’ Get the GUID name of this device object instance sGuid = oDIDOI.GetGuidType Select Case sGuid Case “GUID_XAxis” IsAxisPresent(1) = True Case “GUID_YAxis” IsAxisPresent(2) = True End Select Next End Sub
Summary The joystick device is the latest invention for computer input devices. It includes a large array of devices, including steering wheels, flight sticks, yokes, and joysticks. Its wide acceptance in the game and multimedia market has encouraged Microsoft to dedicate a portion of DirectInput to its use. DirectInput not only offers standard input handling for joystick devices, but also adds the new functionality of force feedback. With force feedback, users can now experience the thrill of physical responses through their joystick devices. In the next chapter, you will learn how to use and set up a mouse device to work with DirectX.
CHAPTER
The Mouse
14
IN THIS CHAPTER • Retrieving User Input from the Mouse • Considerations for DirectInput Use of the Mouse 240 • Immediate Data • Summary
244
244
238
238
Monitoring User Input with DirectInput PART III
Contrary to popular belief, the mouse has been around for a long time. The mouse first made its debut in 1968 at the Fall Joint Computer Conference in San Francisco, CA, where Douglas C. Engelbart introduced it to the world. It was not until years later that the mouse became an integral part of the modern computing environment with its incorporation into the Apple Macintosh and Windows operating systems. Today, the mouse is a standard input device for all personal computers. People use the mouse every day to navigate software programs, manipulate objects, and draw some of the finest computer art. The mouse has also spawned many other devices, such as trackballs and laptop pointers that use virtually the same technology.
Retrieving User Input from the Mouse To use the mouse in your DirectX applications, you need to begin by creating your DirectInput object. Then, you set the mouse parameters, access the mouse, and finally retrieve immediate data from the mouse. The mouse is made up of three axes and a maximum of eight buttons. The three axes are labeled X, Y, and Z. The X axis goes from left to right horizontally. The Y axis is the vertical axis that goes from top to bottom. The Z axis refers to the wheel control in the middle of many mice.
Creating Your Objects To access the input data from the mouse, you must declare your DirectInput class. After initializing the DirectInput class, you can then access the DirectInputDevice class, which can then be associated with your mouse on the application computer. Begin by creating a DirectX object, DirectInput object, and DirectInputDevice object. These three objects are the basis for monitoring the mouse input. The following code sample shows how these three objects are created. Note that the code uses a default GUID called GUID_SysMouse in the CreateDevice method to assign the mouse input to your DirectInputDevice object. ‘’’ Dim Dim Dim
Create your objects oDX As New DirectX8 oDI As DirectInput8 oDID As DirectInputDevice8
‘’’ Initialize your DirectInput object oDI = oDX.DirectInputCreate() ‘’’ Initialize your DirectInputDevice and assign ‘’’ the mouse to the device. oDID = oDI.CreateDevice(“GUID_SysMouse”)
The Mouse CHAPTER 14
239
Setting the Buffer Size Next, you need to establish a buffer to receive data from the mouse device. To do this, use the DirectInputDevice8.SetProperty method. You also need to use a DIPROPLONG data type to hold the property values you want to set. If you might want to check the mouse input only at certain times in your application, you use a buffer to hold all the mouse input to enable you to choose when to check for the latest mouse movement data. If you don’t use a buffer to store data, all mouse movements will be lost to your application, and you won’t have any idea what the user has been doing. The following example shows how to declare and use the DIPROPLONG data type and the SetProperty method to set the buffer size: ‘’’ Constants Const mBUFFERSIZE = 256 ‘’’ Declare your DirectX objects Dim DID as DirectInputDevice Dim DIP As DIPROPLONG ‘’’ Set the properties with DIP .lHow = DIPH_DEVICE .lObj = 0 .lData = mBUFFERSIZE end with DID.SetProperty “DIPROP_BUFFERSIZE”, diProp
NOTE
Event Notification The mouse is not like other devices in that you don’t want to poll the mouse in a loop to find out whether it wants you to do anything. The better approach is to wait for the mouse to tell you that it needs information. To do that, you use event notifications. This process puts all the responsibility on the mouse and leaves the application code to react only when it’s necessary to do so. To set up event notifications, you need to create a DirectX event.
14 THE MOUSE
A buffer size can be any value larger than 0. This value denotes how much data the buffer will hold before overwriting older mouse data. The buffer should be big enough to hold the mouse messages coming into your application. A good rule of thumb is to set this value to 256.
240
Monitoring User Input with DirectInput PART III
Creating the Event To monitor the DirectX mouse device, you need to monitor the event from the device. Because you have set it to exclusive mode, you need to get a DirectX event for the form you’re going to work with in your application. In the following code example, the VB .NET form is called frmMain. ‘’’ Create the handle variable Dim lEventHandle as long ‘’’ Create an event for the frmMain form ‘’’ and assign the new event to the handle lEventHandle = DX.CreateEvent frmMain
Setting the Event Notification Using the lEventHandle you just created, you can then assign it to the DirectInputDevice object by using the SetEventNotification method. The following code shows how to do this: DID.SetEventNotification lEventHandle
Implementing the Event After creating the event and specifying that the event should notify the form of any changes, you need to implement the event. This procedure is basically like creating a new event that did not exist in your form by default. You can then add code to this event in your application and respond appropriately every time something occurs with the mouse. To do this, you use the Implements keyword. The following code shows how to implement the DirectX event: Implements DirectXEvent8
Considerations for DirectInput Use of the Mouse There are a few issues to consider when using DirectInput to manage the mouse device: • DirectInput does not show the mouse icon onscreen when managing the mouse device. You must provide code to turn on the mouse cursor if needed. • If the user switches to another application via the keyboard, your application must reacquire the mouse device. • Menus are not accessible because the mouse cursor is disabled. You must enable the cursor to access these items. Some DirectX programmers don’t even use the DirectInput class to manage the mouse. Instead, they use the built-in VB .NET mouse events. This method works great except that the mouse icon is still on the screen. To alleviate this annoyance, they use a Windows API call to hide the icon.
The Mouse CHAPTER 14
241
The mouse device can be reacquired by using the Acquire method of DirectInputDevice8. The syntax is as follows: DirectInputDevice8.Acquire()
When using a menu item, you can release the mouse from DirectInput by using the DirectInputDevice8 method Unacquire. This is the syntax for using the method: DirectInputDevice8.Unacquire()
By checking the form’s Form_MouseMove event, you can then reacquire the device when the user is finished.
Retrieving the Mouse Data Every time a DirectInput device event occurs, the DirectX event you created for your form is called. This event then processes the input and makes decisions about what to do. The data submitted to the event comes in the form of buffered data. To interpret the data, the first thing you need to do is to create a buffer variable of the same size as the one you created earlier with SetProperty. The following code shows how to do that: Dim oDIDOD(1 To mBUFFERSIZE) As DIDEVICEOBJECTDATA
The GetDeviceData Method The GetDeviceData method retrieves all the buffered data at once. You then take that chunk of data and parse through it to make decisions. GetDeviceData is used as shown here: Dim iItems As Integer ‘’’ Stores number of data elements Dim DDID(1 To BufferSize) As DIDEVICEOBJECTDATA ‘’’ Stores an array of data iItems = oDID.GetDeviceData(DDID, 0)
The DIDEVICEOBJECTDATA variable that you declared now holds all the device data in an array format that you can parse through now because you know how many element arrays there are.
If the mouse device is lost, an event will be called. If this happens, the GetDeviceData method is subsequently called and an error is reported because the device no longer exists. Therefore, it’s a good idea to check for this error and handle it. Otherwise, your application could have problems if someone decides to Alt+Tab out of it.
Analyzing the DIDEVICEOBJECTDATA Variable The DIDEVICEOBJECTDATA variable you declared earlier contains a lot of information about every action that occurred since the last DirectXEvent was called. Each element in this object
THE MOUSE
CAUTION
14
242
Monitoring User Input with DirectInput PART III
contains member objects that provide additional data. The following code snippet shows how to cycle through this data and check for the left and right coordinate changes: Dim i As Integer Static OldSequence As Long ‘’’ Process each message For iCount = 1 To IItems Select Case DDID(iCount).lOfs Case DIMOFS_X g_cursorx = g_cursorx + DDID(iCount).lData * g_Sensitivity If OldSequence DDID(iCount).lSequence Then UpdateCursor OldSequence = DDID(iCount).lSequence Else OldSequence = 0 End If Case DIMOFS_Y g_cursory = g_cursory + DDID(iCount).lData * g_Sensitivity If OldSequence DDID(iCount).lSequence Then UpdateCursor OldSequence = DDID(iCount).lSequence Else OldSequence = 0 End If ‘’’ You can also add cases to this loop to handle the left mouse button ‘’’ (DIMOFS_BUTTON0) and right mouse button (DIMOFS_BUTTON1) End Select Next iCount
The lOfs Member The lOfs member gives you information about which button or axis of the mouse was pressed or used. To use this information, you need to compare the lOfs member with the constants for the mouse device. Table 14.1 shows the constants that relate to the mouse device. TABLE 14.1
Mouse Button and Axis Constants
Constant
Value
Type
DIMOFS_BUTTON0
12 13 14
Button Button Button
DIMOFS_BUTTON1 DIMOFS_BUTTON2
The Mouse CHAPTER 14
TABLE 14.1
243
Continued
Constant
Value
Type
DIMOFS_BUTTON3
15 16 17 18 19 0 4 8
Button Button Button Button Button Axis Axis Axis
DIMOFS_BUTTON4 DIMOFS_BUTTON5 DIMOFS_BUTTON6 DIMOFS_BUTTON7 DIMOFS_X DIMOFS_Y DIMOFS_Z
In this table are a few items of special note. The DIMOFS_Z axis refers to the movement of the wheel in the center of the mouse. DIMOFS_BUTTON3 refers to the wheel when it has been pressed.
The lData Member The lData member supplies specific data related to a button or axis. The following example shows how to check element 3 of the mouse device data: ‘’’ Check the lOfs member for Y axis movement if DDID(3).lOfs = DIMOFS_Y then ‘’’ Update the cursor location by checking the lData member lCursorLocation_Y = lCursorLocation_Y + DDID(3).lData end if
To determine whether a button was pressed, you need to compare the lData member of the element to &H80, as shown in this example:
represents the value of a button in the down position. If the current value from the lData member and the &H80 value are the same, you know that the button has been pressed.
&H80
THE MOUSE
‘’’ Check the lOfs member for Button 0 if DDID(4).lOfs = DIMOFS_ BUTTON0 then If diDeviceData(i).lData And &H80 Then bMouseDown = True Else bMouseDown = False End If End if
14
244
Monitoring User Input with DirectInput PART III
The lSequence Member The lSequence member can be used to determine in what order the specified events occurred in the buffer. When a diagonal movement is registered with the events, it registers as both an X and a Y offset value. Because both of them occurred at the same time, they have the same lSequence value. Therefore, it’s a good idea to check the sequence value to determine whether it’s the same as the previous one. If it is, you should calculate the new position based on both values.
Immediate Data When dealing with the mouse, you can retrieve immediate data by polling the mouse. This is the process of looping through your code and checking the state of the mouse periodically. Every time you reach a point in the code when you want to find out what is going on with the mouse, you simply call the GetDeviceStateMouse or GetDeviceStateMouse2 methods of the DirectInputDevice8 class. In applications that need quick responses, such as game simulators, the immediate mode is a good choice. However, in other programs such as those for drawing, the buffer is a better choice.
Summary The mouse is one of the foundations of the modern computer. Through DirectInput, you can monitor the buttons and axes of a mouse input device. Mouse data can be retrieved in a buffered or immediate format. Buffered data is submitted every time the mouse device creates an event. Immediate data is evaluated periodically, as you want to know the information. In Part IV, “Adding Music and Sounds with DirectAudio,” you will learn about DirectAudio. The first chapter of that section covers the basics of DirectAudio and how DirectSound and DirectMusic can be used to create great audio in your applications.
Adding Music and Sounds with DirectAudio
Music and sound are an integral part of any multimedia application. This section focuses on these two components of DirectAudio. DirectAudio is discussed with respect to composing music, playing audio and sound files, and incorporating sound effects in your application.
IN THIS PART 15 DirectX Audio—DirectMusic and DirectSound 247 16 Composing Music
257
17 Adding Sounds to Your Application with DirectSound 271
PART
IV
DirectX Audio—DirectMusic and DirectSound
IN THIS CHAPTER • What Is DirectMusic?
248
• What Is DirectSound?
250
• When Should I Use DirectSound Versus DirectMusic? 256 • Summary
256
CHAPTER
15
248
Adding Music and Sounds with DirectAudio PART IV
DirectX Audio is the collection of components in DirectX that gives you the ability to create music and sound effects for any application. These libraries include support for musical instruments, sound effects, and much more. They also enable you to provide asynchronous audio playback, meaning that sound playback will not interfere with other processes running in your program. In this chapter, you will learn about the DirectMusic and DirectSound architecture and the classes that compose these two components. Finally, you will learn when you should use one over the other.
What Is DirectMusic? DirectMusic is the musical aspect of DirectX Audio. It’s responsible for loading and playing music and sound from different sources. DirectMusic can load a MIDI file, a wave file (WAV), or a segment file created in DirectMusic Producer. DirectMusic Producer is detailed in Chapter 16, “Composing Music.”
DirectMusic Architectural Overview The DirectMusic architecture is composed of nine main objects that are grouped based on their functionality. Figure 15.1 shows these components and their relationships. DirectMusicAudioPath8
DirectMusicBand8
DirectMusicComposer8
DirectMusicInstrument8
DirectMusic
DirectMusicLoader8
DirectMusicPerformance8
DirectMusic Segment objects DirectMusicSegment8 DirectMusicSegmentState8
DirectMusicStyle8
FIGURE 15.1 The DirectMusic architecture.
DirectX Audio—DirectMusic and DirectSound CHAPTER 15
249
DirectMusic Classes The nine main objects in DirectMusic maintain specific parts of the DirectMusic class. Table 15.1 lists these objects and their corresponding classes. TABLE 15.1
The DirectMusic Classes
Object
Class Name
AudioPath
DirectMusicAudioPath8
Band
DirectMusicBand8
Composer
DirectMusicComposer8
Instrument
DirectMusicInstrument8
Loader
DirectMusicLoader8
Performance
DirectMusicPerformance8
Segment
DirectMusicSegment8
SegmentState
DirectMusicSegmentState8
Style
DirectMusicStyle8
The AudioPath Object An audiopath is considered the path for music to be loaded into. It’s a logical path, representing memory that holds a segment of music. An AudioPath object can be created for each type of music or sound used in the application. For example, if you would like to include a musical score and sound effects at the same time, you would need to create two audiopaths: one for the sound effects and one for the music.
The Band Object A band is a collection of instruments used in a piece of music. Each Band object contains performance parameters that define how it can be used in the music it’s associated with. A band can have any of the following parameters: • Instrument: Represents the MIDI instrument that plays the music. • DLS (Downloadable Sounds) collection: Represents a set of downloadable sounds that can then be used to create a MIDI instrument. • Volume: Controls the volume of the band. • Transposition: Refers to transposing (or moving notes up or down on a scale).
DIRECTX AUDIO
• Pan: Specifies the relative volume between the right and left speakers.
15
250
Adding Music and Sounds with DirectAudio PART IV
The Composer Object A Composer object can be used to create a new segment of music or provide a transition between two musical segments. It can also change the chordmap of an existing segment. A chordmap is a mapping of chord progressions, the process of moving harmoniously from one chord to another. A chordmap, therefore, moves the notes that are being played back, up, and down various chords based on its own instructions.
The Instrument Object As its name implies, the Instrument object defines what the music should sound like for each musical instrument being applied.
The Loader Object The Loader object is used for loading all music objects into the DirectX application. By creating a Loader object, you can then gain access to bands, chordmaps, segments, and styles.
The Performance Object The Performance object wraps all the musical components together. It manages segments by controlling their playback, audiopaths, and all messages associated with the music. Performance messages contain information about timing and data routing.
The Segment Object Segments are portions of the performance that provide the musical undertones. The primary Segment object supplies the main musical theme, and the secondary Segment objects provide supporting music and sound effects that highlight the musical effect. Each time a Segment is played, a segment state object is also created. The SegmentState object can be used to get information about the audiopath and playback status.
The Style Object The Style object is a compilation of patterns and instruments that can be used to create a musical score. A style contains one or more bands, a tempo, and the time signature of a performance. The Style object can be compared to a style of music, such as jazz, reggae, or rock.
What Is DirectSound? DirectSound is the other part of DirectAudio. It produces quicker performance than DirectMusic does, and is specifically designed for shorter pieces of audio data. DirectSound’s main advantage is its speed and its 3D audio effects.
DirectX Audio—DirectMusic and DirectSound CHAPTER 15
251
DirectSound Architectural Overview The DirectSound architecture is made up of 16 main objects that are grouped based on their functionality. Figure 15.2 shows these components and their relationships.
DirectSound 3D objects DirectSound3DBuffer8 DirectSound3DListener8
DirectSound Enumerator DirectSoundEnum8
DirectSound Capture objects DirectSoundCapture8 DirectSoundCaptureBuffer8
DirectSound Capture objects DirectSound
DirectSoundCapture8 DirectSoundCaptureBuffer8
DirectSound FX objects DirectSoundFXChorus8 DirectSoundFXCompressor8 DirectSoundFXDistortion8 DirectSoundFXEcho8 DirectSoundFXFlanger8 DirectSoundFXGargle8 DirectSoundFX13DL2Reverb8 DirectSoundFXParamEq8 DirectSoundFXWavesReverb8
DirectSound Buffers DirectSoundPrimaryBuffer8 DirectSoundSecondaryBuffer8
FIGURE 15.2 The DirectSound architecture.
15 DIRECTX AUDIO
252
Adding Music and Sounds with DirectAudio PART IV
DirectSound Classes The 16 main DirectSound objects, described in Table 15.2, maintain specific parts of the DirectSound class. TABLE 15.2
The DirectSound Classes
Object
Class Name
3DBuffer
DirectSound3DBuffer8
3DListener
DirectSound3DListener8
Capture
DirectSoundCapture8
CaptureBuffer
DirectSoundCaptureBuffer8
Enum
DirectSoundEnum8
FXChorus
DirectSoundFXChorus8
FXCompressor
DirectSoundFXCompressor8
FXDistortion
DirectSoundFXDistortion8
FXEcho
DirectSoundFXEcho8
FXFlanger
DirectSoundFXFlanger8
FXGargle
DirectSoundFXGargle8
(interactive 3D audio level 2 reverberation effect) FXParamEq (parametric equalizer effect)
DirectSoundFXI3DL2Reverb8
FXWavesReverb
DirectSoundFXWavesReverb8
PrimaryBuffer
DirectSoundPrimaryBuffer8
SecondaryBuffer
DirectSoundSecondaryBuffer8
FXI3DL2Reverb
DirectSoundFXParamEq8
The 3DBuffer Object The DirectSound 3DBuffer object represents the sound buffer in a 3D sound environment, which is like the “surround sound” we’re familiar with in high-tech movie theaters. The DirectSound 3D buffer controls such items as the distance, position, and velocity settings.
The 3DListener Object The 3DListener object represents the recipient of the 3D Sound buffer. It has many of the same settings as 3DBuffer, including distance, position, and velocity.
The Capture Object The Capture object is used to determine the capabilities of the capture device in use. It also creates CaptureBuffer objects to hold the captured sound. A prime example of a common capture device is a microphone.
DirectX Audio—DirectMusic and DirectSound CHAPTER 15
253
The CaptureBuffer Object The CaptureBuffer object represents a buffer used to capture sounds from wave (WAV) files. The Enum Object The Enum object is used to enumerate the DirectSound-compatible objects on the user’s machine. Enumeration gives you a list of all the DirectSound audio devices on the machine.
Objects for Sound Effects DirectSound uses effects (abbreviated FX) to modify the sound and produce certain changes. You can use these effects to change a sound into a completely different audio experience.
The FXChorus Object The FXChorus object can be applied to the sound buffer you are working with. This effect gives the illusion of a chorus by doubling the voice and playing the second voice a split second later than the first.
The FXCompression Object As an audio signal reaches a predefined amplitude, the compression effect begins to compress the wave. The FXDistortion Object The FXDistortion object creates a distortion effect in which the high levels are clipped off.
The FXEcho Object The FXEcho object produces a delay effect on the primary sound, thus giving the illusion of an echo.
The FXFlanger Object The FXFlanger object produces an effect similar to the echo, creating a sound that is slightly off from the primary sound. However, the time difference in the two sounds is much smaller than in the echo effect.
The FXGargle Object The FXGargle object changes the amplitude of the audio signal by modifying the sound’s hertz and wave shape. It creates an effect similar to that of someone gargling.
The FXI3DL2Reverb object uses the Interactive 3D Audio Level 2 approved standards for a reverberation effect.
15 DIRECTX AUDIO
The FXI3DL2Reverb Object
254
Adding Music and Sounds with DirectAudio PART IV
The FXParamEq Object A parametric equalizer simulates the effect of using a hardware equalizer on the audio stream. Tones can be modified by adjusting the bandwidth, center, and gain on the audio stream.
The FXWavesReverb Object The FXWaves object produces an effect based on the Waves MaxxVerb technology and is intended primarily for musical sounds.
Sound Buffers Buffers are used to hold audio data for processing and playback. While it’s in a buffer, sound data can be manipulated to produce new sounds.
The PrimaryBuffer Object The primary buffer is the canvas on which the final audio output is assembled. Secondary buffers are placed and mixed on the primary buffer, until you achieve the audio output you want.
The SecondaryBuffer Object The secondary buffer manages a sound or audio segment. It is assembled with other secondary buffers to form a completed primary buffer.
DirectSound 3D DirectSound 3D is made up of many objects that help define its location, speed, direction, and playback.
Cones Cones are areas of sound that include an inner cone and an outer cone. When listeners pass the inner cone, they hear the full sound. The outer cone surrounds this area and handles the transition from no sound to the full sound in the inner cone. As a listener passes the outer cone barrier, he begins to hear sound that gets louder as he approaches the inner cone. Creating an effective sound cone can add a lot of realistic effects to a scene. For example, you can have noise coming from a doorway as a person passes by it. As she approaches the edge of the doorway, she is entering the outer cone. When she reaches the doorway’s opening, she is in the inner cone. Figure 15.3 shows the cones in DirectSound 3D.
DirectX Audio—DirectMusic and DirectSound CHAPTER 15
255
Sound Source
No Sound
Softer
Loud
Outer Cone
Inner Cone
FIGURE 15.3 Inner and outer cones in DirectSound 3D.
Velocity The velocity of a sound buffer has to do with the Doppler effect—in other words, the frequency of the sound increasing as you approach its source and decreasing as you leave the source (see the “Doppler Effect” section later in this chapter). Velocity, measured in meters per second, measures how fast the listener is moving during the Doppler effect.
Position Position is expressed as a vector (a combination of magnitude and direction) relative to world space or the listener, depending on the processing mode. Positions are defined with x, y, and z coordinates. For example, you could have a position that is always in the user’s left ear, such as a bird that follows the person around. Or you could place the sound in a water fountain, and as the user approaches the fountain, the sound would become louder.
Operation Mode DirectSound 3D’s operation mode specifies whether it’s turned on or off. If the operation mode is set to DS3DMODE_DISABLE, it’s disabled from the listener’s point of view. DS3DMODE_HEADRELATIVE is used if you want all DirectSound 3D calculations to be performed from the point of view of the listener’s head. DS3DMODE_NORMAL can be used to set the parameters in relation to world space.
15 DIRECTX AUDIO
256
Adding Music and Sounds with DirectAudio PART IV
Direction Direction, of course, defines the direction in which the sound will travel, either away from the listener or toward the listener.
Doppler Effect The Doppler effect is a physics principle stating that as you get closer to a sound, the distance the sound has to travel decreases. This effect is supported automatically in DirectSound 3D. You can change the Doppler effect by adjusting its factor value.
Orientation (Listener Orientation) Orientation refers to the direction in which the listener object (the user) is facing. If listeners are facing away from the 3D sound, they might not hear the sound as clearly as if they were facing the sound directly.
Roll Off Factor The roll off factor defines how much quieter the sound becomes as the listener gets farther from the source. For example, sound doesn’t travel as far through a fog, so you would want to increase the roll off factor to muffle the sounds more than you would on a normal sunny day.
When Should I Use DirectSound Versus DirectMusic? For development, it is advisable to use DirectSound when you need faster response times, such as creating sounds that provide audio feedback to the user. An example of this use is the punching sounds you hear when a character gets hit in a game. Conversely, DirectMusic should be used when you are playing an audio track of any type. DirectMusic can also play sound files as DirectSound does, but it’s a little slower because of its added features’ overhead. Therefore, avoid using DirectMusic unless you are using it for speeches or background music.
Summary In this chapter, you have taken a look at the different objects that make up the DirectAudio components. You have also learned about DirectMusic’s musical capabilities and DirectSound’s sound capabilities. In addition, you’ve seen the effects available in DirectSound to enhance the audio you are using. Finally, you’ve reviewed some reasons for using the DirectSound architecture instead of DirectMusic. In the next chapter, you will learn about DirectMusic and the loader, performance, segment, audio parameter structure, and band objects.
CHAPTER
Composing Music
16
IN THIS CHAPTER • The Loader Object
258
• The Performance Object • The Segment Object
259
263
• The Audio Parameter Structure • The Band Object
265
• Modifying the Performance • A DirectMusic Example • DirectMusic Producer • Summary
269
264
266 268
265
258
Adding Music and Sounds with DirectAudio PART IV
As discussed Chapter 15, “DirectX Audio—DirectMusic and DirectSound,” DirectMusic is the object library of DirectX designed to give you high-end music playback capabilities for your DirectX applications. Before you begin using DirectMusic, you need to look at its components. To create a DirectMusic session, you need a minimum of four elements: a DirectMusic Loader object, a DirectMusic Performance object, a DirectMusic Segment object, and a DirectMusic audio parameter structure. With these four objects and a small amount of code, you can add professional-grade music to any of your applications. This chapter will focus on DirectMusic and how to use it in your applications. You’ll also see an example of how each part of the DirectMusic performance is assembled and used.
The Loader Object You use the DirectMusic Loader object to retrieve the data file of the music you want to play. It provides methods that can load bands, chords, Downloadable Sounds (DLS) collections, segments, and styles. DLS is a MIDI standard that provides a mechanism for creating synthesized sound from predefined audio sources.
Using the DirectMusic Loader Object The following code sample shows how to declare the DirectMusicLoader8 object: Private oDML As DirectMusicLoader8
Table 16.1 describes all the methods available to the DirectMusicLoader8 object. TABLE 16.1
The DirectMusicLoader8 Methods
Method
Description
LoadBand
Searches the current directory or the directory supplied by the SetSearchDirectory method for a band file to load. Loads band data from a resource. Searches the current directory or the directory supplied by the SetSearchDirectory method for a chord file to load. Loads chord data from a resource. Searches the current directory or the directory supplied by the SetSearchDirectory method for a DLS collection file to load. Loads DLS collection data from a resource. Searches the current directory or the directory supplied by the SetSearchDirectory method for a segment file to load.
LoadBandFromResource LoadChordMap LoadChordMapFromResource LoadCollection
LoadCollectionFromResource LoadSegment
Composing Music CHAPTER 16
TABLE 16.1
Continued
16 Description
LoadSegmentFromResource
Loads segment data from a resource. Searches the current directory or the directory supplied by the SetSearchDirectory method for a style file to load. Loads style data from a resource. Sets the directory for all the Loader methods to find their data files.
LoadStyleFromResource SetSearchDirectory
A resource includes a description of the wave format, with parameters such as the sampling rate and number of output channels. Using the methods outlined in Table 16.1, a resource can be used to create a style, DLS collection, chordmap, or band.
The Performance Object Just like a musician performing for an audience, a DirectMusic performance is a collection of tasks that produce the final result. The DirectMusic Performance object is used to maintain the entire playback of the music. It is responsible for such tasks as playing the music file, establishing the audiopath to the music file, setting parameters for the playback, checking and setting timing, and handling segments of music. One of the Performance object’s special features is the ability to have more than one performance playing at the same time. For instance, one performance can be the orchestral piece playing in the background, and a secondary performance can be used to add short musical interludes that overlap the primary performance. This feature makes it possible to overlay musical pieces.
Using the DirectMusic Performance Object The following code sample shows how to declare the DirectMusicPerformance8 object: Private oDMP As DirectMusicPerformance8
A performance needs a variety of elements to fulfill its needs. Among these are the audiopath, the chordmap, the groove level, and the latency time. • Audiopath: Defines the stages in data flow from the performance to the DirectSound buffers. • Chordmap: Represents a collection of chords providing the foundation of the music’s harmonic structure and mood.
COMPOSING MUSIC
Method LoadStyle
259
260
Adding Music and Sounds with DirectAudio PART IV
• Groove level: A value given to music during style playback. This level determines which pattern will be selected at a given time and is measured in music time. Music time counts 768 ticks per quarter note and differs from performance to performance, based on the tempo used. • Latency time: The delay between when the buffer begins to play and when the sound actually comes out of the speakers. • Time signature: Defines the number of beats per measure in a section of music. • Transposing: The act of moving notes up or down a scale to create a lighter- or deeper-sounding piece. Table 16.2 describes the methods available to the DirectMusicPerformance8 object. TABLE 16.2
The DirectMusicPerformance8 Methods
Method
Description
AddNotificationType
Used to notify the Performance object when a chord changes or an event fires, such as commands or events for measures, beats, performance, recomposition, or segments. Adjusts the internal performance time forward or backward to compensate for drift, when a performance is being performed a few seconds faster or slower than expected. AdjustTime fixes this problem. Changes clock time to music time. Closes down the performance. This must be done before the Performance object can be destroyed. Creates an AudioPath object from an audiopath configuration file. An audiopath configuration file is created in DirectMusic Producer. Creates a basic default AudioPath object. Gets the amount of time between port buffer messages being inserted and being processed. Gets the chordmap from the control segment. Gets the current time. Gets the command from the control segment. Gets the default audiopath. Gets the groove level from the control segment. Gets the current latency time.
AdjustTime
ClockToMusicTime CloseDown CreateAudioPath
CreateStandardAudioPath GetBumperLength GetChordmap GetClockTime GetCommand GetDefaultAudioPath GetGrooveLevel GetLatencyTime
Composing Music CHAPTER 16
TABLE 16.2
Continued
16 Description
GetMasterAutoDownload
Gets the current parameters for automatically downloading instruments. Gets the master groove level. Gets the master tempo level. Gets the master volume level. Gets the current time in music time units. Gets the next awaiting notification message. Gets the approximate interval between the time messages are prepared and the time they are processed and heard. Gets the current queue time. Modifies the given time to within a certain boundary. Boundaries can be a specific time after a latency time, prepare time, or queue time. Gets a DirectMusicSegmentState object from a specified time within a primary segment. Gets the style of the current control segment within a given time frame. Gets the tempo within a given time frame. Gets the time signature within a given time frame. Initializes the default audiopath and the Performance object. Resets the time for the queued messages to start and clears out the older queued messages. Tells whether a specified segment is currently being played. Converts the music time to clock time. Tempo changes are taken into effect when making this conversion. Plays a segment. Removes a notification type defined by the AddNotificationType method. Resets the DirectMusic performance port.
GetMasterTempo GetMasterVolume GetMusicTime GetNotificationPMSG GetPrepareTime GetQueueTime GetResolvedTime
GetSegmentState GetStyle GetTempo GetTimeSig InitAudio Invalidate IsPlaying MusicToClockTime PlaySegmentEx RemoveNotificationType Reset
COMPOSING MUSIC
Method
GetMasterGrooveLevel
261
262
Adding Music and Sounds with DirectAudio PART IV
TABLE 16.2
Continued
Method
Description
SendCurvePMSG
Sends a detailed message to the Performance object to execute a curve, which is a series of MIDI control changes used to fade the volume in and out of a performance. The PMSG in method names refers to “performance message.” Sends a detailed message to the Performance object about a MIDI channel. Sends a detailed message to the Performance object about a note. Sends a detailed message to the performance object about a MIDI patch change. Sends a detailed message to the Performance object about a tempo change. Sends a detailed message to the Performance object about a time signature. Sends a detailed message to the Performance object to start a transposition. Sets the delay between when messages enter the port buffer and when they are displayed. Specifies the default audiopath by passing the AudioPath object. Turns the automatic downloading of instruments feature on or off. Sets a new value to be applied to all groove levels. This value moves all groove levels up or down as a whole. Sets a delta value to be applied to all tempo levels. Sets a delta value to be applied to all volume levels. Sets the event handle for notifications to the Performance object. Sets the delay between when messages are created and the time they are displayed. Stops playback of a DirectMusic segment, segment state, or AudioPath object.
SendMIDIPMSG SendNotePMSG SendPatchPMSG SendTempoPMSG SendTimeSigPMSG SendTransposePMSG SetBumperLength SetDefaultAudioPath SetMasterAutoDownload SetMasterGrooveLevel SetMasterTempo SetMasterVolume SetNotificationHandle SetPrepareTime StopEx
Composing Music CHAPTER 16
The Segment Object
Using the DirectMusic Segment Object The following code sample shows how to declare the DirectMusicSegment8 object: Private oDMS As DirectMusicSegment8
Table 16.3 describes all the methods available to the DirectMusicSegment8 object. TABLE 16.3
The DirectMusicSegment8 Methods
Method
Description
Clone
Copies all or parts of a segment. Attaches a DLS instrument collection to the specified Segment object. Downloads band and wave data to a performance or AudioPath object. Retrieves the audiopath configuration file for the current segment. Gets a chordmap for the specified segment. Gets the length of the segment in music time. Gets the loop point in the segment at which the repeating section stops. Gets the loop point in the segment at which the repeating section starts. Gets the internal name of the segment. Gets the number of times a looping segment is to reiterate. Gets the starting point for playing the current segment. Gets a style from a specified track and time within a segment. Turns automatic downloading of instruments on or off. Gets the length of the segment. Gets both the starting and ending points for a loop within a segment. Sets the number of times a looping segment is to repeat.
ConnectToCollection Download GetAudioPathConfig GetChordMap GetLength GetLoopPointEnd GetLoopPointStart GetName GetRepeats GetStartPoint GetStyle SetAutoDownloadEnable SetLength SetLoopPoints SetRepeats
16 COMPOSING MUSIC
All music performances are composed of segments, which are analogous to pieces of music that can be tied together to form a complete work or can be played in their segmented state. Segments can also be composed of different instruments and tempos.
263
264
Adding Music and Sounds with DirectAudio PART IV
TABLE 16.3
Continued
Method
Description
SetStandardMidiFile
Sets the DirectMusic object so that it understands the supplied MIDI file is standard, not one specific for DirectMusic. Sets the starting point for playing a segment. Turns the enable tempo messages for the specified segment on or off. Turns the “enable time signature” messages for the specified segment on or off. Unloads instruments that were downloaded by the Download method.
SetStartPoint SetTempoEnable SetTimeSigEnable Unload
The Audio Parameter Structure The audio parameter structure is used with the DirectMusicPerformance8.InitAudio method to handle all the settings needed to initialize the musical performance. The audio parameter structure is vital to the performance because it sets up the default synthesizer, sets the capabilities of the AudioPath object, regulates the sampling rate, and specifies the number of voices used by the synthesizer.
Using the DirectMusic Audio Parameter Type The following code sample shows how to declare the DMUS_AUDIOPARAMS object: Private DMAP As DMUS_AUDIOPARAMS
Because DMUS_AUDIOPARAMS is a type and not a class, it has supporting members instead of methods. All of the DMUS_AUDIOPARAMS members are described in Table 16.4. TABLE 16.4
The DMUS_AUDIOPARAMS Members
Member
Description
clsidDefaultSynth
Class identifier of the default synthesizer. This is a Boolean value that specifies whether the sink and synthesizer are initialized immediately. A sink is a buffer that accepts data directly from the synthesizer, not from other buffers. Flags specifying the capabilities of the AudioPath object.
fInitNow
lFeatures
Composing Music CHAPTER 16
TABLE 16.4
Continued
16 Description
lSampleRate
Sample rate of sink and synthesizer, in the range from 11,025kHz to 96,000kHz. Flags that specify which members of this structure contain valid data. Number of voices.
lVoices
The Band Object A band is a collection of instruments selected for use in a particular segment or style. More than one band can be added to a segment. However, there is always a default(or primary) band. By changing the band of a segment or style, you can change the range of sounds in a particular performance. It’s important to remember that a band changes only the instruments being played, not the tempo or any other attribute of the piece of music.
Using the DirectMusic Band Object The following code sample shows how to declare the DirectMusicBand8 object: Private oDMB As DirectMusicBand8
All of the DirectMusicBand8 methods are described in Table 16.5. TABLE 16.5
The DirectMusicBand8 Methods
Method
Description
CreateSegment
Creates a Segment object from the current band. Downloads the DLS data for the band into a Performance object or an AudioPath object. Unloads the band data from the Performance or AudioPath object previously supplied.
Download Upload
Modifying the Performance You can modify a performance’s playback by changing its volume and tempo. These attributes can enhance the user’s mood by instilling a sense of urgency or calm, for example, during the performance.
COMPOSING MUSIC
Member
lValidData
265
266
Adding Music and Sounds with DirectAudio PART IV
Volume The volume of a piece of music can be raised or lowered to increase or decrease the excitement level. This change can be very effective in a video game or product demo. Also, you might want your users to be able to adjust the volume in the application to suit their needs at runtime. To adjust the volume, you need to use the SetMasterVolume method of the Direct MusicPerformance8 object. The valid ranges for volume can vary widely and are measured in hundredths of a decibel. A good rule of thumb is to use values between –2500 and 200.
NOTE By changing the volume with SetMasterVolume, you are modifying the overall volume of the performance, not affecting the volume values set by the user in the Windows Control Panel.
The following code sample shows how to use the SetMasterVolume method: Dim oDMP As DirectMusicPerformance8 ‘’’ Set the volume to a new value oDMP.SetMasterVolume 50
Tempo A performance’s tempo dictates the speed at which it’s played. By increasing the tempo, you can create the effect of urgency. By decreasing the tempo, you can induce a feeling of calm. Used with volume, you can create some great mood effects. To change a performance’s master tempo, you use the SetMasterTempo method. The master tempo can be changed from a range of .01 to 100; the default tempo value is 1. For example, if you used the value .25, you would produce a tempo that was one-fourth the speed of the default tempo. A value of 4 would produce a tempo four times as fast as the default tempo. The following code sample shows how to use the SetMasterTempo method: Dim oDMP as DirectMusicPerformance8 ‘’’ Set the tempo to one-fourth its current tempo oDMP.SetMasterTempo .25
A DirectMusic Example The following example takes you through the basics of setting up the DirectMusic environment and playing a music soundtrack.
Composing Music CHAPTER 16
Declaring the Variables
The following code sample shows how to declare all the variables for a DirectMusic application. Some of the objects are created much later in this chapter’s example. ‘’’ Declare all of your DirectX8 and DirectMusic variables Private oDX As New DirectX8 Private oDML As DirectMusicLoader8 Private oDMP As DirectMusicPerformance8 Private oDMS As DirectMusicSegment8 Private DMAP As DMUS_AUDIOPARAMS ‘’’ Create the Loader and Performance objects oDML = oDX.DirectMusicLoaderCreate oDMP = oDX.DirectMusicPerformanceCreate
Initializing the Performance At this point, you can determine whether the audio card on the machine has the required capabilities to initialize your DirectMusic Performance object. The most likely cause of the InitAudio method failing is the audio card not having the capabilities specified in the InitAudio parameters. The following code sample shows how to initialize the performance variables for a DirectMusic application: oDMP.InitAudio Me.Handle.ToInt32, DMUS_AUDIOF_ALL, DMAP, _ ➥ Nothing, DMUS_APATH_SHARED_STEREOPLUSREVERB, 64
Using the Loader Object Next, you need to use the Loader object to set your search directory and load the segment you are going to use with DirectMusic. The following code sample shows how to load the segment with the Loader object: ‘’’ Set up the directory where the music data can be found. oDML.SetSearchDirectory FindMediaDir(“party.sgt”, True) ‘’’ Load the segment into the DirectMusic Segment object. oDMS = oDML.LoadSegment (“party.sgt”)
16 COMPOSING MUSIC
To start, you need to make sure you have instantiated all the objects you are going to be working with. In the following code sample, you’re creating a DirectX8 object, a DirectMusic Loader object, a DirectMusic Performance object, a DirectMusic Segment object, and a DirectMusic audio parameter object (DMUS_AUDIOPARAMS).
267
268
Adding Music and Sounds with DirectAudio PART IV
Using the Segment Object After you’ve specified how to load the segment into your Segment object, you need to actually perform the download by using the DirectMusic Segment object’s Download method. The following code sample shows how to call the Download method: ‘’’ Download the segment from the default audiopath ‘’’ supplied by the DirectMusic Performance object oDMS.Download(DMP.GetDefaultAudioPath)
Using the Performance Object Now that the segment has been loaded successfully, it’s time to begin playing the segment. You do this by calling the PlaySegmentEx method of the DirectMusic Performance object. To stop the performance from playing, you call the Performance object’s StopEx method. The following code sample shows how to start and stop the playback of the Performance object: ‘’’ Play the segment oDMP.PlaySegmentEx oDMS, 0, 0 ‘’’ Stops everything playing on the audiopath oDMP.StopEx oDMP. GetDefaultAudioPath, 0, 0
DirectMusic Producer The DirectMusic Producer is an additional application that Microsoft supplies with DirectMusic. It gives the user a wide variety of tools that help in arranging music, adding instruments, and changing tempo, volume, and other variables. You can also use the DirectMusic Producer to create DLS files for import into your DirectMusic applications. Because of this tool’s complexity, it is beyond the scope of this book. However, it is highly recommended that you learn to use this tool if you are going to be creating complex DirectMusic applications. Figure 16.1 shows a sample of what the DirectMusic Producer looks like. DirectMusic Producer has a single timeline that controls all playback. Changes in tempo, volume, instruments, and more can be applied to the timeline by using its interface. DirectMusic Producer also provides for multiple layers of wave files for each note in an instrument. An unlimited number of files, channels, and voices can be played at the same time and you can create effects by controlling the wave forms for each sampling or downloading others off the Web.
Composing Music CHAPTER 16 Menus
Toolbars
269
16 COMPOSING MUSIC
Project Tree
Editing Window
FIGURE 16.1 The DirectMusic Producer.
DirectMusic Producer also supports a variation of the VBScript programming language. With this component, you can create dynamic effects that respond to commands from your application. DirectMusic uses the DLS standard to create synthesized sound from predefined audio sources. This technology enables you to create dynamic audio that responds to the user and can offer varying experiences, depending on what the user decides to do.
Summary In this chapter, you have seen how DirectMusic can be used to create complex musical audio tracks for your application. You’ve learned how segments, performances, and bands work together to create the performances by analyzing a step-by-step process of creating a performance from segments. Finally, you have gotten a glimpse of a sophisticated editing tool called DirectMusic Producer. In the next chapter, you will learn about DirectSound and all its subcomponents. You will also learn how to record sounds and modify them in a sound buffer.
CHAPTER
Adding Sounds to Your Application with DirectSound
17
IN THIS CHAPTER • The DirectSound Object • Buffers
272
273
• The DirectSound Buffer Descriptor • Using the Sound Buffers
277
• Modifying the Sound Buffer • Recording
280
• DirectSound3D • Summary
286
283
279
274
272
Adding Music and Sounds with DirectAudio PART IV
DirectSound is the audio-specific part of DirectX that is responsible for playback and editing audio streams. DirectSound provides many effects and 3D sound techniques to enhance the listener’s audio experience. This chapter shows how the DirectSound object is created. You’ll then see how to manage the sound buffer and output the produced sounds.
The DirectSound8 Object The DirectSound8 object is the basis of the DirectSound libraries. It provides the foundation that all DirectSound work is based on; therefore, it must be declared first before you can perform any DirectSound work. With the DirectSound8 object, you can create sound buffers, retrieve the hardware sound capabilities, and modify the speaker configuration.
Using the DirectSound8 Object The following code sample shows how to declare the DirectSound8 object: Dim oDS As DirectSound8
Table 17.1 describes the available DirectSound8 methods. TABLE 17.1
The DirectSound8 Methods
Method
Description
CreatePrimarySoundBuffer
Creates the primary sound buffer. Creates a secondary sound buffer. Creates a secondary sound buffer by loading a file. Creates a secondary sound buffer by retrieving a WAV file from a resource. Creates a secondary sound buffer that is a copy of the original secondary sound buffer passed to it. Retrieves the hardware capabilities of the DirectSound-compatible hardware on the current machine. Retrieves the configuration of the speakers on the machine. Sets the priority level of the application for this sound device. Modifies the configuration of the speakers on the machine.
CreateSoundBuffer CreateSoundBufferFromFile CreateSoundBufferFromResource DuplicateSoundBuffer GetCaps
GetSpeakerConfig SetCooperativeLevel SetSpeakerConfig
Adding Sounds to Your Application with DirectSound CHAPTER 17
273
Buffers Buffers serve the purpose of holding sound data—both the complete data stream stored in the primary sound buffer and the sound segments being assembled in secondary sound buffers.
Primary Sound Buffer
For example, if you wanted to create a sidewalk scene in a big city, you could use secondary buffers for each distinct sound such as “car crashing,” “horn honking,” “female talking,” “male talking,” and so forth. You can then layer these sounds in the primary buffer and create a scene with many different distinct sounds playing at once. The following code sample shows how to declare the DirectSoundSecondaryBuffer8 object: Dim oDSSB As DxVBLibA.DirectSoundSecondaryBuffer8
Table 17.2 shows the methods of the DirectSoundSecondaryBuffer8 object. TABLE 17.2
The DirectSoundSecondaryBuffer8 Methods
Method
Description
AcquireResources
Acquires the necessary resources for a secondary buffer. Gets the capabilities of the secondary buffer. Gets the position of the play cursor and the write cursor. Gets a secondary sound buffer that can be configured to produce 3D effects.
GetCaps GetCurrentPosition GetDirectSound3DBuffer
WITH
The secondary sound buffer is used as a mixing place for sounds that are going to be merged into the primary buffer. You should view the secondary buffer as the staging area for individual sounds. Every DirectSound application must have at least one secondary buffer. Also, you can layer secondary buffers on top of each other. There is no specified limit to how many secondary buffers that can be used; you are limited only by available memory.
ADDING SOUNDS
Secondary Sound Buffer
17 DIRECTSOUND
The primary sound buffer is where all the sounds are placed for playback. The content of the primary buffer comes from one or more secondary buffers. After all of the sound information is loaded into the primary buffer, it is then passed to the sound hardware for conversion and playback. When the DirectSound8 object is initialized, it automatically creates and manages a primary buffer. Therefore, you will always have a primary buffer available without any additional coding needed.
274
Adding Music and Sounds with DirectAudio PART IV
TABLE 17.2
Continued
Method
Description
GetFormat
Gets the wave format (WAV) information for the current buffer and stores it in a waveformat object. The WAV format is the standard audio format for DirectSound. Gets the frequency that the secondary sound buffer is playing at. Gets an effects object in the buffer’s audiopath. Gets the volume in relation to the right and left speakers. Gets the status of the secondary sound buffer. Gets the volume of the secondary sound buffer. Plays the secondary buffer contents from the play cursor’s current position. Reads a specified portion of the secondary sound buffer and stores it in a supplied buffer. Restores the memory allocation that was lost for this secondary sound buffer. Saves the sounds currently in the sound buffer to a WAV file. Sets the position of the play cursor in the secondary buffer. Sets the frequency at which the secondary sound buffer will be played. Sets the effects that are applied to a secondary buffer. Sets a notification point that can be triggered during playback. Sets the volume in relation to the right and left speakers. Sets the volume of the secondary sound buffer. Stops playback. Writes data from an application buffer back to a sound buffer.
GetFrequency GetObjectInPath GetPan GetStatus GetVolume Play ReadBuffer Restore SaveToFile SetCurrentPosition SetFrequency SetFX SetNotificationPositions SetPan SetVolume Stop WriteBuffer
The DirectSound Buffer Descriptor The buffer descriptor is responsible for defining what the DirectSound Buffer object is used for. It defines its parameters and sets its default settings. The DirectSound buffer descriptor is used with two DirectSound8 methods: CreateSoundBuffer and CreatePrimarySoundBuffer.
Adding Sounds to Your Application with DirectSound CHAPTER 17
275
Buffer Descriptor Members The DSBUFFERDESC type is composed of five members that define its parameters. A member is simply a subcomponent of a type that helps define its abilities. Members are synonymous with parameters. Table 17.3 identifies the members and provides a description of each. TABLE 17.3
The DSBUFFERDESC Methods
Sets the wave format of the buffer. Defines the algorithm to be used if DirectSound3D compatibility is not found on the user’s machine. Sets the size of the buffer (in bytes) for the DirectSound buffer. Defines the flags to turn on for the DirectSound buffer. This parameter uses the CONST_DSBCAPSFLAGS values.
guid3DAlgorithm lBufferBytes lFlags
Creating the DirectSound Buffer Descriptor (DSBUFFERDESC) The following code sample shows how to use the DSBUFFERDESC descriptor object: Dim DSBD As DSBUFFERDESC With DSBD .lFlags = DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME With .fxFormat .lSamplesPerSec = 22050 .nBitsPerSample = 16 .nChannels = 2 .nBlockAlign = (.nChannels * .nBitsPerSample) / 8 .nFormatTag = WAVE_FORMAT_PCM .nSize = 0 .lAvgBytesPerSec = .lSamplesPerSec * .nBlockAlign End With .lBufferBytes = .fxFormat.lAvgBytesPerSec * 2 End With
In the preceding example, notice the use of constants such as DSBCAPS_CTRLPAN. These are DirectSound buffer capability flags, which are used to turn on attributes of the DirectSound buffer. You can use a capability flag (cap flag) to define or retrieve the capabilities of an associated object. The next section explains the purpose of each flag.
17 WITH
fxFormat
ADDING SOUNDS
Description
DIRECTSOUND
Member
276
Adding Music and Sounds with DirectAudio PART IV
CONST_DSBCAPSFLAGS CONST_DSBCAPSFLAGS are flag constants that are combined to define specific information about what the DSBUFFERDESC can do and to indicate the current capabilities of a DSBCAPS type. By using these flags with the DSBUFFERDESC type, you can specify the capabilities of the DirectSound buffer that DSBUFFERDESC is defining. Conversely, you can do a bitwise operation on a DSBCAPS type to determine the capabilities of a DirectSound primary buffer that the DSBCAPS type is attached to. Table 17.4 describes the CONST_DSBCAPSFLAGS constants. TABLE 17.4
The CONST_DSBCAPSFLAGS Constants
Constant
Description
DSBCAPS_CTRL3D
Supports 3D control. Not used at this time. Supports frequency control. Supports sound effects. Supports pan control. Supports position notification. Supports volume control. Supports the play cursor by enabling retrieval of its current position. Supports a global buffer. Sound will be heard whether or not this application has focus. Buffer is not allocated for hardware or software until the sound is played. Supports hardware mixing of sounds. Supports software mixing of sounds. When the maximum distance between the listener and the sound source is exceeded, the sound buffer will no longer play the audio. Buffer is a primary sound buffer. Buffer is put into the sound card’s memory. Sound continues to play as long as focus does not shift to another application running DirectSound. This is called sticky focus.
DSBCAPS_CTRLCHANNELVOLUME DSBCAPS_CTRLFREQUENCY DSBCAPS_CTRLFX DSBCAPS_CTRLPAN DSBCAPS_CTRLPOSITIONNOTIFY DSBCAPS_CTRLVOLUME DSBCAPS_GETCURRENTPOSITION2 DSBCAPS_GLOBALFOCUS DSBCAPS_LOCDEFER DSBCAPS_LOCHARDWARE DSBCAPS_LOCSOFTWARE DSBCAPS_MUTE3DATMAXDISTANCE
DSBCAPS_PRIMARYBUFFER DSBCAPS_STATIC DSBCAPS_STICKYFOCUS
Adding Sounds to Your Application with DirectSound CHAPTER 17
277
Using the Sound Buffers The following sections explain the steps involved in creating and using a sound buffer.
Enumerating the Sound Driver If your program is going to run on only a specific machine with a specific sound card, there’s really no purpose in enumerating all the devices on that machine. However, if you are making a game or multimedia application that could be used with a variety of sound hardware devices, enumeration is vital.
Sub EnumerateSoundDevices Static I as Integer Set oDSE = oDX.GetDSEnum For I = 1 to oDSE.GetCount ‘’’ Add the next description string ‘’’ into the combo box. Combo1.AddItem oDSE.GetDescription(I) Next I End Sub
Creating the Sound Buffer To begin using the sound buffer, you must first create it by declaring an object variable and assigning a DirectSound buffer to it. The following code example shows how this is done. If you used the enumeration method in the preceding section, you could use this code in the combo box’s click event: ‘’’ Assign the selected device as the DirectSound device you will create Set oDS = oDX.DirectSoundCreate(oDSE.GetGuid(Combo1.ListIndex+1))
If you don’t want to deal with enumeration, you can simply use the following line: Set oDS = oDX.DirectSoundCreate(“”)
This code line tells DirectSound to use the default sound driver on the machine.
WITH
Dim oDX as DirectX Dim oDSE as DirectSoundEnum ‘’’ The Enumerator object
ADDING SOUNDS
To enumerate the sound driver, you need the following code:
17 DIRECTSOUND
Enumeration, as mentioned before, is the process of retrieving a collection of sound card devices. With this collection, you, as a programmer, can allow users to choose the best sound card option for their particular needs. Enumeration simply returns a list of the drivers on the machine. By allowing the user to choose, you can potentially reduce technical support phone calls from people who are having sound problems with your application.
278
Adding Music and Sounds with DirectAudio PART IV
Cooperative Levels By using cooperative levels, your DirectSound object can determine how it should behave, or cooperate, on a machine. Specifically, should it be the only user of the sound card, or should it allow others to use it? This is an important consideration, as you might want only one thing playing at a time. However, to ensure that your application is not excessive or greedy, you must decide in advance if you need to have exclusive access to the card. Normally, if you are programming a game or application that takes up the whole screen, it is advisable to take exclusive control of the sound card. At any other time, normal control is fine. The two settings for cooperative levels are DSSCL_NORMAL and DSSCL_EXCLUSIVE. The following example sets the cooperative level to NORMAL: oDS.SetCooperativeLevel frmMain.hWnd, DSSCL_NORMAL
Loading the Buffer The environment is all set up, but you don’t have any sounds to play. That means it’s time to load the buffer with some sound data. You can load the buffer in many different ways, but for simplicity’s sake, you are going to use the DirectSound method CreateSoundBufferFromFile. This method, one of the most commonly used ones, is designed to load the buffer with a WAV file from a hard drive or CD. Wave files are currently the only supported sound files that can be loaded with DirectSound. The following code shows how this method is used: Dim DSB As DirectSoundSecondaryBuffer8 Dim BuffDesc As DSBUFFERDESC BuffDesc.lFlags = DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME _ Or DSBCAPS_CTRLFREQUENCY Set DSB = DS.CreateSoundBufferFromFile(“d:\splash.wav”, buffdesc)
You might have noticed that a DirectSound buffer descriptor was declared with the DirectSound buffer. The buffer descriptor indicates how to set up the buffer for optimal use. In the preceding example, it’s set to support pan, volume, and frequency control. (See the previous section “CONST_DSBCAPSFLAGS” for details on all the constants that can be used with the buffer descriptor.)
Playing the Buffer Playing the buffer is actually the easiest part: Simply tell the DirectSoundSecondaryBuffer to play by using the Play method of DirectSoundSecondaryBuffer8. The following example shows how to do this: oDSB.Play DSBPLAY_LOOPING
Adding Sounds to Your Application with DirectSound CHAPTER 17
279
A DSBPLAY_LOOPING flag tells DirectSound to play this buffer continuously. If you want to stop the playback, just use the Stop method of DirectSoundSecondaryBuffer8.
Modifying the Sound Buffer The sound buffer is the holding place for all digital audio. To modify that data, you need access to methods in the DirectSoundSecondaryBuffer8 object that enable you to change the makeup of the sound stored there. You can change three attributes in the sound buffer: frequency, panning, and volume.
17
Panning controls the left and right attributes of stereo speakers. By adjusting the panning, you can move the sound to the user’s left or right side. This attribute is effective in simple stereo usage of sound effects.
Volume The volume attribute of the sound buffer is obvious—you use it to increase or decrease the volume in response to what the user is doing in your application. This volume is independent of the volume users set for their Windows environment. For example, if you have a racing game, you can increase the volume of the car motor sound to give the impression you are speeding up.
Example The following code example shows how to use the frequency, panning, and volume methods to modify the sound buffer: Dim oDX as DirectX Dim oDS as DirectSound Dim oDSB As DirectSoundSecondaryBuffer8 ‘’’ Change the frequency of the secondary buffer oDSB.SetFrequency 500 ‘’’ Set to low frequency oDSB.SetFrequency DSBFREQUENCY_MAX ‘’’ Set to maximum frequency (100,000) oDSB.SetFrequency DSBFREQUENCY_MIN ‘’’ Set to minimum frequency (100)
WITH
Panning
ADDING SOUNDS
Frequency is the number of hertz used to play back the audio data. By raising or lowering the frequency of the sound buffer, you can make the sound seem faster or slower. For example, you could take a walking sound and turn it into a running sound by changing the frequency level.
DIRECTSOUND
Frequency
280
Adding Music and Sounds with DirectAudio PART IV oDSB.SetFrequency DSBFREQUENCY_ORIGINAL ‘’’ Set to original frequency (0) ‘’’ Change the pan of the oDSB.SetPan 10000 ‘’’ Set oDSB.SetPan DSBPAN_CENTER oDSB.SetPan DSBPAN_LEFT oDSB.SetPan DSBPAN_RIGHT ‘’’ Change the oDSB.SetVolume oDSB.SetVolume oDSB.SetVolume
secondary buffer to the far right of the pan range ‘’’ Set to the center of the pan range (0) ‘’’ Set to the far left of the pan range (-10,000) ‘’’ Set to the far right of the pan range (10,000)
volume of the -1000 ‘’’ Set DSBVOLUME_MAX DSBVOLUME_MIN
secondary buffer to 1,000 units less than the maximum volume ‘’’ Set to the maximum volume (0) ‘’’ Set to the minimum volume (-10,000)
Recording One of the nicest features of DirectSound is the capability to record sound. This feature is unusual because most games do not require recording the users’ voices or their music. Therefore, the recording capabilities are for multimedia in general. DirectSoundCapture can be used in an application to manage recording voices from a microphone or other audio input port.
Creating the Capture Object To start, you need to declare your common objects as well as a few others. The new objects you are going to use include the DirectSoundCapture8, DirectSoundCaptureBuffer8, DSCBUFFERDESC, and WAVEFORMATEX objects. The DirectSoundCapture8 object gives you access to all the features of DirectSound capture. The DirectSoundCaptureBuffer8 object gives you access to a buffer to store the captured data. DSCBUFFERDESC gives you a way to set parameters for the DirectSoundCaptureBuffer8 object. The WAVEFORMATEX object supplies capability information on the sound card’s recording attributes. Your object declaration code looks like this: Private Private Private Private Private Private Private
oDX As New DirectX8 oDSC As DirectSoundCapture8 oDSCB As DirectSoundCaptureBuffer8 DSCBD As DSCBUFFERDESC oDS As DirectSound8 WF As WAVEFORMATEX DSCaps As DSCCAPS
Creating the Capture Buffer To create the capture buffer, first you set up the DirectSound capture buffer descriptor. After you have assigned all the flags and settings you want for the buffer, you then call the CreateCaptureBuffer method of the DirectSoundCapture8 object. The returned value is then assigned to the DirectSoundCaptureBuffer8 object, as shown in the following code:
Adding Sounds to Your Application with DirectSound CHAPTER 17
281
‘’’ Use this to determine the recording abilities of the sound card. oDSC.GetCaps DSCaps Dim Hz As long ‘’’ Hertz of the sound card’s recording capabilities
‘’’ ‘’’ ‘’’ Set
Create the capture buffer by creating a buffer from a DirectSoundCapture object with the attributes set up in the DSCBUFFERDESC descriptor. oDSCB = oDSC.CreateCaptureBuffer(DSCBD)
Recording Recording begins by using the Start method of the DirectSound capture buffer. It is important to remember to set the capture buffer to NOTHING before using the Start method; otherwise, you will not be recording on a clean buffer. Start uses one of two flags to determine what it will do when it reaches the end of the buffer. If the DSCBSTART_DEFAULT flag is used, data capturing stops when the buffer is full. If the DSCBSTART_LOOPING flag is used, the capturing does not end until a Stop method is called. This results in data at the beginning of the buffer being overwritten as the buffer fills up.
WITH
‘’’ Set up the DirectSoundCaptureBuffer descriptor With DSCBD .fxFormat = WF .lBufferBytes = WF.lAvgBytesPerSec * 20 .lFlags = DSCBCAPS_WAVEMAPPED End With
ADDING SOUNDS
‘’’ Set up the wave format capabilities for this sound card With WF .nFormatTag = WAVE_FORMAT_PCM .nChannels = 1 .lSamplesPerSec = Hz .nBitesPerSample = 8 .nBlockAlign = 1 .lAvgBytesPerSec = .lSamplesPerSec * .nBlockAlign .nSize = 0 End With
17 DIRECTSOUND
If (DSCaps.lFormats And WAVE_FORMAT2M08) Then Hz = 22050 ElseIf (DSCaps.lFormats And WAVE_FORMAT_1M08) Then Hz = 11025 Else Msgbox “Your sound card does not support recording.” End End If
282
Adding Music and Sounds with DirectAudio PART IV
The following code shows how to start recording: ‘’’ Clear the buffer Set oDSCB = Nothing ‘’’ Start recording oDSCB.Start DSCBSTART_DEFAULT
To stop recording, use the Stop method of the DirectSoundCaptureBuffer8 object: ‘’’ Stop the recording oDSCB.Stop
Converting the Buffer Because the DirectSound capture buffer cannot save data to the hard drive, you must copy the buffer’s contents to a DirectSound secondary buffer first. This buffer can then use its SaveToFile method to export the data to a WAV file on the user’s machine. The process starts by copying the attributes of the capture buffer to the secondary buffer. The data is then retrieved from the capture buffer with the ReadBuffer method and stored in a buffer array. Finally, the buffer array is written to the secondary buffer by using the WriteBuffer method. The following code example shows this entire procedure: Dim Dim Dim Dim
oDSB As DirectSoundBuffer8 DSC As DSCURSORS DSBD As DSBUFFERDESC ByteBuffer() As Integer ‘’’ Capture buffer.
oDSCB.Stop ‘’’ Stop the capture buffer if it’s running ‘’’ Store the current buffer capture information in a DSCursor oDSCB.GetCurrentPosition DSC DSBD.lBufferBytes = DSC.lWrite + 1 DSBD.fxFormat = oDSCB.fxFormat ‘’’If there is nothing to write, then exit If DSC.lWrite = 0 Then Exit Sub Set oDSB = oDS.CreateSoundBuffer(DSBD) ‘’’Set the size for the buffer ReDim ByteBuffer(DSC.lWrite) ‘’’Read the data from the capture buffer oDSCB.ReadBuffer 0, DSC.lWrite, ByteBuffer(0), DSCBLOCK_DEFAULT ‘’’Write the data to the sound buffer oDSB.WriteBuffer 0, DSC.lWrite, ByteBuffer(0), DSBLOCK_DEFAULT
Adding Sounds to Your Application with DirectSound CHAPTER 17
283
Saving the File To save the file, you simply need to call the SaveToFile method of the DirectSound buffer: ‘’’ Save the file oDSB.SaveToFile “c:\output wave.wav”
DirectSound3D
For DirectSound3D to interact with the environment you are using it in, the same attributes used in Direct3D must also be present in DirectSound3D. Therefore, the most obvious component is a coordinates system. With a set of coordinates, you can tell what the x, y, and z positions are for any 3D sound. As with Direct3D, DirectSound3D uses the x, y, z coordinate system. Figure 17.1 shows what these coordinates represent. Y
Z
X
FIGURE 17.1 The DirectSound3D coordinate system.
In DirectSound3D, the listener (or user of the application) is always at coordinates 0,0,0. X values represent sounds to the listener’s left and right. A positive x value means to the left, and a negative value, to the right. Y values represent sounds above and below the listener, with positive values indicating above, and negative values, below. Z values represent sounds in front of and behind the listener. Therefore, a positive z value means in front, and negative means in back.
WITH
Coordinates
ADDING SOUNDS
One of the downfalls of using DirectSound3D is that it is more hardware intensive than DirectSound because more calculations are involved. Therefore, it’s wise to keep 3D sounds in your applications to a minimum. Use them judiciously, and you will still have a product that performs well.
17 DIRECTSOUND
Early in the DirectSound evolution, 3D sound was not an option. However, with the advent of modern sound cards, you now have the capability to hear sounds anywhere in 3D space. Just like expensive sound systems in your local theater, you can have a “surround sound” experience in your home. To support this technology, Microsoft has made DirectSound more robust by adding DirectSound3D components. These components work with DirectSound to produce 3D sound on hardware that is built to support it.
284
Adding Music and Sounds with DirectAudio PART IV
Distances After you have specified where the sound will be played in relation to the listener, you need to determine how far away it is. This setting adds to the 3D experience because you can make sounds seem to be getting closer to or going farther away from the listener by changing the distance value of the DirectSound3DBuffer8 object.
The 3D Buffer The DirectSound3DBuffer8 object is used to maintain the attributes of a 3D sound buffer. It handles such settings as the sound cones, sound velocity, position of the sound in 3D space, and distance between the sounds where it tapers off in space. For more information on these settings, see Chapter 15, “DirectX Audio—DirectMusic and DirectSound.” All of these settings allow the DirectSound 3D buffer to give the illusion of realistic sound, like what you hear around you every day. For example, the 3D buffer can help you increase the volume of a fountain in a town square as you walk toward it in a virtual world, or it can give you the impression of birds flying by your position in 3D space. The following code sample shows how to declare the DirectSound3DBuffer8 object: Dim oDS3DB As DirectSound3DBuffer8
Table 17.5 describes the DirectSound3DBuffer8 methods. TABLE 17.5
The DirectSound3DBuffer8 Methods
Method
Description
GetAllParameters
Gets a DS3DBUFFER type that contains information about the settings of the 3D buffer. Gets the inside and outside angles of the sound projection cone. Gets the orientation of the sound projection cone. Gets the volume at the outside angle of the sound projection cone. Gets the secondary sound buffer that the 3D buffer was created from. Gets the maximum distance at which the sound will be played. The sound volume will be shut off completely at this distance. Gets the minimum distance at which the sound can be played. The sound will be at its maximum volume at this distance.
GetConeAngles GetConeOrientation GetConeOutsideVolume GetDirectSoundBuffer GetMaxDistance
GetMinDistance
Adding Sounds to Your Application with DirectSound CHAPTER 17
TABLE 17.5
285
Continued
Gets the current sound mode that the 3D buffer is using. The types are normal (world space), disabled, and head relative. Gets the sound buffer’s distance. Gets the velocity of the sound buffer. Sets the parameters of a 3D buffer by attaching a DS3DBUFFER object to the DirectSound 3D buffer. Sets the inside and outside angle of the sound projection cone. Sets the orientation of the sound projection cone. Sets the volume at the outside angle of the sound projection cone. Sets the maximum distance at which the sound will be played. Sets the minimum distance at which the sound will be played. Sets the current sound mode for the 3D sound buffer. Sets the sound buffer’s distance. Sets the velocity of the sound buffer.
GetPosition GetVelocity SetAllParameters SetConeAngles SetConeOrientation SetConeOutsideVolume SetMaxDistance SetMinDistance SetMode SetPosition SetVelocity
The 3D Listener It’s not sufficient to make a 3D sound when there is no one to hear it. Therefore, you need a 3D Listener object. The DirectSound3DListener8 object fills the bill by providing data on the listener’s relative position and orientation. The Listener object improves the realism of a 3D environment by controlling when sounds should be heard. Chapter 15 discusses the listener’s position and orientation. For example, if you have a character sitting on a park bench in a virtual world, you need to make sure he hears only the sounds that are directed toward him. If a bird is flying away from him, he shouldn’t hear it. However, if the bird is approaching his position, you want to make sure the man hears it. The following code sample shows how to declare the DirectSound3DListener8 object: Dim oDS3DB As DirectSound3DListener8
17 WITH
GetMode
ADDING SOUNDS
Description
DIRECTSOUND
Method
286
Adding Music and Sounds with DirectAudio PART IV
Table 17.6 describes the DirectSound3DListener8 methods. TABLE 17.6
The DirectSound3DListener8 Methods
Methods
Description
CommitDeferredSettings
Commits all the parameter changes that were set by the 3D Buffer and 3D Listener objects. Gets the parameters of the 3D world and the listener. Gets the primary buffer that created this Listener object. Gets the number of meters in a vector unit. Gets the Doppler effect factor. Gets the listener’s orientation in space. Gets the listener’s position in space. Gets the roll off factor over a distance. Gets the listener’s velocity in space Sets the parameters of the 3D world and the listener. Sets the number of meters in a vector unit. Sets the Doppler effect factor. Sets the listener’s orientation in space. Sets the listener’s position in space. Sets the roll off factor over a distance. Sets the listener’s velocity in space.
GetAllParameters GetDirectSoundBuffer GetDistanceFactor GetDopplerFactor GetOrientation GetPosition GetRolloffFactor GetVelocity SetAllParameters SetDistanceFactor SetDopplerFactor SetOrientation SetPosition SetRolloffFactor SetVelocity
Summary This chapter has focused on the DirectSound objects and how they work together to create sound and voice in your VB.NET applications. You’ve learned that the DirectSound object gives your application information on sound hardware as well as the ability to create buffers. The primary and secondary buffers offer a template for modifying and assembling your sounds. The 3D Buffer and 3D Listener objects enable you to create the illusion of 3D sound in your applications. In the next chapter, you will learn about DirectShow. You will also learn how DirectShow Editing Services (DES), timelines, filters, media players, and media conversion work together to produce multimedia applications.
PART
V
Streaming Media with DirectShow
DirectShow is the showcase piece of DirectX that enables playing streaming media, such as film and audio. With DirectShow, timelines can be created, multimedia can be displayed, and different forms of media can be converted. This section details these aspects of DirectShow.
IN THIS PART 18 Introduction to DirectShow
289
19 Using DirectShow for Digital Editing 20 Multimedia Players
315
297
CHAPTER
Introduction to DirectShow
18
IN THIS CHAPTER • Uses for DirectShow
290
• Objects in DirectShow • DirectShow Architecture
290 291
• Supported Media Formats and Codecs
293
• Creating a Reference to the ActiveMovie Type Library 295 • Summary
296
290
Streaming Media with DirectShow PART V
DirectShow, a Microsoft solution built on the need to stream video and audio quickly from many different media sources, is designed to provide all the high-quality video playback and capture features that for many years were available only in high-end software products. DirectShow also supplies a widely supported architectural model that allows new media types to be added easily as they become available. DirectShow is based on an earlier product called ActiveMovie that was designed to play video files. This product later became DirectShow and has evolved into a full-fledged multimedia playback and capture library.
Uses for DirectShow DirectShow has two central functions: media playback and media capture. Because of this, DirectShow is an excellent tool for any applications that are going to have media playback, such as DVD or MP3 players. It is also useful in building applications that need to provide video editing and capturing, such as video editing tools.
Objects in DirectShow To understand how DirectShow transforms media formats into new media formats, you need to look at the main objects used to perform this task. Through the use of filters, filter graphs, and pins, DirectShow moves the media stream along in your code. To understand how these items interact with each other and how they perform their tasks, you’ll look at them individually in the following sections.
Filter The filter, the foundation of the DirectShow process, is used to transform a media object. A filter can be used to open, compress, convert, and ultimately display a file. This process is important because it allows incompatible hardware and software to communicate through filters. Filters allow new audio and video formats to be converted to legacy audio and video formats that were designed for the original hardware. As new sound and video software technologies are developed, new filters will be created that can be incorporated into your programs. As you go through the process of retrieving a file to display to the screen or send to your sound card, you must run it through at least two filters. For example, say you are going to display an AVI movie to the screen. You must first use a source filter to load the AVI file, and then convert the output from the source filter by using a transform filter. Finally, you take the output from the transform filter and run that through a render filter. The result is that the rendering process is made up of three filters, each converting the file to a format that Windows can understand and then displaying it to the screen. This example is outlined in Figure 18.1.
Introduction to DirectShow CHAPTER 18
Source Filter
Transform Filter
291
Render Filter
FIGURE 18.1 Using filters to play an AVI file.
The main advantage of using filters is that with this model, you can easily add filters for new audio and video formats and incorporate them into your existing code.
Filter Graph The filter graph is the object that manages all the filters you are working with. It is a collection of filters that are brought together to complete a specific task, which could be as simple as converting one media format to another. This collection of filters, used one after the other, forms a media stream that is managed by the filter graph.
Pin
Figure 18.2 shows two filters with their pins. The first filter has an input and an output pin. In the second filter, there is only one pin: an audio input pin. By connecting the output pins to the input pins, you are able to convert data from one format to another format for playback or conversion purposes.
FIGURE 18.2 Two filters and their pins.
DirectShow Architecture DirectShow is made up of some smaller objects. Combined, these objects form the foundation of the DirectShow architecture. Among these objects are IAMCollection, IBasicAudio, IBasicVideo, IFilterInfo, IMediaControl, IMediaEvent, IMediaPosition, IMediaTypeInfo,
18 INTRODUCTION TO DIRECTSHOW
Filters are linked together by objects called pins, which provide input or output functionality for a filter. For example, if the first filter needs to talk to the second filter, the first filter must have an output pin (to export) and the second filter must have an input pin (to import). Some filters have only one pin. For example, a source filter does not need to provide an input pin, but does need an output pin. The reverse is true for the transform filter.
292
Streaming Media with DirectShow PART V IPinInfo, IRegFilterInfo,
and IVideoWindow. Figure 18.3 shows the DirectShow architecture. The following list describes the objects in the DirectShow architecture:
DirectShow
IAMCollection
IBasicAudio
IBasicVideo
IFilterInfo
IMediaControl
IMediaEvent
IMediaPosition
IMediaTypeInfo
IPinInfo
IRegFilterInfo
IVideoWindow
FIGURE 18.3 The DirectShow architecture.
• IAM Collection This object provides access to a collection that can contain one or more of the other objects, such as IPinInfo, IFilterInfo, or IMediaTypeInfo. •
IBasicAudio
This object is the foundation for audio work in DirectShow. It provides access to volume and balance attributes of the audio stream.
•
IBasicVideo
•
IFilterInfo
This object is the foundation for video work in DirectShow. It provides all the properties and methods necessary to output video to the screen. This object is used to manage a filter and provide access to all the pins connecting it to other filters.
Introduction to DirectShow CHAPTER 18
•
IMediaControl
•
IMediaEvent
•
IMediaPosition
•
IMediaTypeInfo
293
This object is responsible for directing the execution of the media file. The IMediaControl can cause the filter to play, stop, and pause the media stream. Events generated by the filter graph are returned to the IMediaEvent object for processing. If any of the filters in the graph can seek specific points in the stream, this object can be used to navigate to that position. This object retrieves media type information about the current filter
graph. •
This object is responsible for managing pins. It controls what the pin is doing in relation to the filter it is attached to. It also returns information about the pin’s capabilities.
•
IRegFilterInfo
•
IVideoWindow
IPinInfo
This object can be used to retrieve information about all the filters installed on the current machine. This object provides information about the current video window being used by DirectShow.
Windows supports many different media formats that include both audio and video technologies. As new technologies are developed to increase audio/video quality and improve compression rates, they will be released to the public in the form of filters. Windows also supports a wide array of codecs. A codec is a compression/decompression algorithm. Codecs can function as software-only (for example, Cinepak, Indeo), hardware-only (such as DV Camera), or as a combination of hardware and software (MPEG, for instance). They are used to compress large files or data streams, often for efficient transmission over a network, and then decode them when they are displayed or played back. Table 18.1 shows some of the most commonly supported media formats and codecs in DirectShow. TABLE 18.1
DirectShow-Supported Media Formats and Codecs
Media Format
Extension
Type
Advanced Streaming Format Audio Interchange File Format Audio-Video Interleaved
ASF AIFF AVI
Video Audio Video/Audio
18 INTRODUCTION TO DIRECTSHOW
Supported Media Formats and Codecs
294
Streaming Media with DirectShow PART V
TABLE 18.1
Continued
Media Format
Extension
Type
Cinepak Digital Video Indeo ISO MPEG-4 video 1.0 Microsoft MPEG-4 3.0 Microsoft Windows Media Video codec 7.0 Motion Picture Experts Group MPEG Audio Layer-3 MPEG-1 Musical Instrument Digital Interface QuickTime 2.0 Sipro Labs ACELP Sound File Unix Audio Voxware MetaSound WaveForm Audio Windows Media Audio Windows Media Video
N/A DV N/A N/A MPEG N/A
Codec Video Codec Codec Video Codec Video Codec Video Codec
MPG, MPEG, MPEMPEG MPG, MPEG, MP3 MPEG MIDI, MID, RMI
Video Audio Audio/Video Codec Audio
MOV N/A SND AU N/A WAV WMA WMV
Video Audio Codec Audio Audio Codec Audio Audio Video
NOTE Some of these file formats and codecs require the use of the Windows Media Format SDK from Microsoft.
DirectShow derives its capabilities from the DirectDraw and DirectAudio capabilities of the machine the program is running on. Therefore, DirectShow can take advantage of hardwaresupported features of the video and sound card. Moreover, if DirectShow needs capabilities
Introduction to DirectShow CHAPTER 18
295
that are not present, it can use the software emulation of DirectDraw and DirectAudio to create what it needs.
Creating a Reference to the ActiveMovie Type Library DirectShow is part of the DirectX family, but it is not directly integrated into the DirectX 8 type library. Therefore, to use DirectShow, you must specify the ActiveMovie type library to be included in your application for you to access all its features. The ActiveMovie type library is also known as quartz.dll. To create the reference, follow these steps: 1. Open Visual Basic 6. 2. Click the Standard EXE icon in the New tab (shown in Figure 18.4), and click Open.
18 INTRODUCTION TO DIRECTSHOW
FIGURE 18.4 The VB New Project dialog box.
3. Choose Project, References from the main menu in the Visual Basic project window to open the References dialog box, shown in Figure 18.5. 4. In the Available References list box, look for the component labeled ActiveMovie Control Type Library. Click the check box next to the component to add it to the project (see Figure 18.6), and click OK.
296
Streaming Media with DirectShow PART V
FIGURE 18.5 The References dialog box.
FIGURE 18.6 Adding the ActiveMovie type libraries.
Summary In this chapter, you have learned about DirectShow and its major objects, including filters, filter graphs, and pins. You’ve also looked at the DirectShow architecture. Finally, you’ve learned about the supported media formats and how to create a reference to the quartz.dll (ActiveMovie) component. In the next chapter, you will learn about creating a timeline in DirectShow.
CHAPTER
Using DirectShow for Digital Editing
19
IN THIS CHAPTER • DirectShow Editing Services (DES) • Summary
313
298
298
Streaming Media with DirectShow PART V
Digital editing is a new feature of DirectX. With the digital-editing capabilities of DirectShow, you can create applications that function like the ones used in professional studios. The DirectShow Editing Services (DES) is a library that you can use to create timelines, provide transitions and effects, and export the finished product from the editing session.
DirectShow Editing Services (DES) The DirectShow Editing Services is a collection of methods that are part of the qedit.dll (known as the Dexter 1.0 type library). The purpose of this DLL is to give you the capabilities of digital editing software. With this library, you can create audio and video timelines, modify tracks with transitions, and crop and resize video. To use the Dexter 1.0 type library, you must first make a reference to it in the References dialog box in Visual Basic. The DLL is usually found in the following path: C:\WINNT\System32\qedit.dll.
NOTE The following tables that show the methods of each of the classes discussed in this chapter do not include methods that are not supported in VB. Some methods may be available when you reference these objects, but they are really not implemented for VB at this time. Therefore, if you see a method of one of these objects in the VB object browser but don’t see an explanation here, the reason is that it is not supported yet.
The AMTimeLine Class The AMTimeLine class provides methods for managing a DirectShow timeline. It is responsible for creating the objects in the timeline, holding those objects, and setting and retrieving the timeline’s attributes. A timeline is part of the DirectShow Editing Services (DES), which is the core of the DirectShow editing capabilities. A timeline is like a video tape; at specific points along the tape, certain events happen. Video, music, and sound will play, all at times the editor has specified. Table 19.1 shows the AMTimeLine methods that are available in Visual Basic. TABLE 19.1
The AMTimeLine Methods
Method
Description
AddGroup
Adds a group to the timeline. Clears all groups from the timeline.
ClearAllGroups
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.1
299
Continued
Description
CreateEmptyNode
Creates a new timeline object. Finds out whether the effects in the timeline are disabled or enabled. Toggles turning on/off effects in the timeline. Toggles turning on/off transition effects in the timeline. Gets the number of objects of a specific type in a group. This method also counts the specified objects in the children of this group. Gets a GUID for the default effect. Gets the default frames per second (fps) for output on the timeline. Gets a GUID for the default transition that can be used if another transition is not found on the system. Gets the duration of the timeline. Gets a group from a supplied index. Gets the number of groups in the timeline. Sets the default effect by providing the GUID that identifies it. Sets the default frames per second (fps) for output on the timeline. Sets the default transition by providing the GUID that identifies it. Determines whether transitions are enabled/disabled for the timeline. Validates the source names in the timeline.
EffectsEnabled EnableEffects EnableTransitions GetCountOfType
GetDefaultEffectB GetDefaultFPS GetDefaultTransitionB GetDuration2 GetGroup GetGroupCount SetDefaultEffectB SetDefaultFPS SetDefaultTransitionB TransitionEnabled ValidSourceNames
The AMTimelineComp Class The AMTimelineComp class is used to insert or retrieve virtual tracks on a composition in DES. A composition is a combination of two or more video or audio tracks that are combined to create a new track. A track is one single layer of audio or video, such as audio of someone talking or video footage of a bird flying. While the track is in memory, it is referred to as a virtual track. Table 19.2 shows the AMTimelineComp methods that are available in Visual Basic.
19 USING DIRECTSHOW FOR DIGITAL EDITING
Method
300
Streaming Media with DirectShow PART V
TABLE 19.2
The AMTimelineComp Methods
Method
Description
GetCountOfType
Gets the number of a specific type of object in the composition as well as all its children. Gets the next virtual track after a specified track. Gets the lowest track in the order of each virtual track. Gets the virtual track at the specified priority. Gets the number of virtual tracks in the composition. Inserts a virtual track before a specified point. Switches the priority levels of two virtual tracks.
GetNextVTrack GetRecursiveLayerOfType GetVTrack VTrackGetCount VTrackInsBefore VTrackSwapPriorities
The AMTimelineEffect Class The AMTimelineEffect class is used to determine an effect’s priority in a timeline in the DES. A priority level defines in what order the timeline will use the effects. Effects with a priority of 0 have the highest priority. Table 19.3 shows the only AMTimelineEffect method that is available in Visual Basic. TABLE 19.3
The AMTimelineEffect Method
Method
Description
EffectGetPriority
Gets the priority level of an effect.
The AMTimelineGroup Class The AMTimelineGroup class is used to manage groups in the timeline. Groups are collections of one or more tracks and compositions. Table 19.4 shows the AMTimelineGroup methods that are available in Visual Basic. TABLE 19.4
The AMTimelineGroup Methods
Method
Description
GetGroupName
Gets the group’s application-defined name. Gets the number of frames that are buffered during preview. Gets the group’s output frame rate. Gets the group’s preview mode. Gets the group’s priority.
GetOutputBuffering GetOutputFPS GetPreviewMode GetPriority
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.4
301
Continued
Method
Description
GetTimeline
Gets the timeline that corresponds to the group. Sets the group’s application-defined name. Sets the media type (video or audio) for the group. Sets the number of frames that should be buffered during preview. Sets the group’s uncompressed output frame rate. Sets the preview mode for the group (0 = authoring mode, non-zero = preview mode). Sets the group’s compression format by using a source file.
SetGroupName SetMediaTypeForVB SetOutputBuffering SetOutputFPS SetPreviewMode SetRecompFormatFromSource
The AMTimelineObj Class The AMTimelineObj class is responsible for maintaining the timeline itself. Table 19.5 shows the AMTimelineObj methods that are available in Visual Basic. TABLE 19.5
The AMTimelineObj Method
Description
FixTimes2
Rounds the start and stop times to the nearest frame, based on the parent group’s frame rate setting. Gets the object’s generated identifier. Finds out whether the object’s editing state is locked or unlocked (0 = unlocked, non-zero = locked). Finds out whether the object is muted (0 = not muted, nonzero = muted). Gets the object’s start and stop times in relation to its parent. Gets the GUID of the subobject associated with the timeline object. Finds out whether the subobject has been loaded (0 = not created, non-zero = created). Gets the object’s type. Gets the application-defined persistent data. Gets the object’s user ID.
GetGenID GetLocked GetMuted GetStartStop2 GetSubObjectGUIDB GetSubObjectLoaded GetTimelineType GetUserData GetUserID
19 USING DIRECTSHOW FOR DIGITAL EDITING
Method
302
Streaming Media with DirectShow PART V
TABLE 19.5
Continued
Method
Description
GetUserName
Gets the object’s username. Cuts the object out of the timeline so that it can be placed in another location. Removes this object and all its subobjects from the timeline. Sets the object’s editing state to unlocked (0) or locked (non-zero). Sets the object to muted (non-zero) or non-muted(0). Sets the object’s start and stop time based on the object’s parent. Sets the GUID of the subobject associated with the object. Sets an array of persistent data. Sets a user ID for the object. Sets a username for the object.
Remove RemoveAll SetLocked SetMuted SetStartStop2 SetSubObjectGUIDB SetUserData SetUserID SetUserName
The AMTimelineSrc Class The AMTimelineSrc class is used to maintain and manipulate a clip that has been taken from a stream in a source file. You can use these methods to set the start and stop times of the AMTimelineSrc object. Table 19.6 shows the AMTimelineSrc methods that are available in Visual Basic. TABLE 19.6
The AMTimelineSrc Methods
Method
Description
FixMediaTimes2
Rounds the specified time to the nearest frame boundary. Gets the source object’s default frame rate. Gets the media length of this object. Gets the object’s source filename. Gets the media start and stop times. Gets the current stream number. Gets the stretch mode. Finds out if the clip will play at the authorized playback rate.
GetDefaultFPS GetMediaLength2 GetMediaName GetMediaTimes2 GetStreamNumber GetStretchMode IsNormalRate
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.6
303
Continued
Method
Description
ModifyStopTime2
Sets the stop time. Sets the source object’s default frames per second. Sets the duration of the source file. Sets the name of the source file. Sets the media start and stop times. Sets which stream to read from the source file. Sets the stretch mode. Joins two AMTimelineSrc objects.
SetDefaultFPS SetMediaLength2 SetMediaName SetMediaTimes2 SetStreamNumber SetStretchMode SpliceWithNext
The AMTimelineTrack Class The AMTimelineTrack class maintains and manipulates tracks of media. A track is a layer of media that is combined with other tracks to form a final output. Table 19.7 shows the AMTimelineTrack methods that are available in Visual Basic. TABLE 19.7
The AMTimelineTrack Methods
Description
AreYouBlank
Checks the track to see if it contains no source objects. Finds the next source at a specified time or later. Gets the next source after the specified source. Gets a count of the sources on a track. Gets the closest source on the track to a specified time. Inserts space between an object. Adds a source to the track. Removes everything from the track between specified times.
GetNextSrc2 GetNextSrcEx GetSourcesCount GetSrcAtTime2 InsertSpace2 SrcAdd ZeroBetween2
The AMTimelineTrans Class The AMTimelineTrans class is used to manipulate transitions in DES. Transitions are methods for moving from one media to another, such as one picture fading into another picture. Table 19.8 shows the AMTimelineTrans methods that are available in Visual Basic.
19 USING DIRECTSHOW FOR DIGITAL EDITING
Method
304
Streaming Media with DirectShow PART V
TABLE 19.8
The AMTimelineTrans Methods
Method
Description
GetCutPoint2
Gets the cut point. Checks to see whether a transition is rendered as a cut. Checks to see whether the transition inputs are swapped. Sets the cut point. Specifies that the transition is rendered as a cut. Specifies that the transition inputs are swapped.
GetCutsOnly GetSwapInputs SetCutPoint2 SetCutsOnly SetSwapInputs
The IAMErrorLog Class The IAMErrorLog class is used to alert you of errors created in the DES. IAMErrorLog uses the callback method to do this. Table 19.9 shows the IAMErrorLog methods that are available in Visual Basic. LogError
TABLE 19.9
The IAMErrorLog Methods
Method
Description
LogError
Logs an error from the timeline. This method provides the error string, error code, an hresult, and any additional information.
The IAMSetErrorLog Class The IAMSetErrorLog sets or gets an error log in the DES by using a timeline object. You can use this class in your application to log errors at runtime. Table 19.10 shows the IAMSetErrorLog method that is available in Visual Basic. TABLE 19.10
The IAMSetErrorLog Method
Method
Description
ErrorLog
Gets or sets the error log for an object.
The IAMTimelineEffectable Class The IAMTimelineEffectable class is responsible for adding and manipulating effects in a timeline object. Table 19.11 shows the IAMTimelineEffectable methods that are available in Visual Basic.
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.11
305
The IAMTimelineEffectable Methods
Method
Description
EffectGetCount
Gets the number of effects for this object. Inserts a specific effect at the indicated priority level. Swaps the priority levels of two different effects. Gets the effect at a given priority level.
EffectInsBefore EffectSwapPriorities GetEffect
The IAMTimelineSplittable Class The IAMTimelineSplittable class splits a timeline object by specifying when in the timeline to perform the split. By dividing the timeline, you can add transitions. Table 19.12 shows the IAMTimelineSplittable method that is available in Visual Basic. TABLE 19.12
The IAMTimelineSplittable Method
Method
Description
SplitAt2
By specifying how many seconds into the timeline to split it, this method can divide the timeline.
The IAMTimelineTransable Class The IAMTimelineTransable class adds transitions to tracks, compositions, and groups. There can be an unlimited number of transitions in any of the previously supported objects. Table 19.13 shows the IAMTimelineTransable methods that are available in Visual Basic.
19 The IAMTimelineTransable Methods
Method
Description
GetNextTrans2
Gets the current or next transition that occurs at a specific time. Gets the nearest transition to a specified time. You can specify a time in seconds where you want to begin searching for the transition in the timeline. The nearest transition in front of or behind this point is what is returned by this method. Adds a transition to a track, composition, or group. Get the number of transitions in the track, composition, or group.
GetTransAtTime2
TransAdd TransGetCount
USING DIRECTSHOW FOR DIGITAL EDITING
TABLE 19.13
306
Streaming Media with DirectShow PART V
The IAMTimelineVirtualTrack Class The IAMTimelineVirtualTrack class provides the ability to retrieve virtual track priority information for composition and track objects. Table 19.14 shows the IAMTimeline VirtualTrack method that is available in Visual Basic. TABLE 19.14
The IAMTimelineVirtualTrack Method
Method
Description
TrackGetProperty
Gets virtual track priority information for the track or composition.
The IEnumFilters Class The IEnumFilters class contains a collection of the current filters in the filter graph. Table 19.15 shows the IEnumFilters methods that are available in Visual Basic. TABLE 19.15
The IEnumFilters Methods
Method
Description
Clone
Makes a copy of the enumerator. Gets the next specified number of filters in the enumeration sequence. Resets the enumeration sequence to the beginning. Skips over a specific number of filters.
Next Reset Skip
The IEnumMediaTypes Class The IEnumMediaTypes class is used by pins to examine a pin’s preferred media types. This class has the same methods as the IEnumFilters class.
The IEnumPins Class The IEnumPins class is used by the filter graph manager when connecting to filters. You can use this class to get a filter’s pins. This class has the same methods as the IEnumFilters class.
The IErrorLog Class The IErrorLog class has only one method, designed to add error entries to a log file. Table 19.16 shows the IErrorLog method that is available in Visual Basic.
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.16
307
The IErrorLog Method
Method
Description
AddError
Adds an error to the error log.
The IFilterGraph Class The IFilterGraph class provides the methods necessary to build a filter graph. The methods of IFilterGraph can be used to add filters, connect filters, disconnect filters, enumerate filters, find filters, reconnect filters, and remove filters. Table 19.17 shows the IFilterGraph methods that are available in Visual Basic. TABLE 19.17
The IFilterGraph Methods
Method
Description
AddFilter
Adds a filter to the filter graph. Connects two filters by connecting their pins. Disconnects a specific pin. Enumerates all the filters in the filter graph. Finds a filter with a specific name. Breaks and reconnects a connection between pins. Removes a filter from the filter graph. Sets the default synchronization source, which is a clock used to keep track of synchronization needs.
ConnectDirect Disconnect EnumFilters FindFilterByName Reconnect RemoveFilter SetDefaultSyncSource
19 The IGraphBuilder class enables an application to build a filter graph. The methods in this class can add filters and connect, disconnect, render, and remove files from the graph filter. These methods use pins to connect the filters in the filter graph. Table 19.19 shows the IGraphBuilder methods that are available in Visual Basic. TABLE 19.19
The IGraphBuilder Methods
Method
Description
Abort
Sends a request to the builder to return from its current task as soon as possible. Adds a filter to the filter graph.
AddFilter
USING DIRECTSHOW FOR DIGITAL EDITING
The IGraphBuilder Class
308
Streaming Media with DirectShow PART V
TABLE 19.19
Continued
Method
Description
AddSourceFilter
Adds a source filter to the filter graph. Connects two pins. Connects two pins. Disconnects a specific pin. Enumerates all the filters in the filter graph. Finds a filter with a specific name. Breaks and reconnects a connection between pins. Removes a filter from the filter graph. Adds filters to an output pin to render it. Builds a filter graph to output a file. Sets the default synchronization source (a clock used to keep track of synchronization needs). Specifies a file for logging actions during the building of the filter graph. Checks whether the current operation should continue.
Connect ConnectDirect Disconnect EnumFilters FindFilterByName Reconnect RemoveFilter Render RenderFile SetDefaultSyncSource SetLogFile ShouldOperationContinue
The IMediaFilter Class The IMediaFilter classis used by filters to start, stop, and pause their state. Table 19.20 shows the IMediaFilter methods that are available in Visual Basic. TABLE 19.20
The IMediaFilter Methods
Method
Description
GetClassID
Gets the GUID for the specified media filter. Gets the filter’s state (started, stopped, running). Gets the reference clock (syncsource) for the filter. Pauses the filter. Runs the filter. Sets the reference clock (syncsource) for the filter. Stops the filter.
GetState GetSyncSource Pause Run SetSyncSource Stop
Using DirectShow for Digital Editing CHAPTER 19
309
The IMediaSample Class The IMediaSample class is used to get information on media samples, which are pieces of media data such as music, video, or audio. Table 19.21 shows the IMediaSample methods that are available in Visual Basic. TABLE 19.21
The IMediaSample Methods
Description
GetActualDataLength
Gets the length of the accessible data in the buffer. Gets the media time. Gets the media type. Gets a pointer to the read/write memory buffer. Gets the buffer’s size. Gets the start and stop times for the stream. Checks whether the sample has a break in the data stream. Finds out if this sample is a preroll sample. Finds out if the beginning of the stream is a synchronization point. Sets the length of the accessible data in the buffer. Sets whether the sample represents a break in the data stream. Sets the media time. Sets the media type. Specifies whether the specified sample is a preroll. Sets up the beginning of the stream as a synchronization point. Sets the start and stop times for the stream.
GetMediaTime GetMediaType GetPointer GetSize GetTime IsDiscontinuity IsPreroll IsSyncPoint SetActualDataLength SetDiscontinuity SetMediaTime SetMediaType SetPreroll SetSyncPoint SetTime
The IPersistStream Class The IPersistStream class is responsible for managing the filter properties of a stream. Table 19.22 shows the IPersistStream methods that are available in Visual Basic. TABLE 19.22
The IPersistStream Methods
Method
Description
GetSizeMax
Gets the maximum byte size needed for the current stream. Returns a value that tells whether the current object has been modified since its last save to the stream.
IsDirty
19 USING DIRECTSHOW FOR DIGITAL EDITING
Method
310
Streaming Media with DirectShow PART V
TABLE 19.22
Continued
Method
Description
Load
Loads filter data from a given stream. Saves filter data to the supplied stream.
Save
The IPin Class The filter manager uses the IPin class to connect pins and query them for information. This class works with both input and output pins. This class also includes methods that flush (or remove) the pin connections from the filter graph. Table 19.23 shows the IPin methods that are available in Visual Basic. TABLE 19.23
The IPin Methods
Method
Description
BeginFlush
Begins the flush operation. Connects one pin to another. Gets the pin connected to the specified pin. Gets the media type for the current pin. Breaks a pin connection. Ends a flush operation. Tells the pin that no more data is expected. Gathers a list of the pin’s preferred media types. Tells the pin that the next media samples are part of a new segment. Finds out if the pin accepts a specified media type. Gets the direction (input or output) of the pin. Gets the pin identifier. Gets the pins that are part of the filter assigned to another pin. Gets the name, owning filter, and direction of a pin. Gets a connection from another pin.
Connect ConnectedTo ConnectionMediaType Disconnect EndFlush EndOfStream EnumMediaTypes NewSegment QueryAccept QueryDirection QueryId QueryInternalConnections QueryPinInfo ReceiveConnection
The IReferenceClock Class The IReferenceClock class is used to reference a system clock. Table 19.24 shows the IReferenceClock methods that are available in Visual Basic.
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.24
311
The IReferenceClock Methods
Method
Description
AdvisePeriodic
Requests an asynchronous notification that a specific time limit has passed. Requests an asynchronous, periodic notification that a specific time limit has passed. Gets the current time. Cancels the request for notification.
AdviseTime GetTime Unadvise
The ISmartRenderEngine Class The ISmartRenderEngine provides methods that use the smart recompression technology. Smart recompression is designed to improve performance by recompressing source files only when the original file format differs from the final output format. If the formats match, no compression is done. Table 19.25 shows the ISmartRenderEngine methods that are available in Visual Basic. TABLE 19.25
The ISmartRenderEngine Methods
Method
Description
GetGroupCompressor
Gets a compression filter for a specified group. Sets a compression filter for a specified group.
SetGroupCompressor
The MediaDet Class
TABLE 19.26
The MediaDet Methods
Method
Description
CurrentStream
Gets the current stream number being used by the MediaDet class. Switches to grab mode and seeks the filter graph to a specified time. Sets or gets the name of the source file currently being used. Gets the frame rate of the current stream.
EnterBitmapGrabMode Filename FrameRate
19 USING DIRECTSHOW FOR DIGITAL EDITING
The MediaDet class is responsible for obtaining information about a media file, such as the number of streams, duration, frame rate, and type. Table 19.26 shows the MediaDet methods that are available in Visual Basic.
312
Streaming Media with DirectShow PART V
TABLE 19.26
Continued
Method
Description
OutputStreams
Gets the number of output streams in the media source. Gets the duration of the current stream in seconds. Sets or gets the media type for the stream. This value is stored as a GUID. Captures a poster frame at a specified time in the stream and outputs it to a file.
StreamLength StreamTypeB WriteBitmapBits
The MediaLocator Class The MediaLocator class is responsible for validating the filenames of media files used in the DES. You can use these methods to make sure files are available before your code continues. Table 19.27 shows the MediaLocator methods that are available in Visual Basic. TABLE 19.27
The MediaLocator Methods
Method
Description
AddFoundLocation
Adds a directory to the directory cache. Searches for a specified file. If the file is found, a path is returned.
FindMediaFile
The RenderEngine Class The RenderEngine class is responsible for creating the filter graph from an existing timeline. Table 19.28 shows the RenderEngine methods that are available in Visual Basic. TABLE 19.28
The RenderEngine Methods
Method
Description
ConnectFrontEnd
Creates the front end of the filter graph based on the current timeline. Gets the filter graph created by the render engine. Gets the output pin for a group. Gets the timeline being used by the render engine. Gets the vendor string. Creates the previewing portion of the filter graph. Destroys the filter engine created by the render engine.
GetFilterGraph GetGroupOutputPin GetTimelineObject GetVendorString RenderOutputPins ScrapIt
Using DirectShow for Digital Editing CHAPTER 19
TABLE 19.28
313
Continued
Method
Description
SetDynamicReconnectLevel
Sets the dynamic reconnection level during rendering. Sets a filter graph for the render engine to use. Sets how the render engine validates filenames. Assigns a timeline to the render engine.
SetFilterGraph SetSourceNameValidation SetTimelineObject
The SmartRenderEngine Class This class has the same methods as the RenderEngine class.
The Xml2Dex Class The Xml2Dex class is used to load and save DES project files. These files are stored in XML format, so the methods in this class enable you to read and write XML files. Table 19.29 shows the Xml2Dex methods that are available in Visual Basic. TABLE 19.29
The Xml2Dex Methods
Method
Description
ReadXMLFile
Loads an XML project file into memory. Writes the contents of the filter graph to a .grf format file. The .grf format is a DirectX-specific format that stores information about the graphic filter. Takes a timeline and translates it to an XML string. Translates a timeline to an XML string and then writes it to a file.
WriteGrfFile WriteXML WriteXMLFile
In this chapter, you have learned about the digital editing abilities of DirectShow. In DirectShow, you learned that you can use the DirectShow Editing Services (DES) to create timelines, mix audio, create transitions, and render completed timelines. In the next chapter, you will learn about the DirectMovie player and how it can be used with DirectShow to create movie players.
USING DIRECTSHOW FOR DIGITAL EDITING
Summary
19
CHAPTER
Multimedia Players
20
IN THIS CHAPTER • The ActiveMovie DLL
316
• An Example Using the ActiveMovie DLL • Microsoft Web DVD Control • Summary
336
330
324
316
Streaming Media with DirectShow PART V
This chapter focuses on DirectShow and how it can be used to create multimedia players. The main library used for this is the quartz.dll (ActiveMovie). The chapter begins with a review of the objects and methods available in this DLL, and then discusses a multimedia application that will open and play MP3 files. Finally, you will learn about the Web DVD control that allows you to control DVD playback from your applications.
The ActiveMovie DLL One of the components of DirectSound is the quartz.dll ActiveMovie type library. This resource gives you access to many multimedia types and allows you to play back most of them. The ActiveMovie DLL is the multimedia library that gives you full access to playback capabilities for movie players and audio players.
The FilgraphManager Object The filter graph manager object (FilgraphManager) builds the file-playback graphs. It is also the object that stops, starts, and pauses playback of the file-playback graph and looks for filters in the Registry. Table 20.1 shows the FilgraphManager methods that are available in Visual Basic. TABLE 20.1
The FilgraphManager Methods
Methods
Description
AddSourceFilter
Adds a source filter to the filter graph. Gets a collection of the filters in the filter graph. Gets the current state of the filter graph. Pauses the filters in the filter graph. Gets a collection of all the filters listed in the Registry. Builds a filter graph that renders the specified file. Runs the filters in the filter graph. Stops the filters in the filter graph. Pauses the filter graph, allowing the filters to queue data, and then stops the filter graph.
FilterCollection GetState Pause RegFilterCollection RenderFile Run Stop StopWhenReady
The IAMCollection Class This class is used as a collection of objects within ActiveMovie. An IAMCollection can be a collection of pins, filter info, and so on. Table 20.2 shows the IAMCollection methods that are available in Visual Basic.
Multimedia Players CHAPTER 20
TABLE 20.2
317
The IAMCollection Methods
Methods
Description
Count
Gets the number of items in the IAMCollection. Gets a specific item from the IAMCollection.
Item
The IAMStats Class The IAMStats class is used to get performance data from the filter graph manager. Filters can use this class to record performance data. Table 20.3 shows the IAMStats methods that are available in Visual Basic. TABLE 20.3
The IAMStats Methods
Methods
Description
AddValue
Adds a new item to the ActiveMovie Stats object. Gets the number of items that were collected for a given statistic. Gets the index for a specific statistic or creates a new statistic. Gets a statistic that is referenced by a index number. Gets a specific statistic that is referenced by a name. Resets all the statistics to zero.
Count GetIndex GetValueByIndex GetValueByName Reset
The IBasicAudio Class The IBasicAudio class is used to control the balance and volume levels of the filter graph. Table 20.4 shows the IBasicAudio methods that are available in Visual Basic. TABLE 20.4
The IBasicAudio Methods
Methods
Description
Balance
Gets and sets the left and right audio balance. Gets and sets the volume level.
Volume
The IBasicVideo Class
MULTIMEDIA PLAYERS
The IBasicVideo class is used to manipulate the source rectangle, destination rectangle, and video rectangle during video playback. Table 20.5 shows the IBasicVideo methods that are available in Visual Basic.
20
318
Streaming Media with DirectShow PART V
TABLE 20.5
The IBasicVideo Methods
Methods
Description
AvgTimePerFrame
Gets the average time between frames of the video being played. Gets the bit error rate of the video stream. Gets the bit rate of the video stream. Gets the height of the destination rectangle. Gets the left position of the destination rectangle. Gets the top position of the destination rectangle. Gets the width of the destination rectangle. Gets the current image waiting at the renderer. Gets the position of the destination rectangle. Gets the position of the source rectangle. Gets the palette colors for the video. Gets the native video dimensions. Returns a Boolean value that shows whether the renderer is using the default destination rectangle. Returns a Boolean value that shows whether the renderer is using the default source rectangle. Sets the default destination for playback to the default window. Sets the default source position to use the entire video image without cropping. Sets the destination rectangle. Sets the source rectangle. Gets the height of the source rectangle. Gets the left position of the source rectangle. Gets the top position of the source rectangle. Gets the width of the source rectangle. Gets the native height of the video. Gets the native width of the video.
BitErrorRate BitRate DestinationHeight DestinationLeft DestinationTop DestinationWidth GetCurrentImage GetDestinationPosition GetSourcePosition GetVideoPaletteEntries GetVideoSize IsUsingDefaultDestination IsUsingDefaultSource SetDefaultDestinationPosition SetDefaultSourcePosition SetDestinationPosition SetSourcePosition SourceHeight SourceLeft SourceTop SourceWidth VideoHeight VideoWidth
Multimedia Players CHAPTER 20
319
The IBasicVideo2 Class The IBasicVideo2 class is an extension of the IBasicVideo class. It inherits all the IBasicVideo methods and adds one additional method to handle aspect ratios. Table 20.6 shows the IBasicVideo2 method that is available in Visual Basic. TABLE 20.6
The IBasicVideo2 Method
Methods
Description
GetPreferredAspectRatio
Gets a pair of dimensionless values whose ratio defines the movie’s preferred aspect ratio.
The IDeferredCommand Class The IDeferredCommand class is used to modify or stop graph-control commands that were started by the IQueueCommand class. Table 20.7 shows the IDeferredCommand methods that are available in Visual Basic. TABLE 20.7
The IDeferredCommand Methods
Methods
Description
Cancel
Cancels a previously queued command. Gets a confidence value (scale: 0 to 100) that indicates how likely it is that the command will be completed at the requested time. Gets the returned value from the command that was issued. Sets a new time for the command to be issued.
Confidence GetHResult Postpone
The IFilterInfo Object The IFilterInfo object manages information about the filter. It also gives you access to the filter and to the filter’s pins. Table 20.8 shows the IFilterInfo methods that are available in Visual Basic. TABLE 20.8
The IFilterInfo Methods
Description
Filename
Gets the filename containing the media source. Gets the IBaseFilter interface for the filter. Finds a pin and returns an IPinInfo interface.
Filter FindPin
20 MULTIMEDIA PLAYERS
Methods
320
Streaming Media with DirectShow PART V
TABLE 20.8
Continued
Methods
Description
IsFileSource
Finds out if the filter is a file source filter. Gets the filter name. Gets an IAMCollection interface, which provides access to the pin interfaces for this filter. Gets a string with information about the current filter.
Name Pins VendorInfo
The IMediaEvent Object The IMediaEvent object is responsible for getting event notifications. It also overrides the filter graph manager’s handling of events. Table 20.9 shows the IMediaEvent methods that are available in Visual Basic. TABLE 20.9
The IMediaEvent Methods
Methods
Description
CancelDefaultHandling
Cancels the filter graph manager’s default handling. Frees event parameters of the filter graph manager. Gets the next event notification from the event queue. Gets a handle to a media event. Returns control of event handling to the filter graph manager’s default handler. Waits for all available data to be rendered by the filter graph.
FreeEventParams GetEvent GetEventHandle RestoreDefaultHandling WaitForCompletion
The IMediaEventEx Object This object is an extension of the IMediaEvent object. It includes all the IMediaEvent methods and adds the ones listed in Table 20.10. TABLE 20.10
The IMediaEventEx Methods
Methods
Description
SetNotifyWindow
Sets up a window to process event notifications. Enables or disables event notification. Finds out if event notifications are enabled.
SetNotifyFlags GetNotifyFlags
Multimedia Players CHAPTER 20
321
The IMediaPosition Object The IMediaPosition object has methods that position the pointer at a specific point in a stream and set the playback rate. The IMediaPosition object is retrieved from the filter graph manager. Table 20.11 shows the IMediaPosition methods that are available in Visual Basic. TABLE 20.11
The IMediaPosition Methods
Methods
Description
CanSeekBackward
Checks to see whether the filter graph can seek backward in the stream. Checks to see whether the filter graph can seek forward in the stream. Sets or gets the current position in the stream. Gets the duration of the stream. Gets the amount of data queued before the start position. Gets or sets the playback rate. Gets or sets the time the playback will stop.
CanSeekForward CurrentPosition Duration PrerollTime Rate StopTime
The IMediaTypeInfo Object The IMediaTypeInfo object retrieves the media type of a pin connection. Table 20.12 shows the IMediaTypeInfo methods that are available in Visual Basic. TABLE 20.12
The IMediaTypeInfo Methods
Methods
Description
Subtype
Gets the subtype’s GUID. Gets the pin’s GUID.
Type
The IPinInfo Object The IPinInfo object enables you to get information, such as the media type and direction, about a pin. You can also use it to connect pins. Table 20.13 shows the IPinInfo methods that are available in Visual Basic.
20 MULTIMEDIA PLAYERS
322
Streaming Media with DirectShow PART V
TABLE 20.13
The IPinInfo Methods
Methods
Description
Connect
Connects to a specific pin. Connects directly to a pin, bypassing any intermediate filters. Gets the IPinInfo interface for the connected pin. Gets the IMediaTypeInfo object that has the connection information. Connects to a specific pin, using a specified media type. Gets the pin direction. Disconnects the pin. Gets the IFilterInfo interface for the filter that this pin belongs to. Gets an IAMCollection interface that provides access to the preferred media types supported by this pin. Gets the name of the pin. Gets an IPin interface object. Gets the pin identifier. Connects the filters needed to render the pin’s output, using any necessary filters.
ConnectDirect ConnectedTo ConnectionMediaType ConnectWithType Direction Disconnect FilterInfo MediaTypes Name Pin PinID Render
The IQueueCommand Class The IQueueCommand class queues methods to be called at specified times. Table 20.14 shows the IQueueCommand methods that are available in Visual Basic. TABLE 20.14
The IQueueCommand Methods
Methods
Description
InvokeAtPresentationTime
Queues a method to be called at a specified presentation time. Queues a method to be called at a specified stream time.
InvokeAtStreamTime
The IRegFilterInfo Object The IRegFilterInfo object provides information about filters that are registered in the Windows Registry. It also adds a filter to the filter graph. Table 20.15 shows the IRegFilterInfo methods that are available in Visual Basic.
Multimedia Players CHAPTER 20
TABLE 20.15
323
The IRegFilterInfo Methods
Methods
Description
Filter
Creates an instance of a filter and adds it to the filter graph. Gets the name of the filter.
Name
The IVideoWindow Class The IVideoWindow class is responsible for setting up a video window for playback. It includes methods that specify attributes such as the size and position of the video window. Table 20.16 shows the IVideoWindow methods that are available in Visual Basic. TABLE 20.16
The IVideoWindow Methods
Description
AutoShow
Finds out if the video renderer automatically shows the video window when it receives video data. Finds out if the video window realizes its palette in the background. Gets the color that shows up around the edges of the destination rectangle. Gets and sets the window caption. Enables or disables the full-screen mode. Gets the maximum ideal size for the video image. Gets the minimum ideal size for the video image. Gets the restored window position. Gets the position of the video window. Gets and sets the height of the video window. Hides or shows the cursor. Finds out if the cursor is hidden. Gets or sets the x-coordinate of the video window. Gets and sets a window that receives mouse and keyboard messages from the video window. Forwards a message to the video window. Gets or sets the parent window for the video window. Brings the video window to the foreground. Sets the position of the video window.
BackgroundPalette BorderColor Caption FullScreenMode GetMaxIdealImageSize GetMinIdealImageSize GetRestorePosition GetWindowPosition Height HideCursor IsCursorHidden Left MessageDrain NotifyOwnerMessage Owner SetWindowForeground SetWindowPosition
20 MULTIMEDIA PLAYERS
Methods
324
Streaming Media with DirectShow PART V
TABLE 20.16
Continued
Methods
Description
Top
Gets and sets the y-coordinate of the video window. Gets and sets the visibility property of the video window. Gets and sets the width of the video window. Gets and sets the window state (includes show, hide, minimize, and maximize) of the video window. Gets and sets the window styles of the video window. Gets and sets the extended window styles on the video window.
Visible Width WindowState WindowStyle WindowStyleEx
An Example Using the ActiveMovie DLL Listing 20.1 is a portion of the Jukebox program, which uses the ActiveMovie DLL to create a MP3 audio player. The subroutine in the listing handles creating all the ActiveMovie classes used in the Jukebox program. The comments in the code explain how and why each component and method is being used. The complete code for this example can be found on the Sams Web site. LISTING 20.1
The Jukebox Application
Private m_sFileName As String Private m_dMediaLength As Double Private m_dStartPos As Double Private m_bMediaPlaying As Boolean
‘’’Loaded filename ‘’’Length (in seconds) of ‘’’ media file ‘’’Start position in seconds ‘’’Flag used to trigger clock
Private Private Private Private
‘’’Basic Audio object ‘’’MediaEvent object ‘’’MediaControl object ‘’’MediaPosition object
m_oBasicAudio As IBasicAudio m_oMediaEvent As IMediaEvent m_oMediaControl As IMediaControl m_oMediaPosition As IMediaPosition
‘***************************************************************************** ‘** ObjectName: cmdPause_Click ‘** ‘** Description: This is the click event when the user presses the pause ‘** button. ‘** ‘***************************************************************************** Private Sub cmdPause_Click()
Multimedia Players CHAPTER 20
LISTING 20.1
325
Continued
If Not m_oMediaControl Is Nothing Then ‘’’ Pause the playback m_oMediaControl.Pause m_bMediaPlaying = False ‘’’ Update your buttons cmdPlay.Enabled = True cmdPause.Enabled = False cmdStop.Enabled = True End If End Sub ‘***************************************************************************** ‘** ObjectName: cmdPlay_Click ‘** ‘** Description: This is the click event when the user presses the play ‘** button. ‘** ‘***************************************************************************** Private Sub cmdPlay_Click() If Not m_oMediaControl Is Nothing Then ‘’’ Reset the starting position If CLng(m_oMediaPosition.CurrentPosition) < CLng(m_dStartPos) Then ‘’’ Paused, so you need to reset the current position ‘’’ to the start position from where it was paused. m_oMediaPosition.CurrentPosition = m_dStartPos ElseIf CLng(m_oMediaPosition.CurrentPosition) = CLng(m_dMediaLength) _ Then ‘’’ At the end of the file, so reset counter m_oMediaPosition.CurrentPosition = m_dStartPos End If ‘’’ Play is invoked by calling the Run method m_oMediaControl.Run
MULTIMEDIA PLAYERS
m_bMediaPlaying = True
20
326
Streaming Media with DirectShow PART V
LISTING 20.1
Continued
‘’’ Update your buttons cmdPlay.Enabled = False cmdPause.Enabled = True cmdStop.Enabled = True End If End Sub ‘***************************************************************************** ‘** ObjectName: cmdLoadMP3_Click ‘** ‘** Description: This subroutine loads a common dialog to determine the MP3 ‘** file to load. You can then create a filter graph, create the ‘** IBasicAudio object, and set the volume. You then can set up ‘** the IMediaEvent and IMediaPosition, and start the playback ‘** of the MP3 file. ‘** ‘***************************************************************************** Private Sub cmdLoadMP3_Click() Dim nCount As Long Dim sFileTitle As String ‘’’ Load the common dialog and find a file to play. CommonDialog1.Filter = “MP3 Files (*.mp3)|*.mp3” CommonDialog1.ShowOpen m_sFileName = CommonDialog1.FileName sFileTitle = CommonDialog1.FileTitle ‘’’ Clean out any older files Call Form_Unload(True) ‘’’ Create a filter graph Set m_oMediaControl = New FilgraphManager Call m_oMediaControl.RenderFile(m_sFileName) ‘’’ Display the filename lblTitle.Caption = sFileTitle ‘’’ Set up the IBasicAudio object and set the volume Set m_oBasicAudio = m_oMediaControl m_oBasicAudio.Volume = sldVolume.Value
Multimedia Players CHAPTER 20
LISTING 20.1
327
Continued
‘’’ Set up the IMediaEvent Set m_oMediaEvent = m_oMediaControl ‘’’ Set up the IMediaPosition Set m_oMediaPosition = m_oMediaControl ‘’’ Find out how long the file is. m_dMediaLength = Round(m_oMediaPosition.Duration, 2) lblElapsed.Caption = CStr(m_dMediaLength) ‘’’ Reset start position to 0 m_dStartPos = 0 ‘’’ Update your buttons cmdPlay.Enabled = True cmdStop.Enabled = False cmdPause.Enabled = False ‘’’ Run the media file cmdPlay_Click End Sub ‘***************************************************************************** ‘** ObjectName: cmdStop_Click ‘** ‘** Description: This subroutine tells the IMediaControl object to stop ‘** playback and set the current position to the start of the ‘** media file. ‘** ‘***************************************************************************** Private Sub cmdStop_Click() If Not m_oMediaControl Is Nothing Then ‘’’ Call the stop method of the IMediaControl Call m_oMediaControl.Stop m_bMediaPlaying = False ‘’’ Reset the position in the file for playback m_oMediaPosition.CurrentPosition = 0 lblElapsed.Caption = “00:00”
MULTIMEDIA PLAYERS
‘’’ Update your buttons cmdPlay.Enabled = True cmdPause.Enabled = False cmdStop.Enabled = False
20
328
Streaming Media with DirectShow PART V
LISTING 20.1
Continued
End If End Sub Private Sub Form_Load() tmrTimer.Interval = 250
‘1/4 second intervals
‘’’ Update your buttons cmdPlay.Enabled = False cmdPause.Enabled = False cmdStop.Enabled = False End Sub ‘***************************************************************************** ‘** ObjectName: Form_Unload ‘** ‘** Description: This subroutine is responsible for turning off playback, ‘** stopping the IMediaControl, and destroying all the objects ‘** you created. ‘** ‘***************************************************************************** Private Sub Form_Unload(Cancel As Integer) m_bMediaPlaying = False DoEvents ‘’’ Stop the media control if it’s still available If Not m_oMediaControl Is Nothing Then m_oMediaControl.Stop End If ‘’’ Remove the references you’ve created If Not m_oBasicAudio Is Nothing Then Set m_oBasicAudio = Nothing If Not m_oMediaControl Is Nothing Then Set m_oMediaControl = Nothing If Not m_oMediaPosition Is Nothing Then Set m_oMediaPosition = Nothing End Sub ‘***************************************************************************** ‘** ObjectName: sldVolume_Change ‘** ‘** Description: This subroutine updates the volume of the playback by ‘** setting the volume method of the IBasicAudio object. ‘** ‘*****************************************************************************
Multimedia Players CHAPTER 20
LISTING 20.1
329
Continued
Private Sub sldVolume_Change() ‘’’ Adjust the volume If Not m_oMediaControl Is Nothing Then _ m_oBasicAudio.Volume = sldVolume.Value Exit Sub End Sub ‘***************************************************************************** ‘** ObjectName: sldVolume_MouseMove ‘** ‘** Description: This subroutine updates the volume of the playback by ‘** setting the volume method of the IBasicAudio object. ‘** ‘***************************************************************************** Private Sub sldVolume_MouseMove(Button As Integer, Shift As Integer, _ x As Single, y As Single) ‘’’ Adjust the volume If Not m_oMediaControl Is Nothing Then _ m_oBasicAudio.Volume = sldVolume.Value Exit Sub End Sub ‘***************************************************************************** ‘** ObjectName: tmrTimer_Timer ‘** ‘** Description: This subroutine will be called whenever the timer is called. ‘** This routine is used to update the display with the time ‘** elapsed during playback. ‘** ‘***************************************************************************** Private Sub tmrTimer_Timer() Dim nReturnCode As Long Dim dblPosition As Double
‘’’ Check the return code Call m_oMediaEvent.WaitForCompletion(100, nReturnCode)
20 MULTIMEDIA PLAYERS
‘’’ Display the elapsed time. On Local Error GoTo ErrLine If m_bMediaPlaying = True Then
330
Streaming Media with DirectShow PART V
LISTING 20.1
Continued
If nReturnCode = 0 Then ‘’’Find the current position for display dblPosition = m_oMediaPosition.CurrentPosition lblElapsed.Caption = CStr(Format(Round(dblPosition, 2), “00:00”)) Else ‘’’ Playback is finished ‘’’ Display the elapsed time. lblElapsed.Caption = CStr(Format(Round(m_dMediaLength, 2), “00:00”)) ‘’’ Reset the buttons cmdPlay.Enabled = True cmdPause.Enabled = False cmdStop.Enabled = False m_bMediaPlaying = False End If End If Exit Sub ErrLine: Err.Clear Resume Next Exit Sub End Sub
Microsoft Web DVD Control The Microsoft Web DVD control is a custom control designed for DVD video playback. It has three classes that provide information about what’s on the DVD, methods for playing, stopping, and pausing the DVD, and methods that allow the user to navigate through the DVD. The Microsoft Web DVD control can be found in this location: C:\winnts\system32\mswebdvd.oca. To use the control, you simply need to add it as a component to your VB project and then access its methods and properties. You can add items such as buttons to turn features of the playback on and off.
The DVDRect Class The DVDRect class is used to provide rectangle information about the playback window. Table 20.17 shows the DVDRect methods that are available in Visual Basic.
Multimedia Players CHAPTER 20
TABLE 20.17
The DVDRect Methods
Method
Description
Height
Height of the rectangle. Width of the rectangle. X-coordinate of the rectangle. Y-coordinate of the rectangle.
Width x y
331
The MSDVDAdm Class The MSDVDAdm class is used to configure parental controls on a DVD session. It turns on settings for parental locking and specifies the parental country, passwords, and bookmarks. Table 20.18 shows the MSDVDAdm methods that are available in Visual Basic. TABLE 20.18
The MSDVDAdm Methods
Description
BookmarkOnClose
Sets or gets a value that tells the MSDVDAdm object to bookmark the current location when the user closes the application. Sets or gets a value that tells the MSDVDAdm object to bookmark the current location when the user clicks the stop button. Saves a password in the Registry. Checks the new password with the saved password in the Registry. Sets or gets the locale identifier (LCID) for the audio stream from the Registry. Sets or gets the LCID for menus from the Registry. Sets or gets the user-specified default LCID for the subpicture stream from the Registry. Disables the screensaver. Gets the parental country that was last saved in the Registry. Gets the parental level that was last saved in the Registry. Turns the system screensaver on or off. Saves the new parental country to the Registry. Saves the parental level to the Registry.
BookmarkOnStop ChangePassword ConfirmPassword DefaultAudioLCID DefaultMenuLCID DefaultSubpictureLCID DisableScreenSaver GetParentalCountry GetParentalLevel RestoreScreenSaver SaveParentalCountry SaveParentalLevel
20 MULTIMEDIA PLAYERS
Method
332
Streaming Media with DirectShow PART V
The MSWebDVD Class The MSWebDVD is used to navigate and control playback of the DVD and to retrieve information from the DVD. This is the main class on which you can hook your controls in the user interface. Table 20.19 shows the MSWebDVD methods that are available in Visual Basic. TABLE 20.19
The MSWebDVD Methods
Method
Description
AcceptParentalLevelChange
Tells the DVD Navigator to accept or reject the temporary parental management level. Activates the menu button at a specified position. Activates the selected menu button. Gets the number of angles available. Gets the aspect ratio of the current video stream. Gets the number of audio streams available. Sets or gets the color of the area around the playback window. Sets or gets the speaker balance for the audio stream. Gets the total number of buttons on the menu. Checks to see if the MPEG-2 decoder can do frame stepping. Captures a still image from the video frame. Sets or gets the value of whether the closed caption is turned on or off. Sets or gets the color key used in the closed caption. Sets or gets the current angle in an angle block. Sets or gets the number of enabled audio streams. Gets the number for the selected button. Sets or gets the current closed-captioning service. Gets the number of the currently playing chapter. Gets the current side of the DVD. Gets the domain that the DVD Navigator is using. Gets the selected subpicture stream. Gets the playback time. Gets the number of the current title.
ActivateAtPosition ActivateButton AnglesAvailable AspectRatio AudioStreamsAvailable BackColor Balance ButtonsAvailable CanStep Capture CCActive ColorKey CurrentAngle CurrentAudioStream CurrentButton CurrentCCService CurrentChapter CurrentDiscSide CurrentDomain CurrentSubpictureStream CurrentTime CurrentTitle
Multimedia Players CHAPTER 20
TABLE 20.19
333
Continued
Description
CurrentVolume
Gets the volume number for the current root directory. Sets or gets the current cursor type. Gets the default audio language from the DVD. Gets the default audio language extension from the DVD. Gets the default menu language. Gets the default subpicture language from the DVD. Gets the default subpicture language extension from the DVD. Deletes a bookmark. Enables or disables the mouse-processing functionality. Provides access to the DVDAdm object. Sets or gets the root directory of the current volume. Gets a string with the current time on the DVD. Gets a unique ID that identifies the current DVD. Opens or closes the drive bay door. Sets or gets an indicator that tells whether play will resume after it has been stopped. Gets the frame rate for the current DVD. Sets or gets the DVD playback in full-screen mode. Gets a string that indicates the language of a specified audio stream. Gets the number of the button at a specified position. Gets the rectangle coordinates for the specified button. Gets the clipping rectangle for the video display. Gets the delay time for the ToolTip to show. Gets the locale identifier (LCID) for the specified text string block. Gets the number of languages available. Gets the number of text strings available in a specified language. Gets the specified string from the DVD.
CursorType DefaultAudioLanguage DefaultAudioLanguageExt DefaultMenuLanguage DefaultSubpictureLanguage DefaultSubpictureLanguageExt DeleteBookmark DisableAutoMouseProcessing DVDAdm DVDDirectory DVDTimeCode2bstr DVDUniqueID Eject EnableResetOnStop FramesPerSecond FullScreenMode GetAudioLanguage GetButtonAtPosition GetButtonRect GetClipVideoRect GetDelayTime GetDVDTextLanguageLCID GetDVDTextNumberOfLanguages GetDVDTextNumberOfStrings GetDVDTextString
20 MULTIMEDIA PLAYERS
Method
334
Streaming Media with DirectShow PART V
TABLE 20.19
Continued
Method
Description
GetDVDTextStringType
Gets a value indicating the type of information contained in the DVD text string. Gets the specified general parameter register. Gets a value that indicates how the karaoke channels are assigned to the left and right speakers. Gets a value that indicates the type of content in the karaoke channel. Gets a readable string when given a primary language identifier. Gets the number of chapters in this title. Gets the current country from the DVD Navigator. Gets the parental level from the DVD Navigator. Gets the specified system parameter register. Gets the default subpicture language from the DVD. Gets the parental levels for the specified title. Gets the native video size. Finds out if a specified audio stream is enabled. Gets a value indicating whether the specified subpicture stream is enabled. Sets or gets the right-left speaker mix for the karaoke channels. Turns mute on or off. Turns the event handling for parental level commands on or off. Pauses playback. Plays the DVD. Sets a time that playback will begin in the current title. Sets a time that playback will begin in a specified title. Starts playing the movie backward. Starts playback from a specified chapter. Starts playback from a specified chapter in a specified title.
GetGPRM GetKaraokeChannelAssignment GetKaraokeChannelContent GetLangFromLangID GetNumberOfChapters GetPlayerParentalCountry GetPlayerParentalLevel GetSPRM GetSubpictureLanguage GetTitleParentalLevels GetVideoSize IsAudioStreamEnabled IsSubpictureStreamEnabled KaroaokeAudioPresentationMode Mute NotifyParentalLevelChange Pause Play PlayAtTime PlayAtTimeInTitle PlayBackwards PlayChapter PlayChapterInTitle
Multimedia Players CHAPTER 20
TABLE 20.19
335
Continued
Description
PlayChaptersAutoStop
Plays back a specified chapter and continues playing for a specified number of chapters in a specific title. Starts playing the movie forward. Plays the next chapter on the DVD. Sets a start and stop time and begins playback. Starts playback of the previous chapter. Gets the current play state. Starts playback at the beginning of the specified title. Sets or gets the user’s preferred subpicture stream from the viewing session. Gets the current ready state. Allows users to change their region. Sets up the DVD filter graph for playback. Starts playing the current chapter again. Moves the DVD Navigator back to the current bookmark and resets all subpicture settings. Resumes playback from where it stopped. Moves the focus from a submenu to its parent menu. Saves the current position and settings of the DVD Navigator. Selects and activates the specified button. Selects the menu button a the specified position. Sets the default audio language for playback. Sets the current default subpicture language in the DVD navigator. Selects the left directional button from the menu. Selects the lower directional button from the menu. Sets the specified parental country for future playbacks. Sets the specified parental level for future playbacks. Selects the right directional button from the menu. Selects the upper directional button from the menu. Sets the video’s clipping rectangle.
PlayForwards PlayNextChapter PlayPeriodInTitleAutoStop PlayPrevChapter PlayState PlayTitle PreferredSubpictureStream ReadyState RegionChange Render ReplayChapter RestoreBookmark Resume ReturnFromSubmenu SaveBookmark SelectAndActivateButton SelectAtPosition SelectDefaultAudioLanguage SelectDefaultSubpictureLanguage SelectLeftButton SelectLowerButton SelectParentalCountry SelectParentalLevel SelectRightButton SelectUpperButton SetClipVideoRect
20 MULTIMEDIA PLAYERS
Method
336
Streaming Media with DirectShow PART V
TABLE 20.19
Continued
Method
Description
SetDelayTime
Sets the delay time for the ToolTip. Sets the specified general parameter register. Shows the cursor. Shows the specified menu. Moves forward through the playback a specified number of frames. Resumes playback and turns off still mode. Stops playback. Sets or gets the current subpicture state. Gets the number of available subpicture streams. Gets the number of titles on the DVD. Sets a ToolTip that appears over the window. Sets the maximum width for the ToolTip message. Gets the total playback time for the current title. Gets a value indicating whether the current operation is valid. Gets or adjusts the current volume. Gets the number of volumes on the DVD. Turns on windowed or windowless mode. Zooms the video display in or out.
SetGPRM ShowCursor ShowMenu Step StillOff Stop SubpictureOn SubpictureStreamsAvailable TitlesAvailable ToolTip ToolTipMaxWidth TotalTitleTime UOPValid Volume VolumesAvailable WindowlessActivation Zoom
Summary In this chapter, you have learned the basics of using the DirectShow ActiveMovie DLL, which can be used to create and manage multimedia playback programs such as audio and video players. You have also learned how to create an MP3 player and how the Web DVD player control can be used for playback of DVDs in any of your VB applications. In Part VI you will learn about DirectPlay and how it can be used to transmit data and voice for multiplayer applications. The next chapter, Chapter 21, “Using DirectPlay to Create Multiplayer Games,” introduces you to DirectPlay and how it can be used to create multiplayer programs.
PART
VI
Multiuser Strategies with DirectPlay
DirectPlay is the cornerstone of multiplayer games and applications, so this section details all the aspects of DirectPlay important to multimedia developers. This DirectPlay section focuses on using DirectPlay for multiplayer game communication, including lobbies, message handling, and managing multiuser games.
IN THIS PART 21 Using DirectPlay to Create Multiplayer Games 339 22 Using Lobbies to Create Player Interactions 23 Managing Games with DirectPlay
353
361
24 Using DirectPlay Voice in Your Application
375
CHAPTER
Using DirectPlay to Create Multiplayer Games
21
IN THIS CHAPTER • A DirectPlay Primer
340
• Communication Models • DirectPlay Events
344
346
• A DirectPlay Peer-to-Peer Client
346
• A DirectPlay Client/Server Connection • Summary
351
349
340
Multiuser Strategies with DirectPlay PART VI
Early games relied on rudimentary communication methods to allow users to talk to one another—a serial cable linked down the hall was my favorite. You were restricted to complex setups and only a one-to-one gaming session. Over the years, however, networks and the Internet have allowed us to play games with our friends no matter where they are located. This chapter focuses on DirectPlay and how it enables you to create multiplayer games as the pros do.
A DirectPlay Primer DirectPlay is a series of classes that are fundamental to communication between applications in the DirectX world. With DirectPlay, your users can talk to each other regardless of the distance, as long as they are connected by one of the following: a network connection, an Internet connection, a modem, or a serial cable. DirectPlay makes all these communication options available by simply checking the users’ machines and allowing them to pick the option they want to use from a list. To accomplish this, DirectPlay relies on a series of components discussed in the following sections.
Service Provider Service providers (also called connection types) refer to the medium in which users become connected to your game. They can choose from modem, serial cable, network, or Internet connections. A machine can have all of these service providers or have only one. Therefore, when you create your multiplayer game or application, you must program for all of these possible service providers. Luckily, DirectPlay makes this task almost completely transparent for you by automatically enumerating the connection types available on the user’s machine. Users can use any of these service providers that their computers support to connect to your application. The different users in a game don’t have to be using the same connection type. Figure 21.1 shows a typical service provider selection screen.
FIGURE 21.1 Selecting a service provider.
Using DirectPlay to Create Multiplayer Games CHAPTER 21
Connection
Session The particular game that a user is playing is called a session. Sessions are responsible for controlling who is allowed in the game and who is not. When users make a connection to the host server, they must choose a session to join. In multiplayer games, this session could be a particular game. Some multiplayer game servers have hundreds of sessions (games) the user can choose from. Some game servers allow players to join a game already in progress, but others allow only people who started the session to play. If you like, you can program your applet either way.
Player The player is, of course, the user. This term also represents all the other users in a session. In each session, the individual players are referred to as “player objects,” but it’s easier to remember a player as one of the participants in a session. There is no maximum on how many players can be in a session; however, because of network traffic constraints, 50 is considered the maximum you should try.
Group A group is a logical organization of players, used to send messages to multiple players simultaneously, thus making some message tasks much easier. A session can contain more than one group, and players can be members of more than one group. For example, in some messaging programs, you can turn on an option specifying who receives your messages and who doesn’t. This feature works the same way for creating groups. You are creating groups of people who can hear you. You might have a friends group, a work group, and a personal group, each made up of specific people, and some groups might contain some of the same people.
Host In each session, one player, called the host, is unique. The host player’s role is to manage the game for all the other players in that session. The host is responsible for the following items: • Keeping a list of players in the session • Keeping a list of the players’ network addresses
21 CREATING MULTIPLAYER GAMES
A connection is established when the user chooses his or her service provider. The information supplied by the user can be an Internet address, a phone number, or a computer IP address. For example, if users choose to use a modem connection, they will probably need to supply a phone number to complete the connection. Part of the process of initializing the connection is to provide information vital for that service provider’s connection.
341
342
Multiuser Strategies with DirectPlay PART VI
• Deciding whether a player can enter a game • Notifying all users of new players as they enter the game • Notifying new users of the current game status • Notifying all users when a player leaves the session The host role usually runs on the machine that started the session. When the player who started the session leaves a game, the host role gets transferred to the next machine in the chain—the person who came into the game immediately after the first player. This is called host migration. A good example of host migration can be seen in multiplayer games such as Microsoft Age of Empires. If the person who started the session leaves, the game doesn’t just stop. The host is transferred to the next machine in the session and play continues practically uninterrupted. As a developer, you can choose whether you want to use host migration. If you don’t use it, the game will terminate when the host leaves the session. The person who creates the session is the host, but this is not always the best choice because the host might have a very slow connection and computer. Therefore, DirectPlay supplies data about the hosts’ connection that others who want to join the game can query to determine whether they want to join that session. In the gaming community, if a bunch of friends want to get together to play, the fastest computer usually starts the game; therefore, that player automatically become the host. Then each of the other players simply connects to that session. If two players decide they both want to host the session for the group, two sessions are created, and everyone else has to decide which one to join.
Message To communicate between players, DirectPlay uses an object called a message, which is a packet of information that travels between machines in the session to provide data about players and the game. Player messages, movements, and game data of all types are sent to each player via the message object. Sound can be converted to data format and sent to the other players in this method. Therefore, voice systems can convert the audio they receive to data and send it to other players by using the message object to transmit the data. For example, you would probably like each player in a session to know when another player has left the game. Ideally, players would not have to wait a long time to discover this information. Through messages, you can quickly receive data about each player .
Network Providers A provider is the network transport (or transport protocol) used to handle the communication of data between players or between the player and the server. Four network providers are available with DirectX: TCP/IP, IPX, modem, and serial. TCP/IP and IPX are universally accepted
Using DirectPlay to Create Multiplayer Games CHAPTER 21
System Messages System messages supply information about the status of the session, players, host, groups, voice messages, and more. These messages are sent to peers, servers, or clients. Among the system messages are notifications of the success or failure of a message reaching its destination. They also include messages that inform the session about players being added and removed, groups being created and destroyed, players connecting and disconnecting, host migration, and much more. System messages are basically network, connection, and system messages that are not specific to the game. They help maintain the connections between all players. The type of messages discussed earlier in this chapter provide data that is important for the game’s logical processing, such as troop movements, taunts from players, and game status.
Lobby Lobbies are like meeting places for singles. You come into a lobby in most multiplayer games to chat and talk about the game you want to play. From the lobby, you can then go into a session and begin playing. The lobby is where users can start a session or join an existing one and where a lot of “talking” goes on before a session is agreed on. For example, users might make a connection to a game server, and then hang around in the lobby and wait for their friends to show up. When they do, they can talk about which game settings they want to use and who they want to join their session (game). Then one of the players can create the session from the lobby (thereby becoming the host), and the rest of the players can join the session. See Chapter 22, “Using Lobbies to Create Player Interaction,” for more information on how lobbies are used.
GUID A DirectPlay application must have a unique GUID to identify it to other DirectPlay applications. A GUID is a 128-bit number used to uniquely identify objects in the Windows environment. To get a GUID for your application, you can simply use a third-party GUID generating application to supply a random GUID that you can use in your code. GUIDs can be created by using one of many available tools. In Visual Studio 6, the UUIDGEN.exe DOS program can create a GUID without the brackets. All you have to do is copy the string it creates to your code and surround it with curly brackets ({}). I have also created a small GUID generating utility, called “A GUID Generation Program,” that can be downloaded from the Web page for this book. This utility, shown in Figure 21.2, uses the DirectX method CreateNewGuid to generate a GUID on demand.
21 CREATING MULTIPLAYER GAMES
network providers used widely in Internet and network connections. The modem and serial providers are often used when you are creating a peer-to-peer game between just you and another player.
343
344
Multiuser Strategies with DirectPlay PART VI
FIGURE 21.2 A GUID Generation Program.
When you create a DirectPlay-compatible application, you want to make sure your messages don’t get mixed up with messages for another DirectPlay-compatible application. Therefore, you give your program a unique GUID to identify it. You must create it when you are developing the application because DirectX doesn’t create one automatically.
Communication Models A communication model is the method computers use to talk to each other. DirectPlay has two distinct communication models: peer-to-peer and client/server.
Peer-to-Peer Peer-to-peer describes a communication method that has been around since the early IBM PCs. A peer-to-peer connection requires at least two computers connected to each other. These two computers can each be connected to all the others in the session, and each computer sends information about what it’s doing to all the other computers in the session. This configuration works quite well for small groups; however, it’s not practical for larger sessions. For example, you don’t want to tell 50 computers about each movement you make because each of those computers will be receiving 50 other messages at the exact same time, which could bog down the connection considerably. Figure 21.3 shows a typical peer-to-peer connection. As you can see in the diagram, each player is talking to all the other players.
Client/Server A client/server model uses an architecture that has been used for many years in the network community. A server is used to host the session. Its responsibility is to send information back and forth to all the machines (clients) connected to it. This configuration has a few advantages. First, the server sends data only to the client that needs it, so less traffic is processed by the client machines. However, the server has to do this for many users, so its traffic is increased. This model also supports passwords and secure connections, which prevent unwanted users from getting into your game. The only downside to this configuration is that you need to have a beefed-up server somewhere for all the clients to connect to. This is not always easy to provide and can be expensive.
Using DirectPlay to Create Multiplayer Games CHAPTER 21
345
21 CREATING MULTIPLAYER GAMES
Player 2
Player 1
Player 3
FIGURE 21.3 A peer-to-peer communication model.
Figure 21.4 shows a typical client/server connection. Each of the players is talking only to the server, not to each other.
Player 2
Player 1
Server (Host)
Player 4
FIGURE 21.4 A client/server communication model.
Player 3
346
Multiuser Strategies with DirectPlay PART VI
DirectPlay Events Events are triggered when system messages are sent back and forth between clients, servers, and peers. DirectPlay, DirectPlay Lobbies, and DirectPlay Voice objects all accept event notifications through their own event objects. Whenever you send a message via a DirectPlay8Peer or DirectPlay8Client object, the destination player that was declared by the code in a DirectPlay8Event, DirectPlay8LobbyEvent, or DirectPlay8VoiceEvent receives the message. The destination player can then interpret the message and send its own messages back by using its objects. The best way to think of this is that DirectPlay events listen for system messages and handle them when they reach your object.
A DirectPlay Peer-to-Peer Client In this section, you will be introduced to the basics of creating a DirectPlay peer-to-peer client and learn how to retrieve a list of available service providers. You will then determine the host of the peer-to-peer session, and learn how to connect to the peer-to-peer session and manage it.
Assigning a GUID The following code example shows how to assign a GUID in your application. As mentioned previously, the GUID is an identifier used in DirectPlay to uniquely identify all network traffic. In this way, your application will pick up only messages that are sent from applications with the same GUID that you have. Because of this, it is important to take care of this task first before doing anything else to your code. Examples of GUID generating programs are listed in the “GUID” section earlier in this chapter. Public Const AppGuid As String = “{E070A2F3-2508-47E5-BB34-9B3568A8BE2E}”
Initializing the DirectPlay Peer-to-Peer Client To create a DirectPlay client, you must first create an instance of the DirectPlay8Peer object, as shown here: Public oDX As NewDirectX8 Public oDPP AsDirectPlay8Peer
The next step is to use the DirectPlayPeerCreate method of DirectX to finish instancing the DirectPlay8Peer object. Use the following code as an example:. Set oDPP = oDX.DirectPlayPeerCreate
Using DirectPlay to Create Multiplayer Games CHAPTER 21
oDPP.RegisterMessageHandler(Me)
Registering the message handler gives your client code an entry point for the DirectPlay8Peer class to send messages through.
Finding the Available Service Providers You then need to get a list of your service providers by using the GetServiceProvider method of the DirectPlay8Peer object to retrieve the next service provider available on the current machine. Because GetServiceProvider needs to know which enumerated service provider you want to display, you can use the GetCountServiceProviders method to find out how many there are. By simply wrapping these methods up into a For...Next loop, you can populate a list box with all the service providers on the current machine. This process is what’s used to create the dialog box that was shown in Figure 21.1. The following code shows how to do this: ‘’’ Declare a storage space for the service provider information Dim oDPN AsDPN_SERVICE_PROVIDER_INFO ‘’’ Parse through all the possible service providers on this machine ‘’’ and add them to a list box. For lCount = 1 To oDPP.GetCountServiceProviders oDPN = oDPP.GetServiceProvider(lCount) lstSP.Items.Add(oDPN.name) Next lCount
Finding the Game Host Next, you must create the game host for the session by creating a DirectPlay8LobbyEvent. With this event, you can monitor the Connect method. When you connect to a lobby, the Connect method is called by the lobby you are connecting to. The DirectPlay8LobbyEvent then passes you the host address object as well as other information for processing.
Connecting to the Session To connect to the game session, you must first have the address of the session host. With this address, you can then call the SetPeerInfo method of the DirectPlay8Peer object. By passing the player name into this method, you register this player with the session. You must then
21 CREATING MULTIPLAYER GAMES
To find out about your service provider, first you need to register the message handler. To do that, you use the RegisterMessageHandler method of the DirectPlay8Peer object, as shown in this example:
347
348
Multiuser Strategies with DirectPlay PART VI
call the Connect method of the DirectPlay8Peer object to connect to the session, as shown in this example: ‘’’ Create an DPN player information object Dim pInfo AsDPN_PLAYER_INFO ‘’’ Populate the parameters of the player information object With pInfo .lInfoFlags = DPNINFO_NAME .Name = “Kirby” End With ‘’’ Sync up with other peer objects by passing information about ‘’’ ‘Kirby’ to the session. oDPP.SetPeerInfo(pInfo,DPNOP_SYNC) ‘’’ Connect to the selected session oDPP.Connect(dpApp, HostAddr, DeviceAddr, ➥ DPNCONNECT_OKTOQUERYFORADDRESSING,0,0)
Managing the Session Managing the session falls on the shoulders of the host. When a player tries to join a session, DirectPlay calls the IndicateConnect method of the DirectPlay8Event on the host machine. The host then decides if the player can join the session by changing the value of fRejectMsg. Setting fRejectMsg to False allows the player to join the session. Any other value rejects the user. The player is then sent a DirectPlay8Event message through the ConnectComplete method indicating whether he or she has been accepted.
Sending Messages Messages are sent to DirectPlay players by using the SendTo method of the DirectPlay8Peer object. This causes the Receive method on the recipient’s DirectPlay8Event object to receive a message with the transmitted data.
Closing the Session The Close method of the DirectPlay8Peer object is used to close the session that the user was attached to. This method in turn calls the DestroyPlayer method of the DirectPlay8Event object on the player’s machine. To push everyone out of a session, the TerminateSession method of the DirectPlay8Peer object can be used. This method then calls each of the players in the session, sending him or her a TerminateSession method in the DirectPlay8Event object.
Using DirectPlay to Create Multiplayer Games CHAPTER 21
A DirectPlay Client/Server Connection
Assigning a GUID The following example shows how to assign a GUID in your application. As mentioned previously, the GUID is used in DirectPlay to uniquely identify all network traffic. In this way, your application will pick up only messages that are sent from applications with the same GUID that you have. You should take care of this task before doing anything else to your code. Examples of GUID generating programs are listed in the earlier “GUID” section. Public Const AppGuid As String = “{5A4D515C-8C19-4079-A0DC-37D9ED87D30F}”
Initializing the DirectPlay Client/Server Client To create a DirectPlay client, you must first create an instance of the DirectPlay8Client object, as shown in the following example: Public oDX As NewDirectX8 Public oDPC AsDirectPlay8Client
The next step is to use the DirectPlayClientCreate method of DirectX to finish the instancing of the DirectPlay8Client object: Set oDPC = oDX.DirectPlayClientCreate
Next, you register the message handler, as you do in the peer-to-peer session, to find out about the service providers. You use the RegisterMessageHandler method of the DirectPlay8Peer object, as shown here: oDPP.RegisterMessageHandler(Me)
Finding the Available Service Providers To get a list of the service providers, you use the GetServiceProvider method of the DirectPlay8Client object to retrieve the next service provider available on the current machine. Because GetServiceProvider needs to know which enumerated service provider you want to display, you can use the GetCountServiceProviders method to find out how many there are. By simply wrapping these methods into a For...Next loop, you can populate a list box with all the service providers on the current machine, as shown here: ‘’’ Declare a storage space for the service provider information Dim oDPN AsDPN_SERVICE_PROVIDER_INFO
21 CREATING MULTIPLAYER GAMES
In this section, you will be introduced to the basics of creating a DirectPlay client/server connection. You will also learn how to retrieve a list of available service providers, determine the host of the client/server session, and connect to the client/server session and manage it.
349
350
Multiuser Strategies with DirectPlay PART VI ‘’’ Parse through all the possible service providers on this machine ‘’’ and add them to a list box. For lCount = 1 To oDPC.GetCountServiceProviders oDPN = oDPC.GetServiceProvider(lCount) lstSP.Items.Add(oDPN.name) Next lCount
Finding the Game Host When working with a peer-to-peer session, finding the game host is different than it is in other communication models. To create the game host for the session, you can create a DirectPlay8LobbyEvent to monitor the Connect method. When you connect to a lobby, the Connect method is called by the lobby you are connecting to. It then passes you the host address object as well as other information for processing. A client can then use the EnumHosts method of the DirectPlay8Client class to find a list of the available hosts. After the client has found a host, it can request a connection to that host’s session.
Connecting to the Session To connect to the game session, you must first have the session host’s address. The client can then request a connection to the host by using the SetClientInfo method of the DirectPlay8Client class. The client can also use the SetClientInfo method to send its name to the host server. After this is done, the client would call the DirectPlay8Client.Connect method to try to make the connection to the session. If the client’s ConnectComplete method in the DirectPlay8Event receives an accepted connection response, then the connection has been established. On the server, the process is a little different. You are waiting for a trigger to occur in the DirectPlay8Event method IndicateConnect. When this method is triggered, the server knows that a client is trying to join. The server can then determine whether to accept or reject the player (client). The player receives an event message in the ConnectComplete method telling the client whether the connection was successful.
Managing the Session Managing the session falls on the shoulders of the server (who is also the host now). When a player tries to join a session, DirectPlay calls the IndicateConnect method of the DirectPlay8Event on the host machine. The host then decides whether the player can join the session by changing the value of fRejectMsg. Setting fRejectMsg to False allows the player to join the session; any other value rejects the user. The player is then sent a DirectPlay8Event message through the ConnectComplete method, indicating whether he or she has been accepted.
Using DirectPlay to Create Multiplayer Games CHAPTER 21
Sending Messages
Closing the Session The Close method of the DirectPlay8Server object is used to close the session that the client was attached to. This method in turn calls each of the clients in the session, sending him or her a TerminateSession method in the DirectPlay8Event object.
Summary This chapter has introduced you to the DirectPlay core class objects. You learned about service providers, connections, sessions, players, groups, hosts, messages, network providers, system messages, and lobbies. Throughout this chapter, you have also looked at the differences between peer-to-peer communication versus client/server communication. You’ve learned how the peer-to-peer communication model works well for smaller groups of people. You’ve also seen that by using a little more expensive client/server architecture, you can create games and applications scalable for large populations. You have also learned how events are used to listen for system messages that relay changes in the session environment in all DirectPlay communications, and you have seen the flow of communication involved in setting up a peer-to-peer session and a client/server session. In the next chapter, you will be learning about lobbies and how they are used to manage game play across the Internet.
21 CREATING MULTIPLAYER GAMES
Messages are sent to DirectPlay players by using the SendTo method of the DirectPlay8Peer object. This method causes the Receive method on the recipient’s DirectPlay8Event object to receive a message with the data that was transmitted.
351
CHAPTER
Using Lobbies to Create Player Interactions
22
IN THIS CHAPTER • Lobby Architecture • Lobby Servers
355
• Lobby Clients
356
354
• DirectPlay Lobbied Application • DirectPlay Lobby Event • Summary
359
358
357
354
Multiuser Strategies with DirectPlay PART VI
When you’re creating a multiplayer game, the lobby is the meeting place for everyone. Lobbies give the players a place to talk to each other. Players can also connect to an existing session or create a new session from within a lobby.
Lobby Architecture A lobby is actually not one entity, but five. A lobby is made up of a lobby server application, a lobby client, a lobbyable game application, a DirectPlay lobby client object, and a DirectPlay lobbied application object. You will need to work with only the lobby objects that correspond with your applications needs. For example, one application might be designed to be the lobby server, while another may need to talk to a lobby—therefore, it would be a lobby client. Take a look at each of these objects in the following list: • Lobby server: The lobby server, typically located on a remote server, communicates with other machines via the Internet. A lobby server is not necessary for a serial cable connection because a serial connection uses only two computers. • Lobby client: The lobby client is an application that communicates with the lobby server and with the player’s game application through the DirectPlay lobby client object. • Lobbyable game application: The lobbyable game application is a program that communicates with the lobby client by using the DirectPlay lobbied application object. It can also talk to the lobby server through the lobby client. • DirectPlay lobby client object: The DirectPlay lobby client object is a DirectPlay8 object used to handle the communication between the lobby client and the player’s game application. • DirectPlay lobby application object: The DirectPlay lobby application object is a DirectPlay8 object used to handle the communication between the lobbyable game application and the lobby client. These five entities are actually combined into three classes: DirectPlay8LobbiedApplication, and DirectPlay8LobbyEvent. Figure 22.1 shows the relationship between the DirectPlayLobby classes.
DirectPlay8LobbyClient,
Using Lobbies to Create Player Interaction CHAPTER 22
355
DirectPlayLobby
DirectPlay8LobbiedApplication
22
DirectPlay8LobbyEvent
FIGURE 22.1 The DirectPlayLobby classes.
Lobby Servers The lobby server is the meeting place for all multiplayer games. When users attach to a lobby, they are actually talking to a lobby server, which is responsible for receiving and passing on messages between clients. These messages can be in the form of text, game data, or system data. Lobby servers are useful for other functions besides just meeting for games. They are also great for chat rooms, such as live auctions, singles areas, and news and interest groups. A lobby server is responsible for the following tasks: • Maintaining the network addresses of each of the players and their sessions • Launching sessions by calling the game application on each user’s computer • Adding players to a current session
USING LOBBIES TO CREATE PLAYER INTERACTION
DirectPlay8LobbyClient
356
Multiuser Strategies with DirectPlay PART VI
• Connecting players to the correct session • Maintaining the status of the host and assigning that role • Notifying other players of changes in anyone’s connection status
Lobby Clients A lobby client is an application created by the lobby server vendor and downloaded to the player’s computer. Its purpose is to handle the communication between the game application and the lobby server. A lobby client is usually installed on the player’s machine as part of a separate multiplayer installation. For example, the Microsoft Game Zone requires you to download a lobby client before you can play DirectPlay games, such as Microsoft Age of Empires, on its game server. Once this client is downloaded, the lobby server can talk to the lobby client, which can then talk to the game application—Age of Empires, in this example. Figure 22.2 shows a sample flow of execution for a typical multiplayer environment that uses a lobby server and a lobby client. 1. Player requests an account
Lobby Server
2. Player downloads the client software
Player
3. Player requests a session on the game server
Players Machine Session 4. Lobby server launches the client
5. Lobby Creates a session.
Lobby Client
6. Launches lobbyable game
Game
FIGURE 22.2 A multiplayer scenario.
In this diagram, you can see that the player creates an account on the server and then downloads the lobby client. The player then goes back to the lobby server and logs in. Once the player is successfully logged in, he can request a session to join or create a new one. The lobby
Using Lobbies to Create Player Interaction CHAPTER 22
357
server then launches the lobby client on the player’s machine. The lobby client creates the session and then launches the game on the player’s machine. The game can now communicate with the lobby server through the lobby client.
The DirectPlay8LobbyClient Class The following code snippet shows how you would create a variable to hold the DirectPlay8LobbyClient class: Dim oDPLC As DxVBLibA.DirectPlay8LobbyClient
TABLE 22.1
gives you access to many methods, described in Table 22.1.
The DirectPlay8LobbyClient Methods
Method
Description
Close
Closes the lobby client. Launches a lobbied application and connects it to a session. Gets the number of lobbied applications available on the user’s machine. Gets program information about a specific lobbied application on the client machine. Registers a message handler in the lobby client to receive messages from the lobbied application. Releases a lobbied application and closes the connection between the application and client. Sends messages to lobbied applications connected to the current lobby client. Sets up the connection settings for the lobby client. Unregisters the lobby client from DirectPlay.
ConnectApplication GetCountLocalPrograms GetLocalProgram RegisterMessageHandler ReleaseApplication Send SetConnectionSettings UnRegisterMessageHandler
DirectPlay Lobbied Application The DirectPlay8LobbiedApplication class is used to create an application or game that you want to be able to connect to a lobby. It provides the foundation for lobby support in an application. The core of this functionality is that a lobby can launch your application by sending instructions to do so without any user intervention being necessary.
22 USING LOBBIES TO CREATE PLAYER INTERACTION
DirectPlay8LobbyClient
358
Multiuser Strategies with DirectPlay PART VI
The DirectPlay8LobbiedApplication Class The following code snippet shows how you would create a variable to hold the DirectPlay8LobbiedApplication class: Dim oDPLA As DxVBLibA.DirectPlay8LobbiedApplication DirectPlay8LobbiedApplication
TABLE 22.2
gives you access to many methods, as shown in Table 22.2.
The DirectPlay8LobbiedApplication Methods
Method
Description
Close
Closes the lobbied application Gets the connection settings from a lobby client. Registers a message handler in the lobbied application to receive messages from the lobby client. Registers a lobbied application with DirectPlay. Sends messages from the lobbied application to the lobby client. Sets up a lobbied application as available or unavailable for connection to a lobby client. Sets the connection settings for the lobbied application. Unregisters the lobbied application message handler. Unregisters the lobbied application from DirectPlay. Updates the status of a lobbied application by sending data to the lobby client.
GetConnectionSettings RegisterMessageHandler RegisterProgram Send SetAppAvailable SetConnectionSettings UnRegisterMessageHandler UnRegisterProgram UpdateStatus
DirectPlay Lobby Event When DirectPlay lobbied applications or DirectPlay lobby clients create events, the events are processed by the DirectPlay lobby event. This event class, called DirectPlay8LobbyEvent, is responsible for receiving these lobby messages and processing them.
NOTE Remember that all the methods of the DirectPlay8LobbyEvent class must be implemented in your form. Failure to do so can cause unpredictable behavior in your application.
Using Lobbies to Create Player Interaction CHAPTER 22
359
The DirectPlay8LobbyEvent Class The following code snippet shows how you would implement a DirectPlay8LobbyEvent object: ‘’’ This must be implemented before messages will be sent Implements DxVBLibA.DirectPlay8LobbyEvent Dim oDPLE As DxVBLibA.DirectPlay8LobbyEvent DirectPlay8LobbyEvent
The DirectPlay8LobbyEvent Methods
Method
Description
Connect
Triggered by the client when the connection to the lobbied application is being established. Triggered when the lobby client or the lobbied application sets up connection settings. Triggered when the lobby client has released the current lobbied application. Triggered when a lobbied application or lobby client sends a message to the current lobbied application. Triggered when the lobbied application is updating its status.
ConnectionSettings Disconnect Receive SessionStatus
Summary Lobbies are a vital component in DirectPlay. With DirectPlay lobbies, you can create message centers where users can communicate with each other and launch programs. In this chapter, you’ve learned that the DirectPlayLobby architecture is made up of five objects: lobby server, lobby client, lobbyable game application, DirectPlay lobby client, and DirectPlay lobby application. You’ve also looked at how to declare a DirectPlay lobbied application and specify what members it can use to support a multiplayer application. You’ve learned how DirectPlay clients can send and receive information to DirectPlay servers and learned about the methods that support the client. Finally, you’ve learned about the DirectPlay lobby event, which monitors system messages from clients and servers in the lobby environment. In the next chapter, you will learn how to manage games by using DirectPlay.
22 USING LOBBIES TO CREATE PLAYER INTERACTION
TABLE 22.3
gives you access to many methods, outlined in Table 22.3.
Managing Games with DirectPlay
IN THIS CHAPTER • DirectPlay Concepts
362
• DirectPlay Architecture • Summary
373
363
CHAPTER
23
362
Multiuser Strategies with DirectPlay PART VI
DirectPlay is made up of many classes that help maintain the connections between the client machines and the servers. This chapter will discuss those classes and focus on explaining the class objects that make up the session object, the client object, the peer object, the core event object, and the address object. These objects are vital to setting the framework in a DirectPlay application. After programmers have set these objects up in their code, components such as DirectPlay Lobbies and DirectPlay Voice can be used. Chapter 22, “Using Lobbies to Create Player Interactions,” provides a more detailed discussion of lobbies, and Chapter 24, “Using DirectPlay Voice in Your Application,” supplies more information about DirectPlay Voice.
DirectPlay Concepts To understand DirectPlay, it’s a good idea to look at some of the terms used in DirectPlay. • Address: The address of a DirectPlay object is a unique address created by the DirectPlay8Address object. This address can be to a server or to a client machine being communicated with in DirectPlay. The address can be made up of a combination of a provider GUID, a device type, a baud rate, a phone number, and a port number. You can define an address by using the methods of the DirectPlay8Address object, or you can assign a URL to the DirectPlay8Address object that specifies what all the settings are. • Client: The DirectPlay client is the recipient of information. The client is usually an end user trying to communicate with other clients and the server. In this chapter, a client is synonymous with a player. • Message queue: A message queue is a holding place for messages being sent from a client, server, or peer. These messages are marked with one of three pending message queues. A high-priority message queue is checked first, and all the old messages in this queue are sent first. Once there are no other messages in the high-priority queue, the medium-priority queue is checked. If the medium-priority queue has any messages, the oldest ones are sent. If there are no more messages in the medium-priority queue, the lowpriority queue is checked. And, of course, it follows the same procedure as the previous two queues. DirectPlay Voice messages are sent in the medium-priority queue. • Server: The server is where all the messages are handled in a client/server connection. Messages are sent to the server from all its clients, and the server then communicates with each of its clients individually. • Peer: A peer is a computer with the same standing as another computer. Peers can communicate with each other without the need of a server. • Event: DirectPlay communicates with clients, servers, and peers through events. Whenever a connection is made, a session created, or a message sent, an event occurs. Events can occur on clients and servers. The event object in DirectPlay is triggered in an application that has instantiated the DirectPlayEvent8 class.
Managing Games with DirectPlay CHAPTER 23
363
Now that you’ve been introduced to the terms used in DirectPlay, you can look at the architecture that makes up DirectPlay.
DirectPlay Architecture The core DirectPlay architecture is made up of five classes that provide the basis for the core communication methods between DirectPlay components. These classes, covered in more detail in the following sections, are DirectPlay8Address, DirectPlay8Client, DirectPlay8Event, DirectPlay8Peer, and DirectPlay8Server. Figure 23.1 shows the relationship between the core DirectPlay classes.
DirectPlay
DirectPlay8Address
23
DirectPlay8Event
DirectPlay8Peer
DirectPlay8Server
FIGURE 23.1 The DirectPlay core classes.
Using the DirectPlay8Address Class Each component in DirectPlay must be identified with a unique address. This address is made up of a combination of a provider GUID, a device type, a baud rate, a phone number, and a
MANAGING GAMES WITH DIRECTPLAY
DirectPlay8Client
364
Multiuser Strategies with DirectPlay PART VI
port number. You can define an address by using the methods of the DirectPlay8Address object, or you can assign a URL to the DirectPlay8Address object that specifies what all the settings are. Addresses are organized into two types: host addresses and device addresses. A host address is used by the server, and the device address is used by the client. Table 23.1 shows the data values required for a host address. TABLE 23.1
Standard Data Types for a Host Address
Data Value
IP
IPX
Modem
Serial
Application Instance Baud Device Flow Control Host Name Parity Phone Number Port Program Provider Stop Bits
Optional N/A N/A N/A Required N/A N/A Required Optional Required N/A
Optional N/A Optional N/A Required N/A N/A Required Optional Required N/A
Optional N/A Required N/A Optional N/A Required N/A Optional Required N/A
Optional Required Required Required Optional Required Not used N/A Optional Required Required
Table 23.2 shows the data values required for a host address. TABLE 23.2
Standard Data Types for a Device Address
Data Value
IP
IPX
Modem
Serial
Application Instance Baud Flow Control Host Name Device Parity Phone Number Port Program
Optional N/A N/A Optional Optional N/A N/A Optional Optional
Optional N/A N/A Optional Required N/A N/A Required Optional
Optional N/A N/A Optional Required N/A N/A N/A Optional
Optional Required Required Optional Required Required N/A N/A Optional
Managing Games with DirectPlay CHAPTER 23
TABLE 23.2
365
Continued
Data Value
IP
IPX
Modem
Serial
Provider Stop Bits
Required N/A
Required N/A
Required N/A
Required Required
To use these data values, you would simply use the BuildFromURL method in the DirectPlay8Address class. The following code shows how they would be created: ‘’’ Local IP Address Call oDPA.BuildFromURL(“x-directplay:/ ➥provider=%7BAA7D6E-64CD-49EC-BE58-289BFD281EF7%; ➥device=IP ADAPTER GUID;port=0000230034#IPUserData”) ‘’’ Local IPX Address Call oDPA.BuildFromURL(“x-directplay:/ ➥provider=%172EB192-2280-4E6D-A459-CED79C6C555D%; ➥device=IPX ADAPTER GUID;port=00230#IPXUserData”)
‘’’ Remote Modem Address Call oDPA.BuildFromURL(“x-directplay:/ ➥provider=%D92D60F1-66ED-4F64-AA38-432730D26615%; ➥device=MODEM DEVICE GUID;phonenumber=555-1212#ModemUserData”)
The following code snippet shows how you would create a variable to hold the DirectPlay8Address class: Dim oDPA As DirectPlay8Address
The DirectPlay8Address class gives you access to many methods, described in Table 23.3. TABLE 23.3
The DirectPlay8Address Methods
Method
Description
AddComponentLong
Adds and replaces a component to the address with the type of long. Adds and replaces a component to the address with the type of string. Assigns a URL to the address object.
AddComponentString BuildFromURL
23 MANAGING GAMES WITH DIRECTPLAY
‘’’ Local Serial Address Call oDPA.BuildFromURL(“x-directplay:/ ➥provider=%07FF8843-FDE3-46BE-9DB0-B6E9AB46C729%;device=COM PORT GUID;baud=57600;stopbits=1;parity=NONE;flowcontrol=RTSDTR#SerialUserData”)
366
Multiuser Strategies with DirectPlay PART VI
TABLE 23.3
Continued
Method
Description
Clear
Clears the contents of the address. Creates a copy of the address object. Gets a component value of type long from the address object. Gets a component value of type string from the address object. Gets the local device’s GUID for the address object. Gets the number of components in the address. Gets the service provider’s GUID from the address object. Gets the URL represented by the address object. Gets the user data from the address object. Sets the local device’s GUID for the address object. Sets the local address to a supplied address. Sets the service provider’s GUID in the address object. Sets the user’s data in the address object.
Duplicate GetComponentLong GetComponentString GetDevice GetNumComponents GetSP GetURL GetUserData SetDevice SetEqual SetSP SetUserData
Using the DirectPlay8Client Class The DirectPlay8Client class is responsible for creating and managing the client applications in a client/server configuration. These responsibilities include managing the sessions in which the clients are participating. The client object also monitors and manages its message queue, and is responsible for getting information from the server and setting its own configurations for the server to retrieve later. The following code snippet shows how you would create a variable to hold the DirectPlay8Client class: Dim oDPC As DirectPlay8Client
The DirectPlay8Client class gives you access to many methods, detailed in Table 23.4. TABLE 23.4
The DirectPlay8Client Methods
Method
Description
CancelAsyncOperation
Cancels asynchronous operations. Closes the connection to a session. Opens a communication channel between the client and the server.
Close Connect
Managing Games with DirectPlay CHAPTER 23
TABLE 23.4
367
Continued
Description
EnumHosts
Enumerates a collection of applications that are designed to support DirectPlay. Gets the description of the application connected to the client. Gets the capabilities of the current client. Gets the connection information about the local endpoint and the server this client is connected to. Gets the number of service providers available to this client. Gets the number of messages in the message queue and the number of bytes being transferred to the current client. Gets the server’s address in the current session. Gets the data set for the server this client is connected to. Gets information about the specified service provider. Gets detailed information about the capabilities of the specified service provider. Registers or unregisters this client application with a lobby. Creates an entry point in the current client for messages to be received for processing. Sends an asynchronous or synchronous message to the server that this client is attached to. Sets up the capabilities of the session for the client. Sets up the settings of this client with the application. Sets up the capabilities of the service provider for the client. Closes up the entry point created by the RegisterMessageHandler method.
GetApplicationDesc GetCaps GetConnectionInfo GetCountServiceProviders GetSendQueueInfo GetServerAddress GetServerInfo GetServiceProvider GetSPCaps RegisterLobby RegisterMessageHandler Send SetCaps SetClientInfo SetSPCaps UnRegisterMessageHandler
Using the DirectPlay8Event Class The DirectPlay events are responsible for listening for messages from peers, clients and servers. When one of these messages comes in, it’s routed to an appropriate method in the DirectPlay8Event class. These classes listen for the creating and deletion of players and groups. The events class also listens for changes in the host and messages to DirectPlay and sends out confirmations when messages are received.
23 MANAGING GAMES WITH DIRECTPLAY
Method
368
Multiuser Strategies with DirectPlay PART VI
NOTE Remember that all methods in the DirectPlay8Event class must be implemented in your form. Failure to do this could cause unpredictable behavior in your application.
The following code snippet shows how you would create a variable to hold the DirectPlay8Event class: ‘’’ This must be implemented before messages will be sent Implements DirectPlay8Event Dim oDPE As DirectPlay8Event
The DirectPlay8Event class gives you access to many methods, described in Table 23.5. TABLE 23.5
The DirectPlay8Event Methods
Method
Description
AddRemovePlayerGroup
Triggered by a peer, server, or client when a player has been added or removed from a group. Triggered when the application description has changed. Triggered upon the completion of an asynchronous operation. Triggered when a host or server receives a completed connection from a client. Triggered when a group is created. Triggered when a player is created. Triggered when a group is destroyed. Triggered when a player is destroyed. Triggered when the peer or client requests host enumeration. Triggered when the peer or client requests host enumeration. This event contains the actual data from the request. Triggered when host has been changed to another player in the session. Triggered when a player has requested a connection to the session. This occurs on the machine hosting the session.
AppDesc AsyncOpComplete ConnectComplete CreateGroup CreatePlayer DestroyGroup DestroyPlayer EnumHostsQuery EnumHostsResponse HostMigrate IndicateConnect
Managing Games with DirectPlay CHAPTER 23
TABLE 23.5
369
Continued
Method
Description
IndicateConnectAborted
Triggered if the connection to the host was aborted. Triggered when the client, server, peer, or group has been updated. Triggered when a message is being sent to the receiver from another player or the host. Triggered when a message has been received at the destination. Triggered when a peer terminates the session.
InfoNotify Receive SendComplete TerminateSession
Using the DirectPlay8Peer Class
The following code snippet shows how you would create a variable to hold the DirectPlay8Peer class: Dim oDPP As DirectPlay8Peer
The DirectPlay8Peer class gives you access to many methods, detailed in Table 23.6. TABLE 23.6
The DirectPlay8Peer Methods
Method
Description
AddPlayerToGroup
Adds a player to a group. Cancels an asynchronous request. Closes the connection to the session. Connects the peer to a server. Creates a group for the current session. Destroys a group and notifies all members. Deletes a peer from the current session. Enumerates a collection of applications that are designed to support DirectPlay.
CancelAsyncOperation Close Connect CreateGroup DestroyGroup DestroyPeer EnumHosts
23 MANAGING GAMES WITH DIRECTPLAY
The DirectPlay8Peer class is used to create and maintain a peer-to-peer connection with other DirectPlay applications running a peer connection. To do this, the peer class gets information about the service providers, the connection, and application data. It also sends and receives message from other DirectPlay peer clients. The DirectPlay8 peer object manages the player by setting up the player information and deleting players from a session. It can also add and remove players from groups and delete groups if needed.
370
Multiuser Strategies with DirectPlay PART VI
TABLE 23.6
Continued
Method
Description
GetApplicationDesc
Gets the description of the application connected to the peer. Gets the capabilities of the current peer. Gets the connection information about the local endpoint and the host. Gets the number of clients or groups in the current session. Gets the number of players in a group. Gets the number of service providers available to this peer. Gets a collection of the addresses of the hosts that have responded. Gets the group name and any data being held by the group. Gets the identifier for the player who is a member of the specified group. Gets the address of the specified peer. Gets information about specified players, including whether they are the host, their name, and any data published about the players. Gets the client or group identifier. Gets the information about the number and size of messages currently in the queue. Gets information about the specified service provider. Gets detailed information about the capabilities of the specified service provider. Sets up the host of the peer-to-peer session. Registers or unregisters this application with a lobby. Sets up the entry point for messages to come into the client. Removes a player from a group and sends a message to all the other players. Sends out data to a specified player. Sets up the description for the application being hosted.
GetCaps GetConnectionInfo GetCountClientsAndGroups GetCountGroupMembers GetCountServiceProviders GetEnumHostResponseAddress GetGroupInfo GetGroupMember GetPeerAddress GetPeerInfo
GetPlayerOrGroup GetSendQueueInfo GetServiceProvider GetSPCaps Host RegisterLobby RegisterMessageHandler RemovePlayerFromGroup SendTo SetApplicationDesc
Managing Games with DirectPlay CHAPTER 23
TABLE 23.6
371
Continued
Method
Description
SetCaps
Sets up the capabilities of the session for the peer. Sets the group name and any data that needs to be held by the group. Sets up the settings of a peer with a DirectPlay application. Sets up the capabilities of the session for the peer. Terminates the session that this peer is connected to. Unregisters the current message handler that was created with the RegisterMessageHandler method.
SetGroupInfo SetPeerInfo SetSPCaps TerminateSession UnregisterMessageHandler
Using the DirectPlay8Server Class
The following code snippet shows how you would create a variable to hold the DirectPlay8Server class: Dim oDPS As DirectPlay8Server
The DirectPlay8Server class gives you access to many methods, described in Table 23.7. TABLE 23.7
The DirectPlay8Server Methods
Method
Description
AddPlayerToGroup
Adds a player to a group. Cancels any asynchronous operations in the session. Closes a connection to the current session. Creates a group in the current session. Destroys a client connection to the current session. Destroys a group in the current session. Gets the application description for the current application.
CancelAsyncOperation Close CreateGroup DestroyClient DestroyGroup GetApplicationDesc
23 MANAGING GAMES WITH DIRECTPLAY
Servers are essential in the client/server configuration of DirectPlay. The DirectPlay8Server class handles much of the overhead of managing a multiplayer game. This class is responsible for managing the session by getting and sending out session information and hosting the game. It also sends and receives messages from clients and routes them to the appropriate receivers. The server object is also responsible for creating groups, adding and removing players from them, and destroying clients, if needed.
372
Multiuser Strategies with DirectPlay PART VI
TABLE 23.7
Continued
Method
Description
GetCaps
Gets the general capabilities for the server. Gets the address for a specific client connection. Gets information about a specific client. Gets connection information about the connection between a client and the server. Gets the number of players residing in a group. Gets the number of players or groups in the current session. Gets the number of service providers available to the server. Gets information about the specified group, including name and any data being held by the group. Gets the identification number of a specific member of a specific group. Gets the identifier for a specific player or group. Gets information about the send message queue. Gets a list of the service providers available to the server. Gets a list of the capabilities of a specific service provider. Sets the host for the session. Registers an lobbyable application with the server’s lobby. Registers an entry point in the server so that it can receive messages from itself and clients. Removes a specific player from a specific group. Sends a synchronous our asynchronous message to a specific player. Sets up the settings for the hosted application. Sets up the session capabilities. Assigns a name and group data to a specific group. Sets up the settings of a client in an application. Sets up the service provider capabilities. Unregisters the message handler created by the RegisterMessageHandler method.
GetClientAddress GetClientInfo GetConnectionInfo GetCountGroupMembers GetCountPlayersAndGroups GetCountServiceProviders GetGroupInfo GetGroupMember GetPlayerOrGroup GetSendQueueInfo GetServiceProvider GetSPCaps Host RegisterLobby RegisterMessageHandler RemovePlayerFromGroup SendTo SetApplicationDesc SetCaps SetGroupInfo SetServerInfo SetSPCaps UnregisterMessageHandler
Managing Games with DirectPlay CHAPTER 23
373
Summary DirectPlay is vital to multiuser applications. In this chapter, you’ve looked at the terms used in DirectPlay—including addresses, clients, message queues, servers, peers, and events—and at the core DirectPlay classes that make up DirectPlay’s base. You’ve learned about the DirectPlay address and all its methods for getting address information. You’ve learned how the DirectPlay address object can provide detailed information about the connection type and data of the host and clients. You’ve also examined the DirectPlay client to discover how it communicates with the server via its methods, and the DirectPlay event to see how it handles listening to session changes and monitoring system messages. You’ve seen how the DirectPlay peer class can be used to talk to another DirectPlay peer in a small multiuser environment. Finally, you’ve examined the methods and inner workings of the DirectPlay server object. In the next chapter, you will be learning about DirectPlay Voice and how it can be used to transmit people’s voices across different types of networks.
23 MANAGING GAMES WITH DIRECTPLAY
Using DirectPlay Voice in Your Application
IN THIS CHAPTER • DirectPlay Concepts
376
• DirectPlay Voice Architecture • Using DirectPlay Voice • Summary
382
381
377
CHAPTER
24
376
Multiuser Strategies with DirectPlay PART VI
If you’ve had the pleasure of playing any of the many multiplayer games on the market today, you have probably noticed that more and more of them are supporting voice communication. Many people have found that being able to talk directly with their teammates when they’re hunting down the enemy is much faster and more enjoyable than typing in commands to each other. With this new technology, users feel more immersed in the game. DirectPlay Voice is a new architecture model encompassing a full-fledged voice communication system that can work with the rest of DirectPlay. It’s also important to mention that although DirectPlay Voice is often used as a game communication medium, it can also be used simply to provide voice communication between remote users of any kind. Let’s take a look at the architecture involved in making DirectPlay Voice work in your applications.
NOTE To use DirectPlay Voice, players must have a full-duplex compatible sound card. Fullduplex simply means that two signals can be processed at the same time. Basically, the card can send an audio stream to the speakers at the same time it receives data from the microphone. Most sound cards today support this feature; however, it’s a good idea to check with the manufacturer to make sure.
DirectPlay Concepts To understand DirectPlay Voice, it’s a good idea to look at some of the terms used with it.
Voice Session Like other sessions in DirectPlay, a voice session is responsible for grouping together players who want to interact for play or conversation. The voice session defines who is involved in the conversation. Basically, it defines a game table your players are sitting at. A voice session helps make the voice communications between players easier because it sends messages to only those users who are in the same session. People outside the users’ session won’t hear any of the communications. This concept can best be understood in the context of an online game. Of the thousands of voice messages coming to the host server, you want only the ones that pertain to your voice session to go out to the people you are playing with. After all, you don’t want to hear a thousand people all talking at once.
Transmission Target What happens if you want your voice to go to only one other player? You can’t just ask everyone else in your session to take off his or her earphones and come back later. Therefore, there
Using DirectPlay Voice in Your Application CHAPTER 24
377
has to be a method to determine who gets the message and who doesn’t. That’s where the transmission target comes in, which is a list of players or groups in the session that you want to send messages to. A transmission target list can contain up to 64 players or groups.
DirectPlay Voice Architecture DirectPlay Voice is made up of four distinct classes: DirectPlayVoiceClient8, DirectPlayVoiceServer8, DirectPlayVoiceEvent8, and DirectPlayVoiceTest8. The client and server objects in DirectPlay Voice handle client/server voice communication. The DirectPlayVoiceEvent8 class is responsible for listening for messages from the DirectPlayVoiceClient8 and DirectPlayVoiceServer8 in the same session as your application. The DirectPlayVoiceTest8 class is designed specifically to test the communication connection and verify that the microphone is working on your computer. Figure 24.1 shows the relationship between the DirectPlay Voice classes.
DirectPlayVoice
DirectPlayVoiceClient8
DirectPlayVoiceEvent8
24
DirectPlayVoiceTest8
FIGURE 24.1 The DirectPlay Voice classes.
USING DIRECTPLAY VOICE
DirectPlayVoiceServer8
378
Multiuser Strategies with DirectPlay PART VI
Using the DirectPlayVoiceClient8 Class During a voice session of DirectPlay, the DirectPlayVoiceClient8 class is used to manage the client traffic. This class is responsible for managing the buffers, evaluating the capabilities of the client device, connecting and disconnecting from sessions, and so forth. The following code snippet shows how you would create a variable to hold the DirectPlayVoiceClient8 class: Dim oDPVC As DirectPlayVoiceClient8
The DirectPlayVoiceClient8 class gives you access to many methods, described in Table 24.1. TABLE 24.1
The DirectPlayVoiceClient8 Methods
Method
Description
Connect
Connects the client to a DirectPlay Voice session. Gets the 3D sound buffer for a player or group. Deletes the 3D sound buffer for a specific player or group. Disconnects the client from a DirectPlay Voice session. Retrieves a list of the enumerated DirectPlay Voice capabilities. Gets the client configuration. Gets the compression type. Returns the number of compression types for this client. Gets the session description for the current client. Gets the sound device configuration of the current session. Gets a reference to the current capture and playback objects. Gets the transmission target of the voice stream for this client. Initializes the DirectPlayVoiceClient8 class before a Connect method is called. Sets up the configuration for the current client. Sets up the current sound devices for capture and playback to this client. Sets up the transmission target (player or group) that will receive the audio transmission from this client.
Create3DSoundBuffer Delete3DSoundBuffer Disconnect GetCaps GetClientConfig GetCompressionType GetCompressionTypeCount GetSessionDesc GetSoundDeviceConfig GetSoundDevices GetTransmitTargets Initialize SetClientConfig SetCurrentSoundDevices SetTransmitTargets
Using DirectPlay Voice in Your Application CHAPTER 24
TABLE 24.1
379
Continued
Method
Description
StartClientNotification
Sends a notification to the DirectPlayVoiceEvent8 object on the client machine to begin receiving messages from the client and server. Unregisters the message handler in the current client.
UnRegisterMessageHandler
Using the DirectPlayVoiceEvent8 Class Other applications use their DirectPlayVoiceClient8 and DirectPlayVoiceServer8 classes to call the DirectPlayVoiceEvent8 class on everyone’s machine in the voice session. Therefore, the DirectPlayVoiceEvent8 class is responsible for receiving these voice messages and processing them.
NOTE Remember that all methods in the DirectPlayVoiceEvent8 class must be implemented in your form. Failure to do this could cause unpredictable behavior in your application.
The following code snippet shows how you would create a variable to hold the DirectPlayVoiceEvent8 class: ‘’’ This must be implemented before messages will be sent Implements DirectPlayVoiceEvent8
The DirectPlayVoiceEvent8 class gives you access to many methods, described in Table 24.2. TABLE 24.2
The DirectPlayVoiceEvent8 Methods
Method
Description
ConnectResult
Triggered when a call to the DirectPlayVoiceClient8.Connect method is completed. Triggered when a new player joins the voice session. Triggered when a player quits the voice session. Triggered when a call to the DirectPlayVoiceClient8.Disconnect method is completed.
CreateVoicePlayer DeleteVoicePlayer DisconnectResult
USING DIRECTPLAY VOICE
Dim oDPVE As DirectPlayVoiceEvent8
24
380
Multiuser Strategies with DirectPlay PART VI
TABLE 24.2
Continued
Method
Description
HostMigrated
Triggered when the host has changed to some other player. Triggered to notify the player that the input level from the microphone has changed. Triggered to notify the player that the output level from the microphone has changed. Triggered to indicate that an individual player’s output level has changed. Triggered when an incoming voice stream begins playback. Triggered when an incoming voice stream stops playback. Triggered when the local client begins voice input. Triggered when the local client stops recording voice input. Triggered when the voice session is terminated.
InputLevel OutputLevel PlayerOutputLevel PlayerVoiceStart PlayerVoiceStop RecordStart RecordStop SessionLost
Using the DirectPlayVoiceServer8 Class In a DirectPlay Voice session, there must always be a host, which is the DirectPlay Voice server object. These objects communicate with all the other members of the session by using the DirectPlayVoiceServer8 class. This class manages the session host. The following code snippet shows how you would create a variable to hold the DirectPlay8Server class: Dim oDPVS As DirectPlayVoiceServer8
The DirectPlayVoiceServer8 class gives you access to many methods, detailed in Table 24.3. TABLE 24.3
The DirectPlayVoiceServer8 Methods
Method
Description
GetCaps
Gets the server’s DirectPlay Voice capabilities. Gets the compression type of the server. Gets the number of compression types available to the server. Gets the session description. Gets the transmission targets (player or group) in a session.
GetCompressionType GetCompressionTypeCount GetSessionDesc GetTransmitTargets
Using DirectPlay Voice in Your Application CHAPTER 24
TABLE 24.3
381
Continued
Method
Description
Initialize
Initializes the DirectPlayVoiceClient8 class by associating the DirectPlayVoiceServer8 class with a DirectPlay object. Sets up the session description. Sets up the transmission targets from the client to the other members of the session. Sends a notification to the DirectPlayVoiceEvent8 object on the client machine to begin receiving messages from the client and server. Starts a DirectPlay voice session. Stops a DirectPlay voice session. Unregisters the message handler form the server.
SetSessionDesc SetTransmitTargets StartServerNotification
StartSession StopSession UnregisterMessageHandler
Using the DirectPlayVoiceTest8 Class is designed to perform tests on the DirectPlay Voice connection. It is unique in that only one method is associated with it: CheckAudioSetup. CheckAudioSetup is used to determine whether the audio configuration is working correctly. This is done by running the Audio Setup Wizard on the specified device. The wizard runs through a series of tests to determine whether the device is capable of full-duplex audio. It also checks to make sure the microphone is working correctly. DirectPlayVoiceTest8
DirectPlay Voice relies on DirectPlay for its communication. Therefore, a DirectPlay session must be created before you can create DirectPlay Voice objects.
DirectPlay Voice on a Peer-to-Peer Connection If your DirectPlay architecture involves a peer-to-peer connection, the DirectPlay Voice classes will be sending data to all the machines connected to yours in the session. When the voice message gets to the machine it’s supposed to go to, it will be combined with other voice streams. The combined voice streams are then played back on the receiver’s speakers as one voice stream. It’s as though you had many people talking at once while you recorded their conversation. When you play the tape back, you have one audio file made up of many voices.
24 USING DIRECTPLAY VOICE
Using DirectPlay Voice
382
Multiuser Strategies with DirectPlay PART VI
DirectPlay Voice on a Forwarding Server Connection A forwarding server is responsible for passing the messages from a client on to other clients, thus acting as a switchboard for voice messages. The forwarding server receives messages and then sends them to the appropriate players. A forwarding server can send more than one message at a time to the client. It’s up to the client to receive the messages and combine them into one audio stream that is sent to their own speakers.
DirectPlay Voice on a Mixing Server Session A mixing server is a machine with the sole purpose of handling the receiving, mixing, and distribution of DirectPlay Voice messages to each of its clients. When clients receive messages, the mixing server must determine who gets what message, and then combine these messages into one stream that it constantly feeds to the specific player. Unlike in a forwarding server connection, the client receives one stream of voice data instead of multiple streams. Therefore, the client has to send only the audio; there is no need to combine multiple audio streams into one before sending the signal to the speakers.
Summary DirectPlay Voice is one of the newest components of DirectX. It offers DirectX programmers many new features for handling the transmission and receipt of voice data across the DirectPlay connection. You’ve learned that DirectPlay Voice has four classes. DirectPlayVoiceClient8 is responsible for handling the client communication needs. The server’s communication needs are supplied by the DirectPlayVoiceServer8 class. The DirectPlayVoiceEvent8 class is implemented in a DirectPlay Voice application to listen for messages from other DirectPlay Voice clients and servers. The DirectPlayVoiceTest8 class is used to test audio equipment on the client machine. In this chapter, you’ve learned that DirectPlay Voice can be used in a peer-to-peer connection, a forwarding server connection, and a mixing server session. In the next chapter, you will learn about DirectSetup.
Finishing Touches
This section focuses on the final aspects of DirectX and covers the DirectSetup libraries. It also looks at how to install DirectX on a user’s machine and handle the setup of all your components.
IN THIS PART 25 DirectSetup
385
PART
VII
CHAPTER
DirectSetup
25
IN THIS CHAPTER • Working with the DirectXSetup Libraries
386
• Using the Package and Deployment Wizard 389 • Alternatives to the Package and Deployment Wizard 395 • Summary
395
386
Finishing Touches PART VII
This chapter focuses on DirectSetup and the distribution of DirectX applications. DirectSetup is a small library used to determine whether DirectX is installed on the user’s machine and the exact version number of DirectX being used. It also includes a function that can be used to call the DirectX setup libraries, which will begin the install of the retail version of DirectX.
Working with the DirectXSetup Libraries The DirectXSetup library is encased in the dxsetup.dll file, which can be found in the \redist\DirectX81 folder. To use the functions in this DLL, you need to initialize the libraries by using Declare statements in your VB code. You also need to use the DirectXSetupGetVersion function to determine the major and minor version of DirectX on the user’s machine. Finally, you need to use the DirectXSetup function to install DirectX on the user’s machine.
Initializing the DirectXSetup Functions To begin working with DirectXSetup, you need to create constants to represent the flags used in the DirectXSetup functions. You also need to declare the two DirectXSetup functions so that they can be referenced throughout your code.
Flags To work with DirectXSetup in your code, it’s easier to set up some flag constants at the beginning of your code. The following code sample contains the most common constants used. They specify that you want to set up DirectDraw drivers, DirectSound drivers, and the DirectX core engine. ‘’’ DirectSetup constants Private Const DSETUP_DDRAWDRV As Long = 8 Private Const DSETUP_DSOUNDDRV As Long = 16 Private Const DSETUP_DXCORE As Long = 65536 Private Const DSETUP_DIRECTX As Long = (DSETUP_DXCORE Or DSETUP_DDRAWDRV _ ➥ Or DSETUP_DSOUNDDRV) Private Const DSETUP_TESTINSTALL As Long = 131072 Private Const DSETUP_NTINSTALL As Long = 524288 Private Const DSETUPERR_SUCCESS_RESTART As Long = 1 Private Const DSETUPERR_SUCCESS As Long = 0 Private Const DSETUP_VERSION As Long = &H40000
Referencing DirectXSetup Because you can’t directly reference dsetup.dll (DirectSetup), you need to reference it by using the Declare command. The following code shows how you would reference the two functions you are going to use, DirectXSetup and DirectXSetupGetVersion.
DirectSetup CHAPTER 25
387
‘’’ DirectSetup Install routines Private Declare Function DirectXSetup Lib “dsetup.dll” Alias “DirectXSetupA” _ ➥ (ByVal hWnd As Long, ByVal lpszRootPath As String, ByVal dwFlags As Long) _ ➥ As Long Private Declare Function DirectXSetupGetVersion Lib “dsetup.dll” _ ➥ (dwVersion As Long, dwRevision As Long) As Long
Now that you have created the constants and the declarations to the DirectSetup functions, you can begin working with the DirectXSetupGetVersion function.
Using the DirectXSetupGetVersion Function The DirectXSetupGetVersion function can be used to find out which version of DirectX is currently installed on the user’s machine. If you get a return value of 0, the function was unable to find a DirectX version on the machine. In this case, you would want to install DirectX. If the return value is anything other than 0, you can look at the byRef value lMajor to see which major version of DirectX is currently on the user’s machine. If it’s not the correct version for your application, you can install DirectX by using the DirectXSetup function. You can also look at the byRef value lMinor, to find out which minor version of the DirectX application is installed on the computer. The major version represents the main numbers, such as DirectX 7 or DirectX 8. By looking at the minor number, you can identify the difference between DirectX 8 and DirectX 8.1 on the user’s machine. bInstall = False ‘Do not install by default lReturnValue = DirectXSetupGetVersion(lMajor, lMinor) If lReturnValue = 0 Then ‘’’ 0 means no version found. ‘’’ Install by default bInstall = True Else lMajor = lMajor - (lMajor And DSETUP_VERSION) If lMajor < 8 Then ‘’’ The current version is less than 8.0 ‘’’ If this is the case, you need to install bInstall = True End If End If
After determining whether DirectX is on the user’s machine, and which version is being used, you can then install DirectX if necessary by calling the DirectXSetup function.
25 DIRECTSETUP
388
Finishing Touches PART VII
Using the DirectXSetup Function The DirectXSetup function is really pretty simple. The first parameter passed into the function is the handle to the current window. If you use 0 as the value for this parameter, the function defaults to the current window. The next parameter is the location of the DirectX redistributable setup files. These files include dsetup.dll, dsetup32.dll, as well as the DirectX redistributable files in the \redist\DirectX81 folder. The final parameter is a flag that determines how DirectXSetup should run. The most common flags are listed in Table 25.1. TABLE 25.1
Constant Flags Used in the DirectXSetup Function
Constant Flag
Description
DSETUP_DDRAWDRV
Install the DirectDraw drivers Install the DirectSound drivers Install the DirectX core components Install all three of the preceding components
DSETUP_DSOUNDDRV DSETUP_DXCORE DSETUP_DIRECTX
NOTE The constant names listed in Table 25.1 are custom constant names created for your program. They represent the values used by the DirectXSound function and just make it easier for you to read and understand your code.
The following routine is an example of how you can use the DirectXSetup function. In this example, the return value is checked to see if a reboot is necessary, and if so, a flag is set for reboot. ‘’’ Install DirectX if you’ve determined that it isn’t already on the machine. If bInstall Then lReturnValue = DirectXSetup(0, Left$(gsTEMPDIR, Len(gsTEMPDIR) - 1), _ ➥ DSETUP_DIRECTX) If lReturnValue = DSETUPERR_SUCCESS_RESTART Then gReboot = True ‘’’ Set a flag so we know to reboot. Else ‘’’ There was an error in install of DirectX MsgBox “An error occured while installing DirectX.” End If End If
DirectSetup CHAPTER 25
389
Using the Package and Deployment Wizard The Package and Deployment Wizard comes as part of Visual Studio 6. With this program, you can compile and distribute your finished applications. Of course, it helps to know what settings you need to use to package and distribute DirectX applications. Therefore, in the following sections, you will be learning how to create a setup package, modify it for DirectX, and deploy it to a place for distribution.
Creating the Setup Package This process creates the Setup.exe, the CAB files, a batch build file, and all supporting files. These files are necessary for the setup program to compile, decompress, and install itself on the user’s machine. To create the setup package, follow these steps: 1. Open the Package and Deployment Wizard, using the menu choices shown in Figure 25.1.
25 FIGURE 25.1 2. In the Select Project list, choose the location of your project (shown in Figure 25.2).
DIRECTSETUP
The menu choices for starting the Package And Deployment Wizard.
390
Finishing Touches PART VII
FIGURE 25.2 Selecting the project location.
3. Select the Package option to bundle your project into a distributable package. If you have not compiled the executable for your program yet, you will be prompted to do so. 4. DirectX applications are almost always standard setup packages. Therefore, it is best to choose this option in the Package Type list box (see Figure 25.3).
FIGURE 25.3 Choosing the package type.
5. Click Next to move to the wizard’s Package Folder window, and select the folder where the final package will be created. 6. The Package and Deployment Wizard will most likely not be able to obtain dependency information about the DirectX 7 or DirectX 8 DLLs, but that’s okay because you aren’t creating a dependency file. When the message box shown in Figure 25.4 opens to tell you this, simply click OK.
DirectSetup CHAPTER 25
391
FIGURE 25.4 The Missing Dependency Information message box.
7. The wizard then moves to the Included Files window, where you see a list of all the DLLs and libraries that will be included in the setup package with your application (see Figure 25.5). It’s important to remove the check marks from the DirectX 7 and DirectX 8 DLLs (dx7vb.dll and dx8vb.dll). You will add the DirectX support files later.
FIGURE 25.5 Deselecting the DirectX components.
8. Next, click the Add button in the Included Files window so that you can add the files for the DirectX runtime environment. By including these files with the setup, all the hard stuff is taken care of for you. In the Add Files dialog box, browse to the following folder: \redist\DirectX81. Make sure you select All Files (*.*) in the Files of Type list box (see Figure 25.6), or you won’t see all the files in the folder. Select all the files in this folder, and then click Open to add each component of this folder to your package.
25 DIRECTSETUP
392
Finishing Touches PART VII
FIGURE 25.6 Adding files to the setup package.
9. Click OK in the Missing Dependency Information message box that appears again. All the DirectX supporting setup files should now be part of your setup package. 10. Click Next in the Included Files window to move to the Cab Options window. If you are going to put your application setup package on the network or on a CD, select the Single Cab radio button. If you are putting the package on floppies, select the Multiple Cabs radio button. 11. Click Next to move to the next window, where you specify the title of the application. Change the title, if you like, and click Next. 12. In the Start Menu Items window, you choose how the application will appear in the Start menu system in Windows. You can choose to create a Windows menu group, add additional items to the menu, and adjust its properties. Figure 25.7 shows what this window looks like. Click Next to move to the next window.
FIGURE 25.7 Start Menu Items window.
DirectSetup CHAPTER 25
393
13. Click Next in the Install Locations window to accept the default selections. 14. Click Next in the Shared Files window to accept the default selections. 15. In the final window, you will see a name given to the package. If you want to change it, you can. Then click Finish to start creating the package. 16. After the package is created, you will see a packaging report. Take a look at the report for any errors, and then click Close. Figure 25.8 shows what the package report looks like.
FIGURE 25.8 A package report.
A Little Voodoo Normally in Visual Basic, you would continue the package and deployment process by deploying the setup you just finished creating. Normally, yes—however, with DirectX you have to make another modification. These instructions are critical, so follow them carefully. 1. Copy the following file to the Support subfolder of your package folder: \samples\Multimedia\VBSamples\Misc\bin\Setup1.exe. This folder should be where you told the Package and Deployment Wizard to create the package. You will be replacing the Setup1.exe file that is already there. 2. In the Support folder is also a .bat file (the only .bat file in this folder). Start the batch file.
Now, you can begin the process of deploying the setup.
DIRECTSETUP
This process will re-create the package with all the parameters you specified during the package process, but will use a new Setup1.exe file in the CAB file. This procedure is necessary because a normal Setup1.exe file does not know how to set up DirectX on a user’s machine.
25
394
Finishing Touches PART VII
Deploying the Setup After creating the setup package, you need to clean it up and move it to a location for pickup by the user. These processes are part of the deployment phase. In this phase, the Package and Deployment Wizard just picks up the final packaged files from the package folder and places them in a new folder for distribution. The following steps show how this is done: 1. Start the Package and Deployment Wizard again. (refer back to Figure 25.1 for the menu choices). 2. To deploy your setup, click the Deploy button in the wizard’s first window. 3. The Package to Deploy window opens. If the displayed package is the one you have just created, then click Next. If not, select it in the drop-down list (see Figure 25.9).
FIGURE 25.9 The Package to Deploy window.
4. The next window you see is the Deployment Method window. If you want to distribute the application on floppies, choose the Floppy Disk radio button; if distribution will be on CD or a network, choose the Folder radio button; and if distribution will be on a Web server, choose the Web Publishing radio button. For DirectX applications, the Folder option is the most widely used. Then click Next. 5. Next, you need to select a folder to accept the package. Choose the local or network path, and then click Next. 6. After you have made all your choices for deployment, the wizard will ask you for a name for the deployment script. Click Finish if you want to use the default; otherwise, you can change it. 7. After the package is deployed, you will see a deployment report. Take a look at the report for any errors, and then click Close.
DirectSetup CHAPTER 25
395
Your package has been deployed. All you have to do is copy the files in the setup directory to a CD or network location, and people can begin using your program.
Alternatives to the Package and Deployment Wizard There are some great third-party packaging programs on the market that I would suggest if you are going to be doing a lot of DirectX application programming. The two major ones are Wise and Install Shield. Both can be customized and provide support for DirectX with plug-ins that can be downloaded from their Web sites. Using a third-party application such as these programs can make your application look more professional and make your life a lot easier, too.
Summary In this chapter, you have learned about the basics of using the DirectXSetup library DLL to determine the user’s version of DirectX. You’ve also learned how to set up DirectX on the user’s machine by using the same DirectXSetup libraries and the DirectXSetup function. You have also learned how to use the Package and Deployment Wizard to create a full setup for your DirectX applications. Finally, you’ve learned about alternative setup programs that offer good support for DirectX. In the following appendix, you will learn how to use DirectX with the new VB .NET development environment.
25 DIRECTSETUP
PART
VIII
Appendix
The appendix includes information about the VB .NET environment and how it can be used with DirectX 7 and DirectX 8. It also details some debugging tools that can help when working with DirectX.
IN THIS PART A VB .NET and DirectX
399
APPENDIX
VB .NET and DirectX
A
IN THIS APPENDIX • Setting Up DirectX for Use in Visual Basic 400 • Debugging Your Code in VB .NET
403
400
Appendix PART VIII
VB .NET can use most of the functionality of DirectX; however, there are a few things you need to know to use DirectX in this new environment. This appendix focuses on items specific to using DirectX to work with VB .NET. First, you’ll look at how to set up the VB .NET environment to communicate with DirectX. Then you will be looking at error handling and debugging in the VB .NET environment.
Setting Up DirectX for Use in VB .NET Before you can begin working with DirectX in the VB environment, you should understand some of the necessary items to make this transition easier. Among them is the ability to create a reference to DirectX within VB. You also need to understand how to reference the DirectX objects. Finally, this chapter gives you some tips on performance enhancement to help your applications run more efficiently.
Converting the DirectX DLLs to VB .NET Format Because VB .NET handles Component Object Model (COM) objects differently than previous versions of Visual Basic did, you need to convert the DirectX 7 and DirectX 8 dynamic link libraries (DLLs) to a Visual Studio .NET format. To do that, you use a tool called the Type Library to .NET Assembly Converter (tlbimp.exe), following these steps: 1. Click the Start button on your desktop, click Run, type cmd.exe in the Open text box, and then click the OK button. 2. From the command prompt, navigate to the tlbimp.exe file (c:\program files\microsoft.net\frameworksdk\bin). 3. Type in the following and press Enter to run it: tlbimp.exe c:\winnt\system32\dx7vb.dll
4. Type in the following and press Enter to run it: tlbimp.exe c:\winnt\system32\dx8vb.dll
5. Close the command-prompt window. The output you will see on the screen will look similar to Figure A.1.
Creating a Reference to the DirectX 8 Type Library For DirectX to work in a VB .NET application, you need to create a reference to the DirectX 8 type library. This reference tells the VB .NET project where to find information on the DirectX objects you’ll be using in your program. Without this reference, VB .NET would have no idea what you were talking about, resulting in runtime errors when you try to compile your program.
VB .NET and DirectX APPENDIX A
401
A VB .NET AND DIRECTX
FIGURE A.1 The Output From the Type Library to .NET Assembly Converter.
To create a reference to the DirectX type library for VB .NET, you must have the DirectX 8 SDK installed. All the examples used in this book and on the book’s CD require the DirectX 8 SDK to be installed. You can get the DirectX 8 SDK from Microsoft’s Web site or on the CD included with this book. To create the reference, follow these steps: 1. Open Visual Studio .NET. 2. Click the Create New Project link on the VS Home Page (shown in Figure A.2) to open the New Project dialog box. 3. In the New Project dialog box (shown in Figure A.3), select Windows Application under the Templates section, and click OK. This will open up a new Windows Application project that we can begin developing and take us back to the Visual Studio Home Page. 4. Choose Project, Add Reference from the menu in the VS Home Page to open the Add Reference dialog box, shown in Figure A.4. 5. Select the COM tab, and look for the components labeled DirectX 7 for Visual Basic Type Library and DirectX 8 for Visual Basic Type Library. Double-click each component to add it to the Selected Components box at the bottom (see Figure A.5), and then click OK.
402
Appendix PART VIII
FIGURE A.2 The VS Home Page.
FIGURE A.3 Selecting the Windows Application template.
FIGURE A.4 The Add Reference dialog box.
VB .NET and DirectX APPENDIX A
403
A VB .NET AND DIRECTX
FIGURE A.5 Selecting the DirectX 8 for Visual Basic Type Library component.
Debugging Your Code in VB .NET Debugging your DirectX code in the VB .NET environment is very similar to how it is done in Visual Basic 6; however, there are enough differences to mention them here. The first thing you need to understand is that error trapping is done a little differently in VB .NET. Also, VB .NET has added some new debugging tools that can help in the debugging process.
Error Trapping in VB .NET As in most programs, error handling is key to a good program. This concept is especially vital in DirectX and VB programming. Error handling in VB .NET has changed drastically since previous versions of VB. With this in mind, it’s important to use the new standard to trap all potential errors in your DirectX code. If you are unable to create a DirectX object, your code should stop running and handle the problem correctly. Failure to do that properly can cause unpredictable behavior in DirectX. It can also give your users the opinion that the program is inferior. The new standard for error handling in VB .NET is to use the Try...Catch...End Try structure. This structure is probably familiar to you if you have used Java or C++ error handling. This type of error handling gives you the benefit of a more structured and readable way of trapping for errors. The examples supplied with this book use this new error-handling structure. Execution code should be placed just after the Try statement. Errors generated within the Try statement are then handled in the Catch statement. After all the errors are handled in the Catch statement, the End Try statement exits the error handling. Any code written after the End Try statement is not handled by the previous Try statement.
404
Appendix PART VIII
The following example shows a simple use of the Try...Catch...End
Try
structure:
Sub MySubroutine() Try ‘’’ Execute code here. Catch ‘’’ Execute error handling code here. End Try ‘’’ Any code that doesn’t need error handling goes here. End Sub
This next example shows the same structure with some actual code applied, illustrating how to trap for a simple divide by zero error: Sub DivideNumbers() Try ‘’’ Begin code execution. x = x / y Catch ‘’’ If a division by zero error occurs, you want to ‘’’ force x to change its value to 0. x = 0 End Try ‘’’ Write out the value for x System.Diagnostics.Debug.WriteLin(x) End Sub
New Debugging Features of VB .NET A few new debugging tools have been added to VB .NET. The two main ones are the exceptions window and the step by line/statement/instruction. The next two sections explain how these two new features can be used to aid in the debugging process.
Exceptions Window: New to VB .NET An exception is an abnormal error that occurs when a program is running. Some exceptions are handled by the objects they occur within; others are not. With the Exceptions window, the developer can trap for exceptions that are not handled through code. It also aids in debugging by causing a break in code execution when an exception is thrown.
Step by Line/Statement/Instruction: New to VB .NET With VB .NET, you can now change the type of stepping you do while debugging. You can choose to step through each line of code, each code statement, or each instruction. This feature is especially helpful in large applications, when navigating can become a nightmare.
NUMBERS 2D graphics animations (DirectDraw), 17 graphics background vertices, creating, 159-161 bee’s coordinates, updating, 162-163 breeze application, 157-163 environments, initializing, 157-159 objects, declaring, 156-157 screens, drawing, 161-162 Object genre type, 196 3D graphics. See also Direct3D animations, 16 buffers, 284-285 DirectSound, cones, 254-256 DirectSound3D, 283-286 graphics balls, 107 brick textures, 109 burlap textures, 109 camera space, 105 curves, comparing simple and complex, 106 4x4 matrix, 111 left-handed Cartesian coordinate system, 104-105 light effects, 110 marble textures, 109
INDEX
406
3D Graphics
matrices, 111-112 meshes, mustard bottles or supporting faces, 108 model space, 105
AcquireResources method, 273
IBasicVideo2 class, methods, 319
action (eA), 195
IDeferredCommand class, methods, 319
action maps, 194
objects, 105-109
application actions, 195
polygon count, 106
ConfigureDevices method, 202-203
right-handed Cartesian coordinate system, 104 scaling matrix, 111 space coordinate system, 104-105 textures (brick, burlap, marble), 109
configuring, 200-203 controls, assigning actions, 198-199 device objects, assigning actions, 198-199 devices, 200-201
3D world space, 105
DirectInput, 190
view space, 105
genres, 195-199
Listener object (DirectSound3D), 285-286
GetDeviceData method, 203
Mark Web site, 43
matching devices, finding, 199
Model genre type, 196
preparing, 195
Navigation genre type, 196
priorities, 197
Object genre type, 196
SetActionMap method, 201
3DBuffer object, 252 3DListener object, 252 world space, 105 4x4 matrix, 111
A
actions, assigning to controls or to device objects, 198-199 ActivateAtPosition method, 332
IMediaEvent object, methods, 320 IMediaEventEx object, methods, 320 IMediaPosition object, methods, 321 IMediaTypeInfo object, methods, 321 IPinInfo object, methods, 321-322 IQueueCommand class, methods, 322 IRegFilterInfo object, methods, 322 IVideoWindow class, methods, 323-324 Jukebox application, code, 324-330 libraries, type quartz.dll, 316 references, creating, 295
ActivateButton method, 332
Add Files dialog box, 391
ActiveMovie DLL
Add Reference dialog box, 21, 401-402
Abort method, 307
FilgraphManager object, methods, 316
AcceptParentalLevelChange method, 332
IAMCollection class, methods, 316
access times, reducing, 36
IAMStats class, methods, 317
accessing keyboards, 207
IBasicAudio class, methods, 317
Acquire method, 183, 225, 241
IFilterInfo object, methods, 319
IBasicVideo class, methods, 317-318
AddAttachedSurface method, 58 AddComponentLong method, 365 AddComponentString method, 365 AddDirtyBox method, 128
animations
AddDirtyRect method, 118, 126
AMTimelineGroup class, methods, 300-301
AddError method, 307
AMTimelineObj class, methods, 301-302
AddFilter method, 307 AddFoundLocation method, 312 AddGroup method, 298 AddNotificationType method, 260 AddPlayerToGroup method, 369-371
AMTimelineSrc class, methods, 302-303
keyframes, 42
Output window, 30
analyzing
addresses
keyboard data, 214-215
DirectPlay games, 362
AnglesAvailable method, 332
DirectPlay8Address class, 363-365
animations. See also 2D graphics; 3D graphics back buffering, 48-49
AddSourceFilter method, 308, 316
backgrounds, 42
AddValue method, 317
blits (bit block transfers), 43-44
Advanced Animation and Rendering Techniques: Theory and Practice, 104
improving, 25
AMTimelineTrans class, methods, 303
joystick data, 226-227
AdjustTime method, 260
images, 81
model sheets, 40
DIDEVICEOBJECTDATA variable, 241-244
hosts, data types, 364
gamma controls, 72, 82-83
AMTimelineTrack class, methods, 303
AddRemovePlayerGroup method, 368
devices, data types, 364-365
frames, 40-43
billboards, 47-48
blitting, 48, 72
offscreen drawing surfaces, 45
overlay surfaces (screens), 72, 83-85 page flipping, 48-49, 72 palettes, 45 animations, 92, 95-101 code to share, 94-95 colors, 92 cycling, 49 DirectDrawPalette.SetEntr ies method, 96 DirectDrawSurface7.SetPa lette method, 97 entries, 92-93 modifying, 96-97
breakpoints, 30-31
PALETTEENTRY data type, code, 92-93
clipping, 46-47
sharing, 93
AdvisePeriodic method, 311
color controls, 72, 82-83
AdviseTime method, 311
cycles, 41
surfaces, code to change, 98-100
Air Combat genre type, 196
debugging, 30-31
switching, 97
alpha-blending images, 81
Direct3D, 16
types, 92
AMTimeLine class, methods, 298-299
DirectDraw, 17
primary drawing surfaces, 45
DirectDrawSurface command (Shooting Gallery), 45, 85-88
RECT type, definition, 46
AMTimelineComp class, methods, 299 AMTimelineEffect class, methods, 300
error trapping, 29-30 execution loops, 27-29
rectangles, 46 secondary drawing surfaces, 45
407
408
animations
Shooting Gallery (DirectDraw), code, 65-68, 86-88 sprites, 44 Step Into debugging tool, 30 Step Over debugging tool, 30 storyboards, 41-42 surfaces BLIT routine, 79-82
lobbyable game, 354
AutoShow method, 323
multimedia, 8
AvgTimePerFrame method, 318
objects, declaring, 163-164 overlays, creating, 84 scenes, rendering, 168-171 templates, 402 vectors or vertices, manipulating, 171-173
blitting to, 79
ApplyStateBlock method, 119
Blt method, code, 79-80
architectures
BltColorFill method, 80-81 BltFast method, code, 81 BltFx method, 81-82 BltToDC method, code, 82 creating, 72-75 descriptions, 75-77 flipping, 77
DirectDraw, 55-62
DirectPlay, 363
backgrounds
DirectPlay Voice, 377 DirectShow, 291-293 DirectSound, 251
AreYouBlank method, 303 AspectRatio method, 332 assembly converter, output from type library, 401 asynchronous audio playback, 248
billboards, 164-173
AsyncOpComplete method, 368
breeze, 157-163
audio. See sound
creating, 163
AudioPath object, 249
environments, initializing, 165-168
audiopaths (DirectMusic Performance object), 259
Jukebox, code, 324-330
AudioStreamsAvailable method, 332
lobby (DirectPlay), 357-358
B
BackColor method, 332
lobby (DirectPlay), 354
actions (action maps), 195
object, 180
DirectMusic, 248
Watch window, 30
applications. See also Direct3D
mouse, 238, 242-243
back buffering, animations, 48-49
DirectX object model overview, 17
AppDesc method, 368
axes
DirectInput, 180-190
timers, 25-26
APIs (Application Programming Interfaces), 10-11
AVI files, playing with filters, 291
animations, 42 vertices, 159-161 BackgroundPalette method, 323 backward-compatibility, VB6( ) functions, 36 Balance method, 317, 332 balls polygon counts, 107 reflective, 110 Band object, 249 Baseball Batting genre type, 196 Baseball Fielding genre type, 196 Baseball Pitching genre type, 196 Basketball Defense genre type, 196 Basketball Offense genre type, 196
CanStep method
BltFx method, 58, 81-82
3D, DirectSound3D, 284-285
breeze application, 156-163
BltToDC method, 82
unlocking, 127
coordinates, updating 2D graphics, 162-163
.bmp file extension, 74
BuildActionmap method, 183 BuildFromURL method, 365
BeginFlush method, 310
boards, storyboards, 41. See also billboards
BeginScene method, 119, 131, 161
BookmarkOnClose method, 331
button (eB), 195
BeginStateBlock method, 119
BookmarkOnStop method, 331
buttons
bees
billboards animations, 47-48 constants, code to declare, 164 creating, 163 environments, initializing, 165-168 objects, declaring, 163-164 scenes, rendering, 168-171 vectors or vertices, manipulating, 171-173 bit block transfers (blits), 43-44
Deploy, 394
bottles, mustard (meshes), 108
Floppy Disk, 394
brackets, { } (curly), 343
mouse, axis constants, 242243
breakpoints, animations, 30-31 breeze application, 156-163
blitting
ByVal declaration (Direct3D parameters), 132
buffered data, 185 buffering,
buffers
converting, 282
SetActionMap method, 201
descriptors, 274-276
camera space, 105
DirectSound, 273-280
Cancel method, 319
index, 123
CancelAsyncOperation method, 366, 369-371
locking, 127
image rectangles, 72
secondary, 254, 273-274
to surfaces, 79-82
sizes, setting for user input from mouse, 239
BltFast method, 58, 81
calling property sheets, 203
primary, 254, 273
BltColorFill method, 58, 80-81
C
capture, creating, 280-281
animations, 48
Blt method, 58, 79-80
Single Cab, 392
Browser genre type, 196
Z-buffering images, 81
blits (bit block transfers), 43-44
Multiple Cabs, 392
ButtonsAvailable, 332
bitmap images, textures (3D objects), 109
BLIT routine, surfaces, 79-82
Folder, 394
brick textures, 109
back, 48-49
blending, alpha-blending images, 81
button object, 180
BorderColor method, 323
BitErrorRate method, 318
BitRate method, 318
burlap textures, 109
CancelDefaultHandling method, 320 CanSeekBackward method, 321
sound, 254, 277-280
CanSeekForward method, 321
sticky focus, 276
CanStep method, 332
409
410
capabilities
capabilities (Caps), 31 Caps Viewer, 31-32
Civilian Flight genre type, 196
DirectInputEnumEffectsDevic eInstance, 189
Caption method, 323
classes, 22-23
DirectMusic, 249-250
capture buffers, creating, 280-281
AMTimeLine, methods, 298-299
DirectPlay Voice, 377
Capture
AMTimelineComp, methods, 299
DirectPlay8Client, methods, 366-367
AMTimelineEffect, methods, 300
DirectPlay8Event, 367-369
method, 332 object, 252 capture objects, creating, 280 CaptureBuffer object, 253
AMTimelineGroup, methods, 300-301
CaptureStateBlock method, 119
AMTimelineObj, methods, 301-302
cards
AMTimelineSrc, methods, 302-303
full-duplex sound (DirectPlace Voice), 376 graphics, display modes, 64
AMTimelineTrack, methods, 303
cars, changing colors, 95
AMTimelineTrans, methods, 303
Cartesian coordinate system (3D graphics)
core (DirectPlay), 363
left-handed, 104-105 right-handed, 104 CCActive method, 332 ChangePassword method, 331 CheckDepthStencilMatch method, 116 CheckDeviceFormat method, 116 CheckDeviceMultiSampleTyp e method, 116 CheckDeviceType method, 116 chordmaps DirectMusic, 250 DirectMusic Performance object, 259
DirectDraw, 55-56, 65-68 DirectDrawClipper, 61-62 DirectDrawPalette, 59-61 DirectDrawSurface, 57-59 DirectInput, 181-182, 238, 206 DirectInputDevice, 183-185, 238 DirectInputDeviceInstance, methods, 186-187 DirectInputDeviceObjectInsta nce, methods, 185-186
DirectPlay8Address, 363-366
DirectPlay8LobbiedApplication, methods, 358 DirectPlay8LobbyClient, methods, 357 DirectPlay8LobbyEvent, methods, 358-359 DirectPlay8Peer, methods, 369-371 DirectPlay8Server, methods, 371-372 DirectPlayLobby, relationships, 354 DirectPlayVoiceClient8, 378379 DirectPlayVoiceEvent8, 379-380 DirectPlayVoiceServer8, 380-381 DirectPlayVoiceTest8, 381 DirectSound, 252-254 Direct3D8, methods, 116-117 Direct3DBaseTexture8, methods, 117-118
DirectInputEffect, 187-189
Direct3DCubeTexture8, methods, 118
DirectInputEffectDeviceInstan ce, 188
Direct3DDevice8, methods, 119-123
DirectInputEnumEffects, 189-190
Direct3DIndexBuffer8, methods, 123-124
code
Direct3DResource8, methods, 124-125
IEnumMediaTypes, methods, 306
Direct3DSurface8, methods, 125
IEnumPins, methods, 306
Direct3DSwapChain8, methods, 126
IFilterGraph, methods, 307
Direct3DTexture8, methods, 126 Direct3DVertexBuffer8, methods, 127
IErrorLog, methods, 306
clients DirectPlay games, 362 lobby, 356-357 peer-to-peer, 346-348
IGraphBuilder, methods, 307308
DirectPlay8Client class, 366
IMediaFilter, methods, 308
DirectPlayVoiceClient8 class, 378
IMediaSample, methods, 309
clipping
Direct3DVolume8, methods, 127-128
IPersistStream, methods, 309
Direct3DVolumeTexture8, methods, 128
IQueueCommand, methods, 322
ClockToMusicTime method, 260
DirectXEvent, 214, 226
IReferenceClock, methods, 310
Clone method, 263, 306, 351, 357-358, 366
ISmartRenderEngine, methods, 311
CloseDown method, 260
DVDRect, methods, 330 IAMCollection, methods, 316 IAMErrorLog, methods, 304 IAMSetErrorLog, methods, 304 IAMStats, methods, 317 IAMTimelineEffectable, methods, 304
IPin, methods, 310
IVideoWindow, methods, 323-324
animations, 46-47 clipper rectangles, 47
closing sessions, 348, 351
MediaLocator, methods, 312
clsidDefaultSynth (DirectMusic DMUS AUDIOPARAMS member), 264
MSDVDAdm, methods, 331
code. See also syntax
MediaDet, methods, 311
IAMTimelineSplittable, methods, 305
MSWebDVD, methods, 332-336
backward-compatibility, VB6( ) functions, 36
IAMTimelineTransable, methods, 305
RenderEngine, methods, 312-313
billboard applications
IAMTimelineVirtualTrack, methods, 306
SmartRenderEngine, methods, 313
IBasicAudio, methods, 317
Xml2Dex, methods, 313
IBasicVideo, methods, 317-318
Clear method, 119, 131, 366
IBasicVideo2, methods, 319
client/servers (DirectPlay)
IDeferredCommand, methods, 319 IEnumFilters, methods, 306
ClearAllGroups method, 298
constants, declaring, 164 environments, initializing, 165-168 objects, declaring, 164 scenes, rendering, 168-171 vectors or vertices, functions, 171-173
clients, initializing, 349
Blt method, surfaces, 79-80
communication model, 344-345
BltColorFill method, surfaces, 81
connections, 349-351
BltFast method, surfaces, 81
411
412
code
BltFx method, surfaces, 82 BltToDC method, surfaces, 82 breeze application
Form MouseMove event, modifying, 162-163
PALETTEENTRY data type, 93
gamma control objects, creating, 83
palettes, 45, 92-95, 99
background vertices, initializing, 159-161
joystick program, 228-236
initializing, 157-159
Jukebox application, 324
objects, declaring, 156-157
Keyboard program, 215-217 overlays, creating, 84-85
color control objects, creating, 83
Palette Animation program, 100-101
converting VB6 to VB .NET, 36
PALETTEENTRY data type, 92-93
CreateSurface method, 73
palettes
CreateSurfaceFromFile methods, 74-75
manipulating, 96-97 sharing, 94-95
DDSURFACEDESC2 declaration, surface descriptions, 76-77 DirectDrawSurface command (Shooting Gallery), 86-88 DirectDrawSurface.Flip method, 78 DirectInputDevice8 object, declaring, 208 DirectPlayVoiceClient8 class, holding, 378
surfaces, changing, 98-100
DirectDrawPalette, Palette Animation program, code, 100-101 DirectDrawSurface, 72, 85-88 Project menu, References, 295 CommitDeferredSettings method, 286
comparing
sound buffers, modifying, 279-280 code flowcharts, Shooting Gallery (DirectDraw), 68 codecs (DirectShow), 293-295
ColorKey method, 332
stepping by line, statement, or instruction, 404
DirectDraw7.CreateSurface, 72
Shooting Gallery (DirectDraw), 65-68, 86-88
DirectPlayVoiceServer8 class, holding, 380
Exceptions window, 404
commands
communication models (DirectPlay), 344-345
collections, IAM Collection, 292
debugging, 403-404
Combat Racing genre type, 196
screens, drawing, 161-162
DirectPlayVoiceEvent8 class, holding, 379
DirectX
COM (Component Object Model), 23
colors of cars, changing, 95 color control objects, code to create, 83 controls (images), 72, 82-83
DirectXSetup function, 388
gamma controls (images), 72, 82-83
Flip method, surfaces, 78
palette animations, 92, 95-100
coordinate spaces, 105 DirectMusic and DirectSound, 256 &H80 and lData member (DIDEVICEOBJECTDATA variable), 243 HAL (Hardware Abstraction Layer) and HEL (Hardware Emulation Layer), 62-63 simple and complex curves, 106 Windows display mode and full-screen display mode, 64 compatibility, backward (VB6( ) functions), 36 compiling speed, increasing, 35-36
constants
complex and simple curves, comparing, 106
Connect method, 308-310, 322, 347-350, 359, 366,
Component Object Model (COM), 23
ConnectApplication method, 357
billboard applications, code to declare, 164
components
ConnectComplete method, 350, 368
CONST DIKEYFLAGS values, 209-214
ConnectDirect method, 307-308, 322
CONST DSBCAPSFLAGS (flag constants), 276
DirectInput, 190-191 DirectX, 16-18, 24-25, 391 Composer object, 250 composing music (DirectMusic) audio parameter structures, 264-265
ConnectedTo method, 310, 322 ConnectFrontEnd method, 312
constants axis, mouse button, 242-243
D3DPT_TRIANGLELIS, 136 DIMOFS_BUTTON0, 242 DIMOFS_BUTTON1, 242
connecting to sessions (DirectPlay), 350
DIMOFS_BUTTON2, 242
DirectMusic Band object, 265 DirectMusic Loader object, 258-259
connection types (DirectPlay service providers), 340
DIMOFS_BUTTON4, 243
DirectMusic Performance object, 259-262 DirectMusic Segment object, 263-264 Loader object, 267 Performance object, 268 performances, 265-267 Producer, 268-269
finding, 349-350 peer-to-peer clients, 347 ConnectionMediaType method, 310, 322 connections DirectPlay, 341, 347-351 DirectPlay Voice, 381-382
Segment object, 268
ConnectionSettings method, 359
variables, declaring, 267
ConnectResult method, 379
condition effect, joystick force feedback, 228
ConnectToCollection method, 263
cones (DirectSound 3D), 254-256
ConnectWithType method, 322
Confidence method, 319
CONST DIKEYFLAGS constant values, 209-214
ConfigureDevices method, 182, 202-203 configuring action maps, 200-203 ConfirmPassword method, 331
CONST DSBCAPSFLAGS (flag constants), 276 constant force effect, joystick force feedback, 228
DIMOFS_BUTTON3, 243
DIMOFS_BUTTON5, 243 DIMOFS_BUTTON6, 243 DIMOFS_BUTTON7, 243 DIMOFS_X, 243 DIMOFS_Y, 243 DIMOFS_Z, 243 DSBCAPS_CTRL3D, 276 DSBCAPS_ CTRLCHANNELVOLUME, 276 DSBCAPS_CTRLFREQUENCY, 276 DSBCAPS_CTRLFX, 276 DSBCAPS_CTRLPAN, 276 DSBCAPS_CTRLPOSITIONNOTIFY, 276 DSBCAPS_CTRLVOLUME, 276 DSBCAPS_GETCURRENTPOSITION2, 276 DSBCAPS_GLOBALFOCUS, 276 DSBCAPS_LOCDEFER, 276
413
414
constants
DSBCAPS_ LOCHARDWARE, 276 DSBCAPS_ LOCSOFTWARE, 276 DSBCAPS_MUTE3DATMAXDISTANCE, 276 DSBCAPS_PRIMARYBUFFER, 276
joysticks, setting, 222 parameter, setting, 207
CreateDevice method, 117, 130, 165, 182, 206
sound buffers, 278
GUID_SysMouse, 238
supported by DirectInput object, 207
joysticks, 220
coordinates bees, 2D graphics, 162-163
DSBCAPS_STATIC, 276
camera space, 105
DSBCAPS_STICKYFOCUS, 276
DirectSound3D, 283
CreateEffect method, 183 CreateEffectFromFile method, 183 CreateEmptyNode method, 299 CreateGroup method, 368371
flags, 388
left-handed Cartesian coordinate system, 104-105
genres (action maps), 196-197
model space, 105
CreateImageSurface method, 119
keyboards, 209-214
right-handed Cartesian coordinate system, 104
CreateIndexBuffer method, 119
spaces, comparing, 105
CreateLights subroutine, 144-146
controls action maps, assigning actions, 198-199 color or gamma (images), 72, 82-83 Microsoft Web DVD
3D space coordinate system, 104-105 view space, 105 CopyRects method, 119
CreateMatrices function, 141 subroutine, 139-141
DVDRect class, methods, 330
core classes (DirectPlay), 363
CreateNewGuid method, 343
Count method, 317
CreatePalette method, 56
MSDVDAdm class, methods, 331
Create3DsoundBuffer method, 378
CreatePixelShader method, 119
MSWebDVD class, methods, 332-336
CreateAdditionalSwapChain method, 119, 126
CreatePlayer method, 368
virtual, 198 converting buffers, 282 DirectX DLLs, 400 VB6 to VB .NET, 36 cooperative levels
CreateAudioPath method, 260 CreateCaptureBuffer method, 280 CreateClipper method, 56 CreateCubeTexture method, 119
DirectInput user interactions, 180
CreateCustomEffect method, 183
DSSCL_EXCLUSIVE, 278
CreateDepthStencilSurface method, 119
DSSCL_NORMAL, 278
CreatePrimarySoundBuffer method, 272-274 CreateRenderTarget method, 119 CreateSegment method, 265 CreateSoundBuffer method, 272-274 CreateSoundBufferFromFile method, 272, 278 CreateSoundBufferFromReso urce method, 272
CurrentTime method
CreateStandardAudioPath method, 260 CreateStateBlock method, 119 CreateSufraceFromFile method, 75 CreateSurface method, 56
capture objects, 280 color control objects, code, 83 Direct3D applications, 129 environment setups, 130-131
CreateTextureFromFile method, 148 CreateVertexBuffer method, 119, 135
matrices, 137-142
sound buffers, 277-278
meshes, 149-153
surfaces, 72-73, 94
objects, destroying, 132
BLIT routine, 79-82
objects, initializing, 129-130
blitting to, 79
scenes, rendering, 131-132
BltColorFill method, 80-81
textures, 146-149 vertices, 133-137
CreateVertexShader method, 119
DirectPlay8Client object instances, 349
CreateVoicePlayer method, 379
DirectPlay8Peer object instances, 346
CreateVolumeTexture method, 119
DirectX objects, 23
creating action map devices, 200
DSBUFFERDESC type (buffer descriptors), 275-276 events for user input from mouse, 240
application overlays, 84 background vertices for 2D graphics, 159-161
gamma control objects, code, 83 joystick objects, 220-222
billboard applications environments, initializing, 165-168 objects, declaring, 163-164
lights for Direct3D applications, 144-145 matrices for Direct3D applications, 139-141 objects, 238
scenes, rendering, 168-171 overlays, code, 84-85 vectors or vertices, manipulating, 171-173
DirectX 8 type library, 21, 400-401 setup packages, 389-393
surfaces, code, 73
CreateTexture method, 119
ActiveMovie type library, 295
lights, 142-146
overlays, code to create, 84-85
CreateSurfaceFromFile method, 56, 74-75
references
rectangles, 126
Blt method, code, 79-80
BltFast method, code, 81 BltFx method, 81-82 BltToDC method, code, 82 descriptions, 75-77 flipping, 77 from files, 74-75 vertices for Direct3D applications, 135-136 curly brackets ({ }), 343 CurrentAngle method, 332 CurrentAudioStream method, 332 CurrentButton method, 332 CurrentCCService method, 332 CurrentChapter method, 332 CurrentDiscSide method, 332 CurrentDomain method, 332 CurrentPosition method, 321 CurrentStream method, 311
buffer descriptors, 275-276
CurrentSubpictureStream method, 332
capture buffers, 280-281
CurrentTime method, 332
415
416
CurrentTitle method
CurrentTitle method, 332 CurrentVolume method, 333 CursorType method, 333 curves, comparing simple and complex, 106
mouse
DirectDraw objects, 56
GetDeviceData method, 241
DirectDrawClipper objects, 61
intermediate, 244
DirectDrawSurface objects, 57
retrieving, 241
DirectDrawPalette objects, 60
cycles, animations, 41
private, 126
DirectInputDevice8 object, code, 208
cycling palettes, animations, 49
synchronizing, 15-16
DirectMusic variables, 267
types
DirectSoundSecondaryBuffer8 object, 273
device addresses, 364-365
D D3DDISPLAYMODE structure, 130 D3DPRESENT_PARAMETERS, 130 D3DPT_TRIANGLELIST constant, 136 D3DVertexBuffer8SetData function, 136 data buffered, 185
DIPROPLONG, 239 host addresses, 364 PALETTEENTRY, code, 92-93 DDSURFACEDESC2 declaration, surface descriptions, 75-77 dead zones (joysticks), 224-225 Debug statements, removing, 36 debugging
data format parameter, setting, 207
animations, 30-31
immediate, 185
tools, Step Into or Step Over, 30
joysticks analyzing, 226-227 DirectXEvent class, 226 formats, defining, 222 handling, 225 looping, 226-227 retrieving, 226 keyboards analyzing, 214-215
DirectX code, 403-404
declarations ByVal, Direct3D parameters, 132 DDSURFACEDESC2, surface descriptions, 75-77 declaring
DirectSound3DBuffer8 object, 284 DirectSound3DListener8 object, 285 DirectX objects, 23-24 objects for billboard applications, 163-164 for breeze application, code, 156-157 for 2D graphics, 156-157 DefaultAudioLanguage method, 333 DefaultAudioLanguageExt method, 333 DefaultAudioLCID method, 331 DefaultMenuLanguage method, 333 DefaultMenuLCID method, 331 DefaultSubpictureLanguage method, 333
constants for billboard applications, code, 164
DefaultSubpictureLanguageE xt method, 333
Direct3D
DefaultSubpictureLCID method, 331
interpreting, 208
COM objects, 24
retrieving, 207-214
variables, 130
Deviceobject
defining joystick data formats, 222
AMTimelineSrc class, methods, 302-303
IReferenceClock class, methods, 310
definitions, RECT type, 46
AMTimelineTrack class, methods, 303
ISmartRenderEngine class, methods, 311
AMTimelineTrans class, methods, 303
MediaDet class, methods, 311
DeleteBookmark method, 333 DeletePatch method, 120 DeletePixelShader method, 120 DeleteStateBlock method, 120 Delete3DsoundBuffer method, 378 DeleteVertexShader method, 120 DeleteVoicePlayer method, 379 deleting elements, 36 demos Doggie (WinG), 10 Jump Start (WinToon), 11 Deploy button, 394 Deploying setup packages, 394-395 Deployment Method window, 394 DES (DirectShow Editing Services)
Dexter 1.0 type library, 298
MediaLocator class, methods, 312
IAMErrorLog class, methods, 304
RenderEngine class, methods, 312-313
IAMSetErrorLog class, methods, 304
SmartRenderEngine class, methods, 313
IAMTimelineEffectable class, methods, 304
Xml2Dex class, methods, 313
IAMTimelineSplittable class, methods, 305 IAMTimelineTransable class, methods, 305 IAMTimelineVirtualTrack class, methods, 306 IEnumFilters class, methods, 306 IEnumMediaTypes class, methods, 306 IEnumPins class, methods, 306 IErrorLog class, methods, 306 IFilterGraph class, methods, 307
AMTimeLine class, methods, 298-299
IGraphBuilder class, methods, 307-308
AMTimelineComp class, methods, 299
IMediaFilter class, methods, 308
AMTimelineEffect class, methods, 300
IMediaSample class, methods, 309
AMTimelineGroup class, methods, 300-301
IPersistStream class, methods, 309
AMTimelineObj class, methods, 301-302
IPin class, methods, 310
descriptions, surfaces, 75-77 descriptors DDSURFACEDESC2 surfaces, 77 DirectSound buffers, 274-276 deselecting DirectX components, 391 DestinationHeight method, 318 DestinationLeft method, 318 DestinationTop method, 318 DestinationWidth method, 318 DestroyClient method, 371 DestroyGroup method, 368-371 destroying objects, 36, 132 DestroyPeer method, 369 DestroyPlayer method, 348, 368 developers (DirectX), 12-13 device addresses, data types, 364-365 Device object, 179-180
417
418
devices
devices action maps, 200-20 DirectInput, 179-180 enumeration, 179 HIDs (Human Interface Devices), 185 input, exclusive or nonexclusive, 180 joysticks, 221-224 matching, finding, 199 objects (action maps), assigning actions, 198-199 Dexter 1.0 type library, 298 dialog boxes
DIMOFS_BUTTON6 constant, 243
code flowchart (sample), 68
DIMOFS_BUTTON7 constant, 243
CreatePalette method, 56
DIMOFS_X constant, 243 DIMOFS_Y constant, 243 DIMOFS_Z constant, 243
CreateSurface method, 56 CreateSurfaceFromFile method, 56
DIPROPLONG data type, 239
DirectDraw class, 55-56, 65-68
DIPROP_AUTOCENTER flag, 223
DirectDrawClipper class, 61-62
DIPROP_AXISMODE flag, 223
DirectDrawPalette class, 59-61
DIPROP_BUFFERSIZE flag, 223 DIPROP_CALIBRATIONMODE flag, 224
Add Files, 391
DIPROP_DEADZONE flag, 224
Add Reference, 21, 401-402
DIPROP_FFGAIN flag, 224
New Project, 401
DIPROP_FFLOAD flag, 224
References, 22, 295-296
DIPROP_GRANULARITY flag, 224
VB New Project, 21, 295
CreateClipper method, 56
DirectDrawSurface class, 57-59 display modes, 63-64 DrawText method, 58 Flip method, 58 GetCaps method, 58, 60 GetClipList method, 62
DIPROP_RANGE flag, 224
GetClipper method, 58
DIPROP_SATURATION flag, 224
GetColorKey method, 58
DirectAudio library
digital editing. See DES
DirectMusic, 17
GetDirectDrawGammaControl method, 59
DIMOFS_BUTTON0 constant, 242
DirectSound, 18
GetDisplayMode method, 56
DIDEVICEOBJECTDATA variable, analyzing, 241-244 DIDEVICEOBJECTSEQUENCE variable, 244
DirectDraw, 17, 24
GetDirectDraw method, 58
GetEntries method, 61
DIMOFS_BUTTON1 constant, 242
AddAttachedSurface method, 58
GetHWnd method, 62
DIMOFS_BUTTON2 constant, 242
architecture, 55
HAL (Hardware Abstraction Layer) and HEL (Hardware Emulation Layer), comparing, 62-63
DIMOFS_BUTTON3 constant, 243 DIMOFS_BUTTON4 constant, 243 DIMOFS_BUTTON5 constant, 243
Blt method, 58 BltColorFill method, 58 BltFast method, 58 BltFx method, 58 classes, 55 Shooting Gallery, code, 65-68 syntax, 56
graphics, 54, 64
IsClipListChanged method, 62 IsLost method, 59 life of, 156 LoadPaletteFromBitmap method, 57
DirectInputDeviceInstance class
objects, declaring, 56
DirectDrawSurface7. SetPalette method, 97
Restore method, 59
DirectGraphics, 55, 104
graphic tablets, 180
DirectInput, 17, 24
joysticks, 179, 191
methods, 56-57
RestoreAllSurfaces method, 57 SetClipList method, 62
force feedback, 190-191 gas pedals, 179
action mapping, 190
keyboards, 179, 191
architecture, 180
mouse, 191, 240-244
SetClipper method, 59
DirectInput class, 181-182
SetColorKey method, 59
DirectInputDevice class, 183-185
cooperative levels, supporting, 207
DirectInputDeviceInstance class, 186-187
mouse, 238
DirectInputDeviceObject Instance class, 185-186
relationships among DirectX and DirectInputDevice objects, 220
SetDisplayModel method, 57 SetEntries method, 61 SetFont method, 59 SetHWnd method, 62 SetPalette method, 59 Windows display mode and full-screen display mode, comparing, 64 DirectDraw7.CreateSurface command, 72 DirectDraw7. CreateSurfaceFromFile method, 74 DirectDrawClipper class, 61-62 objects, declaring, 61 DirectDrawPalette class, 59-61 command, Palette Animation program, code, 100-101 objects, declaring, 60
DirectInputEffect class, 187-189 DirectInputEnumEffects class, 189-190
objects, 179-180, 206
steering wheels, 179, 191 technologies, 190-191 trackballs, 180
axes object, 180 user interactions, 178-180 button object, 180 virtual reality gloves, 180 class, 182, 206, 238 yokes, 179, 191 components, 190-191
DirectInputDevice
devices, 179-180 class, 183-185, 238 DirectInput objects, 206, 220, 238 class, 181-182 object, 179
DirectInputDevice8 object, code to declare, 208
DirectInputDevice class, 183-185
DirectInputDevice8.Acquire method, 207
DirectInputDeviceInstance class, 186-187
DirectInputDevice8.Get DeviceStateJoystick method, 226
DirectDrawPalette.SetEntries method, palettes, 96
DirectInputDeviceObjectInsta nce class, 185-186
DirectDrawSurface
DirectInputEffect class, 187-189
DirectInputDevice8. GetDeviceStateKeyboard method, 208
command, 72, 85-88
DirectInputEnumEffects class, 189-190
DirectInputDevice8.Set Property method, 239
objects, declaring, 57
enumeration, 179
DirectInputDeviceInstance class, 186-187
class, 57-59
DirectDrawSurface.Flip method, 77-78
419
420
DirectInputDeviceObjectInstance class
DirectInputDeviceObject Instance class, 185-186
DirectMusic Loader object, 258-259
DirectInputEffect class, 187-188
DirectMusic Performance object, 259-262
DirectInputEffectDevice Instance class, 188
DirectMusic Segment object, 263-264
core classes, 363
DirectInputEnumEffects class, 189
Loader object, 267
DirectPlay8Address class, 363-365
DirectInputEnumEffects DeviceInstance class, 189 Direction method, 322 direction property, joystick force feedback, 228 DirectMusic, 17, 24 architecture, 248 asynchronous audio playback, 248 audio parameter structures, 264-265 AudioPath object, 249 Band object, 249, 265 chordmaps, 250 classes, 249-250 Composer object, 250 DirectSound, comparing, 256 DMUS_AUDIOPARAMS Members, 264-265 Instrument object, 250 Leader object, 250 Loader object, 258-259, 267 MIDI files, 248 music, composing audio parameter structures, 264-265 DirectMusic Band object, 265
communication models client/server, 344-345 peer-to-peer, 344 connections, 341, 349-351
Performance object, 268 DirectPlay8Client class, 366 performances, 265-267 Producer, 268-269 Segment object, 268 variables, declaring, 267
DirectPlay8Event class, 367-368 DirectPlay8LobbiedApplicatio n class, methods, 358
Performance object, 250, 259-262, 268
DirectPlay8LobbyClient class, methods, 357
Segment object, 250, 263-264, 268
DirectPlay8LobbyEvent class, methods, 359
Style object, 250
DirectPlay8Peer class, 369
WAV (wave) files, 248
DirectPlay8Server class, 371
DirectMusicBand8 methods, 265
events, 346, 362 games, 362-371
DirectMusicLoader8 object, methods, 258-259
GUID Generation Program (A), 343-344
DirectMusicPerformance8 methods, 260-262
host migration, 342
DirectMusicPerformance8.Init Audio method, 264
lobbies, 343, 354-359 Lobbies object, 346
DirectMusicSegment8 methods, 263-264
managing with, 362
DirectPlay, 17, 25, 340
network providers, 342-343
message queues, 362
addresses, 362
object, 346
architecture, 363
peer-to-peer, 362
client/servers communication model, 344-345 connections, 349-351 clients, 346-348, 362
clients, 346-348 communication model, 344 players, 341-342 servers, 362 service providers, 340
DirectSound
sessions, 341 system messages, 343 DirectPlay Voice architecture, 377
DirectPlay8LobbyEvent, 347 class, 358-359 object, 346 DirectPlay8Peer
classes, 377
class, methods, 369-371
DirectPlayVoiceClient8 class, 378
object, creating instances, 346
DirectPlayVoiceEvent8 class, 379 DirectPlayVoiceServer8 class, 380 DirectPlayVoiceTest8 class, 381 forwarding server connections, 382 full-duplex sound cards, 376 mixing server sessions, 382 object, 346 peer-to-peer connections, 381 transmission targets, 376 voice sessions, 376
CreateSoundBufferFromFile method, 278 DirectMusic, comparing, 256 DirectSoundCapture8 object, 280 DirectSoundCaptureBuffer8 object, 280
DirectPlay8Server class, methods, 371-372
DirectSound8 object, methods, 272
DirectPlay8VoiceEvent object, 346
DirectSoundSecondaryBuffer8 object, 273-274
DirectPlayClientCreate method, 349
DirectSound3D, 283-286
DirectPlayLobby classes, relationships, 354 DirectPlayPeerCreate method, 346 DirectPlayVoiceClient8 class, 378-379 DirectPlayVoiceEvent8 class, 379-380 DirectPlayVoiceServer8 class, 380-381
DirectSound3DBuffer8, 284-285 DirectSound3DListener8, 285-286 DSBUFFERDESC type (buffer descriptors), 275-276 DSCBUFFERDESC object, 280 Enum object, 253 FX13DL2Reverb object, 253
DirectPlay8Address class, 363-366
DirectPlayVoiceTest8 class, 381
FXChorus object, 253
DirectPlay8Client
FXCompression object, 253
DirectSetup, 18, 386-395
FXDistortion object, 253
class, methods, 366-367
DirectShow, 18, 290-295
FXEcho object, 253
object, 346, 349
DirectShow Editing Services. See DES
FXFlanger object, 253
DirectPlay8Client.Connect method, 350 DirectPlay8Event class, 367-369 object, 346 DirectPlay8LobbiedApplicatio n class, methods, 358 DirectPlay8LobbyClient class, methods, 357
DirectSound, 18, 25, 250
FXGargle object, 253 FXParamEq object, 254
architecture, 251
FXWavesReverb object, 254
asynchronous audio playback, 248
objects for sound effects, 253-254
buffers, 273-280
Play method, 278
capture buffers, NOTHING setting, 281
primary buffers, 254, 273 PrimaryBuffer object, 254
Capture object, 252 ReadBuffer method, 282 CaptureBuffer object, 253 classes, 252-254
421
422
DirectSound
SaveToFile method, 282-283
matrices, 137-142
secondary buffers, 254, 273-274
meshes, 149-153
locking, 127
objects, destroying, 132
unlocking, 127
SecondaryBuffer object, 254
buffers
objects, initializing, 129-130
burlap textures, 109
COM objects, declaring, 24
Start method, 281
scenes, rendering, 131-132
3D, 254-256
textures, 146-149
CreateLights subroutine, 144-146
3DBuffer object, 252
vertices, 133-137
sound, 280-283 sound buffers, 254, 277-280
3DListener object, 252 WAVEFORMATEX object, 280 WriteBuffer method, 282
balls polygon counts, 107 reflective, 110 billboard application
DirectSoundCapture8 object, 280
constants, code to declare, 164
DirectSoundCaptureBuffer8 object, 280
creating, 163
DirectSound8 object, methods, 272 DirectSoundSecondaryBuffer 8 object, 273-274 DirectSound3D, 283-286 DirectSound3DBuffer8 methods, 284-285 object, declaring, 284 DirectSound3DListener8
environments, code to initialize, 165-168 objects, declaring, 163-164 scenes, code to render, 168-171 vectors or vertices, manipulating, 171-173 breeze application background vertices, code to initialize, 159-161
methods, 286 code to initialize, 157-159 object, declaring, 285 Direct3D (Direct X Graphics), 16, 24. See also 2D graphics; 3D graphics
Form MouseMove event, code to modify, 162-163 objects, code to declare, 156-157
applications creating, 129 environment setup, 130-131 lights, 142-146
screens, code to draw, 161-162 brick textures, 109
camera space, 105
CreateMatrices subroutine, 139-141 curves, comparing simple and complex, 106 data, private, 126 DirectGraphics, 104 Direct3D8 class, methods, 116-117 Direct3DBaseTexture8 class, 117-118 Direct3DCubeTexture8 class, methods, 118 Direct3DDevice8 class, methods, 119-123 Direct3DIndexBuffer8 class, 123-124 Direct3DResource8 class, methods, 124-125 Direct3DSurface8 class, methods, 125 Direct3DSwapChain8 class, methods, 126 Direct3DTexture8 class, methods, 126 Direct3DVertexBuffer8 class, methods, 127 Direct3DVolume8 class, 127-128 Direct3DVolumeTexture8 class, methods, 128
DrawIndexedPrimitiveUP method,
dirty rectangles, 118 display mode, setting, 130 4x4 matrix, 111 index buffers, 123 left-handed Cartesian coordinate system, 104-105 lights, effects, 110 locking rectangles, 125 marble textures, 109 matrices, 111-112 meshes, mustard bottles or supporting faces, 108 model space, 105 objects, 24, 105-108, 116, 130 parameters, ByVal declaration, 132 polygon count, 106
Direct3DDevice8 class, methods, 119-123
DirectXSetupGetVersion function, 387
Direct3D8 class, methods, 116-117
dirty rectangles, 118
Direct3DIndexBuffer8 class, 123-124 Direct3DResource8 class, methods, 124-125 Direct3DSurface8 class, methods, 125 Direct3DSwapChain8 class, methods, 126 Direct3DTexture8 class, methods, 126 Direct3DVertexBuffer8 class, methods, 127 Direct3DVolume8 class, 127-128
DisableAutoMouseProcessing method, 333 DisableScreenSaver method, 331 Disconnect method, 307-310, 322, 359, 378 DisconnectResult method, 379 display modes Direct3D, 130 DirectDraw, 63-64 graphics cards, 64 Windows and full-screen, comparing, 64
private data, 126
Direct3DVolumeTexture8 class, methods, 128
distances (DirectSound3D), 284
rectangles, 118, 125-126
DirectX 8
distributing DirectX (DirectSetup), 18
Render subroutine, 145, 148
components, 16, 391
right-handed Cartesian coordinate system, 104
history, 8-12
DLLs, 298, 400. See also ActiveMovie DLL
installing, 20
DMO Test tool, 32-33
setting up, 20, 400
DMUS_AUDIOPARAMS Members, 264-265
scaling matrix, 111 space coordinate system, 104-105 swap chains, 126 textures, 109, 117
Visual Basic, evolution of, 12 DirectXEvent class, 214, 226
DoEvents method, 37
DirectXSetup, library
Doggie demo (WinG), 10
DirectXSetup functions, 386-388
Doppler effect (DirectSound 3D), 256
dxsetup.dll file, 386
DOS, DirectX history, 9
Install Shield packaging program, 395
Download method, 188, 263-265, 268
Direct3DBaseTexture8 class, 117-118
Package and Deployment Wizard, 389-394
DrawIndexedPrimitive method, 120
Direct3DCreate method, 130
Wise packaging program, 395
DrawIndexedPrimitiveUP method, 120
unlocking rectangles, 125 variables, declaring, 130 view space, 105 volumes, 127-128
Direct3DCubeTexture8 class, methods, 118
423
424
drawing
drawing screens, code, 161-162 surfaces, 45 DrawPrimitive method, 120, 136, 141 DrawPrimitiveUP method, 120, 161 DrawRectPatch method, 120 DrawSubset method, 152
DSBCAPS_MUTE3DATMAXDISTANCE constant, 276
DVDRect class, methods, 330
DSBCAPS_PRIMARYBUFFER constant, 276
DVDUniqueID method, 333
DSBCAPS_STATIC constant, 276
DVDTimeCode2bstr method, 333
dxsetup.dll file, 386
DSBCAPS_STICKYFOCUS constant, 276
E
DrawText method, 58
DSBUFFERDESC type (buffer descriptors), 275-276
DrawTriPatch method, 120
DSCBUFFERDESC object, 280
drivers (sound), enumerating, 277
DSETUP_DDRAWDRV constant flag, 388
DSBCAPS_CTRL3D constant, 276
DSETUP_DIRECTX constant flag, 388
EffectGetCount method, 305
DSBCAPS_CTRLCHANNEL VOLUME constant, 276
DSETUP_DSOUNDDRV constant flag, 388
EffectGetPriority method, 300
DSBCAPS_CTRLFREQUENCY constant, 276
DSETUP_DXCORE constant flag, 388
EffectInsBefore method, 305
DSBCAPS_CTRLFX constant, 276
DSSCL_EXCLUSIVE, 278
DSBCAPS_CTRLPAN constant, 276
Duplicate method, 366
joystick force feedback, 228
DuplicateSoundBuffer method, 272
EffectsEnabled method, 299
DSBCAPS_CTRLPOSITION NOTIFY constant, 276 DSBCAPS_CTRLVOLUME constant, 276 DSBCAPS_GETCURRENTPOSITION2 constant, 276 DSBCAPS_GLOBALFOCUS constant, 276
DSSCL_NORMAL, 278
Duration method, 321
eB (button), 195 editing. See also DES Force Feedback Editor, 33-34 GraphEdit tool, 34
effects Doppler (DirectSound 3D), 256
EffectSwapPriorities method, 305
duration property, joystick force feedback, 228
Eject, 333
DVD, Microsoft Web DVD control
EnableResetOnStop method, 333
DVDRect class, methods, 330
DSBCAPS_LOCDEFER constant, 276
MSDVDAdm class, methods, 331
DSBCAPS_LOCHARDWARE constant, 276
MSWebDVD class, methods, 332-336
DSBCAPS_LOCSOFTWARE constant, 276
eA (action), 195
EnableEffects method, 299
EnableTransitions method, 299 EndFlush method, 310 EndOfStream method, 310
DVDAdm method, 333
EndScene method, 120, 131, 161
DVDDirectory method, 333
EndStateBlock method, 120
finding
EnterBitmapGrabMode method, 311 entries, palettes, 92-93 Enum object, 253 EnumAdapterModes method, 117 enumerating
events
files
creating, 240
adding to setup packages, 392
DirectPlay, 346, 362
assigning, 74
DirectPlay8Event class, 367-368
AVI, playing with filters, 291
DirectPlay8LobbyEvent, 347
joystick devices, 221-222
DirectPlayVoiceEvent8 class, 379
sound drivers, 277
Form MouseMove, modifying
enumeration (DirectInput devices), 179 EnumFilters method, 307-308 EnumHosts method, 350, 367-369 EnumHostsQuery method, 368 EnumHostsResponse method, 368 EnumMediaTypes method, 310 environments billboard applications, initializing, 165-168
code, 162-163 Form_MouseMove, 241 implementing, 240 lobby (DirectPlay), 358-359 notifications, user input from mouse, 239-240 evolution of Visual Basic, 12 Exceptions window, debugging code, 404
error handling, Try...Catch...End Try structure, 403-404 Error Lookup, 31-32
MIDI, 248 qedit.dll, 298 quartz.dll type library, 316 sound, saving, 283 surfaces, creating, 74-75 WAV (wave), 248 X, 150 FilgraphManager object, methods, 316 filter graph object, 291 Filter method, 319, 323 filter object, 290-291
execution loops, animations, 27-29
FilterCollection method, 316
extensions of files, .bmp, 74
filters
FilterInfo method, 322
AVI files, playing, 291
F faces supporting meshes, 108 3D objects, 107 features, new DirectGraphics, 55
error trapping, 29-30, 403-404
Exceptions window, 404
ErrorLog method, 304
stepping by line, statement, or instruction, 404
errors (Error Lookup), 31-32
dxsetup.dll, 386
exclusive input devices, 180
setups for Direct3D applications, 130-134, 138-139, 143-144, 148-151 2D graphics, initializing, 157-159
.bmp extension, 74
feedback, force (joysticks), 190-191, 227-228 Filename method, 311, 319
color or gamma controls (images), 72, 82-83 IFilterInfo, 292 IRegFilterInfo, 293 pins, 291 FindFilterByName method, 307-308 finding game hosts (DirectPlay), 347, 350 matching devices, 199 service providers (DirectPlay), 347-350
425
426
FindMediaFile method
FindMediaFile method, 312
Form_MouseMove event, 241
FXEcho object, 253
fInitNow (DirectMusic DMUS AUDIOPARAMS member), 264
forwarding server connections (DirectPlay Voice), 382
fxFormat method, 275
Fishing genre type, 196
frames, animations, 40-43
FixMediaTimes2 method, 302
FramesPerSecond method, 333
FindPin method, 319
FixTimes2 method, 301 flags, 223-224, 276, 386-388 Flip method, 58, 78-79 flipping pages, animations, 48-49, 72 surfaces, 77-78 Floppy Disk button, 394 flowcharts, code (Shooting Gallery), 68 Folder button, 394 Football Defense genre type, 196 Football Offense genre type, 196 Football Play genre type, 196 Football Quarterback genre type, 196
FrameRate method, 311
FreePrivateData method, 124-125, 128 fRejectMsg, setting values, 348-350 frequency, sound buffers, 279 full-duplex sound cards (DirectPlace Voice), 376
formats data (joysticks), defining, 222 DirectX DLLS, converting to, 400 media (DirectShow), 293-295
G game hosts (DirectPlay) finding, 350 peer-to-peer clients, 347 game programming, 15 games. See also DirectPlay Snowman, 16 video, 8
functions
gas pedals, 179
CreateMatrices, 141 D3DVertexBuffer8SetData, 136 DirectXSetup, 386-388
InitializeVertices, 159-161
Form MouseMove event, code to modify, 162-163
FXWavesReverb object, 254
gamma controls (images), 72, 82-83
force feedback
Force Feedback Editor, 33-34
FXParamEq object, 254
FullScreenMode method, 323, 333
GetTickCount, 26
joysticks, 227-228
FXGargle object, 253
FreeEventParams method, 320
For...Next loop, wrapping methods, 347-349
DirectInput, 190-191
FXFlanger object, 253
GetVector, 140
VB6( ), backwardcompatibility, 36 vectors or vertices for billboard applications, code, 171-173 FX13DL2Reverb object, 253 FXChorus object, 253 FXCompression object, 253 FXDistortion object, 253
genres (action maps), 195-199 GetActualDataLength method, 309 GetAdapterCount method, 117 GetAdapterDisplayMode method, 117, 130 GetAdapterIdentifier method, 117 GetAdapterModeCount method, 117 GetAdapterMonitor method, 117 GetAllParameters method, 284-286 GetApplicationDesc method, 367, 370-371
GetDeviceStateJoystick2 method
GetAudioLanguage method, 333
GetComponentString method, 366
GetCurrentTexturePalette method, 120
GetAudioPathConfig method, 263
GetCompressionType method, 378-380
GetCutPoint2 method, 304
GetAvailableTextureMem method, 120
GetCompressionTypeCount method, 378-380
GetBackBuffer method, 120, 126
GetConeAngles method, 284
GetBumperLength method, 260 GetButtonAtPosition method, 333
GetConeOrientation method, 284 GetConeOutsideVolume method, 284
GetCutsOnly method, 304 GetDefaultAudioPath method, 260 GetDefaultEffectB method, 299 GetDefaultFPS method, 299, 302 GetDefaultTransitionB method, 299
GetButtonRect method, 333
GetConnectionInfo method, 367, 370-372
GetCapabilities method, 184, 222
GetConnectionSettings method, 358
GetCaps method, 58, 60, 272-273, 367, 370-372, 378-380
GetContainer method, 125, 128
GetDesc method, 124-128
GetCount method, 190, 221
GetChordmap method, 260, 263
GetDesignatorIndex method, 186
GetCountClientsAndGroups method, 370
GetClassID method, 308
GetCountGroupMembers method, 370-372
GetClientAddress method, 372 GetClientConfig method, 378 GetClientInfo method, 372 GetClipList method, 62 GetClipper method, 58 GetClipPlane method, 120 GetClipStatus method, 120 GetClipVideoRect method, 333
GetCountLocalPrograms method, 357 GetCountOfType method, 299-300 GetCountPlayersAndGroups method, 372 GetCountServiceProviders method, 347-349, 367, 370-372
GetClockTime method, 260
GetCreationParameters method, 120
GetCollectionNumber method, 186
GetCubeMapSurface method, 118
GetColorKey method, 58
GetCurrentImage method, 318
GetCommand method, 260 GetComponentLong method, 366
GetCurrentPosition method, 273
GetDelayTime method, 333 GetDepthStencilSurface method, 120
GetDestinationPosition method, 318 GetDevice method, 124-125, 128, 366 GetDeviceCaps method, 117, 120 GetDeviceData method, 184, 203, 208, 226, 241 GetDeviceInfo method, 184 GetDeviceObjectsEnum method, 184 GetDevicesBySemantics method, 182 GetDeviceState method, 184, 208 GetDeviceStateJoystick method, 184 GetDeviceStateJoystick2 method, 184
427
428
GetDeviceStateKeyboard method
GetDeviceStateKeyboard method, 184
GetDynamicParams method, 190
GetGuidFFDriver method, 187
GetDeviceStateMouse method, 184, 244
GetEffect method, 305
GetGuidInstance method, 187, 221
GetDeviceStateMouse2 method, 184, 244 GetDeviceStatus method, 182 GetDevType method, 187 GetDIDevices method, 182, 221 GetDimension method, 186 GetDirect3D method, 120 GetDirectDraw method, 58 GetDirectDrawColorControl method, 83 GetDirectDrawGammaContro l method, 59, 83 GetDirectSound3Dbuffer method, 273 GetDirectSoundBuffer method, 284-286 GetDisplayMode method, 56, 121 GetDistanceFactor method, 286
GetEffectGuid method, 189-190 GetEffectsEnum method, 184
GetGuidType method, 186
GetEffectStatus method, 189
GetHResult method, 319
GetEntries method, 61
GetHWnd method, 62
GetEnumHostResponseAddre ss method, 370
GetImageInfo method, 184
GetEvent method, 320
GetIndices method, 121
GetEventHandle method, 320
GetInfo method, 121
GetFilterGraph method, 312 GetFlags method, 186 GetForceFeedbackState method, 184 GetFormat method, 274 GetFrequency method, 274 GetFrontBuffer method, 121 GetGammaRamp method, 121
GetKaraokeChannelContent method, 334 GetLangFromLangID method, 334 GetLatencyTime method, 260 GetLength method, 263
GetLevelDesc method, 118, 126-128
GetGrooveLevel method, 260
GetGroupCompressor method, 311
GetDVDTextLanguageLCID method, 333
GetGroupCount method, 299
GetDVDTextStringType method, 334
GetKaraokeChannelAssignm ent method, 334
GetLevelCount method, 118
GetDuration2 method, 299
GetDVDTextString method, 333
GetInstanceName method, 187
GetGPRM method, 334
GetGroup method, 299
GetDVDTextNumberOfString s method, 333
GetIndex method, 317
GetGenID method, 301
GetDopplerFactor method, 286
GetDVDTextNumberOfLangu ages method, 333
GetGuidProduct method, 187
GetGroupInfo method, 370-372
GetLight method, 121 GetLightEnable method, 121 GetLocalProgram method, 357 GetLocked method, 301 GetLOD method, 118
GetGroupMember method, 370-372
GetLoopPointEnd method, 263
GetGroupName method, 300
GetLoopPointStart method, 263
GetGroupOutputPin method, 312
GetMasterAutoDownload method, 261
GetSourcesCount method
GetMasterGrooveLevel method, 261
GetObjectInPath method, 274
GetProductName method, 187
GetMasterTempo method, 261
GetOrientation method, 286
GetProperty method, 184, 224
GetMasterVolume method, 261
GetOutputBuffering method, 300
GetQueueTime method, 261
GetOutputFPS method, 300
GetRasterStatus method, 121
GetPaletteEntries method, 121
GetRecursiveLayerOfType method, 300
GetMaxIdealImageSize method, 323
GetPan method, 274
GetRenderState method, 121
GetParameters method, 189
GetMediaLength2 method, 302
GetParentalCountry method, 331
GetRenderTarget method, 121
GetMediaName method, 302
GetParentalLevel method, 331
GetResolvedTime method, 261
GetMediaTimes2 method, 302
GetPeerAddress method, 370 GetPeerInfo method, 370
GetRestorePosition method, 323
GetMediaType method, 309
GetPixelShader method, 121
GetRolloffFactor method, 286
GetMinDistance method, 284
GetPixelShaderConstant method, 121
GetSegmentState method, 261
GetPixelShaderFunction method, 121
GetSendQueueInfo method, 367, 370-372
GetPlayerOrGroup method, 370-372
GetServerAddress method, 367
GetPlayerParentalCountry method, 334
GetServerInfo method, 367
GetMaterial method, 121 GetMaxDistance method, 284
GetMediaTime method, 309
GetMinIdealImageSize method, 323 GetMode method, 285 GetMusicTime method, 261 GetMuted method, 301 GetName method, 190, 263 GetNextSrc2 method, 303
GetRepeats method, 263
GetServiceProvider method, 347-349, 367, 370-372
GetNextSrcEx method, 303
GetPlayerParentalLevel method, 334
GetNextTrans2 method, 305
GetPointer method, 309
GetSessionDesc method, 378-380
GetNextVTrack method, 300
GetPosition method, 285-286
GetSize method, 309
GetNotificationPMSG method, 261
GetPreferredAspectRatio method, 319
GetSizeMax method, 309
GetNotifyFlags method, 320
GetPrepareTime method, 261
GetSoundDeviceConfig method, 378
GetNumberOfChapters method, 334
GetPreviewMode method, 300
GetSoundDevices method, 378
GetNumComponents method, 366
GetPriority method, 124, 300
GetSourcePosition method, 318
GetObjectInfo method, 184
GetPrivateData method, 124-125, 128
GetSourcesCount method, 303
429
430
GetSP method
GetSP method, 366 GetSPCaps method, 367, 370-372 GetSpeakerConfig method, 272 GetSPRM method, 334 GetSrcAtTime2 method, 303 GetStartPoint method, 263 GetStartStop2 method, 301 GetState method, 308, 316 GetStaticParams, 190
GetTimelineObject method, 312
GetVideoPaletteEntries method, 318
GetTimelineType method, 301
GetVideoSize method, 318, 334
GetTimeSig method, 261
GetViewport method, 122
GetTitleParentalLevels method, 334
GetVolume method, 274
GetTransAtTime2 method, 305
GetVTrack method, 300
GetTransform method, 121-123
GetVolumeLevel method, 128
GetWindowPosition method, 323 Glassner, Andrew S., 104
GetStatus method, 274
GetTransmitTargets method, 378-380
GetStreamNumber method, 302
GetType method, 125, 186, 190
Golf genre type, 197
GetStreamSource method, 121
GetURL method, 366
Graphic Gems I, 104
GetUsage method, 186-187
GetStretchMode method, 302
GetUserData method, 301, 366
graphics. See also DirectDraw; 2D graphics; 3D graphics
GetStyle method, 261-263
gloves (virtual reality), 180
GraphEdit tool, 34
GetSubObjectGUIDB method, 301
GetUserID method, 301
cards, display modes, 64
GetUserName method, 302
DirectGraphics, 55
GetSubObjectLoaded method, 301
GetValueByIndex method, 317
overlay surfaces (screens), 72, 83-85
GetSubpictureLanguage method, 334
GetValueByName method, 317
page flipping, 72
GetSurfaceLevel method, 127
GetVector function, 140
Shooting Gallery, code flowchart (sample), 68
GetSwapInputs method, 304
GetVelocity method, 285-286
tablets, 180
GetSyncSource method, 308
GetVendorString method, 312
Windows display mode and full-screen display mode, comparing, 64
GetTempo method, 261 GetTexture method, 121 GetTextureStageState method, 121 GetTickCount function, 26 method, 164 GetTime method, 309-311 GetTimeline method, 301
GetVertexShader method, 121 GetVertexShaderConstant method, 122 GetVertexShaderDeclaration method, 122 GetVertexShaderFunction method, 122
groove levels, DirectMusic Performance object, 260 group players (DirectPlay), 341 GUID client/server connections, assigning, 349 DirectPlay, 343-344
images
history of DirectX, 8-12
flags GetProperty method, 224 SetProperty method, 223-224 Generation Program (A), 343-344 peer-to-peer clients, assigning, 346 guid3Dalgorithm method, 275 GUID_SysKeyboard, 206, 220 GUID_SysMouse (CreateDevice method), 238
H HAL (Hardware Abstraction Layer) and HEL (Hardware Emulation Layer), comparing, 62-63 &H80 and lData member (DIDEVICEOBJECTDATA variable) comparing, 243 Hand-To-Hand genre type, 196 handling errors, Try…Catch…End Try structure, 403-404 Height method, 323, 331 HEL (Hardware Emulation Layer) and HAL (Hardware Abstraction Layer), comparing, 62-63 Helicopter Combat genre type, 196 Help, Kill Help, 35 HideCursor method, 323 HIDs (Human Interface Devices), 185
Hockey Defense genre type, 197
IAMSetErrorLog class, methods, 304 IAMStats class, methods, 317
Hockey Goalie genre type, 197
IAMTimelineEffectable class, methods, 304
Hockey Offense genre type, 197
IAMTimelineSplittable class, methods, 305
holding
IAMTimelineTransable class, methods, 305
DirectPlayVoiceClient8 class, code to create varibables, 378 DirectPlayVoiceEvent8 class, code to create varibables, 379 DirectPlayVoiceServer8 class, code to create varibables, 380 home pages, VS Home Page, 402 Host method, 370-372 host migration, 342 HostMigrate method, 368
IAMTimelineVirtualTrack class, methods, 306 IBasicAudio, 292, 317 IBasicVideo, 292, 317-318 IBasicVideo2 class, methods, 319 IDeferredCommand class, methods, 319 IEnumFilters class, methods, 306 IEnumMediaTypes class, methods, 306
HostMigrated method, 380
IEnumPins class, methods, 306
hosts
IErrorLog class, methods, 306
addresses, data types, 364 finding in DirectPlay games, 350 players (DirectPlay), 341-342 Human Interface Devices (HIDs), 185 Hunting genre type, 197
IFilterGraph class, methods, 307 IFilterInfo, 319 292 IGraphBuilder class, methods, 307-308 images alpha-blending, 81 bitmaps, textures (3D objects), 109
I IAM Collection, 292, 316 IAMErrorLog class, methods, 304
color or gamma controls, 72, 82-83 mirroring, 81 rectangles, blitting, 72
431
432
images
stretching, 81
DirectXSetup functions, 386-387
intermediate data for mouse, 244
Z-buffering, 81
environments
Invalidate method, 261
sprites, 44
IMediaControl, 293 IMediaEvent, 293, 320 IMediaEventEx object, methods, 320 IMediaFilter class, methods, 308 IMediaPosition, 293, 321
for billboard applications, 165-168
InvokeAtPresentationTime method, 322
for 2D graphics, 157-159
InvokeAtStreamTime method, 322
objects for Direct3D applications, 129-134, 138, 143, 147-149 peer-to-peer clients (DirectPlay), 346-347
IMediaSample class, methods, 309
inner cones (DirectSound), 254
IMediaTypeInfo, 293 321
input devices (DirectInput), 17
immediate data, 185 Implements keyword, 240 Included Files window, 392 index buffers, 123 IndicateConnect method, 348-350, 368 IndicateConnectAborted method, 369 InfoNotify method, 369 InitAudio method, 261, 267 Initialize method, 378, 381 InitializeEnvironment method, breeze application, code to initialize, 157-159 InitializeVertices function, background vertices, code to initialize, 159-161 initializing background vertices, code, 159-161 breeze application, code, 157-159 client/server clients (DirectPlay), 349 DirectMusic performances, 267
IPersistStream class, methods, 309 IPin class, methods, 310 IPinInfo, 293, 321-322 IQueueCommand class, methods, 322 IReferenceClock class, methods, 310
input. See DirectInput; user input
IRegFilterInfo, 293, 322
InputLevel method, 380
IsAudioStreamEnabled method, 334
InsertSpace2 method, 303 Install Shield packaging program, 395 installing DirectX, 20 instances DirectPlay8Client object, creating, 349 DirectPlay8Peer object, creating, 346 Instrument object, 250 interactions, user DirectX, 14 DirectInput, 178-180 interfaces APIs (Application Programming Interfaces), WinG, 10 HIDs (Human Interface Devices), 185
IsClipListChanged method, 62 IsCursorHidden method, 323 IsDirty method, 309 IsDiscontinuity method, 309 IsFileSource method, 320 IsLost method, 59 ISmartRenderEngine class, methods, 311 IsNormalRate method, 302 IsPlaying method, 261 IsPreroll method, 309 IsSubpictureStreamEnabled method, 334 IsSyncPoint method, 309 IsUsingDefaultDestination method, 318 IsUsingDefaultSource method, 318
libraries
K
Item method, 317
L
IVideoWindow, 293, 323-324
J joysticks, 179
KaroaokeAudioPresentation Mode method, 334
latency times (DirectMusic Performance object), 260
Keyboard program, code, 215-217
layerOutputLevel method, 380
keyboards, 179
layers, comparing HAL (Hardware Abstraction Layer) and HEL (Hardware Emulation Layer), 62-63
capabilities, 222
accessing, 207
cooperative levels, setting, 222
CONST DIKEYFLAGS constant values, 209-214
CreateDevice method, 220 data analyzing, 226-227 formats, defining, 222 dead zones, 224-225
constants, 209-214
lBufferBytes method, 275
CreateDevice method, 206
lData member (DIDEVICE OBJECTDATA variable) and &H80, comparing, 243
data
Leader object, 250
cooperative levels, 207
analyzing, 214-215
Left method, 323
enumerating, 221-222
format parameter, setting, 207
properties, setting, 223-224
interpreting, 208
left-handed Cartesian coordinate system (3D graphics), 104-105
devices
DirectInput, 191 force feedback, 227-228 GetProperty method, 224 objects creating, 220-222 relationships among DirectX, DirectInput and DirectInputDevice, 220 program example, code, 228-236 SetProperty method, 223-224 user input, retrieving, 220-227 Jukebox application, code, 324-330 Jump Start demo (WinToon), 11
retrieving, 207-214 DirectInput, 191, 206 DirectInputDevice object, 206 DirectX object, 206 DirectXEvent class, 214 GetDeviceData method, 208 GetDeviceState method, 208 GUID_SysKeyboard, 206 looping, 214-215 objects, creating, 206 parameters, setting, 206-207 property sheets, 202 user input, retrieving, 206-215 keyframes, animations, 42 keywords, Implements, 240 Kill Help, 35
level of detail (LOD), 117 levels of cooperation, DirectInput user interactions, 180 lFeatures (DirectMusic DMUS AUDIOPARAMS member), 264 lFlags method, 275 libraries ActiveMovie type library, creating references, 295 Dexter 1.0 type library, 298 DirectAudio, 17-18 DirectX, 20-22, 400-401 DirectXSetup, 386-39 quartz.dll, 316 type, output to assembly converter, 401 Visual Basic Type Library, 401-403
433
434
LightEnable method
LightEnable method, 122
architecture, 354
lights, 109-110, 142-146
client object, 354
execution, animations, 27-29
Listener (3D) object (DirectSound3D), 285-286
clients, 356-357
For...Next, wrapping methods, 347-349
listener orientation (DirectSound 3D), 256 listings. See code Load method, 310 LoadBand method, 258
DirectPlay8LobbiedApplicatio n class, methods, 358 DirectPlay8LobbyClient class, methods, 357 DirectPlay8LobbyEvent class, implementing methods, 358
LoadBandFromResource method, 258
DirectPlay8LobbyEvent class, methods, 359
LoadChordMap method, 258
DirectPlayLobby classes, relationships, 354
LoadChordMapFromResource method, 258
events, 358-359
LoadCollection method, 258
lobbyable game application, 354
LoadCollectionFromResource method, 258
players, 356
Loader object (DirectMusic), 267
server object, 354
loading
users attaching to, 355
servers, 355-356
loops
lSampleRate (DirectMusic DMUS AUDIOPARAMS member), 265 lSequence member (DIDEVICEOBJECTSEQUENCE variable), 244 lValidData (DirectMusic DMUS AUDIOPARAMS member), 265 lVoices (DirectMusic DMUS AUDIOPARAMS member), 265
M MadOnion Web site, 3D Mark, 43
meshes for Direct3D applications, 150-151
Lock method, 124, 127 LockBox method, 128
magnitude property, joystick force feedback, 228
sound buffers, 278
locking
managing
textures for Direct3D applications, 148 LoadPaletteFromBitmap method, 57 LoadSegment method, 258 LoadSegmentFromResource method, 259 LoadStyle method, 259 LoadStyleFromResource method, 259 lobby (Direct Play), 343 application object, 354 applications, 357-358
buffers, 127 rectangles, 125-126 LockRect method, 118, 125-127 LOD (level of detail), 117 lOfs member (DIDEVICE OBJECTDATA variable), 242-243 LogError method, 304 looping, analyzing joystick data, 226-227 keyboard data, 214-215
DirectPlay games, 362-371 sessions, 348-350 DirectInput user interactions, 178 mapping, action (DirectInput), 190 maps, chordmaps (DirectMusic), 250, 259. See also action maps marble textures, 109 matching devices (action maps), finding, 199 materials, 3D objects, 109 matrices, 111-112, 137-142
methods
Mechanical Fighting genre type, 196 media. See also ActiveMovie DLL formats (DirectShow), 293-295 Microsoft Web DVD control, 316 DVDRect class, methods, 330
MessageDrain method, 323
AMTimelineEffect class, 300
Messages (DirectPlay)
AMTimelineGroup class, 300-301
peer-to-peer clients, sending, 348 players, 342 sending, 351 system, 343 methods Abort, 307
MSDVDAdm class, methods, 331
AcceptParentalLevelChange, 332
MSWebDVD class, methods, 332-336
Acquire, 183, 225, 241
MediaDet class, methods, 311 MediaLocator class, methods, 312
AcquireResources, 273 ActivateAtPosition, 332 ActivateButton, 332 AddAttachedSurface, 58
MediaTypes method, 322
AddComponentLong, 365
members. See also parameters
AddComponentString, 365 AddDirtyBox, 128
buffer descriptors, 275
AddDirtyRect, 118, 126
DIDEVICEOBJECTDATA variable, 242-243
AddError, 307
DIDEVICEOBJECTSEQUENCE variable, 244
AddFoundLocation, 312
DSBUFFERDESC type (buffer descriptors), 275
AddFilter, 307
AddGroup, 298 AddNotificationType, 260
memory, surfaces, 72-82
AddPlayerToGroup, 369-371
menus, Package and Deployment Wizard choices, 389
AddRemovePlayerGroup, 368
Mesh Viewer tool, 35 meshes Direct3D applications, 149-153 3D objects, 107-108 message queues (DirectPlay games), 362
AddSourceFilter, 308, 316 AddValue, 317 AdjustTime, 260 AdvisePeriodic, 311 AdviseTime, 311 AMTimeLine class, 298-299 AMTimelineComp class, 299
AMTimelineObj class, 301-302 AMTimelineSrc class, 302-303 AMTimelineTrack class, 303 AMTimelineTrans class, 303 AnglesAvailable, 332 AppDesc, 368 ApplyStateBlock, 119 AreYouBlank, 303 AspectRatio, 332 AsyncOpComplete, 368 AudioStreamsAvailable, 332 AutoShow, 323 AvgTimePerFrame, 318 BackColor, 332 BackgroundPalette, 323 Balance, 317, 332 BeginFlush, 310 BeginScene, 119, 131, 161 BeginStateBlock, 119 BitErrorRate, 318 BitRate, 318 Blt, 58, 79-80 BltColorFill, 58, 80-81 BltFast, 58, 81 BltFx, 58, 81-82 BltToDC, 82 BookmarkOnClose, 331 BookmarkOnStop, 331 BorderColor, 323
435
436
methods
BuildActionmap, 183
ConnectComplete, 350, 368
BuildFromURL, 365
ConnectDirect, 307-308, 322
Cancel, 319
ConnectedTo, 310, 322
CancelAsyncOperation, 366, 369-371
ConnectFrontEnd, 312
CreatePrimarySoundBuffer, 272-274 CreateRenderTarget, 119 CreateSegment, 265 CreateSoundBuffer, 272-274
CancelDefaultHandling, 320
ConnectionMediaType, 310, 322
CanSeekBackward, 321
ConnectionSettings, 359
CanSeekForward, 321
ConnectResult, 379
CanStep, 332
ConnectToCollection, 263
Caption, 323
ConnectWithType, 322
CreateStandardAudioPath, 260
Capture, 332
CopyRects, 119
CreateStateBlock, 119
CaptureStateBlock, 119
Count, 317
CreateSurface, 56, 73, 84-85
CCActive, 332
Create3DSoundBuffer, 378
ChangePassword, 331
CreateSurfaceFromFile, 56, 74-75
CheckDepthStencilMatch, 116
CreateAdditionalSwapChain, 119, 126
CheckDeviceFormat, 116
CreateAudioPath, 260
CreateTextureFromFile, 148
CheckDeviceMultiSampleType, 116
CreateCaptureBuffer, 280
CreateVertexBuffer, 119, 135
CreateClipper, 56
CreateVertexShader, 119
CheckDeviceType, 116
CreateCubeTexture, 119
CreateVoicePlayer, 379
Clear, 119, 131, 366
CreateCustomEffect, 183
CreateVolumeTexture, 119
ClearAllGroups, 298
CreateDepthStencilSurface, 119
CurrentAngle, 332
Clone, 263, 306
CreateDevice, 117, 130, 165, 206, 220, 238
CurrentButton, 332
Close, 351, 357-358, 366, 369-371
CreateEffect, 183
CloseDown, 260
CreateEffectFromFile, 183
ColorKey, 332
CreateEmptyNode, 299
CommitDeferredSettings, 286
CreateGroup, 368-371
Confidence, 319
CreateImageSurface, 119
ConfigureDevices, 182, 202-203
CreateIndexBuffer, 119
ConfirmPassword, 331
CreatePalette, 56
Connect, 308-310, 322, 347-350, 359
CreatePixelShader, 119
ClockToMusicTime, 260
ConnectApplication, 357
CreateNewGuid, 343
CreatePlayer, 368
CreateSoundBufferFromFile, 272, 278 CreateSoundBufferFromResou rce, 272
CreateTexture, 119
CurrentAudioStream, 332
CurrentCCService, 332 CurrentChapter, 332 CurrentDiscSide, 332 CurrentDomain, 332 CurrentPosition, 321 CurrentStream, 311 CurrentSubpictureStream, 332 CurrentTime, 332 CurrentTitle, 332 CurrentVolume, 333 CursorType, 333
methods
DefaultAudioLanguage, 333
DirectInput class, 182
DefaultAudioLanguageExt, 333
DirectInputDevice class, 183-185
DefaultAudioLCID, 331
DirectInputDevice8.Acquire, 207
DefaultMenuLanguage, 333 DefaultMenuLCID, 331 DefaultSubpictureLanguage, 333 DefaultSubpictureLanguageExt, 333 DefaultSubpictureLCID, 331 Delete3DSoundBuffer, 378 DeleteBookmark, 333 DeletePatch, 120 DeletePixelShader, 120 DeleteStateBlock, 120 DeleteVertexShader, 120 DeleteVoicePlayer, 379 DestinationHeight, 318 DestinationLeft, 318 DestinationTop, 318 DestinationWidth, 318 DestroyClient, 371 DestroyGroup, 368-371 DestroyPeer, 369 DestroyPlayer, 348, 368 DirectDraw, 56-57 DirectDraw7.CreateSurfaceFro mFile, 74 DirectDrawClipper class, 62 DirectDrawPalette class, 60-61 DirectDrawSurface class, 58-59 DirectDrawSurface.Flip, 77-78 DirectDrawSurface7.SetPalette , 97
DirectInputDevice8.GetDevic eStateJoystick, 226 DirectInputDevice8.GetDevic eStateKeyboard, 208
DirectPlay8LobbyClient class, 357 DirectPlay8LobbyEvent class, 358-359 DirectPlay8Peer class, 369-371 DirectPlay8Server class, 371-372 DirectPlayPeerCreate, 346
DirectInputDevice8.SetProper ty, 239
DirectPlayVoiceClient8 class, 378-379
DirectInputDeviceInstance class, 187
DirectPlayVoiceEvent8 class, 379-380
DirectInputDeviceObjectInsta nce class, 186
DirectPlayVoiceServer8 class, 380-381
DirectInputEffect class, 188-189
DirectSound3DBuffer8, 284-285
DirectInputEnumEffects class, 190
DirectSound3DListener8, 286
Direction, 322 DirectMusicBand8, 265 DirectMusicLoader8 object, 258-259 DirectMusicPerformance8, 260-262 DirectMusicPerformance8.Init Audio, 264 DirectMusicSegment8, 263-264 DirectPlayClientCreate, 349 DirectPlay8Address, 365-366 DirectPlay8Client, 366-367 DirectPlay8Client.Connect, 350
DirectSound8 object, 272 DirectSoundSecondaryBuffer8 object, 273-274 Direct3D8 class, 116-117 Direct3DBaseTexture8 class, 118 Direct3DCreate, 130 Direct3DCubeTexture8 class, 118 Direct3DDevice8 class, 119-123 Direct3DIndexBuffer8 class, 124 Direct3DResource8 class, 124-125 Direct3DSurface8 class, 125
DirectPlay8Event class, 368-369
Direct3DSwapChain8 class, 126
DirectPlay8LobbiedApplicatio n class, 358
Direct3DTexture8 class, 126 Direct3DVertexBuffer8 class, 127
437
438
methods
Direct3DVolume8 class, 128
EnableResetOnStop, 333
Direct3DVolumeTexture8 class, 128
EnableTransitions, 299
DisableAutoMouseProcessing, 333 DisableScreenSaver, 331 Disconnect, 307-310, 322, 359, 378
EndFlush, 310 EndOfStream, 310 EndScene, 120, 131, 161 EndStateBlock, 120 EnterBitmapGrabMode, 311
GetAdapterDisplayMode, 117, 130 GetAdapterIdentifier, 117 GetAdapterModeCount, 117 GetAdapterMonitor, 117 GetAllParameters, 284-286 GetApplicationDesc, 367, 370-371
DisconnectResult, 379
EnumAdapterModes, 117
DoEvents, 37
EnumFilters, 307-308
Download, 188, 263-265, 268
EnumHosts, 350, 367-369
DrawIndexedPrimitive, 120
EnumHostsQuery, 368
DrawIndexedPrimitiveUP, 120
EnumHostsResponse, 368
DrawPrimitive, 120, 136, 141
EnumMediaTypes, 310
DrawPrimitiveUP, 120, 161
ErrorLog, 304
DrawRectPatch, 120
Filename, 311, 319
DrawSubset, 152
FilgraphManager object, 316
DrawText, 58
Filter, 319, 323
GetCaps, 58-60, 272-273, 367, 370-372, 378-380
DrawTriPatch, 120
FilterCollection, 316
GetChordmap, 260, 263
DSBUFFERDESC type (buffer descriptors), 275
FilterInfo, 322
GetClassID, 308
FindFilterByName, 307-308
GetClientAddress, 372
Duplicate, 366
FindMediaFile, 312
GetClientConfig, 378
DuplicateSoundBuffer, 272
FindPin, 319
GetClientInfo, 372
Duration, 321
FixMediaTimes2, 302
GetClipList, 62
DVDAdm, 333
FixTimes2, 301
GetClipper, 58
DVDDirectory, 333
Flip, 58, 78-79
GetClipPlane, 120
DVDRect class, 330
FrameRate, 311
GetClipStatus, 120
DVDTimeCode2bstr, 333
FramesPerSecond, 333
GetClipVideoRect, 333
DVDUniqueID, 333
FreeEventParams, 320
GetClockTime, 260
EffectGetCount, 305
FreePrivateData, 124-125, 128
GetCollectionNumber, 186
EffectGetPriority, 300
FullScreenMode, 323, 333
GetColorKey, 58
EffectInsBefore, 305
fxFormat, 275
GetCommand, 260
EffectsEnabled, 299
GetActualDataLength, 309
GetComponentLong, 366
EffectSwapPriorities, 305
GetAdapterCount, 117
GetComponentString, 366
EnableEffects, 299
GetAudioLanguage, 333 GetAudioPathConfig, 263 GetAvailableTextureMem, 120 GetBackBuffer, 120, 126 GetBumperLength, 260 GetButtonAtPosition, 333 GetButtonRect, 333 GetCapabilities, 184, 222
methods
GetCompressionType, 378-380
GetDesc, 124-128
GetCompressionTypeCount, 378-380
GetDestinationPosition, 318
GetConeAngles, 284
GetDesignatorIndex, 186
GetDevice, 124-125, 128, 366
GetDVDTextLanguageLCID, 333 GetDVDTextNumberOfLangu ages, 333
GetDeviceCaps, 117, 120
GetDVDTextNumberOfString s, 333
GetConeOutsideVolume, 284
GetDeviceData, 184, 203, 208, 226, 241
GetDVDTextString, 333
GetConnectionInfo, 367, 370-372
GetDeviceInfo, 184
GetConeOrientation, 284
GetConnectionSettings, 358 GetContainer, 125, 128 GetCount, 190, 221 GetCountClientsAndGroups, 370 GetCountGroupMembers, 370-372 GetCountLocalPrograms, 357
GetDeviceObjectsEnum, 184 GetDevicesBySemantics, 182 GetDeviceState, 184, 208 GetDeviceStateJoystick, 184 GetDeviceStateJoystick2, 184 GetDeviceStateKeyboard, 184 GetDeviceStateMouse, 184, 244
GetDVDTextStringType, 334 GetDynamicParams, 190 GetEffect, 305 GetEffectGuid, 189-190 GetEffectsEnum, 184 GetEffectStatus, 189 GetEntries, 61 GetEnumHostResponseAddress, 370 GetEvent, 320
GetDeviceStateMouse2, 184, 244
GetEventHandle, 320
GetDeviceStatus, 182
GetFilterGraph, 312
GetCountServiceProviders, 347-349, 367, 370-372
GetDevType, 187
GetFlags, 186
GetDIDevices, 182, 221
GetForceFeedbackState, 184
GetCreationParameters, 120
GetDimension, 186
GetFormat, 274
GetCubeMapSurface, 118
GetDirect3D, 120
GetFrequency, 274
GetCurrentImage, 318
GetDirectDraw, 58
GetFrontBuffer, 121
GetCurrentPosition, 273
GetDirectDrawColorControl, 83
GetGammaRamp, 121
GetDirectDrawGammaControl, 59, 83
GetGPRM, 334
GetCountOfType, 299-300 GetCountPlayersAndGroups, 372
GetCurrentTexturePalette, 120 GetCutPoint2, 304 GetCutsOnly, 304 GetDefaultAudioPath, 260
GetDirectSound3DBuffer, 273
GetDefaultEffectB, 299
GetDirectSoundBuffer, 284-286
GetDefaultFPS, 299, 302
GetDisplayMode, 56, 121
GetDefaultTransitionB, 299
GetDistanceFactor, 286
GetDelayTime, 333
GetDopplerFactor, 286
GetDepthStencilSurface, 120
GetDuration2, 299
GetGenID, 301
GetGrooveLevel, 260 GetGroup, 299 GetGroupCompressor, 311 GetGroupCount, 299 GetGroupInfo, 370-372 GetGroupMember, 370-372 GetGroupName, 300 GetGroupOutputPin, 312
439
440
methods
GetGuidFFDriver, 187
GetMediaLength2, 302
GetPixelShaderFunction, 121
GetGuidInstance, 187, 221
GetMediaName, 302
GetPlayerOrGroup, 370-372
GetGuidProduct, 187
GetMediaTime, 309
GetGuidType, 186
GetMediaTimes2, 302
GetPlayerParentalCountry, 334
GetHResult, 319
GetMediaType, 309
GetHWnd, 62
GetMinDistance, 284
GetImageInfo, 184
GetMinIdealImageSize, 323
GetIndex, 317
GetMode, 285
GetIndices, 121
GetMusicTime, 261
GetInfo, 121
GetMuted, 301
GetInstanceName, 187
GetName, 186, 190, 263
GetKaraokeChannelAssignment, 334
GetNextSrc2, 303
GetKaraokeChannelContent, 334 GetLangFromLangID, 334 GetLatencyTime, 260 GetLength, 263 GetLevelCount, 118 GetLevelDesc, 118, 126-128 GetLight, 121 GetLightEnable, 121 GetLocalProgram, 357 GetLocked, 301 GetLOD, 118 GetLoopPointEnd, 263 GetLoopPointStart, 263 GetMasterAutoDownload, 261 GetMasterGrooveLevel, 261 GetMasterTempo, 261 GetMasterVolume, 261 GetMaterial, 121 GetMaxDistance, 284 GetMaxIdealImageSize, 323
GetNextSrcEx, 303 GetNextTrans2, 305 GetNextVTrack, 300 GetNotificationPMSG, 261 GetNotifyFlags, 320 GetNumberOfChapters, 334 GetNumComponents, 366 GetObjectInfo, 184 GetObjectInPath, 274 GetOrientation, 286 GetOutputBuffering, 300 GetOutputFPS, 300 GetPaletteEntries, 121
GetPlayerParentalLevel, 334 GetPointer, 309 GetPosition, 285-286 GetPreferredAspectRatio, 319 GetPrepareTime, 261 GetPreviewMode, 300 GetPriority, 124, 300 GetPrivateData, 124-125, 128 GetProductName, 187 GetProperty, 184, 224 GetQueueTime, 261 GetRasterStatus, 121 GetRecursiveLayerOfType, 300 GetRenderState, 121 GetRenderTarget, 121 GetRepeats, 263 GetResolvedTime, 261 GetRestorePosition, 323 GetRolloffFactor, 286 GetSegmentState, 261
GetPan, 274
GetSendQueueInfo, 367, 370-372
GetParameters, 189
GetServerAddress, 367
GetParentalCountry, 331
GetServerInfo, 367
GetParentalLevel, 331 GetPeerAddress, 370
GetServiceProvider, 347-349, 367, 370-372
GetPeerInfo, 370
GetSessionDesc, 378-380
GetPixelShader, 121
GetSize, 309
GetPixelShaderConstant, 121
GetSizeMax, 309 GetSoundDeviceConfig, 378
methods
GetSoundDevices, 378
GetTransAtTime2, 305
IAMErrorLog class, 304
GetSourcePosition, 318
GetTransform, 121
IAMSetErrorLog class, 304
GetSourcesCount, 303
GetTransmitTargets, 378-380
IAMStats class, 317
GetSP, 366
GetType, 125, 186, 190
GetSPCaps, 367, 370-372
GetURL, 366
IAMTimelineEffectable class, 304
GetSpeakerConfig, 272
GetUsage, 186-187
GetSPRM, 334
GetUserData, 301, 366
GetSrcAtTime2, 303
GetUserID, 301
GetStartPoint, 263
GetUserName, 302
GetStartStop2, 301
GetValueByIndex, 317
IAMTimelineVirtualTrack class, 306
GetState, 308, 316
GetValueByName, 317
IBasicAudio class, 317
GetStaticParams, 190
GetVelocity, 285-286
IBasicVideo class, 317-318
GetStatus, 274
GetVendorString, 312
IBasicVideo2 class, 319
GetStreamNumber, 302
GetVertexShader, 121
IDeferredCommand class, 319
GetStreamSource, 121
GetVertexShaderConstant, 122
IEnumFilters class, 306
GetVertexShaderDeclaration, 122
IEnumPins class, 306
GetSubObjectLoaded, 301
GetVertexShaderFunction, 122
IFilterGraph class, 307
GetSubpictureLanguage, 334
GetVideoPaletteEntries, 318
IFilterInfo object, 319
GetSurfaceLevel, 127
GetVideoSize, 318, 334
IGraphBuilder class, 307-308
GetSwapInputs, 304
GetViewport, 122
IMediaEvent object, 320
GetSyncSource, 308
GetVolume, 274
IMediaEventEx object, 320
GetTempo, 261
GetVolumeLevel, 128
IMediaFilter class, 308
GetTexture, 121
GetVTrack, 300
IMediaPosition object, 321
GetTextureStageState, 121
GetWindowPosition, 323
IMediaSample class, 309
GetTickCount, 164
guid3DAlgorithm, 275
IMediaTypeInfo object, 321
GetTime, 309-311
Height, 323, 331
IndicateConnect, 348-350, 368
GetTimeline, 301
HideCursor, 323
IndicateConnectAborted, 369
GetTimelineObject, 312
Host, 370-372
InfoNotify, 369
GetTimelineType, 301
HostMigrate, 368
InitAudio, 261, 267
GetTimeSig, 261
HostMigrated, 380
Initialize, 378, 381
GetTitleParentalLevels, 334
IAMCollection class, 316
InitializeEnvironment, 157-159
GetStretchMode, 302 GetStyle, 261-263 GetSubObjectGUIDB, 301
IAMTimelineSplittable class, 305 IAMTimelineTransable class, 305
IEnumMediaTypes class, 306
IErrorLog class, 306
441
442
methods
InputLevel, 380
Left, 323
NotifyOwnerMessage, 323
InsertSpace2, 303
lFlags, 275
Invalidate, 261
LightEnable, 122
NotifyParentalLevelChange, 334
InvokeAtPresentationTime, 322
Load, 310
InvokeAtStreamTime, 322 IPersistStream class, 309 IPin class, 310
LoadBand, 258 LoadBandFromResource, 258 LoadChordMap, 258
OutputLevel, 380 OutputStreams, 312 Owner, 323 Pause, 308, 316, 334 Pin, 322
IPinInfo object, 321-322
LoadChordMapFromResource , 258
IQueueCommand class, 322
LoadCollection, 258
Pins, 320
IReferenceClock class, 310
Play, 274, 278, 334
IRegFilterInfo object, 322
LoadCollectionFromResource , 258
IsAudioStreamEnabled, 334
LoadPaletteFromBitmap, 57
PlayAtTimeInTitle, 334
IsClipListChanged, 62
LoadSegment, 258
PlayBackwards, 334
IsCursorHidden, 323
LoadSegmentFromResource, 259
PlayChapter, 334
IsDirty, 309
PinID, 322
PlayAtTime, 334
PlayChapterInTitle, 334 LoadStyle, 259
IsDiscontinuity, 309
PlayChaptersAutoStop, 335 LoadStyleFromResource, 259
IsFileSource, 320
PlayerOutputLevel, 380 Lock, 124, 127
IsLost, 59
PlayerVoiceStart, 380 LockBox, 128
ISmartRenderEngine class, 311
LockRect, 118, 125-127
IsNormalRate, 302
LogError, 304
IsPlaying, 261
MediaDet class, 311
IsPreroll, 309
MediaLocator class, 312
PlayPeriodInTitleAutoStop, 335
IsSubpictureStreamEnabled, 334
MediaTypes, 322
PlayPrevChapter, 335
MessageDrain, 323
PlaySegmentEx, 261, 268
IsSyncPoint, 309
ModifyStopTime2, 303
PlayState, 335
IsUsingDefaultDestination, 318
MSDVDAdm class, 331
PlayTitle, 335
MSWebDVD class, 332-336
Poll, 184
MultiplyTransform, 122
Postpone, 319
MusicToClockTime, 261 Name, 320-323
PreferredSubpictureStream, 335
NewSegment, 310
PreLoad, 125
Next, 306
PrerollTime, 321
IsUsingDefaultSource, 318 Item, 317 IVideoWindow class, 323-324 KaroaokeAudioPresentationM ode, 334 lBufferBytes, 275
PlayerVoiceStop, 380 PlayForwards, 335 PlayNextChapter, 335
methods
Present, 122, 126, 131, 161
RenderOutputPins, 312
SendCurvePMSG, 262
ProcessVertices, 122
ReplayChapter, 335
SendDeviceData, 184
QueryAccept, 310
Reset, 122, 261, 306, 317
QueryDirection, 310
ResourceManagerDiscardBytes, 122
SendForceFeedbackCommand, 184
QueryId, 310 QueryInternalConnections, 310
SendMIDIPMSG, 262
Restore, 59, 274
SendNotePMSG, 262
RestoreAllSurfaces, 57
SendPatchPMSG, 262
QueryPinInfo, 310
RestoreBookmark, 335
SendTempoPMSG, 262
Rate, 321
RestoreDefaultHandling, 320
SendTimeSigPMSG, 262
ReadBuffer, 274, 282
RestoreScreenSaver, 331
SendTo, 348, 351, 370-372
ReadXMLFile, 313
Resume, 335
SendTransposePMSG, 262
ReadyState, 335
ReturnFromSubmenu, 335
SessionLost, 380
Receive, 348, 351, 359, 369
Run, 308, 316
SessionStatus, 359
ReceiveConnection, 310
RunControlPanel, 182-184
SetActionMap, 184, 201
Reconnect, 307-308
Save, 310
SetActualDataLength, 309
RecordStart, 380
SaveBookmark, 335
SetAllParameters, 285-286
RecordStop, 380
SaveParentalCountry, 331
SetAppAvailable, 358
RegFilterCollection, 316
SaveParentalLevel, 331
SetApplicationDesc, 370-372
RegionChange, 335
SaveToFile, 274, 282-283
SetAutoDownloadEnable, 263
RegisterLobby, 367, 370-372
ScrapIt, 312
SetBumperLength, 262
RegisterMessageHandler, 347-349, 357-358, 367, 370372
SelectAndActivateButton, 335
SetCaps, 367, 371-372
SelectAtPosition, 335
SetClientConfig, 378
SelectDefaultAudioLanguage, 335
SetClientInfo, 350, 367
RegisterProgram, 358 RegisterSoftwareDevice, 117 ReleaseApplication, 357
SelectDefaultSubpictureLangu age, 335
Remove, 302
SelectLeftButton, 335
RemoveAll, 302
SelectLowerButton, 335
RemoveFilter, 307-308
SelectParentalCountry, 335
RemoveNotificationType, 261
SelectParentalLevel, 335
RemovePlayerFromGroup, 370-372
SelectRightButton, 335
Render, 308, 322, 335
Send, 357-358, 367
RenderEngine class, 312-313
SendComplete, 369
RenderFile, 308, 316
SelectUpperButton, 335
SetClipList, 62 SetClipper, 59 SetClipPlane, 122 SetClipStatus, 122 SetClipVideoRect, 335 SetColorKey, 59 SetCommonDataFormat, 184, 207, 222 SetConeAngles, 285 SetConeOrientation, 285 SetConeOutsideVolume, 285
443
444
methods
SetConnectionSettings, 357-358
SetGammaRamp, 122
SetOutputBuffering, 301
SetGPRM, 336
SetOutputFPS, 301
SetGroupCompressor, 311
SetPalette, 59
SetGroupInfo, 371-372
SetPaletteEntries, 123
SetGroupName, 301
SetPan, 274
SetHWnd, 62
SetParameters, 188
SetIndices, 123
SetPeerInfo, 347, 371
SetLength, 263
SetPixelShader, 123
SetLight, 123
SetPixelShaderConstant, 123
SetLocked, 302
SetPosition, 285-286
SetLOD, 118
SetPrepareTime, 262
SetLogFile, 308
SetPreroll, 309
SetLoopPoints, 263
SetPreviewMode, 301
SetDefaultEffectB, 299
SetMasterAutoDownload, 262
SetPriority, 125
SetDefaultFPS, 299, 303
SetMasterGrooveLevel, 262
SetPrivateData, 125, 128
SetDefaultSourcePosition, 318
SetMasterTempo, 262, 266
SetDefaultSyncSource, 307-308
SetMasterVolume, 262, 266
SetProperty, 185, 223-224, 239
SetDefaultTransitionB, 299
SetMaxDistance, 285
SetDelayTime, 336
SetMediaLength2, 303
SetRenderState, 123, 139, 144, 148, 151
SetDestinationPosition, 318
SetMediaName, 303
SetRenderTarget, 123
SetDevice, 366
SetMediaTime, 309
SetRepeats, 263
SetDiscontinuity, 309
SetMediaTimes2, 303
SetRolloffFactor, 286
SetDisplayModel, 57
SetMediaType, 309
SetSearchDirectory, 259
SetDistanceFactor, 286
SetMediaTypeForVB, 301
SetServerInfo, 372
SetDopplerFactor, 286
SetMinDistance, 285
SetSessionDesc, 381
SetDynamicReconnectLevel, 313
SetMode, 285 SetMuted, 302
SetSourceNameValidation, 313
SetNotificationHandle, 262
SetSourcePosition, 318
SetNotificationPositions, 274
SetSP, 366
SetNotifyFlags, 320
SetSPCaps, 367, 371-372
SetNotifyWindow, 320
SetSpeakerConfig, 272
SetOrientation, 286
SetStandardMidiFile, 264
SetCooperativeLevel, 185, 207, 272 SetCurrentPosition, 274 SetCurrentSoundDevices, 378 SetCurrentTexturePalette, 122 SetCursorPosition, 122 SetCursorProperties, 122 SetCutPoint2, 304 SetCutsOnly, 304 SetDefaultAudioPath, 262 SetDefaultDestinationPosition, 318
SetEntries, 61 SetEqual, 366 SetFilterGraph, 313 SetFont, 59 SetFrequency, 274 SetFX, 274
SetMaterial, 123, 152
SetRecompFormatFromSource, 301
SetStartPoint, 264
methods
SetStartStop2, 302
SmartRenderEngine class, 313
TransGetCount, 305
SetStreamNumber, 303
SourceHeight, 318
TransitionEnabled, 299
SetStreamSource, 123, 136, 141
SourceLeft, 318
Type, 321
SourceTop, 318
Unacquire, 185, 241
SetStretchMode, 303
SourceWidth, 318
Unadvise, 311
SetSubObjectGUIDB, 302
SpliceWithNext, 303
Unload, 189, 264
SetSwapInputs, 304
SplitAt2, 305
Unlock, 124, 127
SetSyncPoint, 309
SrcAdd, 303
UnlockBox, 128
SetSyncSource, 308
Start, 188, 281
UnlockRect, 118, 125-127
SetTempoEnable, 264
StartClientNotification, 379
SetTexture, 123, 148, 152, 161
StartServerNotification, 381
SetTextureStageState, 123, 148
UnRegisterMessageHandler, 357-358, 367, 371-372, 379-381
StartSession, 381
SetTextureStateState, 148 SetTime, 309 SetTimelineObject, 313 SetTimeSigEnable, 264 SetTransform, 123 SetTransmitTargets, 378, 381 SetUserData, 302, 366 SetUserID, 302 SetUserName, 302
Step, 336 StillOff, 336 Stop, 188, 274, 308, 316, 336 StopEx, 262, 268 StopTime, 321 StopWhenReady, 316 StreamLength, 312 StreamTypeB, 312 SubpictureOn, 336
UnRegisterProgram, 358 UOPValid, 336 UpdateStatus, 358 UpdateTexture, 123 Upload, 265 ValidateDevice, 123 ValidSourceNames, 299 VendorInfo, 320 VideoHeight, 318 VideoWidth, 318
SetVelocity, 285-286
SubpictureStreamsAvailable, 336
Visible, 324
SetVertexShader, 123, 136, 141
Subtype, 321
Volume, 317, 336
TerminateSession, 348, 351, 369-371
VolumesAvailable, 336
SetVertexShaderConstant, 123 SetViewport, 123
TestCooperativeLevel, 123
VTrackInsBefore, 300
SetVolume, 274
TitlesAvailable, 336
VTrackSwapPriorities, 300
SetWindowForeground, 323
ToolTip, 336
WaitForCompletion, 320
SetWindowPosition, 323
ToolTipMaxWidth, 336
Width, 324, 331
ShouldOperationContinue, 308
Top, 324
WindowlessActivation, 336
TotalTitleTime, 336
WindowState, 324
TrackGetProperty, 306
WindowStyle, 324
TransAdd, 305
WindowStyleEx, 324
ShowCursor, 123, 336 ShowMenu, 336 Skip, 306
VTrackGetCount, 300
445
446
methods
Wrapping, For...Next loop, 347-349 WriteBitmapBits, 312 WriteBuffer, 274, 282 WriteGrfFile, 313 WriteXML, 313 WriteXMLFile, 313 x, 331 Xml2Dex class, 313 y, 331 ZeroBetween2, 303 Zoom, 336 Microsoft Web DVD control
modes DirectDraw displays, 63-64 display (Direct3D), 130 operation (DirectSound 3D), 255 ModifyStopTime2 method, 303 Mountain Biking genre type, 197 mouse Acquire method, 241
MSDVDAdm class, methods, 331 MSWebDVD class, methods, 332-336 multimedia, 15. See also ActiveMovie DLL applications, 8 players, Microsoft Web DVD control, 316 DVDRect class, methods, 330
axes, 238
MSDVDAdm class, methods, 331
button, axis constants, 242-243
MSWebDVD class, methods, 332-336
DVDRect class, methods, 330
data, intermediate, 244
MSDVDAdm class, methods, 331
DIPROPLONG data type, 239
animations, 25-31
DirectInput, 191, 238-244
classes, 22-23
DirectInputDevice, 238
COM (Component Object Model), 23
MSWebDVD class, methods, 332-336 MIDI files, 248
DirectInputDevice8.SetProper ty method, 239
programming
DirectX object, 238
compiling speed, increasing, 35-36
mirroring images, 81
Form_MouseMove event, 241
Direct3D, 24
Missing Dependency Information message box, 391
GetDeviceStateMouse method, 244
DirectDraw, 24
GetDeviceStateMouse2 method, 244
DirectMusic, 24
GUID_SysMouse (CreateDevice method), 238
DirectSound, 25
migrations, host (DirectPlay), 342
mixing server sessions (DirectPlay Voice), 382 models COM (Component Object Model), 23
Implements keyword, 240
communication (DirectPlay), 344-345
SetProperty method, 239
DirectX object model, architectural overview, 17 sheets, animations, 40 space, 105
intermediate data, 244
Unacquire method, 241 user input, retrieving, 238-240 X axis, 238 Y axis, 238 Z axis, 238
DirectInput, 24
DirectPlay, 25
DirectX, 20-25, 400 DirectX 8 SDK utilities, 31-35 DirectX 8 type library, creating references, 21, 400-401
objects
error trapping, 403-404
performances, initializing, 267
Exceptions window, 404
performances, modifying, 265-266
objects, 22-23 stepping by line, statement, or instruction, 404 multiplayer games. See DirectPlay
Producer, 268-269 Segment object, 268
MusicToClockTime method, 261
MultiplyTransform method, 122
mustard bottles (meshes), 108
music (DirectMusic), 13-14, 17
Mute, 334
DirectMusic Performance object, 259-262 DirectMusic Segment object, 263-264 Loader object, 267 Performance object, 268 performances, 265-267
N networks (DirectPlay)
billboard applications, 163-164
connections, 341 Billboards, animations, 47-48 client/server sessions, 350 peer-to-peer client sessions, 347-348
blitting, animations, 48 new features
button, 180
Exceptions window, 404
Capture, 252, 280
stepping by line, statement, or instruction, 404
CaptureBuffer, 253
variables, declaring, 267
Next method, 306
Loader object, 267 Performance object, 268
breeze application, code to declare, 156-157
DirectGraphics, 55
NewSegment method, 310
DirectMusic Segment object, 263-264
blits (bit block transfers), 43-44
providers, 342-343
Segment object, 268
DirectMusic Performance object, 259-262
back buffering, animations, 48-49 Band, 249-250
New Project dialog box, 401
DirectMusic Loader object, 258-259
objects
Name method, 320-323
Producer, 268-269
DirectMusic Band object, 265
O
axes, 180
composing
DirectMusic Loader object, 258-259
NotifyParentalLevelChange method, 334
AudioPath, 249
audio parameter structures, 264-265
DirectMusic Band object, 265
NotifyOwnerMessage method, 323
variables, declaring, 267
Multiple Cabs button, 392
audio parameter structures, 264-265
notifications of events, user input from mouse, 239-240
nonexclusive input devices, 180 NOTHING setting (capture buffers), 281
clipping, animations, 46-47 color control, code to create, 83 COM (Component Object Model), 23 Composer, 250 creating, 206, 238 destroying, 36, 132 Device, 179-180 devices (action maps), assigning actions, 198-199 DirectDraw, declaring, 56
447
448
objects
DirectDrawClipper, declaring, 61
DirectSound3DBuffer8, declaring, 284
filter, 290-291
DirectDrawPalette, declaring, 60
DirectSound3DListener8, declaring, 285
frame rates, animations, 43
DirectDrawSurface, declaring, 57
Direct3D
DirectInput, 179-180, 206 cooperative levels, supporting, 207 mouse, 238
filter graph, 291
FX13DL2Reverb, 253 FXChorus, 253 creating, 130 FXCompression, 253 declaring, 24 FXDistortion, 253 Direct3D8 class methods, 116-117
FXEcho, 253
Direct3DBaseTexture8 class, 117-118
FXFlanger, 253
DirectInputDevice, 206, 238 DirectInputDevice8, code to declare, 208
Direct3DCubeTexture8 class methods, 118
FXParamEq, 254
DirectMusic Band, 265 DirectMusic Loader, 258-259
Direct3DDevice8 class methods, 119-123
DirectMusic Performance, 259-262
Direct3DIndexBuffer8 class, 123-124
DirectMusic Segment, 263-264
Direct3DResource8 class methods, 124-125
DirectMusicLoader8, methods, 258-259
Direct3DSwapChain8 class methods, 126
DirectPlay, 346
Direct3DTexture8 class methods, 126
DirectPlay Lobbies, 346 DirectPlay Voice, 346 DirectPlay8Client, 346, 349 DirectPlay8Event, 346 DirectPlay8LobbyEvent, 346 DirectPlay8Peer, 346 DirectPlay8VoiceEvent, 346 DirectShow, 290-291 DirectSound, sound effects, 253-254
Direct3DVertexBuffer8 class methods, 127
gamma control, code to create, 83 IfilterInfo, methods, 319 IMediaEvent, methods, 320 IMediaEventEx, methods, 320 IMediaPosition, methods, 321 IMediaTypeInfo, methods, 321 initializing for Direct3D applications, 129-134, 138, 143, 147-149 IPinInfo, methods, 321-322
Direct3DVolumeTexture8 class methods, 128
Joysticks, creating, 220-222
volumes, 127-128 Direct3D COM, declaring, 24 DirectX, 23-25, 206, 238 drawing surfaces, 45 DSCBUFFERDESC, 280
DirectSoundCaptureBuffer8, 280
Enum, 253
DirectSoundSecondaryBuffer8 , 273-274
FXWavesReverb, 254
Direct3DVolume8 class methods, 128
DirectSoundCapture8, 280
DirectSound8, methods, 272
FXGargle, 253
FilgraphManager, methods, 316
IRegFilterInfo, methods, 322
Leader, 250 Loader (DirectMusic), 267 lobby, 354 models (DirectX), architectural overview, 17 page flipping, animations, 48-49 palettes, animations, 45, 49 Performance, 250, 268
PlayAtTimeInTitle method
P
pin, 291 PrimaryBuffer, 254 rectangles, animations, 46 relationships among DirectX, DirectInput, and DirectInputDevice, 220 SecondaryBuffer, 254 Segment, 250, 268 sound effects, 253-254 sprites, animations, 44
Package and Deployment Wizard, creating setup packages, 389-393 Package to Deploy window, 394 packages, setups, 389-395 page flipping (animations), 48-49, 72
Style, 250, 254
Palette Animation program, code, 100-101
2D graphics, declaring, 156-157
PALETTEENTRY data type, code, 92-93
3D, 105-108
palettes
3D Listener, DirectSound3D, 285-286
animations, 45, 92, 95-101
3DBuffer, 252
colors, 92
3DListener, 252
cycling, animations, 49
WAVEFORMATEX, 280
DirectDrawSurface7. SetPalette method, 97
offscreen drawing surfaces, 45
cars, changing colors, 95
entries, 92-93
parameters. See also members audio parameter structures (DirectMusic), 264-265 cooperative level, setting, 207 D3DPRESENT_PARAMETERS, 130 data format, setting, 207 Direct3D, ByVal declaration, 132 of keyboards, setting, 206-207 Pause method, 308, 316, 334 peer-to-peer clients (DirectPlay), 346-348 communication model (DirectPlay), 344 connections (DirectPlay Voice), 381 peers DirectPlay games, 362 DirectPlay8Peer class, 369 Performance object, 250 268
OpenGL, 11
manipulating, code, 96-97
operation mode (DirectSound 3D), 255
methods, DirectDrawPalette. SetEntries, 96
orientation (listener), DirectSound 3D, 256
modifying, 96-97
periodic effect, joystick force feedback, 228
PALETTEENTRY data type, code, 92-93
Pin method, 322
outer cones (DirectSound), 254 output from type library to assembly converter, 401 Output window, animations, 30 OutputLevel method, 380 OutputStreams method, 312 overlay surfaces (screens), 72, 83-85 Owner method, 323
sharing, 93-95 surfaces, 94, 98-100 switching, 97 types, 92 panning, sound buffers, 279
performances (DirectMusic), 265-267
pin object, 291 PinID method, 322 pins, 291-293 Pins method, 320 Platform genre type, 196 Play method, 274, 278, 334 PlayAtTime method, 334 PlayAtTimeInTitle method, 334
449
450
playback
playback, asynchronous audio, 248
polygons (3D objects), 106-109
Project menu commands, References, 295
PlayBackwards method, 334
positions (DirectSound 3D), 255
projection matrix, 112
PlayChapter method, 334 PlayChapterInTitle method, 334 PlayChaptersAutoStop method, 335 players, multimedia (Microsoft Web DVD control), 316. See also ActiveMovie DLL; DirectPlay DVDRect class, methods, 330 MSDVDAdm class, methods, 331 MSWebDVD class, methods, 332-336
Postpone method, 319 PreferredSubpictureStream method, 335 PreLoad method, 125
properties (joystick) direction, duration, and magnitude (force feedback), 228 devices, setting, 223-224 property sheets
PrerollTime method, 321
calling, 203
Present method, 122, 126, 131, 161
keyboard, 202
Presentations (DirectShow), 18 primary buffers (DirectSound), 254 primary drawing surfaces, 45
SideWinder game pad, 202-203 providers (DirectPlay) network, 342-343 service, 340
primary sound buffers, 273
finding, 349-350
PlayerVoiceStart method, 380
PrimaryBuffer object, 254
peer-to-peer clients, 347
PlayerVoiceStop method, 380
priorities (action maps), 197
PlayForwards method, 335
private data, 126
playing
ProcessVertices method, 122
AVI files with filters, 291 sound buffers, 278-279 playing games. See DirectPlay PlayNextChapter method, 335 PlayPeriodInTitleAutoStop method, 335 PlayPrevChapter method, 335 PlaySegmentEx method, 261, 268 PlayState method, 335 PlayTitle method, 335 Poll method, 184
Q
Producer (DirectMusic), 268-269
qedit.dll file, 298
products, showcasing, 13
QueryAccept method, 310
programming games, 15. See also DirectX 8; multimedia programming
QueryDirection method, 310
programs
quartz.dll type library, 316
QueryId method, 310 QueryInternalConnections method, 310
Install Shield packaging, setup packages, 395
QueryPinInfo method, 310
joysticks, code, 228-236
questions (trivia), user interactions, 14
Keyboard, code, 215-217 Palette Animation, code, 100-101 Shooting Gallery, 85-88 Wise packaging, setup packages, 395
queues, messages (DirectPlay games), 362
routines
R
referencing DirectXSetup functions, 386-387
Racing genre type, 196
reflective balls, 110
Racquet genre type, 197
RegFilterCollection method, 316
ramp force effect, joystick force feedback, 228 Rate method, 321 rates, frame (animations), 43 ReadBuffer method, 274, 282 ReadXMLFile method, 313 ReadyState method, 335
RegionChange method, 335 RegisterLobby method, 367, 370-372 RegisterMessageHandler method, 347-349, 357-358, 367, 370-372
Direct3D applications, 131-132, 136-137, 141-142, 145-153 RenderOutputPins method, 312 ReplayChapter method, 335 Reset method, 122, 261, 306, 317 ResourceManagerDiscardByte s method, 122 Restore method, 59, 274
RegisterProgram method, 358
RestoreAllSurfaces method, 57
RegisterSoftwareDevice method, 117
RestoreBookmark method, 335
ReleaseApplication method, 357
RestoreDefaultHandling method, 320
RecordStart method, 380
Remote Control genre type, 196
RestoreScreenSaver method, 331
RecordStop method, 380
Remove method, 302
Resume method, 335
RECT type, definition, 46
RemoveAll method, 302
retrieving
rectangles
RemoveFilter method, 307-308
Receive method, 348, 351, 359, 369 ReceiveConnection method, 310 Reconnect method, 307-308 recording sound, 280-283
animations, 46 clipper, 47 creating, 126
RemoveNotificationType method, 261
dirty, 118
RemovePlayerFromGroup method, 370-372
images, blitting, 72
removing elements, 36
locking or unlocking, 125-126
Render
reducing access times, 36 References command (Project menu), 295 dialog box, 22, 295-296 references, creating ActiveMovie type library, 295 DirectX 8 type library, 21, 400-401
method, 308, 322, 335 subroutine, 145, 148 RenderEngine class, methods, 312-313
joystick data, 226 keyboard data, 207-214 user input joysticks, 220-227 keyboards, 206-215 ReturnFromSubmenu method, 335 right-handed Cartesian coordinate system (3D graphics), 104 Role-Playing genre type, 197
RenderFile method, 308, 316
roll off factors (DirectSound 3D), 256
rendering scenes
routines
fbillboard applications, code, 168-171
BLIT, surfaces, 79-82 CreateLights subroutine, 144-146
451
452
routines
CreateMatrices subroutine, 139-141 Render subroutine, 145, 148 subroutines, removing unused, 36
Windows display mode and full-screen display mode, comparing, 64 screensavers, 15
Run method, 308, 316
SDK (Software Developer’s Kit), 11, 31-35
RunControlPanel method, 182-184
secondary buffers (DirectSound), 254 secondary drawing surfaces, 45
S
secondary sound buffers, 273-274
Save method, 310
SecondaryBuffer object, 254
SaveBookmark method, 335
Segment object, 250, 268
SaveParentalCountry method, 331
SelectAndActivateButton method, 335
SaveParentalLevel method, 331
SelectAtPosition method, 335
SaveToFile method, 274, 282-283
SelectDefaultAudioLanguage method, 335
saving sound files, 283
SelectDefaultSubpictureLang uage method, 335
scaling matrix, 111 scenes billboard applications, code to render, 168-171 Direct3D applications, rendering, 131-132, 136-137, 141-149, 152-153 ScrapIt method, 312 screens clipper rectangles, 47 clipping, animations, 46-47
SelectLeftButton method, 335 SelectLowerButton method, 335 SelectParentalCountry method, 335 SelectParentalLevel method, 335 SelectRightButton method, 335
drawing, code, 161-162
SelectUpperButton method, 335
overlay surfaces, 72, 83-85
Send method, 357-358, 367
rectangles, animations, 46
SendComplete method, 369
2D graphics, drawing, 161-162
SendCurvePMSG method, 262
SendDeviceData method, 184 SendForceFeedbackComman d method, 184 sending messages (DirectPlay), 348, 351 SendMIDIPMSG method, 262 SendNotePMSG method, 262 SendPatchPMSG method, 262 SendTempoPMSG method, 262 SendTimeSigPMSG method, 262 SendTo method, 348, 351, 370-372 SendTransposePMSG method, 262 servers DirectPlay client/servers, 344-345, 349-351 games, 362 lobby, 355-356 DirectPlay Voice, 382 DirectPlay8Server class, 371 DirectPlayVoiceServer8 class, 380 service providers (DirectPlay), 340 finding, 349-350 peer-to-peer clients, 347 SessionLost method, 380
SetMasterTempo method
sessions DirectPlay, 341 closing, 351 connecting to, 350 managing, 350 peer-to-peer clients, connecting to, 347-348 DirectPlay Voice mixing server, 382 voice, 376 SessionStatus method, 359 Set , 36 SetActionMap method, 184, 201 SetActualDataLength method, 309 SetAllParameters method, 285-286 SetAppAvailable method, 358 SetApplicationDesc method, 370-372
SetCommonDataFormat method, 184, 207, 222 SetConeAngles method, 285 SetConeOrientation method, 285 SetConeOutsideVolume method, 285 SetConnectionSettings method, 357-358 SetCooperativeLevel method, 185, 207, 272 SetCurrentPosition method, 274
SetDevice method, 366 SetDiscontinuity method, 309 SetDisplayModel method, 57 SetDistanceFactor method, 286 SetDopplerFactor method, 286 SetDynamicReconnectLevel method, 313 SetEntries method, 61 SetEqual method, 366 SetFilterGraph method, 313
SetCurrentSoundDevices method, 378
SetFont method, 59
SetCurrentTexturePalette method, 122
SetFX method, 274
SetCursorPosition method, 122 SetCursorProperties method, 122 SetCutPoint2 method, 304 SetCutsOnly method, 304
SetFrequency method, 274
SetGammaRamp method, 122 SetGPRM method, 336 SetGroupCompressor method, 311 SetGroupInfo method, 371-372
SetAutoDownloadEnable method, 263
SetDefaultAudioPath method, 262
SetBumperLength method, 262
SetDefaultDestinationPositio n method, 318
SetCaps method, 367, 371-372
SetDefaultEffectB method, 299
SetClientConfig method, 378
SetDefaultFPS method, 299, 303
SetLocked method, 302
SetDefaultSourcePosition method, 318
SetLogFile method, 308
SetClientInfo method, 350, 367 SetClipList method, 62 SetClipper method, 59 SetClipPlane method, 122
SetDefaultSyncSource method, 307-308
SetClipStatus method, 122
SetDefaultTransitionB method, 299
SetClipVideoRect method, 335
SetDelayTime method, 336
SetColorKey method, 59
SetDestinationPosition method, 318
SetGroupName method, 301 SetHWnd method, 62 SetIndices method, 123 SetLength method, 263 SetLight method, 123
SetLOD method, 118
SetLoopPoints method, 263 SetMasterAutoDownload method, 262 SetMasterGrooveLevel method, 262 SetMasterTempo method, 262, 266
453
454
SetMasterVolume method
SetMasterVolume method, 262, 266 SetMaterial method, 123, 152 SetMaxDistance method, 285 SetMediaLength2 method, 303 SetMediaName method, 303
SetPosition method, 285-286 SetPrepareTime method, 262 SetPreroll method, 309 SetPreviewMode method, 301 SetPriority method, 125
SetStreamSource method, 123, 136, 141 SetStretchMode method, 303 SetSubObjectGUIDB method, 302 SetSwapInputs method, 304 SetSyncPoint method, 309
SetMediaTime method, 309
SetPrivateData method, 125, 128
SetMediaTimes2 method, 303
SetProperty method, 185, 223-224, 239
SetTempoEnable method, 264
SetMediaType method, 309
SetRecompFormatFromSourc e method, 301
SetTexture method, 123, 148, 152, 161
SetRenderState method, 123, 139, 144, 148, 151
SetTextureStageState method, 123, 148
SetRenderTarget method, 123
SetTextureStateState method, 148
SetRepeats method, 263
SetTime method, 309
SetRolloffFactor method, 286
SetTimelineObject method, 313
SetMediaTypeForVB method, 301 SetMinDistance method, 285 SetMode method, 285 SetMuted method, 302 SetNotificationHandle method, 262
SetSyncSource method, 308
SetNotificationPositions method, 274
SetSearchDirectory method, 259
SetNotifyFlags method, 320
SetServerInfo method, 372
SetNotifyWindow method, 320
SetSessionDesc method, 381
SetTransmitTargets method, 378, 381
SetSourceNameValidation method, 313
setup packages
SetOrientation method, 286
SetSourcePosition method, 318
creating, 389-393
SetOutputBuffering method, 301 SetOutputFPS method, 301
SetSP method, 366
files, adding, 392
SetPalette method, 59
SetSPCaps method, 367, 371-372
Install Shield packaging program, 395
SetSpeakerConfig method, 272
Wise packaging program, 395
SetPaletteEntries method, 123 SetPan method, 274
SetTimeSigEnable method, 264
deploying, 394-395
SetUserData method, 302, 366
SetParameters method, 188
SetStandardMidiFile method, 264
SetPeerInfo method, 347, 371
SetStartPoint method, 264
SetUserName method, 302
SetPixelShader method, 123
SetStartStop2 method, 302
SetVelocity method, 285-286
SetPixelShaderConstant method, 123
SetStreamNumber method, 303
SetVertexShader method, 123, 136, 141
SetUserID method, 302
strips
Skip method, 306
SpliceWithNext method, 303
SmartRenderEngine class, methods, 313
SplitAt2 method, 305
SetViewport method, 123 SetVolume method, 274
Snowman game, 16
SetWindowForeground method, 323
Soccer Defense genre type, 197
SetWindowPosition method, 323
Soccer Offense genre type, 197
Shared Files window, 393
Software Developer’s Kit (SDK), 11, 31-35
SetVertexShaderConstant method, 123
sharing palettes, 93-95 sheets, model (animations), 40 Shooting Gallery (DirectDraw) DirectDrawSurface command, 85
sound, 13-14. See also DirectMusic; DirectPlay Voice; DirectSound buffers, 277-280 cards, full-duplex (DirectPlace Voice), 376
sprites, 44 SrcAdd method, 303 standard DirectDraw display modes, 64 Start Menu Items window, 392 Start method, 188, 281 StartClientNotification method, 379 StartServerNotification method, 381 StartSession method, 381 steering wheels, 179, 191
cooperative levels, 27
Step Into debugging tool, 30
Shooting genre type, 196
DirectShow, 290
Step method, 336
ShouldOperationContinue method, 308
drivers, enumerating, 277
Step Over debugging tool, 30
showcasing products, 13
files, saving, 283
stepping by line, statement, or instruction, 404
ShowCursor method, 123, 336
IBasicAudio, 292
sticky focus (buffers), 276
playback, asynchronous, 248
StillOff method, 336
recording, 280-283
code, 65-68, 86-88
ShowMenu method, 336
effects, objects, 253-254
Side-to-side genre type, 196
SourceHeight method, 318
Stop method, 188, 274, 308, 316, 336
SideWinder game pad, property sheets, 202-203
SourceLeft method, 318
StopEx method, 262, 268
SourceTop method, 318
StopSession method, 381
SourceWidth method, 318
StopTime method, 321
Silicon Graphics, Inc. (OpenGL), 11
Space Combat genre type, 196
StopWhenReady method, 316
simple and complex curves, comparing, 106
spaces
storyboards (animations), 41-42
signatures, time (DirectMusic Performance object), 260
Single Cab button, 392 sizes of buffers, setting for user input from mouse, 239 Skiing genre type, 197
coordinate system (3D graphics), 104-105 3D world, 105 speed of compiling, increasing, 35-37
StreamLength method, 312 StreamTypeB method, 312 stretching images, 81 strips, sprite, 44
455
456
structures
structures audio parameters (DirectMusic), 264-265
DirectDrawSurface.Flip method, 77-78
TestCooperativeLevel method, 123
Flip method, code, 78
tests, DirectPlayVoiceTest8 class, 381
D3DDISPLAYMODE, 130
flipping, 77-78
D3DPRESENT_ PARAMETERS, 130
gamma control objects, code to create, 83
Try...Catch...End Try, error handling, 403-404
overlays (screens), 72, 83-85
Style object, 250
Direct3D applications, 146-149
Shooting Gallery, 85-88
LOD (level of detail), 117
swap chains, 126
SubpictureStreamsAvailable method, 336
synchronizing data, 15-16
CreateLights, 144-146 CreateMatrices, 139-141 Render, 145, 148 unused, removing, 36 Subtype method, 321 surfaces
textures
palettes, 93-99
SubpictureOn method, 336
subroutines
Texture tool, 32-33
syntax. See also code
3D objects, 109 Third-Person Action genre type, 196
DirectDraw class, 56
time signatures (DirectMusic Performance object), 260
DirectDrawClipper class, 61
timers, animations, 25-26
DirectDrawPalette class, 60
TitlesAvailable method, 336
DirectDrawSurface class, 57
tools
Set , 36 system messages (DirectPlay), 343
debugging, 30 DMO Test tool, 32-33
BLIT routine, 79-82
GraphEdit tool, 34
blitting to, 79
Mesh Viewer tool, 35
color control objects, code to create, 83
T tables, matrices, 111-112
Texture tool, 32-33 ToolTip method, 336
tablets, graphic, 180
ToolTipMaxWidth method, 336
Tank genre type, 196
Top method, 324 TotalTitleTime method, 336
creating, 72-75, 94
targets, transmission (DirectPlay Voice), 376
DDSURFACEDESC2 declaration, 75-77
technologies, DirectInput, 190-191
descriptions, 75-77
templates, Windows application, 402
CreateSurface method, code, 73 CreateSurfaceFromFile method, code, 74-75
DirectDraw7.CreateSurface command, 72 DirectDraw7.CreateSurface FromFile method, 74 DirectDrawSurface command (Shooting Gallery), 85-88
tempo, DirectMusic performances, 266 TerminateSession method, 348, 351, 369-371
trackballs, 180 TrackGetProperty method, 306 TransAdd method, 305 TransGetCount method, 305 TransitionEnabled method, 299 transmission targets (DirectPlay Voice), 376
variables
transposing (DirectMusic Performance object), 260 trapping errors, 29-30, 403-404 trivia questions, user interactions, 14
UnRegisterMessageHandler method, 357-358, 367, 371-372, 379-381 UnRegisterProgram method, 358
utilities, DirectX 8 SDK Caps Viewer, 31-32 DMO Test tool, 32-33 Error Lookup, 31-32
UOPValid method, 336
Force Feedback Editor, 33-34
Try...Catch...End Try structure, error handling, 403-404
UpdateStatus method, 358
GraphEdit tool, 34
UpdateTexture method, 123
Kill Help, 35
Turn-Based genre type, 197
Upload method, 265
Mesh Viewer tool, 35
type libraries
user input
Texture tool, 32-33
ActiveMovie type, creating references, 295 Dexter 1.0 type, 298
action maps, 194 application actions, 195
DirectX, 22
ConfigureDevices method, 202-203
output to assembly converter, 401
configuring, 200-203
quartz.dll type, 316
controls, assigning actions, 198-199
Type method, 321 types
device objects, assigning actions, 198-199
V ValidateDevice method, 123 ValidSourceNames method, 299 values, fRejectMsg, setting, 348-350 variables
palettes, 92
devices, 200-201
RECT, definition, 46
genres, 195-199
DIDEVICEOBJECTDATA, 242-243
GetDeviceData method, 203
DIDEVICEOBJECTDATA, analyzing, 241-244
matching devices, finding, 199
DIDEVICEOBJECTSEQUENCE, lSequence member, 244
U Unacquire method, 185, 241 Unadvise method, 311 Unload method, 189, 264 Unlock method, 124, 127 UnlockBox method, 128 unlocking
preparing, 195 priorities, 197 SetActionMap method, 201 retrieving joysticks, 220-227
DirectMusic, declaring, 267 DirectPlayVoiceClient8 class, holding, 378 DirectPlayVoiceEvent8 class, holding, 379
buffers, 127
keyboards, 206-215
DirectPlayVoiceServer8 class, holding, 380
rectangles, 125-126
mouse, 238-240
Direct3D, declaring, 130
UnlockRect method, 118, 125-127
user interactions DirectX, 14 DirectInput, 178-180
unused, removing, 36
457
458
VB .NET
VB .NET
new features
action maps, 199-200
Exceptions window, 404
assembly converter, output from type library, 401
stepping by line, statement, or instruction, 404
3D objects, 106 wireframes (3D objects), 107-108 VideoHeight method, 318 videos
ConfigureDevices method, 203
PALETTEENTRY data type, 93
CreateSufraceFromFile method, 75
palettes, modifying, 97
games, 8
property sheets, calling, 203
IBasicVideo, 292
CreateSurface method, 73
SetActionMap method, calling, 201
IVideoWindow, 293
DDSURFACEDESC2 surface descriptor, 77
surfaces, creating, 94, 99
Direct3D objects, declaring, 24
VB6, converting to VB .NET, 36
DirectDraw objects, declaring, 56
VB6( ) functions, backwardcompatibility, 36
DirectDrawClipper objects, declaring, 61
VB New Project dialog box, 21, 295
DirectDrawPalette objects, declaring, 60
VB6, converting to VB .NET, 36
DirectDrawSurface objects, declaring, 57
VB6( ) functions, backwardcompatibility, 36
DirectInput class, 182
vectors for billboard applications, code for functions, 171-173
DirectInputDevice class, 183 DirectInputDeviceInstance class, 187 DirectInputDeviceObject Instance class, 185 DirectInputEffectDevice Instance class, 188
velocity (DirectSound 3D), 255 VendorInfo method, 320 vertices backgrounds
DirectInputEnumEffectsDevic eInstance class, 189
code to initialize, 159-161
DirectX, 24, 400-404
2D graphics, creating, 159-161
Flip method, 79 GetTickCount function, 26 overlays, creating, 85
billboard applications, code for functions, 171-173 Direct3D applications, 133-137 meshes (3D objects), 107-108
DirectShow, 290
VideoWidth method, 318 view matrix, 112 view space, 105 viewers, Caps Viewer, 31-32 virtual controls, 198 virtual reality gloves, 180 Visible method, 324 Visual Basic, evolution of, 12 voice. See DirectPlay Voice Volume method, 317, 336 volumes DirectMusic performances, 266 Direct3D objects, 127 sound buffers, 279 Textures, Direct3D objects, 128 VolumesAvailable method, 336 VS Home Page, 402 VtrackGetCount method, 300 VtrackInsBefore method, 300 VtrackSwapPriorities method, 300
Zoom method
W WaitForCompletion method, 320 Watch window, animations, 30 Watt, Alan, 104 Watt, Mark, 104 WAV (wave) files, 248 WAVEFORMATEX object, 280 Web sites, 3D Mark, 43 Width method, 324, 331 WindowlessActivation method, 336 Windows application templates, 402 DirectX history, 9-10 display mode and full-screen display mode, comparing, 64 windows Deployment Method, 394 Exceptions, debugging code, 404
WinG, APIs (Application Programming Interfaces), 10 WinToon, Jump Start demo, 11 wireframes (3D objects), 107-108 Wise packaging program, setup packages, 395 wizards, Package and Deployment Wizard, 389-395 world (world transformation) matrix, 112 wrapping methods, For...Next loop, 347-349 WriteBitmapBits method, 312 WriteBuffer method, 274, 282 WriteGrfFile method, 313 WriteXML method, 313 WriteXMLFile method, 313
Included Filed, 392
X
Output, animations, 30 Package to Deploy, 394
X axis, mouse, 238
Shared Files, 393
X files, 150
Start Menu Items, 392
x method, 331
Watch, animations, 30
Xml2Dex class, methods, 313
Windows Media Format SDK (DirectShow), 294 WindowState method, 324 WindowStyle method, 324 WindowStyleEx method, 324
Y Y axis, mouse, 238 y method, 331 yokes, 179, 191
Z Z axis, mouse, 238 Z-buffering images, 81 ZeroBetween2 method, 303 Zones, dead (joysticks), 224-225 Zoom method, 336
459