📄 player.cc
字号:
moveSpeed *= 1.0f + m_fMoveRate;
if(mState == RunState)
moveSpeed *= mDataBlock->m_fRunRate + m_fRunRate;
#endif
// Cancel any script driven animations if we are going to move.
if (moveVec.x + moveVec.y + moveVec.z != 0 &&
(mActionAnimation.action >= PlayerData::NumTableActionAnims
|| mActionAnimation.action == PlayerData::LandAnim))
mActionAnimation.action = PlayerData::NullAnimation;
}
else
{
moveVec.set(0,0,0);
moveSpeed = 0;
}
#ifndef ENBABLE_RPG_COLLISION /// TGE_Collision
// Force a 0 move if there is no energy, and only drain
// move energy if we're moving.
VectorF pv;
if (mEnergy >= mDataBlock->minRunEnergy) {
if (moveSpeed)
mEnergy -= mDataBlock->runEnergyDrain;
pv = moveVec;
}
else
pv.set(0,0,0);
//计算与Run surface平行的速度分量
// Adjust the players's requested dir. to be parallel
// to the contact surface.
F32 pvl = pv.len();
if (pvl) {
VectorF nn;
mCross(pv,VectorF(0,0,1),&nn);
nn *= 1 / pvl;
VectorF cv(0,0,1);
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}
// Convert to acceleration
if (pvl)
{
pv *= moveSpeed / pvl;
/// updatePos中加入canWalkAt检测地形的障碍标志,决定人物是否能行走
/// 不检测人物所在坐标的障碍(这样人物行走时,将在所在坐标标志为人物障碍)
/// TGE_PlayerAnim,检测障碍,如果有障碍将速度至0
if(g_pTerrainBlock)
{
Point3F ptPos,ptOrigin;
getTransform().getColumn(3,&ptOrigin);
ptPos = ptOrigin + pv*TickSec;
ptOrigin.x = mFloor(ptOrigin.x);
ptOrigin.y = mFloor(ptOrigin.y);
ptOrigin.z = 0;
ptPos.x = mFloor(ptPos.x);
ptPos.y = mFloor(ptPos.y);
ptPos.z = 0;
if(m_ptOriginBak != ptOrigin && m_ptOriginBak.z == 0)
g_pTerrainBlock->setSelfBlockAt(m_ptOriginBak.x,m_ptOriginBak.y,false);
g_pTerrainBlock->setSelfBlockAt(ptOrigin.x,ptOrigin.y,true);
m_ptOriginBak = ptOrigin;
/// 不检测人物所在坐标的障碍
if(ptOrigin != ptPos && !g_pTerrainBlock->canWalkAt(ptPos.x,ptPos.y))
pv.set(0,0,0);
}
}
mVelocity = pv;
#else
// Acceleration due to gravity
/// 计算重力加速度
VectorF acc(0,0,mGravity * mGravityMod * TickSec);
// Determine ground contact normal. Only look for contacts if
// we can move.
/// 计算移动潜在的地面接触法线,
VectorF contactNormal;
bool jumpSurface = false, runSurface = false;
if (!isMounted())
findContact(&runSurface,&jumpSurface,&contactNormal);
if (jumpSurface)
mJumpSurfaceNormal = contactNormal;
// Acceleration on run surface
if (runSurface)
{
mContactTimer = 0;
/// 消除进入接触面的加速度分量
// Remove acc into contact surface (should only be gravity)
// Clear out floating point acc errors, this will allow
// the player to "rest" on the ground.
F32 vd = -mDot(acc,contactNormal);
if (vd > 0) {
VectorF dv = contactNormal * (vd + 0.002);
acc += dv;
if (acc.len() < 0.0001)
acc.set(0,0,0);
}
// Force a 0 move if there is no energy, and only drain
// move energy if we're moving.
VectorF pv;
if (mEnergy >= mDataBlock->minRunEnergy) {
if (moveSpeed)
mEnergy -= mDataBlock->runEnergyDrain;
pv = moveVec;
}
else
pv.set(0,0,0);
//计算与Run surface平行的速度分量
// Adjust the players's requested dir. to be parallel
// to the contact surface.
F32 pvl = pv.len();
if (pvl) {
VectorF nn;
mCross(pv,VectorF(0,0,1),&nn);
nn *= 1 / pvl;
VectorF cv = contactNormal;
cv -= nn * mDot(nn,cv);
pv -= cv * mDot(pv,cv);
pvl = pv.len();
}
// Convert to acceleration
if (pvl)
pv *= moveSpeed / pvl;
VectorF runAcc = pv - (mVelocity + acc);
F32 runSpeed = runAcc.len();
// Clamp acceleratin, player also accelerates faster when
// in his hard landing recover state.
F32 maxAcc = (mDataBlock->runForce / mMass) * TickSec;
if (mState == RecoverState)
maxAcc *= mDataBlock->recoverRunForceScale;
if (runSpeed > maxAcc)
runAcc *= maxAcc / runSpeed;
acc += runAcc;
// If we are running on the ground, then we're not jumping
if (mDataBlock->isJumpAction(mActionAnimation.action))
mActionAnimation.action = PlayerData::NullAnimation;
}
else
mContactTimer++;
/// 计算跳跃加速度
// Acceleration from Jumping
if (move->trigger[2] && !isMounted() && canJump())
{
// Scale the jump impulse base on maxJumpSpeed
F32 zSpeedScale = mVelocity.z;
if (zSpeedScale <= mDataBlock->maxJumpSpeed)
{
zSpeedScale = (zSpeedScale <= mDataBlock->minJumpSpeed)? 1:
1 - (zSpeedScale - mDataBlock->minJumpSpeed) /
(mDataBlock->maxJumpSpeed - mDataBlock->minJumpSpeed);
// Desired jump direction
VectorF pv = moveVec;
F32 len = pv.len();
if (len > 0)
pv *= 1 / len;
// We want to scale the jump size by the player size, somewhat
// in reduced ratio so a smaller player can jump higher in
// proportion to his size, than a larger player.
F32 scaleZ = (getScale().z * 0.25) + 0.75;
// If we are facing into the surface jump up, otherwise
// jump away from surface.
F32 dot = mDot(pv,mJumpSurfaceNormal);
F32 impulse = mDataBlock->jumpForce / mMass;
if (dot <= 0)
acc.z += mJumpSurfaceNormal.z * scaleZ * impulse * zSpeedScale;
else
{
acc.x += pv.x * impulse * dot;
acc.y += pv.y * impulse * dot;
acc.z += mJumpSurfaceNormal.z * scaleZ * impulse * zSpeedScale;
}
mJumpDelay = mDataBlock->jumpDelay;
mEnergy -= mDataBlock->jumpEnergyDrain;
setActionThread((mVelocity.len() < 0.5)?
PlayerData::StandJumpAnim: PlayerData::JumpAnim, true, false, true);
mJumpSurfaceLastContact = JumpSkipContactsMax;
}
}
else
if (jumpSurface) {
if (mJumpDelay > 0)
mJumpDelay--;
mJumpSurfaceLastContact = 0;
}
else
mJumpSurfaceLastContact++;
// Add in force from physical zones...
acc += (mAppliedForce / mMass) * TickSec;
// Adjust velocity with all the move & gravity acceleration
// TG: I forgot why doesn't the TickSec multiply happen here...
mVelocity += acc;
// apply horizontal air resistance
// 空气阻力处理
F32 hvel = mSqrt(mVelocity.x * mVelocity.x + mVelocity.y * mVelocity.y);
if(hvel > mDataBlock->horizResistSpeed)
{
F32 speedCap = hvel;
if(speedCap > mDataBlock->horizMaxSpeed)
speedCap = mDataBlock->horizMaxSpeed;
speedCap -= mDataBlock->horizResistFactor * TickSec * (speedCap - mDataBlock->horizResistSpeed);
F32 scale = speedCap / hvel;
mVelocity.x *= scale;
mVelocity.y *= scale;
}
if(mVelocity.z > mDataBlock->upResistSpeed)
{
if(mVelocity.z > mDataBlock->upMaxSpeed)
mVelocity.z = mDataBlock->upMaxSpeed;
mVelocity.z -= mDataBlock->upResistFactor * TickSec * (mVelocity.z - mDataBlock->upResistSpeed);
}
// Container buoyancy & drag
// 浮力、拖拉力处理
if (mBuoyancy != 0)
{ // Applying buoyancy when standing still causing some jitters-
if (mBuoyancy > 1.0 || !mVelocity.isZero() || !runSurface)
mVelocity.z -= mBuoyancy * mGravity * mGravityMod * TickSec;
}
mVelocity -= mVelocity * mDrag * TickSec;
//下降处理,如果未接触到任何物件,或-z超过指定阀值时,将视为下降
// If we are not touching anything and have sufficient -z vel,
// we are falling.
if (runSurface)
mFalling = false;
else {
VectorF vel;
mWorldToObj.mulV(mVelocity,&vel);
mFalling = vel.z < sFallingThreshold;
}
#endif // #ifdef ENBABLE_RPG_COLLISION /// TGE_Collision
#ifdef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
// Vehicle Dismount
if(move->trigger[2] && isMounted())
Con::executef(mDataBlock,2,"doDismount",scriptThis());
if(!inLiquid && mWaterCoverage != 0.0f) {
Con::executef(mDataBlock,4,"onEnterLiquid",scriptThis(), Con::getFloatArg(mWaterCoverage), Con::getIntArg(mLiquidType));
//inLiquid = true;
}
else if(inLiquid && mWaterCoverage == 0.0f) {
Con::executef(mDataBlock,3,"onLeaveLiquid",scriptThis(), Con::getIntArg(mLiquidType));
inLiquid = false;
}
if(!inLiquid && mWaterCoverage >= 1.0f) {
inLiquid = true;
}
else if(inLiquid && mWaterCoverage < 0.8f) {
if(getVelocity().len() >= mDataBlock->exitSplashSoundVel && !isMounted())
alxPlay(mDataBlock->sound[PlayerData::ExitWater], &getTransform());
//inLiquid = false;
}
#else
if (!isGhost()) {
// Vehicle Dismount
if(move->trigger[2] && isMounted())
Con::executef(mDataBlock,2,"doDismount",scriptThis());
if(!inLiquid && mWaterCoverage != 0.0f) {
Con::executef(mDataBlock,4,"onEnterLiquid",scriptThis(), Con::getFloatArg(mWaterCoverage), Con::getIntArg(mLiquidType));
inLiquid = true;
}
else if(inLiquid && mWaterCoverage == 0.0f) {
Con::executef(mDataBlock,3,"onLeaveLiquid",scriptThis(), Con::getIntArg(mLiquidType));
inLiquid = false;
}
}
else {
if(!inLiquid && mWaterCoverage >= 1.0f) {
inLiquid = true;
}
else if(inLiquid && mWaterCoverage < 0.8f) {
if(getVelocity().len() >= mDataBlock->exitSplashSoundVel && !isMounted())
alxPlay(mDataBlock->sound[PlayerData::ExitWater], &getTransform());
inLiquid = false;
}
}
#endif
}
//----------------------------------------------------------------------------
bool Player::checkDismountPosition(const MatrixF& oldMat, const MatrixF& mat)
{
AssertFatal(getContainer() != NULL, "Error, must have a container!");
AssertFatal(getObjectMount() != NULL, "Error, must be mounted!");
Point3F pos;
Point3F oldPos;
mat.getColumn(3, &pos);
oldMat.getColumn(3, &oldPos);
RayInfo info;
disableCollision();
getObjectMount()->disableCollision();
if (getContainer()->castRay(oldPos, pos, sCollisionMoveMask, &info))
{
enableCollision();
getObjectMount()->enableCollision();
return false;
}
Box3F wBox = mObjBox;
wBox.min += pos;
wBox.max += pos;
EarlyOutPolyList polyList;
polyList.mNormal.set(0,0,0);
polyList.mPlaneList.clear();
polyList.mPlaneList.setSize(6);
polyList.mPlaneList[0].set(wBox.min,VectorF(-1,0,0));
polyList.mPlaneList[1].set(wBox.max,VectorF(0,1,0));
polyList.mPlaneList[2].set(wBox.max,VectorF(1,0,0));
polyList.mPlaneList[3].set(wBox.min,VectorF(0,-1,0));
polyList.mPlaneList[4].set(wBox.min,VectorF(0,0,-1));
polyList.mPlaneList[5].set(wBox.max,VectorF(0,0,1));
if (getContainer()->buildPolyList(wBox, sCollisionMoveMask, &polyList))
{
enableCollision();
getObjectMount()->enableCollision();
return false;
}
enableCollision();
getObjectMount()->enableCollision();
return true;
}
//----------------------------------------------------------------------------
bool Player::canJump()
{
/// TGE_PlayerAnim
return (mState == WalkState || mState == RunState) && mDamageState == Enabled && !isMounted() && !mJumpDelay && mEnergy >= mDataBlock->minJumpEnergy && mJumpSurfaceLastContact < JumpSkipContactsMax;
//return mState == MoveState && mDamageState == Enabled && !isMounted() && !mJumpDelay && mEnergy >= mDataBlock->minJumpEnergy && mJumpSurfaceLastContact < JumpSkipContactsMax;
}
//----------------------------------------------------------------------------
void Player::updateDamageLevel()
{
#ifndef TGE_RPGCLIENT2 /// TGE_RPGIsClientObject
if (!isGhost())
setDamageState((mDamage >= mDataBlock->maxDamage)? Disabled: Enabled);
#endif
if (mDamageThread)
mShapeInstance->setPos(mDamageTh
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -