Steve_Yorkshire Posted February 26, 2023 Share Posted February 26, 2023 (edited) After my previous Third Person camera movement system which I have edited to label as a shooter style, I decided to expand it and make an actual Elden Ring/GTA/Sleeping Dogs (the last one I actually have played) style third person free camera with screenSpace based movement input; eg: move left makes the player move screen left. The player also turns to face the direction that they are moving in. In the video this is exaggerated by having side and backwards speed set very low and forward speed set very high. Standard code of Move->x and Move->y are not taken into account and movement speed is based purely on player datablock move speeds and I didn't include "prone" as a pose. void Player::updateMove(const Move* move) { struct Move my_move; //... setImageAltTriggerState( 0, move->trigger[sImageTrigger1] ); } //yorks F32 camZ = 0.0f; GameConnection* con = getControllingClient(); bool thirdP = false; if (con && !con->isFirstPerson()) thirdP = true;//yorks end // Update current orientation if (mDamageState == Enabled) { //... if (doStandardMove) { F32 p = move->pitch * (mPose == SprintPose ? mDataBlock->sprintPitchScale : 1.0f); if (p > M_PI_F) p -= M_2PI_F; //mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle, // mDataBlock->maxLookAngle);//yorks out F32 y = move->yaw * (mPose == SprintPose ? mDataBlock->sprintYawScale : 1.0f); if (y > M_PI_F) y -= M_2PI_F; //yorks start //if (((move->freeLook && isMounted() && getMountNode() == 0) || (con && !con->isFirstPerson()))) if (thirdP)// { //yorks moved down here mHead.x = mClampF(mHead.x + (p * 0.5f), mDataBlock->minLookAngle, mDataBlock->maxLookAngle);//yorks added 0.5f to slow p down a bit //let us run the camera around in a big old never ending circle F32 camRot = mHead.z + (y * 0.5f);//slow y down a bit, techincally you should do this input script mouse sensitivity, also see p above //constrain the range of camRot within pi*2 /*if (camRot > M_PI_F) camRot -= M_2PI_F; else if (camRot < -M_PI_F) camRot += M_2PI_F;*/ camRot = mWrapF(camRot, 0.0f, M_2PI_F);//yorks use the new method mHead.z = camRot; // mHead.z = mClampF(mHead.z + y, // -mDataBlock->maxFreelookAngle, // mDataBlock->maxFreelookAngle);//yorks end } else { //yorks moved down here mHead.x = mClampF(mHead.x + (p * 0.5f), mDataBlock->minLookAngle, mDataBlock->maxLookAngle);//yorks added 0.5f to slow p down a bit mRot.z += y; // Rotate the head back to the front, center horizontal // as well if we're controlling another object. mHead.z *= 0.5f; if (mControlObject) mHead.x *= 0.5f; } } //... if ((mState == MoveState || (mState == RecoverState && mDataBlock->recoverRunForceScale > 0.0f)) && mDamageState == Enabled && !isAnimationLocked()) { F32 yawDiff = 0.0f; if (thirdP) { GameBase* cam = con->getCameraObject(); if (cam) { //get the camera's transform F32 pos = 1; MatrixF camTrans; cam->getCameraTransform(&pos, &camTrans); //flatten the transform to X&Y (so when the camera //is facing up/down the move remains horizontal) camTrans[9] = 0; camTrans.normalize(); //create a move vector and multiply by the camera transform VectorF temp(move->x, move->y, 0); camTrans.mulV(temp, &moveVec); // get the z rotation of the camera for working with right stick aiming camZ = camTrans.toEuler().z; if (camZ < 0.0f) camZ += M_2PI_F; //Con::printf("Camz %f", camZ); // Constrain the range of camZ within pi*2 camZ = mWrapF(camZ, 0.0f, M_2PI_F);//yorks use the new method if ((!mIsZero(move->y)) || (!mIsZero(move->x))) { // This is make the player turn towards the direction that they are moving Point3F transVec = getTransform().getForwardVector(); F32 tran = mAtan2(transVec.x, transVec.y); if (tran < 0.0f) tran += M_2PI_F; mWrapF(tran, 0.0f, M_2PI_F); F32 moveDir = mAtan2(getVelocity().x, getVelocity().y);//it's the x and y of player velocity we want if(moveDir < 0.0f) moveDir += M_2PI_F; yawDiff = moveDir - tran; //Con::printf("moveDir %f; tran %f; yawDiff %f", moveDir, tran, yawDiff); //ignore very small rotations if (mFabs(yawDiff) < 0.005f && mFabs(yawDiff) > -0.005f)//yorks now less than a third of 1 degree//0.001f)// yawDiff = 0.0f; if (!mIsZero(yawDiff)) { // now make sure we take the short way around the circle if (yawDiff > M_PI_F) yawDiff -= M_2PI_F; else if (yawDiff < -M_PI_F) yawDiff += M_2PI_F; F32 slower;//slower exists to slow the turn down slower = 0.15f; mRot.z += yawDiff * slower; mHead.z -= yawDiff * slower;//the camera is still attached to the player so we need to compensate for the player's new rotation } } } } if (thirdP)//yorks this is broken up a bit for debug testing { //get facing movement direction as yawDiff F32 dirSpeed = 0.0f; if (yawDiff < 0.785f)//0-45deg { if (mSwimming) dirSpeed = mDataBlock->maxUnderwaterForwardSpeed; else if (mPose == CrouchPose) dirSpeed = mDataBlock->maxCrouchForwardSpeed; else if (mPose == SprintPose) dirSpeed = mDataBlock->maxSprintForwardSpeed; else dirSpeed = mDataBlock->maxForwardSpeed; //Con::printf("forward 0-0.785; %f", yawDiff); } else if (yawDiff > 5.497f)//315-360deg { if (mSwimming) dirSpeed = mDataBlock->maxUnderwaterForwardSpeed; else if (mPose == CrouchPose) dirSpeed = mDataBlock->maxCrouchForwardSpeed; else if (mPose == SprintPose) dirSpeed = mDataBlock->maxSprintForwardSpeed; else dirSpeed = mDataBlock->maxForwardSpeed; //Con::printf("forward 5.497-6.283; %f", yawDiff); } else if (yawDiff > 0.784f && yawDiff < 2.356f) { if (mSwimming) dirSpeed = mDataBlock->maxUnderwaterSideSpeed; else if (mPose == CrouchPose) dirSpeed = mDataBlock->maxCrouchSideSpeed; else if (mPose == SprintPose) dirSpeed = mDataBlock->maxSprintSideSpeed; else dirSpeed = mDataBlock->maxSideSpeed; //Con::printf("side right 0.784-2.356; %f", yawDiff); } else if(yawDiff < 5.496f && yawDiff > 3.926f) { if (mSwimming) dirSpeed = mDataBlock->maxUnderwaterSideSpeed; else if (mPose == CrouchPose) dirSpeed = mDataBlock->maxCrouchSideSpeed; else if (mPose == SprintPose) dirSpeed = mDataBlock->maxSprintSideSpeed; else dirSpeed = mDataBlock->maxSideSpeed; //Con::printf("side left 3.926-5.496; %f", yawDiff); } else { if (mSwimming) dirSpeed = mDataBlock->maxUnderwaterBackwardSpeed; else if (mPose == CrouchPose) dirSpeed = mDataBlock->maxCrouchBackwardSpeed; else if (mPose == SprintPose) dirSpeed = mDataBlock->maxSprintBackwardSpeed; else dirSpeed = mDataBlock->maxBackwardSpeed; //Con::printf("back 2.356-5.496; %f", yawDiff); } moveSpeed = dirSpeed; } else { //move the first person standard movement here - yorks zRot.getColumn(0, &moveVec); moveVec *= (move->x * (mPose == SprintPose ? mDataBlock->sprintStrafeScale : 1.0f)); VectorF tv; zRot.getColumn(1, &tv); moveVec += tv * move->y; // Clamp water movement if (move->y > 0.0f) { if (mSwimming) moveSpeed = getMax(mDataBlock->maxUnderwaterForwardSpeed * move->y, mDataBlock->maxUnderwaterSideSpeed * mFabs(move->x)); else if (mPose == PronePose) moveSpeed = getMax(mDataBlock->maxProneForwardSpeed * move->y, mDataBlock->maxProneSideSpeed * mFabs(move->x)); else if (mPose == CrouchPose) moveSpeed = getMax(mDataBlock->maxCrouchForwardSpeed * move->y, mDataBlock->maxCrouchSideSpeed * mFabs(move->x)); else if (mPose == SprintPose) moveSpeed = getMax(mDataBlock->maxSprintForwardSpeed * move->y, mDataBlock->maxSprintSideSpeed * mFabs(move->x)); else // StandPose moveSpeed = getMax(mDataBlock->maxForwardSpeed * move->y, mDataBlock->maxSideSpeed * mFabs(move->x)); } else { if (mSwimming) moveSpeed = getMax(mDataBlock->maxUnderwaterBackwardSpeed * mFabs(move->y), mDataBlock->maxUnderwaterSideSpeed * mFabs(move->x)); else if (mPose == PronePose) moveSpeed = getMax(mDataBlock->maxProneBackwardSpeed * mFabs(move->y), mDataBlock->maxProneSideSpeed * mFabs(move->x)); else if (mPose == CrouchPose) moveSpeed = getMax(mDataBlock->maxCrouchBackwardSpeed * mFabs(move->y), mDataBlock->maxCrouchSideSpeed * mFabs(move->x)); else if (mPose == SprintPose) moveSpeed = getMax(mDataBlock->maxSprintBackwardSpeed * mFabs(move->y), mDataBlock->maxSprintSideSpeed * mFabs(move->x)); else // StandPose moveSpeed = getMax(mDataBlock->maxBackwardSpeed * mFabs(move->y), mDataBlock->maxSideSpeed * mFabs(move->x)); } } // Cancel any script driven animations if we are going to move. if (moveVec.x + moveVec.y + moveVec.z != 0.0f && (mActionAnimation.action >= PlayerData::NumTableActionAnims || mActionAnimation.action == PlayerData::LandAnim)) mActionAnimation.action = PlayerData::NullAnimation; } else { moveVec.set(0.0f, 0.0f, 0.0f); moveSpeed = 0.0f; } //... Hope this helps someone. Edited February 26, 2023 by Steve_Yorkshire Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.