--- a/src/Terrain.cc Sat Jan 17 02:58:36 2009 +0200
+++ b/src/Terrain.cc Tue Jan 20 22:00:24 2009 +0200
@@ -19,205 +19,251 @@
};
Terrain::Terrain (void) :
- map_width(0), map_height(0)
+ terrain_buf(NULL), width(0), height(0)
{
}
-Terrain::Terrain (PixelDimension map_width, PixelDimension map_height, int seed) :
- terrain(map_width, std::vector<TerrainType>(map_height, TERRAIN_DIRT)),
- map_width(map_width),
- map_height(map_height)
+Terrain::Terrain (PixelDimension width, PixelDimension height, int seed) :
+ terrain_buf(NULL),
+ width(width),
+ height(height)
{
+ // allocate+generate random terrain
generateTerrain(seed);
}
-Terrain::Terrain (const Terrain &t)
-{
- map_width = t.map_width;
- map_height = t.map_height;
- terrain = t.terrain;
+Terrain::~Terrain (void) {
+ // free terrain data
+ delete[] terrain_buf;
+}
+void Terrain::generateTerrain (int seed) {
+ // shouldn't be generated yet
+ assert(!terrain_buf);
+
+ // set random number generator seed.
+ srand(seed);
+
+ // allocate terrain buffer
+ terrain_buf = new TerrainPixel[width * height];
+
+ // fill with dirt
+ memset(terrain_buf, TERRAIN_DIRT, width * height);
+
+ // some constants to control random generation
+ const int min_range = 25;
+ const int max_range = 80;
+ const int num = 50;
+ const int rock_rarity = 4;
+
+ // generate \a num random circles
+ for (int i = 0; i < num; i++) {
+ // circle origin
+ PixelCoordinate mid (rand() % width, rand() % height);
+
+ // radius
+ int range = rand() % (max_range - min_range) + min_range;
+
+ // circle type
+ TerrainType type = TERRAIN_EMPTY;
+
+ // tweak to make sure that there's a circle in the midle of the cave
+ if (i == 0) {
+ mid.x = width / 2;
+ mid.y = height / 2;
+ range = 150;
+
+ } else if (rand() % rock_rarity == 0) {
+ // some rock
+ type = TERRAIN_ROCK;
+ }
+
+ // iterate over the area of the circle
+ for (
+ PixelDimension y = std::max((PixelDimension) 0, mid.y - range);
+ y < std::min(height, mid.y + range);
+ y++
+ ) {
+ for (
+ PixelDimension x = std::max((PixelDimension) 0, mid.x - range);
+ x < std::min(width, mid.x + range);
+ x++
+ ) {
+ // inside radius?
+ if ((x - mid.x) * (x - mid.x) + (y - mid.y) * (y - mid.y) < range * range)
+ terrain_buf[y * width + x] = (TerrainPixel) type;
+ }
+ }
+ }
+
+ // update pixel buffer
generatePixelBuffer();
}
-/*
- * Texture generation util functions
- */
-static void fractal_step(std::vector<double>& land, int size, double str, int dist) {
- for(int i = 0; i < size; i += dist*2) {
- for(int j = dist; j < size; j += dist*2) {
- double sum = 0;
- sum += land[((i+size-dist)%size)+(j*size)];
- sum += land[i+((j+size-dist)%size)*size];
- sum += land[((i+dist)%size)+j*size];
- sum += land[i+((j+dist)%size)*size];
- land[i+j*size] = sum/4 + (rand()%10000-5000)*str;
- }
- }
- for(int i = dist; i < size; i += dist*2) {
- for(int j = 0; j < size; j += dist*2) {
- double sum = 0;
- sum += land[((i+size-dist)%size)+(j*size)];
- sum += land[i+((j+size-dist)%size)*size];
- sum += land[((i+dist)%size)+j*size];
- sum += land[i+((j+dist)%size)*size];
- land[i+j*size] = sum/4 + (rand()%10000-5000)*str;
+void Terrain::generatePixelBuffer (void) {
+ // initialize textures
+ generateTexture();
+
+ // create the pixel buffer of the correct size
+ pixbuf = CL_PixelBuffer(width, height, 4 * width, CL_PixelFormat::rgba8888);
+
+ // iterate over each pixel
+ for (PixelDimension x = 0; x < width; x++) {
+ for (PixelDimension y = 0; y < height; y++) {
+ // draw textureized pixel color
+ pixbuf.draw_pixel(x, y, getTexturePixel(x, y));
}
}
}
-static void fractal_diamond(std::vector<double>& land, int size, double str, int dist) {
- for(int i = dist; i < size; i += dist*2) {
- for(int j = dist; j < size; j += dist*2) {
+/*
+ * Texture generation utility functions
+ */
+static void fractal_step (std::vector<double>& land, int size, double str, int dist) {
+ for (int i = 0; i < size; i += dist * 2) {
+ for (int j = dist; j < size; j += dist * 2) {
double sum = 0;
- sum += land[((i+size-dist)%size)+(((j+size-dist)%size)*size)];
- sum += land[((i+dist)%size)+((j+size-dist)%size)*size];
- sum += land[(i+size-dist)%size+((j+dist)%size)*size];
- sum += land[(i+dist)%size+((j+dist)%size)*size];
- land[i+j*size] = sum/4 + (rand()%10000-5000)*str;
+ sum += land[(i + size - dist) % size + j * size];
+ sum += land[i + ((j + size - dist) % size) * size];
+ sum += land[(i + dist) % size + j * size];
+ sum += land[i + ((j + dist) % size) * size];
+ land[i + j * size] = sum / 4 + (rand() % 10000 - 5000) * str;
+ }
+ }
+ for (int i = dist; i < size; i += dist * 2) {
+ for (int j = 0; j < size; j += dist * 2) {
+ double sum = 0;
+ sum += land[(i + size - dist) % size + j * size];
+ sum += land[i + ((j + size - dist) % size) * size];
+ sum += land[(i + dist) % size + j * size];
+ sum += land[i + ((j + dist) % size) * size];
+ land[i + j * size] = sum / 4 + (rand() % 10000 - 5000) * str;
}
}
}
-void Terrain::generate_texture (void) {
+static void fractal_diamond (std::vector<double>& land, int size, double str, int dist) {
+ for (int i = dist; i < size; i += dist*2) {
+ for (int j = dist; j < size; j += dist*2) {
+ double sum = 0;
+ sum += land[(i + size - dist) % size + ((j + size - dist) % size) * size];
+ sum += land[(i + dist) % size + ((j + size - dist) % size) * size];
+ sum += land[(i + size - dist) % size + ((j + dist) % size) * size];
+ sum += land[(i + dist) % size + ((j + dist) % size) * size];
+ land[i + j * size] = sum / 4 + (rand() % 10000 - 5000) * str;
+ }
+ }
+}
+
+void Terrain::generateTexture (void) {
+ // texture is a 128x128 px pattern
int texturesize = 128;
+
+ // store the generated texture
texture = std::vector<std::vector<int> >(texturesize, std::vector<int>(texturesize));
- std::vector<double> land(texture.size()*texture.size());
+
+ // generate texture into this
+ std::vector<double> land(texture.size() * texture.size());
+
+ // XXX: magic constants with unintelligble names
double str = 0.8;
double H = 0.8;
- for(int i = 512; i >= 1; i /= 2) {
+
+ // do some magic
+ for (int i = 512; i >= 1; i /= 2) {
fractal_diamond(land, texturesize, str, i);
fractal_step(land, texturesize, str, i);
str *= H;
}
+
double min = 100000;
double max = -100000;
- for(int i = 0; i < texturesize*texturesize; i++) {
- if(land[i] < min) min = land[i];
- if(land[i] > max) max = land[i];
+
+ // find the range of minimum and maximum values
+ for (int i = 0; i < texturesize * texturesize; i++) {
+ if (land[i] < min) min = land[i];
+ if (land[i] > max) max = land[i];
}
+
+ // normalize min down to zero
max -= min;
- for(int i = 0; i < texturesize*texturesize; i++) {
+
+ // normalize values to [0, max]
+ for (int i = 0; i < texturesize * texturesize; i++) {
land[i] -= min;
}
- for(int i = 0; i < texturesize*texturesize; i++) {
- land[i] = land[i]*255/max;
- texture[i%texturesize][i/texturesize] = (int)(land[i]);
+
+ // copy+mangle land to texture as integers
+ for (int i = 0; i < texturesize * texturesize; i++) {
+ land[i] = land[i] * 255 / max;
+ texture[i % texturesize][i / texturesize] = (int) land[i];
}
}
-/**
- * Changes color depending on x and y values
- * x and y should be valid coordinates (not outside)
- */
-void Terrain::noisifyPixel(CL_Color& color, PixelCoordinate pc) {
+static int normalizeRange (int min, int val, int max) {
+ if (val < min)
+ return min;
+
+ else if (val > max)
+ return max;
+
+ else
+ return val;
+}
+
+CL_Color Terrain::getTexturePixel (PixelDimension x, PixelDimension y) {
+ CL_Color color;
int texture_fade = 8;
- switch (terrain[pc.x][pc.y]) {
- case TERRAIN_EMPTY:
- break;
- case TERRAIN_DIRT:
- texture_fade = 4;
- break;
- case TERRAIN_ROCK:
- texture_fade = 2;
- break;
+
+ // determine fade constant
+ switch (getType(x, y)) {
+ case TERRAIN_EMPTY:
+ color = COLOR_EMPTY;
+ break;
+
+ case TERRAIN_DIRT:
+ color = COLOR_DIRT;
+ texture_fade = 4;
+ break;
+
+ case TERRAIN_ROCK:
+ color = COLOR_ROCK;
+ texture_fade = 2;
+ break;
}
- int tx = (pc.x + texture_fade * 37) % texture.size();
- int ty = (pc.y + texture_fade * 37) % texture[0].size();
+
+ // calculate texture coordinate
+ int tx = (x + texture_fade * 37) % texture.size();
+ int ty = (y + texture_fade * 37) % texture[0].size();
+
+ // get color components
int red = color.get_red();
int green = color.get_green();
int blue = color.get_blue();
-
+
+ // apply noise from texture
red += (texture[tx][ty] - 128) / texture_fade;
green += (texture[tx][ty] - 128) / texture_fade;
blue += (texture[tx][ty] - 128) / texture_fade;
-
- if (red < 0)
- red = 0;
- else if (red >= 256)
- red = 255;
-
- if (green < 0)
- green = 0;
- else if (green >= 256)
- green = 255;
-
- if (blue < 0)
- blue = 0;
- else if (blue >= 256)
- blue = 255;
-
- color = CL_Color(red, green, blue);
+
+ // normalize colors to within range and return new color
+ return CL_Color(
+ normalizeRange(0, red, 255),
+ normalizeRange(0, green, 255),
+ normalizeRange(0, blue, 255)
+ );
}
-/**
- * Sets to color the correct color of pixel in (x,y)
- */
-void Terrain::loadPixelColor(CL_Color& color, PixelCoordinate pc) {
- if ((pc.x < 0) || (pc.y < 0) || (pc.x >= map_width) || (pc.y >= map_height)) {
- color = CL_Color(0, 0, 0);
- return;
- }
-
- switch (terrain[pc.x][pc.y]) {
- case TERRAIN_EMPTY:
- color = COLOR_EMPTY;
- break;
-
- case TERRAIN_DIRT:
- color = COLOR_DIRT;
- break;
-
- case TERRAIN_ROCK:
- color = COLOR_ROCK;
- break;
- }
-
- noisifyPixel(color, pc);
+const TerrainPixel* Terrain::getTerrainBuffer (void) const {
+ return terrain_buf;
}
-
-void Terrain::generatePixelBuffer (void) {
- // initialze texture
- generate_texture();
-
- // create pixel buffer
- pixbuf = CL_PixelBuffer(map_width, map_height, 4 * map_width, CL_PixelFormat::rgba8888);
+
+void Terrain::loadFromBuffer (const TerrainPixel *buf) {
+ // copy bytes
+ memcpy(terrain_buf, buf, width * height);
- CL_Color color;
-
- for (PixelDimension x = 0; x < map_width; x++) {
- for (PixelDimension y = 0; y < map_height; y++) {
- PixelCoordinate pc(x, y);
-
- loadPixelColor(color, pc);
-
- pixbuf.draw_pixel(pc.x, pc.y, color);
- }
- }
-}
-
-PixelCoordinate Terrain::getPixelCoordinate (Vector point) const {
- // XXX: assume 1:1
- return PixelCoordinate((int) point.x, (int) point.y);
-}
-
-PixelCoordinate Terrain::getDimensions (void) const {
- return PixelCoordinate(map_width, map_height);
-}
-
-TerrainType Terrain::getType (PixelDimension px, PixelDimension py) const {
- if ((px < 0) || (py < 0) ||(px >= map_width) || (py >= map_height))
- return TERRAIN_ROCK;
-
- return terrain[px][py];
-}
-
-TerrainType Terrain::getType (PixelCoordinate pc) const {
- return getType(pc.x, pc.y);
-}
-
-TerrainType Terrain::getType (Vector point) const {
- return getType((PixelDimension) point.x, (PixelDimension) point.y);
+ // regenerate pixbuf
+ generatePixelBuffer();
}
bool Terrain::collides (const Vector &point) const {
@@ -225,85 +271,74 @@
}
bool Terrain::collides (const Vector &begin, const Vector &end) const {
- // TODO: Maybe we should have another function prototype that also
- // returns the point where we collided.
+ // TODO: Maybe there should be another function that also returns the point where we collided.
- // We'll use Bresenhams line algorithm to go trough all the
- // "pixels" of the line.
+ // use Bresenhams line algorithm to go trough all the "pixels" of the line.
PixelCoordinate b = getPixelCoordinate(begin);
PixelCoordinate e = getPixelCoordinate(end);
+ // steepness of line (large angle against horizontal)
bool steep = (abs(e.y - b.y) > abs(e.x - b.x)); // k > 1
-
+
+ // if the line is steep, swap the x and y coordinates
if (steep) {
- // Line is steep -> swap x and y coordinates
std::swap(b.x, b.y);
std::swap(e.x, e.y);
}
-
- if (b.x > e.x) {
- // Line goes down -> make it go up
+
+ // normalize so that the line goes upwards
+ if (b.x > e.x)
std::swap(b, e);
- }
-
+
+ // line length
PixelDimension dx = e.x - b.x, dy = abs(e.y - b.y);
PixelDimension err = dx / 2;
- PixelDimension ystep, y = b.y;
-
- // Is the line ascending or descending
- if (b.y < e.y)
- ystep = 1;
-
- else
- ystep = -1;
+ PixelDimension y = b.y;
+
+ // ascending or descending line?
+ PixelDimension ystep = b.y < e.y ? 1 : -1;
- // Go trough the line
- for (PixelDimension x = b.x; x <= e.x; x++) {
+ // iterate through the pixels on the line
+ for (PixelDimension x = b.x; x <= e.x; x++) {
if (steep) {
- // X and Y coordinates must be switched if steep
- if (getType(y, x) != TERRAIN_EMPTY) {
- // Collision!
+ // x and y coordinates must be switched if steep
+ if (getType(y, x) != TERRAIN_EMPTY)
return true;
- }
+
} else {
- if (getType(x, y) != TERRAIN_EMPTY) {
- // Collision!
+ if (getType(x, y) != TERRAIN_EMPTY)
return true;
- }
+
}
err = err - dy;
if (err < 0) {
- // Check if we want to make an ystep
+ // check if we want to make an ystep
y = y + ystep;
err = err + dx;
}
}
- return false; // No Collision
+ // no collision
+ return false;
}
void Terrain::removeGround (const Vector &pos, float radius) {
- // TODO: Implement. Some circle algoritmh should be usefull here,
- // though the current impelementation doesn't seem too bad either.
-
+ // scale arguments to pixel units
PixelCoordinate mid = getPixelCoordinate(pos);
- PixelDimension r = (unsigned int) radius; // XXX: scale
+ PixelDimension r = scale(radius);
+
+ // iterate through the circle's pixels
+ for (PixelDimension j = mid.y - r; j < mid.y + r; j++) {
+ for (PixelDimension i = mid.x - r; i < mid.x + r; i++) {
+ // getType also returns TERRAIN_ROCK if out-of-bounds
+ if (getType(i, j) != TERRAIN_ROCK) {
- for (PixelDimension i = mid.x - r; i < mid.x + r; i++) {
- for (PixelDimension j = mid.y-r; j < mid.y+r; j++) {
- PixelCoordinate pc(i, j);
-
- if (getType(pc) != TERRAIN_ROCK) {
- // getType returns ROCK if out of bounds
-
+ // within radius?
if ((i - mid.x) * (i - mid.x) + (j - mid.y) * (j - mid.y) < r * r) {
- terrain[i][j] = TERRAIN_EMPTY;
-
- CL_Color color;
- loadPixelColor(color, pc);
- pixbuf.draw_pixel(pc.x, pc.y, color);
+ // update terrain buf
+ setType(i, j, TERRAIN_EMPTY);
}
}
}
@@ -339,12 +374,8 @@
return 0;
}
-/**
- * point should be ground and prevPoint air, but it's easy to assure that
- * @param point - pixel on ground to which was collided
- * @param prevPoint - pixel where we are when we collide
- */
Vector Terrain::getNormal(Vector point, Vector prevPoint) const {
+ // XXX: cleanup
PixelCoordinate p = getPixelCoordinate(point);
assert(point != prevPoint);
@@ -375,66 +406,13 @@
return normal;
}
-// TODO: This could better :)
-// TODO: And this need some cleaning :)
-void Terrain::generateTerrain (int seed) {
- srand(seed); // Set random number generator seed.
-
- // Some constants to control random generation
- const int min_range = 25;
- const int max_range = 80;
- const int num = 50;
- const int rock_rarity = 4;
-
- // Generate circles (or whatever)
- for (int i = 0; i < num; i++) {
- // Random generate circle attributes
- PixelCoordinate mid(rand() % map_width, rand() % map_width);
-
- int range = rand()%(max_range-min_range)+min_range;
-
- // Make sure that there's a circle in the midle of the cave
- if (i == 0) {
- mid.x = map_width / 2;
- mid.y = map_height / 2;
- range = 150;
- }
-
- TerrainType type = TERRAIN_EMPTY;
-
- if (rand() % rock_rarity == 0) {
- type = TERRAIN_ROCK;
- }
-
- // Loops for every pixel of the cirlcle (or square as it seems
- // now)
- for (
- PixelDimension x = std::max((PixelDimension) 0, mid.x - range);
- x < std::min(map_width, mid.x + range);
- x++
- ) {
- for (
- PixelDimension y = std::max((PixelDimension) 0, mid.y - range);
- y < std::min(map_height, mid.y + range);
- y++
- ) {
- if ((x - mid.x) * (x - mid.x) + (y - mid.y) * (y - mid.y) < range * range) {
- terrain[x][y] = type;
- }
- }
- }
- }
+void Terrain::draw (Graphics *g, PixelCoordinate camera) {
+ // XXX: can we optimize this somehow?
- // regenerate pixel buffer
- this->generatePixelBuffer();
-}
-
-void Terrain::draw (Graphics *g, PixelCoordinate camera) {
+ // load the terrain pixbuf as a surface
CL_Surface surf (pixbuf);
+
+ // draw it onto the graphics, offset by camera position
surf.draw(-camera.x, -camera.y, g->get_gc());
}
-std::vector<std::vector<TerrainType> > Terrain::getTerrain() const {
- return terrain;
-}
-
--- a/src/Terrain.hh Sat Jan 17 02:58:36 2009 +0200
+++ b/src/Terrain.hh Tue Jan 20 22:00:24 2009 +0200
@@ -8,13 +8,26 @@
#include "Types.hh"
#include "Config.hh"
+/**
+ * Different types of terrain available
+ */
enum TerrainType {
- TERRAIN_EMPTY,
- TERRAIN_DIRT,
- TERRAIN_ROCK
+ /** Empty space, air */
+ TERRAIN_EMPTY = 0x00,
+
+ /** Dirt, which can be destroyed/dug through */
+ TERRAIN_DIRT = 0x01,
+
+ /** Indestructible rock */
+ TERRAIN_ROCK = 0x02
};
/**
+ * Terrain "pixel" type
+ */
+typedef uint8_t TerrainPixel;
+
+/**
* Terrain class. Represents game terrain and contains member
* functions to manipulate terrain and get info about it.
*
@@ -25,57 +38,78 @@
* and it uses pixelcoordinates internally.
*/
class Terrain {
-public: // XXX: until we fix Network's access to this
- std::vector<std::vector<TerrainType> > terrain;
+protected:
+ /** The terrain data is stored as a linear array in row-major order, with width*height elements */
+ TerrainPixel *terrain_buf;
+
+ /** Terrain dimensions */
+ PixelDimension width, height;
- /**
- * Generates pixelbuffer from terrain. Should be used only on
- * constructors because this is expected to be slow.
- */
- void generatePixelBuffer();
-
-protected:
- // terrain dimensions
- PixelDimension map_width, map_height;
-
- // We can pre-render the terrain as a pixel buffer and then just modify this
+ /** We pre-render the textured terrain data for display */
CL_PixelBuffer pixbuf;
- // terrain texture
+ // XXX: terrain texture
std::vector<std::vector<int> > texture;
/**
* Default constructor. The width/height are set to zero and the terrain is invalid until it gets updated
- *
- * @param scale The "real" width and height of the terrain.
*/
Terrain (void);
/**
* Constructor.
*
- * @param scale The "real" width and height of the terrain.
- * @param seed Random number generator seed used to create the
- * terrain.
+ * @param width terrain width
+ * @param height terrain height
+ * @param seed andom number generator seed used to generate the random terrain.
*/
- Terrain (PixelDimension map_width, PixelDimension map_height, int seed);
-
- /**
- * Copy constructor.
- *
- * @param t Terrain to be copied.
- */
- Terrain (const Terrain &t);
+ Terrain (PixelDimension width, PixelDimension height, int seed);
/**
* Destructor
*/
- ~Terrain (void) {}
+ ~Terrain (void);
+
+private:
+ /* No copying */
+ Terrain (const Terrain ©);
+ Terrain &operator= (const Terrain ©);
protected:
- void generate_texture();
- void noisifyPixel(CL_Color& col, PixelCoordinate pc);
+ /**
+ * Set induvidual pixel value, updates both terrain_buf and pixbuf
+ */
+ inline void setType (PixelDimension x, PixelDimension y, TerrainType t) {
+ terrain_buf[y * width + x] = (TerrainPixel) t;
+ // XXX: locking?
+ pixbuf.draw_pixel(x, y, getTexturePixel(x, y));
+ }
+
+ /**
+ * Generate random terrain using given seed
+ *
+ * @param seed seed for the random number generator
+ */
+ void generateTerrain (int seed);
+
+ /**
+ * Regenerates our pixbuf from the current terrain. This is a slow process, but using the pixbuffer directly
+ * greatly speeds up drawing.
+ */
+ void generatePixelBuffer (void);
+
+ /**
+ * Generates an area of random texture using a fractal-based algorithm, this can then be applied to the terrain
+ * pixels using noisifyPixel
+ */
+ void generateTexture();
+
+ /**
+ * Applies noise generated using generateTexture to generate a slightly varying color for the terrain pixel
+ * at \a pc.
+ */
+ CL_Color getTexturePixel (PixelDimension x, PixelDimension y);
/**
* Scale parameter to "pixels"
@@ -83,12 +117,9 @@
* @param x Scaled value
* @return Corresponding value in pixels
*/
- PixelDimension scale (float x) const;
-
- /**
- * Sets to color the correct color of pixel in (x,y)
- */
- void loadPixelColor (CL_Color& color, PixelCoordinate pc);
+ inline PixelDimension scale (float x) const {
+ return (int) x;
+ }
public:
/**
@@ -97,92 +128,94 @@
* @param point Point in "real" units
* @return Int vector
*/
- PixelCoordinate getPixelCoordinate (Vector point) const;
+ inline PixelCoordinate getPixelCoordinate (Vector point) const {
+ return PixelCoordinate(scale(point.x), scale(point.y));
+ }
/**
* Return the terrain dimensions à la a PixelCoordinate
*/
- PixelCoordinate getDimensions (void) const;
+ inline PixelCoordinate getDimensions (void) const {
+ return PixelCoordinate(width, height);
+ }
/**
- * Return the type of terrain at given position. Returns ROCK if
- * given point is not inside terrain area.
+ * Return the type of terrain at given position. Returns TERRAIN_ROCK if given point is not inside terrain area.
*
- * @param x X coordinate
- * @param y Y coordinate
- * @return Terrain type
+ * @param x terrain x coordinate
+ * @param y terrain x coordinate
+ * @return terrain pixel type
*/
- TerrainType getType (PixelDimension px, PixelDimension py) const;
- TerrainType getType (PixelCoordinate pc) const;
- TerrainType getType (Vector point) const;
+ TerrainType getType (PixelDimension x, PixelDimension y) const {
+ // XXX: optimize access by removing error checking?
+ if (x < 0 || y < 0 || x >= width || y >= height)
+ return TERRAIN_ROCK;
+
+ return (TerrainType) terrain_buf[y * width + x];
+ }
+
+ inline TerrainType getType (PixelCoordinate pc) const {
+ return getType(pc.x, pc.y);
+ }
+
+
+ inline TerrainType getType (Vector point) const {
+ return getType(getPixelCoordinate(point));
+ }
/**
- * Check if given point has some terrain.
+ * Get raw read-only terrain data buffer
*
- * @param point Point that is in scaled units.
+ * @see terrain_buf
+ */
+ const TerrainPixel* getTerrainBuffer (void) const;
+
+ /**
+ * Load new terrain data from given buffer. Must be the right size
+ *
+ * @see terrain_buf
+ */
+ void loadFromBuffer (const TerrainPixel *buf);
+
+ /**
+ * Check if the given point is terrain
*/
bool collides (const Vector &point) const;
+
/**
- * Check if given line collides with terrain.
+ * Check if the given line collides with terrain
*
- * @param begin Line begin point in scaled units.
- * @param end Line end point in scaled units.
+ * @param begin line starting point
+ * @param end line ending point
*/
bool collides (const Vector &begin, const Vector &end) const;
/**
- * Remove a circular area from terrain.
+ * Remove a circular area of terrain
*
- * @param pos Circle center
- * @param r Circle radius
+ * @param pos circle center
+ * @param r circle radius
*/
void removeGround (const Vector &pos, float r);
/**
- * Return normal for the given point.
+ * Returns direction normal vector for the given \a point.
*
- * @param point Point for which the normal is calculated.
- * @return Normal vector ((0,0) if there's no terrain)
+ * \a point should be ground, and \a prevPoint air.
+ *
+ * @param point the ground that we collided into
+ * @param prevPoint position in air where we were before the collision
+ * @return direction ormal vector, or (0,0) if there's no terrain
*/
Vector getNormal (Vector point, Vector prevPoint) const;
/**
- * Generate random terrain.
+ * Draw the terrain onto the given graphics context
*
- * @param seed Seed for the randomnumber generator.
- */
- void generateTerrain (int seed);
-
- /**
- * Draw the terrain for given graphicscontext.
- *
- * @param gc CL_GraphicContext
- * @param camera - upper left corner of screen
+ * @param gc Graphics to draw on
+ * @param camera view position
*/
virtual void draw (Graphics *g, PixelCoordinate camera = PixelCoordinate(0, 0));
-
- /**
- * Draw part of the terrain for given graphiscontext.
- *
- * @param gc CL_GraphicContext
- * @param center Center of the rectangle drawn.
- * @param dimension Dimensions of the rectangle.
- */
- //void draw(CL_GraphicContext &gc, Vector center, Vector dimensions);
-
- /**
- * Set terrain.
- *
- * @param terrain Terrain.
- */
- void setTerrain (const std::vector<std::vector<TerrainType> > &terrain);
-
- /**
- * Get terrain.
- *
- * @return Terrain.
- */
- std::vector<std::vector<TerrainType> > getTerrain() const;
};
#endif