コード例 #1
0
    private void performAnimations(TankStateInfo tankStateInfo)
    {
        string leftWheelStateName = Mathf.Sign(tankStateInfo.LeftCurPower) > 0 ? "WheelForward" : "WheelBackward";

        if (tankStateInfo.LeftCurPower == 0)
        {
            leftWheelStateName = "WheelIdle";
        }
        Animator leftAnimator = tankGOConstructor.LeftWheelGO.GetComponent <Animator>();

        if (!leftAnimator.GetCurrentAnimatorStateInfo(0).IsName(leftWheelStateName))
        {
            leftAnimator.Play(leftWheelStateName);
        }

        string rightWheelStateName = Mathf.Sign(tankStateInfo.RightCurPower) > 0 ? "WheelForward" : "WheelBackward";

        if (tankStateInfo.RightCurPower == 0)
        {
            rightWheelStateName = "WheelIdle";
        }
        Animator rightAnimator = tankGOConstructor.RightWheelGO.GetComponent <Animator>();

        if (!rightAnimator.GetCurrentAnimatorStateInfo(0).IsName(rightWheelStateName))
        {
            rightAnimator.Play(leftWheelStateName);
        }
    }
コード例 #2
0
    public static bool IsInOpponentFireVec(TankStateInfo selfTank, TankStateInfo oppTank, List <WeaponPart> oppWeapons)
    {
        bool canBeHit = false;

        foreach (WeaponPart weapon in oppWeapons)
        {
            if (weapon.CalcTimeToReloaded() > 0.25f)
            {
                continue;
            }

            Vector2 targetPos     = selfTank.Pos;
            Vector2 curFireVec    = weapon.CalculateFireVec();
            Ray     ray           = new Ray(weapon.CalculateFirePos(), curFireVec);
            float   shortestDist  = Vector3.Cross(ray.direction, (Vector3)(targetPos) - ray.origin).magnitude;
            bool    canHitIfFired = shortestDist < oppTank.Size.x;

            Vector2 targetVec = targetPos - weapon.CalculateFirePos();

            bool fireVecFacingTarget = Vector2.Angle(curFireVec, targetVec) < 90f;
            bool inRange             = targetVec.magnitude < weapon.Schematic.Range;
            if (inRange && canHitIfFired && fireVecFacingTarget)
            {
                canBeHit = true;
                break;
            }
        }

        return(canBeHit);
    }
コード例 #3
0
    public static float CalcTimeToHitPos(Vector2 curPos, Vector2 curFireVec, TankStateInfo aimingTankInfo, WeaponPartSchematic schematic, Vector2 targetPos)
    {
        float timeToHit = 0;

        Vector2 diffVec = targetPos - curPos;

        // We have to calculate three things: rotation time, travel time to in range, and bullet travel time.

        // First calculate rotation time.
        timeToHit += aimingTankInfo.CalcTimeToRotate(curFireVec, diffVec);

        // Next, calculate travel time.
        float moveAmount = Mathf.Max(diffVec.magnitude - schematic.Range, 0);

        if (moveAmount > 0)
        {
            Vector2 newPos = diffVec.normalized * moveAmount + curPos;
            timeToHit += aimingTankInfo.CalcTimeToReachPosWithNoRot(newPos);
        }

        // Finally, calculate bullet travel time.
        timeToHit += Mathf.Min(schematic.Range, diffVec.magnitude) / schematic.ShootImpulse;

        return(timeToHit);
    }
コード例 #4
0
ファイル: TankUtility.cs プロジェクト: tmoritaa/JunkMetal
    public static Vector2 CalcAppliedLinearForce(TankStateInfo stateInfo)
    {
        Vector3 leftForceVec  = stateInfo.ForwardVec * stateInfo.LeftCurPower * stateInfo.EnergyPower / 2f;
        Vector3 rightForceVec = stateInfo.ForwardVec * stateInfo.RightCurPower * stateInfo.EnergyPower / 2f;

        Vector2 linearForce = rightForceVec + leftForceVec;

        return(linearForce);
    }
