FpsCharacterNode.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <Samples/PhysicsPlayground/FpsCharacterNode.h>
  6. #include <Samples/PhysicsPlayground/GrenadeNode.h>
  7. #include <Samples/PhysicsPlayground/Events.h>
  8. static void createFogVolumeFadeEvent(SceneNode* node)
  9. {
  10. CString script = R"(
  11. density = 15
  12. radius = 3.5
  13. function update(event, prevTime, crntTime)
  14. node = event:getAssociatedSceneNodes():getAt(0)
  15. -- logi(string.format("Will fade fog for %s", node:getName()))
  16. fogComponent = node:getFirstFogDensityComponent()
  17. dt = crntTime - prevTime
  18. density = density - 4.0 * dt
  19. radius = radius + 0.5 * dt
  20. pos = node:getLocalOrigin()
  21. pos:setY(pos:getY() - 1.1 * dt)
  22. node:setLocalOrigin(pos)
  23. if density <= 0.0 or radius <= 0.0 then
  24. node:markForDeletion()
  25. else
  26. node:setLocalScale(Vec3.new(radius))
  27. fogComponent:setDensity(density)
  28. end
  29. end
  30. function onKilled(event, prevTime, crntTime)
  31. -- Nothing
  32. end
  33. )";
  34. ScriptEvent* event = SceneGraph::getSingleton().getEventManager().newEvent<ScriptEvent>(-1, 10.0, script);
  35. event->addAssociatedSceneNode(node);
  36. }
  37. FpsCharacter::FpsCharacter(CString name)
  38. : SceneNode(name)
  39. {
  40. newComponent<PlayerControllerComponent>();
  41. SceneNode* cam = SceneGraph::getSingleton().newSceneNode<SceneNode>("FpsCharacterCam");
  42. cam->setLocalTransform(Transform(Vec3(0.0f, 2.0f, 0.0f), Mat3::getIdentity(), Vec3(1.0f)));
  43. CameraComponent* camc = cam->newComponent<CameraComponent>();
  44. camc->setPerspective(0.1f, 1000.0f, Renderer::getSingleton().getAspectRatio() * toRad<F32>(g_cvarGameFov), toRad<F32>(g_cvarGameFov));
  45. addChild(cam);
  46. m_cameraNode = cam;
  47. SceneNode* shotgun = SceneGraph::getSingleton().newSceneNode<SceneNode>("Shotgun");
  48. shotgun->setLocalTransform(Transform(m_shotgunRestingPosition, Mat3(m_shotgunRestingRotation), Vec3(1.0f, 1.0f, 0.45f)));
  49. shotgun->newComponent<MeshComponent>()->setMeshFilename("Assets/sleevegloveLOW.001_893660395596b206.ankimesh");
  50. shotgun->newComponent<MaterialComponent>()->setMaterialFilename("Assets/arms_3a4232ebbd425e7a.ankimtl").setSubmeshIndex(0);
  51. shotgun->newComponent<MaterialComponent>()->setMaterialFilename("Assets/boomstick_89a614a521ace7fd.ankimtl").setSubmeshIndex(1);
  52. cam->addChild(shotgun);
  53. m_shotgunNode = shotgun;
  54. }
  55. void FpsCharacter::frameUpdate([[maybe_unused]] Second prevUpdateTime, [[maybe_unused]] Second crntTime)
  56. {
  57. // Change FOV
  58. CameraComponent& camc = m_cameraNode->getFirstComponentOfType<CameraComponent>();
  59. if(toRad<F32>(g_cvarGameFov) != camc.getFovY())
  60. {
  61. camc.setFovX(Renderer::getSingleton().getAspectRatio() * toRad<F32>(g_cvarGameFov));
  62. camc.setFovY(toRad<F32>(g_cvarGameFov));
  63. }
  64. // Mouselook
  65. const Input& inp = Input::getSingleton();
  66. const Vec2 mousePos = inp.getMousePosition();
  67. if(mousePos != 0.0f)
  68. {
  69. Mat3 camRot = m_cameraNode->getLocalRotation();
  70. Mat3 newRot(Euler(g_cvarGameMouseLookPower * mousePos.y(), g_cvarGameMouseLookPower * -mousePos.x(), 0.0f));
  71. newRot = camRot * newRot;
  72. const Vec3 newz = newRot.getColumn(2).normalize();
  73. const Vec3 newx = Vec3(0.0, 1.0, 0.0).cross(newz);
  74. const Vec3 newy = newz.cross(newx);
  75. newRot.setColumns(newx, newy, newz);
  76. newRot = newRot.reorthogonalize();
  77. m_cameraNode->setLocalRotation(newRot);
  78. }
  79. // Movement
  80. {
  81. Vec3 moveVec(0.0);
  82. if(inp.getKey(KeyCode::kW))
  83. {
  84. moveVec.z() += 1.0f;
  85. }
  86. if(inp.getKey(KeyCode::kA))
  87. {
  88. moveVec.x() += 1.0f;
  89. }
  90. if(inp.getKey(KeyCode::kS))
  91. {
  92. moveVec.z() -= 1.0f;
  93. }
  94. if(inp.getKey(KeyCode::kD))
  95. {
  96. moveVec.x() -= 1.0f;
  97. }
  98. F32 jumpSpeed = 0.0f;
  99. if(inp.getKey(KeyCode::kSpace))
  100. {
  101. jumpSpeed += m_jumpSpeed;
  102. }
  103. Bool crouchChanged = false;
  104. if(inp.getKey(KeyCode::kC))
  105. {
  106. m_crouching = !m_crouching;
  107. crouchChanged = true;
  108. }
  109. if(moveVec != 0.0f || jumpSpeed != 0.0f || crouchChanged)
  110. {
  111. Vec3 dir;
  112. if(moveVec != 0.0f)
  113. {
  114. dir = -(m_cameraNode->getLocalRotation() * moveVec);
  115. dir.y() = 0.0f;
  116. dir = dir.normalize();
  117. }
  118. F32 speed = m_walkingSpeed;
  119. if(inp.getKey(KeyCode::kLeftShift))
  120. {
  121. speed *= 2.0f;
  122. }
  123. PlayerControllerComponent& playerc = getFirstComponentOfType<PlayerControllerComponent>();
  124. playerc.setVelocity(speed, jumpSpeed, dir, m_crouching);
  125. }
  126. }
  127. // Animate gun back to resting position
  128. if(m_shotgunNode->getLocalOrigin() != m_shotgunRestingPosition)
  129. {
  130. const Vec3 gunPos = m_shotgunNode->getLocalOrigin();
  131. Vec3 travelDir = m_shotgunRestingPosition - gunPos;
  132. const F32 remainlingDist = travelDir.length();
  133. travelDir = travelDir.normalize();
  134. const F32 speed = getRandomRange(0.2f, 0.4f);
  135. const F32 dist = speed * F32(crntTime - prevUpdateTime);
  136. if(dist >= remainlingDist)
  137. {
  138. m_shotgunNode->setLocalOrigin(m_shotgunRestingPosition);
  139. m_shotgunNode->setLocalRotation(Mat3(m_shotgunRestingRotation));
  140. }
  141. else
  142. {
  143. m_shotgunNode->setLocalOrigin(travelDir * dist + gunPos);
  144. const F32 distFactor = dist / remainlingDist;
  145. const Quat crntAngle(m_shotgunNode->getLocalRotation());
  146. const Quat restingAngle(m_shotgunRestingRotation);
  147. const Quat newAngle = crntAngle.slerp(restingAngle, distFactor);
  148. m_shotgunNode->setLocalRotation(Mat3(newAngle));
  149. }
  150. }
  151. // Shooting
  152. if(inp.getMouseButton(MouseButton::kLeft) == 1)
  153. {
  154. fireShotgun();
  155. const Vec3 newPosition(0.0f, getRandomRange(-0.05f, -0.03f), 0.15f);
  156. m_shotgunNode->setLocalOrigin(m_shotgunRestingPosition + newPosition);
  157. const Euler newRotation(getRandomRange(0.0_degrees, 10.0_degrees), getRandomRange(-10.0_degrees, 1.0_degrees), 0.0f);
  158. m_shotgunNode->setLocalRotation(Mat3(newRotation) * Mat3(m_shotgunRestingRotation));
  159. }
  160. if(inp.getMouseButton(MouseButton::kRight) == 1)
  161. {
  162. fireGrenade();
  163. }
  164. }
  165. void FpsCharacter::fireShotgun()
  166. {
  167. for(U32 i = 0; i < 8; ++i)
  168. {
  169. F32 spreadAngle = getRandomRange(-m_shotgunSpreadAngle / 2.0f, m_shotgunSpreadAngle / 2.0f);
  170. Mat3 randDirection(Axisang(spreadAngle, Vec3(1.0f, 0.0f, 0.0f)));
  171. spreadAngle = getRandomRange(-m_shotgunSpreadAngle / 2.0f, m_shotgunSpreadAngle / 2.0f);
  172. randDirection = randDirection * Mat3(Axisang(spreadAngle, Vec3(0.0f, 1.0f, 0.0f)));
  173. randDirection = m_cameraNode->getLocalRotation().getRotationPart() * randDirection;
  174. const Vec3 from = m_cameraNode->getWorldTransform().getOrigin().xyz();
  175. const Vec3 to = from + -randDirection.getZAxis() * m_shotgunMaxLength;
  176. RayHitResult result;
  177. const Bool hit = PhysicsWorld::getSingleton().castRayClosestHit(from, to, PhysicsLayerBit::kStatic | PhysicsLayerBit::kMoving, result);
  178. if(hit && result.m_object->getType() == PhysicsObjectType::kBody)
  179. {
  180. PhysicsBody& body = static_cast<PhysicsBody&>(*result.m_object);
  181. const Bool isStatic = body.getMass() == 0.0f;
  182. if(isStatic)
  183. {
  184. // Create rotation
  185. const Vec3& zAxis = result.m_normal;
  186. Vec3 yAxis = Vec3(0, 1, 0.5);
  187. Vec3 xAxis = yAxis.cross(zAxis).normalize();
  188. yAxis = zAxis.cross(xAxis);
  189. Mat3 rot;
  190. rot.setXAxis(xAxis);
  191. rot.setYAxis(yAxis);
  192. rot.setZAxis(zAxis);
  193. const Transform trf(result.m_hitPosition, rot, Vec3(1.0f, 1.0f, 1.0f));
  194. // Create an obj
  195. SceneNode* bulletDecal = SceneGraph::getSingleton().newSceneNode<SceneNode>("");
  196. bulletDecal->setLocalTransform(trf);
  197. bulletDecal->setLocalScale(Vec3(0.1f, 0.1f, 0.3f));
  198. DecalComponent* decalc = bulletDecal->newComponent<DecalComponent>();
  199. decalc->loadDiffuseImageResource("Assets/bullet_hole_decal.ankitex", 1.0f);
  200. createDestructionEvent(bulletDecal, 10.0_sec);
  201. }
  202. else
  203. {
  204. const Vec3 force = -result.m_normal * m_shotgunForce;
  205. body.applyForce(force);
  206. }
  207. if(i == 0)
  208. {
  209. SceneNode* fogNode = SceneGraph::getSingleton().newSceneNode<SceneNode>("");
  210. FogDensityComponent* fogComp = fogNode->newComponent<FogDensityComponent>();
  211. fogNode->setLocalScale(Vec3(2.1f));
  212. fogComp->setDensity(15.0f);
  213. fogNode->setLocalOrigin(result.m_hitPosition);
  214. createDestructionEvent(fogNode, 10.0_sec);
  215. createFogVolumeFadeEvent(fogNode);
  216. }
  217. }
  218. }
  219. }
  220. void FpsCharacter::fireGrenade()
  221. {
  222. Transform camTrf = m_cameraNode->getWorldTransform();
  223. const Vec3 newPos = camTrf.getOrigin().xyz() + camTrf.getRotation().getZAxis() * -3.0f;
  224. camTrf.setOrigin(newPos.xyz0());
  225. SceneNode* grenade = SceneGraph::getSingleton().newSceneNode<GrenadeNode>("");
  226. BodyComponent& bodyc = grenade->getFirstComponentOfType<BodyComponent>();
  227. bodyc.teleportTo(camTrf.getOrigin().xyz(), camTrf.getRotation().getRotationPart());
  228. bodyc.applyForce(camTrf.getRotation().getZAxis().xyz() * -1200.0f, Vec3(0.0f, 0.0f, 0.0f));
  229. }