Created
December 15, 2013 12:37
-
-
Save jonbro/7972507 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "bhPlacement.h" | |
| float BHPlacement::cx; | |
| float BHPlacement::cy; | |
| // lua accessible functions | |
| BHPlacement::BHPlacement(lua_State *l) | |
| { | |
| } | |
| int BHPlacement::AddPiece(lua_State *l) | |
| { | |
| BHRoom *r = new BHRoom(); | |
| r->x = luaL_checknumber(l, 1); | |
| r->y = luaL_checknumber(l, 2); | |
| r->w = luaL_checknumber(l, 3); | |
| r->h = luaL_checknumber(l, 4); | |
| lua_pushvalue(l, 5); | |
| // store this stack position in the registry index | |
| r->roomRef = luaL_ref(l, LUA_REGISTRYINDEX); | |
| // store all the edges in the edge table as well | |
| for(int i=0;i<4;i++){ | |
| edges.push_back(&r->edges[i]); | |
| r->edges[i].dir = 0; | |
| r->edges[i].owner = r; | |
| } | |
| rooms.push_back(r); | |
| return 0; | |
| } | |
| int BHPlacement::RemovePiece(lua_State *l) | |
| { | |
| //lua_pushvalue(l, 1); | |
| cout << "should be removing room " << endl; | |
| for(int i=edges.size()-1;i>=0;i--){ | |
| // retrieve and store room value on stack | |
| lua_rawgeti(l, LUA_REGISTRYINDEX, edges[i]->owner->roomRef); | |
| if(lua_equal(l, -1, -2) == 1){ | |
| edges.erase(edges.begin()+i); | |
| cout << "found edge to remove" << endl; | |
| } | |
| // pop the value off the top | |
| lua_pop(l, 1); | |
| } | |
| for(int i=0;i<rooms.size();i++){ | |
| lua_rawgeti(l, LUA_REGISTRYINDEX, rooms[i]->roomRef); | |
| if(lua_equal(l, -1, -2) == 1){ | |
| luaL_unref(l, LUA_REGISTRYINDEX, rooms[i]->roomRef); | |
| rooms.erase(rooms.begin()+i); | |
| cout << "found room to remove" << endl; | |
| break; | |
| } | |
| lua_pop(l, 1); | |
| } | |
| return 0; | |
| } | |
| bool Overlaps(BHRoom *a, BHRoom *b){ | |
| return a->x + a->w > b->x && | |
| a->x < b->x + b->w && | |
| a->y + a->h > b->y && | |
| a->y < b->y + b->h; | |
| } | |
| bool Overlaps(vector<BHRoom*> a, BHRoom *b){ | |
| for(int j=0;j<a.size();j++){ | |
| if(Overlaps(a[j], b)) | |
| return true; | |
| } | |
| } | |
| int BHPlacement::FindPositionForPiece(lua_State *l) | |
| { | |
| // create a block that represents the incoming position | |
| BHRoom *ir = new BHRoom(); | |
| ir->x = luaL_checknumber(l, 1); | |
| ir->y = luaL_checknumber(l, 2); | |
| ir->w = luaL_checknumber(l, 3); | |
| ir->h = luaL_checknumber(l, 4); | |
| buildEdgePositions(ir); | |
| // now that the edges have been built and sorted, time to loop through them | |
| bool foundPosition = false; | |
| BHRoom *parent; | |
| for(int i=0;i<edges.size();i++){ | |
| BHEdge *v = edges[i]; | |
| ir->x = v->px; | |
| ir->y = v->py; | |
| parent = v->owner; | |
| // break; | |
| // check with each room to see if the new ghost block overlaps | |
| bool foundOverlap = false; | |
| for(int j=0;j<rooms.size();j++){ | |
| // if this new position (based on the edge) | |
| // overlaps, then we want to fudge it around a bit | |
| if(Overlaps(rooms[j], ir)){ | |
| foundOverlap = true; | |
| BHRoom *a = rooms[j]; | |
| // do the north south direction first | |
| if(v->dir == 0 || v->dir == 1){ | |
| float ox = ir->x; | |
| // push off room that we are overlapping | |
| if(a->x < ir->x) | |
| ir->x = fmin(ir->x+ir->w/4, a->x+ir->w); | |
| else | |
| ir->x = fmax(ir->x-ir->w/4, a->x-ir->w); | |
| // check to see if we are still adjacent to edge, and make sure we aren't overlapping | |
| if(ir->x >= v->owner->x-ir->w && | |
| ir->x <= v->owner->x + v->owner->w && | |
| !Overlaps(rooms, ir)) | |
| { | |
| foundPosition = true; | |
| }else{ | |
| ir->x = ox; | |
| } | |
| }else{ | |
| float oy = ir->y; | |
| // push off room that we are overlapping | |
| if(a->y < ir->y) | |
| ir->y = fmin(ir->y+ir->h/4, a->y+ir->h); | |
| else | |
| ir->y = fmax(ir->y-ir->h/4, a->y-ir->h); | |
| // check to see if we are still adjacent to edge, and make sure we aren't overlapping | |
| if(ir->y >= v->owner->y-ir->h && | |
| ir->y <= v->owner->y + v->owner->h && | |
| !Overlaps(rooms, ir)) | |
| { | |
| foundPosition = true; | |
| }else{ | |
| ir->y = oy; | |
| } | |
| } | |
| // not sure if it should check every possible overlap to see if it | |
| // can be fudged or not. Might should break after failing at the first one | |
| } | |
| } | |
| if(foundPosition || !foundOverlap){ | |
| cout << "checked " << i << endl; | |
| break; | |
| } | |
| } | |
| // return the x,y positions of the new block, and the parent that we found | |
| lua_pushnumber(l, ir->x); | |
| lua_pushnumber(l, ir->y); | |
| lua_rawgeti(l, LUA_REGISTRYINDEX, parent->roomRef); | |
| return 3; | |
| } | |
| // just declare up front so we save some memory thrashing | |
| float aex, aey, bex, bey, ad, bd; | |
| bool BHPlacement::edgeSort(BHEdge *a, BHEdge *b) | |
| { | |
| aex = a->ex; | |
| aey = a->ey; | |
| bex = b->ex; | |
| bey = b->ey; | |
| ad = distSQ(cx, cy, a->ex, a->ey); | |
| bd = distSQ(cx, cy, b->ex, b->ey); | |
| // if everything is equal, then we do some operation to everything | |
| // called fixpoint in the original code. | |
| // it compresses the edges by one on each side, | |
| // so nothing should be at an overlapping position anymore | |
| // I wonder if I could do this when generating the edges in the first place | |
| // also only the "e" part of the edge is used for meausring distances | |
| // the "p" part doesn't need to be set until the ghost block is being placed | |
| if(ad == bd){ | |
| // fix a points | |
| if(a->dir == 0 || a->dir == 1){ | |
| if(aex < a->owner->y + a->owner->w/2) | |
| aex++; | |
| else | |
| aex--; | |
| }else{ | |
| if(aey<a->owner->y+a->owner->h/2) | |
| aey++; | |
| else | |
| aey--; | |
| } | |
| if(b->dir == 0 || b->dir == 1){ | |
| if(bex< b->owner->y+b->owner->w/2) | |
| bex++; | |
| else | |
| bex--; | |
| }else{ | |
| if(bey < b->owner->y+b->owner->h/2) | |
| bey++; | |
| else | |
| bey--; | |
| } | |
| return distSQ(cx, cy, a->ex, a->ey) < distSQ(cx, cy, b->ex, b->ey); | |
| } | |
| return ad < bd; | |
| } | |
| void BHPlacement::buildEdgePositions(BHRoom *incomingr) | |
| { | |
| cx = incomingr->x + incomingr->w/2.0f; | |
| cy = incomingr->y + incomingr->h/2.0f; | |
| for(int i=0;i<rooms.size();i++){ | |
| BHRoom *r = rooms[i]; | |
| BHEdge *n = &r->edges[0]; | |
| BHEdge *s = &r->edges[1]; | |
| BHEdge *e = &r->edges[2]; | |
| BHEdge *w = &r->edges[3]; | |
| n->px = fmax(fmin(incomingr->x, r->x+r->w), r->x-incomingr->w); | |
| n->py = r->y-incomingr->h; | |
| n->ex = fmax(fmin(cx, r->x+r->w), r->x); | |
| n->ey = r->y; | |
| s->px = fmax(fmin(incomingr->x, r->x+r->w), r->x-incomingr->w); | |
| // doesn't need recalc; | |
| s->py = r->y+r->h; | |
| s->ex = fmax(fmin(cx, r->x+r->w), r->x); | |
| s->ey = r->y+r->h; | |
| e->px = r->x-incomingr->w; | |
| e->py = fmax(fmin(incomingr->y, r->y+r->h), r->y-incomingr->h); | |
| e->ex = r->x; | |
| e->ey = fmax(fmin(cy, r->y+r->h),r->y); | |
| w->px = r->x+r->w; | |
| w->py = fmax(fmin(incomingr->y, r->y+r->h), r->y-incomingr->h); | |
| w->ex = r->x+r->w; | |
| w->ey = fmax(fmin(cy, r->y+r->h),r->y); | |
| } | |
| // sort the edges | |
| sort(edges.begin(), edges.end(), BHPlacement::edgeSort); | |
| } | |
| const char BHPlacement::className[] = "BHPlacement"; | |
| Lunar<BHPlacement>::RegType BHPlacement::methods[] = { | |
| method(BHPlacement, AddPiece), | |
| method(BHPlacement, RemovePiece), | |
| method(BHPlacement, FindPositionForPiece), | |
| {0,0} | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment