#ifndef OCT_TERMBOX_SPRITE_H #define OCT_TERMBOX_SPRITE_H #include #include #include #include #include #include "termbox.h" #define OCT_MAX_SPRITE_SIZE 101 #define OCT_INITIAL_NUM_SPRITES 100 #define OCT_SPRITE_LIST_REALLOC_LENGTH 100 #define OCT_SPRITE_MEMBER_NAME_MAXLENGTH 10 #define OCT_SPRITE_PRINT_BUFFER_SIZE 1024 #define OCT_OUT_OF_SCREEN 1000 struct oct_tb_sprite { int x; int y; uintattr_t fg; uintattr_t bg; char shape[OCT_MAX_SPRITE_SIZE]; }; struct { // Array of pointers to oct_tb_sprites struct oct_tb_sprite** sprite_list; uint32_t new_index; uint32_t size; uint8_t initialized; } oct_tb_sprite_list; int oct_tb_sprite_list_initialize() { oct_tb_sprite_list.sprite_list = calloc(OCT_INITIAL_NUM_SPRITES, sizeof(struct oct_tb_sprite*)); if (!oct_tb_sprite_list.sprite_list) { perror("Could not allocate memory for sprite list"); return 0; } oct_tb_sprite_list.new_index = 0; oct_tb_sprite_list.size = OCT_INITIAL_NUM_SPRITES; oct_tb_sprite_list.initialized = 1; return 1; } int oct_tb_sprite_list_deinitialize() { free(oct_tb_sprite_list.sprite_list); oct_tb_sprite_list.sprite_list = NULL; oct_tb_sprite_list.new_index = 0; oct_tb_sprite_list.size = 0; oct_tb_sprite_list.initialized = 0; return 1; } // No functionality to remove sprites (just draw offscreen) int oct_tb_sprite__index(lua_State *L) { char index[OCT_SPRITE_MEMBER_NAME_MAXLENGTH]; struct oct_tb_sprite* self = (struct oct_tb_sprite*)lua_touserdata(L, -2); strncpy(index, luaL_checkstring(L, -1), OCT_SPRITE_MEMBER_NAME_MAXLENGTH); if (!strncmp(index, "x", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { lua_pushinteger(L, self->x); } else if (!strncmp(index, "y", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { lua_pushinteger(L, self->y); } else if (!strncmp(index, "fg", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { lua_pushinteger(L, self->fg); } else if (!strncmp(index, "bg", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { lua_pushinteger(L, self->bg); } else if (!strncmp(index, "shape", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { lua_pushstring(L, self->shape); } else { lua_pushnil(L); } return 1; } int oct_tb_sprite__newindex(lua_State *L) { char index[OCT_SPRITE_MEMBER_NAME_MAXLENGTH]; struct oct_tb_sprite* self = (struct oct_tb_sprite*)lua_touserdata(L, -3); strncpy(index, luaL_checkstring(L, -2), OCT_SPRITE_MEMBER_NAME_MAXLENGTH); if (!strncmp(index, "x", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { self->x = luaL_checkinteger(L, -1); } else if (!strncmp(index, "y", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { self->y = luaL_checkinteger(L, -1); } else if (!strncmp(index, "fg", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { self->fg = (uintattr_t)luaL_checkinteger(L, -1); } else if (!strncmp(index, "bg", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { self->bg = (uintattr_t)luaL_checkinteger(L, -1); } else if (!strncmp(index, "shape", OCT_SPRITE_MEMBER_NAME_MAXLENGTH)) { strncpy(self->shape, luaL_checkstring(L, -1), OCT_MAX_SPRITE_SIZE); } return 1; } int oct_tb_sprite__tostring(lua_State *L) { struct oct_tb_sprite* self = (struct oct_tb_sprite*)lua_touserdata(L, -1); char buffer[OCT_SPRITE_PRINT_BUFFER_SIZE]; snprintf(buffer, OCT_SPRITE_PRINT_BUFFER_SIZE, "{\n" "\tx: %d\n" "\ty: %d\n" "\tfg: %d\n" "\tbg: %d\n" "\tshape: %s\n" "}", self->x, self->y, self->bg, self->fg, self->shape); lua_pushstring(L, buffer); return 1; } struct luaL_Reg oct_tb_sprite_metamethods[] = { {"__index", oct_tb_sprite__index}, {"__newindex", oct_tb_sprite__newindex}, {"__tostring", oct_tb_sprite__tostring}, {NULL, NULL} }; int oct_tb_sprite_new(lua_State *L) { if (oct_tb_sprite_list.size == oct_tb_sprite_list.new_index) { if (!reallocarray(oct_tb_sprite_list.sprite_list, sizeof(struct oct_tb_sprite*), oct_tb_sprite_list.size+OCT_SPRITE_LIST_REALLOC_LENGTH)) { perror("Could not reallocate memory for sprite list"); } } struct oct_tb_sprite* new_sprite = (struct oct_tb_sprite*)lua_newuserdata(L, sizeof(struct oct_tb_sprite)); new_sprite->x = OCT_OUT_OF_SCREEN; new_sprite->y = OCT_OUT_OF_SCREEN; new_sprite->fg = 0; new_sprite->bg = 1; strncpy(new_sprite->shape, "", OCT_MAX_SPRITE_SIZE); oct_tb_sprite_list.sprite_list[oct_tb_sprite_list.new_index] = new_sprite; lua_pushstring(L, "oct_tb_sprite_metatable"); lua_gettable(L, LUA_REGISTRYINDEX); lua_setmetatable(L, -2); oct_tb_sprite_list.new_index++; return 1; } void oct_tb_initialize_lua(lua_State *L) { lua_pushcfunction(L, oct_tb_sprite_new); lua_setglobal(L, "oct_tb_sprite_new"); if (luaL_newmetatable(L, "oct_tb_sprite_metatable")) { luaL_setfuncs(L, oct_tb_sprite_metamethods, 0); } } #endif