- Added stay-in-tile-class and border-tile-class constraints.
- Made objects snap to terrain (the game does this automatically for entities but it was a problem with actors) - Small enhancements to the RMS API - New version of cantabrian_highlands This was SVN commit r2688.
This commit is contained in:
parent
c428f510f6
commit
467b14e928
@ -22,11 +22,12 @@ JSFunctionSpec globalFunctions[] = {
|
||||
{"setTexture", setTexture, 3},
|
||||
{"getHeight", getHeight, 2},
|
||||
{"setHeight", setHeight, 3},
|
||||
{"getMapSize", getMapSize, 0},
|
||||
{"randInt", randInt, 1},
|
||||
{"randFloat", randFloat, 0},
|
||||
{"placeObject", placeObject, 5},
|
||||
{"placeObject", placeObject, 4},
|
||||
{"createArea", createArea, 3},
|
||||
{"createObjectGroup", createObjectGroup, 2},
|
||||
{"createObjectGroup", createObjectGroup, 3},
|
||||
{"createTileClass", createTileClass, 0},
|
||||
{0, 0, 0}
|
||||
};
|
||||
@ -220,7 +221,7 @@ JSBool placeObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval
|
||||
JS_ValueToNumber(cx, argv[3], &y);
|
||||
JS_ValueToNumber(cx, argv[4], &orientation);
|
||||
|
||||
theMap->addObject(new Object(type, player, x,0,y, orientation));
|
||||
theMap->addObject(new Object(type, player, x,y, orientation));
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -284,7 +285,7 @@ JSBool createArea(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *
|
||||
JSBool createObjectGroup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
CheckInit(true, cx, __FUNCTION__);
|
||||
if(argc != 1 && argc != 2) {
|
||||
if(argc != 2 && argc != 3) {
|
||||
JS_ReportError(cx, "createObjectGroup: expected 1 or 2 arguments but got %d", argc);
|
||||
}
|
||||
|
||||
@ -294,16 +295,22 @@ JSBool createObjectGroup(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
if(!(placer = ParseObjectGroupPlacer(cx, argv[0]))) {
|
||||
JS_ReportError(cx, "createObjectGroup: argument 1 must be a valid object group placer");
|
||||
}
|
||||
if(argc == 2) {
|
||||
if(!(constr = ParseConstraint(cx, argv[1]))) {
|
||||
JS_ReportError(cx, "createObjectGroup: argument 2 must be a valid constraint");
|
||||
if(!JSVAL_IS_INT(argv[1])) {
|
||||
JS_ReportError(cx, "createObjectGroup: argument 2 must be a valid player number");
|
||||
}
|
||||
|
||||
if(argc == 3) {
|
||||
if(!(constr = ParseConstraint(cx, argv[2]))) {
|
||||
JS_ReportError(cx, "createObjectGroup: argument 3 must be a valid constraint");
|
||||
}
|
||||
}
|
||||
else {
|
||||
constr = new NullConstraint();
|
||||
}
|
||||
|
||||
bool ret = theMap->createObjectGroup(placer, constr);
|
||||
int player = JSVAL_TO_INT(argv[1]);
|
||||
|
||||
bool ret = theMap->createObjectGroup(placer, player, constr);
|
||||
|
||||
delete placer;
|
||||
delete constr;
|
||||
@ -324,3 +331,14 @@ JSBool createTileClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js
|
||||
*rval = INT_TO_JSVAL(id);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool getMapSize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
CheckInit(true, cx, __FUNCTION__);
|
||||
if(argc != 0) {
|
||||
JS_ReportError(cx, "getMapSize: expected 0 arguments but got %d", argc);
|
||||
}
|
||||
|
||||
*rval = INT_TO_JSVAL(theMap->size);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ JSBool getTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *
|
||||
JSBool setTexture(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool getHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool setHeight(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
JSBool getMapSize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
||||
// Low-level placement functions
|
||||
JSBool placeTerrain(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
|
||||
|
@ -18,11 +18,13 @@ ClumpPlacer::~ClumpPlacer()
|
||||
{
|
||||
}
|
||||
|
||||
bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& ret) {
|
||||
bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& retVec) {
|
||||
if(!m->validT(x, y) || !constr->allows(m, x, y)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set<Point> ret;
|
||||
|
||||
float radius = sqrt(size / PI);
|
||||
float perim = 3 * radius * 2 * PI;
|
||||
int intPerim = (int)(ceil(perim));
|
||||
@ -71,7 +73,7 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
|
||||
for(float k=0; k<r; k++) {
|
||||
int i = (int)xx, j = (int)yy;
|
||||
if(m->validT(i, j) && constr->allows(m, i, j)) {
|
||||
ret.push_back(Point(i, j));
|
||||
ret.insert(Point(i, j));
|
||||
}
|
||||
else {
|
||||
failed++;
|
||||
@ -81,6 +83,10 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
|
||||
}
|
||||
}
|
||||
|
||||
for(set<Point>::iterator it = ret.begin(); it != ret.end(); it++) {
|
||||
retVec.push_back(*it);
|
||||
}
|
||||
|
||||
return failed > size * failFraction ? false : true;
|
||||
|
||||
/*if(m->validT(x,y)) {
|
||||
|
@ -39,7 +39,7 @@ bool GetIntField(JSContext* cx, jsval obj, const char* name, int& ret) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetBoolField(JSContext* cx, jsval obj, const char* name, int& ret) {
|
||||
bool GetBoolField(JSContext* cx, jsval obj, const char* name, bool& ret) {
|
||||
jsval val;
|
||||
if(!GetJsvalField(cx, obj, name, val)) return false;
|
||||
if(!JSVAL_IS_BOOLEAN(val)) return false;
|
||||
@ -188,6 +188,7 @@ ObjectGroupPlacer* ParseObjectGroupPlacer(JSContext* cx, jsval val) {
|
||||
jsval jsv;
|
||||
vector<jsval> array;
|
||||
int x, y;
|
||||
bool avoidSelf;
|
||||
TileClass* tileClass;
|
||||
vector<SimpleGroup::Element*> elements;
|
||||
|
||||
@ -196,6 +197,7 @@ ObjectGroupPlacer* ParseObjectGroupPlacer(JSContext* cx, jsval val) {
|
||||
// convert x and y
|
||||
if(!GetIntField(cx, val, "x", x)) return 0;
|
||||
if(!GetIntField(cx, val, "y", y)) return 0;
|
||||
if(!GetBoolField(cx, val, "avoidSelf", avoidSelf)) return 0;
|
||||
if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0;
|
||||
// convert the elements (which will be JS SimpleElement objects)
|
||||
if(!GetJsvalField(cx, val, "elements", jsv)) return 0;
|
||||
@ -210,7 +212,7 @@ ObjectGroupPlacer* ParseObjectGroupPlacer(JSContext* cx, jsval val) {
|
||||
if(!GetFloatField(cx, array[i], "distance", distance)) return 0;
|
||||
elements[i] = new SimpleGroup::Element(type, count, distance);
|
||||
}
|
||||
return new SimpleGroup(elements, tileClass, x, y);
|
||||
return new SimpleGroup(elements, tileClass, avoidSelf, x, y);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
@ -222,6 +224,7 @@ Constraint* ParseConstraint(JSContext* cx, jsval val) {
|
||||
int areaId;
|
||||
TileClass* tileClass;
|
||||
float distance;
|
||||
float distance2;
|
||||
string texture;
|
||||
jsval jsv, jsv2;
|
||||
|
||||
@ -258,6 +261,17 @@ Constraint* ParseConstraint(JSContext* cx, jsval val) {
|
||||
if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0;
|
||||
return new AvoidTileClassConstraint(tileClass, distance);
|
||||
|
||||
case TYPE_STAY_IN_TILE_CLASS_CONSTRAINT:
|
||||
if(!GetFloatField(cx, val, "distance", distance)) return 0;
|
||||
if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0;
|
||||
return new StayInTileClassConstraint(tileClass, distance);
|
||||
|
||||
case TYPE_BORDER_TILE_CLASS_CONSTRAINT:
|
||||
if(!GetFloatField(cx, val, "distanceInside", distance)) return 0;
|
||||
if(!GetFloatField(cx, val, "distanceOutside", distance2)) return 0;
|
||||
if(!GetTileClassField(cx, val, "tileClass", tileClass)) return 0;
|
||||
return new BorderTileClassConstraint(tileClass, distance, distance2);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ const int
|
||||
TYPE_SMOOTH_ELEVATION_PAINTER = 9,
|
||||
TYPE_SIMPLE_GROUP = 10,
|
||||
TYPE_AVOID_TILE_CLASS_CONSTRAINT = 11,
|
||||
TYPE_TILE_CLASS_PAINTER = 12;
|
||||
TYPE_TILE_CLASS_PAINTER = 12,
|
||||
TYPE_STAY_IN_TILE_CLASS_CONSTRAINT = 13,
|
||||
TYPE_BORDER_TILE_CLASS_CONSTRAINT = 14;
|
||||
|
||||
// Helper functions to convert objects from JS versions
|
||||
|
||||
|
@ -279,8 +279,8 @@ Area* Map::createArea(AreaPlacer* placer, AreaPainter* painter, Constraint* cons
|
||||
return a;
|
||||
}
|
||||
|
||||
bool Map::createObjectGroup(ObjectGroupPlacer* placer, Constraint* constr) {
|
||||
return placer->place(this, constr);
|
||||
bool Map::createObjectGroup(ObjectGroupPlacer* placer, int player, Constraint* constr) {
|
||||
return placer->place(this, player, constr);
|
||||
}
|
||||
|
||||
int Map::createTileClass() {
|
||||
@ -288,3 +288,18 @@ int Map::createTileClass() {
|
||||
return tileClasses.size();
|
||||
}
|
||||
|
||||
float Map::getExactHeight(float x, float y) {
|
||||
// copied & modified from ScEd
|
||||
|
||||
int xi = min((int) floor(x), size);
|
||||
int yi = min((int) floor(y), size);
|
||||
float xf = x - xi;
|
||||
float yf = y - yi;
|
||||
|
||||
float h00 = height[xi][yi];
|
||||
float h01 = height[xi][yi+1];
|
||||
float h10 = height[xi+1][yi];
|
||||
float h11 = height[xi+1][yi+1];
|
||||
|
||||
return ( 1 - yf ) * ( ( 1 - xf ) * h00 + xf * h10 ) + yf * ( ( 1 - xf ) * h01 + xf * h11 ) ;
|
||||
}
|
||||
|
@ -46,9 +46,11 @@ public:
|
||||
void addObject(class Object* ent);
|
||||
|
||||
Area* createArea(AreaPlacer* placer, AreaPainter* painter, Constraint* constr);
|
||||
bool createObjectGroup(ObjectGroupPlacer* placer, Constraint* constr);
|
||||
bool createObjectGroup(ObjectGroupPlacer* placer, int player, Constraint* constr);
|
||||
|
||||
int createTileClass(); // returns ID of the new class
|
||||
|
||||
float getExactHeight(float x, float y); // get height taking into account terrain curvature
|
||||
};
|
||||
|
||||
#endif
|
@ -6,12 +6,11 @@ using namespace std;
|
||||
Object::Object() {
|
||||
}
|
||||
|
||||
Object::Object(const string& name, int player, float x, float y, float z, float orientation) {
|
||||
Object::Object(const string& name, int player, float x, float y, float orientation) {
|
||||
this->name = name;
|
||||
this->player = player;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->orientation = orientation;
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,11 @@ class Object {
|
||||
public:
|
||||
std::string name; // "template" field for objects, "actor" field for nonobjects
|
||||
int player; // -1 for nonobjects
|
||||
float x, y, z;
|
||||
float x, y;
|
||||
float orientation;
|
||||
|
||||
Object();
|
||||
Object(const std::string& name, int player, float x, float y, float z, float orientation);
|
||||
Object(const std::string& name, int player, float x, float y, float orientation);
|
||||
bool isEntity();
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
class ObjectGroupPlacer
|
||||
{
|
||||
public:
|
||||
virtual bool place(class Map* m, Constraint* constr) = 0;
|
||||
virtual bool place(class Map* m, int player, Constraint* constr) = 0;
|
||||
|
||||
ObjectGroupPlacer(void);
|
||||
virtual ~ObjectGroupPlacer(void);
|
||||
|
@ -7,13 +7,15 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
void OutputObject(Object* e, ostringstream& xml) {
|
||||
void OutputObject(Map* m, Object* e, ostringstream& xml) {
|
||||
float height = m->getExactHeight(e->x, e->y);
|
||||
|
||||
if(e->isEntity()) {
|
||||
xml << "\
|
||||
<Entity>\n\
|
||||
<Template>" << e->name << "</Template>\n\
|
||||
<Player>" << e->player << "</Player>\n\
|
||||
<Position x=\"" << 4*e->x << "\" y=\"" << 4*e->y << "\" z=\"" << 4*e->z << "\" />\n\
|
||||
<Position x=\"" << 4*e->x << "\" y=\"" << height << "\" z=\"" << 4*e->y << "\" />\n\
|
||||
<Orientation angle=\"" << e->orientation << "\" />\n\
|
||||
</Entity>\n";
|
||||
}
|
||||
@ -21,7 +23,7 @@ void OutputObject(Object* e, ostringstream& xml) {
|
||||
xml << "\
|
||||
<Nonentity>\n\
|
||||
<Actor>" << e->name << "</Actor>\n\
|
||||
<Position x=\"" << 4*e->x << "\" y=\"" << 4*e->y << "\" z=\"" << 4*e->z << "\" />\n\
|
||||
<Position x=\"" << 4*e->x << "\" y=\"" << height << "\" z=\"" << 4*e->y << "\" />\n\
|
||||
<Orientation angle=\"" << e->orientation << "\" />\n\
|
||||
</Nonentity>\n";
|
||||
}
|
||||
@ -30,7 +32,7 @@ void OutputObject(Object* e, ostringstream& xml) {
|
||||
void OutputObjects(ostringstream& xml, Map* m, bool entities) {
|
||||
for(int i=0; i<m->objects.size(); i++) {
|
||||
if(m->objects[i]->isEntity() == entities) {
|
||||
OutputObject(m->objects[i], xml);
|
||||
OutputObject(m, m->objects[i], xml);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +41,7 @@ void OutputObjects(ostringstream& xml, Map* m, bool entities) {
|
||||
vector<Object*>& vec = m->terrainObjects[x][y];
|
||||
for(int i=0; i<vec.size(); i++) {
|
||||
if(vec[i]->isEntity() == entities) {
|
||||
OutputObject(vec[i], xml);
|
||||
OutputObject(m, vec[i], xml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,8 +71,37 @@ AvoidTileClassConstraint::AvoidTileClassConstraint(TileClass* tileClass, float d
|
||||
|
||||
bool AvoidTileClassConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return !tileClass->hasTilesInRadius(x, y, distance);
|
||||
return tileClass->countMembersInRadius(x, y, distance) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// StayInTileClassConstraint /////////////////////////////////////////////////////////////
|
||||
|
||||
StayInTileClassConstraint::StayInTileClassConstraint(TileClass* tileClass, float distance) {
|
||||
this->tileClass = tileClass;
|
||||
this->distance = distance;
|
||||
}
|
||||
|
||||
bool StayInTileClassConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return tileClass->countNonMembersInRadius(x, y, distance) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// BorderTileClassConstraint /////////////////////////////////////////////////////////////
|
||||
|
||||
BorderTileClassConstraint::BorderTileClassConstraint(TileClass* tileClass, float distanceInside,
|
||||
float distanceOutside) {
|
||||
this->tileClass = tileClass;
|
||||
this->distanceInside = distanceInside;
|
||||
this->distanceOutside = distanceOutside;
|
||||
}
|
||||
|
||||
bool BorderTileClassConstraint::allows(Map* m, int x, int y)
|
||||
{
|
||||
return tileClass->countMembersInRadius(x, y, distanceOutside) > 0
|
||||
&& tileClass->countNonMembersInRadius(x, y, distanceInside) > 0;
|
||||
}
|
||||
|
||||
|
@ -45,5 +45,23 @@ public:
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
class StayInTileClassConstraint : public Constraint {
|
||||
private:
|
||||
TileClass* tileClass;
|
||||
float distance;
|
||||
public:
|
||||
StayInTileClassConstraint(TileClass* tileClass, float distance);
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
class BorderTileClassConstraint : public Constraint {
|
||||
private:
|
||||
TileClass* tileClass;
|
||||
float distanceInside;
|
||||
float distanceOutside;
|
||||
public:
|
||||
BorderTileClassConstraint(TileClass* tileClass, float distanceInside, float distanceOutside);
|
||||
virtual bool allows(Map* m, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -17,34 +17,50 @@ SimpleGroup::Element::Element(const std::string& t, int c, float d):
|
||||
SimpleGroup::Element::~Element() {
|
||||
}
|
||||
|
||||
bool SimpleGroup::Element::place(int cx, int cy, Map* m, Constraint* constr, vector<Object*>& ret) {
|
||||
bool SimpleGroup::Element::place(int cx, int cy, Map* m, int player, bool avoidSelf,
|
||||
Constraint* constr, vector<Object*>& ret) {
|
||||
int failCount = 0;
|
||||
for(int i=0; i<count; i++) {
|
||||
while(true) {
|
||||
float ang = RandFloat()*2*PI;
|
||||
float x = cx + distance*cos(ang) + 0.5f;
|
||||
float y = cy + distance*sin(ang) + 0.5f;
|
||||
int ix = (int) x;
|
||||
int iy = (int) y;
|
||||
if(m->validT(ix, iy) && constr->allows(m, ix, iy)) {
|
||||
ret.push_back(new Object(type, 0, x, 0, y, RandFloat()*2*PI));
|
||||
break;
|
||||
float x = cx + 0.5f + distance*cos(ang);
|
||||
float y = cy + 0.5f + distance*sin(ang);
|
||||
|
||||
if(x<0 || y<0 || x>m->size || y>m->size) {
|
||||
goto bad;
|
||||
}
|
||||
else {
|
||||
failCount++;
|
||||
if(failCount > 20) {
|
||||
return false;
|
||||
|
||||
if(avoidSelf) {
|
||||
for(int i=0; i<ret.size(); i++) {
|
||||
float dx = x - ret[i]->x;
|
||||
float dy = y - ret[i]->y;
|
||||
if(dx*dx + dy*dy < 1) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!constr->allows(m, (int)x, (int)y)) {
|
||||
goto bad;
|
||||
}
|
||||
|
||||
// if we got here, we're good
|
||||
ret.push_back(new Object(type, player, x, y, RandFloat()*2*PI));
|
||||
break;
|
||||
|
||||
bad: failCount++;
|
||||
if(failCount > 20) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimpleGroup::place(Map* m, Constraint* constr) {
|
||||
bool SimpleGroup::place(Map* m, int player, Constraint* constr) {
|
||||
vector<Object*> ret;
|
||||
for(int i=0; i<elements.size(); i++) {
|
||||
if(!elements[i]->place(x, y, m, constr, ret)) {
|
||||
if(!elements[i]->place(x, y, m, player, avoidSelf, constr, ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -57,8 +73,8 @@ bool SimpleGroup::place(Map* m, Constraint* constr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SimpleGroup::SimpleGroup(vector<SimpleGroup::Element*>& e, TileClass* tc, int _x, int _y):
|
||||
elements(e), x(_x), y(_y), tileClass(tc)
|
||||
SimpleGroup::SimpleGroup(vector<SimpleGroup::Element*>& e, TileClass* tc, bool as, int _x, int _y):
|
||||
elements(e), x(_x), y(_y), tileClass(tc), avoidSelf(as)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -17,16 +17,18 @@ public:
|
||||
Element::Element(const std::string& type, int count, float distance);
|
||||
Element::~Element();
|
||||
|
||||
bool place(int cx, int cy, class Map* m, Constraint* constr, std::vector<Object*>& ret);
|
||||
bool place(int cx, int cy, class Map* m, int player, bool avoidSelf,
|
||||
Constraint* constr, std::vector<Object*>& ret);
|
||||
};
|
||||
|
||||
std::vector<Element*> elements;
|
||||
bool avoidSelf;
|
||||
int x, y;
|
||||
TileClass* tileClass;
|
||||
|
||||
virtual bool place(class Map* m, Constraint* constr);
|
||||
virtual bool place(class Map* m, int player, Constraint* constr);
|
||||
|
||||
SimpleGroup(std::vector<Element*>& elements, TileClass* tileClass, int x, int y);
|
||||
SimpleGroup(std::vector<Element*>& elements, TileClass* tileClass, bool avoidSelf, int x, int y);
|
||||
virtual ~SimpleGroup(void);
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ SimpleTerrain::SimpleTerrain(const std::string& texture, const std::string& tree
|
||||
void SimpleTerrain::placeNew(Map* m, int x, int y) {
|
||||
vector<Object*>& vec = m->terrainObjects[x][y];
|
||||
if(treeType != "") {
|
||||
vec.push_back(new Object(treeType, 0, x+0.5f, 0, y+0.5f, RandFloat()*PI));
|
||||
vec.push_back(new Object(treeType, 0, x+0.5f, y+0.5f, RandFloat()*PI));
|
||||
}
|
||||
m->texture[x][y] = m->getId(texture);
|
||||
}
|
||||
|
@ -5,45 +5,51 @@ using namespace std;
|
||||
|
||||
TileClass::TileClass(int mapSize) {
|
||||
this->mapSize = mapSize;
|
||||
inclusionCount = new int*[mapSize];
|
||||
for(int i=0; i<mapSize; i++) {
|
||||
inclusionCount[i] = new int[mapSize];
|
||||
memset(inclusionCount[i], 0, mapSize*sizeof(int));
|
||||
rc.push_back(new RangeCount(mapSize));
|
||||
}
|
||||
}
|
||||
|
||||
TileClass::~TileClass() {
|
||||
for(int i=0; i<mapSize; i++) {
|
||||
delete inclusionCount[i];
|
||||
delete rc[i];
|
||||
}
|
||||
delete inclusionCount;
|
||||
}
|
||||
|
||||
void TileClass::add(int x, int y) {
|
||||
rc[y]->add(x, 1);
|
||||
|
||||
tiles.insert(Point(x, y));
|
||||
if(!inclusionCount[x][y]) {
|
||||
rc[y]->add(x,1);
|
||||
}
|
||||
inclusionCount[x][y]++;
|
||||
}
|
||||
|
||||
void TileClass::remove(int x, int y) {
|
||||
rc[y]->add(x, -1);
|
||||
|
||||
if(rc[y]->get(x) == 0) {
|
||||
tiles.erase(Point(x, y));
|
||||
inclusionCount[x][y]--;
|
||||
if(!inclusionCount[x][y]) {
|
||||
rc[y]->add(x, -1);
|
||||
}
|
||||
}
|
||||
|
||||
bool TileClass::hasTilesInRadius(float cx, float cy, float r) {
|
||||
// special check for really small classes
|
||||
if(tiles.size() < 4*r) {
|
||||
for(set<Point>::iterator it = tiles.begin(); it != tiles.end(); it++) {
|
||||
Point p = *it;
|
||||
float dx = p.x - cx;
|
||||
float dy = p.y - cy;
|
||||
if(dx*dx + dy*dy <= r*r) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
int TileClass::countMembersInRadius(float cx, float cy, float r) {
|
||||
int mem, nonMem;
|
||||
countInRadius(cx, cy, r, mem, nonMem);
|
||||
return mem;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
int TileClass::countNonMembersInRadius(float cx, float cy, float r) {
|
||||
int mem, nonMem;
|
||||
countInRadius(cx, cy, r, mem, nonMem);
|
||||
return nonMem;
|
||||
}
|
||||
|
||||
void TileClass::countInRadius(float cx, float cy, float r, int& members, int& nonMembers) {
|
||||
members = 0;
|
||||
nonMembers = 0;
|
||||
|
||||
for(float y = cy-r; y <= cy+r; y++) {
|
||||
int iy = (int) y;
|
||||
@ -57,10 +63,9 @@ bool TileClass::hasTilesInRadius(float cx, float cy, float r) {
|
||||
float x2 = cx + dx;
|
||||
int minX = max(0, (int) x1);
|
||||
int maxX = min(mapSize-1, (int) x2);
|
||||
if(rc[iy]->get(minX, maxX+1) > 0) {
|
||||
return true;
|
||||
}
|
||||
int total = maxX - minX + 1;
|
||||
int mem = rc[iy]->get(minX, maxX+1);
|
||||
members += mem;
|
||||
nonMembers += total - mem;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -13,7 +13,7 @@ class TileClass {
|
||||
private:
|
||||
int mapSize;
|
||||
std::vector<RangeCount*> rc; // range count on each row
|
||||
std::set<Point> tiles; // the distinct tiles in the class
|
||||
int** inclusionCount; // the inclusion count for each tile
|
||||
public:
|
||||
TileClass(int mapSize);
|
||||
~TileClass();
|
||||
@ -21,7 +21,9 @@ public:
|
||||
void add(int x, int y);
|
||||
void remove(int x, int y);
|
||||
|
||||
bool hasTilesInRadius(float cx, float cy, float r);
|
||||
void countInRadius(float cx, float cy, float r, int& members, int& nonMembers);
|
||||
int countMembersInRadius(float cx, float cy, float r);
|
||||
int countNonMembersInRadius(float cx, float cy, float r);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user