diff options
-rw-r--r-- | src/client/input.cc | 1 | ||||
-rw-r--r-- | src/core/entity.cc | 24 | ||||
-rw-r--r-- | src/core/entity.h | 8 | ||||
-rw-r--r-- | src/core/net.h | 2 | ||||
-rw-r--r-- | src/game/game.cc | 1 | ||||
-rw-r--r-- | src/game/ship.cc | 122 | ||||
-rw-r--r-- | src/game/shipmodel.cc | 6 |
7 files changed, 123 insertions, 41 deletions
diff --git a/src/client/input.cc b/src/client/input.cc index aaf83fa..044ebc2 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -618,6 +618,7 @@ void frame(float seconds) if (core::application()->connected() && core::localcontrol()) { mouse_control = !console()->visible() && ((input_mousecontrol->value() > 0) || mouse_control_override); + core::localcontrol()->set_autolevel(!mouse_control); if (mouse_control) { // the mouse will not react if it is in the deadzone diff --git a/src/core/entity.cc b/src/core/entity.cc index 20e34ee..d23959f 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -322,6 +322,7 @@ EntityControlable::EntityControlable(Player *owner, unsigned int flags) : EntityDynamic(flags) { entity_thrust = 0; + entity_autolevel = false; target_direction = 0.0f; target_thrust = 0.0f; @@ -338,6 +339,14 @@ EntityControlable::EntityControlable(std::istream & is) : { unsigned int o; + entity_thrust = 0; + entity_autolevel = false; + + target_direction = 0.0f; + target_thrust = 0.0f; + target_pitch = 0.0f; + target_roll = 0.0f; + is >> entity_thrust; is >> o; @@ -366,6 +375,7 @@ void EntityControlable::serialize_client_update(std::ostream & os) const os << " " << target_pitch; os << " " << target_thrust; os << " " << target_roll; + os << " " << (autolevel() ? 1 : 0); } @@ -376,6 +386,13 @@ void EntityControlable::receive_client_update(std::istream &is) is >> target_pitch; is >> target_thrust; is >> target_roll; + + unsigned int b = 0; + is >> b; + if (b) + entity_autolevel = true; + else + entity_autolevel = true; } void EntityControlable::serialize_server_update(std::ostream & os) const @@ -409,6 +426,13 @@ void EntityControlable::set_thrust(float thrust) } } +void EntityControlable::set_autolevel(bool autolevel) +{ + if (entity_autolevel != autolevel) { + entity_autolevel = autolevel; + entity_dirty = true; + } +} void EntityControlable::set_direction(float direction) { if ((flags() & Static) == Static) diff --git a/src/core/entity.h b/src/core/entity.h index ca2d029..2515796 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -286,6 +286,9 @@ public: /// serialize a server-to-client update on a stream virtual void serialize_server_update(std::ostream & os) const; + /// autolevel mode + bool autolevel() const { return entity_autolevel; } + /*----- mutators -------------------------------------------------- */ @@ -300,6 +303,9 @@ public: /// set the target direction void set_direction(float direction); + + /// set autolevel request + void set_autolevel(bool autolevel); /// set the target pitch void set_pitch(float pitch); @@ -336,7 +342,7 @@ public: private: // owner of the entity Player *entity_owner; - + bool entity_autolevel; }; /// a Globe entity diff --git a/src/core/net.h b/src/core/net.h index c80b979..04c77a5 100644 --- a/src/core/net.h +++ b/src/core/net.h @@ -11,7 +11,7 @@ namespace core { /// network protocol version -const unsigned int PROTOCOLVERSION = 3; +const unsigned int PROTOCOLVERSION = 4; /// maximum lenght of a (compressed) network message block const unsigned int FRAMESIZE = 1152; diff --git a/src/game/game.cc b/src/game/game.cc index b6c0366..e481c9f 100644 --- a/src/game/game.cc +++ b/src/game/game.cc @@ -498,6 +498,7 @@ bool Game::load_ships() } else if (shipsini.got_key_float("maxspeed", shipmodel->shipmodel_maxspeed)) { continue; } else if (shipsini.got_key_float("turnspeed", shipmodel->shipmodel_turnspeed)) { + math::clamp(shipmodel->shipmodel_turnspeed, 0.0f, 90.0f); continue; } else { con_warn << shipsini.name() << " unknown key '" << shipsini.key() << "' at line " << shipsini.line() << std::endl; diff --git a/src/game/ship.cc b/src/game/ship.cc index f61c9bd..d8f7bb3 100644 --- a/src/game/ship.cc +++ b/src/game/ship.cc @@ -17,6 +17,8 @@ using math::degrees180f; namespace game { +const float MIN_DELTA = 10e-10; + Ship::Ship(core::Player *owner, ShipModel *shipmodel) : core::EntityControlable(owner, ship_enttype) { @@ -45,31 +47,68 @@ Ship::~Ship() void Ship::frame(float seconds) { const float direction_change_speed = 2; + float cosangle; // cosine of an angle + float angle; // angle in radians + math::Vector3f n; // normal of a plane - // update thrust + // target axis + math::Axis target_axis(entity_axis); + + // clamp input values math::clamp(target_thrust, 0.0f, 1.0f); - entity_thrust = target_thrust; - - // update pitch math::clamp(target_pitch, -1.0f, 1.0f); - if (current_target_pitch < target_pitch) { - current_target_pitch += direction_change_speed * seconds; - if (current_target_pitch > target_pitch) - current_target_pitch = target_pitch; - } else if (current_target_pitch > target_pitch) { - current_target_pitch -= direction_change_speed * seconds; - if (current_target_pitch < target_pitch) - current_target_pitch = target_pitch; + math::clamp(target_roll, -1.0f, 1.0f); + math::clamp(target_direction, -1.0f, 1.0f); + + // update thrust + entity_thrust = target_thrust; + + + if (autolevel()) { + n.assign(math::crossproduct(entity_axis.up(), math::Vector3f(0, 0, 1.0f))); + if (!(n.length() < MIN_DELTA)) { + cosangle = math::dotproduct(entity_axis.up(), math::Vector3f(0, 0, 1.0f)); + target_roll = acos(cosangle); + math::clamp(target_roll, 0.0f, 1.0f); + target_roll *= M_1_PI; + target_roll *= math::sgnf(math::dotproduct(entity_axis.left(), math::Vector3f(0.0, 0.0f, 1.0f))); + } else { + target_roll = 0; + } } - - if (fabs(seconds*current_target_pitch) > 0.0f) { - math::clamp(current_target_pitch, -1.0f, 1.0f); - float pitch_offset = seconds * current_target_pitch; - entity_axis.change_pitch(360.0f * ship_shipmodel->turnspeed() * pitch_offset); + + if (current_target_roll < target_roll) { + current_target_roll += direction_change_speed * seconds; + if (current_target_roll > target_roll) + current_target_roll = target_roll; + } else if (current_target_roll > target_roll) { + current_target_roll -= direction_change_speed * seconds; + if (current_target_roll < target_roll) + current_target_roll = target_roll; } + math::clamp(current_target_roll, -1.0f, 1.0f); - // update direction - math::clamp(target_direction, -1.0f, 1.0f); + if (fabs(current_target_roll) > MIN_DELTA) { + float roll_offset = seconds * current_target_roll; + entity_axis.change_roll(ship_shipmodel->turnspeed() * roll_offset); + } else { + current_target_roll = 0.0f; + } + + // auto-leveling + if (autolevel()) { + n.assign(math::crossproduct(entity_axis.up(), math::Vector3f(0.0f, 0.0f, 1.0f))); + if (!(n.length() < MIN_DELTA)) { + cosangle = math::dotproduct(entity_axis.up(), math::Vector3f(0.0f, 0.0f, 1.0f)); + target_pitch = acos(cosangle); + math::clamp(target_roll, 0.0f, 1.0f); + target_pitch *= -math::sgnf(math::dotproduct(entity_axis.forward(), math::Vector3f(0.0, 0.0f, 1.0f))); + } else { + target_pitch = 0; + } + } + + // update target_axis direction if (current_target_direction < target_direction) { current_target_direction += direction_change_speed * seconds; if (current_target_direction > target_direction) { @@ -81,27 +120,38 @@ void Ship::frame(float seconds) current_target_direction = target_direction; } } - if (fabs(seconds*current_target_direction) > 0.0f ) { + + if (fabs(current_target_direction) > MIN_DELTA ) { math::clamp(current_target_direction, -1.0f, 1.0f); - float direction_offset = seconds * current_target_direction; - entity_axis.change_direction(360.0f * ship_shipmodel->turnspeed() * direction_offset); + target_axis.change_direction(ship_shipmodel->turnspeed() * current_target_direction); + } else { + //current_target_direction = 0.0f; } - // update roll - math::clamp(target_roll, -1.0f, 1.0f); - if (current_target_roll < target_roll) { - current_target_roll += direction_change_speed * seconds; - if (current_target_roll > target_roll) - current_target_roll = target_roll; - } else if (current_target_roll > target_roll) { - current_target_roll -= direction_change_speed * seconds; - if (current_target_roll < target_roll) - current_target_roll = target_roll; + if (current_target_pitch < target_pitch) { + current_target_pitch += direction_change_speed * seconds; + if (current_target_pitch > target_pitch) + current_target_pitch = target_pitch; + } else if (current_target_pitch > target_pitch) { + current_target_pitch -= direction_change_speed * seconds; + if (current_target_pitch < target_pitch) + current_target_pitch = target_pitch; } - if (fabs(current_target_roll) > 0.0f) { - math::clamp(current_target_roll, -1.0f, 1.0f); - float roll_offset = seconds * current_target_roll; - entity_axis.change_roll(360.0f * ship_shipmodel->turnspeed() * roll_offset); + + if (fabs(current_target_pitch) > MIN_DELTA) { + math::clamp(current_target_pitch, -1.0f, 1.0f); + target_axis.change_pitch(ship_shipmodel->turnspeed() * current_target_pitch); + } else { + //current_target_pitch = 0.0f; + } + + n.assign(math::crossproduct(entity_axis.forward(), target_axis.forward())); + if (!(n.length() < MIN_DELTA)) { + n.normalize(); + cosangle = math::dotproduct(entity_axis.forward(), target_axis.forward()); + angle = acos(cosangle) * seconds; // * 180.0f / M_PI; + if (angle > MIN_DELTA) + entity_axis.rotate(n, -angle); } // update speed diff --git a/src/game/shipmodel.cc b/src/game/shipmodel.cc index 6a226f4..8ff182f 100644 --- a/src/game/shipmodel.cc +++ b/src/game/shipmodel.cc @@ -15,9 +15,9 @@ std::map<std::string, ShipModel *> ShipModel::registry; ShipModel::ShipModel() { //default specifications - shipmodel_acceleration = 1.0f; - shipmodel_maxspeed = 3.0f; - shipmodel_turnspeed = 0.1f; + shipmodel_acceleration = 1.0f; // thruster acceleration in game untits/second^2 + shipmodel_maxspeed = 3.0f; // maximum thruster speed in game units/second + shipmodel_turnspeed = 45.0f; // 45 degrees per second shipmodel_jumpdrive = false; } |