游戏结束:
当然了,任意时刻按下ESC键就会退出,当life减为0的时候,按下F1就会重新开始游戏。
这里说明一下:
为什么游戏是2.0版本,而不是1.0版本。
因为最先开始1.0版本的时候我想的是干脆就不要life这个参数,球掉到屏幕的下方的时候。照样弹起来,不过分数减去100分
后来听了车韵的意见,加入了生命值这个参数。
并且加入提示语句。每过一次关卡,小球的横向速度和纵向速度都会增加2
也就是说,速度增加2*sqrt(2)
另外每一关的砖块分数会比上一关多一点。
游戏还是那样。分成三个部分。初始化的时候把所有表面都创建好。然后调色板也创建好。
当然,其中有一个很重要的一步,就是去宏定义很多参数
比如每一个砖块的宽度和高度,以及砖块与砖块之间的间距。
游戏的时候,需要做碰撞检测以及绘画,还有检测键盘消息等
最后退出的时候释放掉内存即可。
当然程序的其他重点还有:
1、碰撞检测。
怎么样方便的碰撞检测,判断当前的小球是否碰到砖块或者屏幕边界
碰到的话,就需要更改方向。
检测碰撞,这个要利用每一个砖块的的每一条边都是要么垂直于屏幕的一个边,要门水平。
所以我们就可以不用去写砖块的每一条边的解析式,然后做线段与射线的交点。
这个已经涉及到非常复杂的计算几何算法。
一种比较简单的写法是:
(ball_cx>x)&&(ball_cxy&&ball_cy
如果同时满足这四个条件,那么球必然碰撞了砖块。
2、碰撞后的折返
更改方向这个其实不好想。
首先,如果单纯的从解析几何的角度去设一条直线为y=kx+b,然后各种计算。这样的话必然要考虑斜率为0和无穷大的两种非常特殊的情况
另外,如果这样写,势必会产生大量的浮点数。精度损失,效率低下,计算复杂各种悲剧的事情就会接踵而至。
一个比较好的方法是:
把速度分解为x方向和y方向。两个分量
如果碰撞,则把相应的方向速度设置为反向。这样就大大的简化了计算
改进方向:
可以增加游戏的趣味性,比如增加一些道具,可以把下面的乒乓球板扩大等等
另外还可以每5000分或者更高的时候,增加一条生命。
#pragma comment(lib,"dxguid.lib")
#include
#include
#include
#include
#include
#define KEYDOWN(key) ((GetAsyncKeyState(key) & 0x8000) ? 1 : 0)
#define KEYUP(key) ((GetAsyncKeyState(key) & 0x8000) ? 0 : 1)
#define DD_INIT_STRUCT(ddstruct){memset(&ddstruct,0,sizeof(ddstruct));ddstruct.dwSize=sizeof(ddstruct);}
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8
#define BLOCK_ROW 6
#define BLOCK_COL 8
#define PADDLE_WIDTH 50
#define PADDLE_HEIGHT 8
#define PADDLE_COLOR 191
#define BLOCK_WIDTH 64
#define BLOCK_HEIGHT 16
#define BLOCK_ORIGIN_X 8
#define BLOCK_ORIGIN_Y 8
#define BLOCK_X_GAP 80
#define BLOCK_Y_GAP 32
#define BALL_SIZE 4
UCHAR *double_buffer = NULL;
LPDIRECTDRAW7 lpdd=NULL;
LPDIRECTDRAWSURFACE7 lpddsprimary=NULL;
LPDIRECTDRAWSURFACE7 lpddsback=NULL;
DDSURFACEDESC2 ddsd;
LPDIRECTDRAWPALETTE lpddpal=NULL;
PALETTEENTRY palette[256];
UCHAR blocks[BLOCK_ROW][BLOCK_COL];
#define _RGB16BIT555(r,g,b) ((b&31)+((g&31)<<5)+((r&31)<<10))
#define _RGB16BIT565(r,g,b) ((b&31)+((g&63)<<5)+((r&31)<<11))
#define _RGB32BIT(a,r,g,b) ((b)+((g)<<8)+((r)<<16)+((a)<<24))
struct BALL
{
int x;
int y;
int xv;
int yv;
};
struct PADDLE
{
int x;
int y;
int v;
};
PADDLE paddle;
BALL ball;
int block_hit;
int score=0;
int level=0;
int life=3;
int count=0;
void Plot_Pixel_Faster32(int x,int y,int a,int r,int g,int b,UINT *video_buffer,int lpitch32)
{
UINT color;
color=_RGB32BIT(a,r,g,b);
video_buffer[x+y*lpitch32]=color;
}
HWND hwd;
HINSTANCE hIns;
LRESULT CALLBACK WinSunProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
HDC hdc;
PAINTSTRUCT ps;
switch(uMsg)
{
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
EndPaint(hwnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
LPDIRECTDRAWCLIPPER DDraw_Attach_Clipper(LPDIRECTDRAWSURFACE7 lpdds,int num_rects,LPRECT clip_list)
{
int index;
LPDIRECTDRAWCLIPPER lpddclipper;
LPRGNDATA region_data;
if (FAILED(lpdd->CreateClipper(0,&lpddclipper,NULL)))
return(NULL);
region_data=(LPRGNDATA)malloc(sizeof(RGNDATAHEADER)+num_rects*sizeof(RECT));
memcpy(region_data->Buffer,clip_list,sizeof(RECT)*num_rects);
region_data->rdh.dwSize=sizeof(RGNDATAHEADER);
region_data->rdh.iType=RDH_RECTANGLES;
region_data->rdh.nCount=num_rects;
region_data->rdh.nRgnSize=num_rects*sizeof(RECT);
region_data->rdh.rcBound.left=64000;
region_data->rdh.rcBound.top=64000;
region_data->rdh.rcBound.right=-64000;
region_data->rdh.rcBound.bottom=-64000;
for(index=0;indexrdh.rcBound.left)
region_data->rdh.rcBound.left=clip_list[index].left;
if (clip_list[index].right>region_data->rdh.rcBound.right)
region_data->rdh.rcBound.right=clip_list[index].right;
if (clip_list[index].toprdh.rcBound.top)
region_data->rdh.rcBound.top=clip_list[index].top;
if (clip_list[index].bottom>region_data->rdh.rcBound.bottom)
region_data->rdh.rcBound.bottom=clip_list[index].bottom;
}
if(FAILED(lpddclipper->SetClipList(region_data, 0)))
{
free(region_data);
return(NULL);
}
if(FAILED(lpdds->SetClipper(lpddclipper)))
{
free(region_data);
return(NULL);
}
free(region_data);
return(lpddclipper);
}
int Draw_Text_GDI(char *text,int x,int y,int color,LPDIRECTDRAWSURFACE7 lpdds=lpddsback)
{
HDC xdc;
if (lpdds->GetDC(&xdc)!=DD_OK)
return(0);
SetTextColor(xdc,RGB(palette[color].peRed,palette[color].peGreen,palette[color].peBlue));
SetBkMode(xdc,TRANSPARENT);
TextOut(xdc,x,y,text,strlen(text));
lpdds->ReleaseDC(xdc);
return(1);
}
int DDraw_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds,int color)
{
DDBLTFX ddbltfx;
DD_INIT_STRUCT(ddbltfx);
ddbltfx.dwFillColor=color;
lpdds->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx);
return(1);
}
void Draw_Rectangle(int x1,int y1,int x2,int y2,int color,LPDIRECTDRAWSURFACE7 lpdds=lpddsback)
{
DDBLTFX ddbltfx;
RECT fill_rect;
fill_rect.left=x1;
fill_rect.top=y1;
fill_rect.right=x2;
fill_rect.bottom=y2;
DD_INIT_STRUCT(ddbltfx);
ddbltfx.dwFillColor=color;
lpddsback->Blt(&fill_rect,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&ddbltfx);
}
void Game_Init()
{
if(FAILED(DirectDrawCreateEx(NULL,(void**)&lpdd,IID_IDirectDraw7,NULL)))
return;
if(FAILED(lpdd->SetCooperativeLevel(hwd,DDSCL_FULLSCREEN|DDSCL_ALLOWMODEX|DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT)))
return;
if(FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,0,0)))
return;
DD_INIT_STRUCT(ddsd);
ddsd.dwFlags=DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount=1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
if(FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary,NULL)))
return;
ddsd.ddsCaps.dwCaps=DDSCAPS_BACKBUFFER;
if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback)))
return;
int index;
for(index=0;index<256;index++)
{
if(index<64)
palette[index].peRed=index*4;
else if(index>=64&&index<128)
palette[index].peGreen=(index-64)*4;
else if(index>=128&&index<192)
palette[index].peBlue=(index-128)*4;
else if(index>=192&&index<256)
palette[index].peRed=palette[index].peGreen=palette[index].peBlue = (index-192)*4;
palette[index].peFlags = PC_NOCOLLAPSE;
}
if(FAILED(lpdd->CreatePalette(DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,palette,&lpddpal,NULL)))
return;
if(FAILED(lpddsprimary->SetPalette(lpddpal)))
return;
DDraw_Fill_Surface(lpddsprimary,0);
DDraw_Fill_Surface(lpddsback,0);
RECT screen_rect={0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1};
DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
srand(time(NULL));
memset(&ball,0,sizeof(ball));
ball.x=SCREEN_WIDTH/2;
ball.y=SCREEN_HEIGHT/2;
while(ball.xv==0)
ball.xv=rand()%8-4;
while(ball.yv==0)
ball.yv=rand()%8-4;
paddle.x=(SCREEN_WIDTH/2-16);
paddle.y=SCREEN_HEIGHT-32;
int i,j;
for(i=0;iSCREEN_WIDTH-PADDLE_WIDTH)
paddle.x=SCREEN_WIDTH-PADDLE_WIDTH;
}
if(KEYDOWN(VK_LEFT))
{
paddle.x=paddle.x-paddle.v;
if(paddle.x<0)
paddle.x=0;
}
Draw_Blocks();
ball.x=ball.x+ball.xv;
ball.y=ball.y+ball.yv;
Draw_Rectangle(ball.x-4,ball.y+4,ball.x+BALL_SIZE-4,ball.y+BALL_SIZE+4,0);
Draw_Rectangle(ball.x,ball.y,ball.x+BALL_SIZE,ball.y+BALL_SIZE,255);
if((ball.x>=SCREEN_WIDTH-BALL_SIZE)||(ball.x<=0))
{
ball.xv=-ball.xv;
ball.x=ball.x+ball.xv;
}
if(ball.y<=0)
{
ball.yv=-ball.yv;
ball.y=ball.y+ball.yv;
}
if(ball.y>=SCREEN_HEIGHT-BALL_SIZE)
{
ball.yv=-ball.yv;
ball.y=ball.y+ball.yv;
life--;
memset(&ball,0,sizeof(ball));
ball.x=SCREEN_WIDTH/2;
ball.y=SCREEN_HEIGHT/2;
while(ball.xv==0)
ball.xv=rand()%8-4;
while(ball.yv==0)
ball.yv=rand()%8-4;
paddle.x=SCREEN_WIDTH/2-16;
paddle.y=SCREEN_HEIGHT-32;
Sleep(1500);
}
Draw_Rectangle(paddle.x-4,paddle.y+4,paddle.x+PADDLE_WIDTH-4,paddle.y+PADDLE_HEIGHT+4,0);
Draw_Rectangle(paddle.x,paddle.y,paddle.x+PADDLE_WIDTH,paddle.y+PADDLE_HEIGHT,PADDLE_COLOR);
sprintf(buffer,"B E A T B L O C K S 2.0 S C O R E: %d L E V E L: %d L I F E: %d",score,level,life);
Draw_Text_GDI(buffer,8,SCREEN_HEIGHT-16,100);
if(life==0)
{
sprintf(buffer,"G A M E O V E R Y O U G O T: %d",score);
Draw_Text_GDI(buffer,SCREEN_WIDTH/2-100,SCREEN_HEIGHT/2,100);
sprintf(buffer,"P R E S S F 1 T O R E S T A R , E S C T O Q U I T T H E G A M E");
Draw_Text_GDI(buffer,SCREEN_WIDTH/2-250,SCREEN_HEIGHT/2+16,100);
ball.xv=0;
ball.yv=0;
if(KEYDOWN(VK_F1))
{
score=0;
life=3;
memset(&ball,0,sizeof(ball));
ball.x=SCREEN_WIDTH/2;
ball.y=SCREEN_HEIGHT/2;
while(ball.xv==0)
ball.xv=rand()%8-4;
while(ball.yv==0)
ball.yv=rand()%8-4;
paddle.x=SCREEN_WIDTH/2-16;
paddle.y=SCREEN_HEIGHT-32;
}
}
int i,j;
int x=BLOCK_ORIGIN_X;
int y=BLOCK_ORIGIN_Y;
int ball_cx=ball.x+BALL_SIZE/2;
int ball_cy=ball.y+BALL_SIZE/2;
if((ball_cx>paddle.x)&&(ball_cxpaddle.y&&ball_cyx)&&(ball_cxy&&ball_cyFlip(NULL,DDFLIP_WAIT)));
Sleep(30);
}
void Game_Shut()
{
if(lpddpal)
{
lpddpal->Release();
lpddpal=NULL;
}
if(lpddsprimary)
{
lpddsprimary->Release();
lpddsprimary=NULL;
}
if(lpdd)
{
lpdd->Release();
lpdd=NULL;
}
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdline,
int nShowCmd
)
{
WNDCLASS wndclass;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hInstance=hInstance;
wndclass.lpfnWndProc=WinSunProc;
wndclass.lpszClassName="bingshen";
wndclass.lpszMenuName=NULL;
wndclass.style=CS_HREDRAW|CS_VREDRAW;
//-------------------------------------------
HWND hwnd;
RegisterClass(&wndclass);
//-------------------------------------------
hwnd=CreateWindow("bingshen","-------bingshen",WS_POPUP|WS_VISIBLE,
0,0,SCREEN_WIDTH,SCREEN_HEIGHT,
NULL,NULL,hInstance,NULL);
//-------------------------------------------
hwd=hwnd;
HDC hdc=GetDC(hwnd);
ShowCursor(FALSE);
hIns=hInstance;
Game_Init();
MSG msg;
while(true)
{
DWORD Start_time=GetTickCount();
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Game_Main();
}
Game_Shut();
ReleaseDC(hwnd,hdc);
return msg.wParam;
}