コード例 #1
0
ファイル: EnemyBehaviour.cs プロジェクト: DavidBocek/GGJ2020
    private void EnterState(eAIState newState)
    {
        m_currentState = newState;

        switch (newState)
        {
        case eAIState.ATTACK:
            m_theta = Mathf.Asin(-1 * m_vecToTarget.z);
            if (-1 * m_vecToTarget.x < 0)
            {
                m_theta = (Mathf.PI) - m_theta;
            }
            break;
        }
    }
コード例 #2
0
    public override void TakeDamage(float damageAmount, Ship attacker, Vector2 hitlocation)
    {
        base.TakeDamage(damageAmount, attacker, hitlocation);

        if (isAlive)
        {
            //todo
            //do a chance check and maybe check fearfulness (doesn't exist yet)
            //check current health as well
            if (Random.Range(0, 50) > 40)
            {
                aggressor = attacker;
                switch (stateAI)
                {
                case eAIState.Hunting:
                {
                    //go into a strafing flee, dont just turn directly around
                    //set the target location
                    float coinToss = Random.Range(0, 2);
                    if (coinToss >= 1)
                    {
                        targetLocation = new Vector2(transform.position.x, transform.position.y) +
                                         (forward.normalized * 5) +
                                         new Vector2(forward.y, -forward.x).normalized *Random.Range(2, 7);
                    }
                    else
                    {
                        targetLocation = new Vector2(transform.position.x, transform.position.y) +
                                         (forward.normalized * 5) +
                                         new Vector2(-forward.y, forward.x).normalized *Random.Range(2, 7);
                    }
                    fleeOffsetTime    = 0;
                    fleeOffsetMaxTime = Random.Range(6, 12);
                    stateAI           = eAIState.StrafingToFlee;
                }
                break;

                default:
                {
                    stateAI = eAIState.Fleeing;
                    RecalulateFleeOffset();
                }
                break;
                }
                ;
            }
        }
    }
コード例 #3
0
    void Start()
    {
        firingTimerReset = firingTimer;
        acceleration     = new Vector2();
        myBody           = gameObject.GetComponent <Rigidbody2D>();
        GameObject playerManagerObject = GameObject.Find("PlayerManagerMain");

        playerManager = playerManagerObject.GetComponent <PlayerManager>();
        playerManager.ships.Add(this);
        stateAI        = eAIState.Travelling;
        fleeOffset     = new Vector2();
        targetLocation = transform.position;
        new Vector2(transform.up.x, transform.up.y);
        shipId = playerManager.AssignShip();
        base.LateStart();
    }
