aoi十字链表
#include <stdio.h> #include <string.h> extern "C" { #include <lua.h> #include <lauxlib.h> #include <lualib.h> } //#pragma comment(lib,"lua.lib") #define LUA_LIB #include "skynet.h" #include <stdio.h> #include <stdint.h> #include <string.h> #include <stdbool.h> #include <assert.h> #include <stdlib.h> #include <time.h> #include <lua.h> #include <lauxlib.h> #include <iostream> #define INVALID_ID (~0) #define PRE_ALLOC 30000 #define AOI_RADIS 25 #define MAX_POSITION 1200 #define MODE_WATCHER 1 #define MODE_MARKER 2 #define MODE_MOVE 4 #define MODE_DROP 8 #define MAX_PATROL_POINTS 10 #define \ CHECK_MINMAX(x, min, max) \ if ((x) < (min)) \ return; \ if ((x) >= (max)) \ return; \ //hash struct element { int64_t key; int64_t value; }; struct hashtable { struct element **elm; int64_t count; int64_t size; // PRE_ALLOC }; int64_t hashcode(struct hashtable* t, int64_t key) { return key%t->size; } struct hashtable* hash_init() { struct hashtable *t = (struct hashtable*)malloc(sizeof(struct hashtable)); t->size = PRE_ALLOC; t->count = 0; t->elm = (struct element **)malloc(t->size * sizeof(struct element*)); for (int64_t i = 0; i < t->size; i++) { t->elm[i] = (struct element*)malloc(sizeof(struct element)); t->elm[i]->key = -1; t->elm[i]->value = -1; } return t; } void hash_release(struct hashtable* t) { if (NULL == t) return; for (int64_t i = 0; i < t->size; i++) { free(t->elm[i]); } free(t->elm); free(t); } void hash_reset(struct hashtable* t) { t->count = 0; for (int64_t i = 0; i < t->size; i++) { t->elm[i]->key = -1; t->elm[i]->value = -1; } } void hash_copy(struct hashtable* t, struct hashtable* s) { if (s&&t) { for (int64_t i = 0; i < t->size; i++) { t->elm[i]->key = -1; t->elm[i]->value = -1; } for (int64_t i = 0; i < s->size; i++) { t->elm[i]->key = s->elm[i]->key; t->elm[i]->value = s->elm[i]->value; } t->count = s->count; t->size = s->size; } } void hash_set(struct hashtable* t, int64_t key, int64_t value) { if (NULL == t) return; int64_t position = hashcode(t, key); for (int64_t i = 1; t->elm[position]->key >= 0 && i < t->size; i++) { position = (hashcode(t, position) + i) % t->size; } t->elm[position]->key = key; t->elm[position]->value = value; t->count += 1; } int64_t hash_get(struct hashtable* t, int64_t key) { if (NULL == t) return -1; int64_t position = hashcode(t, key); while (t->elm[position]->key != key) { position = hashcode(t, position + 1); if (t->elm[position]->key == -1 || position == hashcode(t, key)) { return -1; } } return position; } //hash //可见对象集合 struct watchset { int64_t* idset; uint32_t last; struct hashtable* htable; }; //坐标节点 struct dnode { int64_t id; int x; int y; int mode; struct dnode * xPrev; struct dnode * xNext; struct dnode * yPrev; struct dnode * yNext; }; //data from lua struct objectdata { int64_t id; int x; int y; int iswatcher; int ismarker; int patrols[MAX_PATROL_POINTS][2]; uint32_t patrolNum; uint32_t aoirange; }; struct object { int ref; int64_t id; int version; int mode; int last[2]; int position[2]; ///被观察者(地图上对象),观察者也会存进来 struct dnode** patrolnodes; //第一个节点为当前移动节点 int patrols[MAX_PATROL_POINTS][2]; //行军路点 uint32_t patrolNum; //观察者(玩家) struct watchset* watchedset; //可见列表 uint32_t aoirange; //视野范围 }; //objhash struct objelement { int64_t key; struct object* value; }; struct objhashtable { struct objelement **elm; int64_t count; int64_t size; // PRE_ALLOC }; int64_t objhashcode(struct objhashtable* t, int64_t key) { return key%t->size; } struct objhashtable* objhash_init() { struct objhashtable *t = (struct objhashtable*)malloc(sizeof(struct objhashtable)); t->size = PRE_ALLOC; t->count = 0; t->elm = (struct objelement **)malloc(t->size * sizeof(struct objelement*)); for (int64_t i = 0; i < t->size; i++) { t->elm[i] = (struct objelement*)malloc(sizeof(struct objelement)); t->elm[i]->key = -1; t->elm[i]->value = NULL; } return t; } void objhash_release(struct objhashtable* t) { if (NULL == t) return; for (int64_t i = 0; i < t->size; i++) { free(t->elm[i]); } free(t->elm); free(t); } static void objhash_foreach(struct objhashtable* t, void(*func)(void *ud, struct object *obj), void *ud) { for (int64_t i = 0; i < t->size; i++) { if (t->elm[i]->value) { func(ud, t->elm[i]->value); } } } void objhash_reset(struct objhashtable* t) { t->count = 0; for (int64_t i = 0; i < t->size; i++) { t->elm[i]->key = -1; t->elm[i]->value = NULL; } } void objhash_copy(struct objhashtable* t, struct objhashtable* s) { if (s&&t) { for (int64_t i = 0; i < t->size; i++) { t->elm[i]->key = -1; t->elm[i]->value = NULL; } for (int64_t i = 0; i < s->size; i++) { t->elm[i]->key = s->elm[i]->key; t->elm[i]->value = s->elm[i]->value; } t->count = s->count; t->size = s->size; } } void objhash_set(struct objhashtable* t, int64_t key, struct object* value) { if (NULL == t) return; int64_t position = objhashcode(t, key); for (int64_t i = 1; t->elm[position]->key >= 0 && i < t->size; i++) { position = (objhashcode(t, position) + i) % t->size; } t->elm[position]->key = key; t->elm[position]->value = value; t->count += 1; } int64_t objhash_get(struct objhashtable* t, int64_t key) { if (NULL == t) return -1; int64_t position = objhashcode(t, key); while (t->elm[position]->key != key) { position = objhashcode(t, position + 1); if (t->elm[position]->key == -1 || position == objhashcode(t, key)) { return -1; } } return position; } struct object* objhash_getobject(struct objhashtable* t, int64_t key) { if (NULL == t) return NULL; int64_t position = objhashcode(t, key); while (t->elm[position]->key != key) { position = objhashcode(t, position + 1); if (t->elm[position]->key == -1 || position == objhashcode(t, key)) { return NULL; } } return t->elm[position]->value; } //hash struct map_slot { int64_t id; struct object * obj; int64_t next; }; struct map { int64_t size; int64_t lastfree; struct map_slot * slot; }; struct aoispace { struct skynet_context *ctx; //struct map * object; struct objhashtable* object; struct dnode*** dnodearray; //[1200][1200]用于快速查找 struct dnode** dlinks; struct watchset* lastSet; int64_t newidset[PRE_ALLOC]; uint32_t newid; int64_t delidset[PRE_ALLOC]; uint32_t delid; int64_t updateidset[PRE_ALLOC]; uint32_t updateid; }*space; struct watchset* new_watchset() { struct watchset * wset = (struct watchset *)malloc(sizeof(*wset)); wset->idset = (int64_t*)malloc(PRE_ALLOC * sizeof(int64_t)); wset->last = 0; wset->htable = hash_init(); return wset; }; void delete_watchset(struct aoispace * space, struct watchset * wset) { free(wset->idset); hash_release(wset->htable); free(wset); } void copy_watchset(struct watchset* dest, struct watchset* src) { dest->last = src->last; memcpy(dest->idset, src->idset, PRE_ALLOC * sizeof(int64_t)); hash_copy(dest->htable, src->htable); } void compare_watchset(struct aoispace * space, struct watchset* newSet, struct watchset* oldSet) { space->newid = 0; space->delid = 0; space->updateid = 0; memset(space->newidset, 0, sizeof(space->newidset)); memset(space->delidset, 0, sizeof(space->delidset)); memset(space->updateidset, 0, sizeof(space->updateidset)); for (uint32_t i = 0; i < newSet->last; ++i) { int64_t id = newSet->idset[i]; if (hash_get(oldSet->htable, id) >= 0) { space->updateidset[space->updateid++] = id; } else { space->newidset[space->newid++] = id; } } for (uint32_t i = 0; i < oldSet->last; ++i) { int64_t id = oldSet->idset[i]; if (hash_get(newSet->htable, id) < 0) { space->delidset[space->delid++] = id; } } } void add_dnode(struct aoispace * space, struct dnode * node) { int slot = node->x; CHECK_MINMAX(slot, 0, MAX_POSITION); struct dnode* curnode = space->dlinks[slot]; struct dnode* cur = curnode; struct dnode* pre = cur->yPrev; while (cur != NULL) { if (cur->y > node->y) { node->yNext = cur; node->yPrev = cur->yPrev; cur->yPrev->yNext = node; cur->yPrev = node; int yslot = node->y; CHECK_MINMAX(yslot, 0, MAX_POSITION); if (space->dnodearray[slot][yslot] == NULL) { space->dnodearray[slot][yslot] = node; } else { node->xNext = space->dnodearray[slot][yslot]; space->dnodearray[slot][yslot] = node; } return; } pre = cur; cur = cur->yNext; } pre->yNext = node; node->yPrev = pre; int yslot = node->y; CHECK_MINMAX(yslot, 0, MAX_POSITION); if (space->dnodearray[slot][yslot] == NULL) { space->dnodearray[slot][yslot] = node; } else { node->xNext = space->dnodearray[slot][yslot]; space->dnodearray[slot][yslot] = node; } } //获取[x,y]aoirange内的对象集合 watcher 0: marker 1:watcher (0:观察者得到被观察者,1:被观察者得到观察者) void getwatch(struct aoispace * space, uint32_t x, uint32_t y, uint32_t aoirange, char watcher, struct watchset* watchedset) { //reset watchedset->last = 0; hash_reset(watchedset->htable); if (aoirange == 0) { aoirange = AOI_RADIS; } int curslot = x; int startslot = curslot - aoirange; if (startslot < 0) startslot = 0; int endslot = curslot + aoirange; if (endslot >= MAX_POSITION) endslot = MAX_POSITION - 1; int startsloty = y - aoirange; if (startsloty < 0) startsloty = 0; int endsloty = y + aoirange; if (endsloty >= MAX_POSITION) endsloty = MAX_POSITION - 1; for (int i = startslot; i <= endslot; ++i) { struct dnode* first = NULL; for (int j = startsloty; j <= endsloty; ++j) { if (space->dnodearray[i][j] != NULL) { first = space->dnodearray[i][j];//[1][1] break; } } if (first == NULL) { continue; } struct dnode* curnode = first; while (curnode != NULL) { if (hash_get(watchedset->htable, curnode->id) >= 0) { curnode = curnode->xNext; std::cout << "dup" << std::endl; continue; } if (watcher == 0 && (curnode->mode&MODE_WATCHER)) { curnode = curnode->xNext; continue; } if (watcher == 1 && (curnode->mode&MODE_MARKER)) { curnode = curnode->xNext; continue; } if (watcher == 1) { //检查观察者视野 struct object* watcher = objhash_getobject(space->object, curnode->id); if (watcher) { if (watcher->position[0] + watcher->aoirange < x) { curnode = curnode->xNext; continue; } if (watcher->position[0] > watcher->aoirange + x) { curnode = curnode->xNext; continue; } if (watcher->position[1] + watcher->aoirange < y) { curnode = curnode->xNext; continue; } if (watcher->position[1] > watcher->aoirange + y) { curnode = curnode->xNext; continue; } } } watchedset->idset[watchedset->last++] = curnode->id; std::cout << "111add id:" << curnode->id << " x:" << curnode->x << " y" << curnode->y << std::endl; hash_set(watchedset->htable, curnode->id, 1); curnode = curnode->xNext; } curnode = first->yNext;//[1][2] while (curnode != NULL) { if (hash_get(watchedset->htable, curnode->id) >= 0) { curnode = curnode->yNext; std::cout << "dup" << std::endl; continue; } if (watcher == 0 && (curnode->mode&MODE_WATCHER)) { curnode = curnode->yNext; continue; } if (watcher == 1 && (curnode->mode&MODE_MARKER)) { curnode = curnode->yNext; continue; } if (watcher == 1) { //检查观察者视野 struct object* watcher = objhash_getobject(space->object, curnode->id); if (watcher) { if (watcher->position[0] + watcher->aoirange < x) { curnode = curnode->yNext; continue; } if (watcher->position[0] > watcher->aoirange + x) { curnode = curnode->yNext; continue; } if (watcher->position[1] + watcher->aoirange < y) { curnode = curnode->yNext; continue; } if (watcher->position[1] > watcher->aoirange + y) { curnode = curnode->yNext; continue; } } } if (curnode->y + aoirange < y) { curnode = curnode->yNext; continue; } if (curnode->y > aoirange + y) { break; } watchedset->idset[watchedset->last++] = curnode->id; std::cout << "222add id:" << curnode->id << " x:" << curnode->x << " y" << curnode->y << std::endl; hash_set(watchedset->htable, curnode->id, 1); curnode = curnode->yNext; } } } // void getmarkers(struct aoispace * space, struct object * obj) { copy_watchset(space->lastSet, obj->watchedset); getwatch(space, obj->position[0], obj->position[1], obj->aoirange, 0, obj->watchedset); compare_watchset(space, obj->watchedset, space->lastSet); //printf("obj %d watch total = %d,lasttotal = %d,new = %d , del = %d, update = %d\n",obj->id,obj->watchedset->last,space->lastSet->last,space->newid,space->delid,space->updateid); }; //一个对象的观察者集合 void getwatchers(struct aoispace * space, struct object * obj) { getwatch(space, obj->position[0], obj->position[1], obj->aoirange, 1, space->lastSet); }; struct dnode* new_objdnode(struct aoispace * space, int64_t id, int x, int y, int mode) { struct dnode* node = (struct dnode*)malloc(sizeof(*node)); node->id = id; node->x = x; node->y = y; node->mode = mode; node->xPrev = NULL; node->xNext = NULL; node->yPrev = NULL; node->yNext = NULL; add_dnode(space, node); return node; }; void update_objdnode(struct aoispace * space, struct dnode* node, int x, int y, int mode) { node->x = x; node->y = y; node->mode = mode; node->xPrev = NULL; node->xNext = NULL; node->yPrev = NULL; node->yNext = NULL; add_dnode(space, node); }; void delete_objdnode(struct aoispace * space, struct dnode* node) { if (node) { free(node); node = NULL; } } void dnode_leave(struct aoispace * space, struct dnode * node) { if (!node) { return; } if (node->xPrev) { node->xPrev->xNext = node->xNext; } if (node->xNext) { node->xNext->xPrev = node->xPrev; } if (node->yPrev) { node->yPrev->yNext = node->yNext; } if (node->yNext) { node->yNext->yPrev = node->yPrev; } CHECK_MINMAX(node->x, 0, MAX_POSITION); CHECK_MINMAX(node->y, 0, MAX_POSITION); //dnodearray struct dnode* cur = space->dnodearray[node->x][node->y]; struct dnode* pre = NULL; while (cur != NULL) { if (cur == node) { if (pre) { pre->xNext = cur->xNext; } if (cur == space->dnodearray[node->x][node->y]) { space->dnodearray[node->x][node->y] = cur->xNext; } cur->xNext = NULL; } pre = cur; cur = cur->xNext; } node->xPrev = NULL; node->xNext = NULL; node->yPrev = NULL; node->yNext = NULL; }; static struct object * new_object(struct aoispace * space, struct objectdata* data) { struct object * obj = (struct object *)malloc(sizeof(*obj)); obj->ref = 1; obj->id = data->id; obj->version = 0; obj->mode = 0; obj->aoirange = data->aoirange; obj->position[0] = data->x; obj->position[1] = data->y; if (data->iswatcher) { obj->mode |= MODE_WATCHER; obj->watchedset = new_watchset(); //观察者也加入链表(只是保存) obj->patrolNum = 1; obj->patrolnodes = (struct dnode**)malloc(sizeof(struct dnode*)); struct dnode* objdnode = new_objdnode(space, obj->id, data->x, data->y, obj->mode); obj->patrolnodes[0] = objdnode; } if (data->ismarker) { obj->mode |= MODE_MARKER; obj->patrols[0][0] = data->x; obj->patrols[0][1] = data->y; obj->patrolNum = data->patrolNum + 1; for (int i = 0; i < data->patrolNum; ++i) { obj->patrols[i + 1][0] = data->patrols[i][0]; obj->patrols[i + 1][1] = data->patrols[i][1]; } obj->patrolnodes = (struct dnode**)malloc(obj->patrolNum * sizeof(struct dnode*)); for (int i = 0; i < obj->patrolNum; i++) { struct dnode* objdnode = new_objdnode(space, obj->id, obj->patrols[i][0], obj->patrols[i][1], obj->mode); obj->patrolnodes[i] = objdnode; } } return obj; } static void update_object(void *s, struct object * obj, struct objectdata* data) { struct aoispace * space = (struct aoispace *)s; if (obj->mode&MODE_WATCHER) { dnode_leave(space, obj->patrolnodes[0]); update_objdnode(space, obj->patrolnodes[0], data->x, data->y, obj->mode); } if (obj->mode&MODE_MARKER) { for (int i = 0; i < obj->patrolNum; i++) { dnode_leave(space, obj->patrolnodes[i]); } obj->patrols[0][0] = data->x; obj->patrols[0][1] = data->y; obj->patrolNum = data->patrolNum + 1; for (int i = 0; i < data->patrolNum; ++i) { obj->patrols[i + 1][0] = data->patrols[i][0]; obj->patrols[i + 1][1] = data->patrols[i][1]; } for (int i = 0; i < obj->patrolNum; i++) { if (obj->patrolnodes[i] != NULL) { update_objdnode(space, obj->patrolnodes[i], obj->patrols[i][0], obj->patrols[i][1], obj->mode); } else { struct dnode* objdnode = new_objdnode(space, obj->id, obj->patrols[i][0], obj->patrols[i][1], obj->mode); obj->patrolnodes[i] = objdnode; } } } obj->position[0] = data->x; obj->position[1] = data->y; obj->aoirange = data->aoirange; } static void delete_object(void *s, struct object * obj) { //printf("delete_object...%d\n",obj->id); struct aoispace * space = (struct aoispace *)s; for (int i = 0; i < obj->patrolNum; i++) { delete_objdnode(space, obj->patrolnodes[i]); } free(obj->patrolnodes); if (obj->mode&MODE_WATCHER) { delete_watchset(space, obj->watchedset); } free(obj); } inline static void grab_object(struct object *obj) { ++obj->ref; } //objmgr inline static void drop_object(struct aoispace * space, struct object *obj) { --obj->ref; if (obj->ref <= 0) { for (int i = 0; i < obj->patrolNum; ++i) { dnode_leave(space, obj->patrolnodes[i]); } int64_t position = objhash_get(space->object, obj->id); if (position >= 0) { space->object->elm[position]->key = -1; space->object->elm[position]->value = NULL; } //objhash_set(space->object, obj->id); delete_object(space, obj); } } struct aoispace * aoispace_create(void) { struct aoispace *space = (struct aoispace *)malloc(sizeof(*space)); space->object = objhash_init(); space->dnodearray = (struct dnode***)malloc(MAX_POSITION * sizeof(struct dnode**)); space->dlinks = (struct dnode**)malloc(MAX_POSITION * sizeof(struct dnode*)); for (int i = 0; i < MAX_POSITION; i++) { space->dnodearray[i] = (struct dnode**)malloc(MAX_POSITION * sizeof(struct dnode*)); for (int j = 0; j < MAX_POSITION; j++) { space->dnodearray[i][j] = NULL; } space->dlinks[i] = (struct dnode*)malloc(sizeof(struct dnode)); space->dlinks[i]->id = -1; space->dlinks[i]->x = 0; space->dlinks[i]->y = 0; space->dlinks[i]->mode = 0; space->dlinks[i]->yPrev = space->dlinks[i]; space->dlinks[i]->yNext = NULL; space->dlinks[i]->xPrev = NULL; space->dlinks[i]->xNext = NULL; } space->lastSet = new_watchset(); return space; } void aoispace_release(struct aoispace *space) { objhash_foreach(space->object, delete_object, space); objhash_release(space->object); for (int i = 0; i < MAX_POSITION; i++) { free(space->dnodearray[i]); free(space->dlinks[i]); } free(space->dnodearray); free(space->dlinks); delete_watchset(space, space->lastSet); free(space); } ///debug void dumpspacedlinks(struct aoispace *space) { //dump for (int i = 0; i < MAX_POSITION; ++i) { struct dnode* curnode = space->dlinks[i]->yNext; while (curnode != NULL) { printf("i=%d id=%ld,x=%d,y=%d\n", i, curnode->id, curnode->x, curnode->y); curnode = curnode->yNext; } } } //lua export func int linit(lua_State *L) { space = aoispace_create(); //printf("aoispace_create..%p\n",space); return 0; } int lexit(lua_State *L) { //printf("aoispace_release..%p\n",space); aoispace_release(space); return 0; } bool printluatable(lua_State *L, int index) { int level = 0; lua_pushnil(L); while (lua_next(L, -2) != 0) { int keyType = lua_type(L, -2); if (keyType == LUA_TNUMBER) { double value = lua_tonumber(L, -2); printf("\n%d--Key:%f ", level, value); } else if (keyType == LUA_TSTRING) { const char* value = lua_tostring(L, -2); printf("\n%d--Key:%s ", level, value); } else { return false; } int valueType = lua_type(L, -1); switch (valueType) { case LUA_TNIL: { break; } case LUA_TBOOLEAN: { int value = lua_toboolean(L, -1); printf("%d\n", value); break; } case LUA_TNUMBER: { printf("%f\n", lua_tonumber(L, -1)); break; } case LUA_TSTRING: { printf("%s\n", lua_tostring(L, -1)); break; } case LUA_TTABLE: { level++; int index = lua_gettop(L); if (!printluatable(L, index)) { printf("popTable error in popTable,error occured\n"); return false; } break; } default: { return false; } } lua_pop(L, 1); } return true; } bool parse_objectdata(lua_State *L, int index, struct objectdata* objdata) { lua_pushnil(L); while (lua_next(L, -2) != 0) { int keyType = lua_type(L, -2); int valueType = lua_type(L, -1); if (keyType == LUA_TSTRING) { const char* key = lua_tostring(L, -2); if (!strcmp(key, "id")) { objdata->id = lua_tonumber(L, -1); //printf("level=%d, id=%d \n",level,objdata->id); } else if (!strcmp(key, "x")) { objdata->x = lua_tonumber(L, -1); //printf("level=%d, x=%d \n",level,objdata->x); } else if (!strcmp(key, "y")) { objdata->y = lua_tonumber(L, -1); //printf("level=%d, y=%d \n",level,objdata->y); } else if (!strcmp(key, "iswatcher")) { objdata->iswatcher = lua_tonumber(L, -1); //printf("level=%d, iswatcher=%d \n",level,objdata->iswatcher); } else if (!strcmp(key, "ismarker")) { objdata->ismarker = lua_tonumber(L, -1); //printf("level=%d, ismarker=%d \n",level,objdata->ismarker); } else if (!strcmp(key, "aoirange")) { objdata->aoirange = lua_tonumber(L, -1); } else if (!strcmp(key, "patrols")) { } else if (!strcmp(key, "px")) { objdata->patrols[objdata->patrolNum - 1][0] = lua_tonumber(L, -1); //printf("level=%d, px=%d \n",level,objdata->patrols[objdata->patrolNum][0]); } else if (!strcmp(key, "py")) { objdata->patrols[objdata->patrolNum - 1][1] = lua_tonumber(L, -1); //printf("level=%d, py=%d \n",level,objdata->patrols[objdata->patrolNum][1]); } else { printf("parse_objectdata error key = %s\n", key); return false; } } else if (keyType == LUA_TNUMBER) { objdata->patrolNum = lua_tointeger(L, -2); } if (LUA_TTABLE == valueType) { int subindex = lua_gettop(L); parse_objectdata(L, subindex, objdata); } lua_pop(L, 1); } return true; } int laddobj(lua_State *L) { struct objectdata data; memset(&data, 0, sizeof(data)); bool ret = parse_objectdata(L, 1, &data); if (ret) { lua_pushinteger(L, 1); for (int k = 0; k < 2; ++k) { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { data.id = k * 100 + i * 10 + j; data.x = i; data.y = j; data.iswatcher = 0; data.ismarker = 1; if (data.id == 0) { data.iswatcher = 1; data.ismarker = 0; } data.aoirange = 300; struct object* obj = objhash_getobject(space->object, data.id); if (obj != NULL) { printf("laddobj.. obj!=NULL id = %ld", data.id); lua_pushinteger(L, 0); return 1; } struct object* newobj = new_object(space, &data); objhash_set(space->object, data.id, newobj); printf("laddobj..%p,%p\n", space, newobj); } } } } else { lua_pushinteger(L, 0); } return 1; } int lupdateobj(lua_State *L) { struct objectdata data; memset(&data, 0, sizeof(data)); bool ret = parse_objectdata(L, 1, &data); if (ret) { struct object* obj = objhash_getobject(space->object, data.id); if (obj == NULL) { printf("lupdateobj.. obj==NULL id = %ld", data.id); lua_pushinteger(L, 0); return 0; } update_object(space, obj, &data); lua_pushinteger(L, 1); } else { lua_pushinteger(L, 0); } return 1; } int ldelobj(lua_State *L) { int64_t id = lua_tointeger(L, 1); struct object* obj = objhash_getobject(space->object, id); if (obj == NULL) { printf("ldelobj.. obj==NULL id = %ld", id); return 0; } drop_object(space, obj); printf("ldelobj..%p,%p\n", space, obj); return 0; } //得到被观察对象集合 int lgetmarkers(lua_State *L) { int64_t id = lua_tointeger(L, 1); struct object* obj = objhash_getobject(space->object, id); if (obj == NULL) { printf("lgetmakers.. obj==NULL id = %ld\n", id); return 0; } if ((obj->mode & MODE_WATCHER) == 0) { printf("lgetmakers.. obj is not watcher id = %ld\n", id); return 0; } printf("lgetmarkers..%p,%p\n", space, obj); getmarkers(space, obj); lua_newtable(L); lua_pushinteger(L, id); lua_setfield(L, -2, "id");//{["id"] = id} lua_newtable(L); for (uint32_t i = 0; i < space->newid; i++) { lua_pushinteger(L, space->newidset[i]); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "new"); //{["new"] = {11,22,33}} lua_newtable(L); for (uint32_t i = 0; i < space->updateid; i++) { lua_pushinteger(L, space->updateidset[i]); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "update"); //{["update"] = {22,33,44}} lua_newtable(L); for (uint32_t i = 0; i < space->delid; i++) { lua_pushinteger(L, space->delidset[i]); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "del");//{["del"] = {33,44,55}} //printf("stack size = %d\n", lua_gettop(L)); return 1; } //得到观察对象集合 int lgetwatchers(lua_State *L) { int64_t id = lua_tointeger(L, 1); printf("lgetwatchers..%p,%ld\n", space, id); struct object* obj = objhash_getobject(space->object, id); printf("lgetwatchers..%p,%p\n", space, obj); if (obj == NULL) { printf("lgetwatchers.. obj==NULL id = %ld\n", id); return 0; } if ((obj->mode & MODE_MARKER) == 0) { printf("lgetwatchers.. obj is not watcher id = %ld\n", id); return 0; } getwatchers(space, obj); lua_newtable(L); lua_pushinteger(L, id); lua_setfield(L, -2, "id"); lua_newtable(L); for (uint32_t i = 0; i < space->lastSet->last; i++) { lua_pushinteger(L, space->lastSet->idset[i]); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "watchers"); return 1; } //根据坐标算出视野内所有对象 int lgetwatch(lua_State *L) { int x = lua_tointeger(L, 1); int y = lua_tointeger(L, 2); int range = lua_tointeger(L, 3); int watcher = lua_tointeger(L, 4); getwatch(space, x, y, range, watcher, space->lastSet); lua_newtable(L); lua_newtable(L); for (uint32_t i = 0; i < space->lastSet->last; i++) { lua_pushinteger(L, space->lastSet->idset[i]); lua_rawseti(L, -2, i + 1); } lua_setfield(L, -2, "watch"); return 1; } ///////lua int luaopen_aoispace(lua_State *L) { luaL_Reg l[] = { { "init", linit }, { "exit", lexit }, { "addobj", laddobj }, { "updateobj", lupdateobj }, { "delobj", ldelobj }, { "getmarkers", lgetmarkers }, { "getwatchers", lgetwatchers }, { "getwatch", lgetwatch }, { NULL, NULL } }; //luaL_newlib(L, l); return 1; } int main() { lua_State* L = luaL_newstate(); luaL_dofile(L, "Test.lua"); //执行"Test.lua"文件中的代码 /* table is in the stack at index 't' */ //lua_pushnil(L); /* first key */ //stackDump(L); //while (lua_next(L, 2) != 0) { // /* uses 'key' (at index -2) and 'value' (at index -1) */ // printf("%s - %s\n", // lua_typename(L, lua_type(L, -2)), // lua_typename(L, lua_type(L, -1))); // /* removes 'value'; keeps 'key' for next iteration */ // lua_pop(L, 1); //} linit(L); laddobj(L); lua_settop(L, 0); lua_pushnumber(L, 0); lgetmarkers(L); //lua_getglobal(L, "background"); //if (!lua_istable(L, -1)) //{ // return; //} //int red = getfield("r"); //int green = getfield("g"); //int blue = getfield("b"); //dumpspacedlinks(space); getchar(); return 0; }
2022.3.16
目前用的格子的方式。我觉得是九宫格的思维,把地图对象放到格子中
之前aoi,是个链表,可以看成只有Y轴一条链,十字链表可以实现动态的视野范围,获取aoi时,只需要根据视野的x轴,遍历y轴链表
我觉得对于大地图更节省内存,效率更好些,可以实现动态视野,但实现更复杂,九宫格实现简单些,不容易出bug
ROK这种类型的游戏,视野变化很大,最大视野可能是最小视野的2倍以上,动态视野收益很大,视图同步包体积会减少很多在最小视野的时候,符合十字链表的使用场景。
十字链表也有格子的概念,只是格子比较小,比如你们地图大小是1000x1000,一个坐标单位实际上是10