CollisionEvent CollisionGrid::cast(const ray& r, CollisionObject* ignore) { CollisionEvent e; e.intersected = false; std::list<vec2> grid_list; rayGridIntersections(r, grid_list); for(std::list<vec2>::iterator g = grid_list.begin(); g != grid_list.end(); g++) { int len = grid_list.size(); int x = (*g)[0]; int y = (*g)[1]; if(x < 0) continue; if(x >= size_x) continue; if(y < 0) continue; if(y >= size_y) continue; std::list<CollisionObject*>& lst = grid[x+y*size_x]; for(std::list<CollisionObject*>::iterator obj = lst.begin(); obj != lst.end(); obj++) { if(ignore == (*obj)) continue; Transformable* t = (Transformable*)((*obj)->script)->getLink(LINK_TRANSFORMABLE); vec3 p = t->getPosition(); float radius = (*obj)->radius; vec2 closestP; float distance; if(!rayCircleIntersection(r, vec2(p[0], p[2]), radius, closestP, distance)) { continue; } else { e.distance = distance; e.intersected = true; e.obj_script = (*obj)->script; e.obj_type = (*obj)->type; return e; } } } return e; }
CollisionEvent CollisionGrid::range_closest(const vec2& i, const float& range) { CollisionEvent e; e.intersected = false; float closest_dist_sq = 999999999.f; CollisionObject* closest_object = 0; int start_x = i[0]-range; if(start_x < 0) start_x = 0; int start_y = i[1]-range; if(start_y < 0) start_y = 0; int end_x = i[0]+range; if(end_x >= size_x) end_x = size_x-1; int end_y = i[0]+range; if(end_y >= size_y) end_y = size_y-1; float range_sq = range*range; for(int x=start_x; x<end_x; x++) { for(int y=start_y; y<end_y; y++) { std::list<CollisionObject*>& lst = grid[x+y*size_x]; for(std::list<CollisionObject*>::iterator obj = lst.begin(); obj != lst.end(); obj++) { Transformable* t = (Transformable*)((*obj)->script->getLink(LINK_TRANSFORMABLE)); vec2 p(t->getPosition()[0], t->getPosition()[2]); float radius = (*obj)->radius; float distance_sq = (p - i).length2(); if(distance_sq <= range_sq && distance_sq < closest_dist_sq && !((*obj)->script->destroyOnNextFrame)) { closest_dist_sq = distance_sq; closest_object = (*obj); } } } } if(closest_object != 0) { e.intersected = true; e.distance = sqrt(closest_dist_sq); e.obj_script = closest_object->script; e.obj_type = closest_object->type; } return e; }
void CollisionGrid::add(Script* script, int type, float radius) { Transformable* t = (Transformable*)script->getLink(LINK_TRANSFORMABLE); if(!t) return; vec3 pos = t->getPosition(); int x = pos[0], y = pos[2]; CollisionObject* obj = new CollisionObject; obj->script = script; obj->type = type; obj->radius = radius; objects.push_back(obj); script->setCollisionObject(obj); update(0.f); }
std::list<CollisionEvent> CollisionGrid::range_all(const vec2& i, const float& range) { std::list<CollisionEvent> events; int start_x = i[0]-(range); if(start_x < 0) start_x = 0; int start_y = i[1]-(range); if(start_y < 0) start_y = 0; int end_x = i[0]+(range); if(end_x >= size_x) end_x = size_x-1; int end_y = i[0]+(range); if(end_y >= size_y) end_y = size_y-1; float range_sq = range*range; for(int x=start_x; x<end_x; x++) { for(int y=start_y; y<end_y; y++) { std::list<CollisionObject*>& lst = grid[x+y*size_x]; for(std::list<CollisionObject*>::iterator obj = lst.begin(); obj != lst.end(); obj++) { Transformable* t = (Transformable*)((*obj)->script->getLink(LINK_TRANSFORMABLE)); vec2 p = vec2(t->getPosition()[0], t->getPosition()[2]); float radius = (*obj)->radius; float distance_sq = (p - i).length2(); if(distance_sq <= range_sq && !((*obj)->script->destroyOnNextFrame)) { CollisionEvent e; e.intersected = true; e.distance = sqrt(distance_sq); e.obj_script = (*obj)->script; e.obj_type = (*obj)->type; events.push_back(e); } } } } return events; }
void CollisionGrid::update(float frameDelta) { //if(!grid) return; for(boost::unordered_map<int, std::list<CollisionObject*> >::iterator lst = grid.begin(); lst != grid.end(); lst++) { lst->second.clear(); } // memset(walk_grid, 0, sizeof(bool)*size_x*size_y); for(std::list<CollisionObject*>::iterator obj = objects.begin(); obj != objects.end(); obj++) { Transformable* t = (Transformable*)((*obj)->script->getLink(LINK_TRANSFORMABLE)); vec3 p = t->getPosition(); float r = (*obj)->radius; int x = p[0], y = p[2]; walk_grid[x+y*size_x] = 1; grid[x+y*size_x].push_back(*obj); } }
Transformable::Transformable(const Transformable& other) { // We can only copy the layouts when they are strings Layout2d position = {other.getPosition()}; Layout2d size = {other.getSize()}; if (other.m_position.x.getImpl()->operation == LayoutImpl::Operation::String) position.x = other.m_position.x.getImpl()->stringExpression; if (other.m_position.y.getImpl()->operation == LayoutImpl::Operation::String) position.y = other.m_position.y.getImpl()->stringExpression; if (other.m_size.x.getImpl()->operation == LayoutImpl::Operation::String) size.x = other.m_size.x.getImpl()->stringExpression; if (other.m_size.y.getImpl()->operation == LayoutImpl::Operation::String) size.y = other.m_size.y.getImpl()->stringExpression; setPosition(position); setSize(size); }