コード例 #4
0
    public static IEnumerator EvaluateAI(Character mCharacter)
    {
        Debug.Log("Starte AI für " + mCharacter.pName + " Faction:" + mCharacter.pFaction + " Pat:" + mCharacter.pPatrouilleSelection);
        //mCharacter.pApCurrent = mCharacter.pAp;
        eAIState  pAIState      = eAIState.Patrouille;
        Character pActiveTarget = null;

        List <Tile> pSteps = new List <Tile>();

        #region AI v2
        while (mCharacter.pApCurrent > 9)
        {
            Debug.Log("AI current AP " + mCharacter.pApCurrent);
            yield return(new WaitForSeconds(0.5f)); // blocks debug stepping. Remove if nessesary

            switch (pAIState)
            {
            case eAIState.Patrouille:
                #region Patrouille
                pActiveTarget = AIfindTarget(mCharacter);
                if (pActiveTarget != null)
                {
                    pAIState = eAIState.Fight;
                    Debug.Log("AI switching from patrol to fight mode");
                    break;
                }

                if (mCharacter.pPatrouilleSelection == ePatrouilleSelection.Static)     // wenn statischer gegner ohne wegpunkte, early exit
                {
                    mCharacter.pApCurrent = 0;
                    Debug.Log("AI Nothing to do, skipping turn");
                    break;
                }


                Tile patrolTile;
                if (mCharacter.pFaction == eFactions.AI1)
                {
                    if (mCharacter.pPatrouilleSelection == ePatrouilleSelection.A)
                    {
                        patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI1PatrouilleA[mCharacter.mPatWaypointID]);
                    }
                    else
                    {
                        patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI1PatrouilleB[mCharacter.mPatWaypointID]);
                    }
                }
                else
                {
                    if (mCharacter.pPatrouilleSelection == ePatrouilleSelection.A)
                    {
                        patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI2PatrouilleA[mCharacter.mPatWaypointID]);
                    }
                    else
                    {
                        patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI2PatrouilleB[mCharacter.mPatWaypointID]);
                    }
                }


                pSteps = GridManager.pInstance.GetPathTo(mCharacter.pTile, patrolTile);
                if (pSteps == null)
                {
                    break;
                }
                int currentStepsLeft = mCharacter.pWalkRange;

                if (pSteps.Count < 3)     //close enough to pat-point?
                {
                    Debug.Log("AI patrol to next waypoint");
                    mCharacter.mPatWaypointID = (mCharacter.mPatWaypointID + 1) % (mCharacter.pPatrouilleSelection == ePatrouilleSelection.A ? GridManager.pInstance.pCurrentLevel.pAI1PatrouilleA.Length : GridManager.pInstance.pCurrentLevel.pAI1PatrouilleB.Length);
                    if (mCharacter.pFaction == eFactions.AI1)
                    {
                        if (mCharacter.pPatrouilleSelection == ePatrouilleSelection.A)
                        {
                            patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI1PatrouilleA[mCharacter.mPatWaypointID]);
                        }
                        else
                        {
                            patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI1PatrouilleB[mCharacter.mPatWaypointID]);
                        }
                    }
                    else
                    {
                        if (mCharacter.pPatrouilleSelection == ePatrouilleSelection.A)
                        {
                            patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI2PatrouilleA[mCharacter.mPatWaypointID]);
                        }
                        else
                        {
                            patrolTile = GridManager.pInstance.GetTileAt(GridManager.pInstance.pCurrentLevel.pAI2PatrouilleB[mCharacter.mPatWaypointID]);
                        }
                    }

                    pSteps = GridManager.pInstance.GetPathTo(mCharacter.pTile, patrolTile);
                }

                if (pSteps.Count > mCharacter.pWalkRange)
                {
                    yield return(mCharacter.MoveEnumerator(pSteps[pSteps.Count - mCharacter.pWalkRange]));
                }
                else
                {
                    yield return(mCharacter.MoveEnumerator(pSteps[0]));
                }


                pActiveTarget = AIfindTarget(mCharacter);
                if (pActiveTarget != null)
                {
                    pAIState = eAIState.Fight;
                }
                #endregion
                break;

            case eAIState.Fight:
                #region Fight
                Debug.Log(mCharacter.pName + " is searching for cover against " + pActiveTarget.pName);

                List <Tile> walkableTiles = GridManager.pInstance.GetReachableTiles(mCharacter.pTile, mCharacter.pWalkRange);
                //remove tiles with players on it
                for (int i = walkableTiles.Count - 1; i > 0; --i)
                {
                    if (walkableTiles[i].pCharacterId != -1)
                    {
                        walkableTiles.Remove(walkableTiles[i]);
                    }
                }
                eBlockType currentCoverTarget = eBlockType.Empty;

                //Creating lists with all options to choose from

                List <Tile> coverPositionsFull = new List <Tile>();
                List <Tile> coverPositionsHalf = new List <Tile>();
                foreach (Tile walkableTile in walkableTiles)
                {
                    if (GridManager.pInstance.GetVisibilityToTarget(mCharacter.pTile, pActiveTarget.pTile, mCharacter.pVisionRange) == eVisibility.Seethrough &&
                        walkableTile.pCharacterId == -1)        // now with occupied tiles
                    {
                        switch (GridManager.pInstance.GetCoverFromTarget(mCharacter.pTile, pActiveTarget.pTile))
                        {
                        case eBlockType.Blocked:
                            if (currentCoverTarget != eBlockType.HalfBlocked)
                            {
                                currentCoverTarget = eBlockType.Blocked;
                            }
                            coverPositionsFull.Add(walkableTile);
                            break;

                        case eBlockType.HalfBlocked:
                            currentCoverTarget = eBlockType.HalfBlocked;
                            coverPositionsHalf.Add(walkableTile);
                            break;
                        }
                    }
                }

                // sort the choosen options by distance. Switch just for avoiding unnessesary sorting of tiles that are not suitable

                List <Tile> wayToTarget = new List <Tile>();
                switch (currentCoverTarget)
                {
                case eBlockType.Empty:
                    wayToTarget = GridManager.pInstance.GetPathTo(pActiveTarget.pTile, mCharacter.pTile);
                    break;

                case eBlockType.Blocked:
                    coverPositionsFull.Sort((a, b) => Tile.Distance(a, pActiveTarget.pTile).CompareTo(Tile.Distance(b, pActiveTarget.pTile)));
                    wayToTarget = GridManager.pInstance.GetPathTo(mCharacter.pTile, coverPositionsFull[0]);
                    break;

                case eBlockType.HalfBlocked:
                    coverPositionsHalf.Sort((a, b) => Tile.Distance(a, pActiveTarget.pTile).CompareTo(Tile.Distance(b, pActiveTarget.pTile)));
                    wayToTarget = GridManager.pInstance.GetPathTo(mCharacter.pTile, coverPositionsHalf[0]);
                    break;

                default:
                    break;
                }

                /*
                 * // if we are going to get cover
                 * if (currentCoverTarget != eBlockType.Empty && wayToTarget.Count <= mCharacter.pApCurrent / mCharacter.pWalkCost && wayToTarget.Count > 1)
                 * {
                 *  Debug.Log("Move to cover because it seems reachable");
                 *  for (int i = 0; i < (wayToTarget.Count > mCharacter.pWalkRange ? mCharacter.pWalkRange : wayToTarget.Count); ++i) // walk until range is spent or target reached
                 *  {
                 *      yield return AIevaluator.AImove(mCharacter, pSteps[1]);
                 *  }
                 *  mCharacter.pApCurrent -= 10;
                 *  break;
                 * }
                 */
                // if we need to get in range and no cover is present
                if (currentCoverTarget == eBlockType.Empty && wayToTarget.Count > mCharacter.Range)
                {
                    // weglist durchgehen und einen punkt wählen der dicht genug für schuss ist und nicht blockiert ist
                    int possibleFinalWaypoint = 0;
                    for (int wayPointCounter = wayToTarget.Count - 1; wayPointCounter > 0; --wayPointCounter)
                    {
                        if (wayToTarget[wayPointCounter].pCharacterId == -1 && wayToTarget.Count - wayPointCounter - 1 <= mCharacter.Range)
                        {
                            possibleFinalWaypoint = wayPointCounter;
                        }
                        else if (wayToTarget[wayPointCounter].pCharacterId == -1 && wayToTarget.Count - wayPointCounter - 1 > mCharacter.Range)
                        {
                            possibleFinalWaypoint = wayPointCounter;
                            break;
                        }
                    }

                    Debug.Log("Move to Enemy because out of range, possible " + wayToTarget.Count.ToString() + " steps");
                    yield return(mCharacter.MoveEnumerator(wayToTarget[mCharacter.pWalkRange]));

                    break;
                }

                if (mCharacter.pApCurrent < 15)     // not enough AP to shoot
                {
                    Debug.Log("No shots left, skipping turn");
                    mCharacter.pApCurrent = 0;
                    break;
                }
                Debug.Log("AI shooting Normal spell at " + pActiveTarget.pName);
                yield return(mCharacter.StandardAttackCoroutine(pActiveTarget.pTile)); // shoot normal spell at target

                pActiveTarget = AIfindTarget(mCharacter);                              //check for survivors
                if (pActiveTarget == null)
                {
                    pAIState = eAIState.Patrouille;
                }
                #endregion
                break;

            default:
                Debug.LogError("AI in unknown state");
                break;
            }
        }// loop if char has still points to use

        #endregion

        // end AI turn
        Debug.Log("AI spent all AP, end turn");
        yield return(new WaitForSeconds(1));

        mCharacter.pAura.SetActive(false);
        EntityManager.pInstance.EndRound(mCharacter);

        //ending AI turn and switch to next player
        GameManager.pInstance.pCurrentFaction = GameManager.pInstance.pCurrentFaction == eFactions.AI1 ? eFactions.Player1 : eFactions.Player2;
        //EntityManager.pInstance.pGetFactionEntities(pCurrentFraction)[0].Select(); // move camera to an faction entity
        GameManager.pInstance.ChangeState(eGameState.Select);
    }
