目录
Class 3:实体管理——EntityManager
原文件改动
相较于Class2,Class3新增实体管理部分
-
Config.h用宏定义实现一个foreach循环,来快捷遍历数组
-
GameFunction.c新增头文件EntityManager.h
-
GameFunction.c中init()改动新增EntityManager* em = GetEntityManager();
-
player1 = GetEntity();变为player1 = em->addEntity(GetEntity());
-
GameFunction.c中clean() 中的Cast(player1)->clean();改为GetEntityManager()->clean();
-
GameFunction.c中update() 中的Cast(player1)->update();改为GetEntityManager()->update();
-
GameFunction.c中render() 中的Cast(player1)->render();改为GetEntityManager()->render();
-
Entity.c中的update()取消输出
新文件知识点
-
define定义多行函数
//定义常量 #define MAX_VALUE 100 //定义整型变量MAX_VALUE值为100 #define USER_NAME "huge" //定义字符串变量USER_NAME值为"huge" #define PI 3.1415926 //定义浮点数变量PI值为3.1415926 //定义简单函数 #define MAX(a,b) (a>b)?a:b //取两个数最大值 #define MIN(a,b) (a<b)?a:b //取两个数最小值 //定义复杂多行的函数 #define MACRO(arg1, arg2) do { \ \ stmt1; \ stmt2; \ \ } while(0) 关键是要在每一个换行的时候加上一个 "\ "
程序构建
主程序——main.c
#include <stdio.h>
#include "GameFuntion.h"
int main(int argc,char *argv[])
{
float frameRate = 1000.0/24; //帧率
uint32_t startTime = 0;
uint32_t frameTime = 0;
GameFuntion* game = GameInstance();
game->init("SDL",640,480);
while(game->running())
{
startTime = SDL_GetTicks();
game->update();
game->render();
game->handleEvents();
frameTime = SDL_GetTicks() - startTime;
if(frameRate - frameTime > 0)
{
SDL_Delay(frameRate - frameTime);
}
}
game->clean();
return 0;
}
共用配置头文件——Config.h
#ifndef CONFIGER_H_
#define CONFIGER_H_
#include <stdbool.h>
#include "SDL.h"
#pragma comment(lib,"SDL2.lib")
#pragma comment(lib,"SDLmain.lib")
#define foreach(val,arr) \
for (size_t i = 0,ctr = 0;i<sizeof(arr)/sizeof(arr[0]);i++,ctr = 0)\
for(val = arr[i];ctr < 1;++ctr)
#endif
/*【示例】高难度:用宏定义实现一个foreach循环,来快捷遍历数组
#include <stdio.h>
#define foreach(val,arr) \
for (size_t i = 0,ctr = 0;i<sizeof(arr)/sizeof(arr[0]);i++,ctr = 0)\
for(val = arr[i];ctr < 1;++ctr)
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
foreach(int a,arr)
{
printf("%d",a);
}
char* str[] = {"hello","world"};
foreach(char* val,str)
{
puts(val);
}
return 0;
}
#*/
单例头文件——GameFunction.h
#ifndef GAMEFUNTION_H_
#define GAMEFUNTION_H_
#include "Config.h"
typedef struct GameFuntion
{
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Event events;
bool isRunning;
//声明函数指针
//返回值类型 (*指针变量名) (形参列表)
bool (*init)(const char* title,int w,int h);
void (*clean)();
void (*update)();
void (*render)();
void (*handleEvents)();
bool (*running)();
void (*quit)();
}GameFuntion;
GameFuntion* GameInstance();
#endif
单例源文件——GameFunction.c
#include "GameFuntion.h"
#include "Entity.h"
#include "EntityManager.h"
static bool init(const char* title,int w,int h);
static void clean();
static void update();
static void render();
static void handleEvents();
static bool running();
static void quit();
static GameFuntion* pthis = NULL;
GameFuntion* GameInstance()
{
static GameFuntion game;
if (!pthis)
{
pthis = &game;
pthis->init = init;
pthis->clean = clean;
pthis->update = update;
pthis->render = render;
pthis->handleEvents = handleEvents;
pthis->running = running;
pthis->quit = quit;
}
return pthis;
}
Entity* player1;
Entity* player2;
bool init(const char* title,int w,int h)
{
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
SDL_Log("SDL Init");
pthis->window = SDL_CreateWindow(title,SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,w,h,SDL_WINDOW_SHOWN);
if (pthis->window)
{
SDL_Log("Window Created");
}
pthis->renderer = SDL_CreateRenderer(pthis->window,-1,0);
if(pthis->renderer)
{
SDL_Log("Renderer Created");
}
pthis->isRunning = true;
}
else
{
pthis->isRunning = false;
}
EntityManager* em = GetEntityManager(); //新增
player1 = em->addEntity(GetEntity()); //改动,原:player1 = GetEntity();
player2 = em->addEntity(GetEntity());
return pthis->isRunning;
}
void clean()
{
GetEntityManager()->clean(); //新增
//Cast(player1)->clean();
//Cast(player2)->clean();
SDL_DestroyRenderer(pthis->renderer);
SDL_DestroyWindow(pthis->window);
SDL_Quit();
SDL_Log("SDL Clean");
}
int cnt = 0;
void update()
{
cnt++;
GetEntityManager()->update();
//Cast(player1)->update();
//Cast(player2)->update();
}
void render()
{
//SDL_Log("cnt:%d",cnt);
GetEntityManager()->render();
//Cast(player1)->render();
//Cast(player2)->render();
}
void handleEvents()
{
if(SDL_PollEvent(&pthis->events))
{
if(pthis->events.type == SDL_QUIT)
{
quit();
}
}
}
bool running(){return pthis->isRunning;}
static void quit(){pthis->isRunning = false;}
实体头文件——Entity.h
#ifndef ENTITY_H_
#define ENTITY_H_
#include "Config.h"
typedef struct Entity
{
bool (*init)();
void (*clean)();
void (*update)();
void (*render)();
}Entity;
Entity* GetEntity();
Entity* entity_cast(Entity* e);
#define Cast(e) entity_cast(e)
#endif
实体源文件——Entity.c
#include "Config.h"
#include "Entity.h"
static bool init();
static void clean();
static void update();
static void render();
static Entity* pthis = NULL;
Entity* GetEntity()
{
Entity* ins = SDL_calloc(1,sizeof(Entity));
SDL_assert(ins != NULL);
pthis = ins;
pthis->init = init;
pthis->clean = clean;
pthis->update = update;
pthis->render = render;
return pthis;
}
Entity* entity_cast(Entity* e)
{
pthis = e;
return e;
}
bool init()
{
return true;
}
void clean()
{
SDL_Log("%s",__FUNCTION__);
}
void update()
{
//SDL_Log("%s,%p",__FUNCTION__,pthis);
}
void render()
{
// SDL_Log("%s",__FUNCTION__);
}
实体管理头文件——EntityManager.h
#ifndef ENTITYMANAGER_H_
#define ENTITYMANAGER_H_
#include "Config.h"
typedef struct Entity Entity;
typedef struct EntityManager
{
Entity** Entities; //实体指针数组
int capacity; //容量
int size;
Entity* (*addEntity)(Entity* e); //添加实体
void (*removeEntity)(Entity* e); //移除实体
bool (*init)();
void (*clean)();
void (*update)();
void (*render)();
}EntityManager;
EntityManager* GetEntityManager();
#endif
实体管理头源文件——EntityManager.c
#include "EntityManager.h"
#include "Entity.h"
#define foreach_Manager(val,arr) \
for (size_t i = 0,ctr = 0;i<arr->size;i++,ctr = 0)\
for(val = arr->Entities[i];ctr < 1;++ctr)
static Entity* addEntity(Entity* e);
static void removeEntity(Entity* e);
static bool init();
static void clean();
static void update();
static void render();
static EntityManager* pthis = NULL;
EntityManager* GetEntityManager()
{
static EntityManager em;
if(!pthis)
{
pthis = &em;
pthis->addEntity = addEntity;
pthis->removeEntity = removeEntity;
pthis->init = init;
pthis->clean = clean;
pthis->update = update;
pthis->render = render;
pthis->init();
}
return pthis;
}
Entity* addEntity(Entity* e)
{
pthis->Entities[pthis->size++] = e;
return e;
}
void removeEntity(Entity* e)
{
for(int i = 0;i<pthis->size;i++)
{
Entity* en = pthis->Entities[i];
if(en == e)
{
e->clean();
SDL_free(e);
for(int pos = i;pos < pthis->size-1;pos++)
{
pthis->Entities[i] = pthis->Entities[i+1];
}
pthis->size--;
break;
}
}
}
bool init()
{
pthis->capacity = 8;
pthis->size = 0;
pthis->Entities = SDL_calloc(pthis->capacity,sizeof(Entity*));
SDL_assert(pthis->Entities!=0); //断言
}
void clean()
{
foreach_Manager(Entity* e,pthis) //遍历
{
Cast(e)->clean();
}
}
void update()
{
foreach_Manager(Entity* e,pthis)
{
Cast(e)->update();
}
}
void render()
{
foreach_Manager(Entity* e,pthis)
{
Cast(e)->render();
}
}