在游戏开发中背景卷轴的详细分析-游戏开发频道-中国IT实验室-技术·资讯·教育·服务·社区
首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
 您现在的位置: 中国IT实验室 >> 游戏开发 >> 游戏开发入门 >> 正文
在游戏开发中背景卷轴的详细分析
来源:ChinaItLab 作者: 时间:2004-12-26


  
 

  在 Windowed Mode(窗口模式) 下使用计时器卷动背景图象。
  编译成功后拖曳窗口改变大小,确认图象可以随着画面伸缩。
  另外,尝试进一步简化源程序。
  卷轴有各种各样的卷法,这回我们用下面的方式卷:
  
  1. 用两张相同的图片左右并排拼成一张。
  (下面是我用的图片, 640*240 。用两张 320*240 的图片拼的,命名为 "约塞米蒂山谷.bmp" ,放在 G:\DirectX 8\ 下。)
  

  2. 因为画面的初始大小是 640*480 ,所以把上面的图片扩展到 1280*480 ,储存在 BmpSurface :
  if (FAILED(hr= g_pDisplay->CreateSurfaceFromBitmap(&g_pBmpSurface,
  "E:\\DirectX 8\\约塞米蒂山谷.bmp",1280,480)))
  return hr;
  
  3. 启动计时器控制卷轴速度。
  指定计时间隔 20 毫秒:
  #define   ID_TIMER  32767
  :
  SetTimer(hWnd,ID_TIMER,20,NULL);
  
  
  4. 在计时器(WM_TIMER)中计数 g_cnt :
  int     g_cnt     = 0;
  :
  case WM_TIMER:
  g_cnt++;
  break;
  
  
  5. 把作为背景描绘的 BmpSurface 的矩形区域设定为 RECT 结构体。
  画面初始大小是 640*480 :
  RECT  rt;
  
  top= 0;
  rt.bottom= 480;
  rt.left= g_cnt%640;
  rt.right= rt.left+640;
  
  6. 从图片的左端(横坐标 = 0)向中间(横坐标 = 639)一边挪动一边描绘:
  g_pDisplay->Blt(0,0,g_pBmpSurface,&rt);
  if (FAILED(hr= g_pDisplay->Present())) return hr;
  
  
  7. 横坐标达到 640 就返回到左端(横坐标 = 0)。(注意那个 g_cnt%640)。
  如果你的图片不是用两张相同的图片左右拼起来的,卷轴的时候看起来就很不舒服:卷到末尾、忽然跳到开头;再卷到末尾、再忽然跳到开头……感觉并不是连续卷轴。你可以把一张图片裁成 640*240 试试。
  8. 退出程序时关闭计时器:
  case WM_DESTROY:
  KillTimer(hWnd, ID_TIMER);
  
  下面把创建窗口的代码给它尽量简化。
  
  640*480 是窗口的初始大小,我们用 ddutil.cpp 里面的 CreateWindowedDisplay() 函数重新设定窗口大小:
  WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst,
  NULL,NULL,NULL,NULL,NAME
  };
  if (RegisterClass(&wc)==0)  return FALSE;
  
  HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,0,0,640,480,
  GetDesktopWindow(),NULL,wc.hInstance,NULL);
  if (hWnd==NULL)  return FALSE;
  
  
  虽说有 WNDCLASS 和 WNDCLASSEX 两种类型,如果不使用扩展机能,实际上用哪个都一样。
  这里开出 WNDCLASSEX 的代码:
  WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst,
  NULL,NULL,NULL,NULL,NAME,NULL
  };
  if (RegisterClassEx(&wc)==0)  return FALSE;
  
  
  实际决定窗口大小的 CreateWindowedDisplay() :
  if (FAILED(hr = g_pDisplay->CreateWindowedDisplay(hWnd,640,480)))
  {  ERMSG("Failed initializing DirectDraw.");
  return hr;
  }
  
  
  下面说明工程的创建方法。
  
  1. 新建一个 Win32 Application 空白工程,命名为 "Scrool"。
  
  2. 向工程中新建一个 C++ Source File ,命名为 "scrool" ,向其中键入篇末附带的源程序。
  
  3. 把下面4个文件复制到工程文件夹(我是 G:\DirectX 8\Scrool\):
  E:\Mssdk\samples\Multimedia\Common\include\ddutil.h
  E:\Mssdk\samples\Multimedia\Common\include\dxutil.h
  E:\Mssdk\samples\Multimedia\Common\src\ddutil.cpp
  E:\Mssdk\samples\Multimedia\Common\src\dxutil.cpp
  然后选择菜单 [Project|工程]-[Add To Project|添加到工程]-[Files...|文件...] ,向工程中添加这4个文件。
  
  4. 准备合适的图象文件(我是在 G:\DirectX 8\ 下放了张 "约塞米蒂山谷.bmp" ,参见本章开头)。
  
  5. 选择菜单 [Project|工程]-[Settings...|设定...] 打开[Project Settings|工程设定] 面板,点击 [Link|链接] 标签,向 [Object/library modules|对象、库模块] 栏内添加下面4个库文件:
  dxguid.lib
  ddraw.lib
  dxerr8.lib
  winmm.lib
  
  6. 编译并执行!
  源程序:
  /*****************************************/
  /*★ 背景卷轴   2001-01-14 前田 稔 ★*/
  /*****************************************/
  #define   NAME    "BMP Scrool"
  #define   STRICT
  #include  
  #include  
  #include  
  #include  "ddutil.h"
  
  #define   ID_TIMER  32767
  
  // Defines, constants, and global variables
  #define SAFE_DELETE(p) { if (p) { delete (p);   (p)=NULL; } }
  #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
  #define ERMSG(x)    MessageBox(hWnd, x, "DirectDraw Samplee", MB_OK);
  
  CDisplay*  g_pDisplay  = NULL;
  CSurface*  g_pBmpSurface = NULL;
  BOOL    g_bActive   = FALSE;
  int     g_cnt     = 0;
  
  // Function-prototypes
  LRESULT   CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  HRESULT   InitDraw(HWND hWnd);
  VOID    FreeDraw();
  HRESULT   DisplayFrame();
  
  //★ Windows Main
  int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow)
  {  MSG   msg;
  /*
  WNDCLASSEX wc = { sizeof(WNDCLASSEX),CS_CLASSDC,WndProc,0L,0L,hInst,
  NULL,NULL,NULL,NULL,NAME,NULL
  };
  if (RegisterClassEx(&wc)==0)  return FALSE;
  */
  WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst,
  NULL,NULL,NULL,NULL,NAME
  };
  if (RegisterClass(&wc)==0)  return FALSE;
  
  HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,0,0,640,480,
  GetDesktopWindow(),NULL,wc.hInstance,NULL);
  if (hWnd==NULL)  return FALSE;
  
  if (FAILED(InitDraw(hWnd)))
  {  if (g_pDisplay)
  g_pDisplay->GetDirectDraw()->SetCooperativeLevel(NULL, DDSCL_NORMAL);
  ERMSG("DirectDraw init failed. The sample will now exit.");
  return FALSE;
  }
  
  ShowWindow(hWnd, nCmdShow);
  UpdateWindow(hWnd);
  SetTimer(hWnd,ID_TIMER,20,NULL);
  while(TRUE)
  {  if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
  {  if (0 == GetMessage(&msg, NULL, 0, 0)) return (int)msg.wParam;
  TranslateMessage(&msg);
  DispatchMessage(&msg);
  }
  else
  {  if (g_bActive)
  {  if (FAILED(DisplayFrame()))
  {  SAFE_DELETE(g_pDisplay);
  ERMSG("Displaying the next frame failed");
  return FALSE;
  }
  }
  else  WaitMessage();
  }
  }
  }
  
  //★ WndProc()
  LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  {  switch (msg)
  {  case WM_KEYDOWN:
  PostMessage(hWnd,WM_CLOSE,0,0);
  return 0L;
  case WM_TIMER:
  g_cnt++;
  break;
  case WM_PAINT:
  if (g_pDisplay)
  {  // Display the new position of the sprite
  if (DisplayFrame() == DDERR_SURFACELOST)
  {  PostMessage(hWnd,WM_CLOSE,0,0);
  }
  }
  break;
  case WM_MOVE:
  if (g_pDisplay)  g_pDisplay->UpdateBounds();
  return 0L;
  case WM_SIZE:
  // Check to see if we are losing our window...
  if (SIZE_MAXHIDE==wParam||SIZE_MINIMIZED==wParam) g_bActive= FALSE;
  else  g_bActive= TRUE;
  if (g_pDisplay)  g_pDisplay->UpdateBounds();
  break;
  case WM_DESTROY:
  KillTimer(hWnd, ID_TIMER);
  FreeDraw();
  PostQuitMessage(0);
  return 0L;
  }
  return DefWindowProc(hWnd, msg, wParam, lParam);
  }
  
  //★ InitDraw()
  HRESULT InitDraw(HWND hWnd)
  {  HRESULT   hr;
  
  g_pDisplay = new CDisplay();
  if (FAILED(hr = g_pDisplay->CreateWindowedDisplay(hWnd,640,480)))
  {  ERMSG("Failed initializing DirectDraw.");
  return hr;
  }
  if (FAILED(hr= g_pDisplay->CreateSurfaceFromBitmap(&g_pBmpSurface,
  "G:\\DirectX 8\\约塞米蒂山谷.bmp",1280,480)))
  return
【责编:admin】

中国IT教育热线咨询

相关文章
游戏开发新手入门之位图化图形
给希望成为游戏美术设计师的朋友
Ogre游戏引擎鼠标选取物体演示  
所有绘画的核心灵魂——素描知识
DirectDraw与DirectInput游戏编程体验
推荐文章

 精彩友情推荐
·Asp源码 PHP源码
·CGI源码 JSP源码
·建站书籍教程
·服务器软件 .net源码
·建站工具软件
·IDC资讯大全
·机房品质万里行
·IDC托管必备知识
·全国IDC报价
·网站推广优化
 基础入门  开发文档
 最新推荐
  多数的Windows程序都需要Windows.h和Windowsx.h这两个头文件,要确保使用它们。当然,你还需要其它......
游戏引擎演化史
在Windows上安装OGRE的方法
关于滤镜遮罩概念,Sobel 遮罩
游戏开发新手入门之Windows编程
游戏开发新手入门之位图化图形
教你实现卡通渲染的另类勾边方法
游戏设计大师谈如何成为一名游戏设
Visual C#编写 3D游戏框架示例
真正的 Java 学习从入门到精通
游戏开发经验——游戏开发的基本常
  为什么要研究攻击行为在人类有记载的5600年的历史中,共计发生了14,400次战争;今天,平均一天要发生............
游戏开发中显示对话的特殊句法
游戏原型设计的介绍
网络游戏中的攻击行为
谈动作类游戏的必要条件
规则的多元分析模式
载入位图文件到DirectDraw
Archer Game Suite 是什么?
浅谈游戏企划-新手入门篇
暴雪称霸游戏业界的六大秘密绝招
骨骼动画及示例Skinned Mesh的解析
  培训中心