⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo8_9.cpp

📁 《Windows游戏编程大师技巧(第二版)》源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// DEMO8_9.CPP 8-bit general polygon fill demo

// INCLUDES ///////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN  // just say no to MFC

#define INITGUID

#include <windows.h>   // include important windows stuff
#include <windowsx.h> 
#include <mmsystem.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> // include directdraw

// DEFINES ////////////////////////////////////////////////

// defines for windows 
#define WINDOW_CLASS_NAME "WINCLASS1"

// default screen size
#define SCREEN_WIDTH    640  // size of screen
#define SCREEN_HEIGHT   480
#define SCREEN_BPP      8    // bits per pixel

#define BITMAP_ID            0x4D42 // universal id for a bitmap
#define MAX_COLORS_PALETTE   256

const double PI = 3.1415926535;

// TYPES //////////////////////////////////////////////////////

// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char  UCHAR;
typedef unsigned char  BYTE;

// a 2D vertex
typedef struct VERTEX2DI_TYP
        {
        int x,y; // the vertex
        } VERTEX2DI, *VERTEX2DI_PTR;

// a 2D vertex
typedef struct VERTEX2DF_TYP
        {
        float x,y; // the vertex
        } VERTEX2DF, *VERTEX2DF_PTR;


// a 2D polygon
typedef struct POLYGON2D_TYP
        {
        int state;        // state of polygon
        int num_verts;    // number of vertices
        int x0,y0;        // position of center of polygon  
        int xv,yv;        // initial velocity
        DWORD color;      // could be index or PALETTENTRY
        VERTEX2DF *vlist; // pointer to vertex list
 
        } POLYGON2D, *POLYGON2D_PTR;


// PROTOTYPES  //////////////////////////////////////////////

int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color);

void Draw_Filled_Polygon2D(POLYGON2D_PTR poly, UCHAR *vbuffer, int mempitch);

int Translate_Polygon2D(POLYGON2D_PTR poly, int dx, int dy);

int Rotate_Polygon2D(POLYGON2D_PTR poly, int theta);

int Scale_Polygon2D(POLYGON2D_PTR poly, float sx, float sy);

int Set_Palette_Entry(int color_index, LPPALETTEENTRY color);

int Draw_Text_GDI(char *text, int x,int y,int color, LPDIRECTDRAWSURFACE7 lpdds);

// MACROS /////////////////////////////////////////////////

// tests if a key is up or down
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

// initializes a direct draw struct
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }

// some math macros
#define DEG_TO_RAD(ang) ((ang)*PI/180)
#define RAD_TO_DEG(rads) ((rads)*180/PI)

// GLOBALS ////////////////////////////////////////////////

HWND      main_window_handle = NULL; // globally track main window
int       window_closed      = 0;    // tracks if window is closed
HINSTANCE hinstance_app      = NULL; // globally track hinstance

// directdraw stuff
LPDIRECTDRAW7         lpdd         = NULL;   // dd object
LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface
LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface
LPDIRECTDRAWPALETTE   lpddpal      = NULL;   // a pointer to the created dd palette
LPDIRECTDRAWCLIPPER   lpddclipper  = NULL;   // dd clipper
PALETTEENTRY          palette[256];          // color palette
PALETTEENTRY          save_palette[256];     // used to save palettes
DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct
DDBLTFX               ddbltfx;               // used to fill
DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct
HRESULT               ddrval;                // result back from dd calls
DWORD                 start_clock_count = 0; // used for timing


// global clipping region

int min_clip_x = 0,      // clipping rectangle 
    max_clip_x = SCREEN_WIDTH - 1,
    min_clip_y = 0,
    max_clip_y = SCREEN_HEIGHT - 1;

char buffer[80];                             // general printing buffer

// storage for our lookup tables
float cos_look[360];
float sin_look[360];

POLYGON2D object; // the polygon object

// FUNCTIONS ////////////////////////////////////////////////

int Draw_Text_GDI(char *text, int x,int y,int color, LPDIRECTDRAWSURFACE7 lpdds)
{
// this function draws the sent text on the sent surface 
// using color index as the color in the palette

HDC xdc; // the working dc

// get the dc from surface
if (FAILED(lpdds->GetDC(&xdc)))
   return(0);

// set the colors for the text up
SetTextColor(xdc,RGB(palette[color].peRed,palette[color].peGreen,palette[color].peBlue) );

// set background mode to transparent so black isn't copied
SetBkMode(xdc, TRANSPARENT);

// draw the text a
TextOut(xdc,x,y,text,strlen(text));

// release the dc
lpdds->ReleaseDC(xdc);

// return success
return(1);
} // end Draw_Text_GDI

///////////////////////////////////////////////////////////////////


int Set_Palette_Entry(int color_index, LPPALETTEENTRY color)
{
// this function sets a palette color in the palette
lpddpal->SetEntries(0,color_index,1,color);

// set data in shadow palette
memcpy(&palette[color_index],color,sizeof(PALETTEENTRY));

// return success
return(1);
} // end Set_Palette_Entry

///////////////////////////////////////////////////////////


