hays2002 发表于 2004-4-6 19:22:00

最简单的游戏程序代码~

#include <windows.h>
#include <ddraw.h>                                 // DirectDraw所使用的头文件;
#define MAP_X 64
#define MAP_Y 48
// 变量、声明函数;
LPDIRECTDRAW lpDD;                                 // DirectDraw对象;
LPDIRECTDRAWSURFACE lpDDSPrimary;                  //主页面,就是你看到的屏幕
LPDIRECTDRAWSURFACE lpDDSBack;                     //后备页面,用于翻转屏幕
LPDIRECTDRAWSURFACE lpBK;                        //地图页面
LPDIRECTDRAWSURFACE lpPlayer;                      //英雄页面
LPDIRECTDRAWSURFACE lplogo;                        //logo页面
LPDIRECTDRAWSURFACE lphays;                        //海斯   

int MAP={
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},                     
{1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,1},
{1,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,1},
{1,0,0,1,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,1,0,1},
{1,0,0,1,0,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,1},
{1,0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,1},
{1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
                     

int SX=0,SY=0;//地图坐标

int old_SX=0,old_SY=0;

RECT rect;//blt用的巨型
int speed=10;

typedef struct{
int x,y;                        //当前坐标
int old_x,old_y;        //旧的坐标
int Way;                        //方向
int Stats;                        //状态
}Role;

Role Hero={1,
         1,
             0,
             0,
             0};



       

//函数声明列表

RECT GetRect(int x1,int y1,int x2,int y2);
void MainLoop();
void Gamehead();      
void BackGround();   
LPDIRECTDRAWSURFACE bitmap_surface(char* file_name);
DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb);
HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb);
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void Delay(long time); //时间函数
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow); // 创建主工作窗口;
BOOL InitDDraw(void);                               // 初始化DirectDraw并且打印字
#define SafeRelease(x) if (x) { x->Release(); x=NULL; }
void Cleanup(void); // 卸载DirectDraw函数;

                           

BOOL InitWindow(HINSTANCE hInstance, int nCmdShow)
{
    HWND hwnd;   // 窗口句柄;
    WNDCLASS wcex; // 窗口类结构;

    // 设置窗口类结构;
    wcex.style=0;                     // 风格;
    wcex.lpfnWndProc=WinProc;         // 窗口处理程序;
    wcex.cbClsExtra=0;                  // 扩充风格;
    wcex.cbWndExtra=0;                  // 扩充程序;
    wcex.hInstance=hInstance;         // 应用程序hInstance句柄;
    wcex.hIcon=LoadIcon(hInstance,IDI_APPLICATION); // 读入默认的图标;
    wcex.hCursor=LoadCursor(NULL,IDC_ARROW);      // 读入默认鼠标形状;
    wcex.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//窗口背景;
    wcex.lpszMenuName=NULL;               // 窗口目录;
    wcex.lpszClassName= "DirectX--Hello"; // 窗口的类名
    // 注册窗口类;
    RegisterClass(&wcex);
    // 创建主窗口;
    hwnd=CreateWindowEx(WS_EX_TOPMOST,"DirectX--Hello","",WS_POPUP|WS_VISIBLE,
                        0,0,GetSystemMetrics(SM_CXSCREEN),
                        GetSystemMetrics(SM_CYSCREEN),NULL,NULL,hInstance,NULL);
    if(!hwnd) return FALSE;
    ShowWindow(hwnd,nCmdShow); // 显示窗口;
    UpdateWindow(hwnd);      // 更新窗口;
   
    SetTimer(hwnd,1,30,NULL);
   
    return TRUE;
}

LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch(message)
    {
    case WM_TIMER:
         lpDDSPrimary->Flip( NULL, 0 );
         break;
         
    case WM_KEYDOWN:    // 如果击键;
      switch(wParam)
      {
             case VK_UP:
                  Hero.Way=3;
                  if (SY<=0 && Hero.y<=240) //往上走
                        {
                        SY=old_SY;
                        Hero.y-=speed;
                        }
                  else if(SY>=MAP_Y-48 && Hero.y>=240)
                        {
                        SY=old_SY;
                        Hero.y-=speed;
                        }
                  else SY--;      
                  
                  break;
                  
            case VK_DOWN:
                  Hero.Way=0;
                  if (SY>MAP_Y-48 && Hero.y>=240) //往下走
                        {
                        SY=old_SY;
                        Hero.y+=speed;
                        }
                  else if (SY<=0 && Hero.y<=240)
                        {
                           SY=old_SY;
                           Hero.y+=speed;
                           }
                  else SY++;
                  
                  break;            
                  
            case VK_LEFT:
                  Hero.Way=1;
                  if (SX<=0 && Hero.x<=320) //往左边走
                        {
                        SX=old_SX;
                        Hero.x-=speed;
                        }
                     else if (SX>=MAP_X-32 && Hero.x>=320)
                              {
                              SX=old_SX;
                              Hero.x-=speed;
                              }
                      else SX--;
                     
                      break;                     
                  
                  
            case VK_RIGHT:
                  Hero.Way=2;
                  if (SX>=MAP_X-32 && Hero.x>=320) //往右边走
                        {
                        SX=old_SX;
                        Hero.x+=speed;
                        }
                     else if (SX<=0 && Hero.x<=320)
                              {
                              SX=old_SX;
                              Hero.x+=speed;
                              }
                      else SX++;
                     
                      break;                     
            }

            
            Hero.Stats++;
            if( Hero.Stats>=3 ) Hero.Stats=0;
            
            break;
            
    case WM_DESTROY:    // 退出消息循环;
      Cleanup();
      PostQuitMessage(0);
      break;
    }
    // 调用缺省消息处理过程;
    return DefWindowProc(hWnd,message,wParam,lParam);
}

// 本程序的最核心内容,即DirectDraw的基本功能与用法;
BOOL InitDDraw(void)
{
    DDSURFACEDESC ddsd;
    HDC hdc;
    DDSCAPS ddscaps;
    // 创建DirectDraw对象;
    if (DirectDrawCreate(NULL,&lpDD,NULL)!=DD_OK) return FALSE;
    // 设置为全屏模式;
    if (lpDD->SetCooperativeLevel(GetActiveWindow(),
    DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN)!=DD_OK)
    return FALSE;
    // 设置显示模式;
    if (lpDD->SetDisplayMode(640,480,16)!=DD_OK) return FALSE;
    // 设置主页面信息;
    ddsd.dwSize=sizeof(ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                          DDSCAPS_FLIP |
                          DDSCAPS_COMPLEX;
                          
        ddsd.dwBackBufferCount = 1;                  

    // 创建一个表面,类似开辟一块屏幕大小的显示内存;
    if (lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL)!=DD_OK)
    MessageBox(NULL,"SDSDSDSD","sdsdsdsdsd",0);
   
    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    if ( lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack)!=DD_OK)
    MessageBox(NULL,"SDSDSDSD","sdsdsdsdsd",0);
   
    lpBK = bitmap_surface("map1.bmp");
    lplogo = bitmap_surface("logo.bmp");
    lphays = bitmap_surface("hays.bmp");
    lpPlayer = bitmap_surface("PLAYER.bmp");
    DDSetColorKey(lpPlayer,RGB(255,238,187));
   
    return TRUE;
}

void Cleanup(void)
{

        SafeRelease(lpBK);
    SafeRelease(lpPlayer);   
    SafeRelease(lpPlayer);   
        SafeRelease(lpDDSBack);
        SafeRelease(lpDD);
        SafeRelease(lplogo);

}

// Windows的主工作函数,类似Dos下Turbo C编程的main();
int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,int nCmdShow)
{
    MSG msg;
   
    // 初始化主窗口;
    if (!InitWindow(hInstance,nCmdShow)) return FALSE;
   
    // 初始化DirectDraw环境,并实现DirectDraw功能;
    if (!InitDDraw())
    {
      MessageBox(GetActiveWindow(),"初始化DirectDraw时出错!",
                   "Error",MB_OK);
      void Cleanup();
      DestroyWindow(GetActiveWindow());
      return FALSE;
    }
    Gamehead();
   
    // 进入消息循环;
        while(1)
        {
                if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
                {
                        if(!GetMessage(&msg, NULL, 0, 0 )) return msg.wParam;
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                }
                else
      MainLoop();
        }       
    return msg.wParam;
}