コード例 #5
0
    void FixedUpdate()
    {
        if (!isAlive)
        {
            return;
        }

        CustomUpdate();
        forward.x = transform.up.x;
        forward.y = transform.up.y;
        float deltaTime = Time.deltaTime;

        switch (stateAI)
        {
        case eAIState.Travelling:
        {
            // find a target if we dont have one
            if (target == null || !target.isAlive || target.teamId == teamId)
            {
                //todo better distance calculation once sections are completed
                int   shipNum  = playerManager.ships.Count;
                int   foundNum = -1;
                float dist     = 9999999;
                for (int i = 0; i < shipNum; i++)
                {
                    Ship temp = playerManager.ships[i];
                    if (temp.shipId != shipId &&
                        temp.isAlive &&
                        temp.teamId != teamId &&
                        Vector2.Distance(temp.transform.position, transform.position) < dist)
                    {
                        dist     = Vector2.Distance(temp.transform.position, transform.position);
                        foundNum = i;
                    }
                }

                if (foundNum >= 0)
                {
                    target  = playerManager.ships[foundNum];
                    stateAI = eAIState.Hunting;
                }
            }
            else
            {
                stateAI = eAIState.Hunting;
            }
        }
        break;

        case eAIState.Following:
        {
            if (target != null)
            {
                float distance = Vector2.Distance(targetLocation, transform.position);
                float angle    = TurnTowards(deltaTime, targetLocation);

                if (angle < thrustAngle && distance > followDistance)
                {
                    MoveForward(deltaTime, 3.3f, true);
                }
                else
                {
                    thrustingTime      = 0;
                    myBody.angularDrag = 1.5f;

                    if (distance > followDistance / 2)
                    {
                        MoveForward(deltaTime, 1.5f, false, 0.2f);
                    }
                    else if (animThrusting)
                    {
                        thrusterAnim.SetBool("IsStarting", false);
                        thrusterAnim.SetBool("IsEnding", true);
                        animThrusting = false;
                    }
                }

                if (target.AIControlled)
                {
                    AIShip theOtherShip = ((AIShip)target);
                    if (!target.isAlive || theOtherShip.stateAI == eAIState.Travelling || theOtherShip.stateAI == eAIState.Fleeing)
                    {
                        stateAI = eAIState.Travelling;
                        theOtherShip.followingShips.Remove(this);
                    }
                }
                else
                {
                    if (!target.isAlive)
                    {
                        stateAI = eAIState.Travelling;
                        target.followingShips.Remove(this);
                    }
                }
            }
            else
            {
                stateAI = eAIState.Travelling;
            }
        }
        break;

        case eAIState.Hunting:
        {
            if (target != null && target.isAlive)
            {
                if (firingTimer > 0)
                {
                    firingTimer -= Time.deltaTime;
                    if (firingTimer < 0)
                    {
                        firingTimer = 0;
                    }
                }

                float distance = Vector2.Distance(target.transform.position, transform.position);
                float angle    = TurnTowards(deltaTime, target.transform.position);

                if (angle < shootAngle && firingTimer == 0)
                {
                    if (distance < fireDistance)
                    {
                        FireLaser();
                    }

                    //chance check to see if this turns into a strafing run
                    if (thrustingTime > 0 && Random.Range(0, 50) > 49)     //if its moving at a good pace
                    {
                        float coinToss = Random.Range(0, 2);
                        if (coinToss >= 1)
                        {
                            targetLocation = new Vector2(transform.position.x, transform.position.y) +
                                             (forward.normalized * 9) +
                                             new Vector2(forward.y, -forward.x).normalized *Random.Range(2, 4);
                        }
                        else
                        {
                            targetLocation = new Vector2(transform.position.x, transform.position.y) +
                                             (forward.normalized * 9) +
                                             new Vector2(-forward.y, forward.x).normalized *Random.Range(2, 4);
                        }
                        stateAI = eAIState.StrafingToAttack;
                    }
                }

                if (angle < thrustAngle && distance > followDistance)
                {
                    MoveForward(deltaTime, 3.3f, true);
                }
                else
                {
                    thrustingTime      = 0;
                    myBody.angularDrag = 1.5f;

                    if (distance > followDistance / 2)
                    {
                        MoveForward(deltaTime, 1.5f, false, 0.2f);
                    }
                    else if (animThrusting)
                    {
                        thrusterAnim.SetBool("IsStarting", false);
                        thrusterAnim.SetBool("IsEnding", true);
                        animThrusting = false;
                    }
                }

                //check for any other ship that is following the same target
                if (followingShips.Count < 2)
                {
                    int shipNum = playerManager.ships.Count;
                    for (int i = 0; i < shipNum; i++)
                    {
                        if (playerManager.ships[i].AIControlled)
                        {
                            AIShip temp = (AIShip)playerManager.ships[i];
                            if (temp.shipId != this.shipId &&
                                temp.isAlive &&
                                temp.teamId == teamId &&
                                temp.stateAI == eAIState.Hunting &&
                                temp.target.shipId == this.target.shipId &&
                                temp.followingShips.Count < 2
                                )
                            {
                                target = temp;
                                FindFollowingPosition();
                                stateAI = eAIState.Following;
                                break;
                            }
                        }
                    }
                }
            }
            else
            {
                stateAI = eAIState.Travelling;
            }
        }
        break;

        case eAIState.Fleeing:
        {
            if (aggressor != null)
            {
                float distance = Vector2.Distance(aggressor.transform.position, transform.position);

                if (distance < fleeDistance)
                {
                    Vector2 pos             = new Vector2(transform.position.x, transform.position.y);
                    var     enemyPos        = aggressor.transform.position;
                    Vector2 targetDirection = pos - new Vector2(enemyPos.x, enemyPos.y);

                    fleeOffsetTime += deltaTime;
                    if (fleeOffsetTime > fleeOffsetMaxTime)
                    {
                        RecalulateFleeOffset();
                    }
                    Vector2 targetPoint = (targetDirection.normalized * fleeDistance) + pos + fleeOffset;
                    float   angle       = TurnTowards(deltaTime, targetPoint);
                    if (angle < thrustAngle)
                    {
                        MoveForward(deltaTime, 3.3f, true);
                    }
                    else
                    {
                        thrustingTime      = 0;
                        myBody.angularDrag = 1.5f;
                        MoveForward(deltaTime, 1.5f, false, 0.2f);
                    }
                }
                else
                {
                    stateAI = eAIState.Travelling;
                }
            }
            else
            {
                //todo
                //search for any nearby enemy units, if there is one, assign a new aggressor
                //if not break out of fleeing
                stateAI = eAIState.Travelling;
            }
        }
        break;

        case eAIState.StrafingToFlee:
        {
            TurnTowards(deltaTime, targetLocation);
            MoveForward(deltaTime, 3.3f, true);

            //test distance from target, if it is small enough, then go into fleeing
            fleeOffsetTime += deltaTime;
            float distance = Vector2.Distance(targetLocation, transform.position);
            if (distance < 0.2f || fleeOffsetTime > fleeOffsetMaxTime)
            {
                stateAI = eAIState.Fleeing;
            }
        }
        break;

        case eAIState.StrafingToAttack:
        {
            TurnTowards(deltaTime, targetLocation);
            MoveForward(deltaTime, 3.3f, true);

            //test distance from target, if it is small enough, then go into fleeing
            fleeOffsetTime += deltaTime;
            float distance = Vector2.Distance(targetLocation, transform.position);
            if (distance < 0.2f)
            {
                stateAI = eAIState.Hunting;
            }
        }
        break;
        }
        ;
    }