WIN32框架下的循环(Gameloop)与绘制(Render)

来源:互联网 发布:淘宝名字大全男生4个字 编辑:程序博客网 时间:2024/06/10 21:04

通常进入WinMain函数之后,系统循环条件【if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))】之后写一个else,在else里面处理自己的循环和绘制;
如下代码所示:

 while (TRUE)
 {
  if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
   if (msg.message == WM_QUIT)
    break;
   if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
  }
  else
  {
   Gameloop();
   Render();   
  }
1、通常情况下,Render()函数不写到Gameloop()里面,然后单独调用Gameloop();我的理解是Render()的绘制需要一定的刷新频率,而gameloop一般是处理时间函数循环的逻辑帧数的,比如说18帧一秒(客户端),3帧一秒(服务器),处理的都是逻辑层面的东西;而绘制放到这里面肯等不行,肯定会不出图来。

2、逻辑层控制绘制层
(1)可以在逻辑循环内部控制循环帧数
比如说:if (g_nGameCounter % GAME_FPS == 0) 可以把原来一秒18次的逻辑帧数改成一秒一次,这里面进行一些逻辑操作;
(2)注意g_nGameCounter++ 的位置
g_nGameCounter 是一个全局变量,就是用它来控制逻辑帧数的频率;
g_nGameCounter++ 的位置,第一次写到了if (g_nGameCounter % GAME_FPS == 0){}里面,【当时没有深刻理解g_nGameCounter++ 的作用,只是简单的模仿】,认为应该有这样的一个步骤;其实g_nGameCounter 是用来控制llLatency 表达式的值的,当llLatency >0的时候,g_nGameCounter 加1,加过1的结果是llLatency<0,于是 GetElapse() * GAME_FPS 继续增加直到llLatency>0满足if(llLatency > 0)条件;如果写在里面,则g_nGameCounter 加过之后等于1,GetElapse() * GAME_FPS - g_nGameCounter * 1000 大于 g_nGameCounter * 1000 是必然的!,但是只有g_nGameCounter % GAME_FPS == 0的时候 g_nGameCounter才可以再次加1;但是这样的条件可以达到吗?显然不可以,所以 llLatency永远大于0,但是永远不可能进入 if (g_nGameCounter % GAME_FPS == 0)也就不会执行BShow = !BShow; 从而造成一系列的逻辑后果!
void Gameloop()
{
 //Render();
 //INT64 位时间计数,保证数据不越界
 INT64 llLatency = GetElapse() * GAME_FPS - g_nGameCounter * 1000;
 if(llLatency > 0)
 {
  if (g_nGameCounter % GAME_FPS == 0)
  {
   BShow = !BShow;    //每过一秒BShow状态变化一次
   //g_nGameCounter = g_nGameCounter+ 1;     //不能写到这个里面,否则g_nGameCounter永远只能为1
  }
  
  g_nGameCounter += 1;    //llLatency 大于零的时候 计数加1
 }
}

3、Render()的内部实现
(1)Render()函数可以写进void Gameloop()的最开始处,因为Gameloop()被调用的频率很高,就是while循环进入else的频率;所以绘制不会出问题。
int g_nState;
void Draw()
{
 int Tempx = 0;
 int Tempy = 0;
 float TranslateX = 30 - 12.5f;
 float TranslateY = 30 - 12.5f;
 
 Tempx = 30 * g_nState;
 Tempy = 30 * g_nState;
 TranslateX = float(Tempx)-12.5f;
 TranslateY = float(Tempy)-12.5f;
 
 if (BShow == false) 
 {
  if(g_nState <= 10)
   g_nState++;
  //else if(g_nState <= 20)
  // g_nState--;
  BShow = true;
 }  
  //d3dxsprite渲染
  m_lpD3dxsprite->Draw(m_lpTexterWhite,NULL,NULL,NULL,0.0f,&D3DXVECTOR2(TranslateX,TranslateY),0xFFFF0000);
 //0xFFFF0000 原来可以控制棋子的颜色,
 //第一个参数,指向IDirect3DTexture9;第二个参数,控制资源的完整性,为NULL则加载的完整的资源;第三个参数,控制图片大小,为NULL则是图片原始大小;
 //第四个参数,控制相对于中心的旋转度;第五个参数,lue;第六个参数,控制图片位置;第七个参数,控制图片颜色,0xFFFFFFFF保持图片原有颜色;
}

(1)首先定义全局变量g_nState;最重要的是清楚Draw()函数被调用的频率很高,次数很多,给Tempx ,Tempy赋的初值一定要在全局变量里面保存起来;否则每次都是从新被初始化;
还有就是 在Draw()里面写循环函数的时候要注意了;最早在if (BShow == false){}里面加了一个循环,结果企图用局部变量i来实现棋子的移动,其实是错误的,因为i没有保存
下来,保存了也是每次调用Draw的时候被初始化,可以认为Draw()被调用的过程,就是一个循环的过程~~呵呵,又掌握了一招撒~~
(2)BShow = true;这句话含量横高,意思是说在全局变量g_nState累加的时候,变化BShow的状态,从而保证一秒g_nState加一次;不然的话g_nState == false 的时间也是一秒,
这一秒调用Draw()的次数不知道多少次,g_nState也不知道加多少次,等到下一秒绘制的时候,棋子都不知道到那里去了~~

原创粉丝点击