Steve_Yorkshire Posted February 25, 2023 Share Posted February 25, 2023 (edited) Disclaimer: I haven't actually played GTA or Elden Ring so I've never actually experienced the camera and movement control system. But anyway - here's what I think it's like (probably). UPDATE: this camera and movement style is really more relevant to a 3rd person shooter. This is a movement test based on third person camera direction, kind of like what I did top-down for Monsters Loot Swag but the camera remains fixed to the player rather than being independant - because of that I had apply inverse rotation to the camera when the player moved and turned to face the camera's original vector. Horizontal camera rotation wraps around -/+M_PI_F rather than being constrained by the stock engine's playerDatablock maxFreeLook value, this means that the camera can loop seamlessly around the player using z axis but is still constrained to maximums when looking up and down, so it doesn't flip upside-down. Code: Player.cpp, in UpdateMove(const Move* move) void Player::updateMove(const Move* 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) { F32 prevZRot = mRot.z; mDelta.headVec = mHead; bool doStandardMove = true; bool absoluteDelta = false; //GameConnection* con = getControllingClient();//yorks out and moved above so we can get this below too #ifdef TORQUE_EXTENDED_MOVE //... 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); 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())))//out if (thirdP)//from above { //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 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); } else {//yorks end block mHead.x = mClampF(mHead.x + p, mDataBlock->minLookAngle, mDataBlock->maxLookAngle);//yorks moved down here for normal cam/move mode 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; }//yorks added // constrain the range of mRot.z while (mRot.z < 0.0f) mRot.z += M_2PI_F; while (mRot.z > M_2PI_F) mRot.z -= M_2PI_F; } //... if ((mState == MoveState || (mState == RecoverState && mDataBlock->recoverRunForceScale > 0.0f)) && mDamageState == Enabled && !isAnimationLocked()) { if (thirdP)//yorks start big in { 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))) { //we are moving and so should turn the player towards the direction that the camera is facing 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 yawDiff = camZ - tran; //Con::printf("camToDir %f; tran %f; yawDiff %f", dir, 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)) { //Con::printf("yawDiff %f", 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 otherwise it's instantaneous 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 } } } }//yorks end big in 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) //... And there you go, that should be it. In 3rd person view and ONLY 3rd person view you can rotate the camera horizontally around the player without it stopping at maxLook and movement is tied to the camera view, so that the player will reorientate himself to that when moving. This could be expanded by adding a lock-on feature to have the camera point constantly at the selected enemy, and also maybe add a toggle that allows the player to move relative to the camera but without turning to face the camera's vector. Hope this helps some folks. Edited February 26, 2023 by Steve_Yorkshire Quote Link to comment Share on other sites More sharing options...
Duion Posted February 25, 2023 Share Posted February 25, 2023 Games with third person view usually do not let you look around freely by default, the camera is more or less locked in place. Some games have like a delay where the camera gradually follows the movement direction, or moves around a little, so it feels more like a free view. Playing with an actually fully free view can get very confusing. You should play some games with it for reference or look at lets play videos. I have not played Elden Ring but from a lets play video it seems like free view but the camera automatically slowly assigns itself again to the player direction, but from just watching it you cannot fully tell how it actually works, what is manual and what automatic. I played GTA however and the third person is usually fixed, but there is a freeview feature for when you are in a vehicle, because in a drive by shooting your drive in one direction but look and shoot in another direction, which is where the free view comes in. In your case I think your top down game would benefit from some slight variations of the camera angle to show off that it is all fully 3D. Quote Link to comment Share on other sites More sharing options...
fLUnKnhaXYU Posted February 25, 2023 Share Posted February 25, 2023 thank you Steve , Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â I think that's pretty neat and I'm wondering how it behaves while controlling a vehicle . 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.