コード例 #5
0
 public LookaheadNode(LookaheadNode parentNode, Vector2 incomingDir, bool incomingWasJet, TankStateInfo stateInfo, float elapsedTimeFromParent, List <Node> passedNodes)
 {
     ParentNode            = parentNode;
     IncomingDir           = incomingDir;
     IncomingWasJet        = incomingWasJet;
     TankInfo              = stateInfo;
     ElapsedTimeFromParent = elapsedTimeFromParent;
     PassedNodes           = passedNodes;
     ChildNodes            = new List <LookaheadNode>();
 }
コード例 #6
0
    public static float CalcTimeToReachPos(TankStateInfo tankInfo, Vector2 targetPos)
    {
        Vector2 curPos = tankInfo.Pos;

        Vector2 diffVec = targetPos - curPos;

        float timeToReach = 0;

        timeToReach += Mathf.Min(tankInfo.CalcTimeToRotate(tankInfo.ForwardVec, diffVec), tankInfo.CalcTimeToRotate(tankInfo.ForwardVec.Rotate(180f), diffVec));
        timeToReach += tankInfo.CalcTimeToReachPosWithNoRot(targetPos);

        return(timeToReach);
    }
コード例 #7
0
    public static TankStateInfo CalcPosInFutureWithRequestedDir(Vector2 _requestDir, float timeInSecs, TankStateInfo tankInfo, out List <Vector2> passedPos)
    {
        TankStateInfo resultInfo = new TankStateInfo(tankInfo);
        Vector2       requestDir = _requestDir;

        float elapsedTime = 0;

        float dt = Time.fixedDeltaTime;

        List <Vector2> allPos = new List <Vector2>();

        allPos.Add(resultInfo.Pos);

        while (elapsedTime <= timeInSecs)
        {
            elapsedTime += dt;

            int[] powerChange = AIUtility.CalcPowerChangeBasedOnRequestDir(requestDir, resultInfo);
            resultInfo.LeftCurPower  = powerChange[0];
            resultInfo.RightCurPower = powerChange[1];

            // Pos update
            {
                Vector2 f    = TankUtility.CalcAppliedLinearForce(resultInfo);
                float   m    = resultInfo.Mass;
                float   drag = resultInfo.LinearDrag;
                Vector2 a    = f / m;
                resultInfo.LinearVel = (resultInfo.LinearVel + a * dt) * (1f / (1f + drag * dt));
                resultInfo.Pos      += resultInfo.LinearVel * dt;

                allPos.Add(resultInfo.Pos);
            }

            // rot update
            {
                float torque       = TankUtility.CalcAppliedTorque(resultInfo);
                float angularDrag  = resultInfo.AngularDrag;
                float angularAccel = torque / resultInfo.Inertia * Mathf.Rad2Deg;

                resultInfo.AngularVel = (resultInfo.AngularVel + angularAccel * dt) * (1f / (1f + angularDrag * dt));
                float rotDiff = resultInfo.AngularVel * dt;
                resultInfo.Rot += rotDiff;

                requestDir = requestDir.Rotate(rotDiff);
            }
        }

        passedPos = allPos;

        return(resultInfo);
    }
コード例 #8
0
ファイル: TankUtility.cs プロジェクト: tmoritaa/JunkMetal
    public static float CalcAppliedTorque(TankStateInfo stateInfo)
    {
        Vector3 leftForceVec  = stateInfo.ForwardVec * stateInfo.LeftCurPower * stateInfo.EnergyPower / 2f;
        Vector3 rightForceVec = stateInfo.ForwardVec * stateInfo.RightCurPower * stateInfo.EnergyPower / 2f;

        float   width       = stateInfo.Size.x;
        Vector3 rightR      = new Vector2(width / 2f, 0).Rotate(stateInfo.Rot);
        Vector3 rightTorque = Vector3.Cross(rightR, rightForceVec);

        Vector3 leftR      = new Vector2(-width / 2f, 0).Rotate(stateInfo.Rot);
        Vector3 leftTorque = Vector3.Cross(leftR, leftForceVec);

        return(rightTorque.z + leftTorque.z);
    }
