Character Action.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Game{
  5. /******************************************************************************/
  6. void Chr::actionBreak() // break current action
  7. {
  8. action=ACTION_NONE;
  9. path.clear();
  10. // clear input
  11. input.move.zero();
  12. input.turn.zero();
  13. }
  14. /******************************************************************************/
  15. Bool Chr::actionMoveTo(C Vec &pos) // set 'move to' action
  16. {
  17. // break any current action
  18. actionBreak();
  19. // try to set new action
  20. path_target=pos;
  21. if(World.path().find(T.pos(), path_target, path)) // if found a path to the target destination
  22. {
  23. path.reverseOrder();
  24. action=ACTION_MOVE_TO; // set new action
  25. return true;
  26. }
  27. return false;
  28. }
  29. /******************************************************************************/
  30. void Chr::actionMoveDir(C Vec &dir) // set 'move to direction' action
  31. {
  32. // break any current action
  33. actionBreak();
  34. // set new action
  35. action =ACTION_MOVE_DIR;
  36. move_dir=dir.xz();
  37. }
  38. /******************************************************************************/
  39. #define ANGLE_INC 10.0f
  40. #define DIR_INC 10.0f
  41. #define DIR_DEC 4.0f
  42. /******************************************************************************/
  43. // set character 'input' according to 'from to' angles and character speeds
  44. // returns true - when the character is near the target angle and can proceed moving forward
  45. // returns false - if it should stay still and rotate only
  46. static Bool InputToAngle(Chr &chr, Flt from, Flt to, Flt turn_speed, Flt desired_speed)
  47. {
  48. Flt d=AngleDelta(from,to),
  49. ad=Abs (d );
  50. if(ad<0.001f)chr.input_turn.x=chr.input.turn.x=0;else
  51. {
  52. Flt div=turn_speed*Time.d();
  53. if( div>EPS)
  54. {
  55. Flt can =22*Time.d(),
  56. max =Lerp(0.1f, 3.0f, Mid((ad-DegToRad(5))/DegToRad(40), 0.0f, 1.0f)),
  57. want_d=d/div,
  58. d =want_d-chr.input_turn.x;
  59. Clamp(d , -can, can); chr.input_turn.x+=d;
  60. Clamp(chr.input_turn.x, -max, max);
  61. chr.input.turn.x=Sign(chr.input_turn.x);
  62. }
  63. }
  64. Flt limit=DegToRad(90);
  65. if(desired_speed>EPS)limit/=Max(1, desired_speed/4.1f);
  66. if( turn_speed>EPS)limit/=Max(1, turn_speed/3.5f);
  67. return ad<limit;
  68. }
  69. static Bool ChrToAngle(Chr &chr, C Vec2 &dir) {return InputToAngle(chr, chr.angle.x+PI_2, Angle(dir), chr.turn_speed, chr.desiredSpeed());}
  70. static Bool ChrToAngle(Chr &chr, C Vec &pos) {return ChrToAngle(chr, pos.xz()-chr.ctrl.actor.pos().xz());}
  71. /******************************************************************************/
  72. static void StopAngleInput(Chr &chr) // stop angle input
  73. {
  74. Flt d=ANGLE_INC*Time.d();
  75. AdjustValDir(chr.input_turn.x, chr.input.turn.x=0, d);
  76. AdjustValDir(chr.input_turn.y, chr.input.turn.y=0, d);
  77. }
  78. static void StopDirInput(Chr &chr) // stop direction movement input
  79. {
  80. Flt inc=DIR_INC*Time.d(),
  81. dec=DIR_DEC*Time.d();
  82. AdjustValDir(chr.input_move.x, chr.input.move.x=0, inc, dec);
  83. AdjustValDir(chr.input_move.z, chr.input.move.z=0, inc, dec);
  84. AdjustValDir(chr.input_move.y, chr.input.move.y=0, inc, dec);
  85. }
  86. static void StopInput(Chr &chr) // stop angle and direction movement input
  87. {
  88. StopAngleInput(chr);
  89. StopDirInput (chr);
  90. }
  91. static void ActionBreak(Chr &chr)
  92. {
  93. chr.actionBreak();
  94. StopInput(chr);
  95. }
  96. /******************************************************************************/
  97. static void UpdateMoveDir(Chr &chr, Vec2 &dir)
  98. {
  99. chr.input.move.x=0;
  100. chr.input.move.z=ChrToAngle(chr, dir); // if the character is facing the target angle then move forward
  101. chr.input.move.y=0;
  102. Flt inc=DIR_INC*Time.d(),
  103. dec=DIR_DEC*Time.d();
  104. AdjustValDir(chr.input_move.x, chr.input.move.x, inc, dec);
  105. AdjustValDir(chr.input_move.z, chr.input.move.z, inc, dec);
  106. AdjustValDir(chr.input_move.y, chr.input.move.y, inc, dec);
  107. }
  108. static void UpdateMoveTo(Chr &chr)
  109. {
  110. Vec from=chr.ctrl.actor.pos(); // get current position
  111. Bool path_searched=false;
  112. for(;;)
  113. {
  114. if(!chr.path.elms()) // if don't have a waypoint
  115. {
  116. if(!path_searched) // if didn't yet searched
  117. {
  118. path_searched=true; // don't try anymore searches
  119. if(World.path().find(from, chr.path_target, chr.path))chr.path.reverseOrder(); // search the path
  120. }
  121. if(!chr.path.elms()) // if still don't have a waypoint
  122. {
  123. ActionBreak(chr); // break the action
  124. break; // return
  125. }
  126. }
  127. Vec2 to =chr.path.last().xz(), // get the next waypoint
  128. dir=to-from.xz(); // set direction from current to the next position
  129. if(dir.length()<=chr.ctrl.radius()) // we've reached the waypoint
  130. {
  131. chr.path.removeLast(); // remove this point
  132. }else
  133. {
  134. UpdateMoveDir(chr, dir); // go in direction of the waypoint
  135. break; // return
  136. }
  137. }
  138. }
  139. /******************************************************************************/
  140. void Chr::updateAction()
  141. {
  142. // update input according to actions
  143. switch(action)
  144. {
  145. case ACTION_MOVE_TO: // move to target
  146. {
  147. input.jump =0;
  148. input.dodge =false;
  149. input.crouch=false;
  150. input.walk =move_walking;
  151. UpdateMoveTo(T); // update the 'move to' action
  152. }break;
  153. case ACTION_MOVE_DIR: // move in direction
  154. {
  155. input.jump =0;
  156. input.dodge =false;
  157. input.crouch=false;
  158. input.walk =move_walking;
  159. UpdateMoveDir(T, move_dir);
  160. }break;
  161. default: // manual input
  162. {
  163. Flt inc, dec;
  164. if(input.adjust_move)
  165. {
  166. inc=DIR_INC*Time.d();
  167. dec=DIR_DEC*Time.d();
  168. AdjustValDir(input_move.x, input.move.x, inc, dec);
  169. AdjustValDir(input_move.z, input.move.z, inc, dec);
  170. AdjustValDir(input_move.y, input.move.y, inc, dec);
  171. }
  172. if(input.adjust_turn)
  173. {
  174. inc=ANGLE_INC*Time.d();
  175. AdjustValDir(input_turn.x, input.turn.x, inc);
  176. AdjustValDir(input_turn.y, input.turn.y, inc);
  177. }
  178. }break;
  179. }
  180. // update character according to input
  181. {
  182. // update angles
  183. angle+=input_turn*(Time.d()*turn_speed);
  184. Clamp(angle.y, -PI_2, PI_2); // limit vertical angle to -PI_2..PI_2 range
  185. // dodge (dodge is a fast strafe acivated by tapping Left or Right direction twice)
  186. dodge_availability-=Time.d(); if(input.dodge && !ctrl.crouched() && ctrl.onGround() && dodge_availability<=0)
  187. {
  188. dodging =input.dodge;
  189. dodge_step =1;
  190. dodge_availability=0.5f;
  191. }
  192. }
  193. }
  194. /******************************************************************************/
  195. void Chr::updateController()
  196. {
  197. // set movement velocity
  198. Vec velocity;
  199. if(dodging) // set according to dodging
  200. {
  201. velocity.y=0; CosSin(velocity.x, velocity.z, angle.x); if(dodging<0)velocity.chs();
  202. velocity.setLength(speed*2.5f*Pow(dodge_step, 0.25f));
  203. dodge_step-=Time.d()*3.33f; if(dodge_step<=0)dodging=0;
  204. }
  205. else // set according to the input
  206. {
  207. // set desired 'wish' vector movement according to the angles and movement
  208. Flt ax =angle.x+PI_2,
  209. ay =angle.y;
  210. Vec dir=input_move;
  211. if(!ctrl.flying())
  212. {
  213. ay =0;
  214. dir.y=0;
  215. }
  216. Flt cx, sx, cy, sy;
  217. CosSin(cx, sx, ax);
  218. CosSin(cy, sy, ay);
  219. Vec wish(dir.z*cx*cy + dir.x*sx, dir.z*sy + dir.y,
  220. dir.z*sx*cy - dir.x*cx);
  221. // slow down when running backwards
  222. Flt length=1; if(dir.z<0)length=Lerp(Lerp(1.0f, 0.75f, anim.walk_run), 1.0f, dir.z+1); // if dir.z is in range -1..0
  223. wish.clipLength(length);
  224. // set final velocity according to 'wish' vector and desired speed
  225. velocity=wish*desiredSpeed();
  226. }
  227. // update character controller
  228. ctrl.update(velocity, ctrl.crouched() ? input.crouch : (anim.stand_crouch>=1), input.jump);
  229. }
  230. /******************************************************************************/
  231. }}
  232. /******************************************************************************/