--- a/src/Terrain.cc Sun Dec 07 19:59:25 2008 +0000
+++ b/src/Terrain.cc Sun Dec 07 20:07:28 2008 +0000
@@ -1,4 +1,5 @@
#include "Terrain.hh"
+#include "Graphics.hh"
#include "Engine.hh"
#include <cmath>
@@ -6,17 +7,30 @@
#include <algorithm>
#include <ClanLib/display.h>
-Terrain::Terrain() {}
-Terrain::Terrain(const int &seed)
- : terrain(MAP_WIDTH, std::vector<TerrainType>(MAP_HEIGHT, DIRT)){
- this->generateTerrain(seed);
-}
-Terrain::Terrain(const Terrain &t) {
- this->terrain = t.getTerrain();
- this->generatePixelBuffer();
+Terrain::Terrain (void) :
+ map_width(0), map_height(0)
+{
}
-void fractal_step(std::vector<double>& land, int size, double str, int dist) {
+Terrain::Terrain (PixelDimension map_width, PixelDimension map_height, int seed) :
+ map_width(map_width), map_height(map_height), terrain(map_width, std::vector<TerrainType>(map_height, TERRAIN_DIRT))
+{
+ generateTerrain(seed);
+}
+
+Terrain::Terrain (const Terrain &t)
+{
+ map_width = t.map_width;
+ map_height = t.map_height;
+ terrain = t.terrain;
+
+ 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;
@@ -38,7 +52,8 @@
}
}
}
-void fractal_diamond(std::vector<double>& land, int size, double str, int dist) {
+
+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;
@@ -54,7 +69,7 @@
/**
* Algorithm read from http://www.gameprogrammer.com/fractal.html
*/
-void Terrain::generate_texture() {
+void Terrain::generate_texture (void) {
int texturesize = 128;
texture = std::vector<std::vector<int> >(texturesize, std::vector<int>(texturesize));
std::vector<double> land(texture.size()*texture.size());
@@ -85,27 +100,31 @@
* Changes color depending on x and y values
* x and y should be valid coordinates (not outside)
*/
-void Terrain::noisifyPixel(CL_Color& color, int x, int y) {
- int tx = x%texture.size();
- int ty = y%texture[0].size();
+void Terrain::noisifyPixel(CL_Color& color, PixelCoordinate pc) {
+ int tx = pc.x % texture.size();
+ int ty = pc.y % texture[0].size();
int red = color.get_red();
int green = color.get_green();
int blue = color.get_blue();
- red += texture[tx][ty]/8-16;
- green += texture[tx][ty]/8-16;
- blue += texture[tx][ty]/8-16;
- if(red < 0)
+
+ red += texture[tx][ty] / 8 - 16;
+ green += texture[tx][ty] / 8 - 16;
+ blue += texture[tx][ty] / 8 - 16;
+
+ if (red < 0)
red = 0;
- if(red >= 256)
+ else if (red >= 256)
red = 255;
- if(green < 0)
+
+ if (green < 0)
green = 0;
- if(blue >= 256)
+ else if (green >= 256)
+ green = 255;
+
+ if (blue < 0)
+ blue = 0;
+ else if (blue >= 256)
blue = 255;
- if(blue < 0)
- blue = 0;
- if(green >= 256)
- green = 255;
color = CL_Color(red, green, blue);
}
@@ -113,137 +132,156 @@
/**
* Sets to color the correct color of pixel in (x,y)
*/
-void Terrain::loadPixelColor(CL_Color& color, int x, int y) {
- if ((x < 0) || (y < 0) ||(x >= MAP_WIDTH) || (y >= MAP_HEIGHT)) {
+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[x][y]) {
- case EMPTY:
+
+ switch (terrain[pc.x][pc.y]) {
+ case TERRAIN_EMPTY:
color = COLOR_EMPTY;
- noisifyPixel(color, x, y);
break;
- case DIRT:
+
+ case TERRAIN_DIRT:
color = COLOR_DIRT;
- noisifyPixel(color, x, y);
break;
- case ROCK:
+
+ case TERRAIN_ROCK:
color = COLOR_ROCK;
- noisifyPixel(color, x, y);
break;
}
+
+ noisifyPixel(color, pc);
}
-void Terrain::generatePixelBuffer() {
+void Terrain::generatePixelBuffer (void) {
+ // initialze texture
generate_texture();
- this->pixbuf = CL_PixelBuffer(MAP_WIDTH, MAP_HEIGHT, 4*MAP_WIDTH,
- CL_PixelFormat::rgba8888);
+
+ // create pixel buffer
+ pixbuf = CL_PixelBuffer(map_width, map_height, 4 * map_width, CL_PixelFormat::rgba8888);
CL_Color color;
- for (uint16_t i = 0; i < MAP_WIDTH; i++) {
- for (uint16_t j = 0; j < MAP_HEIGHT; j++) {
- switch(terrain[i][j]) {
- case EMPTY:
- color = COLOR_EMPTY;
- break;
- case DIRT:
- color = COLOR_DIRT;
- break;
- case ROCK:
- color = COLOR_ROCK;
- break;
- default: // TODO: Shouldn't be here.
- break;
- }
- loadPixelColor(color, i, j);
- this->pixbuf.draw_pixel(i, j, 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);
}
}
}
-Vector Terrain::getPixelLocation(Vector point) const{
- return Vector(scale(point.x),
- scale(point.y));
-}
-
-uint16_t Terrain::scale(float x) const {
- return (uint16_t)(x/MAP_SCALE);
+PixelCoordinate Terrain::getPixelCoordinate (Vector point) const {
+ return PixelCoordinate(point.x, point.y);
}
-TerrainType Terrain::getType(int32_t x, int32_t y) const {
- if ((x < 0) || (y < 0) ||(x >= MAP_WIDTH) || (y >= MAP_HEIGHT)) {
- return ROCK;
- }
- return terrain[x][y];
-}
-TerrainType Terrain::getType(Vector point) const {
- return getType((int32_t)point.x, (int32_t)point.y);
+PixelCoordinate Terrain::getDimensions (void) const {
+ return PixelCoordinate(map_width, map_height);
}
-bool Terrain::collides(const Vector &point) const {
- return (getType(point) != EMPTY);
+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];
}
-bool Terrain::collides(const Vector &begin, const Vector &end) const {
+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);
+}
+
+bool Terrain::collides (const Vector &point) const {
+ return (getType(point) != TERRAIN_EMPTY);
+}
+
+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.
// We'll use Bresenhams line algorithm to go trough all the
// "pixels" of the line.
- Vector b = getPixelLocation(begin);
- Vector e = getPixelLocation(end);
+ PixelCoordinate b = getPixelCoordinate(begin);
+ PixelCoordinate e = getPixelCoordinate(end);
bool steep = (abs(e.y - b.y) > abs(e.x - b.x)); // k > 1
- if (steep) { // Line is steep -> swap 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
+
+ if (b.x > e.x) {
+ // Line goes down -> make it go up
std::swap(b, e);
}
- uint16_t dx = e.x - b.x;
- uint16_t dy = abs(e.y - b.y);
- int32_t err = dx/2;
- uint16_t ystep;
- uint16_t y = b.y;
+
+ 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;
+ if (b.y < e.y)
+ ystep = 1;
+
+ else
+ ystep = -1;
+
// Go trough the line
- for (uint16_t x = b.x; x <= e.x; x++) {
- if (steep) { // X and Y coordinates must be switched if steep
- if (getType(y,x) != EMPTY) { // Collision!
+ 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!
return true;
}
} else {
- if (getType(x,y) != EMPTY) { // Collision!
+ if (getType(x, y) != TERRAIN_EMPTY) {
+ // Collision!
return true;
}
}
+
err = err - dy;
- if (err < 0) { // Check if we want to make an ystep
+
+ if (err < 0) {
+ // Check if we want to make an ystep
y = y + ystep;
err = err + dx;
}
}
+
return false; // No Collision
}
-void Terrain::removeGround(const Vector &pos, const float &radius) {
+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.
- Vector mid = getPixelLocation(pos);
- uint16_t r = scale(radius);
- for (uint16_t i = mid.x-r; i < mid.x+r; i++) {
- for (uint16_t j = mid.y-r; j < mid.y+r; j++) {
- if (getType(i, j) != ROCK) { // getType returns ROCK if
- // out of bounds
- if ((i-mid.x)*(i-mid.x)+(j-mid.y)*(j-mid.y) < r*r) {
- terrain[i][j] = EMPTY;
- CL_Color color(0, 0, 0);
- loadPixelColor(color, i, j);
- pixbuf.draw_pixel(i, j, color);
+ PixelCoordinate mid = getPixelCoordinate(pos);
+ PixelDimension r = radius;
+
+ 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
+
+ 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);
}
}
}
@@ -254,25 +292,26 @@
* Gets the index of the given coordinate direction
* referring to the DIRECTIONS table in Physics.hh
*/
-int getDirectionIndex (Vector direction) {
+static int getDirectionIndex (Vector direction) {
Vector dir = direction.roundToInt();
if(dir.x == 0 && dir.y == -1) {
return 0;
- } else if(dir.x == 1 && dir.y == -1) {
+ } else if (dir.x == 1 && dir.y == -1) {
return 1;
- } else if(dir.x == 1 && dir.y == 0) {
+ } else if (dir.x == 1 && dir.y == 0) {
return 2;
- } else if(dir.x == 1 && dir.y == 1) {
+ } else if (dir.x == 1 && dir.y == 1) {
return 3;
- } else if(dir.x == 0 && dir.y == 1) {
+ } else if (dir.x == 0 && dir.y == 1) {
return 4;
- } else if(dir.x == -1 && dir.y == 1) {
+ } else if (dir.x == -1 && dir.y == 1) {
return 5;
- } else if(dir.x == -1 && dir.y == 0) {
+ } else if (dir.x == -1 && dir.y == 0) {
return 6;
- } else if(dir.x == -1 && dir.y == -1) {
+ } else if (dir.x == -1 && dir.y == -1) {
return 7;
}
+
Engine::log(DEBUG, "Terrain.getDirectionIndex ") << "invalid direction: " << direction;
return 0;
}
@@ -283,7 +322,7 @@
* @param prevPoint - pixel where we are when we collide
*/
Vector Terrain::getNormal(Vector point, Vector prevPoint) const {
- Vector p = getPixelLocation(point);
+ PixelCoordinate p = getPixelCoordinate(point);
assert(point != prevPoint);
@@ -291,54 +330,44 @@
// These two must be rounded separately
int dirIdx = getDirectionIndex(prevPoint.roundToInt() - point.roundToInt());
-// dirIdx = (dirIdx+4)%8;
normal += DIRECTIONS[dirIdx];
+
for (int i = 1; i <= 2; i++) {
- if(getType(point + DIRECTIONS[(dirIdx+i+8)%8]) == EMPTY) {
+ if (getType(point + DIRECTIONS[(dirIdx+i+8)%8]) == TERRAIN_EMPTY) {
normal += DIRECTIONS[(dirIdx+i+8)%8];
}
}
+
for (int i = 1; i <= 2; i++) {
- if(getType(point + DIRECTIONS[(dirIdx-i+8)%8]) == EMPTY) {
+ if (getType(point + DIRECTIONS[(dirIdx-i+8)%8]) == TERRAIN_EMPTY) {
normal += DIRECTIONS[(dirIdx-i+8)%8];
}
}
- if (getType(point) == EMPTY || getType(prevPoint) != EMPTY) {
+ if (getType(point) == TERRAIN_EMPTY || getType(prevPoint) != TERRAIN_EMPTY) {
Engine::log(DEBUG, "Physics.getNormal ") << "logic ground error";
}
-
-// for (int i = 0; i < 8; i++) {
-// if (getType(p.x+DIRECTIONS[i].x, p.y+DIRECTIONS[i].y) == EMPTY) {
-// normal += DIRECTIONS[i];
-// }
-// }
-
-
- // Special cases
- /* Vector tmp = direction(direction(prevPoint-point) + direction(normal));
- Engine::log(DEBUG, "Terrain.getNormal") << "tmp: " << tmp;
- if (normal.length() == 0 || (tmp.x != 0 && tmp.y != 0 && getType(tmp.x, tmp.y) != EMPTY))
- normal = prevPoint - point; // Direct hit
- */
-// Engine::log(DEBUG, "Terrain.getNormal") << "Normal: " << normal;
return normal;
- return Vector(0,-1);
}
-Vector direction(const Vector &v) {
+// XXX: weird vectors
+Vector direction (const Vector &v) {
Vector tmp(v);
- if (tmp.length() > 0) tmp /= tmp.length();
+
+ if (tmp.length() > 0)
+ tmp /= tmp.length();
+
tmp.x = (uint16_t)(tmp.x);
tmp.y = (uint16_t)(tmp.y);
+
return tmp;
}
// TODO: This could better :)
// TODO: And this need some cleaning :)
-void Terrain::generateTerrain(int seed) {
+void Terrain::generateTerrain (int seed) {
srand(seed); // Set random number generator seed.
// Some constants to control random generation
@@ -350,48 +379,49 @@
// Generate circles (or whatever)
for (int i = 0; i < num; i++) {
// Random generate circle attributes
- int midx = rand()%MAP_WIDTH;
- int midy = rand()%MAP_HEIGHT;
+ 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) {
- midx = MAP_WIDTH/2;
- midy = MAP_WIDTH/2;
+ mid.x = map_width / 2;
+ mid.y = map_height / 2;
range = 150;
}
- TerrainType type = EMPTY;
- if (rand()%rock_rarity == 0) {
- type = ROCK;
+ 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 (int x = std::max(0, midx-range);
- x < std::min((int32_t)MAP_WIDTH, midx+range);
- x++) {
- for (int y = std::max(0, midy-range);
- y < std::min((int32_t)MAP_HEIGHT, midy+range);
- y++) {
-
- //terrain[x][y] = type;
-
- if ((x-midx)*(x-midx)+(y-midy)*(y-midy) < range*range) {
+ 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;
}
}
-
}
-
}
+ // regenerate pixel buffer
this->generatePixelBuffer();
}
-void Terrain::draw(CL_GraphicContext *gc, Vector camera) {
- CL_Surface surf(this->pixbuf);
- surf.draw((int)-camera.x, (int)-camera.y ,gc);
+void Terrain::draw (Graphics *g, PixelCoordinate camera) {
+ CL_Surface surf (pixbuf);
+ surf.draw(-camera.x, -camera.y, g->get_gc());
}
std::vector<std::vector<TerrainType> > Terrain::getTerrain() const {