DirectX 8 and Visual Basic Development [illustrated edition] 9780672322259, 0672322250

DirectX 8 and Visual Basic Development fills an unmet need in the marketplace as the first book to explain how to use Vi

437 101 3MB

English Pages 479 Year 2001

Report DMCA / Copyright

DOWNLOAD PDF FILE

Recommend Papers

DirectX 8 and Visual Basic Development [illustrated edition]
 9780672322259, 0672322250

  • Commentary
  • 42074
  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
File loading please wait...
Citation preview

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