void Draw_Filled_Polygon2D(POLYGON2D_PTR poly, UCHAR *vbuffer, int mempitch)
{
// this function draws a general n sided polygon 

int ydiff1, ydiff2,         // difference between starting x and ending x
	xdiff1, xdiff2,         // difference between starting y and ending y
    start,                  // starting offset of line between edges
	length,                 // distance from edge 1 to edge 2
	errorterm1, errorterm2, // error terms for edges 1 & 2
    offset1, offset2,       // offset of current pixel in edges 1 & 2
	count1, count2,         // increment count for edges 1 & 2
    xunit1, xunit2;         // unit to advance x offset for edges 1 & 2

// initialize count of number of edges drawn:
int edgecount = poly->num_verts-1;

// determine which vertex is at top of polygon:

int firstvert=0;         // start by assuming vertex 0 is at top

int min_y=poly->vlist[0].y; // find y coordinate of vertex 0

for (int index=1; index < poly->num_verts; index++) 
    {  
    // Search thru vertices
 	if ((poly->vlist[index].y) < min_y) 
        {  
        // is another vertex higher?
		firstvert=index;                   
		min_y=poly->vlist[index].y;
		} // end if

	} // end for index

// finding starting and ending vertices of first two edges:
int startvert1=firstvert;      // get starting vertex of edge 1
int startvert2=firstvert;      // get starting vertex of edge 2
int xstart1=poly->vlist[startvert1].x+poly->x0;
int ystart1=poly->vlist[startvert1].y+poly->y0;
int xstart2=poly->vlist[startvert2].x+poly->x0;
int ystart2=poly->vlist[startvert2].y+poly->y0;
int endvert1=startvert1-1;           // get ending vertex of edge 1

if (endvert1 < 0) 
   endvert1=poly->num_verts-1;    // check for wrap

int xend1=poly->vlist[endvert1].x+poly->x0;      // get x & y coordinates
int yend1=poly->vlist[endvert1].y+poly->y0;      // of ending vertices
int endvert2=startvert2+1;           // get ending vertex of edge 2

if (endvert2==(poly->num_verts)) 
    endvert2=0;  // Check for wrap

int xend2=poly->vlist[endvert2].x+poly->x0;      // get x & y coordinates
int yend2=poly->vlist[endvert2].y+poly->y0;      // of ending vertices

// draw the polygon:

while (edgecount>0) 
      {    
      // continue drawing until all edges drawn
	  offset1=mempitch*ystart1+xstart1;  // offset of edge 1
	  offset2=mempitch*ystart2+xstart2;  // offset of edge 2
	  
      // initialize error terms
      // for edges 1 & 2
      errorterm1=0;        
	  errorterm2=0;           

      // get absolute value of
   	  if ((ydiff1=yend1-ystart1) < 0) 
         ydiff1=-ydiff1;

      // x & y lengths of edges
	  if ((ydiff2=yend2-ystart2) < 0) 
         ydiff2=-ydiff2; 

  	  if ((xdiff1=xend1-xstart1) < 0) 
         {               
         // get value of length
		 xunit1=-1;                    // calculate X increment
		 xdiff1=-xdiff1;
		 } // end if
	  else 
         {
		 xunit1=1;
		 } // end else

   	  if ((xdiff2=xend2-xstart2) < 0) 
         {
         // Get value of length
  		 xunit2=-1;                   // calculate X increment
		 xdiff2=-xdiff2;
		 } // end else
	  else 
         {
		 xunit2=1;
		 } // end else

	  // choose which of four routines to use
	  if (xdiff1 > ydiff1) 
         {    
         // if x length of edge 1 is greater than y length
		 if (xdiff2 > ydiff2) 
            {  
            // if X length of edge 2 is greater than y length

			// increment edge 1 on X and edge 2 on X:
			count1=xdiff1;    // count for x increment on edge 1
			count2=xdiff2;    // count for x increment on edge 2

			while (count1 && count2) 
                  {  
                  // continue drawing until one edge is done
    			  // calculate edge 1:
  				  while ((errorterm1 < xdiff1) && (count1 > 0)) 
                        { 
                        // finished w/edge 1?
						if (count1--) 
                           {     
                           // count down on edge 1
						   offset1+=xunit1;  // increment pixel offset
						   xstart1+=xunit1;
						   } // end if

  				        errorterm1+=ydiff1; // increment error term

 				        if (errorterm1 < xdiff1) 
                           {  // if not more than XDIFF
					       vbuffer[offset1]=(UCHAR)poly->color; // ...plot a pixel
					       } // end if

					     } // end while
					
                  errorterm1-=xdiff1; // if time to increment X, restore error term

			      // calculate edge 2:

				  while ((errorterm2 < xdiff2) && (count2 > 0)) 
                        {  
                        // finished w/edge 2?
						if (count2--) 
                           {     
                           // count down on edge 2
						   offset2+=xunit2;  // increment pixel offset
						   xstart2+=xunit2;
						   } // end if

  						  errorterm2+=ydiff2; // increment error term

						  if (errorterm2 < xdiff2) 
                             {  // if not more than XDIFF
							 vbuffer[offset2]=(UCHAR)poly->color;  // ...plot a pixel
						     } // end if

  					       } // end while

					errorterm2-=xdiff2; // if time to increment X, restore error term

			        // draw line from edge 1 to edge 2:

					length=offset2-offset1; // determine length of horizontal line

					if (length < 0) 
                       { // if negative...
					   length=-length;       // make it positive
					   start=offset2;        // and set START to edge 2
  				       } // end if
					else 
                       start=offset1;     // else set START to edge 1
			 
              for (int index=start; index < start+length+1; index++)
                  {  // From edge to edge...
    			  vbuffer[index]=(UCHAR)poly->color;         // ...draw the line
                  } // end for index

				offset1+=mempitch;           // advance edge 1 offset to next line
  			    ystart1++;
				offset2+=mempitch;           // advance edge 2 offset to next line

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -