diff --git a/.gitignore b/.gitignore index 29403de..280c76b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ !.gitignore build/ test/ +resource/ +embedding/ *.txt *.obj diff --git a/game_core/Makefile b/game_core/Makefile index 3ab56a5..914a73a 100644 --- a/game_core/Makefile +++ b/game_core/Makefile @@ -1,7 +1,7 @@ # 编译器设置 CC = gcc CFLAGS = -Wall -Wextra -g -I../game_engine -LDFLAGS = +LDFLAGS = -lgdi32 # 目录设置 ROOT_DIR := . @@ -10,18 +10,9 @@ ENGINE_DIR := ../game_engine # 手动指定源文件目录 SRC_DIRS = $(ROOT_DIR) \ - $(ROOT_DIR)/test \ - $(ROOT_DIR)/plantform \ - $(ROOT_DIR)/plantform/win_term \ - $(ENGINE_DIR) \ - $(ENGINE_DIR)/components \ - $(ENGINE_DIR)/events \ - $(ENGINE_DIR)/physics \ - $(ENGINE_DIR)/pynic_log \ - $(ENGINE_DIR)/render \ - $(ENGINE_DIR)/resources \ - $(ENGINE_DIR)/timer \ - $(ENGINE_DIR)/utils + $(ROOT_DIR)/plantform/win_app \ + $(ENGINE_DIR) + SRCS = $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c)) OBJS := $(patsubst $(ROOT_DIR)/%.c,$(BUILD_DIR)/core/%.o,$(filter $(ROOT_DIR)/%,$(SRCS))) diff --git a/game_core/ge_color.h b/game_core/ge_color.h new file mode 100644 index 0000000..40efe72 --- /dev/null +++ b/game_core/ge_color.h @@ -0,0 +1,22 @@ +#ifndef __GE_COLOR_H__ +#define __GE_COLOR_H__ + +// 基础颜色宏 +#define GE_COLOR_BLACK RGB(0, 0, 0) +#define GE_COLOR_WHITE RGB(255, 255, 255) +#define GE_COLOR_RED RGB(255, 0, 0) +#define GE_COLOR_GREEN RGB(0, 255, 0) +#define GE_COLOR_BLUE RGB(0, 0, 255) +#define GE_COLOR_YELLOW RGB(255, 255, 0) +#define GE_COLOR_CYAN RGB(0, 255, 255) +#define GE_COLOR_MAGENTA RGB(255, 0, 255) +#define GE_COLOR_GRAY RGB(128, 128, 128) + +// 扩展颜色宏 +#define GE_COLOR_DARK_RED RGB(139, 0, 0) +#define GE_COLOR_DARK_GREEN RGB(0, 100, 0) +#define GE_COLOR_DARK_BLUE RGB(0, 0, 139) +#define GE_COLOR_ORANGE RGB(255, 165, 0) +#define GE_COLOR_PURPLE RGB(128, 0, 128) + +#endif // __GE_COLOR_H__ diff --git a/game_core/main.c b/game_core/main.c index d53ad46..0c9f736 100644 --- a/game_core/main.c +++ b/game_core/main.c @@ -1,12 +1,13 @@ #include #include #include +#include "ge_color.h" #define GE_VEC2I_USE_SHORT_NAMES #define _pynic_logout_printf(...) fprintf(fp , ##__VA_ARGS__) #include -#include "plantform/win_term/interface.h" +// #include "plantform/win_term/interface.h" FILE* fp; logger_t logger; @@ -17,56 +18,96 @@ static void log_handler fflush(fp); } +#define MAX_BULLET 16 +#define BASIC_SPEED (1 << GE_PHYSICS_VELOCITY_BIT) + +typedef struct { + ge_entity_t* player; + ge_entity_t* bullet[MAX_BULLET]; + ge_render_rect_t screen; +} game_ctx_t; + void init(ge_core_t* core) { - register_win_term(core); - register_win_timer(core); - fp = fopen("./log.txt", "w+"); + (void)core; + fp = fopen("D:\\Git_Code\\school_stm32\\game_core\\log.txt", "w+"); init_logger_ex(&logger, "game", log_handler); Assert(fp != NULL); + + static game_ctx_t ctx = { 0 }; + ge_ecs_add_entity(&core->ecs, &ctx.player); + ctx.player->component_mask = GE_COMPONENT_ACVIVE | GE_RENDERABLE_MASK; + ctx.player->position = (ge_vector2i_t){ 32, 32 }; + ctx.player->renderable = (ge_render_component_t) { + .type = GE_RENDER_COMPONENT_TYPE_RECT, + .data.rect = { + .size = {8, 8}, + .color = GE_COLOR_YELLOW, + } + }; + + for (int i = 0; i < MAX_BULLET; ++i) { + ge_ecs_add_entity(&core->ecs, &ctx.bullet[i]); + ctx.bullet[i]->component_mask = GE_RENDERABLE_MASK | GE_PHYSICS_MASK; + ctx.bullet[i]->renderable = (ge_render_component_t) { + .type = GE_RENDER_COMPONENT_TYPE_RECT, + .data.rect = { + .size = {2, 2}, + .color = GE_COLOR_RED, + } + }; + ctx.bullet[i]->physics_body = (ge_physics_component_t) { + .type = GE_PHYSICS_COMPONENT_TYPE_VELOCITY, + .velocity = { 0, - BASIC_SPEED / 2}, + }; + } + + ctx.screen = (ge_render_rect_t) { + .pos = {0, 0}, + .size = core->_render.screen_size, + }; + core->context = &ctx; } -void run(ge_core_t* core) { - static ge_vector2i_t pos = vec2i(0, 0); - // LOG_INFO("vec2: %d, %d", a.x, a.y); +void process(ge_core_t* core) { + game_ctx_t* ctx = (game_ctx_t*)core->context; + core->_render.func_draw_rect(&core->_render, &ctx->screen, GE_COLOR_WHITE); + ge_vector2i_t* pos = &ctx->player->position; - int key = terminal_get_key((win_term_t*)core->render.content); - switch (key) { - case 'w': - MLOG_INFO(&logger, "w"); - core->render.clear(&core->render); - pos = vec2i_add(pos, GE_VEC2I_UP); - core->render.draw(&core->render, pos, "@"); - break; - case 'a': - MLOG_INFO(&logger, "a"); - core->render.clear(&core->render); - pos = vec2i_add(pos, GE_VEC2I_LEFT); - core->render.draw(&core->render, pos, "@"); - break; - case 's': - MLOG_INFO(&logger, "s"); - core->render.clear(&core->render); - pos = vec2i_add(pos, GE_VEC2I_DOWN); - core->render.draw(&core->render, pos, "@"); - break; - case 'd': - MLOG_INFO(&logger, "d"); - core->render.clear(&core->render); - pos = vec2i_add(pos, GE_VEC2I_RIGHT); - core->render.draw(&core->render, pos, "@"); - break; - case 'q': - core->state = GE_ENGINE_STATE_EXIT; - MLOG_INFO(&logger, "exit"); - break; + ge_input_event_t key; + if (!core->_input.func_recv(&core->_input, &key)) { + switch (key.num) { + case 'w': + MLOG_INFO(&logger, "w"); + *pos = vec2i_add(*pos, GE_VEC2I_UP); + break; + case 'a': + MLOG_INFO(&logger, "a"); + *pos = vec2i_add(*pos, GE_VEC2I_LEFT); + break; + case 's': + MLOG_INFO(&logger, "s"); + *pos = vec2i_add(*pos, GE_VEC2I_DOWN); + break; + case 'd': + MLOG_INFO(&logger, "d"); + *pos = vec2i_add(*pos, GE_VEC2I_RIGHT); + break; + case 'f': + ctx->bullet[0]->component_mask |= GE_COMPONENT_ACVIVE; + ctx->bullet[0]->position.x = pos->x + 4; // TODO + ctx->bullet[0]->position.y = pos->y; // TODO + break; + case 'q': + core->state = GE_ENGINE_STATE_EXIT; + MLOG_INFO(&logger, "exit"); + break; + } } } -int main(void) { - ge_core_t core; - ge_engine_init(&core); - core.callbacks.init = init; - core.callbacks.run = run; - ge_engine_run(&core); +int ge_main(ge_core_t* core) { + core->callbacks.init = init; + core->callbacks.process = process; + ge_engine_run(core); return 0; } diff --git a/game_core/plantform/win_app/win_interface.h b/game_core/plantform/win_app/win_interface.h new file mode 100644 index 0000000..8595ace --- /dev/null +++ b/game_core/plantform/win_app/win_interface.h @@ -0,0 +1,10 @@ +#ifndef __WIN_INTERFACE_H__ +#define __WIN_INTERFACE_H__ + +#include + + +void win_sleep_us(ge_u32_t us); +ge_u32_t win_get_us(void); + +#endif // __WIN_INTERFACE_H__ diff --git a/game_core/plantform/win_app/win_main.c b/game_core/plantform/win_app/win_main.c new file mode 100644 index 0000000..d6de4b5 --- /dev/null +++ b/game_core/plantform/win_app/win_main.c @@ -0,0 +1,293 @@ +#include +#include "win_interface.h" +#include + + +// 自定义渲染上下文结构体(包含双缓冲资源) +typedef struct { + HWND hwnd; // 窗口句柄 + HDC hdc_front; // 前台设备上下文 + HDC hdc_back; // 后台缓冲区设备上下文 + HBITMAP hbm_back; // 后台位图 + HBITMAP hbm_old; // 保存原始位图(用于恢复) + RECT client_rect; // 窗口客户区大小 +} win_render_context_t; + +// 双缓冲初始化函数 +static void win_render_init(ge_render_t* ctx, const ge_render_pos2_t* init_screen_size) { + (void) init_screen_size; + win_render_context_t* wctx = (win_render_context_t*)ctx->context; + HDC hdc = GetDC(wctx->hwnd); + + // 获取窗口尺寸 + GetClientRect(wctx->hwnd, &wctx->client_rect); + int width = wctx->client_rect.right - wctx->client_rect.left; + int height = wctx->client_rect.bottom - wctx->client_rect.top; + + // 创建双缓冲资源 + wctx->hdc_front = hdc; + wctx->hdc_back = CreateCompatibleDC(hdc); + wctx->hbm_back = CreateCompatibleBitmap(hdc, width, height); + wctx->hbm_old = (HBITMAP)SelectObject(wctx->hdc_back, wctx->hbm_back); + + // 保存屏幕尺寸到渲染上下文 + ctx->screen_size.x = width; + ctx->screen_size.y = height; +} + +// 清空后台缓冲区 +static void win_render_draw_rect(ge_render_t* ctx, const ge_render_rect_t* rect, ge_render_color_t color) { + win_render_context_t* wctx = (win_render_context_t*)ctx->context; + RECT win_rect = { + .top = rect->pos.y, + .bottom = rect->pos.y + rect->size.y, + .left = rect->pos.x, + .right = rect->pos.x + rect->size.x, + }; + win_rect.bottom *= 4; + win_rect.right *= 4; + win_rect.left *= 4; + win_rect.top *= 4; + HBRUSH brush = CreateSolidBrush(color); // WHITE background + + FillRect(wctx->hdc_back, &win_rect, brush); + DeleteObject(brush); +} + +// 将后台缓冲区复制到屏幕(双缓冲交换) +static void win_render_flush(ge_render_t* ctx) { + win_render_context_t* wctx = (win_render_context_t*)ctx->context; + BitBlt(wctx->hdc_front, + 0, 0, + wctx->client_rect.right, + wctx->client_rect.bottom, + wctx->hdc_back, + 0, 0, + SRCCOPY); +} + +static void win_render_draw_text(ge_render_t* ctx, const ge_render_pos2_t* pos, const char* text) { + win_render_context_t* wctx = (win_render_context_t*)ctx->context; + // 使用GDI函数在 wctx->hdc_back 上绘制 + TextOut(wctx->hdc_back, pos->x, pos->y, text, strlen(text)); +} + +// 键盘事件处理函数(将按键转换为字符) +static char win_key_to_char(WPARAM wParam, LPARAM lParam) { + BYTE keyboardState[256] = {0}; + WORD charBuffer = 0; + + // 获取当前键盘状态 + GetKeyboardState(keyboardState); + + // 将虚拟键码转换为ASCII字符 + if (ToAscii((UINT)wParam, (UINT)((lParam >> 16) & 0xFF), + keyboardState, &charBuffer, 0) > 0) { + // // 只返回可打印字符(ASCII 32-126) + // if (charBuffer >= 32 && charBuffer <= 126) { + return (char)charBuffer; + // } + } + return 0; // 不可打印字符或转换失败 +} + +// 窗口过程函数 +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + ge_core_t* core = (ge_core_t*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (uMsg) { + case WM_KEYDOWN: + if (!core) { + goto END; + } + + // 将按键转换为字符 + char ch = win_key_to_char(wParam, lParam); + ge_input_event_t event; + if (ch != 0) { + // 将字符放入事件缓冲区 + event.num = ch; + core->_input.func_send(&core->_input, event); + } + + return 0; + case WM_DESTROY: + PostQuitMessage(0); + core->state = GE_ENGINE_STATE_EXIT; + return 0; + default: + END: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +} + +static void win_render_getsize(ge_render_t* ctx, ge_vector2i_t* size) { + win_render_context_t* wctx = (win_render_context_t*)ctx->context; + + GetClientRect(wctx->hwnd, &wctx->client_rect); + ctx->screen_size.x = wctx->client_rect.right - wctx->client_rect.left; + ctx->screen_size.y = wctx->client_rect.bottom - wctx->client_rect.top; + + size->x = ctx->screen_size.x; + size->x = ctx->screen_size.y; +} + +// Windows计时函数 +static ge_u32_t win_get_ms(void* ctx) { + return GetTickCount(); +} + +static void win_sleep_ms(void* ctx, ge_u32_t ms) { + Sleep(ms); +} + +static void win_run_at_frame(ge_core_t* core) { + static MSG msg; + const win_render_context_t* xctx = (win_render_context_t*)core->_inner_context; + + while (PeekMessage(&msg, xctx->hwnd, 0, 0, 0)) { + GetMessage(&msg, NULL, 0, 0); + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +static void win_render_drawex(ge_render_t* ctx, ge_vector2i_t pos, const char* data, const void* propety) { + + win_render_context_t* wctx = (win_render_context_t*)ctx->context; + + // 将 data 转换为 HBITMAP (假设传入的是位图句柄) + HBITMAP hBitmap = (HBITMAP)data; + + // 创建兼容的内存设备上下文 + HDC hdcMem = CreateCompatibleDC(wctx->hdc_back); + + // 将位图选入内存设备上下文 + HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap); + + // 获取位图尺寸 + BITMAP bitmap; + GetObject(hBitmap, sizeof(BITMAP), &bitmap); + + // 绘制位图到后台缓冲区 + BitBlt( + wctx->hdc_back, // 目标设备上下文 + pos.x, // 目标左上角X + pos.y, // 目标左上角Y + bitmap.bmWidth, // 位图宽度 + bitmap.bmHeight, // 位图高度 + hdcMem, // 源设备上下文 + 0, // 源左上角X + 0, // 源左上角Y + SRCCOPY // 光栅操作码 + ); + + // 清理资源 + SelectObject(hdcMem, hOldBitmap); + DeleteDC(hdcMem); +} + +// 主游戏逻辑函数 +int ge_main(ge_core_t* core); +DECLARE_GE_KFIFO(ge_input_fifo, ge_input_event_t, 16, ge_input_fifo_t); + +static int ge_input_send (ge_input_t* ctx, ge_input_event_t event) { + struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context; + if (ge_kfifo_is_full(fifo)) { + return -1; + } + ge_kfifo_put(fifo, event); + return 0; +} + +static int ge_input_peek (ge_input_t* ctx, ge_input_event_t* event) { + struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context; + if (ge_kfifo_is_empty(fifo)) { + return -1; + } + ge_kfifo_peek(fifo, event); + return 0; +} + +static int ge_input_recv (ge_input_t* ctx, ge_input_event_t* event) { + struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context; + if (ge_kfifo_is_empty(fifo)) { + return -1; + } + ge_kfifo_get(fifo, event); + return 0; +} + +// Windows入口点 +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + (void) hPrevInstance; + (void) lpCmdLine; + // 创建窗口 + wchar_t CLASS_NAME[] = L"GameWindow"; + + WNDCLASS wc = {0}; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.lpszClassName = CLASS_NAME; + + RegisterClass(&wc); + + HWND hwnd = CreateWindowEx( + 0, + CLASS_NAME, + "Game Engine", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 128 * 4, 128 * 4, + NULL, NULL, hInstance, NULL + ); + + if (hwnd == NULL) return 0; + + // 初始化引擎核心 + static ge_core_t core; + ge_engine_init(&core); + + // 创建双缓冲上下文 + win_render_context_t* wctx = (win_render_context_t*)malloc(sizeof(win_render_context_t)); + wctx->hwnd = hwnd; + + // 配置渲染器 + core._render.context = wctx; + core._render.init_func = (ge_render_init_func_t)win_render_init; + core._render.func_flush = (ge_render_flush_func_t)win_render_flush; + core._render.func_draw_text = (ge_render_draw_text_func_t)win_render_draw_text; + core._render.func_draw_rect = (ge_render_draw_rect_func_t)win_render_draw_rect; + + // // 初始化渲染器 + // if (core->render.init) core->render.init(&core->render); + + // 配置计时器 + core._timer.func_getms = (ge_timer_getms_func_t)win_get_ms; + core._timer.func_sleepms = (ge_timer_sleepms_func_t)win_sleep_ms; + + core._inner_run = win_run_at_frame; + core._inner_context = wctx; + + INIT_GE_KFIFO(&ge_input_fifo); + core._input.context = &ge_input_fifo; + core._input.func_send = ge_input_send; + core._input.func_peek = ge_input_peek; + core._input.func_recv = ge_input_recv; + + // 将core指针关联到窗口 + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&core); + + ShowWindow(hwnd, nCmdShow); + UpdateWindow(hwnd); + // 运行主游戏逻辑 + ge_main(&core); + + // 清理资源 + SelectObject(wctx->hdc_back, wctx->hbm_old); + DeleteObject(wctx->hbm_back); + DeleteDC(wctx->hdc_back); + ReleaseDC(hwnd, wctx->hdc_front); + free(wctx); + + return 0; +} diff --git a/game_core/plantform/win_app/win_timer.c b/game_core/plantform/win_app/win_timer.c new file mode 100644 index 0000000..c496cf0 --- /dev/null +++ b/game_core/plantform/win_app/win_timer.c @@ -0,0 +1,31 @@ +#include +#include + +// 获取当前时间(微秒) +ge_u32_t win_get_us(void) { + static LARGE_INTEGER frequency; + static BOOL initialized = FALSE; + + if (!initialized) { + QueryPerformanceFrequency(&frequency); + initialized = TRUE; + } + + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return (ge_u32_t)((counter.QuadPart * 1000000) / frequency.QuadPart); +} + +// 微秒级休眠 +void win_sleep_us(ge_u32_t us) { + if (us < 1000) { + // 短时间使用忙等待 + ge_u32_t start = win_get_us(); + while ((win_get_us() - start) < us) { + // 空循环 + } + } else { + // 长时间使用Sleep + Sleep(us / 1000); + } +} \ No newline at end of file diff --git a/game_core/plantform/win_term/interface.h b/game_core/plantform/win_term/interface.h index c8c2c26..dda56d2 100644 --- a/game_core/plantform/win_term/interface.h +++ b/game_core/plantform/win_term/interface.h @@ -11,8 +11,8 @@ static inline void register_win_term(ge_core_t* core); void win_sleep_ms(uint32_t ms); uint32_t win_get_timer_ms(); static inline void register_win_timer(ge_core_t* core) { - core->timer.sleep_ms = (ge_sleep_ms_func_t)win_sleep_ms; - core->timer.get_ms = (ge_get_ms_func_t)win_get_timer_ms; + core->_timer.sleep_ms = (ge_sleep_ms_func_t)win_sleep_ms; + core->_timer.get_ms = (ge_get_ms_func_t)win_get_timer_ms; } static void win_render_draw(ge_render_t* ctx, ge_vector2i_t pos, const char* data) { @@ -44,7 +44,7 @@ static void win_render_draw(ge_render_t* ctx, ge_vector2i_t pos, const char* dat } // 普通字符处理 - char char_str[2] = { *ptr, '\0' }; + char char_str[2] = { *ptr }; terminal_print(term, current_x, current_y, char_str); current_x++; @@ -61,14 +61,19 @@ static void win_render_getsize(ge_render_t* ctx, ge_vector2i_t* size) { size->x = terminal_get_width((win_term_t*)ctx->content); } +static void win_render_flush(ge_render_t* ctx) { + terminal_flush((win_term_t*)ctx->content); +} + static inline void register_win_term(ge_core_t* core) { win_term_t* ctx = terminal_init(); Assert(ctx != NULL); - core->render.content = ctx; - core->render.init = NULL; - core->render.draw = win_render_draw; - core->render.clear = win_render_clear; - core->render.getsize = win_render_getsize; + core->_render.content = ctx; + core->_render.init = NULL; + core->_render.draw = win_render_draw; + core->_render.clear = win_render_clear; + core->_render.getsize = win_render_getsize; + core->_render.flush = win_render_flush; } #endif // __WIN_TERM_INTERFACE_H__ diff --git a/game_core/plantform/win_term/win_term.c b/game_core/plantform/win_term/win_term.c index d0f0300..4c8855d 100644 --- a/game_core/plantform/win_term/win_term.c +++ b/game_core/plantform/win_term/win_term.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "win_term.h" // 终端抽象结构体 @@ -9,35 +10,108 @@ struct win_term { HANDLE hStdout; HANDLE hStdin; CONSOLE_SCREEN_BUFFER_INFO csbi; + int width; + int height; + char buffer[120 * 30 + 120 * 30]; }; +#define ESC "\x1b" +#define CSI "\x1b[" + // 初始化终端 win_term_t* terminal_init() { win_term_t* term = malloc(sizeof(win_term_t)); + Assert(term != NULL); + term->hStdout = GetStdHandle(STD_OUTPUT_HANDLE); term->hStdin = GetStdHandle(STD_INPUT_HANDLE); - + + // Using UTF-8 SetConsoleOutputCP(65001); SetConsoleCP(65001); - // 保存初始控制台信息 - GetConsoleScreenBufferInfo(term->hStdout, &term->csbi); - - // 设置输入模式(禁用行缓冲) - DWORD mode = 0; - GetConsoleMode(term->hStdin, &mode); - SetConsoleMode(term->hStdin, mode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)); - - // 关闭光标(游标) - CONSOLE_CURSOR_INFO cursorInfo; - GetConsoleCursorInfo(term->hStdout, &cursorInfo); - cursorInfo.bVisible = FALSE; // 设置为 FALSE 隐藏光标 - SetConsoleCursorInfo(term->hStdout, &cursorInfo); + // https://learn.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences + // Set output mode to handle virtual terminal sequences + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + if (hOut == INVALID_HANDLE_VALUE) { + return NULL; + } + HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); + if (hIn == INVALID_HANDLE_VALUE) { + return NULL; + } - system("cls"); + DWORD dwOriginalOutMode = 0; + DWORD dwOriginalInMode = 0; + if (!GetConsoleMode(hOut, &dwOriginalOutMode)) { + return NULL; + } + if (!GetConsoleMode(hIn, &dwOriginalInMode)) { + return NULL; + } + + DWORD dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; + DWORD dwRequestedInModes = ENABLE_VIRTUAL_TERMINAL_INPUT; + + DWORD dwOutMode = dwOriginalOutMode | dwRequestedOutModes; + if (!SetConsoleMode(hOut, dwOutMode)) { + // we failed to set both modes, try to step down mode gracefully. + dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING; + dwOutMode = dwOriginalOutMode | dwRequestedOutModes; + if (!SetConsoleMode(hOut, dwOutMode)) { + // Failed to set any VT mode, can't do anything here. + return NULL; + } + } + + DWORD dwInMode = dwOriginalInMode | dwRequestedInModes; + if (!SetConsoleMode(hIn, dwInMode)) { + // Failed to set VT input mode, can't do anything here. + return NULL; + } + + // disable cursor + printf(CSI"?25l"); + term->height = terminal_get_height(term); + term->width = terminal_get_width(term); + terminal_clean(term); + terminal_flush(term); return term; } +void terminal_flush(win_term_t* term) { + // ESC[nJ + // printf(CSI"2J"); + // for (int i = 0; i < term->height; i++) { + // // ESC[x;yH 设置光标位置 x 行 y 列 + // // WriteConsole(term->hStdout, term->buffer + ((term->width + 1) * i), term->width, NULL, NULL); + // WriteFile(term->hStdout, term->buffer + ((term->width + 1) * i), term->width - 1, NULL, NULL); + // } + printf(CSI"0;0H%s", term->buffer); + // fflush(stdout); +} + +int terminal_clean(win_term_t* term) { + // printf(CSI"2J"); + memset(term->buffer, ' ', sizeof(term->buffer)); + for (int i = 1; i <= term->height; i++) { + term->buffer[i * term->width] = '\n'; + } + term->buffer[term->width * term->height] = '\0'; + return 0; +} + +// 打印文本(带位置和颜色) +void terminal_print(win_term_t* term, int x, int y, const char* text) { + // terminal_set_cursor(term, x, y); + // printf(CSI"%d;%dH%s", y, x, text); + while (*text) { + *((term->buffer) + ((term->width + 1) * y) + x) = *text; + x++; + text++; + } +} + // 清理终端 void terminal_cleanup(win_term_t* term) { // 恢复初始属性 @@ -45,19 +119,6 @@ void terminal_cleanup(win_term_t* term) { free(term); } -// 设置光标位置 -static inline void terminal_set_cursor(win_term_t* term, int x, int y) { - COORD coord = { x, y }; - SetConsoleCursorPosition(term->hStdout, coord); -} - -// 打印文本(带位置和颜色) -void terminal_print(win_term_t* term, int x, int y, const char* text) { - terminal_set_cursor(term, x, y); - printf("%s", text); - fflush(stdout); -} - // 获取按键事件 int terminal_get_key(win_term_t* term) { INPUT_RECORD ir; @@ -86,60 +147,6 @@ int terminal_get_height(win_term_t* term) { return term->csbi.srWindow.Bottom - term->csbi.srWindow.Top + 1; } -int terminal_clean(win_term_t* term) { - // Write the sequence for clearing the display. - DWORD written = 0; - PCWSTR sequence = L"\x1b[2J"; - if (!WriteConsoleW(term->hStdout, sequence, (DWORD)wcslen(sequence), &written, NULL)) - { - // If we fail, try to restore the mode on the way out. - SetConsoleMode(term->hStdout, ENABLE_VIRTUAL_TERMINAL_PROCESSING); - return GetLastError(); - } - return 0; -} - -// int main() { -// win_term_t* term = terminal_init(); - -// // 清屏 -// system("cls"); - -// // 打印彩色文本 -// terminal_print(term, 10, 5, -// "按方向键移动, ESC退出"); - -// int x = 10, y = 10; -// char* player = "@"; - -// while (1) { -// // 绘制玩家 -// terminal_print(term, x, y, -// player); - -// // 获取按键 -// int key = terminal_get_key(term); - -// // 擦除旧位置 -// terminal_print(term, x, y, " "); - -// // 处理移动 -// switch (key) { -// case VK_UP: y--; break; -// case VK_DOWN: y++; break; -// case VK_LEFT: x--; break; -// case VK_RIGHT: x++; break; -// case VK_ESCAPE: -// terminal_cleanup(term); -// return 0; -// } - -// // 边界检查 -// if (x < 0) x = 0; -// if (y < 0) y = 0; -// } -// } - uint32_t win_get_timer_ms() { static LARGE_INTEGER freq = {0}; static BOOL has_freq = FALSE; diff --git a/game_core/plantform/win_term/win_term.h b/game_core/plantform/win_term/win_term.h index 4eb57af..26d9ef6 100644 --- a/game_core/plantform/win_term/win_term.h +++ b/game_core/plantform/win_term/win_term.h @@ -10,5 +10,6 @@ int terminal_get_key(win_term_t* term); int terminal_get_width(win_term_t* term); int terminal_get_height(win_term_t* term); int terminal_clean(win_term_t* term); +void terminal_flush(win_term_t* term); #endif // __WIN_TERM_H__ diff --git a/game_core/tilemap.c b/game_core/tilemap.c new file mode 100644 index 0000000..20b7887 --- /dev/null +++ b/game_core/tilemap.c @@ -0,0 +1,9 @@ +#ifndef __TILEMAP_H__ +#define __TILEMAP_H__ + +typedef struct { + +}; + + +#endif // __TILE_MAP_H__ diff --git a/game_engine/components/ge_entity.h b/game_engine/components/ge_entity.h deleted file mode 100644 index ae70999..0000000 --- a/game_engine/components/ge_entity.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __GE_ENTIRY_H__ -#define __GE_ENTIRY_H__ - -#include "../ge_config.h" -#include "../math/ge_vector2i.h" - -typedef struct { - uint16_t id; - uint16_t components; -} ge_entity_t; - -typedef struct { - ge_vector2i_t position; - unsigned char z; -} ge_position_t; - - - - -#endif // __GE_ENTIRY_H__ diff --git a/game_engine/components/ge_sprite.h b/game_engine/components/ge_sprite.h deleted file mode 100644 index 2d531d3..0000000 --- a/game_engine/components/ge_sprite.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __GE_SPRITE_H__ -#define __GE_SPRITE_H__ - - - -#endif // __GE_SPRITE_H__ diff --git a/game_engine/ecs/ge_entity.h b/game_engine/ecs/ge_entity.h new file mode 100644 index 0000000..115f470 --- /dev/null +++ b/game_engine/ecs/ge_entity.h @@ -0,0 +1,64 @@ +#ifndef __GE_ENTIRY_H__ +#define __GE_ENTIRY_H__ + +#include +#include +#include "ge_render_component.h" +#include "ge_physics_component.h" + +#include +typedef uint16_t ge_ecs_id_t; // 支持65536个实体 +#define GE_ECS_MAX 128 + +typedef enum { + GE_COMPONENT_ACVIVE = 1 << 0, + GE_COMPONENT_POSITION = 1 << 1, + GE_COMPONENT_TRANSFORM = 1 << 2, // TODO not implimented + GE_COMPONENT_RENDERABLE = 1 << 3, + GE_COMPONENT_PHYSICS_BODY = 1 << 4, // TODO not implimented + GE_COMPONENT_COLLIDER = 1 << 5, // TODO not implimented + GE_COMPONENT_TIMED_LIFE = 1 << 6, // TODO not implimented +} ge_ecs_mask_t; + +#define GE_RENDERABLE_MASK \ + (GE_COMPONENT_POSITION | GE_COMPONENT_RENDERABLE) +#define GE_PHYSICS_MASK \ + (GE_COMPONENT_POSITION | GE_COMPONENT_PHYSICS_BODY) + +typedef struct ge_entity { + ge_ecs_id_t id; + ge_ecs_mask_t component_mask; + ge_vector2i_t position; + ge_render_component_t renderable; + ge_physics_component_t physics_body; +} ge_entity_t; + +typedef struct { + // TODO static storage to dynamic storage + ge_entity_t entities[GE_ECS_MAX]; + ge_ecs_id_t count; +} ge_ecs_storage_t; + +typedef struct ge_ecs { + ge_ecs_storage_t storage; +} ge_ecs_t; + + +static inline ge_ecs_id_t ge_ecs_add_entity(ge_ecs_t* ecs, ge_entity_t** entity) { + ge_ecs_id_t id = ++ecs->storage.count; + if (id >= GE_ECS_MAX) { + return 0; + } + // TODO squeze the data + if (entity != NULL) *entity = &ecs->storage.entities[id]; + return id; +} + +static inline ge_entity_t* ge_ecs_get_entity(ge_ecs_t* ecs, ge_ecs_id_t id) { + if(id >= ecs->storage.count) { + return NULL; + } + return &ecs->storage.entities[id]; +} + +#endif // __GE_ENTIRY_H__ diff --git a/game_engine/ecs/ge_physics_component.h b/game_engine/ecs/ge_physics_component.h new file mode 100644 index 0000000..5218715 --- /dev/null +++ b/game_engine/ecs/ge_physics_component.h @@ -0,0 +1,21 @@ +#ifndef __GE_PHYSICS_COMPONENT_H__ +#define __GE_PHYSICS_COMPONENT_H__ + +#include + +#define GE_PHYSICS_VELOCITY_BIT 3 +#define GE_PHYSICS_ACCELERATION_BIT 3 + +typedef enum { + GE_PHYSICS_COMPONENT_TYPE_NONE = 1 << 0, + GE_PHYSICS_COMPONENT_TYPE_VELOCITY = 1 << 1, + GE_PHYSICS_COMPONENT_TYPE_ACCELERATION = 1 << 2, +} ge_physics_component_type_t; + +typedef struct ge_physics_component { + ge_physics_component_type_t type; + ge_vector2i_t velocity; + ge_vector2i_t acceleration; +} ge_physics_component_t; + +#endif // __GE_PHYSICS_COMPONENT_H__ diff --git a/game_engine/ecs/ge_physics_system.h b/game_engine/ecs/ge_physics_system.h new file mode 100644 index 0000000..6d02c9d --- /dev/null +++ b/game_engine/ecs/ge_physics_system.h @@ -0,0 +1,39 @@ +#ifndef __GE_PHYSICS_SYSTEM_H__ +#define __GE_PHYSICS_SYSTEM_H__ + +#include "ge_entity.h" +#include "ge_physics_component.h" +#include + +typedef struct ge_physics_system { + ge_ecs_storage_t* ecs; +} ge_physics_system_t; + +#define _GE_PHYSICS_MASK (GE_PHYSICS_MASK | GE_COMPONENT_ACVIVE) + +static inline void +ge_physics_system_run_all(ge_physics_system_t* ctx) { + Assert(ctx != NULL); + ge_ecs_storage_t* ecs = ctx->ecs; + Assert(ecs != NULL); + for (int i = 1; i <= ecs->count && i < GE_ECS_MAX; ++i) { + ge_entity_t* entity = &ecs->entities[i]; + ge_ecs_mask_t mask = entity->component_mask; + if ((mask & _GE_PHYSICS_MASK) != _GE_PHYSICS_MASK) continue; + + ge_physics_component_t* comp = &entity->physics_body; + Assert(comp != NULL); + ge_physics_component_type_t type= comp->type; + + if (type & GE_PHYSICS_COMPONENT_TYPE_ACCELERATION) { + comp->velocity.x += comp->acceleration.x >> GE_PHYSICS_ACCELERATION_BIT; + comp->velocity.y += comp->acceleration.y >> GE_PHYSICS_ACCELERATION_BIT; + } + if (type & GE_PHYSICS_COMPONENT_TYPE_VELOCITY) { + entity->position.x += comp->velocity.x >> GE_PHYSICS_VELOCITY_BIT; + entity->position.y += comp->velocity.y >> GE_PHYSICS_VELOCITY_BIT; + } + } +} + +#endif // __GE_PHYSICS_SYSTEM_H__ diff --git a/game_engine/ecs/ge_render_component.h b/game_engine/ecs/ge_render_component.h new file mode 100644 index 0000000..8cf647b --- /dev/null +++ b/game_engine/ecs/ge_render_component.h @@ -0,0 +1,27 @@ +#ifndef __GE_RENDER_COMPONENT_H__ +#define __GE_RENDER_COMPONENT_H__ + +#include + +typedef enum { + GE_RENDER_COMPONENT_TYPE_NONE, + GE_RENDER_COMPONENT_TYPE_POINT, + GE_RENDER_COMPONENT_TYPE_TEXT, + GE_RENDER_COMPONENT_TYPE_RECT, + GE_RENDER_COMPONENT_TYPE_RECOURCE, +} ge_render_component_type_t; + +typedef struct ge_render_component { + ge_render_component_type_t type; + union { + struct { + ge_render_color_t color; + } point; + struct { + ge_render_pos2_t size; + ge_render_color_t color; + } rect; + } data; +} ge_render_component_t; + +#endif // __GE_RENDER_COMPONENT_H__ diff --git a/game_engine/ecs/ge_render_system.h b/game_engine/ecs/ge_render_system.h new file mode 100644 index 0000000..f1320a7 --- /dev/null +++ b/game_engine/ecs/ge_render_system.h @@ -0,0 +1,69 @@ +#ifndef __GE_RENDER_SYSTEM_H__ +#define __GE_RENDER_SYSTEM_H__ + +#include "ge_entity.h" +#include "ge_render_component.h" +#include + +typedef struct ge_render_system { + ge_render_t* render; + ge_ecs_storage_t* ecs; +} ge_render_system_t; + +static inline void +ge_render_system_init(ge_render_system_t* ctx, ge_render_t* render) { + Assert(ctx != NULL && render != NULL); + ctx->render = render; +} + +#define _GE_RENDERABLE_MASK (GE_RENDERABLE_MASK | GE_COMPONENT_ACVIVE) + +static inline void +ge_render_system_draw_all(ge_render_system_t* ctx) { + Assert(ctx != NULL); + ge_ecs_storage_t* ecs = ctx->ecs; + Assert(ecs != NULL); + for (int i = 1; i <= ecs->count && i < GE_ECS_MAX; ++i) { + ge_entity_t* entity = &ecs->entities[i]; + ge_ecs_mask_t mask = entity->component_mask; + if ((mask & _GE_RENDERABLE_MASK) != _GE_RENDERABLE_MASK) continue; + + ge_render_pos2_t pos = { + entity->position.x, + entity->position.y, + }; + ge_render_component_t* comp = &entity->renderable; + Assert(comp != NULL); + + switch (comp->type) { + case GE_RENDER_COMPONENT_TYPE_POINT: + ctx->render->func_draw_point( + ctx->render, + &pos, + comp->data.point.color + ); + break; + case GE_RENDER_COMPONENT_TYPE_RECT: + ctx->render->func_draw_rect( + ctx->render, + &(ge_render_rect_t) { + pos, + comp->data.rect.size, + }, + comp->data.rect.color + ); + break; + case GE_RENDER_COMPONENT_TYPE_TEXT: + TODO(); + break; + case GE_RENDER_COMPONENT_TYPE_RECOURCE: + TODO(); + break; + default: + LOG_WARN("render component not set Avaliable type %d, id %d", comp->type, i); + break; + } + } +} + +#endif // __GE_RENDER_SYSTEM_H__ diff --git a/game_engine/ge_common.h b/game_engine/ge_common.h index 3acfad6..f328da1 100644 --- a/game_engine/ge_common.h +++ b/game_engine/ge_common.h @@ -9,4 +9,8 @@ #include #include +#include +#include +#include + #endif // __GE_COMMON_H__ diff --git a/game_engine/ge_core.c b/game_engine/ge_core.c index e2c3a47..99c4a99 100644 --- a/game_engine/ge_core.c +++ b/game_engine/ge_core.c @@ -7,48 +7,48 @@ void ge_engine_init(ge_core_t *core) { for (int i = 0; i < (int)sizeof(ge_core_t); i++) { *(ptr + i) = 0; } - core->configs.fps = 60; + core->configs.fps = 120; } static inline void ge_init(ge_core_t* core) { /** * check render */ - ge_render_t* render_ctx = &core->render; - if (render_ctx->content) { - Assert(render_ctx->clear && render_ctx->draw - && render_ctx->getsize); - GE_SAFE_CALL(render_ctx->init, render_ctx); - render_ctx->getsize(render_ctx, &render_ctx->screen_size); + ge_render_t* render_ctx = &core->_render; + if (render_ctx->context) { + GE_SAFE_CALL(render_ctx->init_func, render_ctx, NULL); } - Assert(core->timer.sleep_ms != NULL); - Assert(core->configs.fps != 0); + Assert(core->_timer.func_sleepms != NULL); - core->timer.fps_ctl.target_fps = 0; - if (core->timer.get_ms != NULL) { - ge_fps_init(&core->timer.fps_ctl, core->configs.fps, - core->timer.get_ms, core->timer.sleep_ms); + /** + * init ecs + */ + for (int i = 0; i < GE_ECS_MAX; ++i) { + core->ecs.storage.entities[i].component_mask = 0; } -} + ge_render_system_init(&core->_systems.render, &core->_render); + // TODO using other storage system + core->_systems.render.ecs = &core->ecs.storage; + core->ecs.storage.count = 0; -static inline void ge_render(ge_render_t* ctx) { - // ctx->clear(ctx); + core->_systems.physics.ecs = &core->ecs.storage; } void ge_engine_run(ge_core_t *core) { - GE_SAFE_CALL(core->callbacks.init, core); ge_init(core); + GE_SAFE_CALL(core->callbacks.init, core); core->state = GE_ENGINE_STATE_RUNNING; while (core->state == GE_ENGINE_STATE_RUNNING) { - if (core->timer.fps_ctl.target_fps) ge_fps_begin_frame(&core->timer.fps_ctl); + GE_SAFE_CALL(core->_inner_run, core); - GE_SAFE_CALL(core->callbacks.run, core); - if (core->render.content) ge_render(&core->render); + ge_physics_system_run_all(&core->_systems.physics); + GE_SAFE_CALL(core->callbacks.process, core); + ge_render_system_draw_all(&core->_systems.render); - if (core->timer.fps_ctl.target_fps) ge_fps_end_frame(&core->timer.fps_ctl); - else core->timer.sleep_ms(1000 / core->configs.fps); + GE_SAFE_CALL(core->_render.func_flush, &core->_render); + core->_timer.func_sleepms(&core->_timer, 1000 / core->configs.fps); } GE_SAFE_CALL(core->callbacks.exit, core); } diff --git a/game_engine/ge_core.h b/game_engine/ge_core.h index 65c0a33..a0d460e 100644 --- a/game_engine/ge_core.h +++ b/game_engine/ge_core.h @@ -2,8 +2,9 @@ #define __GE_CORE_H__ #include -#include -#include +#include +#include +#include struct ge_engine_core; typedef struct ge_engine_core ge_core_t; @@ -24,20 +25,31 @@ struct ge_engine_core { struct { ge_init_func_t init; ge_exit_func_t exit; - ge_run_func_t run; + ge_run_func_t process; } callbacks; ge_engine_state_t state; - - ge_render_t render; - ge_timer_t timer; + ge_ecs_t ecs; + DECLARE_GE_KFIFO(einput, ge_uptr_t, 16, ge_event_input_t); struct { ge_uint_t fps; } configs; + void* context; + + struct { + ge_render_system_t render; + ge_physics_system_t physics; + } _systems; + ge_render_t _render; + ge_timer_t _timer; + ge_input_t _input; + ge_run_func_t _inner_run; + void* _inner_context; }; /** * Basic Call */ +int ge_main(ge_core_t* core); void ge_engine_init(ge_core_t *core); void ge_engine_run(ge_core_t *core); diff --git a/game_engine/interface/ge_input.h b/game_engine/interface/ge_input.h new file mode 100644 index 0000000..dd4f02f --- /dev/null +++ b/game_engine/interface/ge_input.h @@ -0,0 +1,57 @@ +#ifndef __GE_INPUT_H__ +#define __GE_INPUT_H__ + +#include + +struct ge_input; +typedef struct ge_input ge_input_t; +typedef union ge_input_event { + void* ctx; + uintptr_t num; +} ge_input_event_t; + +typedef int(*ge_input_send_func_t)(ge_input_t* ctx, ge_input_event_t event); +typedef int(*ge_input_peek_func_t)(ge_input_t* ctx, ge_input_event_t* event); +typedef int(*ge_input_recv_func_t)(ge_input_t* ctx, ge_input_event_t* event); + +struct ge_input { + void* context; + ge_input_send_func_t func_send; + ge_input_peek_func_t func_peek; + ge_input_recv_func_t func_recv; +}; + +#ifdef __GE_INPUT_EASY_IMPLIMENT_H__ + +DECLARE_GE_KFIFO(ge_input_fifo, ge_input_event_t, 16, ge_input_fifo_t); + +static int ge_input_send (ge_input_t* ctx, ge_input_event_t event) { + struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context; + if (ge_kfifo_is_full(fifo)) { + return -1; + } + ge_kfifo_put(fifo, event); + return 0; +} + +static int ge_input_peek (ge_input_t* ctx, ge_input_event_t* event) { + struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context; + if (ge_kfifo_is_empty(fifo)) { + return -1; + } + ge_kfifo_peek(fifo, event); + return 0; +} + +static int ge_input_recv (ge_input_t* ctx, ge_input_event_t* event) { + struct ge_input_fifo_t* fifo = (struct ge_input_fifo_t*)ctx->context; + if (ge_kfifo_is_empty(fifo)) { + return -1; + } + ge_kfifo_get(fifo, event); + return 0; +} + +#endif + +#endif // __GE_INPUT_H__ diff --git a/game_engine/interface/ge_kfifo.h b/game_engine/interface/ge_kfifo.h new file mode 100644 index 0000000..1c51b72 --- /dev/null +++ b/game_engine/interface/ge_kfifo.h @@ -0,0 +1,236 @@ +/* + * A generic kernel FIFO implementation + * + * Copyright (C) 2009/2010 Stefani Seibold + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef __GE_KFIFO_H__ +#define __GE_KFIFO_H__ +/** + * 仿照linux内核中的kfifo实现 + */ + +#ifndef GE_MEMORY_BARRIR +#define GE_MEMORY_BARRIR() __sync_synchronize() +#endif + +#ifndef GE_ARRAY_SIZE +#define GE_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif + +struct __ge_kfifo { + unsigned int in; + unsigned int out; + unsigned int mask; + unsigned int esize; + void *data; +}; + +#define __STRUCT_GE_KFIFO(type, size) \ +{ \ + struct __ge_kfifo kfifo; \ + type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \ +} + +/** + * DECLARE_KFIFO - macro to declare a fifo object + * @fifo: name of the declared fifo + * @type: type of the fifo elements + * @size: the number of elements in the fifo, this must be a power of 2 + */ +#define DECLARE_GE_KFIFO(fifo, type, size, tname) struct tname __STRUCT_GE_KFIFO(type, size) fifo + +#define INIT_GE_KFIFO(fifo) do { \ + struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \ + __kfifo->in = 0; \ + __kfifo->out = 0; \ + __kfifo->mask = GE_ARRAY_SIZE((fifo)->buf) - 1; \ + __kfifo->esize = sizeof(*((fifo)->buf)); \ + __kfifo->data = (fifo)->buf; \ + } while (0) + +/** + * DEFINE_KFIFO - macro to define and initialize a fifo + * @fifo: name of the declared fifo datatype + * @type: type of the fifo elements + * @size: the number of elements in the fifo, this must be a power of 2 + * + * Note: the macro can be used for global and local fifo data type variables. + */ +#define DEFINE_GE_KFIFO(fifo, type, size, tname) \ + DECLARE_GE_KFIFO(fifo, type, size, tname) = \ + (struct tname) { { \ + .in = 0, \ + .out = 0, \ + .mask = GE_ARRAY_SIZE((fifo).buf) - 1, \ + .esize = sizeof(*(fifo).buf), \ + .data = (fifo).buf, \ + }, { 0 } } + +/** + * kfifo_size - returns the size of the fifo in elements + * @fifo: address of the fifo to be used + */ +#define ge_kfifo_size(fifo) \ + ((fifo)->kfifo.mask + 1) + +/** + * kfifo_len - returns the number of used elements in the fifo + * @fifo: address of the fifo to be used + */ +#define ge_kfifo_len(fifo) \ + ((fifo)->kfifo.in - (fifo)->kfifo.out) + +/** + * kfifo_is_empty - returns true if the fifo is empty + * @fifo: address of the fifo to be used + */ +#define ge_kfifo_is_empty(fifo) \ + ((fifo)->kfifo.in == (fifo)->kfifo.out) + +/** + * kfifo_is_full - returns true if the fifo is full + * @fifo: address of the fifo to be used + */ +#define ge_kfifo_is_full(fifo) (ge_kfifo_len(fifo) > (fifo)->kfifo.mask) + +/** + * kfifo_put - put data into the fifo + * @fifo: address of the fifo to be used + * @val: the data to be added + * + * This macro copies the given value into the fifo. + * It returns 0 if the fifo was full. Otherwise it returns the number + * processed elements. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these macro. + */ +#define ge_kfifo_put(fifo, val) do { \ + unsigned int __ret; \ + struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \ + __ret = !ge_kfifo_is_full(fifo); \ + if (__ret) { \ + ((fifo)->buf)[__kfifo->in & __kfifo->mask] = val; \ + /*smp_wmb();*/ \ + GE_MEMORY_BARRIR(); \ + __kfifo->in++; \ + } \ + /*__ret;*/ \ +} while(0) + +/** + * kfifo_get - get data from the fifo + * @fifo: address of the fifo to be used + * @val: address where to store the data + * + * This macro reads the data from the fifo. + * It returns 0 if the fifo was empty. Otherwise it returns the number + * processed elements. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these macro. + */ +#define ge_kfifo_get(fifo, val) do { \ + unsigned int __ret; \ + struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \ + __ret = !ge_kfifo_is_empty(fifo); \ + if (__ret) { \ + *val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \ + /*smp_wmb();*/ \ + GE_MEMORY_BARRIR(); \ + __kfifo->out++; \ + } \ + /*__ret;*/ \ +} while(0) + +/** + * kfifo_peek - get data from the fifo without removing + * @fifo: address of the fifo to be used + * @val: address where to store the data + * + * This reads the data from the fifo without removing it from the fifo. + * It returns 0 if the fifo was empty. Otherwise it returns the number + * processed elements. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these macro. + */ +#define ge_kfifo_peek(fifo, val) do { \ + unsigned int __ret; \ + struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \ + __ret = !ge_kfifo_is_empty(fifo); \ + if (__ret) { \ + *val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \ + /*smp_wmb();*/ \ + GE_MEMORY_BARRIR(); \ + } \ + /*__ret;*/ \ +} while(0) + +/** + * kfifo_in - put data into the fifo + * @fifo: address of the fifo to be used + * @buf: the data to be added + * @n: number of elements to be added + * + * This macro copies the given buffer into the fifo and returns the + * number of copied elements. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these macro. + */ +/* +#define kfifo_in(fifo, buf, n) \ +({ \ + typeof((fifo) + 1) __tmp = (fifo); \ + typeof(__tmp->ptr_const) __buf = (buf); \ + unsigned long __n = (n); \ + const size_t __recsize = sizeof(*__tmp->rectype); \ + struct __kfifo *__kfifo = &__tmp->kfifo; \ + (__recsize) ?\ + __kfifo_in_r(__kfifo, __buf, __n, __recsize) : \ + __kfifo_in(__kfifo, __buf, __n); \ +}) +*/ +/** + * kfifo_out - get data from the fifo + * @fifo: address of the fifo to be used + * @buf: pointer to the storage buffer + * @n: max. number of elements to get + * + * This macro gets some data from the fifo and returns the numbers of elements + * copied. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these macro. + */ +/* +#define kfifo_out(fifo, buf, n) \ +({ \ + typeof((fifo) + 1) __tmp = (fifo); \ + typeof(__tmp->ptr) __buf = (buf); \ + unsigned long __n = (n); \ + const size_t __recsize = sizeof(*__tmp->rectype); \ + struct __kfifo *__kfifo = &__tmp->kfifo; \ + (__recsize) ?\ + __kfifo_out_r(__kfifo, __buf, __n, __recsize) : \ + __kfifo_out(__kfifo, __buf, __n); \ +}) +*/ + +#endif // __GE_KFIFO_H__ diff --git a/game_engine/interface/ge_render.h b/game_engine/interface/ge_render.h new file mode 100644 index 0000000..e45dd78 --- /dev/null +++ b/game_engine/interface/ge_render.h @@ -0,0 +1,42 @@ +#ifndef __GE_RENDER_H__ +#define __GE_RENDER_H__ + +#include "ge_resource.h" +#include +typedef int ge_render_unit_t; +typedef COLORREF ge_render_color_t; + +typedef struct ge_render_pos2 { + ge_render_unit_t x; + ge_render_unit_t y; +} ge_render_pos2_t; + +typedef struct ge_render_rect { + ge_render_pos2_t pos; + ge_render_pos2_t size; +} ge_render_rect_t; + +struct ge_render; +typedef struct ge_render ge_render_t; + +typedef int(*ge_render_init_func_t) (ge_render_t* ctx, const ge_render_pos2_t* init_screen_size); +typedef int(*ge_render_flush_func_t) (ge_render_t* ctx); + +typedef int(*ge_render_draw_point_func_t) (ge_render_t* ctx, const ge_render_pos2_t* pos, ge_render_color_t color); +typedef int(*ge_render_draw_rect_func_t) (ge_render_t* ctx, const ge_render_rect_t* rect, ge_render_color_t color); +typedef int(*ge_render_draw_text_func_t) (ge_render_t* ctx, const ge_render_pos2_t* pos, const char* text); +typedef int(*ge_render_draw_resource_func_t)(ge_render_t* ctx, const ge_render_pos2_t* pos, const ge_resource_t* res); + +struct ge_render { + void* context; + ge_render_pos2_t screen_size; + ge_render_init_func_t init_func; + ge_render_flush_func_t func_flush; + + ge_render_draw_point_func_t func_draw_point; + ge_render_draw_rect_func_t func_draw_rect; + ge_render_draw_text_func_t func_draw_text; + ge_render_draw_resource_func_t func_draw_res; +}; + +#endif // __GE_RENDER_H__ diff --git a/game_engine/interface/ge_resource.h b/game_engine/interface/ge_resource.h new file mode 100644 index 0000000..8aab055 --- /dev/null +++ b/game_engine/interface/ge_resource.h @@ -0,0 +1,12 @@ +#ifndef __GE_RESOURCE_H__ +#define __GE_RESOURCE_H__ + +struct ge_resource; +typedef struct ge_resource ge_resource_t; + +struct ge_resource { + int type; + void* context; +}; + +#endif // __GE_RESOURCE_H__ diff --git a/game_engine/interface/ge_timer.h b/game_engine/interface/ge_timer.h new file mode 100644 index 0000000..03fce0a --- /dev/null +++ b/game_engine/interface/ge_timer.h @@ -0,0 +1,23 @@ +#ifndef __GE_TIMER_H__ +#define __GE_TIMER_H__ + +#include +typedef uint64_t ge_time_t; + +struct ge_timer; +typedef struct ge_timer ge_timer_t; + +typedef ge_time_t(*ge_timer_getus_func_t)(ge_timer_t* timer); +typedef void(*ge_timer_sleepus_func_t)(const ge_timer_t* timer, ge_time_t time); +typedef ge_time_t(*ge_timer_getms_func_t)(ge_timer_t* timer); +typedef void(*ge_timer_sleepms_func_t)(const ge_timer_t* timer, ge_time_t time); + +struct ge_timer { + ge_time_t time; + ge_timer_getms_func_t func_getms; + ge_timer_sleepms_func_t func_sleepms; + ge_timer_getus_func_t func_getus; + ge_timer_sleepus_func_t func_sleepus; +}; + +#endif // __GE_TIMER_H__ diff --git a/game_engine/interface/timer/ge_fps.c b/game_engine/interface/timer/ge_fps.c new file mode 100644 index 0000000..aeab98c --- /dev/null +++ b/game_engine/interface/timer/ge_fps.c @@ -0,0 +1,66 @@ +// ge_fps.c +#include "ge_fps.h" + +// 初始化FPS控制器 +void ge_fps_init(ge_fps_controller_t* fps_ctrl, ge_u32_t target_fps, + ge_fps_get_us_func_t get_us, ge_fps_sleep_us_func_t sleep_us) { + fps_ctrl->target_fps = target_fps; + fps_ctrl->frame_duration = 1000 / target_fps; + fps_ctrl->last_frame_time = get_us(); + fps_ctrl->frame_time = 0; + fps_ctrl->sleep_time = 0; + fps_ctrl->frame_count = 0; + fps_ctrl->fps = 0; + fps_ctrl->last_fps_time = fps_ctrl->last_frame_time; + fps_ctrl->call_get_us = get_us; + fps_ctrl->call_sleep_us = sleep_us; +} + +// 帧开始 +void ge_fps_begin_frame(ge_fps_controller_t* fps_ctrl) { + fps_ctrl->last_frame_time = fps_ctrl->call_get_us(); +} + +// 帧结束 +void ge_fps_end_frame(ge_fps_controller_t* fps_ctrl) { + ge_u32_t current_time = fps_ctrl->call_get_us(); + fps_ctrl->frame_time = current_time - fps_ctrl->last_frame_time; + + // 帧率自适应算法 + if (fps_ctrl->frame_time < fps_ctrl->frame_duration) { + ge_u32_t sleep_time = fps_ctrl->frame_duration - fps_ctrl->frame_time; + + // 动态调整休眠精度 + if (sleep_time > 2000) { // >2ms使用Sleep + fps_ctrl->call_sleep_us(sleep_time - 1000); // 提前1ms唤醒 + current_time = fps_ctrl->call_get_us(); + + // 剩余时间忙等待 + while ((current_time - fps_ctrl->last_frame_time) < fps_ctrl->frame_duration) { + current_time = fps_ctrl->call_get_us(); + } + } else { + // 短时间直接忙等待 + while ((fps_ctrl->call_get_us() - fps_ctrl->last_frame_time) < fps_ctrl->frame_duration); + } + } + + // 更新FPS计数(同原逻辑) + fps_ctrl->frame_count++; + if (current_time - fps_ctrl->last_fps_time >= 1000000) { + fps_ctrl->fps = fps_ctrl->frame_count; + fps_ctrl->frame_count = 0; + fps_ctrl->last_fps_time = current_time; + + // 动态调整目标帧时间(±5%容差) + // ge_u32_t avg_frame_time = 1000000 / fps_ctrl->fps; + // if (avg_frame_time > fps_ctrl->frame_duration * 1.05f) { + // fps_ctrl->frame_duration = avg_frame_time; + // } else if (avg_frame_time < fps_ctrl->frame_duration * 0.95f) { + // fps_ctrl->frame_duration = GE_MAX( + // fps_ctrl->target_fps * 1000, + // avg_frame_time + // ); + // } + } +} \ No newline at end of file diff --git a/game_engine/timer/ge_fps.h b/game_engine/interface/timer/ge_fps.h similarity index 77% rename from game_engine/timer/ge_fps.h rename to game_engine/interface/timer/ge_fps.h index d558634..40333b6 100644 --- a/game_engine/timer/ge_fps.h +++ b/game_engine/interface/timer/ge_fps.h @@ -5,11 +5,11 @@ struct ge_fps_controller; typedef struct ge_fps_controller ge_fps_controller_t; -typedef ge_u32_t (*ge_fps_get_ms_func_t)(void); -typedef void (*ge_fps_sleep_ms_func_t)(ge_u32_t ms); +typedef ge_u32_t (*ge_fps_get_us_func_t)(void); +typedef void (*ge_fps_sleep_us_func_t)(ge_u32_t us); void ge_fps_init(ge_fps_controller_t* fps_ctrl, ge_u32_t target_fps, - ge_fps_get_ms_func_t get_ms, ge_fps_sleep_ms_func_t sleep_ms); + ge_fps_get_us_func_t get_ms, ge_fps_sleep_us_func_t sleep_ms); void ge_fps_begin_frame(ge_fps_controller_t* fps_ctrl); void ge_fps_end_frame(ge_fps_controller_t* fps_ctrl); @@ -24,8 +24,8 @@ struct ge_fps_controller { ge_u32_t fps; // 实际帧率 ge_u32_t last_fps_time; // 上次计算FPS的时间 - ge_fps_get_ms_func_t call_get_ms; - ge_fps_sleep_ms_func_t call_sleep_ms; + ge_fps_get_us_func_t call_get_us; + ge_fps_sleep_us_func_t call_sleep_us; }; #endif // __GE_FPS_H__ diff --git a/game_engine/timer/ge_timer.c b/game_engine/interface/timer/ge_timer.c similarity index 100% rename from game_engine/timer/ge_timer.c rename to game_engine/interface/timer/ge_timer.c diff --git a/game_engine/timer/ge_timer.h b/game_engine/interface/timer/ge_timer.h similarity index 67% rename from game_engine/timer/ge_timer.h rename to game_engine/interface/timer/ge_timer.h index d5f8223..2fcf55f 100644 --- a/game_engine/timer/ge_timer.h +++ b/game_engine/interface/timer/ge_timer.h @@ -7,9 +7,16 @@ typedef void (*ge_sleep_ms_func_t)(ge_u32_t); typedef ge_u32_t (*ge_get_ms_func_t)(void); +typedef void (*ge_sleep_us_func_t)(ge_u32_t); +typedef ge_u32_t (*ge_get_us_func_t)(void); + typedef struct { ge_sleep_ms_func_t sleep_ms; ge_get_ms_func_t get_ms; + + ge_sleep_us_func_t sleep_us; + ge_get_us_func_t get_us; + ge_fps_controller_t fps_ctl; } ge_timer_t; diff --git a/game_engine/pynic_log/pynic_color.h b/game_engine/pynic_log/pynic_color.h index 11c5966..08abfe6 100644 --- a/game_engine/pynic_log/pynic_color.h +++ b/game_engine/pynic_log/pynic_color.h @@ -5,8 +5,8 @@ * 提供跨平台的终端文本颜色和样式控制支持 */ -#ifndef __PYTHONIC_TERMINAL_COLOR_H__ -#define __PYTHONIC_TERMINAL_COLOR_H__ +#ifndef __PYNIC_TERMINAL_COLOR_H__ +#define __PYNIC_TERMINAL_COLOR_H__ /// @name 前景色控制码 /// @{ @@ -56,4 +56,4 @@ #define ANSI_FMT(str, fmt) str ///< 禁用样式输出 #endif -#endif // __PYTHONIC_TERMINAL_COLOR_H__ +#endif // __PYNIC_TERMINAL_COLOR_H__ diff --git a/game_engine/pynic_log/pynic_log.h b/game_engine/pynic_log/pynic_log.h index 7d4b23d..a1b15c9 100644 --- a/game_engine/pynic_log/pynic_log.h +++ b/game_engine/pynic_log/pynic_log.h @@ -3,10 +3,10 @@ * @brief 模仿python标准库logger的日志系统核心模块(支持多级日志、断言和异常处理) */ -#ifndef __PYTHONIC_LOG_H__ -#define __PYTHONIC_LOG_H__ +#ifndef __PYNIC_LOG_H__ +#define __PYNIC_LOG_H__ -#ifndef __NO_STDIO__ +#ifndef __PYNIC_NO_STDIO__ #include #include @@ -21,11 +21,11 @@ #endif #endif -#ifndef __NO_PYNIC_COLOR__ +#ifndef __PYNIC_NO_COLOR__ #include "pynic_color.h" #else -#ifndef __LOG_NO_COLOR__ -#define __LOG_NO_COLOR__ +#ifndef __PYNIC_LOG_NO_COLOR__ +#define __PYNIC_LOG_NO_COLOR__ #endif #endif @@ -50,7 +50,7 @@ #endif #define _PYNIC_STR(str) #str -#define PYLIKE_STR(str) _PYNIC_STR(str) +#define PYNIC_STR(str) _PYNIC_STR(str) /** * @brief 日志级别枚举 @@ -199,7 +199,7 @@ void log_set_handler(logger_t* logger, pynic_log_handler handler); #define AssertFmt(cond, format, ...) _Assert(cond, "Assertion Failure: " format, ## __VA_ARGS__) ///< 带格式的断言检查 #define PanicFmt(format, ...) _Assert(0, "Panic: " format, ## __VA_ARGS__) ///< 立即触发致命错误 #ifndef Assert -#define Assert(cond) AssertFmt(cond, "cond is `" PYLIKE_STR(cond) "`") ///< 基础断言检查 +#define Assert(cond) AssertFmt(cond, "cond is `" PYNIC_STR(cond) "`") ///< 基础断言检查 #endif #define Panic(...) PanicFmt(__VA_ARGS__) ///< 触发致命错误(带自定义消息) #define TODO() PanicFmt("TODO please implement me") ///< 标记未实现代码(触发致命错误) @@ -219,7 +219,7 @@ static inline const char* pynic_level_str(log_level_t level) { return level_str; } -#ifdef __PYTHONIC_TERMINAL_COLOR_H__ +#ifdef __PYNIC_TERMINAL_COLOR_H__ static inline const char* pynic_level_color(log_level_t level) { const char* color_code = ANSI_NONE; switch (level) { @@ -237,11 +237,11 @@ static inline const char* pynic_level_color(log_level_t level) { #ifdef __PYNIC_LOG_IMPLIMENT__ -static void default_handler(log_level_t level, const char* module, const char* file, int line, const char* message) { +static void __pynic_log_default_handler(log_level_t level, const char* module, const char* file, int line, const char* message) { const char* level_str = pynic_level_str(level); -/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出 -#ifndef __LOG_NO_COLOR__ +/// @note: 定义 __PYNIC_LOG_NO_COLOR__ 会取消颜色输出 +#ifndef __PYNIC_LOG_NO_COLOR__ _pynic_logout_printf(ANSI_BOLD "%s[%s] - %s - %s:%d | %s" ANSI_NONE "\n", pynic_level_color(level), level_str, module, file, line, message); #else @@ -256,7 +256,7 @@ static void default_handler(log_level_t level, const char* module, const char* f static logger_t __pynic_root_logger = { .name = "root", .level = LOG_LEVEL_ALL, - .handler = default_handler, + .handler = __pynic_log_default_handler, }; void init_logger(logger_t* logger, const char* name) { @@ -265,7 +265,7 @@ void init_logger(logger_t* logger, const char* name) { void init_logger_ex(logger_t* logger, const char* name, pynic_log_handler hander) { logger->name = name; - logger->handler = hander ? hander : default_handler; + logger->handler = hander ? hander : __pynic_log_default_handler; log_set_level(logger, LOG_LEVEL_ALL); } @@ -285,4 +285,4 @@ void log_set_handler(logger_t* logger, pynic_log_handler handler) { } #endif -#endif // __PYTHONIC_LOG_H__ +#endif // __PYNIC_LOG_H__ diff --git a/game_engine/render/ge_render.h b/game_engine/render/ge_render.h deleted file mode 100644 index cc1c93c..0000000 --- a/game_engine/render/ge_render.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __GE_RENDER_H__ -#define __GE_RENDER_H__ - -#include - -struct ge_render_ctx; -typedef struct ge_render_ctx ge_render_t; - -typedef void (*ge_render_init_func_t)(ge_render_t* ctx); -typedef void (*ge_render_clear_func_t)(ge_render_t* ctx); -typedef void (*ge_render_draw_func_t) - (ge_render_t* ctx, ge_vector2i_t pos, const char* data); -typedef void (*ge_render_drawex_func_t) - (ge_render_t* ctx, ge_vector2i_t pos, const char* data, const void* propety); -typedef void (*ge_render_getsize_func_t) - (ge_render_t* ctx, ge_vector2i_t *size); -typedef void (*ge_render_push_event) - (ge_render_t* ctx, void* event); - -struct ge_render_ctx { - const void* content; - ge_vector2i_t screen_size; - ge_render_init_func_t init; - ge_render_clear_func_t clear; - ge_render_draw_func_t draw; - ge_render_drawex_func_t drawex; - ge_render_getsize_func_t getsize; -}; - -#endif // __GE_RENDER_H__ diff --git a/game_engine/resources/ge_resources.h b/game_engine/resources/ge_resources.h deleted file mode 100644 index 99cb530..0000000 --- a/game_engine/resources/ge_resources.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __GE_RESOURCES_H__ -#define __GE_RESOURCES_H__ - -#include - -typedef struct { -} ge_res_bmp_t; - -typedef struct { - ge_uid_t res_id; - const char* data; -} ge_drawable_t; - -/* -tank 3 * 3 (0) -"|\n" -" # \n" -"###\n" -"###\n" - -wall 3 * 3 (1) -"@@@\n" -"@@@\n" -"@@@\n" - -tilemap 3 * 3 -"1,1,1\n" -"-1,1,0\n" -"1,0,1\n" - -exece -{qiang} - -"@@@\n""@@@\n" -"@@@\n""@@@\n" -"@@@\n""@@@\n" -*/ -#endif // __GE_RESOURCES_H__ diff --git a/game_engine/timer/ge_fps.c b/game_engine/timer/ge_fps.c deleted file mode 100644 index 7b9c5b1..0000000 --- a/game_engine/timer/ge_fps.c +++ /dev/null @@ -1,53 +0,0 @@ -// ge_fps.c -#include "ge_fps.h" - -// 初始化FPS控制器 -void ge_fps_init(ge_fps_controller_t* fps_ctrl, ge_u32_t target_fps, - ge_fps_get_ms_func_t get_ms, ge_fps_sleep_ms_func_t sleep_ms) { - fps_ctrl->target_fps = target_fps; - fps_ctrl->frame_duration = 1000 / target_fps; - fps_ctrl->last_frame_time = get_ms(); - fps_ctrl->frame_time = 0; - fps_ctrl->sleep_time = 0; - fps_ctrl->frame_count = 0; - fps_ctrl->fps = 0; - fps_ctrl->last_fps_time = fps_ctrl->last_frame_time; - fps_ctrl->call_get_ms = get_ms; - fps_ctrl->call_sleep_ms = sleep_ms; -} - -// 帧开始 -void ge_fps_begin_frame(ge_fps_controller_t* fps_ctrl) { - fps_ctrl->last_frame_time = fps_ctrl->call_get_ms(); -} - -// 帧结束 -void ge_fps_end_frame(ge_fps_controller_t* fps_ctrl) { - // 计算当前帧耗时 - ge_u32_t current_time = fps_ctrl->call_get_ms(); - fps_ctrl->frame_time = current_time - fps_ctrl->last_frame_time; - - // 计算需要休眠的时间 - if (fps_ctrl->frame_time < fps_ctrl->frame_duration) { - fps_ctrl->sleep_time = fps_ctrl->frame_duration - fps_ctrl->frame_time; - - // 高精度休眠 - fps_ctrl->call_sleep_ms(fps_ctrl->sleep_time); - - // 更新实际休眠后时间 - current_time = fps_ctrl->call_get_ms(); - fps_ctrl->sleep_time = current_time - fps_ctrl->last_frame_time - fps_ctrl->frame_time; - } else { - fps_ctrl->sleep_time = 0; - } - - // 更新FPS计数 - fps_ctrl->frame_count++; - - // 每秒计算一次实际FPS - if (current_time - fps_ctrl->last_fps_time >= 1000) { - fps_ctrl->fps = fps_ctrl->frame_count; - fps_ctrl->frame_count = 0; - fps_ctrl->last_fps_time = current_time; - } -} diff --git a/game_engine/utils/ge_kfifo.h b/game_engine/utils/ge_kfifo.h index 980f264..1c51b72 100644 --- a/game_engine/utils/ge_kfifo.h +++ b/game_engine/utils/ge_kfifo.h @@ -54,13 +54,13 @@ struct __ge_kfifo { */ #define DECLARE_GE_KFIFO(fifo, type, size, tname) struct tname __STRUCT_GE_KFIFO(type, size) fifo -#define INIT_GE_KFIFO(fifo, type) do { \ +#define INIT_GE_KFIFO(fifo) do { \ struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \ __kfifo->in = 0; \ __kfifo->out = 0; \ - __kfifo->mask = GE_ARRAY_SIZE((fifo).buf) - 1; \ - __kfifo->esize = sizeof(*(fifo).buf); \ - __kfifo->data = (fifo).buf; \ + __kfifo->mask = GE_ARRAY_SIZE((fifo)->buf) - 1; \ + __kfifo->esize = sizeof(*((fifo)->buf)); \ + __kfifo->data = (fifo)->buf; \ } while (0) /** @@ -173,7 +173,7 @@ struct __ge_kfifo { #define ge_kfifo_peek(fifo, val) do { \ unsigned int __ret; \ struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \ - __ret = !kfifo_is_empty(fifo); \ + __ret = !ge_kfifo_is_empty(fifo); \ if (__ret) { \ *val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \ /*smp_wmb();*/ \ diff --git a/game_engine/utils/ge_vector2i.h b/game_engine/utils/ge_vector2i.h index 9fcc46a..1924410 100644 --- a/game_engine/utils/ge_vector2i.h +++ b/game_engine/utils/ge_vector2i.h @@ -14,7 +14,7 @@ #undef GE_ABS #define GE_ABS(x) ((x) > 0 ? (x) : -(x)) #endif -typedef int ge_unit_t; /**< 坐标值类型定义 */ +typedef int32_t ge_unit_t; /**< 坐标值类型定义 */ /** * @struct ge_vector2_t