Notifications
Clear all

Technical: Direct Draw run down


BrodieBrodie
(@brodiebrodie)
Petty Officer Registered
Joined: 13 years ago
Posts: 30
Topic starter  

run down of creating graphics in ad-infinitum:

Sub Note 1a: You can compiled ad infinitum (like a pro) using lcc-win32 which is free and can be found at

http://www.cs.virginia.edu/~lcc-win32/

the code files are all located in the "code" file of the ad infinitum download

Sub Note 1b: the whole program is basically set out as one c file linked with various headers, all are found in the code file. Create a new project using the "infinitum.c" file (I usually copy/paste the c files text onto a new project) and the rest (the header files) should be linked automatically (the ddraw lib file should also be linked automatically but the compiler may need confirmation, see sub note 1c)

Sub Note 1c: Graphic library: Direct Draw lib, this is usually standard in most compilers now days so no need to search for the header and library files

Yes Direct Draw is a dinosaur, but it works on all versions of windows and is very simple

Sub Note 2: For an over view of DirectDraw see: http://www.bringyou.to/games/ddraw.PDF )

first create and add a bmp file to "grafix" file, (create using gimp, paint... etc). The bmp can be called anything and any size and the bits depth can be 1 to 32, but for the purpose of this tutorial we will call it "my_new_surface.bmp" and say it has a size of 100x50 in 32 bits and assume it is in the ad infinitum "grafix" file.

then create a global Direct Draw pointer that will link this image and place it in "global_vars.h" using: LPDIRECTDRAWSURFACE

Don't panic, this is just a long pointer to the memory location where the image will be located, the pointer can be called anything, but it is good to stick the following that will help one to know what it is: lpDDSOff -this stands for lp: long pointer; DD: direct draw; S: Surface; Off: secondary surface (not the primary surface).

so, for example lets call are new surface lpDDSOffmy_new_surface, so simply add this line in "global_vars.h":

Code:
LPDIRECTDRAWSURFACE lpDDSOffmy_new_surface;

this basically gives a pointer to link the memory of the image.

then create the image in "infinitum.c" or in "set_worlds.h"

(in the part where other are also being created)

so using an example that is (lets say) a 100x50 bmp file:

(note the & (address) here and in other places is needed before, dont forget that the variable is a pointer and we now need its address to define its size)

Code:
ddsd.dwHeight = 50; ///set to the bmp’s height (y)
ddsd.dwWidth = 100; ///set to the bmp’s width (x)

if ( FAILED( lpDD->CreateSurface( &ddsd, &lpDDSOffmy_new_surface, NULL ) ) )
{
debugfile ("Couldn't create lpDDSOffmy_new_surface surface",7 );
return Fail( hwnd, "Couldn't create lpDDSOffmy_new_surface\n" );
}

this basically tells the computer to make room in its memory for the bmp data, by giving the bmp size and linking this to its address.

now load image (same places as creating the image, but must be done after creating):

the [name].bmp must correspond to the bmp file to be loaded’s name in the grafix file,

i.e my_new_surface.bmp in this example

Code:
if ( !LoadMyImage( lpDDSOffmy_new_surface, "grafix/my_new_surface.bmp" ) )
{
debugfile ( "Couldn't load lpDDSOffmy_new_surface.\n",1 );
}

this basically loads the information from the disk drive into the programs memory, with its address and memory all now set to receive this information

technical note: this basically calls the ad infinitum function "LoadMyImage" ; this function calls upon the GDI to load the bmp, so the file size, bits etc are loaded automatic and, as bmp's are stored upside down on disk, it also automatically reverses the image. This is the only call to the GDI (graphics device interface). GDI is a basic graphics windows system, useful for loading images but slow and primitive for displaying. basically not to be worried about, the rest of the program's graphics is done via Direct Draw.

now add info to release the memory from the program when it closes;

this is in the "release.h" file

for the example, we would add:

Code:
if ( lpDDSOffmy_new_surface != NULL )
{
lpDDSOffmy_new_surface->Release();
lpDDSOffmy_new_surface = NULL;
}

this basically tells the computer to release the graphics held in memory when the program closes. This is good practice, even if windows automatically closes memory once a program terminates.

image ready to be used, it can be used in several ways, so using example:

sub note: X_location_on Screen and Y_location_on Screen would have to be set to where the image goes, these points are the images top left corner.

blit fast, a bit faster than the usual, but no effects, used rarely :

note: code placed in the appropriate place (usually in "draw_world.h")

Code:
lpDDSBack->BltFast ( X_location_on Screen ,
Y_location_on Screen ,
lpDDSOffmy_new_surface,
NULL,
DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY );

this basically links the surface onto a back surface, this back surface will be (once all the other images have being updated onto it) "flipped" to the screen

or normal blit:

first set a rectangle structure ( RECT ) to define which part of the image you want from the file.

can be called anything, but it is useful to have the word "rcRectGet" in there so that we know what it is for

in this example we will call it rcRectGetMy_surface_part

Code:
RECT rcRectGetMy_surface_part;

set part one wants, currently set to examples size (100x50) but can be a cut out part of this

Code:
rcRectGetMy_surface_part.bottom = 50;
rcRectGetMy_surface_part.right = 100;
rcRectGetMy_surface_part.left= 0;
rcRectGetMy_surface_part.top= 0;

now set a rectangle where the image is to be placed on the screen:

can be called anything, but it is useful to have the word "rcRectPut" in there so that we know what it is for

Code:
RECT rcRectPutMy_surface_part;

and set to where it goes on the screen (x and y coordinates)

note that this rectangle can be bigger or smaller than the get rectangle

these are basic effects and used a great deal in ad infinitum:

if it is smaller, the image is shrunk,

if it is larger, the image is stretched,

if it is the same dimensions the image if place like in blt fast

note x and y should be defined where the image is placed on screen

so: using example size of 100x50 and without stretch shrink effects

Code:
rcRectPutMy_surface_part.bottom = y+50;
rcRectPutMy_surface_part.right = x+100;
rcRectPutMy_surface_part.left= x;
rcRectPutMy_surface_part.top= y;

and finally the drawing of the image (or its selected part) in the appropriate place (usually in draw_world.h)

Code:
lpDDSBack->Blt ( &rcRectPutMy_surface_part,
lpDDSOffmy_new_surface ,
&rcRectGetMy_surface_part,
DDBLT_WAIT | DDBLT_KEYSRC,
NULL );

or a normal blt using mirroring effect:

this mirrors the image from left to right

not this uses the rectangles of normal blt above, but it written as

Code:
ddbltfx.dwDDFX = DDBLTFX_MIRRORLEFTRIGHT;

lpDDSBack->Blt ( &rcRectPutMy_surface_part ,
lpDDSOffmy_new_surface,
&rcRectGetMy_surface_part,
DDBLT_DDFX | DDBLT_WAIT | DDBLT_KEYSRC,
&ddbltfx );


Quote