修訂 | 3d56b61a6045437bf0a2068665ce6b311d3d9a13 (tree) |
---|---|
時間 | 2012-09-08 21:49:44 |
作者 | angeart <angeart@git....> |
Commiter | angeart |
ver0.2.3 ジャンプ式の最終確定(恐らく)
@@ -8,6 +8,18 @@ | ||
8 | 8 | #include "MotionPlayer.hpp" |
9 | 9 | #include "../../common/Logger.hpp" |
10 | 10 | |
11 | + | |
12 | +namespace | |
13 | +{ | |
14 | + | |
15 | +template <typename T, typename U> | |
16 | +inline bool NearlyEqualRelative(const T& lhs, const T& rhs, const U& ratio) | |
17 | +{ | |
18 | + return abs(lhs - rhs) <= ratio * abs(rhs); | |
19 | +} | |
20 | + | |
21 | +} | |
22 | + | |
11 | 23 | class PlayerCharacter::Impl |
12 | 24 | { |
13 | 25 | public: |
@@ -16,8 +28,14 @@ public: | ||
16 | 28 | model_handle_(-1), |
17 | 29 | current_target_pos_(VGet(0, 1000, 0)), |
18 | 30 | prev_target_pos_(VGet(0, 1000, 0)), |
31 | + current_target_vec_y_(0.0f), | |
19 | 32 | current_rot_(VGet(0, 0, 0)), |
20 | 33 | prev_rot_(VGet(0, 0, 0)), |
34 | + move_vec_y_(0.0f), | |
35 | + jump_flag_(false), | |
36 | + flight_duration_ideal_(1.0f), | |
37 | + model_height_(1.58f), | |
38 | + jump_height_(sqrt(15.0f)*2.0f), | |
21 | 39 | current_motion_(-1), |
22 | 40 | prev_motion_(-1), |
23 | 41 | current_speed_(0), |
@@ -32,7 +50,10 @@ public: | ||
32 | 50 | motion.walk_ = MV1GetAnimIndex(model_handle_, _T("walk")); |
33 | 51 | motion.run_ = MV1GetAnimIndex(model_handle_, _T("run")); |
34 | 52 | motion_player_.reset(new MotionPlayer(model_handle_)); |
35 | - } | |
53 | + | |
54 | + model_height_ = data_provider_.model().property().get<float>("character.height",1.58f); | |
55 | + flight_duration_ideal_ = sqrt((model_height_*2.0f)/9.8f) + sqrt((model_height_*0.8f)/9.8); | |
56 | + } | |
36 | 57 | |
37 | 58 | void Impl::Draw() const |
38 | 59 | { |
@@ -43,8 +64,16 @@ public: | ||
43 | 64 | |
44 | 65 | void Impl::Update() |
45 | 66 | { |
67 | + static auto time_now = 0.0f; | |
68 | + prev_target_pos_ = current_target_pos_; | |
46 | 69 | const auto current_target_pos = data_provider_.target_position(); |
70 | + const auto current_target_vec_y_ = data_provider_.vy(); | |
47 | 71 | // if (current_target_pos.y == 0) return; |
72 | + if(current_target_pos != prev_target_pos_ ) | |
73 | + { | |
74 | + time_now = 0.0f; | |
75 | + } | |
76 | + | |
48 | 77 | |
49 | 78 | current_target_pos_ = current_target_pos; |
50 | 79 | current_pos_ = MV1GetPosition(model_handle_); |
@@ -73,50 +102,150 @@ public: | ||
73 | 102 | |
74 | 103 | //Logger::Debug("distance_to_target: %d %d", distance_to_target, current_speed_ * timer_->DeltaSec()); |
75 | 104 | |
76 | - if (current_speed_ * timer_->DeltaSec() > 0.2) | |
77 | - { | |
78 | - current_motion_ = motion.run_; | |
79 | - } | |
80 | - else | |
81 | - { | |
82 | - current_motion_ = motion.stand_; | |
83 | - } | |
84 | - | |
85 | - if (current_motion_ != prev_motion_ && current_motion_ != -1) | |
86 | - { | |
87 | - motion_player_->Play(current_motion_, false, 200, -1, false); | |
88 | - prev_motion_ = current_motion_; | |
89 | - }else if(additional_motion_.first) | |
90 | - { | |
91 | - bool connect_prev = true; | |
92 | - motion_player_->Play(additional_motion_.second, connect_prev, 200, -1, false); | |
93 | - additional_motion_.first = false; | |
94 | - } | |
95 | - | |
96 | 105 | // TODO: Y下方向については重力加速度 |
97 | 106 | if (distance_to_target > 2.0){ |
98 | - const auto direction = current_target_pos_ - current_pos_; | |
107 | + auto direction = current_target_pos_ - current_pos_; | |
99 | 108 | const auto diff_pos = VAdjustLength(direction, current_speed_ * timer_->DeltaSec()); |
100 | 109 | const float roty = atan2(-direction.x, -direction.z); |
110 | + const auto time_entire = VSize(direction) / (current_speed_ * (float)timer_->DeltaSec()); // ターゲットまでの移動完了時間 | |
111 | + time_now += timer_->DeltaSec(); // タイマーのカウントアップ | |
101 | 112 | |
102 | 113 | current_rot_ = VGet(0, roty, 0); |
103 | 114 | //std::cout << "set pos to " << MV1GetPosition(model_handle_) + diff_pos << std::endl; |
104 | 115 | |
116 | + /* | |
117 | + const auto jump_result_y = | |
118 | + jump_height_ * stage_->map_scale() * (time_entire - time_now) * (jump_height_ / 5.0f) * 1.019952f + | |
119 | + 0.5f * -9.8f * (time_entire - time_now) * (time_entire - time_now) * (1.0f / flight_duration_ideal_) * (jump_height_ / 5.0f) * (jump_height_ / 5.0f); // 今からジャンプした際の最終的な位置 | |
120 | + */ | |
121 | + static auto st_acc = -9.8f; | |
122 | + auto acc = -6.5f; | |
123 | + auto prediction_vector = 0.0f; | |
124 | + | |
125 | + for(acc;acc < -11.0f;acc-=0.1f){ | |
126 | + prediction_vector = jump_height_ * stage_->map_scale() + (acc) * (time_entire - time_now) * (jump_height_ / 5.0f) * (1.0f / flight_duration_ideal_ ); | |
127 | + if( current_target_vec_y_ != 0 && jump_flag_ == false ) | |
128 | + { | |
129 | + // ターゲット座標ではジャンプを始めている | |
130 | + if( prediction_vector > current_target_vec_y_ - 1 && prediction_vector < current_target_vec_y_ + 1) | |
131 | + { | |
132 | + // 目標座標でベクトルが上向きなら一致、ジャンプを始める | |
133 | + move_vec_y_ = jump_height_ * stage_->map_scale(); | |
134 | + jump_flag_ = true; | |
135 | + }// それ以外はそのまま | |
136 | + } | |
137 | + } | |
138 | + st_acc = acc; | |
139 | + | |
140 | + VECTOR moved_pos; | |
141 | + moved_pos = current_pos_ + diff_pos; | |
142 | + if( jump_flag_ == true ) | |
143 | + { | |
144 | + move_vec_y_ += (st_acc * stage_->map_scale() * timer_->DeltaSec() * (1.0f/flight_duration_ideal_) * (jump_height_ / 5.0f)); | |
145 | + moved_pos.y = current_pos_.y + move_vec_y_ * timer_->DeltaSec() * (jump_height_ / 5.0f); | |
146 | + } | |
147 | + Logger::Debug(_T("move_vec_y %.3f"), move_vec_y_); | |
148 | + | |
105 | 149 | // 床へのめり込みを防止 |
106 | - VECTOR moved_pos = current_pos_ + diff_pos; | |
107 | 150 | float floor_y; |
108 | - for (int i = 1; | |
109 | - i < 10 && !(stage_->GetFloorY(moved_pos + VGet(0,10 * i,0), moved_pos + VGet(0,-10 * i,0), &floor_y)); | |
110 | - i+=2); | |
111 | - moved_pos.y = std::max(moved_pos.y, floor_y); | |
151 | + std::pair<bool, VECTOR> floor_coll; | |
152 | + if(jump_flag_ == false) | |
153 | + { | |
154 | + // 延長線上で接地検査 | |
155 | + floor_coll = stage_->FloorExists(moved_pos,model_height_,8.0f); | |
156 | + }else if(jump_flag_ == true && current_pos_.y >= moved_pos.y) | |
157 | + { | |
158 | + // 足で接地検査 | |
159 | + floor_coll = stage_->FloorExists(moved_pos,model_height_,0); | |
160 | + } | |
161 | + //moved_pos.y = std::max(moved_pos.y, floor_y); // 床にあたっているときは床の方がyが高くなる | |
162 | + if(jump_flag_ == false){ | |
163 | + // 登ったり下ったりできる段差の大きさの制限を求める | |
164 | + static const float y_max_limit_factor = sin(45 * PHI_F / 180); | |
165 | + static const float y_min_limit_factor = sin(-45 * PHI_F / 180); | |
166 | + const float y_max_limit = y_max_limit_factor * VSize(diff_pos); | |
167 | + const float y_min_limit = y_min_limit_factor * VSize(diff_pos); | |
168 | + | |
169 | + // 接地点計算 | |
170 | + //std::cout << " ground collision check: current pos = " << current_stat_.pos << std::endl; | |
171 | + | |
172 | + auto coll_info = MV1CollCheck_Line(stage_->map_handle().handle(), -1, | |
173 | + moved_pos + VGet(0, y_max_limit, 0), | |
174 | + moved_pos + VGet(0, y_min_limit, 0)); | |
175 | + if(coll_info.HitFlag && NearlyEqualRelative(coll_info.HitPosition.y, floor_coll.second.y, 0.001)){ | |
176 | + // 接地可能 | |
177 | + auto diff = coll_info.HitPosition - current_pos_; | |
178 | + | |
179 | + // 角度が急になるほどdiffの長さが大きくなるから、補正する | |
180 | + if (VSize(diff) > 0) | |
181 | + { | |
182 | + moved_pos = current_pos_ + VSize(diff_pos) * VNorm(diff); | |
183 | + } | |
184 | + | |
185 | + } | |
186 | + if( floor_coll.first ) | |
187 | + { | |
188 | + if( floor_coll.second.y < moved_pos.y ) | |
189 | + { | |
190 | + jump_flag_ = true; | |
191 | + } | |
192 | + } | |
193 | + //move_vec_y_ = 0; | |
194 | + }else{ | |
195 | + if( moved_pos.y <= current_pos_.y ) | |
196 | + { | |
197 | + if( floor_coll.first ) | |
198 | + { | |
199 | + moved_pos = floor_coll.second; | |
200 | + move_vec_y_ = 0; | |
201 | + } | |
202 | + }else{ | |
203 | + // 上昇している | |
204 | + | |
205 | + const auto player_top = VGet(0, model_height_ * stage_->map_scale(), 0); | |
206 | + auto coll_info = MV1CollCheck_Line(stage_->map_handle().handle(), -1, | |
207 | + current_pos_ + player_top, | |
208 | + moved_pos + player_top); | |
209 | + if (coll_info.HitFlag) | |
210 | + { | |
211 | + // 天井に到達した | |
212 | + // std::cout << " current collided to ceiling" << std::endl; | |
213 | + | |
214 | + moved_pos = coll_info.HitPosition - player_top; | |
215 | + move_vec_y_ = -(move_vec_y_ - (st_acc * stage_->map_scale() * timer_->DeltaSec() * (1.0f/flight_duration_ideal_) * (jump_height_ / 5.0f))) * 1.0; // 反射 | |
216 | + } | |
217 | + } | |
218 | + } | |
112 | 219 | |
113 | 220 | data_provider_.set_position(moved_pos); |
114 | 221 | data_provider_.set_theta(current_rot_.y); |
115 | 222 | |
116 | 223 | MV1SetPosition(model_handle_, moved_pos); |
117 | - MV1SetRotationXYZ(model_handle_, current_rot_); | |
224 | + MV1SetRotationXYZ(model_handle_, current_rot_); | |
225 | + | |
226 | + if (current_speed_ * timer_->DeltaSec() > 0.205f) | |
227 | + { | |
228 | + current_motion_ = motion.run_; | |
229 | + } | |
230 | + else | |
231 | + { | |
232 | + current_motion_ = motion.walk_; | |
233 | + } | |
234 | + }else{ | |
235 | + current_motion_ = motion.stand_; | |
118 | 236 | } |
119 | 237 | |
238 | + if (current_motion_ != prev_motion_ && current_motion_ != -1) | |
239 | + { | |
240 | + motion_player_->Play(current_motion_, false, 200, -1, false); | |
241 | + prev_motion_ = current_motion_; | |
242 | + }else if(additional_motion_.first) | |
243 | + { | |
244 | + bool connect_prev = true; | |
245 | + motion_player_->Play(additional_motion_.second, connect_prev, 200, -1, false); | |
246 | + additional_motion_.first = false; | |
247 | + } | |
248 | + | |
120 | 249 | } else { |
121 | 250 | // 離れすぎている場合は瞬間移動 |
122 | 251 |
@@ -138,9 +267,15 @@ private: | ||
138 | 267 | CharacterDataProvider& data_provider_; |
139 | 268 | int model_handle_; |
140 | 269 | VECTOR current_target_pos_; |
141 | - VECTOR prev_target_pos_; | |
270 | + VECTOR prev_target_pos_; // ひとつ前のターゲット | |
142 | 271 | VECTOR current_pos_; |
143 | 272 | VECTOR current_rot_, prev_rot_; |
273 | + float current_target_vec_y_; | |
274 | + float move_vec_y_; | |
275 | + bool jump_flag_; | |
276 | + float flight_duration_ideal_; | |
277 | + float model_height_; | |
278 | + float jump_height_; | |
144 | 279 | int current_motion_; |
145 | 280 | int prev_motion_; |
146 | 281 | float current_speed_; |
@@ -9,7 +9,7 @@ | ||
9 | 9 | |
10 | 10 | #define MMO_VERSION_MAJOR 0 |
11 | 11 | #define MMO_VERSION_MINOR 2 |
12 | -#define MMO_VERSION_REVISION 2 | |
12 | +#define MMO_VERSION_REVISION 3 | |
13 | 13 | |
14 | 14 | #ifdef MMO_VERSION_BUILD |
15 | 15 | #define MMO_VERSION_BUILD_TEXT " Build " MMO_VERSION_TOSTRING(MMO_VERSION_BUILD) |