//游戏需要用到的函数



void Gamehead()
{
RECT rect1={0,0,178,145};
int x=80,y=100;
int i;

lpDDSPrimary->BltFast( 130+80, 202+120, lphays , &rect1, DDBLTFAST_NOCOLORKEY);

for (i=0;i<6;i++)
{
rect1=GetRect(i*65,0,i*65+65,202);
lpDDSPrimary->BltFast( x+=65, y, lplogo , &rect1, DDBLTFAST_NOCOLORKEY);
Delay(500);
}

Delay(3000);
}

void BackGround()   //画地图
{
int i,j;
        for (i=SY;i<SY+15;i++)
       for (j=SX;j<SX+20;j++)
       if (MAP==1)
          {
       rect=GetRect(0,0,32,32);
           lpDDSBack->BltFast( (j-SX)*32, (i-SY)*32, lpBK , &rect, DDBLTFAST_NOCOLORKEY);
          }
       else
       {
       rect=GetRect(0,32,32,64);
       lpDDSBack->BltFast( (j-SX)*32, (i-SY)*32, lpBK , &rect, DDBLTFAST_NOCOLORKEY);
       }
}

RECT GetRect(int x1,int y1,int x2,int y2) //获取对象巨型
{
        RECT TempRect={x1,y1,x2,y2};
        return TempRect;
}

void MainLoop() //游戏循环
{
   BackGround();
   RECT rect2={Hero.Stats*32, Hero.Way*48, Hero.Stats*32+32, Hero.Way*48+48};
   lpDDSBack->BltFast( Hero.x, Hero.y, lpPlayer , &rect2, DDBLTFAST_SRCCOLORKEY);

                if( Hero.x<0 ) Hero.x=0;
                if( Hero.x>640-32 ) Hero.x=640-32;
                if( Hero.y<0 ) Hero.y=0;
                if( Hero.y>480-48 ) Hero.y=480-48;

        Hero.old_x=Hero.x;
        Hero.old_y=Hero.y;
        old_SX = SX; old_SY = SY;
}       


void Delay(long time) //时间函数
{
        static long old_clock, new_clock; //延时变量
        new_clock=old_clock=GetTickCount();
        while( new_clock < old_clock + time )
        {
                new_clock=GetTickCount();
        }
}




//下面是dx相关的函数
LPDIRECTDRAWSURFACE bitmap_surface(char* file_name) //位图载入
{
        HDC hdc;
        HBITMAP bit;
        LPDIRECTDRAWSURFACE surf;



        bit=(HBITMAP) LoadImage(NULL,file_name,IMAGE_BITMAP,0,0,
                                                                LR_DEFAULTSIZE|LR_LOADFROMFILE);
        if (!bit)



                return NULL;



        BITMAP bitmap;
    GetObject( bit, sizeof(BITMAP), &bitmap );
        int surf_width=bitmap.bmWidth;
        int surf_height=bitmap.bmHeight;



        HRESULT ddrval;
        DDSURFACEDESC ddsd;
        ZeroMemory(&ddsd,sizeof(ddsd));
        ddsd.dwSize = sizeof(ddsd);
        ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT ;
        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
        ddsd.dwWidth = surf_width;
        ddsd.dwHeight = surf_height;



        ddrval=lpDD->CreateSurface(&ddsd,&surf,NULL);


        if (ddrval!=DD_OK) {


                DeleteObject(bit);
                return NULL;

        } else {


                surf->GetDC(&hdc);



                HDC bit_dc=CreateCompatibleDC(hdc);


                SelectObject(bit_dc,bit);
                BitBlt(hdc,0,0,surf_width,surf_height,bit_dc,0,0,SRCCOPY);


                surf->ReleaseDC(hdc);
                DeleteDC(bit_dc);
        }



        DeleteObject(bit);


        return surf;
}



DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb) //颜色匹配
{
    COLORREF rgbT;
    HDC hdc;
    DWORD dw = CLR_INVALID;
    DDSURFACEDESC ddsd;
    HRESULT hres;

    //
    //use GDI SetPixel to color match for us
    //
    if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
    {
      rgbT = GetPixel(hdc, 0, 0);             // save current pixel value
      SetPixel(hdc, 0, 0, rgb);               // set our value
      pdds->ReleaseDC(hdc);
    }

    //
    // now lock the surface so we can read back the converted color
    //
    ddsd.dwSize = sizeof(ddsd);
    while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
      ;

    if (hres == DD_OK)
    {
      dw= *(DWORD *)ddsd.lpSurface;                     // get DWORD
      dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;// mask it to bpp
      pdds->Unlock(NULL);
    }

    //
    //now put the color that was there back.
    //
    if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
    {
      SetPixel(hdc, 0, 0, rgbT);
      pdds->ReleaseDC(hdc);
    }

    return dw;
}

/*
* DDSetColorKey
*
* set a color key for a surface, given a RGB.
* if you pass CLR_INVALID as the color key, the pixel
* in the upper-left corner will be used.
*/
HRESULT DDSetColorKey(IDirectDrawSurface *pdds, COLORREF rgb) //关键色设置
{
    DDCOLORKEY          ddck;

    ddck.dwColorSpaceLowValue= DDColorMatch(pdds, rgb);
    ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
    return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
}



我花了一小时写的!!!!!!!!!!!!!!!!!!!!!!
游戏下载地址 hays2002.51.net/game1.rar

游侠无极限 发表于 2004-4-8 20:54:00

干什么的?走迷宫?

还有,代码中混杂英语和中文注译,我怀疑英文部分不是你原创

hzzh 发表于 2004-4-9 16:15:00

楼主牛,我一小时只能读懂程序结构和实现方法。
不过void Delay(long time) 函数有问题,把CPU时间都白白吃光了,应该改成Sleep()

yzhlinux 发表于 2004-4-9 19:35:00

不是吧,这样的程序都叫"最"简单了啊,我看来都是在写白痴程序了

hays2002 发表于 2004-4-10 15:23:00

绝对原创。。。。。。void Delay(long time)   函数的功能就是用来延时的。。。。。。

yzhlinux 发表于 2004-4-10 21:36:00

以下是引用hays2002在2004-4-10 15:23:06的发言:
绝对原创。。。。。。void Delay(long time)   函数的功能就是用来延时的。。。。。。

延时还有比Sleep(int)更好的吗?不浪费cpy啊,你用循环来拖延真是大胆创新啊

游侠无极限 发表于 2004-4-11 15:59:00

循环延时有是有的,不过会造成不同配置上的延时的不一致

再问一次,这个游戏到底是游的什么???

男人 发表于 2004-4-12 16:21:00

是什么游戏啊

hzzh 发表于 2004-4-12 16:58:00

以下是引用hays2002在2004-4-10 15:23:06的发言:
绝对原创。。。。。。void Delay(long time)   函数的功能就是用来延时的。。。。。。

void Delay(long time)   确实可以用来延时,而且延时也比较准,但是Delay()是用CPU满负荷运行换来的。
在你的程序中把Delay(long time) 换成Sleep(long time) ,然后看看CPU的负荷就知道了。
按理说能够在一小时内编出这个游戏的人不会不知道考虑CPU效率的,除非你喜欢让CPU发烧。

唐明 发表于 2004-5-8 19:31:00

timeSetEvent 这个winAPI来定时不是更好马,毫秒精度应该也可以了
另外好像是用mfc还是什么的,mfc总是把我盟在雇里

qztx 发表于 2005-6-6 18:09:00

rpg吗?呵呵

Eagle 发表于 2005-6-7 08:45:00

楼主的编码风格真好,一会用C++的风格,一会儿用C的风格,不知道楼主是不是学这两种语言的时候走火入魔了。
页: [1]
查看完整版本: 最简单的游戏程序代码~