home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Windows Game Programming for Dummies (2nd Edition)
/
WinGamProgFD.iso
/
mac
/
Source
/
GPCHAP16
/
GPDUMB2.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
2002-05-01
|
45KB
|
1,729 lines
// GPDUMB2.CPP - Game Engine Part II
// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN
//#define INITGUID
#include <windows.h> // include important windows stuff
#include <windowsx.h>
#include <mmsystem.h>
#include <objbase.h>
#include <iostream.h> // include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <ddraw.h> // directX includes
#include <dsound.h>
#include <dinput.h>
#include "gpdumb1.h"
#include "gpdumb2.h"
// DEFINES ////////////////////////////////////////////////
// TYPES //////////////////////////////////////////////////
// PROTOTYPES /////////////////////////////////////////////
// EXTERNALS /////////////////////////////////////////////
extern HWND main_window_handle; // access to main window handle in main module
// GLOBALS ////////////////////////////////////////////////
// directsound stuff
LPDIRECTSOUND lpds; // directsound interface pointer
DSBUFFERDESC dsbd; // directsound description
DSCAPS dscaps; // directsound caps
HRESULT dsresult; // general directsound result
DSBCAPS dsbcaps; // directsound buffer caps
LPDIRECTSOUNDBUFFER lpdsbprimary; // the primary mixing buffer
pcm_sound sound_fx[MAX_SOUNDS]; // the array of secondary sound buffers
WAVEFORMATEX pcmwf; // generic waveformat structure
// directinput globals
LPDIRECTINPUT8 lpdi = NULL; // dinput object
LPDIRECTINPUTDEVICE8 lpdikey = NULL; // dinput keyboard
LPDIRECTINPUTDEVICE8 lpdimouse = NULL; // dinput mouse
LPDIRECTINPUTDEVICE8 lpdijoy = NULL; // dinput joystick
GUID joystickGUID; // guid for main joystick
char joyname[80]; // name of joystick
// these contain the target records for all di input packets
UCHAR keyboard_state[256]; // contains keyboard state table
DIMOUSESTATE mouse_state; // contains state of mouse
DIJOYSTATE joy_state; // contains state of joystick
int joystick_found = 0; // tracks if joystick was found and inited
// FUNCTIONS //////////////////////////////////////////////
int Load_VOC(char *filename)
{
// this function loads a .voc file, sets up the directsound buffer and loads the data
// into memory, the function returns the id number of the sound
int sound_id = -1, // id of sound to be loaded
index, // looping variable
data_offset, // offset to data part of file
playback_rate, // playback rate as encoded in file
data_length; // length of data
ULONG bytesread = 0, // actual number of bytes read during file read
filelength; // length of file
int file_handle; // general file handle
UCHAR *snd_buffer, // temporary sound buffer to hold voc data
*audio_ptr_1=NULL, // data ptr to first write buffer
*audio_ptr_2=NULL; // data ptr to second write buffer
DWORD audio_length_1=0, // length of first write buffer
audio_length_2=0; // length of second write buffer
// step one: are there any open id's ?
for (index=0; index < MAX_SOUNDS; index++)
{
// make sure this sound is unused
if (sound_fx[index].state==SOUND_NULL)
{
sound_id = index;
break;
} // end if
} // end for index
// did we get a free id?
if (sound_id==-1)
return(-1);
// step two: load the voc file off disk
if ((file_handle = _open(filename,_O_BINARY | _O_RDONLY))==-1)
return(0);
// get size of file so we can allocate temporary read buffer
filelength = _filelength(file_handle);
// allocate a large enough temporary buffer
snd_buffer = (UCHAR *)malloc(filelength);
// now read in the data
bytesread = _read(file_handle, snd_buffer, filelength);
// access all values and decode VOC encoding for data fields
data_offset = snd_buffer[20];
playback_rate = (-1000000/(snd_buffer[data_offset+4]-256));
data_length = ((*(int *)(snd_buffer+data_offset)) >> 8);
// set rate and size in data structure
sound_fx[sound_id].rate = playback_rate;
sound_fx[sound_id].size = data_length;
sound_fx[sound_id].state = SOUND_LOADED;
// close the file
_close(file_handle);
// step three: create the sound buffer and copy voc data into buffer
// set up the format data structure
memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
pcmwf.wFormatTag = WAVE_FORMAT_PCM; // pulse code modulation
pcmwf.nChannels = 1; // mono
pcmwf.nSamplesPerSec = 11025; // always this rate
pcmwf.nBlockAlign = 1;
pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
pcmwf.wBitsPerSample = 8;
pcmwf.cbSize = 0;
// prepare to create sounds buffer
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
dsbd.dwBufferBytes = data_length-NVB_SIZE;
dsbd.lpwfxFormat = &pcmwf;
// create the sound buffer
if (lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)!=DS_OK)
{
// release memory
free(snd_buffer);
// return error
return(-1);
} // end if
// copy data into sound buffer
if (sound_fx[sound_id].dsbuffer->Lock(0,
data_length-NVB_SIZE,
(void **) &audio_ptr_1,
&audio_length_1,
(void **)&audio_ptr_2,
&audio_length_2,
DSBLOCK_FROMWRITECURSOR)!=DS_OK)
return(0);
// copy first section of circular buffer
memcpy(audio_ptr_1, snd_buffer+data_offset+NVB_SIZE, audio_length_1);
// copy last section of circular buffer
memcpy(audio_ptr_2, (snd_buffer+data_offset+NVB_SIZE+audio_length_1),audio_length_2);
// unlock the buffer
if (sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1,
audio_length_1,
audio_ptr_2,
audio_length_2)!=DS_OK)
return(0);
// release the temp buffer
free(snd_buffer);
// return id
return(sound_id);
} // end Load_Voc
///////////////////////////////////////////////////////////
int Load_WAV(char *filename, int control_flags)
{
// this function loads a .wav file, sets up the directsound
// buffer and loads the data into memory, the function returns
// the id number of the sound
HMMIO hwav; // handle to wave file
MMCKINFO parent, // parent chunk
child; // child chunk
WAVEFORMATEX wfmtx; // wave format structure
int sound_id = -1, // id of sound to be loaded
index; // looping variable
UCHAR *snd_buffer, // temporary sound buffer to hold voc data
*audio_ptr_1=NULL, // data ptr to first write buffer
*audio_ptr_2=NULL; // data ptr to second write buffer
DWORD audio_length_1=0, // length of first write buffer
audio_length_2=0; // length of second write buffer
// step one: are there any open id's ?
for (index=0; index < MAX_SOUNDS; index++)
{
// make sure this sound is unused
if (sound_fx[index].state==SOUND_NULL)
{
sound_id = index;
break;
} // end if
} // end for index
// did we get a free id?
if (sound_id==-1)
return(-1);
// set up chunk info structure
parent.ckid = (FOURCC)0;
parent.cksize = 0;
parent.fccType = (FOURCC)0;
parent.dwDataOffset = 0;
parent.dwFlags = 0;
// copy data
child = parent;
// open the WAV file
if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
return(-1);
// descend into the RIFF
parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
{
// close the file
mmioClose(hwav, 0);
// return error, no wave section
return(-1);
} // end if
// descend to the WAVEfmt
child.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioDescend(hwav, &child, &parent, 0))
{
// close the file
mmioClose(hwav, 0);
// return error, no format section
return(-1);
} // end if
// now read the wave format information from file
if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
{
// close file
mmioClose(hwav, 0);
// return error, no wave format data
return(-1);
} // end if
// make sure that the data format is PCM
if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
{
// close the file
mmioClose(hwav, 0);
// return error, not the right data format
return(-1);
} // end if
// now ascend up one level, so we can access data chunk
if (mmioAscend(hwav, &child, 0))
{
// close file
mmioClose(hwav, 0);
// return error, couldn't ascend
return(-1);
} // end if
// descend to the data chunk
child.ckid = mmioFOURCC('d', 'a', 't', 'a');
if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
{
// close file
mmioClose(hwav, 0);
// return error, no data
return(-1);
} // end if
// finally!!!! now all we have to do is read the data in and
// set up the directsound buffer
// allocate the memory to load sound data
snd_buffer = (UCHAR *)malloc(child.cksize);
// read the wave data
mmioRead(hwav, (char *)snd_buffer, child.cksize);
// close the file
mmioClose(hwav, 0);
// set rate and size in data structure
sound_fx[sound_id].rate = wfmtx.nSamplesPerSec;
sound_fx[sound_id].size = child.cksize;
sound_fx[sound_id].state = SOUND_LOADED;
// set up the format data structure
memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
pcmwf.wFormatTag = WAVE_FORMAT_PCM; // pulse code modulation
pcmwf.nChannels = 1; // mono
pcmwf.nSamplesPerSec = 11025; // always this rate
pcmwf.nBlockAlign = 1;
pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
pcmwf.wBitsPerSample = 8;
pcmwf.cbSize = 0;
// prepare to create sounds buffer
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
dsbd.dwBufferBytes = child.cksize;
dsbd.lpwfxFormat = &pcmwf;
// create the sound buffer
if (lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)!=DS_OK)
{
// release memory
free(snd_buffer);
// return error
return(-1);
} // end if
// copy data into sound buffer
if (sound_fx[sound_id].dsbuffer->Lock(0,
child.cksize,
(void **) &audio_ptr_1,
&audio_length_1,
(void **)&audio_ptr_2,
&audio_length_2,
DSBLOCK_FROMWRITECURSOR)!=DS_OK)
return(0);
// copy first section of circular buffer
memcpy(audio_ptr_1, snd_buffer, audio_length_1);
// copy last section of circular buffer
memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);
// unlock the buffer
if (sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1,
audio_length_1,
audio_ptr_2,
audio_length_2)!=DS_OK)
return(0);
// release the temp buffer
free(snd_buffer);
// return id
return(sound_id);
} // end Load_WAV
///////////////////////////////////////////////////////////
int Replicate_Sound(int source_id)
{
// this function replicates the sent sound and sends back the
// id of the replicated sound, you would use this function
// to make multiple copies of a gunshot or something that
// you want to play multiple times simulataneously, but you
// only want to load once
if (source_id!=-1)
{
// duplicate the sound buffer
// first hunt for an open id
for (int id=0; id < MAX_SOUNDS; id++)
{
// is this sound open?
if (sound_fx[id].state==SOUND_NULL)
{
// first make an identical copy
sound_fx[id] = sound_fx[source_id];
// now actually replicate the directsound buffer
if (lpds->DuplicateSoundBuffer(sound_fx[source_id].dsbuffer,
&sound_fx[id].dsbuffer)!=DS_OK)
{
// reset sound to NULL
sound_fx[id].dsbuffer = NULL;
sound_fx[id].state = SOUND_NULL;
// return error
return(-1);
} // end if
// now fix up id
sound_fx[id].id = id;
// return replicated sound
return(id);
} // end if found
} // end for id
} // end if
else
return(-1);
// else failure
return(-1);
} // end
///////////////////////////////////////////////////////////
int DSound_Init(void)
{
// this function initializes the sound system
static int first_time = 1; // used to track the first time the function
// is entered
// test for very first time
if (first_time)
{
// clear everything out
memset(sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS);
// reset first time
first_time = 0;
// create a directsound object
if (DirectSoundCreate(NULL, &lpds, NULL)!=DS_OK )
return(0);
// set cooperation level
if (lpds->SetCooperativeLevel((HWND)main_window_handle,DSSCL_NORMAL)!=DS_OK)
return(0);
} // end if
// initialize the sound fx array
for (int index=0; index<MAX_SOUNDS; index++)
{
// test if this sound has been loaded
if (sound_fx[index].dsbuffer)
{
// stop the sound
sound_fx[index].dsbuffer->Stop();
// release the buffer
sound_fx[index].dsbuffer->Release();
} // end if
// clear the record out
memset(&sound_fx[index],0,sizeof(pcm_sound));
// now set up the fields
sound_fx[index].state = SOUND_NULL;
sound_fx[index].id = index;
} // end for index
// return sucess
return(1);
} // end DSound_Init
///////////////////////////////////////////////////////////
int DSound_Shutdown(void)
{
// this function releases all the memory allocated and the directsound object
// itself
// first turn all sounds off
Stop_All_Sounds();
// now release all sound buffers
for (int index=0; index<MAX_SOUNDS; index++)
if (sound_fx[index].dsbuffer)
sound_fx[index].dsbuffer->Release();
// now release the directsound interface itself
lpds->Release();
// return success
return(1);
} // end DSound_Shutdown
///////////////////////////////////////////////////////////
int Play_Sound(int id, int flags, int volume, int rate, int pan)
{
// this function plays a sound, the only parameter that
// works is the flags which can be 0 to play once or
// DSBPLAY_LOOPING
if (sound_fx[id].dsbuffer)
{
// reset position to start
if (sound_fx[id].dsbuffer->SetCurrentPosition(0)!=DS_OK)
return(0);
// play sound
if (sound_fx[id].dsbuffer->Play(0,0,flags)!=DS_OK)
return(0);
} // end if
// return success
return(1);
} // end Play_Sound
///////////////////////////////////////////////////////////
int Set_Sound_Volume(int id,int vol)
{
// this function sets the volume on a sound 0-100
if (sound_fx[id].dsbuffer->SetVolume(DSVOLUME_TO_DB(vol))!=DS_OK)
return(0);
// return success
return(1);
} // end Set_Sound_Volume
///////////////////////////////////////////////////////////
int Set_Sound_Freq(int id,int freq)
{
// this function sets the playback rate
if (sound_fx[id].dsbuffer->SetFrequency(freq)!=DS_OK)
return(0);
// return success
return(1);
} // end Set_Sound_Freq
///////////////////////////////////////////////////////////
int Set_Sound_Pan(int id,int pan)
{
// this function sets the pan, -10,000 to 10,0000
if (sound_fx[id].dsbuffer->SetPan(pan)!=DS_OK)
return(0);
// return success
return(1);
} // end Set_Sound_Pan
////////////////////////////////////////////////////////////
int Stop_Sound(int id)
{
// this function stops a sound from playing
if (sound_fx[id].dsbuffer)
{
sound_fx[id].dsbuffer->Stop();
sound_fx[id].dsbuffer->SetCurrentPosition(0);
} // end if
// return success
return(1);
} // end Stop_Sound
///////////////////////////////////////////////////////////
int Delete_All_Sounds(void)
{
// this function deletes all the sounds
for (int index=0; index < MAX_SOUNDS; index++)
Delete_Sound(index);
// return success always
return(1);
} // end Delete_All_Sounds
///////////////////////////////////////////////////////////
int Delete_Sound(int id)
{
// this function deletes a single sound and puts it back onto the available list
// first stop it
if (!Stop_Sound(id))
return(0);
// now delete it
if (sound_fx[id].dsbuffer)
{
// release the com object
sound_fx[id].dsbuffer->Release();
sound_fx[id].dsbuffer = NULL;
// return success
return(1);
} // end if
// return success
return(1);
} // end Delete_Sound
///////////////////////////////////////////////////////////
int Stop_All_Sounds(void)
{
// this function stops all sounds
for (int index=0; index<MAX_SOUNDS; index++)
Stop_Sound(index);
// return success
return(1);
} // end Stop_All_Sounds
///////////////////////////////////////////////////////////
int Status_Sound(int id)
{
// this function returns the status of a sound
if (sound_fx[id].dsbuffer)
{
ULONG status;
// get the status
sound_fx[id].dsbuffer->GetStatus(&status);
// return the status
return(status);
} // end if
else // total failure
return(-1);
} // end Status_Sound
///////////////////////////////////////////////////////////
void HLine(int x1,int x2,int y,int color, UCHAR *vbuffer, int lpitch)
{
// draw a horizontal line using the memset function
int temp; // used for temporary storage during endpoint swap
// perform trivial rejections
if (y > max_clip_y || y < min_clip_y)
return;
// sort x1 and x2, so that x2 > x1
if (x1>x2)
{
temp = x1;
x1 = x2;
x2 = temp;
} // end swap
// perform trivial rejections
if (x1 > max_clip_x || x2 < min_clip_x)
return;
// now clip
x1 = ((x1 < min_clip_x) ? min_clip_x : x1);
x2 = ((x2 > max_clip_x) ? max_clip_x : x2);
// draw the row of pixels
memset((UCHAR *)(vbuffer+(y*lpitch)+x1),
(UCHAR)color,x2-x1+1);
} // end HLine
//////////////////////////////////////////////////////////////////////////////
void VLine(int y1,int y2,int x,int color,UCHAR *vbuffer, int lpitch)
{
// draw a vertical line, note that a memset function can no longer be
// used since the pixel addresses are no longer contiguous in memory
// note that the end points of the line must be on the screen
UCHAR *start_offset; // starting memory offset of line
int index, // loop index
temp; // used for temporary storage during swap
// perform trivial rejections
if (x > max_clip_x || x < min_clip_x)
return;
// make sure y2 > y1
if (y1>y2)
{
temp = y1;
y1 = y2;
y2 = temp;
} // end swap
// perform trivial rejections
if (y1 > max_clip_y || y2 < min_clip_y)
return;
// now clip
y1 = ((y1 < min_clip_y) ? min_clip_y : y1);
y2 = ((y2 > max_clip_y) ? max_clip_y : y2);
// compute starting position
start_offset = vbuffer + (y1*lpitch) + x;
// draw line one pixel at a time
for (index=0; index<=y2-y1; index++)
{
// set the pixel
*start_offset = (UCHAR)color;
// move downward to next line
start_offset+=lpitch;
} // end for index
} // end VLine
///////////////////////////////////////////////////////////
inline void Mem_Set_WORD(void *dest, USHORT data, int count)
{
// this function fills or sets unsigned 16-bit aligned memory
// count is number of words
_asm
{
mov edi, dest ; edi points to destination memory
mov ecx, count ; number of 16-bit words to move
mov ax, data ; 16-bit data
rep stosw ; move data
} // end asm
} // end Mem_Set_WORD
/////////////////////////////////////////////////////////////
void HLine16(int x1,int x2,int y,int color, UCHAR *vbuffer, int lpitch)
{
// draw a horizontal line using the memset function
int temp; // used for temporary storage during endpoint swap
USHORT *vbuffer2 = (USHORT *)vbuffer; // short pointer to buffer
// convert pitch to words
lpitch = lpitch >> 1;
// perform trivial rejections
if (y > max_clip_y || y < min_clip_y)
return;
// sort x1 and x2, so that x2 > x1
if (x1>x2)
{
temp = x1;
x1 = x2;
x2 = temp;
} // end swap
// perform trivial rejections
if (x1 > max_clip_x || x2 < min_clip_x)
return;
// now clip
x1 = ((x1 < min_clip_x) ? min_clip_x : x1);
x2 = ((x2 > max_clip_x) ? max_clip_x : x2);
// draw the row of pixels
Mem_Set_WORD((vbuffer2+(y*lpitch)+x1), color,x2-x1+1);
} // end HLine16
//////////////////////////////////////////////////////////////////////////////
void VLine16(int y1,int y2,int x,int color,UCHAR *vbuffer, int lpitch)
{
// draw a vertical line, note that a memset function can no longer be
// used since the pixel addresses are no longer contiguous in memory
// note that the end points of the line must be on the screen
USHORT *start_offset; // starting memory offset of line
int index, // loop index
temp; // used for temporary storage during swap
// convert lpitch to number of words
lpitch = lpitch >> 1;
// perform trivial rejections
if (x > max_clip_x || x < min_clip_x)
return;
// make sure y2 > y1
if (y1>y2)
{
temp = y1;
y1 = y2;
y2 = temp;
} // end swap
// perform trivial rejections
if (y1 > max_clip_y || y2 < min_clip_y)
return;
// now clip
y1 = ((y1 < min_clip_y) ? min_clip_y : y1);
y2 = ((y2 > max_clip_y) ? max_clip_y : y2);
// compute starting position
start_offset = (USHORT *)vbuffer + (y1*lpitch) + x;
// draw line one pixel at a time
for (index=0; index<=y2-y1; index++)
{
// set the pixel
*start_offset = color;
// move downward to next line
start_offset+=lpitch;
} // end for index
} // end VLine16
///////////////////////////////////////////////////////////
void Screen_Transitions(int effect, UCHAR *vbuffer, int lpitch)
{
// this function can be called to perform a myraid of screen transitions
// to the destination buffer, make sure to save and restore the palette
// when performing color transitions
int pal_reg; // used as loop counter
int index; // used as loop counter
int red,green,blue; // used in fad algorithm
PALETTEENTRY color; // temporary color
PALETTEENTRY work_palette[256]; // used as a working palette
PALETTEENTRY work_color; // used in color algorithms
// test which screen effect is being selected
switch(effect)
{
case SCREEN_DARKNESS:
{
// fade to black
for (index=0; index<80; index++)
{
// get the palette
Save_Palette(work_palette);
// process each color
for (pal_reg=1; pal_reg<256; pal_reg++)
{
// get the entry data
color = work_palette[pal_reg];
// test if this color register is already black
if (color.peRed > 4) color.peRed-=3;
else
color.peRed = 0;
if (color.peGreen > 4) color.peGreen-=3;
else
color.peGreen = 0;
if (color.peBlue > 4) color.peBlue-=3;
else
color.peBlue = 0;
// set the color to a diminished intensity
work_palette[pal_reg] = color;
} // end for pal_reg
// write the palette back out
Set_Palette(work_palette);
// wait a bit
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
} // end for index
} break;
case SCREEN_WHITENESS:
{
// fade to white
for (index=0; index<64; index++)
{
// get the palette
Save_Palette(work_palette);
// loop thru all palette registers
for (pal_reg=0; pal_reg < 256; pal_reg++)
{
// get the entry data
color = work_palette[pal_reg];
// make 32 bit copy of color
red = color.peRed;
green = color.peGreen;
blue = color.peBlue;
if ((red+=4) >=255)
red=255;
if ((green+=4) >=255)
green=255;
if ((blue+=4) >=255)
blue=255;
// store colors back
color.peRed = red;
color.peGreen = green;
color.peBlue = blue;
// set the color to a diminished intensity
work_palette[pal_reg] = color;
} // end for pal_reg
// write the palette back out
Set_Palette(work_palette);
// wait a bit
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
} // end for index
} break;
case SCREEN_REDNESS:
{
// fade to red
for (index=0; index<64; index++)
{
// get the palette
Save_Palette(work_palette);
// loop thru all palette registers
for (pal_reg=0; pal_reg < 256; pal_reg++)
{
// get the entry data
color = work_palette[pal_reg];
// make 32 bit copy of color
red = color.peRed;
green = color.peGreen;
blue = color.peBlue;
if ((red+=6) >=255)
red=255;
if ((green-=4) < 0)
green=0;
if ((blue-=4) < 0)
blue=0;
// store colors back
color.peRed = red;
color.peGreen = green;
color.peBlue = blue;
// set the color to a diminished intensity
work_palette[pal_reg] = color;
} // end for pal_reg
// write the palette back out
Set_Palette(work_palette);
// wait a bit
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
} // end for index
} break;
case SCREEN_BLUENESS:
{
// fade to blue
for (index=0; index<64; index++)
{
// get the palette
Save_Palette(work_palette);
// loop thru all palette registers
for (pal_reg=0; pal_reg < 256; pal_reg++)
{
// get the entry data
color = work_palette[pal_reg];
// make 32 bit copy of color
red = color.peRed;
green = color.peGreen;
blue = color.peBlue;
if ((red-=4) < 0)
red=0;
if ((green-=4) < 0)
green=0;
if ((blue+=6) >=255)
blue=255;
// store colors back
color.peRed = red;
color.peGreen = green;
color.peBlue = blue;
// set the color to a diminished intensity
work_palette[pal_reg] = color;
} // end for pal_reg
// write the palette back out
Set_Palette(work_palette);
// wait a bit
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
} // end for index
} break;
case SCREEN_GREENNESS:
{
// fade to green
for (index=0; index<64; index++)
{
// get the palette
Save_Palette(work_palette);
// loop thru all palette registers
for (pal_reg=0; pal_reg < 256; pal_reg++)
{
// get the entry data
color = work_palette[pal_reg];
// make 32 bit copy of color
red = color.peRed;
green = color.peGreen;
blue = color.peBlue;
if ((red-=4) < 0)
red=0;
if ((green+=6) >=255)
green=255;
if ((blue-=4) < 0)
blue=0;
// store colors back
color.peRed = red;
color.peGreen = green;
color.peBlue = blue;
// set the color to a diminished intensity
work_palette[pal_reg] = color;
} // end for pal_reg
// write the palette back out
Set_Palette(work_palette);
// wait a bit
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
} // end for index
} break;
case SCREEN_SWIPE_X:
{
// do a screen wipe from right to left, left to right
for (index=0; index < (screen_width/2); index+=2)
{
// use this as a 1/70th of second time delay
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
// draw two vertical lines at opposite ends of the screen
VLine(0,(screen_height-1),(screen_width-1)-index,0,vbuffer,lpitch);
VLine(0,(screen_height-1),index,0,vbuffer,lpitch);
VLine(0,(screen_height-1),(screen_width-1)-(index+1),0,vbuffer,lpitch);
VLine(0,(screen_height-1),index+1,0,vbuffer,lpitch);
} // end for index
} break;
case SCREEN_SWIPE_Y:
{
// do a screen wipe from top to bottom, bottom to top
for (index=0; index < (screen_height/2); index+=2)
{
// use this as a 1/70th of second time delay
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
// draw two horizontal lines at opposite ends of the screen
HLine(0,(screen_width-1),(screen_height-1)-index,0,vbuffer,lpitch);
HLine(0,(screen_width-1),index,0,vbuffer,lpitch);
HLine(0,(screen_width-1),(screen_height-1)-(index+1),0,vbuffer,lpitch);
HLine(0,(screen_width-1),index+1,0,vbuffer,lpitch);
} // end for index
} break;
case SCREEN_SCRUNCH:
{
// do a screen wipe from top to bottom, bottom to top
for (index=0; index < (screen_width/2); index+=2)
{
// use this as a 1/70th of second time delay
//DD_Wait_For_Vsync();
Start_Clock(); Wait_Clock(12);
// draw two horizontal lines at opposite ends of the screen
HLine(0,(screen_width-1),(screen_height-1)-index%(screen_height/2),0,vbuffer,lpitch);
HLine(0,(screen_width-1),index%(screen_height/2),0,vbuffer,lpitch);
HLine(0,(screen_width-1),(screen_height-1)-(index%(screen_height/2)+1),0,vbuffer,lpitch);
HLine(0,(screen_width-1),index%(screen_height/2)+1,0,vbuffer,lpitch);
// draw two vertical lines at opposite ends of the screen
VLine(0,(screen_height-1),(screen_width-1)-index,0,vbuffer,lpitch);
VLine(0,(screen_height-1),index,0,vbuffer,lpitch);
VLine(0,(screen_height-1),(screen_width-1)-(index+1),0,vbuffer,lpitch);
VLine(0,(screen_height-1),index+1,0,vbuffer,lpitch);
} // end for index
} break;
case SCREEN_DISOLVE:
{
// disolve the screen by plotting zillions of little black dots
for (index=0; index<=screen_width*screen_height*4; index++)
Draw_Pixel(rand()%screen_width,rand()%screen_height,0,vbuffer,lpitch);
} break;
default:break;
} // end switch
} // end Screen_Transitions
//////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK DI_Enum_Joysticks(LPCDIDEVICEINSTANCE lpddi,
LPVOID guid_ptr)
{
// this function enumerates the joysticks, but
// stops at the first one and returns the
// instance guid of it, so we can create it
*(GUID*)guid_ptr = lpddi->guidInstance;
// copy name into global
strcpy(joyname, (char *)lpddi->tszProductName);
// stop enumeration after one iteration
return(DIENUM_STOP);
} // end DI_Enum_Joysticks
//////////////////////////////////////////////////////////////////////////////
int DInput_Init(void)
{
// this function initializes directinput
if (DirectInput8Create(main_instance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void **)&lpdi,NULL)!=DI_OK)
return(0);
// return success
return(1);
} // end DInput_Init
///////////////////////////////////////////////////////////
void DInput_Shutdown(void)
{
// this function shuts down directinput
if (lpdi)
lpdi->Release();
} // end DInput_Shutdown
///////////////////////////////////////////////////////////
int DI_Init_Joystick(int min_x, int max_x, int min_y, int max_y)
{
// this function initializes the joystick, it allows you to set
// the minimum and maximum x-y ranges
// first find the fucking GUID of your particular joystick
lpdi->EnumDevices(DI8DEVCLASS_GAMECTRL,
DI_Enum_Joysticks,
&joystickGUID,
DIEDFL_ATTACHEDONLY);
if (lpdi->CreateDevice(joystickGUID, &lpdijoy, NULL)!=DI_OK)
return(0);
// set cooperation level
if (lpdijoy->SetCooperativeLevel(main_window_handle,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
return(0);
// set data format
if (lpdijoy->SetDataFormat(&c_dfDIJoystick)!=DI_OK)
return(0);
// set the range of the joystick
DIPROPRANGE joy_axis_range;
// first x axis
joy_axis_range.lMin = min_x;
joy_axis_range.lMax = max_x;
joy_axis_range.diph.dwSize = sizeof(DIPROPRANGE);
joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
joy_axis_range.diph.dwObj = DIJOFS_X;
joy_axis_range.diph.dwHow = DIPH_BYOFFSET;
lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);
// now y-axis
joy_axis_range.lMin = min_y;
joy_axis_range.lMax = max_y;
joy_axis_range.diph.dwSize = sizeof(DIPROPRANGE);
joy_axis_range.diph.dwHeaderSize = sizeof(DIPROPHEADER);
joy_axis_range.diph.dwObj = DIJOFS_Y;
joy_axis_range.diph.dwHow = DIPH_BYOFFSET;
lpdijoy->SetProperty(DIPROP_RANGE,&joy_axis_range.diph);
// acquire the joystick
if (lpdijoy->Acquire()!=DI_OK)
return(0);
// set found flag
joystick_found = 1;
// return success
return(1);
} // end DI_Init_Joystick
///////////////////////////////////////////////////////////
int DI_Init_Mouse(void)
{
// this function intializes the mouse
// create a mouse device
if (lpdi->CreateDevice(GUID_SysMouse, &lpdimouse, NULL)!=DI_OK)
return(0);
// set cooperation level
if (lpdimouse->SetCooperativeLevel(main_window_handle,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
return(0);
// set data format
if (lpdimouse->SetDataFormat(&c_dfDIMouse)!=DI_OK)
return(0);
// acquire the mouse
if (lpdimouse->Acquire()!=DI_OK)
return(0);
// return success
return(1);
} // end DI_Init_Mouse
///////////////////////////////////////////////////////////
int DI_Init_Keyboard(void)
{
// this function initializes the keyboard device
// create the keyboard device
if (lpdi->CreateDevice(GUID_SysKeyboard, &lpdikey, NULL)!=DI_OK)
return(0);
// set cooperation level
if (lpdikey->SetCooperativeLevel(main_window_handle,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)!=DI_OK)
return(0);
// set data format
if (lpdikey->SetDataFormat(&c_dfDIKeyboard)!=DI_OK)
return(0);
// acquire the keyboard
if (lpdikey->Acquire()!=DI_OK)
return(0);
// return success
return(1);
} // end DI_Init_Keyboard
///////////////////////////////////////////////////////////
int DI_Read_Joystick(void)
{
// this function reads the joystick state
// make sure the joystick was initialized
if (!joystick_found)
return(0);
if (lpdijoy)
{
// this is needed for joysticks only
if (lpdijoy->Poll()!=DI_OK)
return(0);
if (lpdijoy->GetDeviceState(sizeof(DIJOYSTATE), (LPVOID)&joy_state)!=DI_OK)
return(0);
}
else
{
// joystick isn't plugged in, zero out state
memset(&joy_state,0,sizeof(joy_state));
// return error
return(0);
} // end else
// return sucess
return(1);
} // end DI_Read_Joystick
///////////////////////////////////////////////////////////
int DI_Read_Mouse(void)
{
// this function reads the mouse state
if (lpdimouse)
{
if (lpdimouse->GetDeviceState(sizeof(DIMOUSESTATE), (LPVOID)&mouse_state)!=DI_OK)
return(0);
}
else
{
// mouse isn't plugged in, zero out state
memset(&mouse_state,0,sizeof(mouse_state));
// return error
return(0);
} // end else
// return sucess
return(1);
} // end DI_Read_Mouse
///////////////////////////////////////////////////////////
int DI_Read_Keyboard(void)
{
// this function reads the state of the keyboard
if (lpdikey)
{
if (lpdikey->GetDeviceState(256, (LPVOID)keyboard_state)!=DI_OK)
return(0);
}
else
{
// keyboard isn't plugged in, zero out state
memset(keyboard_state,0,sizeof(keyboard_state));
// return error
return(0);
} // end else
// return sucess
return(1);
} // end DI_Read_Keyboard
///////////////////////////////////////////////////////////
void DI_Release_Joystick(void)
{
// this function unacquires and releases the joystick
if (lpdijoy)
{
lpdijoy->Unacquire();
lpdijoy->Release();
} // end if
} // end DI_Release_Joystick
///////////////////////////////////////////////////////////
void DI_Release_Mouse(void)
{
// this function unacquires and releases the mouse
if (lpdimouse)
{
lpdimouse->Unacquire();
lpdimouse->Release();
} // end if
} // end DI_Release_Mouse
///////////////////////////////////////////////////////////
void DI_Release_Keyboard(void)
{
// this function unacquires and releases the keyboard
if (lpdikey)
{
lpdikey->Unacquire();
lpdikey->Release();
} // end if
} // end DI_Release_Keyboard
///////////////////////////////////////////////////////////
int Clone_BOBX(BOB_PTR source, BOB_PTR dest)
{
// this function clones a BOB and updates the attr var to reflect that
// the BOB is a clone and not real, this is used later in the destroy
// function so a clone doesn't destroy the memory of a real bob
if (source && dest)
{
// copy the bob data
memcpy(dest,source, sizeof(BOB));
// set the clone attribute
dest->attr |= BOB_ATTR_CLONE;
} // end if
else
return(0);
// return success
return(1);
} // end Clone_BOBX
///////////////////////////////////////////////////////////
int Destroy_BOBX(BOB_PTR bob)
{
// destroy the BOB, tests if this is a real bob or a clone
// if real then release all the memory, otherwise, just resets
// the pointers to null
int index; // looping var
// is this bob valid
if (!bob)
return(0);
// test if this is a clone
if (bob->attr && BOB_ATTR_CLONE)
{
// null link all surfaces
for (index=0; index<MAX_BOB_FRAMES; index++)
if (bob->images[index])
bob->images[index]=NULL;
// release memory for animation sequences
for (index=0; index<MAX_BOB_ANIMATIONS; index++)
if (bob->animations[index])
bob->animations[index]=NULL;
} // end if
else
{
// destroy each bitmap surface
for (index=0; index<MAX_BOB_FRAMES; index++)
if (bob->images[index])
(bob->images[index])->Release();
// release memory for animation sequences
for (index=0; index<MAX_BOB_ANIMATIONS; index++)
if (bob->animations[index])
free(bob->animations[index]);
} // end else not clone
// return success
return(1);
} // end Destroy_BOBX
///////////////////////////////////////////////////////////
int Collision_Test(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2)
{
// this function tests if the two rects overlap
// get the radi of each rect
int width1 = (w1>>1) - (w1>>3);
int height1 = (h1>>1) - (h1>>3);
int width2 = (w2>>1) - (w2>>3);
int height2 = (h2>>1) - (h2>>3);
// compute center of each rect
int cx1 = x1 + width1;
int cy1 = y1 + height1;
int cx2 = x2 + width2;
int cy2 = y2 + height2;
// compute deltas
int dx = abs(cx2 - cx1);
int dy = abs(cy2 - cy1);
// test if rects overlap
if (dx < (width1+width2) && dy < (height1+height2))
return(1);
else
// else no collision
return(0);
} // end Collision_Test
///////////////////////////////////////////////////////////
int Color_Scan(int x1, int y1, int x2, int y2,
UCHAR scan_start, UCHAR scan_end,
UCHAR *scan_buffer, int scan_lpitch)
{
// this function implements a crude collision technique
// based on scanning for a range of colors within a rectangle
// clip rectangle
// x coords first
if (x1 >= screen_width)
x1=screen_width-1;
else
if (x1 < 0)
x1=0;
if (x2 >= screen_width)
x2=screen_width-1;
else
if (x2 < 0)
x2=0;
// now y-coords
if (y1 >= screen_height)
y1=screen_height-1;
else
if (y1 < 0)
y1=0;
if (y2 >= screen_height)
y2=screen_height-1;
else
if (y2 < 0)
y2=0;
// scan the region
scan_buffer +=y1*scan_lpitch;
for (int scan_y=y1; scan_y<=y2; scan_y++)
{
for (int scan_x=x1; scan_x<=x2; scan_x++)
{
if (scan_buffer[scan_x] >= scan_start && scan_buffer[scan_x] <= scan_end )
return(1);
} // end for x
// move down a line
scan_buffer+=scan_lpitch;
} // end for y
// return failure
return(0);
} // end Color_Scan
////////////////////////////////////////////////////////////////
int Color_Scan16(int x1, int y1, int x2, int y2,
USHORT scan_start, USHORT scan_end,
UCHAR *scan_buffer, int scan_lpitch)
{
// this function implements a crude collision technique
// based on scanning for a range of colors within a rectangle
// this is the 16-bit version, thus the interpretation of scan_start
// and end are different, they are they EXACT RGB values you are looking
// for, thus you can test for 2 values at most, else make them equal to
// test for one value
USHORT *scan_buffer2 = (USHORT *)scan_buffer;
// convert number of bytes per line to number of 16-bit shorts
scan_lpitch = (scan_lpitch >> 1);
// clip rectangle
// x coords first
if (x1 >= screen_width)
x1=screen_width-1;
else
if (x1 < 0)
x1=0;
if (x2 >= screen_width)
x2=screen_width-1;
else
if (x2 < 0)
x2=0;
// now y-coords
if (y1 >= screen_height)
y1=screen_height-1;
else
if (y1 < 0)
y1=0;
if (y2 >= screen_height)
y2=screen_height-1;
else
if (y2 < 0)
y2=0;
// scan the region
scan_buffer2 +=y1*scan_lpitch;
for (int scan_y=y1; scan_y<=y2; scan_y++)
{
for (int scan_x=x1; scan_x<=x2; scan_x++)
{
if (scan_buffer2[scan_x] == scan_start || scan_buffer2[scan_x] == scan_end )
return(1);
} // end for x
// move down a line
scan_buffer2+=scan_lpitch;
} // end for y
// return failure
return(0);
} // end Color_Scan16
////////////////////////////////////////////////////////