几个月前在图书馆逛,突然兴起想开始学习游戏编程。花了将近100大洋买了本《逐梦之旅》,书很好,但是阅读的过程中缺少练习,有种纸上得来终觉浅的感觉,二话不说。利用书上程序和贴图示例,自己给自己出了道练习题。由于刚开始接触Windows游戏编程,程序还有很多问题,下面共享一下自己的程序。总结自己的学习,希望得到一些建议。程序运行效果:

//----------------包含文件----------------//
#include<windows.h>
#include<tchar.h>
#include<time.h>#pragma  comment(lib,"Msimg32.lib")     //添加使用TransparentBlt函数所需的库文件
//--------------宏定义部分-----------------//
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE L"窗口核心程序"#define SPRITE_NUM 30//-----------------全局结构体-------------------//
struct Sprite
{int x,y;int direction;bool exist;
};struct Xiaoyao
{int x,y;int direction;bool exist;
};//-----------------全局变量声明-------------------//
HDC g_hdc = NULL;  //设备环境句柄
HDC g_mdc = NULL;  //二级缓冲区环境
HDC g_bufdc = NULL;    //三级缓冲区环境
HBITMAP g_Background = NULL;   //背景对象
int bg_Offset = 0;             //背景
HBITMAP g_Xiaoyao[4] = {0};        //李逍遥 可控制
HBITMAP g_Sprite[4] = {0};     //乱窜的精灵 四个移动方向
HBITMAP g_Swordman = NULL;     //Swordman对象
int Swordman_Xmouse = 0,Swordman_Ymouse = 0,Swordman_Xbitmap = 0,Swordman_Ybitmap = 0;  //记录swordman的位置Sprite Sprites[SPRITE_NUM];      //每个小精灵是一个结构体
Xiaoyao Xiaoyao1;               //李逍遥的结构体DWORD g_tNow = 0,g_tPre = 0; //用于记录游戏时间,驱动游戏循环int Xiaoyao_Num = 0;
int Sprite_Num = 0;
RECT rect;
POINT pt,lt,rb;//--------------------创建字体-------------------//
HFONT hFont;
wchar_t str[20]={0};       //用于存储
//--------------全局函数的声明------------//
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);BOOL Game_Init(HWND hwnd); //资源初始化
VOID Game_Paint(HWND hwnd); //进行绘图代码的书写
BOOL Game_CleanUp(HWND hwnd); //在此进行资源的清理//--------------WinMain( )函数-----------------//
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdLine, int nShowCmd)
{//建立完整的窗口类WNDCLASSEX wndClass = {0};wndClass.cbSize = sizeof( WNDCLASSEX );wndClass.style = CS_HREDRAW | CS_VREDRAW;wndClass.lpfnWndProc = WndProc;wndClass.cbClsExtra = 0;wndClass.cbWndExtra = 0;wndClass.hInstance = hInstance;wndClass.hIcon = (HICON)::LoadImage(NULL,L"game.ico", IMAGE_ICON,0,0, LR_DEFAULTSIZE|LR_LOADFROMFILE );wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);wndClass.lpszMenuName = NULL;wndClass.lpszClassName =L"ForTheDream";//注册窗口类if(!RegisterClassEx(&wndClass))return -1;//创建窗口HWND hwnd = CreateWindow(L"ForTheDream",WINDOW_TITLE,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,WINDOW_WIDTH,WINDOW_HEIGHT,NULL,NULL,hInstance,NULL);//窗口的移动、显示与更新MoveWindow(hwnd, 250,80,WINDOW_WIDTH,WINDOW_HEIGHT,true);ShowWindow(hwnd,nShowCmd);UpdateWindow(hwnd);//游戏初始化,若失败,弹出对话框,返回FALSEif(!Game_Init(hwnd)){MessageBox( hwnd, L"游戏初始化失败", L"消息窗口",0);return FALSE;}//消息循环MSG msg ={0};while(msg.message != WM_QUIT){if(PeekMessage(&msg,0,0,0,PM_REMOVE)){TranslateMessage(&msg);DispatchMessage(&msg);}else{g_tNow = GetTickCount();  //游戏循环if(g_tNow-g_tPre>=100){Game_Paint(hwnd);}}}//窗口类的注销UnregisterClass(L"ForTheDream",wndClass.hInstance);return 0;
}//---------窗口过程函数----------//
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{//PAINTSTRUCT painstStruct;//记录绘制信息switch(message){case WM_KEYDOWN:switch(wParam){ case VK_ESCAPE:DestroyWindow(hwnd);break;case VK_UP:if(Xiaoyao1.exist == true){Xiaoyao1.direction = 0;Xiaoyao1.y -= 20;if(Xiaoyao1.y < 0)Xiaoyao1.y = 0;}break;case VK_DOWN:if(Xiaoyao1.exist == true){Xiaoyao1.direction =1;Xiaoyao1.y += 20;if(Xiaoyao1.y > WINDOW_HEIGHT-108)Xiaoyao1.y = WINDOW_HEIGHT-108;}break;case VK_LEFT:if(Xiaoyao1.exist == true){Xiaoyao1.direction =2;Xiaoyao1.x -= 20;if(Xiaoyao1.x < 0)Xiaoyao1.x = 0;}break;case VK_RIGHT:if(Xiaoyao1.exist == true){Xiaoyao1.direction =3;Xiaoyao1.x += 20;if(Xiaoyao1.x > WINDOW_WIDTH-60 )Xiaoyao1.x = WINDOW_WIDTH-60;}break;case VK_SPACE:Xiaoyao1.exist = !Xiaoyao1.exist;Xiaoyao1.x = Swordman_Xbitmap - 70;Xiaoyao1.y = Swordman_Ybitmap;Xiaoyao1.direction = 2;break;default:return DefWindowProc(hwnd,message,wParam,lParam);}break;case WM_LBUTTONDOWN:for(int i=0;i<SPRITE_NUM;i++){if(Sprites[i].exist == false){Sprites[i].x = Swordman_Xbitmap - 116;Sprites[i].y = Swordman_Ybitmap;Sprites[i].exist = true;break;}}break;case WM_MOUSEMOVE:Swordman_Xmouse = LOWORD(lParam);if(Swordman_Xmouse > WINDOW_WIDTH - 317)Swordman_Xmouse = WINDOW_WIDTH - 317;if(Swordman_Xmouse < 0)Swordman_Xmouse = 0;Swordman_Ymouse = HIWORD(lParam);if(Swordman_Ymouse > WINDOW_HEIGHT - 283)Swordman_Ymouse = WINDOW_HEIGHT - 283;if(Swordman_Ymouse < 0)Swordman_Ymouse =0;break;case WM_DESTROY:Game_CleanUp(hwnd);PostQuitMessage(0);break;default:return DefWindowProc(hwnd,message,wParam,lParam);}return 0;
}//---------------初始化函数,进行一些简单的初始化------------------//
BOOL Game_Init(HWND hwnd)
{wchar_t filename[30];  //用于载入四个方向的图片g_hdc = GetDC(hwnd);HBITMAP bmp;pt.x = 300;pt.y = 100;srand((unsigned)time(NULL)); // 得到随机种子//--------------限制鼠标在窗口客户区内---------------//GetClientRect(hwnd,&rect);lt.x = rect.left;lt.y = rect.top;rb.x = rect.right;rb.y = rect.bottom;ClientToScreen(hwnd,<);ClientToScreen(hwnd,&rb);rect.left = lt.x;rect.top = lt.y;rect.right = rb.x;rect.bottom = rb.y;ClipCursor(&rect);//---------------------设定光标初始位置,状态,属性---------------------//ClientToScreen(hwnd,&pt);SetCursorPos(pt.x,pt.y);ShowCursor(false);//初始各个设备环境g_mdc = CreateCompatibleDC(g_hdc);g_bufdc = CreateCompatibleDC(g_hdc);//初始各个设备环境bmp = CreateCompatibleBitmap(g_hdc,WINDOW_WIDTH,WINDOW_HEIGHT);SelectObject(g_mdc,bmp);//这里弄不清楚为什么有这两句话,但是凡是三缓冲的贴图的程序都是这么写的//初始化XiaoyaoXiaoyao1.exist = false;Xiaoyao1.x = 0;Xiaoyao1.y = 0;//初始化Xiaoyao//初始化 Sprites数组for(int i=0;i<SPRITE_NUM;i++){Sprites[i].exist = false;Sprites[i].direction = 2;}//初始化 Sprites数组//创建字体hFont = CreateFont(20,0,0,0,0,0,0,0,GB2312_CHARSET,0,0,0,0,TEXT("微软雅黑"));//载入所有图片g_Background = (HBITMAP)LoadImage(NULL,L"bg.bmp",IMAGE_BITMAP,WINDOW_WIDTH,WINDOW_HEIGHT,LR_LOADFROMFILE);g_Swordman = (HBITMAP)LoadImage(NULL,L"swordman.bmp",IMAGE_BITMAP,317,283,LR_LOADFROMFILE);for(int i=0;i<4;i++){memset(filename,0,sizeof(filename));  //清零swprintf_s(filename,L"%d.bmp",i+1);      //打印    g_Sprite[i] = (HBITMAP)LoadImage(NULL,filename,IMAGE_BITMAP,384,96,LR_LOADFROMFILE);}for(int i=0;i<4;i++){memset(filename,0,sizeof(filename));   //清零swprintf_s(filename,L"go%d.bmp",i+1);        //打印    g_Xiaoyao[i] = (HBITMAP)LoadImage(NULL,filename,IMAGE_BITMAP,480,216,LR_LOADFROMFILE);}//载入所有图片Swordman_Xbitmap=300;Swordman_Xmouse=300;Swordman_Ybitmap=100;Swordman_Ymouse=100;Game_Paint(hwnd);return TRUE;
}VOID Game_Paint(HWND hwnd)
{//-----------贴上滚动背景------------//SelectObject(g_bufdc,g_Background);BitBlt(g_mdc,0,0,bg_Offset,WINDOW_HEIGHT,g_bufdc,WINDOW_WIDTH-bg_Offset,0,SRCCOPY);//贴右边部分BitBlt(g_mdc,bg_Offset,0,WINDOW_WIDTH-bg_Offset,WINDOW_HEIGHT,g_bufdc,0,0,SRCCOPY);bg_Offset += 10; //滚动清零if(bg_Offset>=WINDOW_WIDTH)bg_Offset = 0;//---------------画李逍遥----------------//if(Xiaoyao1.exist == true){SelectObject(g_bufdc,g_Xiaoyao[Xiaoyao1.direction]);BitBlt(g_mdc,Xiaoyao1.x,Xiaoyao1.y,60,108,g_bufdc,Xiaoyao_Num*60,108,SRCAND);BitBlt(g_mdc,Xiaoyao1.x,Xiaoyao1.y,60,108,g_bufdc,Xiaoyao_Num*60,0,SRCPAINT);}Xiaoyao_Num++;if (Xiaoyao_Num == 8)Xiaoyao_Num = 0;//-----------------画Sprites------------------//for(int i=0;i<SPRITE_NUM;i++){if( Sprites[i].exist == true ){SelectObject(g_bufdc,g_Sprite[Sprites[i].direction]);TransparentBlt(g_mdc,Sprites[i].x,Sprites[i].y,96,96,g_bufdc,Sprite_Num*96,0,96,96,RGB(0,0,0));}}Sprite_Num++;if(Sprite_Num==4)Sprite_Num = 0;//实现乱窜就要随机数决定小精灵的方向for(int i=0;i<SPRITE_NUM;i++){if(Sprites[i].exist == true){switch(rand()%4){case 0:Sprites[i].direction = 0;Sprites[i].y -= 20;if(Sprites[i].y < 0)Sprites[i].y = 0;break;case 1:Sprites[i].direction = 1;Sprites[i].y += 20;if(Sprites[i].y > WINDOW_HEIGHT - 96)Sprites[i].y = WINDOW_HEIGHT-96;break;case 2:Sprites[i].direction = 2;Sprites[i].x -= 20;if(Sprites[i].x < 0)Sprites[i].x = 0;break;case 3:Sprites[i].direction = 3;Sprites[i].x += 20;if(Sprites[i].x > WINDOW_WIDTH - 96)Sprites[i].x = WINDOW_WIDTH - 96;break;}}}//--------------------画Swordman----------------------//if( Swordman_Xbitmap < Swordman_Xmouse ){Swordman_Xbitmap += 20;if(Swordman_Xbitmap>Swordman_Xmouse)Swordman_Xbitmap = Swordman_Xmouse;}else{Swordman_Xbitmap -= 20;if(Swordman_Xbitmap < Swordman_Xmouse)Swordman_Xbitmap = Swordman_Xmouse;}if(Swordman_Ybitmap < Swordman_Ymouse){Swordman_Ybitmap += 20;if(Swordman_Ybitmap > Swordman_Ymouse)Swordman_Ybitmap = Swordman_Ymouse;}else{Swordman_Ybitmap -= 20;if(Swordman_Ybitmap < Swordman_Ymouse)Swordman_Ybitmap = Swordman_Ymouse;}SelectObject(g_bufdc,g_Swordman);TransparentBlt(g_mdc,Swordman_Xbitmap,Swordman_Ybitmap,317,283,g_bufdc,0,0,317,283,RGB(0,0,0));//----------写入控制命令----------//SelectObject(g_mdc,hFont);SetBkMode(g_mdc,TRANSPARENT);SetTextColor(g_mdc,RGB(0,0,0));swprintf_s(str,L"鼠标控制方向");TextOut(g_mdc,0,0,str,wcslen(str));memset(str,0,sizeof(str));swprintf_s(str,L"单机放出乱窜的小精灵");TextOut(g_mdc,0,20,str,wcslen(str));memset(str,0,sizeof(str));swprintf_s(str,L"按Space释放由光标控制的李逍遥");TextOut(g_mdc,0,40,str,wcslen(str));memset(str,0,sizeof(str));//------------汇总贴图------------//BitBlt(g_hdc,0,0,WINDOW_WIDTH,WINDOW_HEIGHT,g_mdc,0,0,SRCCOPY);g_tPre = GetTickCount(); //游戏循环}BOOL Game_CleanUp(HWND hwnd)
{DeleteObject(g_Background);for(int i=0;i<4;i++)DeleteObject(g_Sprite[i]);for(int i=0;i<4;i++)DeleteObject(g_Xiaoyao[i]);DeleteObject(g_Swordman);DeleteDC(g_bufdc);DeleteDC(g_mdc);ReleaseDC(hwnd,g_hdc);return TRUE;
}

经验积累:

1.贴图时,使用结构体记录贴图对象的运动信息(位置,是否存在,运动方向);在窗口过程函数(wndProc)里,不断接受信息,并根据信息修改结构体中对象信息;在绘图函数(Game_Paint)中,不断根据结构体内记录的对象信息,绘制贴图。

遗留问题:

1.程序运行时总感觉有些卡顿,不知道是什么原因。

2.为什么程序中需要加上如下语句:

 bmp = CreateCompatibleBitmap(g_hdc,WINDOW_WIDTH,WINDOW_HEIGHT);SelectObject(g_mdc,bmp);//这里弄不清楚为什么有这两句话,但是凡是三缓冲的贴图的程序都是这么写的

测试发现如果不加上这两句话,程序无法正常运行,查阅书中,并没有深入讨论这两句话的意思?

记录学习历程-----游戏编程相关推荐

  1. 小人物走路、奔跑的VC++游戏特效,适合刚学习VC++游戏编程的朋友

    一个VC++游戏中的模块效果,小人物走路.奔跑效果,用方向键即可在控制小人的走动,当然了,源码还是比较基础的,适合于刚学习VC++游戏编程的朋友们. 界面效果展示: 源码目录结构图: 部分源码展示(由 ...

  2. 学习计算机游戏编程,在线游戏学编程,游戏编程汇总

    21世纪必备技能中,计算机成了现在流行的热门课程,今天小编给大家介绍了一些和游戏结合的编程学习平台,让大家对这门枯燥乏味的编程学习尽量变得有趣.下面介绍的游戏编程中有适合作为入门的编程游戏,还有些可能 ...

  3. DX9贴图-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(11)

    DX9贴图 先准备2张图片,蜘蛛为m1.png,单眼怪物为m2.png 创建一个Form1.frm,输入如下源码: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体 ...

  4. DX9显示文字-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(14)

    DX9显示文字 创建Form1,输入以下源码: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体的 BorderStyle 设置为"Fixed singl ...

  5. DX9光照效果-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(12)

    DX9光照效果 先准备好一张背景贴图砖片bgimg.png 然后在Form1.frm中放入如下代码: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体的 Borde ...

  6. DX9绘图-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(8)

    DX9绘图 前边讲了一些绘图基础,看不懂不要紧,其实我也看不懂哦.数学基础不好的话,确实不容易看懂,但只要懂的调用,能完成想要做的工作,那就马马虎虎吧,若是深入研究的话,建议买本计算机视觉艺术,计算机 ...

  7. DX9鼠标检测-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(16)

    DX9鼠标检测 新建一个Form1,输入如下代码: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体的 BorderStyle 设置为"Fixed sin ...

  8. DX9绘制虚线抗锯齿线-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(13)

    DX9绘制虚线抗锯齿线 划线扩展 绘制划线的实际效果图如下: 新建一个Form1,代码如下: Private Sub Form_Load()'新手注意:游戏编程中, '通常将窗体的 BorderSty ...

  9. VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(1)

    前言 打开CSDN或者度娘(谷哥被墙了,搜索不了),关键词"VB6 dx9 DirectX9 游戏源码",你会发现,讲解DX9技术的文章很多,但是跟VB6都没什么关系.偶有几片文章 ...

  10. Direct3D体系结构-------VB6编程学习DX9游戏编程DirectX9编程2D小游戏源码冷风引擎CoolWind2D游戏引擎(3)

    Direct3D体系结构 以下为本人自学DX9的记录,整理出来是方便大家学习DX9底层基础知识的, 如果你不想学习Direct3D 的原理的话,想直接使用冷风引擎(CoolWind2D游戏引擎), 请 ...

最新文章

  1. “AI明星”第四范式C轮融资超10亿元,估值约12亿美元
  2. ios 如何对UITableView中的内容进行排序
  3. 安卓如何限制横屏和竖屏
  4. case分支 shell函数 字符串的处理
  5. 接口测试工具postman安装及使用
  6. mysql忽略列,MySQL:使用DISTINCT时忽略选定的列
  7. .NET技术之美-网络编程
  8. Gradle 工具的源码研究
  9. ORACLE数据库常用命令总结
  10. 探讨一个好算法——找出一百万个数字中十个最大数字的算法
  11. python静态方法_Python静态方法
  12. 虚拟机安装CentOS系统教程(详细)
  13. 错误:VM5729:1 Blocked script execution in ‘about:blank‘
  14. 蓝底换白底边缘不干净_蓝底换白底【解决措施】
  15. supervisor前端-cesi的安装
  16. 新手学平面设计都会遇到哪些问题
  17. [中国近代史] 第五章测验
  18. 狄利克雷分布的matlab代码实现和R语言函数调用
  19. 英语不好,能不能学会编程?
  20. MySQL Transportable Tablespace

热门文章

  1. 超声波模块工作原理分析及程序
  2. pygame 实现 pong 小游戏
  3. 反思-我们真的初老了么?
  4. bldc不同载波频率_BLDC的双闭环老调不好,求帮助
  5. 【递推】种萝卜 C++题解
  6. 一名爱折腾人士的Apps for iPhone分享
  7. pwn|软件安全相关问题学习笔记
  8. 累计独立访客(UV)不低于 1000是什么意思?如何查看自己小程序的UV数量?
  9. 基于SpringBoot的框架SOFABoot,青出于蓝而胜于蓝
  10. 一只小野鸭的超能量(超有启发性)