Defend 射擊小遊戲教程

暑假準備做個小遊戲,在此把教程寫出來,希望對別人有幫助。
遊戲的基本想法:給你一把槍(實際是用直線代替的)在屏幕的正中央槍可以射出子彈(實際上也是用直線代替的(我承認我的圖形圖像很爛)),
然後四面八方會來怪物在怪物碰到你之前把它消滅,否則遊戲結束。
需要用到的SDK功能:計時器,鼠標,還有繪圖函數
準備工作:要有VC 6.0.然後文件->新建->選擇工程欄->選擇Win32 Application->選一個空的工程
然後再選文件->新建->選文件中的c++ source file->在添加到當前工程上打勾->起個名字->然後在File View裏的Source Files中就能找到
建的程序源文件瞭然後請把下面的模板粘上去。

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, //這是主函數裏面的東西不用管放着就行 
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("BlokOut2") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Mouse Button & Capture Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)//消息回調函數主要工作都是在這裏完成的 
{
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	switch (message)
	{
	case WM_SIZE :

		return 0;
	case WM_LBUTTONDOWN :
	
		return 0 ;
	case WM_LBUTTONUP :
	
		return 0;
	case WM_MOUSEMOVE :
		
		return 0 ;
	case WM_DESTROY :
		PostQuitMessage (0) ;
		return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}


首先要實現的功能就是槍跟着鼠標轉
先定義4個點變量ptBeg, ptEnd,moEnd,fmoEnd;分別表示槍的起始位置,指針的位置,槍的末端位置,槍的上一個末端位置
當鼠標移動時Windows會給 WM_MOUSEMOVE 發消息,這樣就能得到當前指針的位置,從而實現這一功能

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("BlokOut2") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Mouse Button & Capture Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static POINT ptBeg, ptEnd,moEnd,fmoEnd;
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	 double k;
	 int R=30;
	switch (message)
	{
	case WM_SIZE :  //當窗口被創建時windows會發消息到這裏 
		ptBeg.x=LOWORD(lParam)/2;//得到窗口的中間位置 LOWORD(lParam)是windows給的消息裏的窗口寬度,直接用就行,不用深究其中間過程 
		ptBeg.y=HIWORD(lParam)/2;//HIWORD(lParam)是窗口高度 注意窗口左上角的座標是0,0 
		return 0;
	case WM_LBUTTONDOWN :
	
		return 0 ;
	case WM_LBUTTONUP :
	
		return 0;
	case WM_MOUSEMOVE ://當鼠標移動時windows會發消息到這裏 
		hdc=GetDC(hwnd); //得到設備環境句柄,hwnd是窗口句柄,對窗口操作都需要這個,同樣不用深究知道就行,直接用 
		SelectObject(hdc,GetStockObject(WHITE_PEN)); //選擇白色畫筆 ,GetStockObject是用來得到畫筆的數值 
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);			//這是一個畫直線線函數 MoveToEx用來設置起始位置,參數1是設備環境句柄,參數2和3是我們上面求的中間位置,最後一個參數用不到 
		LineTo(hdc,fmoEnd.x,fmoEnd.y);				//LineTo用來設置線的終點位置,後兩個參數是上一個槍的終點位置,上面選擇白色畫筆也就是爲了把上一個槍擦除 
		k=sqrt(((LOWORD(lParam)-ptBeg.x)*(LOWORD(lParam)-ptBeg.x)
			+(HIWORD(lParam)-ptBeg.y)*(HIWORD(lParam)-ptBeg.y))
			/(double)(R*R));						//計算縮小倍數,LOWORD(lParam)得到當前鼠標的橫座標 HIWORD(lParam)得到縱座標R是槍的長度 
		if(k==0)
		{
			moEnd.x=ptBeg.x;
			moEnd.y=ptBeg.y;
		}
		else
		{
			moEnd.x=ptBeg.x+(LOWORD(lParam)-ptBeg.x)/k;
			moEnd.y=ptBeg.y+(HIWORD(lParam)-ptBeg.y)/k;	//的到槍的終點位置				
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));	//選擇黑色畫筆開始畫槍跟上面一樣就不多說了 
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,moEnd.x,moEnd.y);
		fmoEnd.x=moEnd.x;
		fmoEnd.y=moEnd.y;
		ReleaseDC(hwnd,hdc);		//釋放設備環境句柄 
		return 0 ;

	case WM_DESTROY :
		PostQuitMessage (0) ;
		return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}


然後就是子彈移動的效果這就要用到計時器
先定義一個子彈點數組 Shot[500][2] 儲存每個子彈的當前位置和子彈的長度。
爲計時器寫一個回調函數MyTimer處理子彈效果.

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("BlokOut2") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Mouse Button & Capture Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
POINT Shot[500][2],Boundary;
int nShot;
void CALLBACK MyTimer(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime) //這就是計時器的回調函數 
{
	HDC hdc=GetDC(hwnd);
	int i=0;
	SelectObject(hdc,GetStockObject(WHITE_PEN));	
	for(i=0;i<nShot;i++)  	//吧窗口中所有的子彈清除掉 
	{
		MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
		LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
	}
	for(i=0;i<nShot;i++)	//如果子彈到達邊界則清除子彈 
	{
		if(Shot[i][0].x>Boundary.x||Shot[i][0].x<0
			||Shot[i][0].y>Boundary.y||Shot[i][0].y<0)
		{
			int j=i;
			for(;j<nShot-1;j++)
			{
				Shot[j][0].x=Shot[j+1][0].x;
				Shot[j][0].y=Shot[j+1][0].y;
				Shot[j][1].x=Shot[j+1][1].x;
				Shot[j][1].y=Shot[j+1][1].y;
			}
			nShot--;
			i--;
		}
	}
	SelectObject(hdc,GetStockObject(BLACK_PEN));
	for(i=0;i<nShot;i++)	//把全部新的子彈畫在窗口裏 
	{
		Shot[i][0].x+=Shot[i][1].x/2;
		Shot[i][0].y+=Shot[i][1].y/2;
		MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
		LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
	}
	ReleaseDC(hwnd,hdc);
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static POINT ptBeg, ptEnd,moEnd,fmoEnd;
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	 double k;
	 int R=30;
	switch (message)
	{
	case WM_SIZE :
		nShot=0;
		SetTimer(hwnd,0,30,MyTimer);//設定計時器,參數1是窗口句柄,參數2是計時器編號,參數3是調用間隔,參數4是回調函數名字 
		ptBeg.x=LOWORD(lParam)/2;
		ptBeg.y=HIWORD(lParam)/2;
		Boundary.x=LOWORD(lParam);//把邊界保存下來爲子彈處理做準備 
		Boundary.y=HIWORD(lParam);
		return 0;
	case WM_LBUTTONDOWN ://鼠標左鍵點擊時windows會發消息到這裏 
		hdc=GetDC(hwnd);	//下面的代碼是畫子彈的起始位置細節跟前面一樣前面已經講過這裏就不多講了 
		ptEnd.x = GET_X_LPARAM (lParam) ;
		ptEnd.y = GET_Y_LPARAM (lParam) ;
		k=sqrt(((ptEnd.x-ptBeg.x)*(ptEnd.x-ptBeg.x)
			+(ptEnd.y-ptBeg.y)*(ptEnd.y-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			ptEnd.x=ptBeg.x;
			ptEnd.y=ptBeg.y;
		}
		else
		{
			ptEnd.x=ptBeg.x+(ptEnd.x-ptBeg.x)/k*2;
			ptEnd.y=ptBeg.y+(ptEnd.y-ptBeg.y)/k*2;					
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,(ptBeg.x+ptEnd.x)/2,(ptBeg.y+ptEnd.y)/2,NULL);
		LineTo(hdc,ptEnd.x,ptEnd.y);
		ReleaseDC(hwnd,hdc);
		Shot[nShot][0].x=(ptBeg.x+ptEnd.x)/2;	//保存子彈的起始位置 
		Shot[nShot][0].y=(ptBeg.y+ptEnd.y)/2;
		Shot[nShot][1].x=ptEnd.x-(ptEnd.x+ptBeg.x)/2;	//保存子彈的尺寸 
		Shot[nShot][1].y=ptEnd.y-(ptEnd.y+ptBeg.y)/2;
		nShot++;
		return 0 ;
	case WM_MOUSEMOVE :
		hdc=GetDC(hwnd); 
		SelectObject(hdc,GetStockObject(WHITE_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,fmoEnd.x,fmoEnd.y);
		k=sqrt(((LOWORD(lParam)-ptBeg.x)*(LOWORD(lParam)-ptBeg.x)
			+(HIWORD(lParam)-ptBeg.y)*(HIWORD(lParam)-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			moEnd.x=ptBeg.x;
			moEnd.y=ptBeg.y;
		}
		else
		{
			moEnd.x=ptBeg.x+(LOWORD(lParam)-ptBeg.x)/k;
			moEnd.y=ptBeg.y+(HIWORD(lParam)-ptBeg.y)/k;					
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,moEnd.x,moEnd.y);
		fmoEnd.x=moEnd.x;
		fmoEnd.y=moEnd.y;
		ReleaseDC(hwnd,hdc);
		return 0 ;
	case WM_DESTROY :
		PostQuitMessage (0) ;
		return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}


然後還要模擬一直按着鼠標左鍵然後掃射的效果
首先定義一個全局變量isLeftDown來表示鼠標左鍵是否被按下然後再寫一個計時器用來鼠標按下時每隔一段時間就射出一個子彈
用addShot數組來預存子彈最後還要模擬一直按着鼠標左鍵然後掃射的效果

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("BlokOut2") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Mouse Button & Capture Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
POINT Shot[500][2],Boundary,addShot[2];
int nShot,isLeftDown;
void CALLBACK MyTimer(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	HDC hdc=GetDC(hwnd);
	int i=0;
	SelectObject(hdc,GetStockObject(WHITE_PEN));	
	for(i=0;i<nShot;i++)
	{
		MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
		LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
	}
	for(i=0;i<nShot;i++)
	{
		if(Shot[i][0].x>Boundary.x||Shot[i][0].x<0
			||Shot[i][0].y>Boundary.y||Shot[i][0].y<0)
		{
			int j=i;
			for(;j<nShot-1;j++)
			{
				Shot[j][0].x=Shot[j+1][0].x;
				Shot[j][0].y=Shot[j+1][0].y;
				Shot[j][1].x=Shot[j+1][1].x;
				Shot[j][1].y=Shot[j+1][1].y;
			}
			nShot--;
			i--;
		}
	}
	SelectObject(hdc,GetStockObject(BLACK_PEN));
	for(i=0;i<nShot;i++)
	{
		Shot[i][0].x+=Shot[i][1].x/2;
		Shot[i][0].y+=Shot[i][1].y/2;
		MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
		LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
	}
	ReleaseDC(hwnd,hdc);
}
void CALLBACK AddShot(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)//用來添加子彈的第二個計時器回調函數 
{
	if(isLeftDown)  //只要左鍵一直被按下,每隔150毫秒就把當前預存子彈加入到已射出的子彈序列中 
	{
		Shot[nShot][0].x=addShot[0].x;
		Shot[nShot][0].y=addShot[0].y;
		Shot[nShot][1].x=addShot[1].x;
		Shot[nShot][1].y=addShot[1].y;
		nShot++;
	}
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static POINT ptBeg, ptEnd,moEnd,fmoEnd;
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	 double k;
	 int R=30;
	 char s[100];
	switch (message)
	{
	case WM_SIZE :
		nShot=0;isLeftDown=0;
		SetTimer(hwnd,0,30,MyTimer);
		SetTimer(hwnd,1,150,AddShot);
		ptBeg.x=LOWORD(lParam)/2;
		ptBeg.y=HIWORD(lParam)/2;
		Boundary.x=LOWORD(lParam);
		Boundary.y=HIWORD(lParam);
		return 0;
	case WM_LBUTTONDOWN :
		hdc=GetDC(hwnd);

		ptEnd.x = GET_X_LPARAM (lParam) ;
		ptEnd.y = GET_Y_LPARAM (lParam) ;
		k=sqrt(((ptEnd.x-ptBeg.x)*(ptEnd.x-ptBeg.x)
			+(ptEnd.y-ptBeg.y)*(ptEnd.y-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			ptEnd.x=ptBeg.x;
			ptEnd.y=ptBeg.y;
		}
		else
		{
			ptEnd.x=ptBeg.x+(ptEnd.x-ptBeg.x)/k*2;
			ptEnd.y=ptBeg.y+(ptEnd.y-ptBeg.y)/k*2;					
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,(ptBeg.x+ptEnd.x)/2,(ptBeg.y+ptEnd.y)/2,NULL);
		LineTo(hdc,ptEnd.x,ptEnd.y);
		ReleaseDC(hwnd,hdc);
		addShot[0].x=Shot[nShot][0].x=(ptBeg.x+ptEnd.x)/2;
		addShot[0].y=Shot[nShot][0].y=(ptBeg.y+ptEnd.y)/2;
		addShot[1].x=Shot[nShot][1].x=ptEnd.x-(ptEnd.x+ptBeg.x)/2;
		addShot[1].y=Shot[nShot][1].y=ptEnd.y-(ptEnd.y+ptBeg.y)/2;
		nShot++;
		isLeftDown=1;//左鍵已經被按下 

		return 0 ;
	case WM_LBUTTONUP : //左鍵被彈起時windows回發消息到這裏 
		isLeftDown=0;
		return 0;
	case WM_MOUSEMOVE :
		hdc=GetDC(hwnd); 
		SelectObject(hdc,GetStockObject(WHITE_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,fmoEnd.x,fmoEnd.y);
		k=sqrt(((LOWORD(lParam)-ptBeg.x)*(LOWORD(lParam)-ptBeg.x)
			+(HIWORD(lParam)-ptBeg.y)*(HIWORD(lParam)-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			moEnd.x=ptBeg.x;
			moEnd.y=ptBeg.y;
		}
		else
		{
			moEnd.x=ptBeg.x+(LOWORD(lParam)-ptBeg.x)/k;
			moEnd.y=ptBeg.y+(HIWORD(lParam)-ptBeg.y)/k;					
		}

		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,moEnd.x,moEnd.y);
		fmoEnd.x=moEnd.x;
		fmoEnd.y=moEnd.y;
		ReleaseDC(hwnd,hdc);
		if(isLeftDown)		//添加預存子彈 
		{
			addShot[0].x=moEnd.x;
			addShot[0].y=moEnd.y;
			addShot[1].x=moEnd.x-ptBeg.x;
			addShot[1].y=moEnd.y-ptBeg.y;
		}
		return 0 ;

	case WM_DESTROY :
		PostQuitMessage (0) ;
		return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}

接下來是添加怪物,用的都是上面的知識,就不多說了,直接代碼


 

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("BlokOut2") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Mouse Button & Capture Demo"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
POINT Shot[500][2],Boundary,addShot[2],Box[1000][2];
int nShot,isLeftDown,BoxHp[1000],nBox,BoxSpeed[1000];
void DrawBox (HWND hwnd, POINT ptBeg, POINT ptEnd,HGDIOBJ a)
{
     HDC hdc ;
     hdc = GetDC (hwnd) ;
	 SelectObject (hdc,GetStockObject(NULL_PEN));
     SelectObject (hdc, a) ;
     Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;
     ReleaseDC (hwnd, hdc) ;
}
void CALLBACK MyTimer(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	HDC hdc=GetDC(hwnd);
	int i=0;
	SelectObject(hdc,GetStockObject(WHITE_PEN));	
	for(i=0;i<nShot;i++)
	{
		MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
		LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
	}
	for(i=0;i<nShot;i++)
	{
		if(Shot[i][0].x>Boundary.x||Shot[i][0].x<0
			||Shot[i][0].y>Boundary.y||Shot[i][0].y<0)
		{
			int j=i;
			for(;j<nShot-1;j++)
			{
				Shot[j][0].x=Shot[j+1][0].x;
				Shot[j][0].y=Shot[j+1][0].y;
				Shot[j][1].x=Shot[j+1][1].x;
				Shot[j][1].y=Shot[j+1][1].y;
			}
			nShot--;
			i--;
		}
	}
	SelectObject(hdc,GetStockObject(BLACK_PEN));
	for(i=0;i<nShot;i++)
	{
		Shot[i][0].x+=Shot[i][1].x/2;
		Shot[i][0].y+=Shot[i][1].y/2;
		MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
		LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
	}
	ReleaseDC(hwnd,hdc);
}
void CALLBACK AddShot(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(isLeftDown)
	{
		Shot[nShot][0].x=addShot[0].x;
		Shot[nShot][0].y=addShot[0].y;
		Shot[nShot][1].x=addShot[1].x;
		Shot[nShot][1].y=addShot[1].y;
		nShot++;
	}
}
void CALLBACK AddBox(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	int a=rand()%4,b,c=30+rand()%100*7/10;
	if(a==0)
	{
		b=rand()%Boundary.x;
		Box[nBox][0].x=b-c;
		Box[nBox][0].y=-c;
		Box[nBox][1].x=b+c;
		Box[nBox][1].y=c;
	}
	else if(a==1)
	{
		b=rand()%Boundary.y;
		Box[nBox][0].x=Boundary.x-c;
		Box[nBox][0].y=b-c;
		Box[nBox][1].x=Boundary.x+c;
		Box[nBox][1].y=b+c;
	}
	else if(a==2)
	{
		b=rand()%Boundary.x;
		Box[nBox][0].x=b-c;
		Box[nBox][0].y=Boundary.y-c;
		Box[nBox][1].x=b+c;
		Box[nBox][1].y=Boundary.y+c;
	}
	else if(a==3)
	{
		b=rand()%Boundary.y;
		Box[nBox][0].x=-c;
		Box[nBox][0].y=b-c;
		Box[nBox][1].x=c;
		Box[nBox][1].y=b+c;
	}
	BoxSpeed[nBox]=2;
	BoxHp[nBox]=1+c/25;
	DrawBox(hwnd,Box[nBox][0],Box[nBox][1],GetStockObject(BLACK_BRUSH));
	nBox++;
}
void CALLBACK BoxMove(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	int i,j;
	for(i=0;i<nBox;i++)
	{
		DrawBox(hwnd,Box[i][0],Box[i][1],GetStockObject(WHITE_BRUSH));
	}
	for(i=0;i<nBox;i++)
	{
		if(BoxHp[i]<=0)
		{
			for(j=i;j<nBox-1;j++)
			{
				BoxHp[j]=BoxHp[j+1];
				BoxSpeed[j]=BoxSpeed[j+1];
				Box[j][0].x=Box[j+1][0].x;
				Box[j][0].y=Box[j+1][0].y;
				Box[j][1].x=Box[j+1][1].x;
				Box[j][1].y=Box[j+1][1].y;
			}
			nBox--;
			i--;
		}
	}
	for(i=0;i<nBox;i++)
	{
		j=sqrt(((Box[i][0].x+Box[i][1].x)/2-Boundary.x/2)*((Box[i][0].x+Box[i][1].x)/2-Boundary.x/2)
			+((Box[i][0].y+Box[i][1].y)/2-Boundary.y/2)*((Box[i][0].y+Box[i][1].y)/2-Boundary.y/2))/BoxSpeed[i];
		int a=(Boundary.x/2-(Box[i][0].x+Box[i][1].x)/2)/j;
		int b=(Boundary.y/2-(Box[i][0].y+Box[i][1].y)/2)/j;
		Box[i][0].x+=a;
		Box[i][1].x+=a;
		Box[i][0].y+=b;
		Box[i][1].y+=b;
	}
	for(i=0;i<nBox;i++)
	{
		DrawBox(hwnd,Box[i][0],Box[i][1],GetStockObject(BLACK_BRUSH));
	}
}
void CALLBACK isShot(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	int i,j;
	HDC hdc=GetDC(hwnd);
	for(i=0;i<nShot;i++)
	{
		for(j=0;j<nBox;j++)
		{
			if(Shot[i][0].x+Shot[i][1].x>=Box[j][0].x&&Shot[i][0].x+Shot[i][1].x<=Box[j][1].x
				&&Shot[i][0].y+Shot[i][1].y>=Box[j][0].y&&Shot[i][0].y+Shot[i][1].y<=Box[j][1].y)
			{
				BoxHp[j]--;
				SelectObject(hdc,GetStockObject(WHITE_PEN));	
				MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
				LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
				int k=i;
				for(;k<nShot-1;k++)
				{
					Shot[k][0].x=Shot[k+1][0].x;
					Shot[k][0].y=Shot[k+1][0].y;
					Shot[k][1].x=Shot[k+1][1].x;
					Shot[k][1].y=Shot[k+1][1].y;
				}
				nShot--;
				i--;
			}
		}
	}
	ReleaseDC(hwnd,hdc);
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static POINT ptBeg, ptEnd,moEnd,fmoEnd;
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	 double k;
	 int R=30;
	 char s[100];
	switch (message)
	{
	case WM_CREATE:
		srand((unsigned)time(NULL));
		nShot=nBox=0;isLeftDown=0;
		SetTimer(hwnd,0,30,MyTimer);
		SetTimer(hwnd,1,150,AddShot);
		SetTimer(hwnd,2,150,BoxMove);
		SetTimer(hwnd,3,1000,AddBox);
		SetTimer(hwnd,4,20,isShot);
	case WM_SIZE :
		ptBeg.x=LOWORD(lParam)/2;
		ptBeg.y=HIWORD(lParam)/2;
		Boundary.x=LOWORD(lParam);
		Boundary.y=HIWORD(lParam);	
		return 0;
	case WM_LBUTTONDOWN :
		hdc=GetDC(hwnd);
		ptEnd.x = GET_X_LPARAM (lParam) ;
		ptEnd.y = GET_Y_LPARAM (lParam) ;
		k=sqrt(((ptEnd.x-ptBeg.x)*(ptEnd.x-ptBeg.x)
			+(ptEnd.y-ptBeg.y)*(ptEnd.y-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			ptEnd.x=ptBeg.x;
			ptEnd.y=ptBeg.y;
		}
		else
		{
			ptEnd.x=ptBeg.x+(ptEnd.x-ptBeg.x)/k*2;
			ptEnd.y=ptBeg.y+(ptEnd.y-ptBeg.y)/k*2;					
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,(ptBeg.x+ptEnd.x)/2,(ptBeg.y+ptEnd.y)/2,NULL);
		LineTo(hdc,ptEnd.x,ptEnd.y);
		ReleaseDC(hwnd,hdc);
		addShot[0].x=Shot[nShot][0].x=(ptBeg.x+ptEnd.x)/2;
		addShot[0].y=Shot[nShot][0].y=(ptBeg.y+ptEnd.y)/2;
		addShot[1].x=Shot[nShot][1].x=ptEnd.x-(ptEnd.x+ptBeg.x)/2;
		addShot[1].y=Shot[nShot][1].y=ptEnd.y-(ptEnd.y+ptBeg.y)/2;
		nShot++;
		isLeftDown=1;
		return 0 ;
	case WM_LBUTTONUP :
		isLeftDown=0;
		return 0;
	case WM_MOUSEMOVE :
		hdc=GetDC(hwnd);
		SelectObject(hdc,GetStockObject(WHITE_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,fmoEnd.x,fmoEnd.y);
		k=sqrt(((LOWORD(lParam)-ptBeg.x)*(LOWORD(lParam)-ptBeg.x)
			+(HIWORD(lParam)-ptBeg.y)*(HIWORD(lParam)-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			moEnd.x=ptBeg.x;
			moEnd.y=ptBeg.y;
		}
		else
		{
			moEnd.x=ptBeg.x+(LOWORD(lParam)-ptBeg.x)/k;
			moEnd.y=ptBeg.y+(HIWORD(lParam)-ptBeg.y)/k;					
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,moEnd.x,moEnd.y);
		fmoEnd.x=moEnd.x;
		fmoEnd.y=moEnd.y;
		ReleaseDC(hwnd,hdc);
		if(isLeftDown)
		{
			addShot[0].x=moEnd.x;
			addShot[0].y=moEnd.y;
			addShot[1].x=moEnd.x-ptBeg.x;
			addShot[1].y=moEnd.y-ptBeg.y;
		}
		return 0 ;
	case WM_DESTROY :
		PostQuitMessage (0) ;
		return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}


 最後就是完善工作,貼上最後的代碼

#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("BlokOut2") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;

     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"), 
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
    
     hwnd = CreateWindow (szAppName, TEXT ("defend 1.0"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, SW_SHOWMAXIMIZED) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}
POINT Shot[50000][2],Boundary,addShot[2],Box[1000][2];
int R,nShot,isLeftDown,BoxHp[1000],nBox,BoxSpeed[1000],weapen[5],peopleHp,weapenNum[5],boxNum,Step,isStar,isBoom;
void DrawBox (HWND hwnd, POINT ptBeg, POINT ptEnd,HGDIOBJ a)
{
     HDC hdc ;
     hdc = GetDC (hwnd) ;
	 SelectObject (hdc,GetStockObject(NULL_PEN));
     SelectObject (hdc, a) ;
     Rectangle (hdc, ptBeg.x, ptBeg.y, ptEnd.x, ptEnd.y) ;
     ReleaseDC (hwnd, hdc) ;
}
void CALLBACK PrintInfo(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(!isStar) return;
	HDC hdc=GetDC(hwnd);
	SelectObject(hdc,GetStockObject(BLACK_PEN));
	Rectangle(hdc,Boundary.x/2-50,10,Boundary.x/2+50,30);
	SelectObject(hdc,(HBRUSH)CreateSolidBrush(RGB(255,0,0)));
	SelectObject(hdc,GetStockObject(NULL_PEN));
	if(peopleHp<=0) peopleHp=0;
	Rectangle(hdc,Boundary.x/2-50,10,Boundary.x/2-50+peopleHp,30);
	if(peopleHp==0)
	{
		SelectObject(hdc,GetStockObject(WHITE_BRUSH));
		Rectangle(hdc,0,0,Boundary.x,Boundary.y);
		isStar=0;
		peopleHp=100;
		if(MessageBox(NULL,TEXT("你掛了!\n按OK重新開始"),TEXT("輸"),MB_OK)==IDOK)
		{
			MessageBox(NULL,TEXT("按1,2,3,4切槍\n在這一關你只能使用機槍,子彈無限\n按左鍵攻擊"),TEXT("step 1"),MB_OK);
		}
		nShot=nBox=0;isLeftDown=0;
		memset(weapen,0,sizeof(weapen));
		memset(weapenNum,0,sizeof(weapenNum[5]));
		boxNum=10;
		Step=0;
		isStar=isBoom=0;
		weapen[1]=1;
		BoxHp[0]=4;
		BoxSpeed[0]=2;
		peopleHp=100;
		isStar=1;
		Step=1;
	}
	TCHAR s[100];
	int a,i;
	for(i=2;i<5;i++)
	if(weapen[i])
	{
		a=weapenNum[i];
		break;
	}
	if(weapen[1])
	sprintf(s,"%d      |%d      |∞    \0",Step,boxNum);
	else   
	sprintf(s,"%d      |%d      |%d     \0",Step,boxNum,a);
	if(weapen[1])
	TextOut(hdc,Boundary.x/2-50,31,"關卡 怪物 彈藥",strlen("關卡 怪物 彈藥"));
	else if(weapen[2])
	TextOut(hdc,Boundary.x/2-50,31,"關卡 怪物 散射",strlen("關卡 怪物 散射"));
	else if(weapen[3])
	TextOut(hdc,Boundary.x/2-50,31,"關卡 怪物 激光",strlen("關卡 怪物 激光"));
	else if(weapen[4])
	TextOut(hdc,Boundary.x/2-50,31,"關卡 怪物 核爆",strlen("關卡 怪物 核爆"));
	//s[0]='1';s[1]='\0';
	TextOut(hdc,Boundary.x/2-50,46,s,strlen(s));
	if(boxNum<=0) 
	{
		isStar=0;
		nBox=0;
		nShot=0;
		SelectObject(hdc,GetStockObject(NULL_PEN));
		SelectObject(hdc,GetStockObject(WHITE_BRUSH));
		Rectangle(hdc,0,0,Boundary.x,Boundary.y);
		if(Step==1)
		{
			MessageBox(NULL,TEXT("恭喜你通過第一關\n你解鎖了散射槍按2切換"),TEXT("step 2"),MB_OK);
			boxNum=20;
			memset(weapenNum,0,sizeof(weapenNum));
			weapenNum[2]=1000;
			BoxSpeed[0]=5;
			BoxHp[0]=5;
			isBoom=0;
			isStar=1;
			Step=2;
		}
		else if(Step==2)
		{
			MessageBox(NULL,TEXT("恭喜你通過第二關\n你解鎖了激光槍按3切換"),TEXT("step 3"),MB_OK);
			boxNum=30;
			memset(weapenNum,0,sizeof(weapenNum));
			weapenNum[2]=1000;
			weapenNum[3]=2000;
			BoxSpeed[0]=6;
			BoxHp[0]=15;
			isBoom=0;
			isStar=1;
			Step=3;
		}
		else if(Step==3)
		{
			MessageBox(NULL,TEXT("恭喜你通過第三關\n你解鎖了核爆!按4切換\n只有一次,請謹慎使用"),TEXT("step 4"),MB_OK);
			boxNum=40;
			memset(weapenNum,0,sizeof(weapenNum));
			weapenNum[2]=4000;
			weapenNum[3]=6000;
			weapenNum[4]=1;
			BoxSpeed[0]=10;
			BoxHp[0]=40;
			isBoom=0;
			isStar=1;
			Step=4;
		}
		else if(Step==4)
		{
			MessageBox(NULL,TEXT("恭喜你通過第四關\n"),TEXT("step 5"),MB_OK);
			boxNum=40;
			memset(weapenNum,0,sizeof(weapenNum));
			weapenNum[2]=6000;
			weapenNum[3]=7000;
			weapenNum[4]=1;
			BoxSpeed[0]=20;
			BoxHp[0]=60;
			isBoom=0;
			isStar=1;
			Step=5;
		}
		else if(Step==5)
		{
			MessageBox(NULL,TEXT("恭喜你通過第五關\n敬請期待defend 2.0"),TEXT("step 5"),MB_OK);
			boxNum=10;
			memset(weapenNum,0,sizeof(weapenNum));
			weapenNum[2]=1000;
			weapenNum[3]=2000;
			weapenNum[4]=1;
			BoxSpeed[0]=5;
			BoxHp[0]=40;
			isBoom=0;
		}
	}
	ReleaseDC(hwnd,hdc);
}
void CALLBACK MyTimer(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(!isStar) return;
	HDC hdc=GetDC(hwnd);
	if(!weapen[4]||!isBoom)
	{
		int i=0;
		SelectObject(hdc,GetStockObject(WHITE_PEN));	
		for(i=isBoom;i<nShot;i++)
		{
			MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
			LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
		}
		for(i=isBoom;i<nShot;i++)
		{
			if(Shot[i][0].x>Boundary.x||Shot[i][0].x<0
				||Shot[i][0].y>Boundary.y||Shot[i][0].y<0)
			{
				int j=i;
				for(;j<nShot-1;j++)
				{
					Shot[j][0].x=Shot[j+1][0].x;
					Shot[j][0].y=Shot[j+1][0].y;
					Shot[j][1].x=Shot[j+1][1].x;
					Shot[j][1].y=Shot[j+1][1].y;
				}
				nShot--;
				i--;
			}
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		for(i=isBoom;i<nShot;i++)
		{
			Shot[i][0].x+=Shot[i][1].x/2;
			Shot[i][0].y+=Shot[i][1].y/2;
			MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
			LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
		}
	}
	if(isBoom)
	{
		int i,j;
		SelectObject(hdc,GetStockObject(WHITE_PEN));
		SelectObject(hdc,GetStockObject(NULL_BRUSH));
		for(i=0;i<isBoom;i++)
		{
			Ellipse(hdc,Shot[i][0].x,Shot[i][0].y,Shot[i][1].x,Shot[i][1].y);
			Shot[i][0].x-=2;
			Shot[i][0].y-=2;
			Shot[i][1].x+=2;
			Shot[i][1].y+=2;
		}
		for(i=0;i<isBoom;i++)
		{
			if(Shot[i][1].x>Boundary.x)
			{
				for(j=i;j<nShot-1;j++)
				{
					Shot[j][0].x=Shot[j+1][0].x;
					Shot[j][0].y=Shot[j+1][0].y;
					Shot[j][1].x=Shot[j+1][1].x;
					Shot[j][1].y=Shot[j+1][1].y;
				}
				i--;
				nShot--;
				isBoom--;
			}
		}
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		for(i=0;i<isBoom;i++)
		{
			Ellipse(hdc,Shot[i][0].x,Shot[i][0].y,Shot[i][1].x,Shot[i][1].y);
		}
	}
	ReleaseDC(hwnd,hdc);
}
void CALLBACK AddShot(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(!isStar) return;
	if(isLeftDown)
	{
		if(weapen[1])
		{
			Shot[nShot][0].x=addShot[0].x;
			Shot[nShot][0].y=addShot[0].y;
			Shot[nShot][1].x=addShot[1].x;
			Shot[nShot][1].y=addShot[1].y;
			nShot++;
		}
		else if(weapen[2]&&weapenNum[2]>0)
		{
			weapenNum[2]-=11;
			double a;
			if(addShot[0].x-Boundary.x/2==0)
			{
				a=3.14159/2;
			}
			else
			{
				a=atan((addShot[0].y-Boundary.y/2)*1.0/(addShot[0].x-Boundary.x/2));
			}
			if((addShot[0].x-Boundary.x/2)<0) a+=3.1415926;
			Shot[nShot][0].x=Boundary.x/2+R*cos(a);
			Shot[nShot][0].y=Boundary.y/2+R*sin(a);
			Shot[nShot][1].x=R*cos(a);
			Shot[nShot][1].y=R*sin(a);
			nShot++;
			for(int i=1;i<=5;i++)
			{
				double b=a+i*3.14159/60;
				if(b>2*3.14159) b-=2*3.14159;
				Shot[nShot][0].x=Boundary.x/2+R*cos(b);
				Shot[nShot][0].y=Boundary.y/2+R*sin(b);
				Shot[nShot][1].x=R*cos(b);
				Shot[nShot][1].y=R*sin(b);
				nShot++;
				b=a-i*3.14159/60;
				if(b<0) b+=2*3.14159;
				Shot[nShot][0].x=Boundary.x/2+R*cos(b);
				Shot[nShot][0].y=Boundary.y/2+R*sin(b);
				Shot[nShot][1].x=R*cos(b);
				Shot[nShot][1].y=R*sin(b);
				nShot++;
			}

		}
		else if(weapen[3]&&weapenNum[3]>0)
		{
			weapenNum[3]-=90;
			int i,j;
			for(i=0;;i++)
			{
				if(addShot[0].x+addShot[1].x*i>Boundary.x||addShot[0].x+addShot[1].x*i<0
					||addShot[0].y+addShot[1].y*i>Boundary.y||addShot[0].y+addShot[1].y*i<0)
					break;
				for(j=0;j<10;j++)
				{
					Shot[nShot][0].x=addShot[0].x+addShot[1].x*i;
					Shot[nShot][0].y=addShot[0].y+addShot[1].y*i;
					Shot[nShot][1].x=addShot[1].x;
					Shot[nShot][1].y=addShot[1].y;
					nShot++;
				}
			}
		}
	}
}
void CALLBACK AddBox(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(!isStar||boxNum<=0) return;
	int a=rand()%4,b,c=30+rand()%100*7/10;
	if(a==0)
	{
		b=rand()%Boundary.x;
		Box[nBox][0].x=b-c;
		Box[nBox][0].y=-c;
		Box[nBox][1].x=b+c;
		Box[nBox][1].y=c;
	}
	else if(a==1)
	{
		b=rand()%Boundary.y;
		Box[nBox][0].x=Boundary.x-c;
		Box[nBox][0].y=b-c;
		Box[nBox][1].x=Boundary.x+c;
		Box[nBox][1].y=b+c;
	}
	else if(a==2)
	{
		b=rand()%Boundary.x;
		Box[nBox][0].x=b-c;
		Box[nBox][0].y=Boundary.y-c;
		Box[nBox][1].x=b+c;
		Box[nBox][1].y=Boundary.y+c;
	}
	else if(a==3)
	{
		b=rand()%Boundary.y;
		Box[nBox][0].x=-c;
		Box[nBox][0].y=b-c;
		Box[nBox][1].x=c;
		Box[nBox][1].y=b+c;
	}
	BoxSpeed[nBox]=BoxSpeed[0];
	//BoxHp[nBox]=1+c/25;
	BoxHp[nBox]=Step*5;
	DrawBox(hwnd,Box[nBox][0],Box[nBox][1],GetStockObject(BLACK_BRUSH));
	nBox++;
}
void CALLBACK BoxMove(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(!isStar) return;
	int i,j;
	for(i=0;i<nBox;i++)
	{
		DrawBox(hwnd,Box[i][0],Box[i][1],GetStockObject(WHITE_BRUSH));
	}
	for(i=0;i<nBox;i++)
	{
		if(sqrt(((Box[i][0].x+Box[i][1].x)/2-Boundary.x/2)*((Box[i][0].x+Box[i][1].x)/2-Boundary.x/2)
			+((Box[i][0].y+Box[i][1].y)/2-Boundary.y/2)*((Box[i][0].y+Box[i][1].y)/2-Boundary.y/2))<=50)
		{peopleHp-=10;BoxHp[i]=0;}
		if(BoxHp[i]<=0)
		{
			boxNum--;
			for(j=i;j<nBox-1;j++)
			{
				BoxHp[j]=BoxHp[j+1];
				BoxSpeed[j]=BoxSpeed[j+1];
				Box[j][0].x=Box[j+1][0].x;
				Box[j][0].y=Box[j+1][0].y;
				Box[j][1].x=Box[j+1][1].x;
				Box[j][1].y=Box[j+1][1].y;
			}
			nBox--;
			i--;
		}
	}
	for(i=0;i<nBox;i++)
	{
		j=sqrt(((Box[i][0].x+Box[i][1].x)/2-Boundary.x/2)*((Box[i][0].x+Box[i][1].x)/2-Boundary.x/2)
			+((Box[i][0].y+Box[i][1].y)/2-Boundary.y/2)*((Box[i][0].y+Box[i][1].y)/2-Boundary.y/2))/BoxSpeed[i];
		int a=(Boundary.x/2-(Box[i][0].x+Box[i][1].x)/2)/j;
		int b=(Boundary.y/2-(Box[i][0].y+Box[i][1].y)/2)/j;
		Box[i][0].x+=a;
		Box[i][1].x+=a;
		Box[i][0].y+=b;
		Box[i][1].y+=b;
	}
	for(i=0;i<nBox;i++)
	{
		DrawBox(hwnd,Box[i][0],Box[i][1],GetStockObject(BLACK_BRUSH));
	}
}
void CALLBACK isShot(HWND hwnd,UINT message ,UINT iTimerID,DWORD dwTime)
{
	if(!isStar) return;
	int i,j;
	HDC hdc=GetDC(hwnd);
	if(!weapen[4]||!isBoom)
	{
		for(i=isBoom;i<nShot;i++)
		{
			for(j=0;j<nBox;j++)
			{
				if(Shot[i][0].x+Shot[i][1].x>=Box[j][0].x&&Shot[i][0].x+Shot[i][1].x<=Box[j][1].x
					&&Shot[i][0].y+Shot[i][1].y>=Box[j][0].y&&Shot[i][0].y+Shot[i][1].y<=Box[j][1].y)
				{
					BoxHp[j]--;
					SelectObject(hdc,GetStockObject(WHITE_PEN));	
					MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
					LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
					int k=i;
					for(;k<nShot-1;k++)
					{
						Shot[k][0].x=Shot[k+1][0].x;
						Shot[k][0].y=Shot[k+1][0].y;
						Shot[k][1].x=Shot[k+1][1].x;
						Shot[k][1].y=Shot[k+1][1].y;
					}
					nShot--;
					i--;
				}
			}
		}
	}
	if(isBoom)
	{
		for(i=0;i<isBoom;i++)
		{
			double a=((Shot[i][1].x-Boundary.x/2)*(Shot[i][1].x-Boundary.x/2));
			for(j=0;j<nBox;j++)
			{
				double b=(((Box[j][0].x+Box[j][1].x)/2-Boundary.x/2)*((Box[j][0].x+Box[j][1].x)/2-Boundary.x/2)+
							 ((Box[j][0].y+Box[j][1].y)/2-Boundary.y/2)*((Box[j][0].y+Box[j][1].y)/2-Boundary.y/2));
				if(a>=b)
				{
					BoxHp[j]=0;
				}
			}
		}
	}
	ReleaseDC(hwnd,hdc);
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static POINT ptBeg, ptEnd,moEnd,fmoEnd;
     HDC          hdc ;
     PAINTSTRUCT  ps ;
	 double k;
	 char s[100];
	switch (message)
	{
	case WM_CREATE:
		srand((unsigned)time(NULL));
		nShot=nBox=0;isLeftDown=0;
		SetTimer(hwnd,0,30,MyTimer);
		SetTimer(hwnd,1,150,AddShot);
		SetTimer(hwnd,2,150,BoxMove);
		SetTimer(hwnd,3,1000,AddBox);
		SetTimer(hwnd,4,20,isShot);
		SetTimer(hwnd,5,20,PrintInfo);
		memset(weapen,0,sizeof(weapen));
		peopleHp=100;
		memset(weapenNum,0,sizeof(weapenNum[5]));
		boxNum=10;
		Step=0;
		isStar=isBoom=0;
		weapen[1]=1;
		BoxHp[0]=4;
		BoxSpeed[0]=4;
		R=30;
		if(MessageBox(NULL,TEXT("按1,2,3,4切槍\n在這一關你只能使用機槍,子彈無限\n按左鍵攻擊"),TEXT("step 1"),MB_OK)==IDOK) 
		{
			isStar=1;
			Step=1;
		}
		return 0;
	case WM_SIZE :
		ptBeg.x=LOWORD(lParam)/2;
		ptBeg.y=HIWORD(lParam)/2;
		Boundary.x=LOWORD(lParam);
		Boundary.y=HIWORD(lParam);	
		return 0;
	case WM_LBUTTONDOWN :
		if(!isStar) return 0;
		hdc=GetDC(hwnd);
		ptEnd.x = GET_X_LPARAM (lParam) ;
		ptEnd.y = GET_Y_LPARAM (lParam) ;
		if(weapen[1])
		{
			k=sqrt(((ptEnd.x-ptBeg.x)*(ptEnd.x-ptBeg.x)
				+(ptEnd.y-ptBeg.y)*(ptEnd.y-ptBeg.y))
				/(double)(R*R));
			if(k==0)
			{
				ptEnd.x=ptBeg.x;
				ptEnd.y=ptBeg.y;
			}
			else
			{
				ptEnd.x=ptBeg.x+(ptEnd.x-ptBeg.x)/k*2;
				ptEnd.y=ptBeg.y+(ptEnd.y-ptBeg.y)/k*2;					
			}
			addShot[0].x=Shot[nShot][0].x=(ptBeg.x+ptEnd.x)/2;
			addShot[0].y=Shot[nShot][0].y=(ptBeg.y+ptEnd.y)/2;
			addShot[1].x=Shot[nShot][1].x=ptEnd.x-(ptEnd.x+ptBeg.x)/2;
			addShot[1].y=Shot[nShot][1].y=ptEnd.y-(ptEnd.y+ptBeg.y)/2;
			nShot++;
		}
		else if(weapen[2]&&weapenNum[2]>0)
		{
			double a;
			weapenNum[2]-=11;
			if(ptEnd.x-ptBeg.x==0)
			{
				a=3.14159/2;
			}
			else
			{
				a=atan((ptEnd.y-ptBeg.y)*1.0/(ptEnd.x-ptBeg.x));
			}
			if((ptEnd.x-ptBeg.x)<0) a+=3.1415926;
			addShot[0].x=ptEnd.x;
			addShot[0].y=ptEnd.y;
			Shot[nShot][0].x=ptBeg.x+R*cos(a);
			Shot[nShot][0].y=ptBeg.y+R*sin(a);
			Shot[nShot][1].x=R*cos(a);
			Shot[nShot][1].y=R*sin(a);
			nShot++;
			for(int i=1;i<=5;i++)
			{
				double b=a+i*3.14159/60;
				if(b>2*3.14159) b-=2*3.14159;
				Shot[nShot][0].x=ptBeg.x+R*cos(b);
				Shot[nShot][0].y=ptBeg.y+R*sin(b);
				Shot[nShot][1].x=R*cos(b);
				Shot[nShot][1].y=R*sin(b);
				nShot++;
				b=a-i*3.14159/60;
				if(b<0) b+=2*3.14159;
				Shot[nShot][0].x=ptBeg.x+R*cos(b);
				Shot[nShot][0].y=ptBeg.y+R*sin(b);
				Shot[nShot][1].x=R*cos(b);
				Shot[nShot][1].y=R*sin(b);
				nShot++;
			}
		}
		else if(weapen[3]&&weapenNum[3]>0)
		{
			weapenNum[3]-=90;
			k=sqrt(((ptEnd.x-ptBeg.x)*(ptEnd.x-ptBeg.x)
				+(ptEnd.y-ptBeg.y)*(ptEnd.y-ptBeg.y))
				/(double)(R*R));
			if(k==0)
			{
				ptEnd.x=ptBeg.x;
				ptEnd.y=ptBeg.y;
			}
			else
			{
				ptEnd.x=ptBeg.x+(ptEnd.x-ptBeg.x)/k*2;
				ptEnd.y=ptBeg.y+(ptEnd.y-ptBeg.y)/k*2;					
			}
			addShot[0].x=Shot[nShot][0].x=(ptBeg.x+ptEnd.x)/2;
			addShot[0].y=Shot[nShot][0].y=(ptBeg.y+ptEnd.y)/2;
			addShot[1].x=Shot[nShot][1].x=(ptEnd.x-ptBeg.x)/2;
			addShot[1].y=Shot[nShot][1].y=(ptEnd.y-ptBeg.y)/2;
			nShot++;
			int i,j;
			for(i=0;;i++)
			{
				if((ptBeg.x+ptEnd.x)/2+(ptEnd.x-ptBeg.x)/2*i>Boundary.x||(ptBeg.x+ptEnd.x)/2+(ptEnd.x-ptBeg.x)/2*i<0
					||(ptBeg.y+ptEnd.y)/2+(ptEnd.y-ptBeg.y)/2*i>Boundary.y||(ptBeg.y+ptEnd.y)/2+(ptEnd.y-ptBeg.y)/2*i<0)
					break;
				for(j=0;j<10;j++)
				{
					Shot[nShot][0].x=(ptBeg.x+ptEnd.x)/2+(ptEnd.x-ptBeg.x)/2*i;
					Shot[nShot][0].y=(ptBeg.y+ptEnd.y)/2+(ptEnd.y-ptBeg.y)/2*i;
					Shot[nShot][1].x=(ptEnd.x-ptBeg.x)/2;
					Shot[nShot][1].y=(ptEnd.y-ptBeg.y)/2;
					nShot++;
				}
			}
		}
		else if(weapen[4]&&weapenNum[4]>0)
		{
			weapenNum[4]--;
			int i;
			SelectObject(hdc,GetStockObject(WHITE_PEN));	
			for(i=0;i<nShot;i++)
			{
				MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
				LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
			}
			nShot=0;
			for(i=0;i<10;i++)
			{
				Shot[nShot][0].x=ptBeg.x-20-5*i;
				Shot[nShot][0].y=ptBeg.y-20-5*i;
				Shot[nShot][1].x=ptBeg.x+20+5*i;
				Shot[nShot][1].y=ptBeg.y+20+5*i;
				nShot++;
			}
			isBoom=10;
		}
		ReleaseDC(hwnd,hdc);
		isLeftDown=1;
		return 0 ;
	case WM_LBUTTONUP :
		isLeftDown=0;
		return 0;
	case WM_MOUSEMOVE :
		if(!isStar) return 0;
		hdc=GetDC(hwnd);
		SelectObject(hdc,GetStockObject(WHITE_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,fmoEnd.x,fmoEnd.y);
		k=sqrt(((LOWORD(lParam)-ptBeg.x)*(LOWORD(lParam)-ptBeg.x)
			+(HIWORD(lParam)-ptBeg.y)*(HIWORD(lParam)-ptBeg.y))
			/(double)(R*R));
		if(k==0)
		{
			moEnd.x=ptBeg.x;
			moEnd.y=ptBeg.y;
		}
		else
		{
			moEnd.x=ptBeg.x+(LOWORD(lParam)-ptBeg.x)/k;
			moEnd.y=ptBeg.y+(HIWORD(lParam)-ptBeg.y)/k;					
		}
		/*sprintf(s,"%d  %d  %lf  %d  %d  %d  %d  %d",ptBeg.x,ptBeg.y,k,(LOWORD(lParam)-ptBeg.x)*(LOWORD(lParam)-ptBeg.x)
			+(HIWORD(lParam)-ptBeg.y)*(HIWORD(lParam)-ptBeg.y),moEnd.x,moEnd.y,LOWORD(lParam),HIWORD(lParam));
		MessageBox(NULL,s,TEXT("調試"),NULL);*/
		SelectObject(hdc,GetStockObject(BLACK_PEN));
		MoveToEx(hdc,ptBeg.x,ptBeg.y,NULL);
		LineTo(hdc,moEnd.x,moEnd.y);
		fmoEnd.x=moEnd.x;
		fmoEnd.y=moEnd.y;
		ReleaseDC(hwnd,hdc);
		if(isLeftDown)
		{
			addShot[0].x=moEnd.x;
			addShot[0].y=moEnd.y;
			addShot[1].x=moEnd.x-ptBeg.x;
			addShot[1].y=moEnd.y-ptBeg.y;
		}
		return 0 ;
	case WM_RBUTTONDOWN:
		
		return 0 ;
 
	case WM_CHAR :
		switch (wParam)
		{
			case '1':
			memset(weapen,0,sizeof(weapen));
			weapen[1]=1;
			break;
			case '2':
			memset(weapen,0,sizeof(weapen));
			weapen[2]=1;
			break;
			case '3':
			memset(weapen,0,sizeof(weapen));
			weapen[3]=1;
			break;
			case '4':
			if(!isStar) break;
			memset(weapen,0,sizeof(weapen));
			hdc=GetDC(hwnd);
			if(weapenNum[4]>0&&isLeftDown)
			{
				weapenNum[4]--;
				int i;
				SelectObject(hdc,GetStockObject(WHITE_PEN));	
				for(i=0;i<nShot;i++)
				{
					MoveToEx(hdc,Shot[i][0].x,Shot[i][0].y,NULL);
					LineTo(hdc,Shot[i][0].x+Shot[i][1].x,Shot[i][0].y+Shot[i][1].y);
				}
				nShot=0;
				for(i=0;i<10;i++)
				{
					Shot[nShot][0].x=ptBeg.x-20-5*i;
					Shot[nShot][0].y=ptBeg.y-20-5*i;
					Shot[nShot][1].x=ptBeg.x+20+5*i;
					Shot[nShot][1].y=ptBeg.y+20+5*i;
					nShot++;
				}
				isBoom=10;
			}
			weapen[4]=1;
			ReleaseDC(hwnd,hdc);
			break;
		}
		return 0 ;
  
	case WM_PAINT :
		hdc = BeginPaint (hwnd, &ps) ;
		EndPaint (hwnd, &ps) ;
		return 0 ;

	case WM_DESTROY :
		PostQuitMessage (0) ;
		return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章