Table Of Contents

Unzip the project in any directory of your choosing. The main workspace
can be opened using the "DXSmithLib.dsw" workspace. The program requires
at least DirectX 7.0 to compile and run.

[editor's note--the programs have been compiled and run successfully using
VS6 on a Win2K machine with DirectX 9.0 SDK installed]

testwin - A simple demonstration program (see above screenshot)

testgui - Tests a gui full-screen. It is a command line app. Run the
batch file "use_testgui.bat". The mouse_cursor.bmp MUST be in a sub-dir called
data located in the directory that testgui.exe is located.

testsprite - View a sprite full screen to see how it looks on a black
background. It is mainly an example of using a sprite in a simple program.
It takes only one parameter: the name of a spritebank (file.spr) created by
SpriteEdit. The .SPR file and its required .BMP files must be in a
directory called data, located where the exe is.

DXSmith is a wrapper around Microsoft's DirectX graphic libraries. The
current version wraps the Direct Draw 2D graphics, I/O, sound, and music for
DX7. No 3D functions are wrapped or used. The DXSmith wrapper provides a set of
higher level functions that are easier to use and learn than the DirectX API.
DXSmith makes it easier for beginners to use DirectX. DirectX is a very flexible
API, but that very flexibility also makes it fairly complicated. DXSmith also
provides tools to create and draw animated sprites, and simple GUI's without
using MFC calls. A number of GDI calls are also wrapped to provide higher level
functions like lines, circles, text, and pie sections. DXSmith also provides
"resource management". Place all your data files in a sub-directory, or
libraries in the sub-directory and the resource manager will load, unload, and
track the resources in memory.

DXSmith provides everything for the amateur game programmer to get started
with DirectX.

The I/O library provides the graphic primitives, user input, and sound and
music functions that are the building blocks of all other DXSmith utilities.

See testwin for an example of using the DXSmith lib. TestWin is a bare-bones
windows program that uses the DXSmith i/o library. It is an excellent example of
using the library, and is simple enough to easily modify for your own use.

Test1 is a console program that exercises all key parts of the library.

name of the section to read the data from. Do not include the "[ ]" in the
section name.

pKeyName

name of the key within the section to read.

pDefault

value to return if the section or key is not found.

pReturnedString

string to copy the requested value to from the INI file.

sizeRetStr

length of pReturnedString. If the length of the data exceeds sizeRetStr it
will be truncated.

pFileName

name of the INI file to read from. If the filename includes a path (detected
by searching for the back-slash "\" character) the resource paths are not
searched. If the filename has no path, then the currently registered resource
paths are searched for the INI file.

Read integer data from a normal text INI file. Attempts to convert the text
to an integer.

pSectionName

name of the section to read the data from. Do not include the "[ ]" in the
section name.

pKeyName

name of the key within the section to read.

pDefault

value to return if the section or key is not found.

pReturnedLong

integer to copy the requested value to from the INI file.

pFileName

name of the INI file to read from. If the filename includes a path (detected
by searching for the back-slash "\" character) the resource paths are not
searched. If the filename has no path, then the currently registered resource
paths are searched for the INI file.

RETURNS: Length of the string representing the integer copied to
pReturnedLong.

name of the section to write the data to. Do not include the "[ ]" in the
section name.

pKeyName

name of the key within the section to set.

pString

value to set the key to.

pFileName

name of the INI file to write to. If the filename includes a path (detected
by searching for the back-slash "\" character) the resource paths are not
searched. If the filename has no path, then the currently registered resource
paths are searched for the INI file.

name of the section to write the data to. Do not include the "[ ]" in the
section name.

pKeyName

name of the key within the section to set.

value

value to set the key to.

pFileName

name of the INI file to write to. If the filename includes a path (detected
by searching for the back-slash "\" character) the resource paths are not
searched. If the filename has no path, then the currently registered resource
paths are searched for the INI file.

Draw a bitmap to the off-screen buffer. Call Flip() to display
the current off-screen buffer. Use pDest to set the size and location of the
bitmap. By changing the destination size you can scale the bitmap to any desired
size. Clipping is supported. If clipping is disabled be sure that
pDest does not exceed the off-screen buffer's boundaries.

pDest

the destination position and size of the bitmap to be blitted. Note that the
(right - left) equals the width, not the width -1, and (bottom - top) equals the
height.

pScr

source bitmap, loaded by LoadBitpmap(). Transparent--if
non-zero then all pixels matching the top-left pixel are transparent.
Transparency not supported in GDI mode.

hdc

if not NULL the specified hdc is used instead of the default full-screen
hdc.

RETURNS: Zero on success. A GSDX_ERROR_ code on failure.

Blit

Draw a bitmap to the off-screen buffer. Call Flip() to display
the current off-screen buffer. Use pDest to set location of the
bitmap. The bitmap is displayed at its original size. If clipping is disabled be
sure that blitted bitmap does not exceed the off-screen buffer's boundaries.

pDest

the destination position of the bitmap to be blitted.

pScr

source bitmap, loaded by LoadBitpmap().
Transparent--if non-zero then all pixels matching the top-left pixel are
transparent. Not supported in GDI mode.

hdc

if not NULL the specified hdc is used instead of the default
full-screen hdc.

Convert an RGB colour
for use with the current video mode. Not required for any function that uses GDI
(Line(), Ellipse(), PieFill()). Should be used for any DirectX
function that takes a color parameter (Blit()). Only valid for
full-screen modes, and requires that InitGraphics() be called
previously.

Display the current off-screen buffer, and
make the currently displayed buffer the off-screen buffer. The normal
procedure is to call the various drawing functions until the complete frame is
ready, then call Flip() to display it.

Initialize the graphics mode. For the full-screen option
setup a primary buffer and off-screen buffer. Use GetModes() and
GetGraphicsModeInfo() to detect support widths, heights, and color
depths. If the GDI mode is selected the current video mode is NOT changed, and
no buffers are prepared.

This function must be called before any other graphics function is
called.

width

width of the screen in pixels.

height

height of the screen in pixels.

colorDepth

number of bits per pixel.

options

full-screen or GDI. If full screen the GDSX_CONSOLE_MODE option must also be
used if the exe if a console application.

GSDX_FULL_SCREEN

Exclusive full screen mode with double buffering.

GSDX_WINDOWED_GDI

Retain the current video mode. (NOTE: some functions will not be supported
or have reduced function).

GSDX_CONSOLE_MODE

Only use with the full screen option if the exe is a console application.
Failing to use this option with console applications will cause the application
to crash.

Load a bitmap from a file and prepare it to be blitted for the currently
selected video mode. InitResource() must be called first.

If the image is already loaded the currently loaded image is used for the
bitmap. One image can have many bitmaps stored on it. Each bitmap will point to
the area of the main image containing its region.

The returned bitmap must be `deleted' when the bitmap is no longer
required. This only deletes this particular bitmap (which includes a
pointer to the main source image), NOT the main source image in memory. Call
UnLoadAllBitmaps() to unload all the main source images.

pFileName

name of the bitmap to be loaded. The resource paths and libraries
are searched if there is no path included in the name. Currently only BMP
format files are supported, and must have the .bmp file extenstion.

pRect

if NULL the returned bitmap is the whole source image. If pRect
is not NULL and right and bottom are not zero then it defines the region of the
source image to return as the bitmap. This enables multiple bitmaps to be stored
in one image file. If pREct is not NULL, but right and bottom are zero then
pRect is filled in with the size of the whole source
image.

Draw pie-shaped filled
section. The Pie is `cut' from an ellipse bounded by left, top, right, bottom,
and bounded by lines starting at the centre of the bounding box and going out
through (x1,y1) and (x2,y2) in a counter-clock wise direction.

Draw a solid filled rectangle. Note that the same value of color will give
different colors on screen depending on the current video mode's pixel format.
Use ConvertRGB() to change an RGB() value to a video
mode specific value. This function may be faster than Line() for
vertical and horizontal lines.

rect

defines the rectangular region to be filled.

color

colour of the filled rectangle. Note that the same value of color will give
different colours on screen depending on the current video mode's pixel
format.

Define multiple clipping regions. Use EnableClipping() after
calling this function to enable the defined clipping regions. All
Blits() and RectFills() that fall outside of the
defined regions will be clipped (not displayed). A second call to
SetClipping() deletes the previous clipping regions and sets up the
new regions.

Must be called before using
ANY resource related function. LoadBitmap() and
LoadSound() also requires that this be called as they use the
resource functions. Does not depend on InitGraphics(). Default
paths are added: exe_path\data, and cd_drive:\data where exe_path is the path
that the exe ran from. cd_drive is the drive letter for any cd drive
detected.

For example:Foo.exe is run from c:\myexe on a computer with
two cd drives, e: and f: and calls InitResource()The default
paths that are searched will be:

Load a file into memory. The resource paths are searched for the file.
Libraries in the resource paths are also searched. The last `good' path or
library is searched first - always call LoadResource() on files in
the same directory in batches if possible. If the file is already loaded its
count is increased and the existing pointer is returned.

pName

name of file to load into memory.

pIndex

pointer to a DOWRD to return the INDEX in. Can be used by
GetResource() to quickly get a pointer to a previously loaded
resource. Using GetResource() is MUCH faster than calling
LoadResource().

pSize

pointer to a DWORD to hold the size, in bytes, of the file loaded into
memory.

RETURNS: NULL on error, a pointer to the loaded file if OK. Call
GetLastError() to get detailed error information.

This
function should be called frequently to ensure all user i/o is processed
correctly. This function updates internal data structures that are used by the
i/o state functions. Even if you never use any events and only poll the i/o
devices this function MUST be called frequently (a minimum of 60Hz is
recommended).

If pEvent is NULL the user I/O is processed, but the latest
event is discarded. All state information (eg joystick and mouse x, y position)
is updated each time this function is called. InitIO() must be
called with the events desired turned on. If a gsdxEvent_t pointer is passed in
then the oldest event is copied to it.

Events:

Keyboard: each key press and release is an event.

Joystick:

X,Y, Rudder: moving to left/right/top/bottom or returning to centre
generates an event.

Throttle (Z): each movement of more than 100th of the total throttle range
generates an event.

Buttons: all presses and releases generate an event.

HAT: any change generates an event.

Mouse:

Buttons: each press and release generates an event.

X, Y: any movement generates an event.

Wheel: each `click' generates an event.

Please see the definition of gsdxEvent_t for details on the data returned in
an event.

pEvent: pointer to gsdxEvent_t to hold the event
information.

RETURNS: NULL if no event is ready, or no event passed in.
Returns a pointer to pEvent if an event is available.

// current mouse state
typedef struct
{
int x, y, z; // wheel is z, current value for each of theseint dx, dy, dz; // wheel is z, change in each value since last call
DWORD buttons; // if a bit is set the button is down.int max_x, max_y, max_z; // Max_x and max_y // default to the screen resolution in pixels.
}
gsdxMouseState_t;

GuiLib provides functions that display and use simple graphical user
interfaces suitable for use with games without using any MFC or win32 calls. Use
GUIEdit to create GUI panels. Multiple panels can be loaded, but only the
last loaded panel is active and returns events.

Do all logic related
to a gui panel. Does not draw the gui panel. Takes user input and updates the
status of the gui panel. See testgui for a complete example of its use in a
normal windows program. The gadget (panel) last loaded is active.

event: pointer an event to return any user i/o in. The event type will
indicate if it is a gui event, or other type of user i/o. The ID will indicate
which gadget was used if it is a gui event.

GuiEdit is a visual editor for creating gui panels that can be used with the
GUI lib. Gadgets can be added, deleted, copied, moved, resized, and the details
edited. Use TestGui to display and test your gui panels under fullscreen mode.
The TestGui source code also is a good example of using a gui panel created
with GUIEdit.

This version of GuiEdit supports lists, buttons, radio buttons, text, and
sliders.

NOTE! Use ID's higher than 99 for the gadgets you create to avoid conflicts
with system created gadgets.

Grid - Set grid related options. When the Grid is ON, gadgets can only be
moved and sized on the `grid'

Default Values - set default values used when creating new gadgets. These
are NOT saved automatically on program exit.

Save Defaults - save the current defaults. Only one set can be saved.

Tab Order - When this is turned on the tab-order of each gadget is displayed
at its top-left corner. Click on the gadgets in the order you want them to tab
through. If gadgets are already in order you must still click on them in order.
The next tab number is displayed at the lower-left of the view window. Choose
this option again to leave the tab-order mode.

Context (Right-click)

Right-click on a gadget or the main rectangle to bring up this menu.

Add Gadget - add a gadget at the current mouse position. The top-left corner
of the new gadget will be at the mouse position. Choose the desired gadget from
the sub-menu.

Properties - will pop up a dialog allowing all options for the gadget under
the mouse to be set.

Copy - copy the gadget under the mouse.

Delete - delete the gadget under the mouse.

Gadgets

Static Text, Used to place text on the gui panel. Cannot be edited.

Input Box, Allows the user to enter text. If the `password' option is
enabled then only asterisks `*' are displayed. If the `numbers' option is
selected only digits and the period `.' can be entered. Text entered can be up
to 255 characters long. The input box supports horizontal scrolling.

Button - text

Button - bitmap

Button - sprite, a button that can be clicked on with one of the preceding
items displayed on it.

Slider, a vertical or horizontal slider.

Radio buttons, a set of mutually exclusive buttons. Only one can be active.

Pick-List, display a list of text items and allow one, or multiple items to
be selected.

General

Left-click on a gadget and drag to move it. Left-click on a gadget's lower,
right corner and drag to re-size it. Right click on a gadget to access its
properties.

Each sprite in the
currently loaded set is indexed, starting at zero. This function draws one
sprite, using its current frame at position x, y. X, Y is the position of the
top left corner of the sprite (plus adjustments as made in the sprite editor).

A sprite is a small graphic that can be moved across (animated) on the
screen. Each sprite is made up of multiple frames that can be animated also.
SpriteEdit allows you to load a bitmap, and select regions of the bitmap to be
the frames of a sprite. Multiple sprites can be made from a single bitmap, and
multiple bitmaps can be loaded into one "spritebank".

Left click and drag on a visible rectangle to move it. Hold down the SHIFT
key while dragging to resize a rectangle. Hold down the CTRL key while dragging
a collision rectangle to adjust the dx/dy of the current frame.

When adding a frame the currently displayed bitmap is used.

When adding a new sprite it is created with one frame that uses the
currently displayed bitmap.

Loading a bitmap has no effect on the current sprite or frame.

Toolbar

The first two arrow icons move to the previous and next frames of the
current sprite. Hold down the shift key while clicking to move the previous and
next bitmaps. The second pair of arrows moves to the previous and next sprite.

The left and right arrow keys also change frames. The up and down arrow keys
change sprites.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Comments and Discussions

DirectX is a set of code libaries supplied by Microsoft that enable programmers to make graphics applications, such as games, that can use the built in hardware acceleration available of new graphics cards.

DirectX SDK can be downloaded from the MS web site.

This "wrapper" is a set of higher level functions that initialize DirectX, and allow you more eaily use directX by taking care of much of the routine housekeeping and initialization required to use directX.

Asking this question indicates that you may be a beginning programmer. Using this wrapper is aimed at intermediate programmers who already know c++, and at least some win32 programming.

Testwin, spriteEdit and GuiEdit are compiling and working fine but all the other programs are compiling but not working. Essentially they open up (the .bat files), start with the black screen and then immediately close. Any suggestions...?

This is a long article, so please excuse me if I have missed something

If you go to all this trouble is seems strange not to extend it a little further to make it API independant. Your interface presents common tasks as simple functions, so you should be able to see using an abstract base class then implementing it for DX would be a good idea.

Style wise, I dislike how you seem to follow DX's conventions. Just a personal thing, a view probably not shared by most people

It seems this would be a lot better if it was more OO and standard C++ than 'Microsoft'.

Another thing, please kill the INIs. Use XML instead. This is the year 2003... Seriously though, there seems to be no good reason to stick with INIs and other old conventions in you library.

Thanks for the suggestions. Please feel free to go ahead and make these changes if you wish. I'm sure it won't take too long.

XML is quite a bit more complicated than ini files. There are a number of good tools out there for XML and I didn't need it for my own projects. You do NOT have to use the ini functions if they offend your programming sensabilities. Others might find the ini functions useful, so I see no harm in letting them remain.

When I started this project I was not aiming at making a while new graphics API (see Open GL for a good one), I just wanted to play with DirectX. I soon found that a lot of "housekeeping" was required to get started with DirectX and this library is my humble attempt to make life easier for me. I hope others find it useful.

While having many years experience with procedural programming, I must admit that the whole OO thing is a bit new to me. I am starting to see the utility of using more OO style programming and quite like the way it forces you to think and plan out what will be in your "objects". That said, could you give some specific advice in making the DX wrapper more OO'ish.

arussell wrote:feel free to go ahead and make these changes if you wish. I'm sure it won't take too long.

Cheeky I think what you have done is worthwhile btw. It is always good practise to wrap house keeping code and so on. But it is better to wrap it in classes. Anyway, I think people will find your code useful. Some may be turned off completely by an non OO approach however. Not all people of course

arussell wrote:XML is quite a bit more complicated than ini files

Not if you use an existing XML library. Honest Many, many people on this site have moved to XML without any real headaches. XML is excellent for defining scenes / gui layouts without code for example.

arussell wrote:some specific advice in making the DX wrapper more OO'ish.

To keep things simple, you could declare all your functions in an absract class. Then you inherit from this with the actual code. This allows someone else to make a wrapper that inherits the class. Now comes the cool part, people who use you library can change API without having to change their code.

Yes, you could do this without any C++ using DLLs. It's just an idea.

I think it is not my place to teach you OO, but I will point you in a very interesting direction: DirectX in .NET. This is all classes. Some people would say it does not really use OO to the full, but I highly recommend you look at the docs. It seems Microsoft have taken away a lot of the housekeeping jobs

I am not suggesting you use .NET, I am simply saying look at the design.

arussell wrote:That said, could you give some specific advice in making the DX wrapper more OO'ish.

One of the things I've found as project lead on a couple games a few years ago is that it's not that hard to wrap things in OO. But what is a bit more challenging is the glue that holds a game together:

sequencing (for example, after animation A run animation B)

synchronization (for example, start dialog track A on the third frame of animation B while music C is playing)

That about covers it, I think. Another poster mentioned CDX. So what? None of these higher level processing stuff is covered by CDX from what I saw. This is where a good object design implemented in a robust game framework will set you apart from the pack. And personally, I think this is where the fun is and where OO has one of it's uses--a good framework to help automate mundane game development tasks, not just wrapping functions into objects. Wrappers can cause a myriad of crosscutting and separation of concern problems (Aspect Oriented Programming terms).

Just my 2c.

Marc

Every line of code is a liability - Taka MuraokaA doable project is one that is small enough to be done quickly and big enough to be interesting - Ken Orr