コード例 #9
0
ファイル: TankStateInfo.cs プロジェクト: tmoritaa/JunkMetal
 public TankStateInfo(TankStateInfo stateInfo)
 {
     OwningTank    = stateInfo.OwningTank;
     LeftCurPower  = stateInfo.LeftCurPower;
     RightCurPower = stateInfo.RightCurPower;
     Mass          = stateInfo.Mass;
     Pos           = stateInfo.Pos;
     LinearVel     = stateInfo.LinearVel;
     LinearDrag    = stateInfo.LinearDrag;
     AngularVel    = stateInfo.AngularVel;
     AngularDrag   = stateInfo.AngularDrag;
     Rot           = stateInfo.Rot;
     Inertia       = stateInfo.Inertia;
     EnergyPower   = stateInfo.EnergyPower;
     Size          = stateInfo.Size;
 }
コード例 #10
0
        public void Init(TankAIState _state)
        {
            state = _state;
            tank.motion.SetInstruction(instruction);
            tank.weapon.Init(instruction);
            sensoringSimulator = GameObject.Find("MainGameAI").GetComponent <SensoringSimulator>();


            currentMotionState   = MotionStates[(int)MotionStateIndices.going];
            currentShootingState = ShootingStates[(int)ShootingStateIndices.notShooting];

            tankStateInfo_motion = new TankStateInfo
            {
                instruction          = this.instruction,
                tank                 = this.tank,
                AvailableStates      = this.MotionStates,
                AvoidingTendencies   = this.intruderDetector.GetTendencies(),
                destinationPosition  = this.DestinationPosition,
                destinationTransform = this.destinationTransform
            };

            for (int i = 0; i < MotionStates.Length; i++)
            {
                if (MotionStates[i] != null)
                {
                    MotionStates[i].Init(tankStateInfo_motion);
                }
            }

            tankStateInfo_shooting = new TankStateInfo
            {
                instruction     = this.instruction,
                tank            = this.tank,
                AvailableStates = this.ShootingStates,
                targetTank      = this.TargetTank,
                targetTransform = this.TargetTransform
            };

            for (int i = 0; i < ShootingStates.Length; i++)
            {
                if (ShootingStates[i] != null)
                {
                    ShootingStates[i].Init(tankStateInfo_shooting);
                }
            }
        }
コード例 #11
0
    public static int CalcMinTimeForAimerToHitAimee(TankStateInfo aimingTankInfo, TankStateInfo aimeeTankInfo, List <WeaponPart> aimerWeapons, out WeaponPart outWeapon)
    {
        int minTime = 99999;

        outWeapon = null;
        foreach (WeaponPart weapon in aimerWeapons)
        {
            Vector2 fireVec = weapon.OwningTank.Hull.Schematic.OrigWeaponDirs[weapon.EquipIdx].Rotate(aimingTankInfo.Rot);
            int     time    = convertFloatSecondToIntCentiSecond(AIUtility.CalcTimeToHitPos(aimingTankInfo.Pos, fireVec, aimingTankInfo, weapon.Schematic, aimeeTankInfo.Pos) + weapon.CalcTimeToReloaded());

            if (time < minTime)
            {
                minTime   = time;
                outWeapon = weapon;
            }
        }

        return(minTime);
    }
コード例 #12
0
    private void handleMovement()
    {
        TankStateInfo stateInfo = StateInfo;

        if (!DisableMovement)
        {
            Vector2 linearForce = TankUtility.CalcAppliedLinearForce(stateInfo);
            body.AddForce(linearForce);

            float torque = TankUtility.CalcAppliedTorque(stateInfo);
            body.AddTorque(torque, ForceMode2D.Force);
        }
        else
        {
            Hull.PerformPowerChange(0, 0);
        }

        performAnimations(stateInfo);
    }
