public override void update(float elaspedTime) { if (!MathUtility.isFloatEqual(mData.mSpeed, mTargetSpeed)) { if (!MathUtility.isFloatEqual(mNormalAcceleration, mAcceleration)) { mAcceleration = MathUtility.lerp(mAcceleration, mNormalAcceleration, mAccelerationFactor * elaspedTime); } // 当前速度逐渐向目标速度靠近 float speed = MathUtility.lerp(mData.mSpeed, mTargetSpeed, mAcceleration * elaspedTime); // 小于最小间隔时直接设置为目标速度 if ((Mathf.Abs(speed - mTargetSpeed) < mMinDeltaSpeed)) { speed = mTargetSpeed; } // 如果速度降到了0(小于0.01则认为是0),并且角色当前正在跑动,则通知角色停下 if (MathUtility.isFloatZero(speed, 0.01f) && mCharacter.hasState(PLAYER_STATE.PS_RIDING)) { pushCommand <CommandCharacterStop>(mCharacter); } // 速度不为0,并且角色当前正处于休闲状态,则通知角色跑动 else if (speed > 0.0f && mCharacter.hasState(PLAYER_STATE.PS_IDLE)) { pushCommand <CommandCharacterStartRun>(mCharacter); } // 加速 else if (speed > mData.mSpeed) { CommandCharacterSpeedUp cmdSpeedUp = newCmd(out cmdSpeedUp, false); cmdSpeedUp.mSpeed = speed; cmdSpeedUp.mSpeedDelta = speed - mData.mSpeed; pushCommand(cmdSpeedUp, mCharacter); } // 减速 else if (speed < mData.mSpeed) { CommandCharacterSpeedSlow cmdSpeedSlow = newCmd(out cmdSpeedSlow, false); cmdSpeedSlow.mSpeed = speed; pushCommand(cmdSpeedSlow, mCharacter); } // 改变速度 CommandCharacterChangeSpeed cmd = newCmd(out cmd, false); cmd.mSpeed = speed; pushCommand(cmd, mCharacter); } base.update(elaspedTime); }
public override void execute() { Character character = mReceiver as Character; CharacterOther player = character as CharacterOther; if (player == null) { return; } // 移除瞄准状态 if (player.hasState(PLAYER_STATE.PS_AIM)) { CommandCharacterRemoveState cmdState = newCmd(out cmdState); cmdState.mState = PLAYER_STATE.PS_AIM; pushCommand(cmdState, character); } PlayerPack pack = player.getPlayerPack(); int nextNotNullIndex = mIndex != -1 ? mIndex : pack.getNextNotEmptyIndex(); if (nextNotNullIndex == -1) { return; } pack.setItemIndex(nextNotNullIndex); // 通知布局 if (player.isType(CHARACTER_TYPE.CT_MYSELF)) { mScriptProps.showIndex(nextNotNullIndex); } }
public override void use(CharacterOther player) { // 如果已经在瞄准状态中,则不能使用 if (player.hasState(PLAYER_STATE.PS_AIM)) { return; } // 给角色添加瞄准状态 CommandCharacterAddState cmdCharacterAddState = newCmd(out cmdCharacterAddState); cmdCharacterAddState.mState = PLAYER_STATE.PS_AIM; pushCommand(cmdCharacterAddState, player); }
public void OnTriggerEnter(Collider other) { // 角色之间的碰撞 if (other.gameObject.layer == GameUtility.mCharacterLayer) { CharacterOther otherPlayer = GameBase.mCharacterManager.getCharacter(other.name) as CharacterOther; GameBase.mRaceSystem.addCollidePair(mPlayer, otherPlayer); } // 接触起跳点 else if (other.gameObject.layer == GameUtility.mJumpPointLayer && mPlayer.hasState(PLAYER_STATE.PS_GAMING)) { CommandCharacterJump cmdJump = GameBase.newCmd(out cmdJump); cmdJump.mJumpSpeed = GameDefine.JUMP_SPEED; GameBase.pushCommand(cmdJump, mPlayer); } }
public override void execute() { Character character = mReceiver as Character; if (!character.isType(CHARACTER_TYPE.CT_OTHER)) { return; } CharacterOther other = character as CharacterOther; // 玩家有护盾时,攻击没有任何影响 if (other.hasState(PLAYER_STATE.PS_PROTECTED)) { return; } if (mAttackSource == SCENE_ITEM.SI_LAND_MINE || mAttackSource == SCENE_ITEM.SI_MISSILE) { // 进入被攻击状态 CommandCharacterAddState cmdState = newCmd(out cmdState); cmdState.mState = PLAYER_STATE.PS_ATTACKED; pushCommand(cmdState, other); // 设置角色的速度,当角色速度小于3km/h时,则不变,否则速度设置为3km/h CommandCharacterChangeSpeed cmd = newCmd(out cmd, false); cmd.mSpeed = Mathf.Min(MathUtility.KMHtoMS(3.0f), other.getCharacterData().mSpeed); pushCommand(cmd, other); // 播放摔倒动作 Animation animation = other.getAnimation(); animation.CrossFade(GameDefine.ANIM_FALL_DOWN); // 当速度为0时,摔到后为站立状态,否则开始骑行 if (other.getCharacterData().mSpeed <= 0.01f) { animation.CrossFadeQueued(GameDefine.ANIM_STANDING); } else { animation.CrossFadeQueued(GameDefine.ANIM_RIDE); } // 同时需要降低硬件速度组件中从当前速度加速到目标速度的快慢 CharacterSpeedHardware speedHardware = other.getFirstComponent <CharacterSpeedHardware>(); speedHardware.setAcceleration(0.0f); } }
public override void execute() { StartScene gameScene = (mReceiver) as StartScene; if (gameScene.atProcedure(PROCEDURE_TYPE.PT_START_SELECT_ROLE)) { CharacterOther curRole = mRoleSystem.getSelectedRole(); // 当前角色有SELECT_ROLE状态组,如果没有,则说明是第一次进入选人流程 if (curRole != null && curRole.hasStateGroup(STATE_GROUP.SG_SELECT)) { // 当前角色显示完毕时才能切换角色,也不能选择相同的角色 if (!curRole.hasState(PLAYER_STATE.PS_SELECTED_ROLE) || mRoleSystem.getSelectedIndex() == mIndex) { return; } // 取消当前角色的选中 CommandCharacterAddState cmdUnSelect = newCmd(out cmdUnSelect); cmdUnSelect.mState = PLAYER_STATE.PS_UN_SELECT_ROLE; pushCommand(cmdUnSelect, curRole); } // 启动选择的角色 mRoleSystem.setSelectedIndex(mIndex); CharacterOther character = mRoleSystem.getSelectedRole(); if (character != null) { CommandCharacterAddState cmdSelect = newCmd(out cmdSelect); cmdSelect.mState = PLAYER_STATE.PS_ON_SELECT_ROLE; pushCommand(cmdSelect, character); // 通知布局 mScriptSelectRole.selectRole(mIndex); if (mPlayAudio) { GameTools.PLAY_AUDIO_UI(mScriptGlobalAudio.getAudioWindow(), SOUND_DEFINE.SD_SELECTION_CHANGE); } } } }
public override void update(float elapsedTime) { // 转向判断 float turnAngle = 0.0f; if (mCharacter.getProcessTurn()) { turnAngle = mData.mTurnAngle; // 只有转向角度增加时才会判断转弯 if (Mathf.Abs(turnAngle) > Mathf.Abs(mLastTurnAngle) && Mathf.Abs(turnAngle) >= GameDefine.TURN_ANGLE) { CommandCharacterTurn cmdTurn = newCmd(out cmdTurn, false); cmdTurn.mAngle = turnAngle; pushCommand(cmdTurn, mCharacter); } mLastTurnAngle = turnAngle; } // 方向 if (!MathUtility.isFloatZero(turnAngle)) { float angleDelta = turnAngle * elapsedTime * mData.mTurnSensitive; // 一帧的旋转角度不能太大 MathUtility.clamp(ref angleDelta, -GameDefine.MAX_REFLECT_ANGLE, GameDefine.MAX_REFLECT_ANGLE); mData.mSpeedRotation.y += angleDelta; } // 根据运动方向调整角色朝向 mCharacter.setYaw(mData.mSpeedRotation.y); // 位置 Vector3 moveDir = MathUtility.getVectorFromAngle(mData.mSpeedRotation.y * Mathf.Deg2Rad); Vector3 lastPosition = mCharacter.getPosition(); if (!MathUtility.isFloatZero(mData.mSpeed) || !MathUtility.isFloatZero(mData.mVerticalSpeed)) { Vector3 delta = (moveDir * mData.mSpeed + Vector3.up * mData.mVerticalSpeed) * elapsedTime; mCharacter.setPosition(lastPosition + delta); } // 检测前方是否有墙,多次检测确保角色不会穿透墙壁,最多只检测3次,避免在极端情况出现无线循环的现象 const int HIT_WALL_TEST_COUNT = 3; for (int i = 0; i < HIT_WALL_TEST_COUNT; ++i) { // 计算与墙面的碰撞 // 从运动之前的位置向运动方向发射一条射线 Vector3 faceDir = MathUtility.getDirectionFromDegreeYawPitch(mData.mSpeedRotation.y, mCharacter.getRotation().x); Ray dirRay = new Ray(lastPosition, faceDir); #if UNITY_EDITOR Debug.DrawLine(dirRay.origin, dirRay.origin + dirRay.direction * 10.0f, Color.red); #endif RaycastHit dirRet; bool hitWall = false; if (Physics.Raycast(dirRay, out dirRet, 1000.0f, 1 << GameUtility.mWallLayer)) { float wallDis = MathUtility.getLength(dirRet.point - lastPosition); // 减去上一次的位置与当前位置的差值后,如果小于单车前半部分的长度则认为是碰到了墙,计算出反弹方向 if (wallDis - MathUtility.getLength(lastPosition - mCharacter.getPosition()) < GameDefine.BIKE_FRONT_LENGTH) { Vector3 newDir = MathUtility.getReflection(faceDir, dirRet.normal); float reflectAngle = MathUtility.getAngleBetweenVector(newDir, dirRet.normal) * Mathf.Rad2Deg; // 反射角需要限定到一定范围 if (reflectAngle < GameDefine.MIN_REFLECT_ANGLE || reflectAngle > GameDefine.MAX_REFLECT_ANGLE) { MathUtility.clamp(ref reflectAngle, GameDefine.MIN_REFLECT_ANGLE, GameDefine.MAX_REFLECT_ANGLE); // 如果法线与反射方向相同,也就是垂直撞墙,则反射角默认为正 // 否则通过叉乘的结果来判断反射角的符号 if (!MathUtility.isVectorZero(MathUtility.normalize(newDir) - MathUtility.normalize(dirRet.normal))) { Vector3 cross = MathUtility.normalize(Vector3.Cross(newDir, dirRet.normal)); if (cross.y > 0.0f) { reflectAngle = -reflectAngle; } } Quaternion quat = new Quaternion(); quat.eulerAngles = new Vector3(0.0f, reflectAngle, 0.0f); newDir = MathUtility.rotateVector3(dirRet.normal, quat); } // 碰撞墙壁后将摄像机的跟随速度减慢 if (mCharacter.isType(CHARACTER_TYPE.CT_MYSELF)) { CameraLinkerSmoothFollow smoothFollow = mCameraManager.getMainCamera().getCurLinker() as CameraLinkerSmoothFollow; smoothFollow.setFollowPositionSpeed(1.0f); } mData.mSpeedRotation.y = MathUtility.getVectorYaw(newDir) * Mathf.Rad2Deg; // 此处仍然同步设置角色的旋转,暂时保证速度方向与角色的旋转值一致 mCharacter.setYaw(mData.mSpeedRotation.y); // 根据碰撞的入射角度,计算出速度损失量 float inAngle = MathUtility.getAngleBetweenVector(-faceDir, dirRet.normal) * Mathf.Rad2Deg; CommandCharacterHitWall cmdHitWall = newCmd(out cmdHitWall, false); cmdHitWall.mAngle = inAngle; pushCommand(cmdHitWall, mCharacter); hitWall = true; } } // 已经没有接触墙壁,则退出循环 if (!hitWall) { break; } } // 调整自身位置 correctTransform(elapsedTime); // 在地面上时,根据自身的旋转值,判断地面的坡度,计算当前阻力值 if (!mCharacter.hasState(PLAYER_STATE.PS_JUMP) && mCharacter.isType(CHARACTER_TYPE.CT_MYSELF)) { float pitch = mCharacter.getPitch(); MathUtility.adjustAngle180(ref pitch); float friction = -1.0f; // 先将俯仰角限制在一定范围内 MathUtility.clamp(ref pitch, mMaxUphillAngle, mMaxDownhillAngle); // 判断是否在正常范围内 if (MathUtility.isInRange(pitch, mMinUphillAngle, mMinDownhillAngle)) { friction = mNormalFriction; } // 是否为上坡,当角度为负时为上坡 else if (pitch < mMinUphillAngle) { float percent = (pitch - mMinUphillAngle) / (mMaxUphillAngle - mMinUphillAngle); friction = MathUtility.lerp(mMinUphillFriction, mMaxUphillFriction, percent); } else if (pitch > mMinDownhillAngle) { float percent = (pitch - mMinDownhillAngle) / (mMaxDownhillAngle - mMinDownhillAngle); friction = MathUtility.lerp(mMinDownhillFriction, mMaxDownhillFriction, percent); } if (mCurFriction != (int)friction) { mCurFriction = (int)friction; SerialPortPacketFriction packet = mUSBManager.createPacket(out packet, COM_PACKET.CP_FRICTION); packet.setFriction((byte)mCurFriction); mUSBManager.sendPacket(packet); if (mCharacter.isType(CHARACTER_TYPE.CT_MYSELF)) { mScriptDebugInfo.notityFriction(mCurFriction); } } if (mCharacter.isType(CHARACTER_TYPE.CT_MYSELF)) { mScriptDebugInfo.notityPitch(pitch); } } base.update(elapsedTime); }
public override void update(float elapsedTime) { if (mData.mSpeed > 0.0f) { // 判断当前方向是否合法 bool wrongDirection = directionCheck(); // 圈数检测,更新当前移动距离,反向检测,完成比赛检测 if (!wrongDirection) { int curPointIndex = mData.mCurWayPoint; float runDistance = mWayPointManager.getRunDistance(mCharacter.getPosition(), ref curPointIndex, curPointIndex); if (!mPassedPointList.Contains(curPointIndex)) { mPassedPointList.Add(curPointIndex); } // 防止在游戏开始后 后退到终点线之前 导致已过路点添加错误 最后圈数检测错误 if (runDistance >= mWayPointManager.getTotalLength() / 2 && mPassedPointList.Count <= mWayPointManager.getPointCount() / 3) { mPassedPointList.Clear(); } // 已经进入下一圈,并且上一次经过的是当前圈的最后一个路段,当前正处于第0个路段,并且已经完成了当前圈一半以上的路段 if (runDistance > 0.0f && curPointIndex == 0 && mPassedPointList[mPassedPointList.Count - 1] == mWayPointManager.getPointCount() - 1 && mPassedPointList.Count >= mWayPointManager.getPointCount() / 2) { // 圈数改变 mPassedPointList.Clear(); CommandCharacterCircleChanged cmdCircle = newCmd(out cmdCircle); cmdCircle.mCircle = mData.mCircle + 1; pushCommand(cmdCircle, mCharacter); } // 如果已经跑完比赛了,则将距离和路点清零 if (mCharacter.hasState(PLAYER_STATE.PS_FINISH)) { curPointIndex = 0; runDistance = 0.0f; } // 里程改变,必须在更新圈数后才能更新里程,因为计算里程会使用圈数 CommandCharacterDistanceChanged cmdDistance = newCmd(out cmdDistance, false); cmdDistance.mWayPoint = curPointIndex; cmdDistance.mDistance = runDistance; pushCommand(cmdDistance, mCharacter); mWrongDirectionTime = 0.0f; //方向正确后退出游戏中的错误方向状态 if (mCharacter.hasState(PLAYER_STATE.PT_WRONG_DIRECTION)) { CommandCharacterRemoveState cmdRemoveState = newCmd(out cmdRemoveState); cmdRemoveState.mState = PLAYER_STATE.PT_WRONG_DIRECTION; pushCommand(cmdRemoveState, mCharacter); } } else { if (!mCharacter.hasState(PLAYER_STATE.PT_WRONG_DIRECTION)) { mWrongDirectionTime += elapsedTime; if (mWrongDirectionTime >= GameDefine.WRONG_DIRECTION_TIPS_TIME) { CommandCharacterAddState cmdState = newCmd(out cmdState); cmdState.mState = PLAYER_STATE.PT_WRONG_DIRECTION; pushCommand(cmdState, mCharacter); mWrongDirectionTime = 0.0f; } } } } base.update(elapsedTime); }
public override void update(float elapsedTime) { base.update(elapsedTime); int targetIndex = mWayPointManager.getPointIndexFromDistance(mData.mRunDistance + mTargetDistanceOffset, mData.mCurWayPoint); float targetDirection = mWayPointManager.getPointDirection(targetIndex); // 自身的朝向往目标点所在路段的朝向靠拢 float curDirection = mCharacter.getRotation().y; MathUtility.adjustAngle180(ref curDirection); float dirDelta = targetDirection - curDirection; // 如果目标方向与当前方向的差值超过180,则转换到0-360再计算 if (Mathf.Abs(dirDelta) > 180.0f) { MathUtility.adjustAngle360(ref curDirection); MathUtility.adjustAngle360(ref targetDirection); dirDelta = targetDirection - curDirection; } mData.mTurnAngle = MathUtility.lerp(mData.mTurnAngle, dirDelta, 0.1f); float curTargetSpeed = mAIBaseSpeed + mData.mNumber; CharacterSpeedHardware speedHardware = mCharacter.getFirstComponent <CharacterSpeedHardware>(); if (!MathUtility.isFloatEqual(speedHardware.getTargetSpeed(), curTargetSpeed) && mCharacter.getProcessExternalSpeed()) { CommandCharacterHardwareSpeed cmd = newCmd(out cmd); cmd.mSpeed = curTargetSpeed; cmd.mExternalSpeed = true; pushCommand(cmd, mCharacter); } // 如果AI背包中有导弹,则一直搜寻可以瞄准的目标 int missileIndex = mCharacter.getPlayerPack().getFirstItemIndex(PLAYER_ITEM.PI_MISSILE); if (missileIndex != -1 && !mCharacter.hasState(PLAYER_STATE.PS_AIM)) { bool hasAvailableTarget = false; SortedDictionary <int, CharacterOther> allCharacterList = mRoleSystem.getAllPlayer(); float playerDistance = mCharacter.getCharacterData().mRunDistance; foreach (var item in allCharacterList) { if (item.Value != mCharacter) { float curDistance = item.Value.getCharacterData().mRunDistance - playerDistance; if (MathUtility.isInRange(curDistance, 0.0f, GameDefine.MAX_LAUNCH_MISSILE_DISTANCE)) { if (UnityUtility.whetherGameObjectInScreen(item.Value.getWorldPosition())) { hasAvailableTarget = true; break; } } } } if (hasAvailableTarget) { // 需要选中导弹 CommandCharacterSelectItem cmdSelect = newCmd(out cmdSelect); cmdSelect.mIndex = missileIndex; pushCommand(cmdSelect, mCharacter); // 给角色添加瞄准状态 CommandCharacterAddState cmdCharacterAddState = newCmd(out cmdCharacterAddState); cmdCharacterAddState.mState = PLAYER_STATE.PS_AIM; pushCommand(cmdCharacterAddState, mCharacter); } } }