From: Matthias Braun Date: Thu, 10 Aug 2006 19:56:20 +0000 (+0000) Subject: - add a COLGROUP_MOVING_STATIC (in the future we should try to reduce the number... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=ca86583fae991aa3280c5d70bf20dbf0504a93cb;p=supertux.git - add a COLGROUP_MOVING_STATIC (in the future we should try to reduce the number of groups, by changing the group to a bitfield...) - this fixes block stacking nicely - Changed the way grabbing is done SVN-Revision: 4150 --- diff --git a/src/moving_object.hpp b/src/moving_object.hpp index b2f3de995..29e12f2c6 100644 --- a/src/moving_object.hpp +++ b/src/moving_object.hpp @@ -42,6 +42,8 @@ enum CollisionGroup { * MovingOnlyStatic objects), but is tested against all other objects. */ COLGROUP_MOVING_ONLY_STATIC, + /** TODO write docu :-/ */ + COLGROUP_MOVING_STATIC, /** * Doesn't move and isn't explicitely checked for collisions with other * objects (but other objects might check with this) diff --git a/src/object/player.cpp b/src/object/player.cpp index dc2ae8109..2b0ae7710 100644 --- a/src/object/player.cpp +++ b/src/object/player.cpp @@ -230,7 +230,10 @@ Player::update(float elapsed_time) handle_input(); // handle_input() calls apply_friction() when Tux is not walking, so we'll have to do this ourselves - if (deactivated) apply_friction(); + if (deactivated) + apply_friction(); + + try_grab = false; // extend/shrink tux collision rectangle so that we fall through/walk over 1 // tile holes @@ -551,7 +554,8 @@ Player::handle_vertical_input() // swimming physic.set_acceleration_y(0); if (swimming) { - if (controller->hold(Controller::UP) || controller->hold(Controller::JUMP)) physic.set_acceleration_y(-2000); + if (controller->hold(Controller::UP) || controller->hold(Controller::JUMP)) + physic.set_acceleration_y(-2000); physic.set_velocity_y(physic.get_velocity_y() * 0.94); } } @@ -559,29 +563,13 @@ Player::handle_vertical_input() void Player::handle_input() { + Sector* sector = Sector::current(); + if (ghost_mode) { handle_input_ghost(); return; } - if(!controller->hold(Controller::ACTION) && grabbed_object) { - // move the grabbed object a bit away from tux - Vector pos = get_pos() + - Vector(dir == LEFT ? -bbox.get_width()-1 : bbox.get_width()+1, - bbox.get_height()*0.66666 - 32); - Rect dest(pos, pos + Vector(32, 32)); - if(Sector::current()->is_free_space(dest)) { - MovingObject* moving_object = dynamic_cast (grabbed_object); - if(moving_object) { - moving_object->set_pos(pos); - } else { - log_debug << "Non MovingObjetc grabbed?!?" << std::endl; - } - grabbed_object->ungrab(*this, dir); - grabbed_object = NULL; - } - } - /* Peeking */ if( controller->released( Controller::PEEK_LEFT ) ) { peeking = AUTO; @@ -616,8 +604,58 @@ Player::handle_input() } /* Duck or Standup! */ - if (controller->hold(Controller::DOWN)) do_duck(); else do_standup(); + if (controller->hold(Controller::DOWN)) { + do_duck(); + } else { + do_standup(); + } + /* grabbing */ + if(controller->hold(Controller::ACTION) && !grabbed_object + && try_grab && !duck) { + Vector pos; + if(grab_dir == LEFT) { + pos = Vector(bbox.get_left() - 5, bbox.get_bottom() - 16); + } else { + pos = Vector(bbox.get_right() + 5, bbox.get_bottom() - 16); + } + + for(Sector::Portables::iterator i = sector->portables.begin(); + i != sector->portables.end(); ++i) { + Portable* portable = *i; + if(!portable->is_portable()) + continue; + + MovingObject* moving_object = dynamic_cast (portable); + assert(portable); + if(moving_object == NULL) + continue; + + if(moving_object->get_bbox().contains(pos)) { + grabbed_object = portable; + grabbed_object->grab(*this, get_pos(), dir); + break; + } + } + } + + if(!controller->hold(Controller::ACTION) && grabbed_object) { + // move the grabbed object a bit away from tux + Vector pos = get_pos() + + Vector(dir == LEFT ? -bbox.get_width()-1 : bbox.get_width()+1, + bbox.get_height()*0.66666 - 32); + Rect dest(pos, pos + Vector(32, 32)); + if(Sector::current()->is_free_space(dest)) { + MovingObject* moving_object = dynamic_cast (grabbed_object); + if(moving_object) { + moving_object->set_pos(pos); + } else { + log_debug << "Non MovingObjetc grabbed?!?" << std::endl; + } + grabbed_object->ungrab(*this, dir); + grabbed_object = NULL; + } + } } void @@ -917,6 +955,8 @@ Player::collision_solid(const CollisionHit& hit) if(hit.left || hit.right) { physic.set_velocity_x(0); + try_grab = true; + grab_dir = hit.left ? LEFT : RIGHT; } // crushed? @@ -930,21 +970,13 @@ Player::collision_solid(const CollisionHit& hit) } HitResponse -Player::collision(GameObject& other, const CollisionHit& hit) +Player::collision(GameObject& other, const CollisionHit& ) { Bullet* bullet = dynamic_cast (&other); if(bullet) { return FORCE_MOVE; } - // if we hit something from the side that is portable, the ACTION button is pressed and we are not already holding anything: grab it - Portable* portable = dynamic_cast (&other); - if ((hit.left || hit.right) && (portable && portable->is_portable()) && controller->hold(Controller::ACTION) && (!grabbed_object)) { - grabbed_object = portable; - grabbed_object->grab(*this, get_pos(), dir); - return CONTINUE; - } - #ifdef DEBUG assert(dynamic_cast (&other) != NULL); #endif diff --git a/src/object/player.hpp b/src/object/player.hpp index 409b19ddb..0fecfef0a 100644 --- a/src/object/player.hpp +++ b/src/object/player.hpp @@ -279,6 +279,8 @@ private: Sprite* bigtux_star; Vector floor_normal; + bool try_grab; + Direction grab_dir; bool ghost_mode; /**< indicates if Tux should float around and through solid objects */ diff --git a/src/object/rock.cpp b/src/object/rock.cpp index ab3de741c..716ae69fc 100644 --- a/src/object/rock.cpp +++ b/src/object/rock.cpp @@ -32,9 +32,10 @@ namespace { Rock::Rock(const lisp::Lisp& reader) : MovingSprite(reader, "images/objects/rock/rock.sprite") { - sound_manager->preload( ROCK_SOUND ); + sound_manager->preload(ROCK_SOUND); on_ground = false; grabbed = false; + set_group(COLGROUP_MOVING_STATIC); } void @@ -60,15 +61,15 @@ Rock::update(float elapsed_time) void Rock::collision_solid(const CollisionHit& hit) { - if( hit.top || hit.bottom ) - physic.set_velocity_y( 0 ); - if( hit.left || hit.right ) - physic.set_velocity_x( 0 ); - if( hit.crush ) + if(hit.top || hit.bottom) + physic.set_velocity_y(0); + if(hit.left || hit.right) + physic.set_velocity_x(0); + if(hit.crush) physic.set_velocity(0, 0); - if( hit.bottom && !on_ground ){ - sound_manager->play( ROCK_SOUND, get_pos() ); + if(hit.bottom && !on_ground) { + sound_manager->play(ROCK_SOUND, get_pos()); on_ground = true; } } @@ -76,33 +77,17 @@ Rock::collision_solid(const CollisionHit& hit) HitResponse Rock::collision(GameObject& other, const CollisionHit& hit) { - if( !on_ground ){ - if( hit.bottom && physic.get_velocity_y() > 200 ){ + if(!on_ground) { + if(hit.bottom && physic.get_velocity_y() > 200) { MovingObject* moving_object = dynamic_cast (&other); - if( moving_object ){ + if(moving_object) { //Getting a rock on the head hurts. A lot. - moving_object->collision_tile( Tile::HURTS ); + moving_object->collision_tile(Tile::HURTS); } } return FORCE_MOVE; } - //Fake being solid for moving_object. - MovingObject* moving_object = dynamic_cast (&other); - if( moving_object ){ - if( hit.top ){ - float inside = moving_object->get_bbox().get_bottom() - get_bbox().get_top(); - if( inside > 0 ){ - Vector pos = moving_object->get_pos(); - pos.y -= inside; - moving_object->set_pos( pos ); - } - } - CollisionHit hit_other = hit; - std::swap(hit_other.left, hit_other.right); - std::swap(hit_other.top, hit_other.bottom); - moving_object->collision_solid( hit_other ); - } return FORCE_MOVE; } @@ -110,14 +95,15 @@ void Rock::grab(MovingObject& , const Vector& pos, Direction) { movement = pos - get_pos(); - set_group( COLGROUP_DISABLED ); + set_group(COLGROUP_DISABLED); on_ground = true; grabbed = true; } void -Rock::ungrab(MovingObject& , Direction ){ - set_group( COLGROUP_MOVING ); +Rock::ungrab(MovingObject& , Direction ) +{ + set_group(COLGROUP_MOVING_STATIC); on_ground = false; physic.set_velocity(0, 0); grabbed = false; diff --git a/src/sector.cpp b/src/sector.cpp index 027f17129..e155abd04 100644 --- a/src/sector.cpp +++ b/src/sector.cpp @@ -56,6 +56,7 @@ #include "object/invisible_block.hpp" #include "object/bullet.hpp" #include "object/text_object.hpp" +#include "object/portable.hpp" #include "badguy/jumpy.hpp" #include "trigger/sequence_trigger.hpp" #include "player_status.hpp" @@ -345,7 +346,6 @@ Sector::parse_old_format(const lisp::Lisp& reader) void Sector::fix_old_tiles() { - // hack for now... for(std::list::iterator i = solid_tilemaps.begin(); i != solid_tilemaps.end(); i++) { TileMap* solids = *i; for(size_t x=0; x < solids->get_width(); ++x) { @@ -574,26 +574,6 @@ void Sector::update_game_objects() { /** cleanup marked objects */ - for(std::vector::iterator i = bullets.begin(); - i != bullets.end(); /* nothing */) { - Bullet* bullet = *i; - if(bullet->is_valid()) { - ++i; - continue; - } - - i = bullets.erase(i); - } - for(MovingObjects::iterator i = moving_objects.begin(); - i != moving_objects.end(); /* nothing */) { - MovingObject* moving_object = *i; - if(moving_object->is_valid()) { - ++i; - continue; - } - - i = moving_objects.erase(i); - } for(std::vector::iterator i = gameobjects.begin(); i != gameobjects.end(); /* nothing */) { GameObject* object = *i; @@ -626,19 +606,27 @@ bool Sector::before_object_add(GameObject* object) { Bullet* bullet = dynamic_cast (object); - if(bullet) + if(bullet != NULL) { bullets.push_back(bullet); + } MovingObject* movingobject = dynamic_cast (object); - if(movingobject) { + if(movingobject != NULL) { moving_objects.push_back(movingobject); } + Portable* portable = dynamic_cast (object); + if(portable != NULL) { + portables.push_back(portable); + } + TileMap* tilemap = dynamic_cast (object); - if(tilemap && tilemap->is_solid()) solid_tilemaps.push_back(tilemap); + if(tilemap != NULL && tilemap->is_solid()) { + solid_tilemaps.push_back(tilemap); + } Camera* camera = dynamic_cast (object); - if(camera) { + if(camera != NULL) { if(this->camera != 0) { log_warning << "Multiple cameras added. Ignoring" << std::endl; return false; @@ -647,7 +635,7 @@ Sector::before_object_add(GameObject* object) } Player* player = dynamic_cast (object); - if(player) { + if(player != NULL) { if(this->player != 0) { log_warning << "Multiple players added. Ignoring" << std::endl; return false; @@ -677,6 +665,20 @@ Sector::try_expose(GameObject* object) void Sector::before_object_remove(GameObject* object) { + Portable* portable = dynamic_cast (object); + if(portable != NULL) { + portables.erase(std::find(portables.begin(), portables.end(), portable)); + } + Bullet* bullet = dynamic_cast (object); + if(bullet != NULL) { + bullets.erase(std::find(bullets.begin(), bullets.end(), bullet)); + } + MovingObject* moving_object = dynamic_cast (object); + if(moving_object != NULL) { + moving_objects.erase( + std::find(moving_objects.begin(), moving_objects.end(), moving_object)); + } + if(_current == this) try_unexpose(object); } @@ -964,11 +966,14 @@ Sector::collision_static(collision::Constraints* constraints, i != moving_objects.end(); ++i) { MovingObject* moving_object = *i; if(moving_object->get_group() != COLGROUP_STATIC - || !moving_object->is_valid()) + && moving_object->get_group() != COLGROUP_MOVING_STATIC) + continue; + if(!moving_object->is_valid()) continue; - check_collisions(constraints, movement, dest, moving_object->dest, - &object, moving_object); + if(moving_object != &object) + check_collisions(constraints, movement, dest, moving_object->bbox, + &object, moving_object); } } @@ -1083,6 +1088,7 @@ Sector::handle_collisions() i != moving_objects.end(); ++i) { MovingObject* moving_object = *i; if((moving_object->get_group() != COLGROUP_MOVING + && moving_object->get_group() != COLGROUP_MOVING_STATIC && moving_object->get_group() != COLGROUP_MOVING_ONLY_STATIC) || !moving_object->is_valid()) continue; @@ -1096,6 +1102,7 @@ Sector::handle_collisions() i != moving_objects.end(); ++i) { MovingObject* moving_object = *i; if((moving_object->get_group() != COLGROUP_MOVING + && moving_object->get_group() != COLGROUP_MOVING_STATIC && moving_object->get_group() != COLGROUP_MOVING_ONLY_STATIC) || !moving_object->is_valid()) continue; @@ -1110,7 +1117,8 @@ Sector::handle_collisions() for(MovingObjects::iterator i = moving_objects.begin(); i != moving_objects.end(); ++i) { MovingObject* moving_object = *i; - if(moving_object->get_group() != COLGROUP_MOVING + if((moving_object->get_group() != COLGROUP_MOVING + && moving_object->get_group() != COLGROUP_MOVING_STATIC) || !moving_object->is_valid()) continue; @@ -1137,14 +1145,16 @@ Sector::handle_collisions() i != moving_objects.end(); ++i) { MovingObject* moving_object = *i; - if(moving_object->get_group() != COLGROUP_MOVING + if((moving_object->get_group() != COLGROUP_MOVING + && moving_object->get_group() != COLGROUP_MOVING_STATIC) || !moving_object->is_valid()) continue; for(MovingObjects::iterator i2 = i+1; i2 != moving_objects.end(); ++i2) { MovingObject* moving_object_2 = *i2; - if(moving_object_2->get_group() != COLGROUP_MOVING + if((moving_object_2->get_group() != COLGROUP_MOVING + && moving_object_2->get_group() != COLGROUP_MOVING_STATIC) || !moving_object_2->is_valid()) continue; diff --git a/src/sector.hpp b/src/sector.hpp index 8bd89669e..50edf73d8 100644 --- a/src/sector.hpp +++ b/src/sector.hpp @@ -49,6 +49,7 @@ class SpawnPoint; class MovingObject; class CollisionHit; class Level; +class Portable; enum MusicType { LEVEL_MUSIC, @@ -164,6 +165,7 @@ public: typedef std::vector GameObjects; typedef std::vector MovingObjects; typedef std::vector SpawnPoints; + typedef std::vector Portables; private: Level* level; /**< Parent level containing this sector */ @@ -232,6 +234,7 @@ public: // TODO make this private again GameObjects gameobjects; MovingObjects moving_objects; SpawnPoints spawnpoints; + Portables portables; std::string music; float gravity;