📄 raiders3d_2b.cpp
字号:
(WINDOWED_APP ? (WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION) : (WS_POPUP | WS_VISIBLE)),
0,0, // x,y
WINDOW_WIDTH, // width
WINDOW_HEIGHT, // height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance
NULL))) // creation parms
return(0);
// save the window handle and instance in a global
main_window_handle = hwnd;
main_instance = hinstance;
// resize the window so that client is really width x height
if (WINDOWED_APP)
{
// now resize the window, so the client area is the actual size requested
// since there may be borders and controls if this is going to be a windowed app
// if the app is not windowed then it won't matter
RECT window_rect = {0,0,WINDOW_WIDTH-1,WINDOW_HEIGHT-1};
// make the call to adjust window_rect
AdjustWindowRectEx(&window_rect,
GetWindowStyle(main_window_handle),
GetMenu(main_window_handle) != NULL,
GetWindowExStyle(main_window_handle));
// save the global client offsets, they are needed in DDraw_Flip()
window_client_x0 = -window_rect.left;
window_client_y0 = -window_rect.top;
// now resize the window with a call to MoveWindow()
MoveWindow(main_window_handle,
0, // x position
0, // y position
window_rect.right - window_rect.left, // width
window_rect.bottom - window_rect.top, // height
FALSE);
// show the window, so there's no garbage on first render
ShowWindow(main_window_handle, SW_SHOW);
} // end if windowed
// perform all game console specific initialization
Game_Init();
// disable CTRL-ALT_DEL, ALT_TAB, comment this line out
// if it causes your system to crash
SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, NULL, 0);
// enter main event loop
while(1)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
Game_Main();
} // end while
// shutdown game and release all resources
Game_Shutdown();
// enable CTRL-ALT_DEL, ALT_TAB, comment this line out
// if it causes your system to crash
SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, NULL, 0);
// return to Windows like this
return(msg.wParam);
} // end WinMain
////////////////////////////////////////////////////////////////////
void Render_Energy_Bindings(POINT2D_PTR bindings, // array containing binding positions in the form
// start point, end point, start point, end point...
int num_bindings, // number of energy bindings to render 1-3
int num_segments, // number of segments to randomize bindings into
int amplitude, // amplitude of energy binding
int color, // color of bindings
UCHAR *video_buffer, // video buffer to render
int lpitch) // memory pitch of buffer
{
// this functions renders the energy bindings across the main exterior energy
// transmission emitters :) Basically, the function takes two points in 2d then
// it anchors a line at the two ends and randomly walks from end point to the
// other by breaking the line into segments and then randomly modulating the y position
// and amount amplitude +-, maximum number of segments 16
POINT2D segments[17]; // to hold constructed segments after construction
// render each binding
for (int index = 0; index < num_bindings; index++)
{
// store starting and ending positions
// starting position
segments[0] = bindings[index*2];
// ending position
segments[num_segments] = bindings[index*2+1];
// compute vertical gradient, so if y positions of endpoints are
// greatly different bindings will be modulated using the straight line
// as a basis
float dyds = (segments[num_segments].y - segments[0].y) / (float)num_segments;
float dxds = (segments[num_segments].x - segments[0].x) / (float)num_segments;
// now build up segments
for (int sindex = 1; sindex < num_segments; sindex++)
{
segments[sindex].x = segments[sindex-1].x + dxds;
segments[sindex].y = segments[0].y + sindex*dyds + RAND_RANGE(-amplitude, amplitude);
} // end for segment
// draw binding
for (sindex = 0; sindex < num_segments; sindex++)
Draw_Line16(segments[sindex].x, segments[sindex].y,
segments[sindex+1].x, segments[sindex+1].y,
color, video_buffer, lpitch);
} // end for index
} // end Render_Energy_Binding
////////////////////////////////////////////////////////////////////
void Render_Weapon_Bursts(POINT2D_PTR burstpoints, // array containing energy burst positions in the form
// start point, end point, start point, end point...
int num_bursts,
int num_segments, // number of segments to randomize bindings into
int amplitude, // amplitude of energy binding
int color, // color of bindings
UCHAR *video_buffer, // video buffer to render
int lpitch) // memory pitch of buffer
{
// this functions renders the weapon energy bursts from the weapon emitter or wherever
// function derived from Render_Energy_Binding, but generalized
// Basically, the function takes two points in 2d then
// it anchors a line at the two ends and randomly walks from end point to the
// other by breaking the line into segments and then randomly modulating the x,y position
// and amount amplitude +-, maximum number of segments 16
POINT2D segments[17]; // to hold constructed segments after construction
// render each energy burst
for (int index = 0; index < num_bursts; index++)
{
// store starting and ending positions
// starting position
segments[0] = burstpoints[index*2];
// ending position
segments[num_segments] = burstpoints[index*2+1];
// compute horizontal/vertical gradients, so we can modulate the lines
// on the proper trajectory
float dyds = (segments[num_segments].y - segments[0].y) / (float)num_segments;
float dxds = (segments[num_segments].x - segments[0].x) / (float)num_segments;
// now build up segments
for (int sindex = 1; sindex < num_segments; sindex++)
{
segments[sindex].x = segments[0].x + sindex*dxds + RAND_RANGE(-amplitude, amplitude);
segments[sindex].y = segments[0].y + sindex*dyds + RAND_RANGE(-amplitude, amplitude);
} // end for segment
// draw binding
for (sindex = 0; sindex < num_segments; sindex++)
Draw_Line16(segments[sindex].x, segments[sindex].y,
segments[sindex+1].x, segments[sindex+1].y,
color, video_buffer, lpitch);
} // end for index
} // end Render_Weapons_Bursts
///////////////////////////////////////////////////////////////
int Load_Bitmap_Font(char *fontfile, BOB_PTR font)
{
// this is a semi generic font loader...
// expects the file name of a font in a template that is
// 4 rows of 16 cells, each character is 16x14, and cell 0 is the space character
// characters from 32 to 95, " " to "-", suffice for 90% of text work
// load the font bitmap template
if (!Load_Bitmap_File(&bitmap16bit, fontfile))
return(0);
// create the bob that will hold the font, use a bob for speed, we can use the
// hardware blitter
Create_BOB(font, 0,0,16,14,64, BOB_ATTR_VISIBLE | BOB_ATTR_SINGLE_FRAME, DDSCAPS_SYSTEMMEMORY, 0, 16);
// load all the frames
for (int index=0; index < 64; index++)
Load_Frame_BOB16(font, &bitmap16bit,index,index%16,index/16,BITMAP_EXTRACT_MODE_CELL);
// unload the bitmap file
Unload_Bitmap_File(&bitmap16bit);
// return success
return(1);
} // end Load_Bitmap_Font
///////////////////////////////////////////////////////////////
int Draw_Bitmap_Font_String(BOB_PTR font, // pointer to bob containing font
int x, int y, // screen position to render
char *string, // string to render
int hpitch, int vpitch, // horizontal and vertical pitch
LPDIRECTDRAWSURFACE7 dest) // destination surface
{
// this function draws a string based on a 64 character font sent in as a bob
// the string will be drawn at the given x,y position with intercharacter spacing
// if hpitch and a interline spacing of vpitch
// are things semi valid?
if (!string || !dest)
return(0);
// loop and render
for (int index = 0; index < strlen(string); index++)
{
// set the position and character
font->x = x;
font->y = y;
font->curr_frame = string[index] - 32;
// test for overflow set to space
if (font->curr_frame > 63 || font->curr_frame < 0) font->curr_frame = 0;
// render character (i hate making a function call!)
Draw_BOB16(font, dest);
// move position
x+=hpitch;
} // end for index
// return success
return(1);
} // end Draw_Bitmap_Font_String
/////////////////////////////////////////////////////////
int Start_Alien(void)
{
// this function hunts in the alien list, finds an available alien and
// starts it up
for (int index = 0; index < NUM_ALIENS; index++)
{
// is this alien available?
if (aliens[index].state == ALIEN_STATE_DEAD)
{
// clear any residual data
memset((void *)&aliens[index], 0, sizeof (ALIEN) );
// start alien up
aliens[index].state = ALIEN_STATE_ALIVE;
// select random position in bounding volume
aliens[index].pos.x = RAND_RANGE(-1000,1000);
aliens[index].pos.y = RAND_RANGE(-1000,1000);
aliens[index].pos.z = 20000;
// select velocity based on difficulty level
aliens[index].vel.x = RAND_RANGE(-10,10);
aliens[index].vel.y = RAND_RANGE(-10,10);
aliens[index].vel.z = -(10*diff_level+rand()%200);
// set rotation rate for z axis only
aliens[index].rot.z = RAND_RANGE(-5,5);
// return the index
return(index);
} // end if
} // end for index
// failure
return(-1);
} // end Start_Alien
/////////////////////////////////////////////////////////
void Init_Aliens(void)
{
// initializes all the ALIEN fighters to a known state
for (int index = 0; index < NUM_ALIENS; index++)
{
// zero ALIEN fighter out
memset((void *)&aliens[index], 0, sizeof (ALIEN) );
// set any other specific info now...
aliens[index].state = ALIEN_STATE_DEAD;
} // end for
} // end Init_Aliens
/////////////////////////////////////////////////////////
void Draw_Aliens(void)
{
// this function draws all the active ALIEN fighters
MATRIX4X4 mrot; // used to transform objects
for (int index = 0; index < NUM_ALIENS; index++)
{
// which state is alien in
switch(aliens[index].state)
{
// is the alien dead? if so move on
case ALIEN_STATE_DEAD: break;
// is the alien alive?
case ALIEN_STATE_ALIVE:
case ALIEN_STATE_DYING:
{
// reset the object (this only matters for backface and object removal)
Reset_OBJECT4DV2(&obj_alien);
// generate rotation matrix around y axis
Build_XYZ_Rotation_MATRIX4X4(aliens[index].ang.x, aliens[index].ang.y, aliens[index].ang.z ,&mrot);
// rotate the local coords of the object
Transform_OBJECT4DV2(&obj_alien, &mrot, TRANSFORM_LOCAL_TO_TRANS,1);
// set position of constant shaded cube
obj_alien.world_pos.x = aliens[index].pos.x;
obj_alien.world_pos.y = aliens[index].pos.y;
obj_alien.world_pos.z = aliens[index].pos.z;
// attempt to cull object
if (!Cull_OBJECT4DV2(&obj_alien, &cam, CULL_OBJECT_XYZ_PLANES))
{
// perform world transform
Model_To_World_OBJECT4DV2(&obj_alien, TRANSFORM_TRANS_ONLY);
// insert the object into render list
Insert_OBJECT4DV2_RENDERLIST4DV2(&rend_list, &obj_alien,0);
} // end if
// ok, now test for collision with energy bursts, strategy is as follows
// we will project the bounding box of the object into screen space to coincide with
// the energy burst on the screen, if there is an overlap then the target is hit
// simply need to do a few transforms, this kinda sucks that we are going to do this work
// 2x, but the problem is that the graphics pipeline knows nothing about collision etc.,
// so we can't "get to" the information me want since we are ripping the objects apart
// and passing them down the pipeline for a later world to camera transform, thus you
// may want to think about this problem when making your own game, how tight to couple
// collision and the engine, HOWEVER, the only reason we are having a problem at all is that
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -