通常进入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也不知道加多少次,等到下一秒绘制的时候,棋子都不知道到那里去了~~