# HG changeset patch # User terom # Date 1228680448 0 # Node ID 99431fdb0dc8fc02509725e03a6804be4dfc57b2 # Parent 0c3d58912e1b283917fbda206a5129695199daa8 add PixelDimension/PixelCoordinate types, convert Terrain to use them, and convert/clean up drawing code diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Config.hh --- a/src/Config.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Config.hh Sun Dec 07 20:07:28 2008 +0000 @@ -32,6 +32,7 @@ const float PLAYER_AIM_MAX = KG_PI/2; const float PLAYER_INITIAL_X = 400.0; const float PLAYER_INITIAL_Y = 300.0; +const float PLAYER_CROSSHAIR_LENGTH = 10.0; const float CROSSHAIR_ANGLE_SPEED = PI/40; const float PLAYER_MAX_SPEED = 43; diff -r 0c3d58912e1b -r 99431fdb0dc8 src/GameState.cc --- a/src/GameState.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/GameState.cc Sun Dec 07 20:07:28 2008 +0000 @@ -3,7 +3,11 @@ #include "Engine.hh" #include "Config.hh" -GameState::GameState (void) : local_player(NULL), world(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)) { } +GameState::GameState (void) : + local_player(NULL), world(Vector(0, MAP_GRAVITY), Vector(MAP_WIDTH, MAP_HEIGHT)) +{ + +} void GameState::addProjectile (Projectile *projectile) { projectiles.push_back(projectile); @@ -31,9 +35,10 @@ } void GameState::draw(Graphics *g, bool displayWeapon) { - Vector camera = local_player->getPosition()-Vector(800/2, 600/2); + PixelCoordinate camera = world.getPixelCoordinate(local_player->getPosition()) - world.getDimensions() / 2; + // Draw world/terrain - world.draw(g->get_gc(), camera); + world.draw(g, camera); // Draw players for (std::list::iterator it = player_list.begin(); it != player_list.end(); it++) { diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Network/Client.cc --- a/src/Network/Client.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Network/Client.cc Sun Dec 07 20:07:28 2008 +0000 @@ -135,7 +135,7 @@ int flags = pkt.read_uint8(); float aim = pkt.read_float32(); - Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity << ", aim=" << aim << ", [" << flags << "]"; +// Engine::log(INFO, "client_player.on_position") << "obj=" << obj << ", position=" << position << ", velocity=" << velocity << ", aim=" << aim << ", [" << flags << "]"; // just update... updatePhysics(position, velocity, flags & NETWORK_PHYSICS_INAIR, flags & NETWORK_PHYSICS_FACE_RIGHT, aim); diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Network/Server.cc --- a/src/Network/Server.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Network/Server.cc Sun Dec 07 20:07:28 2008 +0000 @@ -174,7 +174,7 @@ // read packet PlayerInput input = pkt.read_uint16(); - Engine::log(INFO, "server_player.on_input") << "player=" << obj << ", old_pos=" << position << ", input=" << input; +// Engine::log(INFO, "server_player.on_input") << "player=" << obj << ", old_pos=" << position << ", input=" << input; // apply input handleInput(input); @@ -220,7 +220,7 @@ pkt.write_uint8(flags); pkt.write_float32(aim); - Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity << " [" << flags << "]"; +// Engine::log(INFO, "server_player.send_position_update") << "obj=" << obj << " -> " << position << "+" << velocity << " [" << flags << "]"; obj.send_all(NETMSG_PLAYER_POSITION, pkt, false); } diff -r 0c3d58912e1b -r 99431fdb0dc8 src/PhysicsObject.hh --- a/src/PhysicsObject.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/PhysicsObject.hh Sun Dec 07 20:07:28 2008 +0000 @@ -162,7 +162,14 @@ * * @return Position vector */ - Vector getPosition(); + Vector getPosition (void); + + /** + * Get current object screen coordinates + * + * @return PixelCoordinate position + */ + PixelCoordinate getCoordinate (void); /** * Get current object velocity. diff -r 0c3d58912e1b -r 99431fdb0dc8 src/PhysicsWorld.cc --- a/src/PhysicsWorld.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/PhysicsWorld.cc Sun Dec 07 20:07:28 2008 +0000 @@ -5,7 +5,7 @@ #include PhysicsWorld::PhysicsWorld (Vector gravity, Vector dimensions) : - Terrain(1337), tick_timer(PHYSICS_TICK_MS), dimensions(dimensions), gravity(gravity) + Terrain(dimensions.x, dimensions.y, 1337), tick_timer(PHYSICS_TICK_MS), dimensions(dimensions), gravity(gravity) { slots.connect(tick_timer.sig_tick(), this, &PhysicsWorld::tick); tick_timer.start(); @@ -20,8 +20,8 @@ } void PhysicsWorld::tick (TimeMS tick_length) { + // tick each object in turn for (std::list::iterator i = objects.begin(); i != objects.end(); i++) { -// Engine::log(DEBUG, "PhysicsWorld.tick") << (*i); (*i)->tick(tick_length); } diff -r 0c3d58912e1b -r 99431fdb0dc8 src/PhysicsWorld.hh --- a/src/PhysicsWorld.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/PhysicsWorld.hh Sun Dec 07 20:07:28 2008 +0000 @@ -33,7 +33,6 @@ // Contains connections between signals and slots CL_SlotContainer slots; - // TODO: Should these be somewhere else? Vector dimensions; Vector gravity; diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Player.cc --- a/src/Player.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Player.cc Sun Dec 07 20:07:28 2008 +0000 @@ -181,12 +181,12 @@ return weapons[selectedWeapon % weapons.size()]; } -void Player::draw (Graphics *g, Vector camera) { +void Player::draw (Graphics *g, PixelCoordinate camera) { CL_GraphicContext *gc = g->get_gc(); - int cx = (int)camera.x, cy = (int)camera.y; - - int aim_img_idx = (int)((1 - (getAim()+KG_PI/2)/KG_PI)*img_num_aim); - int step_img_idx = animation_step%img_num_step; + + // animation indexes + int aim_img_idx = (int)((1 - (getAim() + KG_PI / 2) / KG_PI) * img_num_aim); + int step_img_idx = animation_step % img_num_step; // load skin image if not yet loaded if (!skin_loaded) { @@ -194,46 +194,40 @@ skin_loaded = true; } - // XXX: this logic looks weird - CL_Rectf destination(position.x - img_width/2 -cx, position.y - img_height/2 -cy, position.x + img_width/2 -cx, position.y + img_height/2 -cy); - - if (!getFacing()) { - destination = CL_Rect(position.x + img_width/2 -cx, position.y - img_height/2 -cy, position.x - img_width/2 -cx, position.y + img_height/2 -cy); - } - - skin_surface.draw_subpixel( - CL_Rectf( - step_img_idx * img_width, - aim_img_idx * img_height, - (1 + step_img_idx) * img_width, - (aim_img_idx + 1) * img_height - ), - destination, gc + // calulate where to draw the worm + CL_Rectf destination( + position.x + (getFacing() ? -1 : 1) * img_width / 2 - camera.x, + position.y - img_height / 2 - camera.y, + position.x + (getFacing() ? 1 : -1) * img_width / 2 - camera.x, + position.y + img_height / 2 - camera.y ); - const uint16_t chlen = 10; - int x = position.x -cx; - int y = position.y -cy; + // draw the correct animation frame from the skin + skin_surface.draw_subpixel( + CL_Rectf( + step_img_idx * img_width, + aim_img_idx * img_height, + (1 + step_img_idx) * img_width, + (aim_img_idx + 1) * img_height + ), destination, gc + ); - // draw "crosshair" - if (facingRight) { - gc->draw_line(x + std::cos(aim)*chlen/2, - y - std::sin(aim)*chlen/2, - x + std::cos(aim)*chlen, - y - std::sin(aim)*chlen, - CL_Color::black); - } else { - gc->draw_line(x - std::cos(aim)*chlen/2, - y - std::sin(aim)*chlen/2, - x - std::cos(aim)*chlen, - y - std::sin(aim)*chlen, - CL_Color::black); - } + // draw "crosshair", a half-line from our position to 10px away + Vector crosshair = getDirection() * PLAYER_CROSSHAIR_LENGTH; + PixelCoordinate aim_start = state.world.getPixelCoordinate( + position + crosshair / 2) - camera; + + PixelCoordinate aim_end = state.world.getPixelCoordinate( + position + crosshair) - camera; + + gc->draw_line(aim_start.x, aim_start.y, aim_end.x, aim_end.y, CL_Color::black); + + // draw rope rope.draw(g, camera); } -void LocalPlayer::draw (Graphics *g, bool displayWeapon, Vector camera) { +void LocalPlayer::draw (Graphics *g, bool displayWeapon, PixelCoordinate camera) { // superclass draw Player::draw(g, camera); @@ -241,9 +235,12 @@ if (displayWeapon && getCurrentWeapon()) { const std::string weaponName = getCurrentWeapon()->getName(); + const PixelCoordinate pc = state.world.getPixelCoordinate(position) - camera; + + // XXX: fix magic constants once we know how big the worm is g->getSimpleFont().draw( - position.x - camera.x - g->getSimpleFont().get_width(weaponName) / 2, - position.y - camera.y - 20, + pc.x - g->getSimpleFont().get_width(weaponName) / 2, + pc.y - 20, weaponName, g->get_gc() ); diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Player.hh --- a/src/Player.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Player.hh Sun Dec 07 20:07:28 2008 +0000 @@ -71,7 +71,7 @@ */ static bool skin_loaded; static CL_Surface skin_surface; - virtual void draw (Graphics *g, Vector camera = Vector(0, 0)); + virtual void draw (Graphics *g, PixelCoordinate camera); }; class LocalPlayer : public virtual Player { @@ -97,7 +97,7 @@ /* * As Player, but also draws the current weapon name if displayWeapon */ - virtual void draw (Graphics *g, bool displayWeapon, Vector camera); + virtual void draw (Graphics *g, bool displayWeapon, PixelCoordinate camera); }; class RemotePlayer : public virtual Player { diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Projectile.cc --- a/src/Projectile.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Projectile.cc Sun Dec 07 20:07:28 2008 +0000 @@ -13,7 +13,6 @@ shape[3] = Vector(1, -1); setShape(shape); - target_visible = false; collision_elasticity = 0.9; // = shotType.elasticity state.addProjectile(this); } @@ -43,36 +42,20 @@ PhysicsObject::tick(dt); } -void Projectile::draw(Graphics *g, Vector cam) const { +void Projectile::draw(Graphics *g, PixelCoordinate camera) const { CL_GraphicContext *gc = g->get_gc(); if (visible) { - + PixelCoordinate pos = state.world.getPixelCoordinate(position) - camera; + CL_Quad projectile( - (int)((position).x+1-cam.x), (int)((position).y+1-cam.y), - (int)((position).x-1-cam.x), (int)((position).y+1-cam.y), - (int)((position).x+1-cam.x), (int)((position).y-1-cam.y), - (int)((position).x-1-cam.x), (int)((position).y-1-cam.y) - ); + pos.x + 1, pos.y + 1, + pos.x - 1, pos.y + 1, + pos.x + 1, pos.y - 1, + pos.x - 1, pos.y - 1 + ); gc->fill_quad(projectile, CL_Color::green); - - const uint16_t chlen = 10; - int x = projectile.center().x -cam.x; - int y = projectile.center().y -cam.y; - if (target_visible) { - if (facingRight) { - gc->draw_line(x, y, - x + std::cos(aim)*chlen, - y - std::sin(aim)*chlen, - CL_Color::black); - } else { - gc->draw_line(x, y, - x - std::cos(aim)*chlen, - y - std::sin(aim)*chlen, - CL_Color::black); - } - } } } diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Projectile.hh --- a/src/Projectile.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Projectile.hh Sun Dec 07 20:07:28 2008 +0000 @@ -12,7 +12,6 @@ protected: GameState &state; bool visible; - bool target_visible; float radius; public: @@ -22,7 +21,7 @@ Projectile (GameState &state, Vector position, Vector velocity, bool visible, float radius, TickCount age=1000000000); virtual ~Projectile (void); - virtual void draw (Graphics *g, Vector camera = Vector(0, 0)) const; + virtual void draw (Graphics *g, PixelCoordinate camera) const; protected: /** diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Rope.cc --- a/src/Rope.cc Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Rope.cc Sun Dec 07 20:07:28 2008 +0000 @@ -120,13 +120,16 @@ return 0; } -void Rope::draw (Graphics *g, Vector cam) const { +void Rope::draw (Graphics *g, PixelCoordinate camera) { if (state == ROPE_FOLDED) return; + PixelCoordinate player_pos = world.getPixelCoordinate(player.getPosition()) - camera; + PixelCoordinate self_pos = world.getPixelCoordinate(getPosition()) - camera; + g->get_gc()->draw_line( - player.getPosition().x-cam.x, player.getPosition().y-cam.y, - position.x-cam.x, position.y-cam.y, + player_pos.x, player_pos.y, + self_pos.x, self_pos.y, CL_Color::black ); } diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Rope.hh --- a/src/Rope.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Rope.hh Sun Dec 07 20:07:28 2008 +0000 @@ -77,7 +77,7 @@ /* * Just draws it */ - virtual void draw (Graphics *c, Vector camera = Vector(0, 0)) const; + virtual void draw (Graphics *c, PixelCoordinate camera); }; #endif diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Terrain.cc --- 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 @@ -6,17 +7,30 @@ #include #include -Terrain::Terrain() {} -Terrain::Terrain(const int &seed) - : terrain(MAP_WIDTH, std::vector(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& 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(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& 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& land, int size, double str, int dist) { + +static void fractal_diamond(std::vector& 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 >(texturesize, std::vector(texturesize)); std::vector 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 > Terrain::getTerrain() const { diff -r 0c3d58912e1b -r 99431fdb0dc8 src/Terrain.hh --- a/src/Terrain.hh Sun Dec 07 19:59:25 2008 +0000 +++ b/src/Terrain.hh Sun Dec 07 20:07:28 2008 +0000 @@ -4,9 +4,14 @@ #include #include "Vector.hh" +#include "GraphicsPointer.hh" #include "Config.hh" -enum TerrainType {EMPTY, DIRT, ROCK}; +enum TerrainType { + TERRAIN_EMPTY, + TERRAIN_DIRT, + TERRAIN_ROCK +}; const Vector DIRECTIONS[] = { Vector(0,-1), @@ -19,6 +24,9 @@ Vector(-1,-1) }; +typedef long int PixelDimension; +typedef _Vector PixelCoordinate; + /** * Terrain class. Represents game terrain and contains member * functions to manipulate terrain and get info about it. @@ -30,31 +38,57 @@ * and it uses pixelcoordinates internally. */ class Terrain { - public: // XXX: until we fix Network's access to this - std::vector > terrain; - +public: // XXX: until we fix Network's access to this + std::vector > terrain; + /** * Generates pixelbuffer from terrain. Should be used only on * constructors because this is expected to be slow. */ void generatePixelBuffer(); -private: - // Terrain graphic +protected: + // terrain dimensions + PixelDimension map_width, map_height; + + // We can pre-render the terrain as a pixel buffer and then just modify this CL_PixelBuffer pixbuf; + + // terrain texture std::vector > texture; - void generate_texture(); - - void noisifyPixel(CL_Color& col, int x, int y); + /** + * 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); /** - * Get pixel location of a point that is in "real" units. + * Constructor. * - * @param point Point in "real" units - * @return Int vector + * @param scale The "real" width and height of the terrain. + * @param seed Random number generator seed used to create the + * terrain. */ - Vector getPixelLocation(Vector point) const; + Terrain (PixelDimension map_width, PixelDimension map_height, int seed); + + /** + * Copy constructor. + * + * @param t Terrain to be copied. + */ + Terrain (const Terrain &t); + + /** + * Destructor + */ + ~Terrain (void) {} + +protected: + void generate_texture(); + void noisifyPixel(CL_Color& col, PixelCoordinate pc); + /** * Scale parameter to "pixels" @@ -62,16 +96,27 @@ * @param x Scaled value * @return Corresponding value in pixels */ - uint16_t scale(float x) const; + PixelDimension scale (float x) const; /** * Sets to color the correct color of pixel in (x,y) */ - void loadPixelColor(CL_Color& color, int x, int y); + void loadPixelColor (CL_Color& color, PixelCoordinate pc); public: + /** + * Get pixel location of a point that is in "real" units. + * + * @param point Point in "real" units + * @return Int vector + */ + PixelCoordinate getPixelCoordinate (Vector point) const; - // TODO: This should be private. + /** + * Return the terrain dimensions à la a PixelCoordinate + */ + PixelCoordinate getDimensions (void) const; + /** * Return the type of terrain at given position. Returns ROCK if * given point is not inside terrain area. @@ -80,48 +125,23 @@ * @param y Y coordinate * @return Terrain type */ - TerrainType getType(int32_t x, int32_t y) const; - //point is just rounded and redirected to that above - TerrainType getType(Vector point) const; - - /** - * Constructor. - * - * @param scale The "real" width and height of the terrain. - */ - Terrain(); - /** - * Constructor. - * - * @param scale The "real" width and height of the terrain. - * @param seed Random number generator seed used to create the - * terrain. - */ - Terrain(const int &seed); - /** - * Copy constructor. - * - * @param t Terrain to be copied. - */ - Terrain(const Terrain &t); - /** - * Destructor - */ - ~Terrain() {} + TerrainType getType (PixelDimension px, PixelDimension py) const; + TerrainType getType (PixelCoordinate pc) const; + TerrainType getType (Vector point) const; /** * Check if given point has some terrain. * * @param point Point that is in scaled units. */ - bool collides(const Vector &point) const; + bool collides (const Vector &point) const; /** * Check if given line collides with terrain. * * @param begin Line begin point in scaled units. * @param end Line end point in scaled units. */ - bool collides(const Vector &begin, const Vector &end) const; + bool collides (const Vector &begin, const Vector &end) const; /** * Remove a circular area from terrain. @@ -129,7 +149,7 @@ * @param pos Circle center * @param r Circle radius */ - void removeGround(const Vector &pos, const float &r); + void removeGround (const Vector &pos, float r); /** * Return normal for the given point. @@ -137,14 +157,14 @@ * @param point Point for which the normal is calculated. * @return Normal vector ((0,0) if there's no terrain) */ - Vector getNormal(Vector point, Vector prevPoint) const; + Vector getNormal (Vector point, Vector prevPoint) const; /** * Generate random terrain. * * @param seed Seed for the randomnumber generator. */ - void generateTerrain(int seed); + void generateTerrain (int seed); /** * Draw the terrain for given graphicscontext. @@ -152,7 +172,7 @@ * @param gc CL_GraphicContext * @param camera - upper left corner of screen */ - virtual void draw(CL_GraphicContext *gc, Vector camera = Vector(0, 0)); + virtual void draw (Graphics *g, PixelCoordinate camera = PixelCoordinate(0, 0)); /** * Draw part of the terrain for given graphiscontext. @@ -168,7 +188,8 @@ * * @param terrain Terrain. */ - void setTerrain(const std::vector > &terrain); + void setTerrain (const std::vector > &terrain); + /** * Get terrain. * @@ -177,6 +198,6 @@ std::vector > getTerrain() const; }; -Vector direction(const Vector &v); +Vector direction (const Vector &v); #endif