コード例 #13
0
    private static bool checkIfCloseToWall(TankStateInfo selfTankInfo, out List <Vector2> wallDirections)
    {
        wallDirections = new List <Vector2>();

        Vector2 centerPt = selfTankInfo.Pos;

        Vector2[] checkDirs = new Vector2[] { new Vector2(0, 1), new Vector2(0, -1), new Vector2(1, 0), new Vector2(-1, 0) };

        foreach (Vector2 dir in checkDirs)
        {
            RaycastHit2D hitResult = Physics2D.Raycast(centerPt, dir, selfTankInfo.TerminalVel / 2f);

            if (hitResult.collider != null)
            {
                wallDirections.Add(dir);
            }
        }

        return(wallDirections.Count > 0);
    }
コード例 #14
0
    public static TankStateInfo CalcPosInFutureWithRequestedDirJets(Vector2 _requestDir, float timeInSecs, TankStateInfo tankInfo, out List <Vector2> passedPos)
    {
        TankStateInfo resultInfo = new TankStateInfo(tankInfo);
        Vector2       requestDir = _requestDir;

        float elapsedTime = 0;

        float dt = Time.fixedDeltaTime;

        List <Vector2> allPos = new List <Vector2>();

        allPos.Add(resultInfo.Pos);

        float jetImpulseMag = resultInfo.OwningTank.Hull.Schematic.JetImpulse;

        resultInfo.LinearVel += requestDir.normalized * (jetImpulseMag / resultInfo.Mass);

        while (elapsedTime <= timeInSecs)
        {
            elapsedTime += dt;

            // Pos update
            {
                float m    = resultInfo.Mass;
                float drag = resultInfo.LinearDrag;
                resultInfo.LinearVel = resultInfo.LinearVel * (1f / (1f + drag * dt));
                resultInfo.Pos      += resultInfo.LinearVel * dt;

                allPos.Add(resultInfo.Pos);
            }
        }

        passedPos = allPos;

        return(resultInfo);
    }
コード例 #15
0
    // TODO: In general, later make serialized field if these values feel like they need tweaking
    public static int[] CalcPowerChangeBasedOnRequestDir(Vector2 requestDir, TankStateInfo stateInfo)
    {
        const float MinRatioCutOff = 0.4f;
        const float MaxRatioCutoff = 0.7f;

        const float StartingBackwardArcAngle = 180f;
        const float StartingForwardArcAngle  = 360f - StartingBackwardArcAngle;

        int[] powerChange = new int[2];

        if (requestDir.magnitude == 0)
        {
            if (stateInfo.LeftCurPower != 0)
            {
                powerChange[0] = Mathf.Sign(stateInfo.LeftCurPower) > 0 ? -1 : 1;
            }

            if (stateInfo.RightCurPower != 0)
            {
                powerChange[1] = Mathf.Sign(stateInfo.RightCurPower) > 0 ? -1 : 1;
            }

            return(powerChange);
        }

        // First calculate forward and backwards arc angle based on speed
        float sqrMaxVelocityMag = Mathf.Pow(stateInfo.TerminalVel, 2);
        float sqrCurVelocity    = stateInfo.LinearVel.sqrMagnitude;

        float ratio = Mathf.Clamp(1.0f - sqrCurVelocity / sqrMaxVelocityMag, MinRatioCutOff, MaxRatioCutoff);

        float curBackwardArcAngle = ratio * StartingBackwardArcAngle;
        float curForwardArcAngle  = ratio * StartingForwardArcAngle;

        Vector2 forwardVec  = stateInfo.ForwardVec;
        Vector2 backwardVec = forwardVec.Rotate(180f);

        List <Vector2> arcVectors = new List <Vector2> {
            forwardVec.Rotate(curForwardArcAngle / 2f),
            forwardVec.Rotate(-curForwardArcAngle / 2f),
            backwardVec.Rotate(curBackwardArcAngle / 2f),
            backwardVec.Rotate(-curBackwardArcAngle / 2f)
        };

        CombatDebugHandler.Instance.RegisterObject("actuation_arc_vectors", arcVectors);

        float angleDiffFromFront = Vector2.Angle(forwardVec, requestDir);
        float angleDiffFromBack  = Vector2.Angle(backwardVec, requestDir);

        const float sigma = 10f;

        // In this case we want the AI to continue accelerating while going towards the requested direction
        if ((curForwardArcAngle / 2f) >= angleDiffFromFront)
        {
            float angleToTurn = Vector2.SignedAngle(forwardVec, requestDir);

            if (Mathf.Abs(angleToTurn) > sigma)
            {
                if (Mathf.Sign(angleToTurn) > 0)
                {
                    powerChange[0] = 0;
                    powerChange[1] = 1;
                }
                else
                {
                    powerChange[0] = 1;
                    powerChange[1] = 0;
                }
            }
            else
            {
                powerChange[0] = 1;
                powerChange[1] = 1;
            }

            // In this case we want the tank to start accelerating backwards
        }
        else if ((curBackwardArcAngle / 2f) >= angleDiffFromBack)
        {
            float angleToTurn = Vector2.SignedAngle(backwardVec, requestDir);

            if (Mathf.Abs(angleToTurn) > sigma)
            {
                if (Mathf.Sign(angleToTurn) > 0)
                {
                    powerChange[0] = -1;
                    powerChange[1] = 0;
                }
                else
                {
                    powerChange[0] = 0;
                    powerChange[1] = -1;
                }
            }
            else
            {
                powerChange[0] = -1;
                powerChange[1] = -1;
            }

            // In this case we want the tank to start turning
        }
        else
        {
            float angleToTurnFromFront = Vector2.SignedAngle(forwardVec, requestDir);
            float angleToTurnFromBack  = Vector2.SignedAngle(backwardVec, requestDir);

            bool  turningToFront = Mathf.Abs(angleToTurnFromFront) <= Mathf.Abs(angleToTurnFromBack);
            float angle          = turningToFront ? angleToTurnFromFront : angleToTurnFromBack;

            powerChange = CalcPowerChangeForRotation(angle);
        }

        return(powerChange);
    }
