本篇是創建游戲內核(2)
【接口與實現分離版】的續篇,關于該內核的細節說明請參考創建游戲內核(3),這個版本主要是按照功能劃分模塊的思想,并嚴格按照接口與實現相分離的原則來寫的,沒有用面向對象的思想來寫,沒有繼承沒有多態。大家可以對比兩個版本,比較優劣。
給用戶的接口:
/*************************************************************************
PURPOSE:
Interface for smanager stack.
*************************************************************************/
#ifndef _CORE_MANAGER_H_
#define _CORE_MANAGER_H_
enum PURPOSE
{
NO_PURPOSE = 0,
INIT_PURPOSE,
SHUTDOWN_PURPOSE,
FRAME_PURPOSE
};
typedef void (*MANAGER_FUNC)(void* data, long purpose);
typedef void* MANAGER;
typedef MANAGER* MANAGER_PTR;
typedef int BOOL;
MANAGER manager_create();
void manager_push(MANAGER_PTR top_manager, MANAGER_FUNC func, void* data);
BOOL manager_pop(MANAGER_PTR top_manager, void* data);
void manager_destroy(MANAGER_PTR top_manager, void* data);
BOOL manager_process(MANAGER_PTR top_manager, void* data);
void manager_process_all(MANAGER top_manager, void* data);
#endif
接口的實現:
/*************************************************************************
PURPOSE:
Implements for manager stack.
*************************************************************************/
#include <malloc.h>
#include <memory.h>
#include "core_manager.h"
#pragma warning(disable : 4996)
#define NULL 0
#define TRUE 1
#define FALSE 0
typedef struct _MANAGER
{
MANAGER_FUNC func;
_MANAGER* next;
} *_MANAGER_PTR;
//------------------------------------------------------------------------
// Create manager object.
//------------------------------------------------------------------------
MANAGER manager_create()
{
_MANAGER_PTR _manager = (_MANAGER_PTR) malloc(sizeof(_MANAGER));
memset(_manager, 0, sizeof(_MANAGER));
return (MANAGER) _manager;
}
//------------------------------------------------------------------------
// Push one manager function into manager stack.
//------------------------------------------------------------------------
void manager_push(MANAGER_PTR top_manager, MANAGER_FUNC func, void* data)
{
if(func == NULL)
return;
// allocate a new manager and push it into stack
_MANAGER_PTR new_manager = (_MANAGER_PTR) malloc(sizeof(_MANAGER));
new_manager->func = func;
new_manager->next = (_MANAGER_PTR) *top_manager;
*top_manager = (MANAGER) new_manager;
// call manager function with init purpose
new_manager->func(data, INIT_PURPOSE);
}
//------------------------------------------------------------------------
// Pop top manager object from manager stack.
//------------------------------------------------------------------------
BOOL manager_pop(MANAGER_PTR top_manager, void* data)
{
if(top_manager == NULL || *top_manager == NULL)
return FALSE;
_MANAGER_PTR _top_manager = (_MANAGER_PTR) *top_manager;
if(_top_manager->next == NULL)
return FALSE;
// first call with shutdown purpose
_top_manager->func(data, SHUTDOWN_PURPOSE);
// remove the head of stack (if any)
_MANAGER_PTR _manager_ptr = _top_manager;
_top_manager = (_top_manager)->next;
free(_manager_ptr);
*top_manager = (MANAGER_PTR) _top_manager;
return TRUE;
}
//------------------------------------------------------------------------
// Pop all manager function from stack.
//------------------------------------------------------------------------
void manager_destroy(MANAGER_PTR top_manager, void* data)
{
while(manager_pop(top_manager, data))
;
}
//-----------------------------------------------------------------------------
// process top-most manager function.
//-----------------------------------------------------------------------------
BOOL manager_process(MANAGER_PTR top_manager, void* data)
{
if(top_manager == NULL)
return FALSE;
// process the top-most manager function
((_MANAGER_PTR) top_manager)->func(data, FRAME_PURPOSE);
return TRUE;
}
//-----------------------------------------------------------------------------
// Process all manager functions in stack.
//-----------------------------------------------------------------------------
void manager_process_all(MANAGER top_manager, void* data)
{
_MANAGER_PTR _manager_ptr = (_MANAGER_PTR) top_manager;
while(_manager_ptr && _manager_ptr->next)
{
_manager_ptr->func(data, FRAME_PURPOSE);
_manager_ptr = _manager_ptr->next;
}
}
測試代碼:
/*************************************************************************
PURPOSE:
Test for manager stack.
*************************************************************************/
#include "core_common.h"
#include "core_framework.h"
#include "core_manager.h"
MANAGER g_manager;
void func2(void* data, long purpose)
{
if(purpose == INIT_PURPOSE)
MessageBox(NULL, "Process2 - init", "Message", MB_OK);
else if(purpose == FRAME_PURPOSE)
MessageBox(NULL, "Process2 - frame", "Message", MB_OK);
else if(purpose == SHUTDOWN_PURPOSE)
MessageBox(NULL, "Process2 - shutdown", "Message", MB_OK);
}
void func1(void* data, long purpose)
{
if(purpose == INIT_PURPOSE)
MessageBox(NULL, "Process1 - init", "Message", MB_OK);
else if(purpose == FRAME_PURPOSE)
MessageBox(NULL, "Process1 - frame", "Message", MB_OK);
else if(purpose == SHUTDOWN_PURPOSE)
MessageBox(NULL, "Process1 - shutdown", "Message", MB_OK);
}
BOOL game_init()
{
g_manager = manager_create();
manager_push(&g_manager, func1, NULL);
manager_push(&g_manager, func2, NULL);
manager_process_all(g_manager, NULL);
return TRUE;
}
BOOL game_frame()
{
return TRUE;
}
BOOL game_shutdown()
{
manager_destroy(&g_manager, NULL);
return TRUE;
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE pre_inst, LPSTR cmd_line, int cmd_show)
{
if(! build_window(inst, "MainClass", "MainWindow", WS_OVERLAPPEDWINDOW, 0, 0, 800, 600))
return FALSE;
run_game(game_init, game_frame, game_shutdown);
return 0;
}
點擊下載源碼和工程