quake3源码分析(五)
启动主菜单
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
Sys_CreateConsole();//创建一个用一输出的窗口
Com_Init( sys_cmdline );//相关的初始化操作,加载动态库(opengl32.dll)
NET_Init();//网络初始化
while( 1 ) { //主循环
if ( g_wv.isMinimized || ( com_dedicated && com_dedicated->integer ) ) {
Sleep( 5 );
}
// make sure mouse and joystick are only called once a frame
IN_Frame();
// run the game
Com_Frame();
}
}
void Com_Frame( void )
{
// we may want to spin here if things are going too fast
if ( !com_dedicated->integer && com_maxfps->integer > 0 && !com_timedemo->integer ) {
minMsec = 1000 / com_maxfps->integer;
} else {
minMsec = 1;
}
do {
com_frameTime = Com_EventLoop();
if ( lastTime > com_frameTime ) {
lastTime = com_frameTime; // possible on first frame
}
msec = com_frameTime - lastTime;
} while ( msec < minMsec );
Cbuf_Execute ();
…..
SV_Frame( msec );//server side
……
//client system
Com_EventLoop();
Cbuf_Execute ();
CL_Frame( msec );
}
int Com_EventLoop( void )
{
while ( 1 )
{
ev = Com_GetEvent();//从缓冲区中得到一个event,(缓冲区的event从键盘,mouse,控制台及网络中得到)
// if no more events are available
if ( ev.evType == SE_NONE ) {
// manually send packet events for the loopback channel
while ( NET_GetLoopPacket( NS_CLIENT, &evFrom, &buf ) ) {
CL_PacketEvent( evFrom, &buf );
}
while ( NET_GetLoopPacket( NS_SERVER, &evFrom, &buf ) ) {
// if the server just shut down, flush the events
if ( com_sv_running->integer ) {
Com_RunAndTimeServerPacket( &evFrom, &buf );
}
}
return ev.evTime;
}
//根据event的类型进行处理
switch ( ev.evType ) {
default:
// bk001129 - was ev.evTime
Com_Error( ERR_FATAL, "Com_EventLoop: bad event type %i", ev.evType );
break;
case SE_NONE:
break;
case SE_KEY://键盘事件,一个键按下放开共分3个event,一个SE_KEY按下,一个SE_CHAR,一个SE_KEY没按下
CL_KeyEvent( ev.evValue, ev.evValue2, ev.evTime );
break;
case SE_CHAR:
CL_CharEvent( ev.evValue );
break;
case SE_MOUSE:
CL_MouseEvent( ev.evValue, ev.evValue2, ev.evTime );
break;
}
}
}
void CL_KeyEvent (int key, qboolean down, unsigned time)
{
//当第一次进行游戏,按下”ESC”键之后,会调下面这个函数
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );(vm.c文件)
}
int QDECL VM_Call( vm_t *vm, int callnum, ... )
{
//如果vm已经加载了DLL动态库,调用:vm.name=”ui”àvu_main.c(vmMain);
//vm.name=”cgame”àcg_main.c(vmMain)
r = vm->entryPoint( callnum, args[0], args[1], args[2], args[3],
args[4], args[5], args[6], args[7],
args[8], args[9], args[10], args[11],
args[12], args[13], args[14], args[15]);
}