コード例 #16
0
    public static List <LookaheadNode> FilterByAwayFromWall(List <LookaheadNode> nodes, TankStateInfo selfTankInfo)
    {
        List <LookaheadNode> filteredNodes = new List <LookaheadNode>();

        List <Vector2> hitWallDirs;
        bool           closeToWall = checkIfCloseToWall(selfTankInfo, out hitWallDirs);

        if (closeToWall)
        {
            foreach (LookaheadNode node in nodes)
            {
                Vector2 dir = node.GetNodeOneStepAfterRoot().IncomingDir;

                bool isHitWallDir = false;
                foreach (Vector2 hitWallDir in hitWallDirs)
                {
                    float angle = Vector2.Angle(dir, hitWallDir);

                    if (angle < 90f)
                    {
                        isHitWallDir = true;
                        break;
                    }
                }

                if (!isHitWallDir)
                {
                    filteredNodes.Add(node);
                }
            }
        }

        if (filteredNodes.Count == 0)
        {
            filteredNodes = nodes;
        }

        return(filteredNodes);
    }
コード例 #17
0
    public static TankStateInfo CalcPosInFutureWithRequestedPowerChange(int[] powerChange, float timeInSecs, TankStateInfo tankInfo, out List <Vector2> passedPos)
    {
        Vector2 forwardVec = tankInfo.ForwardVec;

        if (powerChange[0] == powerChange[1])
        {
            forwardVec *= powerChange[0];
        }
        else if (powerChange[0] == 0 || powerChange[1] == 0)
        {
            if (powerChange[0] != 0)
            {
                forwardVec = forwardVec.Rotate(Mathf.Sign(powerChange[0]) > 0 ? -45f : -135f);
            }
            else
            {
                forwardVec = forwardVec.Rotate(Mathf.Sign(powerChange[1]) > 0 ? 45f : 135f);
            }
        }
        else
        {
            if (powerChange[0] > 0)
            {
                forwardVec = forwardVec.Rotate(-90f);
            }
            else
            {
                forwardVec = forwardVec.Rotate(90f);
            }
        }

        return(CalcPosInFutureWithRequestedDir(forwardVec, timeInSecs, tankInfo, out passedPos));
    }