| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <Samples/PhysicsPlayground/FpsCharacterNode.h>
- #include <Samples/PhysicsPlayground/GrenadeNode.h>
- #include <Samples/PhysicsPlayground/Events.h>
- static void createFogVolumeFadeEvent(SceneNode* node)
- {
- CString script = R"(
- density = 15
- radius = 3.5
- function update(event, prevTime, crntTime)
- node = event:getAssociatedSceneNodes():getAt(0)
- -- logi(string.format("Will fade fog for %s", node:getName()))
- fogComponent = node:getFirstFogDensityComponent()
- dt = crntTime - prevTime
- density = density - 4.0 * dt
- radius = radius + 0.5 * dt
- pos = node:getLocalOrigin()
- pos:setY(pos:getY() - 1.1 * dt)
- node:setLocalOrigin(pos)
- if density <= 0.0 or radius <= 0.0 then
- node:markForDeletion()
- else
- node:setLocalScale(Vec3.new(radius))
- fogComponent:setDensity(density)
- end
- end
- function onKilled(event, prevTime, crntTime)
- -- Nothing
- end
- )";
- ScriptEvent* event = SceneGraph::getSingleton().getEventManager().newEvent<ScriptEvent>(-1, 10.0, script);
- event->addAssociatedSceneNode(node);
- }
- FpsCharacter::FpsCharacter(CString name)
- : SceneNode(name)
- {
- newComponent<PlayerControllerComponent>();
- SceneNode* cam = SceneGraph::getSingleton().newSceneNode<SceneNode>("FpsCharacterCam");
- cam->setLocalTransform(Transform(Vec3(0.0f, 2.0f, 0.0f), Mat3::getIdentity(), Vec3(1.0f)));
- CameraComponent* camc = cam->newComponent<CameraComponent>();
- camc->setPerspective(0.1f, 1000.0f, Renderer::getSingleton().getAspectRatio() * toRad<F32>(g_cvarGameFov), toRad<F32>(g_cvarGameFov));
- addChild(cam);
- m_cameraNode = cam;
- SceneNode* shotgun = SceneGraph::getSingleton().newSceneNode<SceneNode>("Shotgun");
- shotgun->setLocalTransform(Transform(m_shotgunRestingPosition, Mat3(m_shotgunRestingRotation), Vec3(1.0f, 1.0f, 0.45f)));
- shotgun->newComponent<MeshComponent>()->setMeshFilename("Assets/sleevegloveLOW.001_893660395596b206.ankimesh");
- shotgun->newComponent<MaterialComponent>()->setMaterialFilename("Assets/arms_3a4232ebbd425e7a.ankimtl").setSubmeshIndex(0);
- shotgun->newComponent<MaterialComponent>()->setMaterialFilename("Assets/boomstick_89a614a521ace7fd.ankimtl").setSubmeshIndex(1);
- cam->addChild(shotgun);
- m_shotgunNode = shotgun;
- }
- void FpsCharacter::frameUpdate([[maybe_unused]] Second prevUpdateTime, [[maybe_unused]] Second crntTime)
- {
- // Change FOV
- CameraComponent& camc = m_cameraNode->getFirstComponentOfType<CameraComponent>();
- if(toRad<F32>(g_cvarGameFov) != camc.getFovY())
- {
- camc.setFovX(Renderer::getSingleton().getAspectRatio() * toRad<F32>(g_cvarGameFov));
- camc.setFovY(toRad<F32>(g_cvarGameFov));
- }
- // Mouselook
- const Input& inp = Input::getSingleton();
- const Vec2 mousePos = inp.getMousePosition();
- if(mousePos != 0.0f)
- {
- Mat3 camRot = m_cameraNode->getLocalRotation();
- Mat3 newRot(Euler(g_cvarGameMouseLookPower * mousePos.y(), g_cvarGameMouseLookPower * -mousePos.x(), 0.0f));
- newRot = camRot * newRot;
- const Vec3 newz = newRot.getColumn(2).normalize();
- const Vec3 newx = Vec3(0.0, 1.0, 0.0).cross(newz);
- const Vec3 newy = newz.cross(newx);
- newRot.setColumns(newx, newy, newz);
- newRot = newRot.reorthogonalize();
- m_cameraNode->setLocalRotation(newRot);
- }
- // Movement
- {
- Vec3 moveVec(0.0);
- if(inp.getKey(KeyCode::kW))
- {
- moveVec.z() += 1.0f;
- }
- if(inp.getKey(KeyCode::kA))
- {
- moveVec.x() += 1.0f;
- }
- if(inp.getKey(KeyCode::kS))
- {
- moveVec.z() -= 1.0f;
- }
- if(inp.getKey(KeyCode::kD))
- {
- moveVec.x() -= 1.0f;
- }
- F32 jumpSpeed = 0.0f;
- if(inp.getKey(KeyCode::kSpace))
- {
- jumpSpeed += m_jumpSpeed;
- }
- Bool crouchChanged = false;
- if(inp.getKey(KeyCode::kC))
- {
- m_crouching = !m_crouching;
- crouchChanged = true;
- }
- if(moveVec != 0.0f || jumpSpeed != 0.0f || crouchChanged)
- {
- Vec3 dir;
- if(moveVec != 0.0f)
- {
- dir = -(m_cameraNode->getLocalRotation() * moveVec);
- dir.y() = 0.0f;
- dir = dir.normalize();
- }
- F32 speed = m_walkingSpeed;
- if(inp.getKey(KeyCode::kLeftShift))
- {
- speed *= 2.0f;
- }
- PlayerControllerComponent& playerc = getFirstComponentOfType<PlayerControllerComponent>();
- playerc.setVelocity(speed, jumpSpeed, dir, m_crouching);
- }
- }
- // Animate gun back to resting position
- if(m_shotgunNode->getLocalOrigin() != m_shotgunRestingPosition)
- {
- const Vec3 gunPos = m_shotgunNode->getLocalOrigin();
- Vec3 travelDir = m_shotgunRestingPosition - gunPos;
- const F32 remainlingDist = travelDir.length();
- travelDir = travelDir.normalize();
- const F32 speed = getRandomRange(0.2f, 0.4f);
- const F32 dist = speed * F32(crntTime - prevUpdateTime);
- if(dist >= remainlingDist)
- {
- m_shotgunNode->setLocalOrigin(m_shotgunRestingPosition);
- m_shotgunNode->setLocalRotation(Mat3(m_shotgunRestingRotation));
- }
- else
- {
- m_shotgunNode->setLocalOrigin(travelDir * dist + gunPos);
- const F32 distFactor = dist / remainlingDist;
- const Quat crntAngle(m_shotgunNode->getLocalRotation());
- const Quat restingAngle(m_shotgunRestingRotation);
- const Quat newAngle = crntAngle.slerp(restingAngle, distFactor);
- m_shotgunNode->setLocalRotation(Mat3(newAngle));
- }
- }
- // Shooting
- if(inp.getMouseButton(MouseButton::kLeft) == 1)
- {
- fireShotgun();
- const Vec3 newPosition(0.0f, getRandomRange(-0.05f, -0.03f), 0.15f);
- m_shotgunNode->setLocalOrigin(m_shotgunRestingPosition + newPosition);
- const Euler newRotation(getRandomRange(0.0_degrees, 10.0_degrees), getRandomRange(-10.0_degrees, 1.0_degrees), 0.0f);
- m_shotgunNode->setLocalRotation(Mat3(newRotation) * Mat3(m_shotgunRestingRotation));
- }
- if(inp.getMouseButton(MouseButton::kRight) == 1)
- {
- fireGrenade();
- }
- }
- void FpsCharacter::fireShotgun()
- {
- for(U32 i = 0; i < 8; ++i)
- {
- F32 spreadAngle = getRandomRange(-m_shotgunSpreadAngle / 2.0f, m_shotgunSpreadAngle / 2.0f);
- Mat3 randDirection(Axisang(spreadAngle, Vec3(1.0f, 0.0f, 0.0f)));
- spreadAngle = getRandomRange(-m_shotgunSpreadAngle / 2.0f, m_shotgunSpreadAngle / 2.0f);
- randDirection = randDirection * Mat3(Axisang(spreadAngle, Vec3(0.0f, 1.0f, 0.0f)));
- randDirection = m_cameraNode->getLocalRotation().getRotationPart() * randDirection;
- const Vec3 from = m_cameraNode->getWorldTransform().getOrigin().xyz();
- const Vec3 to = from + -randDirection.getZAxis() * m_shotgunMaxLength;
- RayHitResult result;
- const Bool hit = PhysicsWorld::getSingleton().castRayClosestHit(from, to, PhysicsLayerBit::kStatic | PhysicsLayerBit::kMoving, result);
- if(hit && result.m_object->getType() == PhysicsObjectType::kBody)
- {
- PhysicsBody& body = static_cast<PhysicsBody&>(*result.m_object);
- const Bool isStatic = body.getMass() == 0.0f;
- if(isStatic)
- {
- // Create rotation
- const Vec3& zAxis = result.m_normal;
- Vec3 yAxis = Vec3(0, 1, 0.5);
- Vec3 xAxis = yAxis.cross(zAxis).normalize();
- yAxis = zAxis.cross(xAxis);
- Mat3 rot;
- rot.setXAxis(xAxis);
- rot.setYAxis(yAxis);
- rot.setZAxis(zAxis);
- const Transform trf(result.m_hitPosition, rot, Vec3(1.0f, 1.0f, 1.0f));
- // Create an obj
- SceneNode* bulletDecal = SceneGraph::getSingleton().newSceneNode<SceneNode>("");
- bulletDecal->setLocalTransform(trf);
- bulletDecal->setLocalScale(Vec3(0.1f, 0.1f, 0.3f));
- DecalComponent* decalc = bulletDecal->newComponent<DecalComponent>();
- decalc->loadDiffuseImageResource("Assets/bullet_hole_decal.ankitex", 1.0f);
- createDestructionEvent(bulletDecal, 10.0_sec);
- }
- else
- {
- const Vec3 force = -result.m_normal * m_shotgunForce;
- body.applyForce(force);
- }
- if(i == 0)
- {
- SceneNode* fogNode = SceneGraph::getSingleton().newSceneNode<SceneNode>("");
- FogDensityComponent* fogComp = fogNode->newComponent<FogDensityComponent>();
- fogNode->setLocalScale(Vec3(2.1f));
- fogComp->setDensity(15.0f);
- fogNode->setLocalOrigin(result.m_hitPosition);
- createDestructionEvent(fogNode, 10.0_sec);
- createFogVolumeFadeEvent(fogNode);
- }
- }
- }
- }
- void FpsCharacter::fireGrenade()
- {
- Transform camTrf = m_cameraNode->getWorldTransform();
- const Vec3 newPos = camTrf.getOrigin().xyz() + camTrf.getRotation().getZAxis() * -3.0f;
- camTrf.setOrigin(newPos.xyz0());
- SceneNode* grenade = SceneGraph::getSingleton().newSceneNode<GrenadeNode>("");
- BodyComponent& bodyc = grenade->getFirstComponentOfType<BodyComponent>();
- bodyc.teleportTo(camTrf.getOrigin().xyz(), camTrf.getRotation().getRotationPart());
- bodyc.applyForce(camTrf.getRotation().getZAxis().xyz() * -1200.0f, Vec3(0.0f, 0.0f, 0.0f));
- }
|