ScummVM API documentation
PlayerMoveStates.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*
23  * Copyright (C) 2006-2010 - Frictional Games
24  *
25  * This file is part of Penumbra Overture.
26  */
27 
28 #ifndef GAME_PLAYER_MOVE_STATES_H
29 #define GAME_PLAYER_MOVE_STATES_H
30 
31 class cPlayer;
32 
34 // BASE STATE
36 
37 iPlayerMoveState::iPlayerMoveState(cPlayer *apPlayer, cInit *apInit) {
38  mpPlayer = apPlayer;
39  mpInit = apInit;
40 
41  mpGameConfig = mpInit->mpGameConfig;
42  mpHeadMove = mpPlayer->GetHeadMove();
43 
44  // Speed setup
45  mfForwardSpeed = 3.0f;
46  mfBackwardSpeed = 1.5f;
47  mfSidewaySpeed = 2.0f;
48 
49  mfForwardAcc = 6.0f;
50  mfForwardDeacc = 12.0f;
51  mfSidewayAcc = 6.0f;
52  mfSidewayDeacc = 12.0f;
53 
54  mbActive = false;
55 
56  // Head move setup
57  mfMaxHeadMove = 0.05f;
58  mfMinHeadMove = -0.06f;
59  mfHeadMoveSpeed = 0.38f;
60  mfHeadMoveBackSpeed = 0.23f;
61 
62  mfHeightAdd = 0;
63  mfHeightAddSpeed = 1.5f;
64 
65  mfSpeedMul = 1;
66 
67  // FootStep multiplier
68  mfFootStepMul = 1.0f;
69 
70  msStepType = "walk";
71 }
72 
73 void iPlayerMoveState::SetupBody() {
74  iCharacterBody *pCharBody = mpPlayer->GetCharacterBody();
75  float fMul = mpPlayer->GetSpeedMul() * mpPlayer->GetHealthSpeedMul();
76 
77  pCharBody->SetMaxPositiveMoveSpeed(eCharDir_Forward, mfForwardSpeed * fMul);
78  pCharBody->SetMaxNegativeMoveSpeed(eCharDir_Forward, -mfBackwardSpeed * fMul);
79 
80  pCharBody->SetMaxPositiveMoveSpeed(eCharDir_Right, mfSidewaySpeed * fMul);
81  pCharBody->SetMaxNegativeMoveSpeed(eCharDir_Right, -mfSidewaySpeed * fMul);
82 
83  pCharBody->SetMoveAcc(eCharDir_Forward, mfForwardAcc);
84  pCharBody->SetMoveDeacc(eCharDir_Forward, mfForwardDeacc);
85  pCharBody->SetMoveAcc(eCharDir_Right, mfSidewayAcc);
86  pCharBody->SetMoveDeacc(eCharDir_Right, mfSidewayDeacc);
87 }
88 
89 void iPlayerMoveState::InitState(iPlayerMoveState *apPrevState) {
90  if (apPrevState) {
91  apPrevState->LeaveState(apPrevState);
92  apPrevState->mbActive = false;
93  }
94 
95  EnterState(apPrevState);
96 
97  // Set up body
98  SetupBody();
99 
100  mpHeadMove->mfMaxHeadMove = mfMaxHeadMove;
101  mpHeadMove->mfMinHeadMove = mfMinHeadMove;
102  mpHeadMove->mfHeadMoveSpeed = mfHeadMoveSpeed;
103  mpHeadMove->mfHeadMoveBackSpeed = mfHeadMoveBackSpeed;
104  mpHeadMove->mfFootStepMul = mfFootStepMul;
105 }
106 
107 void iPlayerMoveState::Start() {
108  if (mbActive == false) {
109  mbActive = true;
110 
111  // Set up body
112  iCharacterBody *pCharBody = mpPlayer->GetCharacterBody();
113  float fMul = mpPlayer->GetSpeedMul();
114 
115  pCharBody->SetMaxPositiveMoveSpeed(eCharDir_Forward, mfForwardSpeed * fMul);
116  pCharBody->SetMaxNegativeMoveSpeed(eCharDir_Forward, -mfBackwardSpeed * fMul);
117 
118  pCharBody->SetMaxPositiveMoveSpeed(eCharDir_Right, mfSidewaySpeed * fMul);
119  pCharBody->SetMaxNegativeMoveSpeed(eCharDir_Right, -mfSidewaySpeed * fMul);
120 
121  pCharBody->SetMoveAcc(eCharDir_Forward, mfForwardAcc);
122  pCharBody->SetMoveDeacc(eCharDir_Forward, mfForwardDeacc);
123  pCharBody->SetMoveAcc(eCharDir_Right, mfSidewayAcc);
124  pCharBody->SetMoveDeacc(eCharDir_Right, mfSidewayDeacc);
125 
126  mpHeadMove->mfMaxHeadMove = mfMaxHeadMove;
127  mpHeadMove->mfMinHeadMove = mfMinHeadMove;
128  mpHeadMove->mfHeadMoveSpeed = mfHeadMoveSpeed;
129  mpHeadMove->mfHeadMoveBackSpeed = mfHeadMoveBackSpeed;
130  mpHeadMove->mfFootStepMul = mfFootStepMul;
131 
132  mpHeadMove->Start();
133  }
134 }
135 
136 void iPlayerMoveState::Stop() {
137  mpHeadMove->Stop();
138 
139  mbActive = false;
140 }
141 
142 void iPlayerMoveState::Update(float afTimeStep) {
143  // Update height add
144  float fPlayerHeightAdd = mpPlayer->GetHeightAdd();
145  if (fPlayerHeightAdd < mfHeightAdd) {
146  fPlayerHeightAdd += mfHeightAddSpeed * afTimeStep;
147  if (fPlayerHeightAdd > mfHeightAdd)
148  fPlayerHeightAdd = mfHeightAdd;
149  }
150 
151  if (fPlayerHeightAdd > mfHeightAdd) {
152  fPlayerHeightAdd -= mfHeightAddSpeed * afTimeStep;
153  if (fPlayerHeightAdd < mfHeightAdd)
154  fPlayerHeightAdd = mfHeightAdd;
155  }
156  mpPlayer->SetHeightAdd(fPlayerHeightAdd);
157 
158  OnUpdate(afTimeStep);
159 }
160 
162 // WALK STATE
164 
166 public:
167  cPlayerMoveState_Walk(cPlayer *apPlayer, cInit *apInit) : iPlayerMoveState(apPlayer, apInit) {
168  mfForwardSpeed = mpGameConfig->GetFloat("Movement_Walk", "ForwardSpeed", 0);
169  mfBackwardSpeed = mpGameConfig->GetFloat("Movement_Walk", "BackwardSpeed", 0);
170  mfSidewaySpeed = mpGameConfig->GetFloat("Movement_Walk", "SidewaySpeed", 0);
171 
172  mfForwardAcc = mpGameConfig->GetFloat("Movement_Walk", "ForwardAcc", 0);
173  mfForwardDeacc = mpGameConfig->GetFloat("Movement_Walk", "ForwardDeacc", 0);
174  mfSidewayAcc = mpGameConfig->GetFloat("Movement_Walk", "SidewayAcc", 0);
175  mfSidewayDeacc = mpGameConfig->GetFloat("Movement_Walk", "SidewayDeacc", 0);
176 
177  // Head move setup
178  mfMaxHeadMove = mpGameConfig->GetFloat("Movement_Walk", "MaxHeadMove", 0);
179  mfMinHeadMove = mpGameConfig->GetFloat("Movement_Walk", "MinHeadMove", 0);
180  mfHeadMoveSpeed = mpGameConfig->GetFloat("Movement_Walk", "HeadMoveSpeed", 0);
181  mfHeadMoveBackSpeed = 0.23f;
182 
183  // FootStep multiplier
184  mfFootStepMul = 1.0f;
185 
186  msStepType = "walk";
187 
188  mType = ePlayerMoveState_Walk;
189  }
190 };
191 
193 // RUN STATE
195 
197 public:
198  cPlayerMoveState_Run(cPlayer *apPlayer, cInit *apInit) : iPlayerMoveState(apPlayer, apInit) {
199  mfForwardSpeed = mpGameConfig->GetFloat("Movement_Run", "ForwardSpeed", 0);
200  mfBackwardSpeed = mpGameConfig->GetFloat("Movement_Run", "BackwardSpeed", 0);
201  mfSidewaySpeed = mpGameConfig->GetFloat("Movement_Run", "SidewaySpeed", 0);
202 
203  mfForwardAcc = mpGameConfig->GetFloat("Movement_Run", "ForwardAcc", 0);
204  mfForwardDeacc = mpGameConfig->GetFloat("Movement_Run", "ForwardDeacc", 0);
205  mfSidewayAcc = mpGameConfig->GetFloat("Movement_Run", "SidewayAcc", 0);
206  mfSidewayDeacc = mpGameConfig->GetFloat("Movement_Run", "SidewayDeacc", 0);
207 
208  // Head move setup
209  mfMaxHeadMove = mpGameConfig->GetFloat("Movement_Run", "MaxHeadMove", 0);
210  mfMinHeadMove = mpGameConfig->GetFloat("Movement_Run", "MinHeadMove", 0);
211  mfHeadMoveSpeed = mpGameConfig->GetFloat("Movement_Run", "HeadMoveSpeed", 0);
212  mfHeadMoveBackSpeed = 0.23f;
213 
214  // FootStep multiplier
215  mfFootStepMul = 1.0f;
216 
217  msStepType = "run";
218 
219  mType = ePlayerMoveState_Run;
220  }
221 };
222 
224 // STILL STATE
226 
228 public:
229  cPlayerMoveState_Still(cPlayer *apPlayer, cInit *apInit) : iPlayerMoveState(apPlayer, apInit) {
230  mfForwardSpeed = 0.0f;
231  mfBackwardSpeed = 0.0f;
232  mfSidewaySpeed = 0.0f;
233 
234  mfForwardAcc = 0.0f;
235  mfForwardDeacc = 6.0f;
236  mfSidewayAcc = 0.0f;
237  mfSidewayDeacc = 6.0f;
238 
239  // Head move setup
240  mfMaxHeadMove = 0.03f;
241  mfMinHeadMove = -0.03f;
242  mfHeadMoveSpeed = 0.12f;
243  mfHeadMoveBackSpeed = 0.23f;
244 
245  // FootStep multiplier
246  mfFootStepMul = 0.6f;
247 
248  msStepType = "walk";
249 
250  mType = ePlayerMoveState_Still;
251  }
252 
253  void EnterState(iPlayerMoveState *apPrevState) {
254  if (apPrevState) {
255  mfHeightAdd = apPrevState->mfHeightAdd;
256  mfHeightAddSpeed = apPrevState->mfHeightAddSpeed;
257  }
258  }
259 };
260 
262 // JUMP STATE
264 
266 public:
267  bool mbFirstUpdate;
268  float mfStartForce;
269  float mfMaxForward;
270  float mfMaxSide;
271 
272  float mfDefaultFowardSpeed;
273  float mfDefaultSidewaySpeed;
274 
275  cPlayerMoveState_Jump(cPlayer *apPlayer, cInit *apInit) : iPlayerMoveState(apPlayer, apInit) {
276  mfForwardSpeed = mpGameConfig->GetFloat("Movement_Jump", "ForwardSpeed", 0);
277  mfDefaultFowardSpeed = mfForwardSpeed;
278  mfBackwardSpeed = mpGameConfig->GetFloat("Movement_Jump", "BackwardSpeed", 0);
279  mfSidewaySpeed = mpGameConfig->GetFloat("Movement_Jump", "SidewaySpeed", 0);
280  mfDefaultSidewaySpeed = mfSidewaySpeed;
281 
282  mfForwardAcc = mpGameConfig->GetFloat("Movement_Jump", "ForwardAcc", 0);
283  mfForwardDeacc = mpGameConfig->GetFloat("Movement_Jump", "ForwardDeacc", 0);
284  mfSidewayAcc = mpGameConfig->GetFloat("Movement_Jump", "SidewayAcc", 0);
285  mfSidewayDeacc = mpGameConfig->GetFloat("Movement_Jump", "SidewayDeacc", 0);
286 
287  // Head move setup
288  mfMaxHeadMove = 0.00f;
289  mfMinHeadMove = 0.00f;
290  mfHeadMoveSpeed = 0.0f;
291  mfHeadMoveBackSpeed = 0.33f;
292 
293  // mfHeightAdd =-0.3f;
294  // mfHeightAddSpeed = 1.2f;
295 
296  // FootStep multiplier
297  mfFootStepMul = 0.0f;
298 
299  msStepType = "run";
300 
301  mfStartForce = mpInit->mpGameConfig->GetFloat("Player", "JumpStartForce", 1);
302 
303  mType = ePlayerMoveState_Jump;
304  }
305 
306  void EnterState(iPlayerMoveState *apPrevState) {
307  iCharacterBody *pBody = mpPlayer->GetCharacterBody();
308 
309  if (apPrevState)
310  mPrevMoveState = apPrevState->mType;
311  else
312  mPrevMoveState = ePlayerMoveState_Walk;
313 
314  float fForce = mfStartForce;
315  if (mPrevMoveState == ePlayerMoveState_Crouch) {
316  fForce *= 0.5f;
317  mfForwardSpeed = mfDefaultFowardSpeed * 0.6f;
318  mfSidewaySpeed = mfDefaultSidewaySpeed * 0.6f;
319  } else {
320  mfForwardSpeed = mfDefaultFowardSpeed;
321  mfSidewaySpeed = mfDefaultSidewaySpeed;
322  }
323 
324  // Set the current move speed as force speed.
325  cVector3f vVel = 0;
326  cVector3f vForward = pBody->GetMoveMatrix().GetForward() * -1.0f;
327  cVector3f vRight = pBody->GetMoveMatrix().GetRight();
328 
329  vVel += vForward * pBody->GetMoveSpeed(eCharDir_Forward);
330  vVel += vRight * pBody->GetMoveSpeed(eCharDir_Right);
331 
332  pBody->AddForceVelocity(vVel);
333 
334  pBody->SetMoveSpeed(eCharDir_Forward, 0);
335  pBody->SetMoveSpeed(eCharDir_Right, 0);
336 
337  // Add jump force
338  pBody->AddForce(cVector3f(0, fForce * mpPlayer->GetDefaultMass(), 0));
339 
340  mbFirstUpdate = true;
341 
342  // Get the maximum speed allowed.
343  if (mPrevMoveState == ePlayerMoveState_Still || mPrevMoveState == ePlayerMoveState_Walk) {
344  mfMaxForward = mpPlayer->GetMoveStateData(ePlayerMoveState_Walk)->mfForwardSpeed;
345  mfMaxSide = mpPlayer->GetMoveStateData(ePlayerMoveState_Walk)->mfSidewaySpeed;
346  } else {
347  mfMaxForward = apPrevState->mfForwardSpeed;
348  mfMaxSide = apPrevState->mfSidewaySpeed;
349  }
350  }
351 
352  void LeaveState(iPlayerMoveState *apNextState) {
353  iCharacterBody *pBody = mpPlayer->GetCharacterBody();
354 
355  pBody->AddForceVelocity(pBody->GetForceVelocity() * -0.7f);
356  }
357 
358  void OnUpdate(float afTimeStep) {
359  iCharacterBody *pBody = mpPlayer->GetCharacterBody();
360 
361  if (mbFirstUpdate) {
362  mbFirstUpdate = false;
363  return;
364  }
365 
366  // Check so that speed is correct
367  cVector3f vForceVel = pBody->GetForceVelocity();
368  float fSpeed = vForceVel.Length();
369 
370  if (fSpeed > mfMaxForward) {
371  // float fNeg = fSpeed - mfMaxForward;
372 
373  float fForwardSpeed = pBody->GetMoveSpeed(eCharDir_Forward);
374  /*if(fForwardSpeed>0){
375  fForwardSpeed -= fNeg;
376  if(fForwardSpeed<0)fForwardSpeed =0;
377  }
378  else {
379  fForwardSpeed += fNeg;
380  if(fForwardSpeed>0)fForwardSpeed =0;
381  }*/
382  pBody->SetMoveSpeed(eCharDir_Forward, fForwardSpeed);
383  }
384 
385  // Skip sideways here, it is sucha strange way to jump anyway.
386 
387  // Check if the jumpbutton is down.
388  if (mpPlayer->GetJumpButtonDown() &&
389  mpPlayer->GetJumpCount() < mpPlayer->GetMaxJumpCount()) {
390  float fMul = 0.4f + 0.5f * (1 - mpPlayer->GetJumpCount() / mpPlayer->GetMaxJumpCount());
391 
392  pBody->AddForce(cVector3f(0, -pBody->GetCustomGravity().y * pBody->GetMass() * fMul, 0));
393  } else if (pBody->GetForceVelocity().y > 0) {
394  // Add some extra gravity
395  pBody->AddForce(cVector3f(0, -20.0f * pBody->GetMass(), 0));
396  }
397 
398  // check if the body is on ground, and if so end jump.
399  if (pBody->IsOnGround() && pBody->GetForceVelocity().y == 0) {
400  mpPlayer->ChangeMoveState(mPrevMoveState);
401  } else if (mpPlayer->GetLandedFromJump()) {
402  mpPlayer->SetLandedFromJump(false);
403  mpPlayer->ChangeMoveState(mPrevMoveState);
404  }
405  }
406 };
407 
409 // CROUCH STATE
411 
413 public:
414  bool mbFirstUpdate;
415 
416  cPlayerMoveState_Crouch(cPlayer *apPlayer, cInit *apInit) : iPlayerMoveState(apPlayer, apInit) {
417  mfForwardSpeed = mpGameConfig->GetFloat("Movement_Crouch", "ForwardSpeed", 0);
418  mfBackwardSpeed = mpGameConfig->GetFloat("Movement_Crouch", "BackwardSpeed", 0);
419  mfSidewaySpeed = mpGameConfig->GetFloat("Movement_Crouch", "SidewaySpeed", 0);
420 
421  mfForwardAcc = mpGameConfig->GetFloat("Movement_Crouch", "ForwardAcc", 0);
422  mfForwardDeacc = mpGameConfig->GetFloat("Movement_Crouch", "ForwardDeacc", 0);
423  mfSidewayAcc = mpGameConfig->GetFloat("Movement_Crouch", "SidewayAcc", 0);
424  mfSidewayDeacc = mpGameConfig->GetFloat("Movement_Crouch", "SidewayDeacc", 0);
425 
426  // Head move setup
427  mfMaxHeadMove = mpGameConfig->GetFloat("Movement_Crouch", "MaxHeadMove", 0);
428  mfMinHeadMove = mpGameConfig->GetFloat("Movement_Crouch", "MinHeadMove", 0);
429  mfHeadMoveSpeed = mpGameConfig->GetFloat("Movement_Crouch", "HeadMoveSpeed", 0);
430  mfHeadMoveBackSpeed = 0.23f;
431 
432  mfHeightAdd = -(mpPlayer->GetSize().y - mpPlayer->GetCrouchHeight());
433  mfHeightAddSpeed = 1.8f;
434 
435  // FootStep multiplier
436  mfFootStepMul = 1.0f;
437 
438  msStepType = "sneak";
439 
440  mType = ePlayerMoveState_Crouch;
441  }
442 
443  void EnterState(iPlayerMoveState *apPrevState) {
444  iCharacterBody *pBody = mpPlayer->GetCharacterBody();
445 
446  cVector3f vFeetPos = pBody->GetPosition() - cVector3f(0, pBody->GetShape()->GetSize().y / 2, 0);
447  pBody->SetActiveSize(1);
448  pBody->SetPosition(vFeetPos + cVector3f(0, pBody->GetShape()->GetSize().y / 2, 0));
449  // pBody->SetGravityActive(false);
450  }
451 
452  void LeaveState(iPlayerMoveState *apNextState) {
453  iCharacterBody *pBody = mpPlayer->GetCharacterBody();
454 
455  cVector3f vFeetPos = pBody->GetPosition() - cVector3f(0, pBody->GetShape()->GetSize().y / 2, 0);
456  pBody->SetActiveSize(0);
457  pBody->SetPosition(vFeetPos + cVector3f(0, pBody->GetShape()->GetSize().y / 2, 0));
458 
460  // Check if the player will fit with the newer size
461  cInit *pInit = mpPlayer->GetInit();
462  iPhysicsWorld *pWorld = pInit->mpGame->GetScene()->GetWorld3D()->GetPhysicsWorld();
463 
464  pBody->SetPosition(pBody->GetPosition() + cVector3f(0, 0.005f, 0));
465 
466  // Check with both bodies. This removes some bugs.
467  for (int i = 0; i < 2; ++i) {
468  iCollideShape *pShape = pBody->GetExtraBody(i)->GetShape();
469 
470  cVector3f vNewPos = pBody->GetPosition();
471  /*bool bCollide = */ pWorld->CheckShapeWorldCollision(&vNewPos, pShape,
472  cMath::MatrixTranslate(pBody->GetPosition()),
473  pBody->GetBody(), false, true);
474 
475  /*Log("Collide when leaving crouch: %d. NewPos: %s OldPos: %s\n",bCollide,
476  vNewPos.ToString().c_str(),
477  pBody->GetPosition().ToString().c_str());*/
478 
479  // If the body is pushed down, then something is colliding from above.
480  // if so, set crouch mode again.
481  if (vNewPos != pBody->GetPosition()) {
482  pBody->SetPosition(pBody->GetPosition() - cVector3f(0, 0.005f, 0));
483  mpPlayer->ChangeMoveState(ePlayerMoveState_Crouch);
484  return;
485  }
486  }
487 
488  pBody->SetPosition(pBody->GetPosition() - cVector3f(0, 0.005f, 0));
489  }
490 
491  void OnUpdate(float afTimeStep) {
492  }
493 };
494 
495 #endif // GAME_PLAYER_MOVE_STATES_H
Definition: PlayerMoveStates.h:165
Definition: Player.h:145
Definition: Player.h:87
Definition: PlayerMoveStates.h:196
Definition: PlayerMoveStates.h:412
Definition: PlayerMoveStates.h:227
Definition: PlayerMoveStates.h:265
Definition: Init.h:70