Example #1
0
    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);
        }
    }
Example #3
0
    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);
    }
Example #4
0
 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);
        }
    }
Example #6
0
    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);
    }
Example #8
0
 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);
 }
Example #9
0
    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);
            }
        }
    }