Exemple #1
0
    //---------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------

    //bot randomly chooses to go left or right, then picks a destination to their left or right
    private EnvKey pickPossibleAction()
    {
        foreach (EnvKey key in possibleLeftActions)
        {
            Debug.LogFormat("Left| {0}: {1}, {2}", key.direction, key.x, key.y);
        }

        foreach (EnvKey key in possibleRightActions)
        {
            Debug.LogFormat("Right| {0}: {1}, {2}", key.direction, key.x, key.y);
        }

        //bot randomly picks a direction, but gives greater weight to moving in the same direction as before
        int chooseDirection = Random.Range(0, 100);

        chooseDirection = (lastMovement == -1) ? (chooseDirection - 20) : chooseDirection + 20;

        //if the bot is on a ramp, it recalculates its decision super often, so make it super inclined to continue int he same direction
        EnvInfo ground     = info[new EnvKey('G', 0, 0)];
        float   groundTilt = (ground.gameObject()) ? ground.gameObject().transform.localEulerAngles.z : 0;

        if (ground.gameObject() && transform.position.y - ground.location().y < 1.6f && groundIsRamp(groundTilt))
        {
            chooseDirection += 40 * lastMovement;
            //Debug.Log("on ramp");
        }
        // else
        //     Debug.Log("off ramp " + ground + ", " + (transform.position.y - ground.location().y) + ", " + groundIsRamp(groundTilt));

        //sometimes the bot MUST go left or MUST go right
        if (possibleLeftActions.Count == 0)
        {
            chooseDirection = 50;
        }
        else if (possibleRightActions.Count == 0)
        {
            chooseDirection = 0;
        }

        //for debugging purposes
        if (testSpecificAction)
        {
            return(testKey);
        }

        Debug.Log(chooseDirection + ", " + lastMovement);
        //pick a left or right destination
        if (chooseDirection < 50 && possibleLeftActions.Count > 0)
        {
            int choice = Random.Range(0, possibleLeftActions.Count);
            return(possibleLeftActions[choice]);
        }

        else if (chooseDirection >= 50 && possibleRightActions.Count > 0)
        {
            int choice = Random.Range(0, possibleRightActions.Count);
            return(possibleRightActions[choice]);
        }

        //if the bot somehow has no left/right paths it found (should be impossible), pick a random direction
        else
        {
            Debug.LogError("both action lists were empty :(");

            int  r   = Random.Range(0, 10);
            char dir = (r <= 4) ? 'R' : 'L';
            return(new EnvKey(dir, 0, 0));
        }
    }
Exemple #2
0
    //---------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------

    //bot makes a plan of action (determines place to reach) and starts moving
    private void figureOutWhereToHeadTo()
    {
        //resest action lists + variables
        possibleLeftActions.Clear();
        possibleRightActions.Clear();
        jumpPlatforms.Clear();
        holeSpottedB4 = false;

        //get x position of closest left and right wall
        float rightWallLocation = info[new EnvKey('R', 0, 0)].location().x;
        float leftWallLocation  = info[new EnvKey('L', 0, 0)].location().x;

        //bot takes into account it's last action/location
        lastAction   = action.Equals(null) ? 'A' : action.direction;
        lastMovement = action.Equals(null) ? 1 : (int)Mathf.Sign(action.x);

        //the bot looks to its left for 1) openings in the floor it can drop down in 2) seperate platforms it can jump to
        for (int offset = -1; offset >= -5; offset--)
        {
            EnvKey floorCheck     = new EnvKey('G', offset, 0);
            EnvKey prevFloorCheck = new EnvKey('G', offset + 1, 0);

            //make sure this opening in the floor is not behind a wall (as the bot can't just walk straight to it then)
            if (info[floorCheck].location().x > leftWallLocation)
            {
                //consider going to the first drop down opening on it's left
                if (info[floorCheck].location().y <= transform.position.y - 3.2f && !holeSpottedB4)
                {
                    holeSpottedB4 = true;
                    possibleLeftActions.Add(floorCheck);
                }

                //consider going to the first seperate platform it can jump to on it's left
                if (offset != -1 && info[floorCheck].location().y > transform.position.y - 6.5f && info[prevFloorCheck].location().y <= info[floorCheck].location().y - 0.1f && holeSpottedB4)
                {
                    possibleLeftActions.Add(floorCheck);
                }
            }
        }

        //reset hole spotted variable
        holeSpottedB4 = false;

        //the bot looks to its right for 1) openings in the floor it can drop down in 2) seperate platforms it can jump to
        for (int offset = 1; offset <= 5; offset++)
        {
            EnvKey floorCheck     = new EnvKey('G', offset, 0);
            EnvKey prevFloorCheck = new EnvKey('G', offset - 1, 0);

            //make sure this opening in the floor is not behind a wall (as the bot can't just walk straight to it then)
            if (info[floorCheck].location().x < rightWallLocation)
            {
                //consider going to the first drop down opening on it's right
                if (info[floorCheck].location().y <= transform.position.y - 3.2f && !holeSpottedB4)
                {
                    holeSpottedB4 = true;
                    possibleRightActions.Add(floorCheck);
                }

                //consider going to the first seperate platform it can jump to on it's right
                else if (offset != 1 && info[floorCheck].location().y > transform.position.y - 6.5f && info[prevFloorCheck].location().y <= info[floorCheck].location().y - 0.1f && holeSpottedB4)
                {
                    possibleRightActions.Add(floorCheck);
                }
            }
        }

        //if there is a hallway to the right, consider going there
        if (possibleRightActions.Count <= 1 && rightWallLocation > transform.position.x + 2f)
        {
            //bot should usually consider going right (if it wasn't already going left or if it can't go LEFT next turn)
            if (lastAction != 'L' || leftWallLocation >= transform.position.x - 2.5f)
            {
                possibleRightActions.Add(new EnvKey('R', 0, 0));
            }

            //if the bot was previously heading left, it should rarely consider going right
            else if (lastAction == 'L')
            {
                int r = Random.Range(0, 10);
                if (r >= 9)
                {
                    possibleRightActions.Add(new EnvKey('R', 0, 0));
                }
            }
        }

        //if there is a hallway to the left, still consider going there
        if (possibleLeftActions.Count <= 1 && leftWallLocation < transform.position.x - 2f)
        {
            //bot should usually consider going left  (if it wasn't already going right or if it can't go right next turn)
            if (lastAction != 'R' || rightWallLocation <= transform.position.x + 2.5f)
            {
                possibleLeftActions.Add(new EnvKey('L', 0, 0));
            }

            //if the bot was previously heading right, it should rarely consider going left
            else if (lastAction == 'R')
            {
                int r = Random.Range(0, 10);
                if (r >= 9)
                {
                    possibleLeftActions.Add(new EnvKey('L', 0, 0));
                }
            }
        }

        //the bot checks for openings in the ceiling
        for (int offset = -5; offset <= 5; offset++)
        {
            //get the y coordinate of the ceiling above the player
            EnvKey  ceilingCheck = new EnvKey('C', offset, 0);
            EnvInfo ceiling      = info[ceilingCheck];

            //get the expected height a ceiling should be (for a normal ceiling with no opening)
            float expectedHeight = 4f + transform.position.y;
            float ceilingHeight  = ceiling.location().y;

            //if there is a gap in the ceiling, and its not behind a left or right wall
            if (ceilingHeight > expectedHeight && ceiling.location().x < rightWallLocation && ceiling.location().x > leftWallLocation)
            {
                //if the bot theoretically jumped through the ceiling gap, calculate how far back the left and right walls are on the new platform they would land on
                Vector2 rayCastOrigin = new Vector2(transform.position.x + offset * 1.5f, transform.position.y + 4f);

                RaycastHit2D leftHit  = Physics2D.Raycast(rayCastOrigin, Vector2.left, 9f, Constants.map);
                RaycastHit2D rightHit = Physics2D.Raycast(rayCastOrigin, Vector2.right, 9f, Constants.map);

                float leftUpperWall  = (leftHit.collider != null) ? leftHit.point.x : rayCastOrigin.x - 9;
                float rightUpperWall = (rightHit.collider != null) ? rightHit.point.x : rayCastOrigin.x + 9;

                float rightUpperWallDistance = rightUpperWall - rayCastOrigin.x;
                float leftUpperWallDistance  = rayCastOrigin.x - leftUpperWall;

                //setting these variables to miscellaneous values to avoid null errors
                EnvInfo    leftCeiling = info[new EnvKey('C', 0, 0)];
                EnvInfo    rightCeiling = info[new EnvKey('C', 0, 0)];
                float      leftCeilingHeight = 0, rightCeilingHeight = 0;
                GameObject leftCeilingObject = null, rightCeilingObject = null;

                //can't do left ceiling checks for the left most ceiling and vice versa on the right side
                if (offset != -5)
                {
                    leftCeiling       = info[new EnvKey('C', offset - 1, 0)];
                    leftCeilingHeight = leftCeiling.location().y;
                    leftCeilingObject = leftCeiling.gameObject();
                }
                if (offset != 5)
                {
                    rightCeiling       = info[new EnvKey('C', offset + 1, 0)];
                    rightCeilingHeight = rightCeiling.location().y;
                    rightCeilingObject = rightCeiling.gameObject();
                }

                GameObject groundObject = info[new EnvKey('G', 0, 0)].gameObject();

                //get the tilt of the walls directly to the left and right of the bot right now
                EnvInfo rightWall     = info[new EnvKey('R', 0, 0)];
                float   rightWallTilt = rightWall.gameObject() ? rightWall.gameObject().transform.eulerAngles.z : 0f;

                EnvInfo leftWall     = info[new EnvKey('L', 0, 0)];
                float   leftWallTilt = leftWall.gameObject() ? leftWall.gameObject().transform.eulerAngles.z : 0f;

                //if bot spots an opening in the ceiling to its left or right and there is ceiling directly to the right of the opening,
                //then add this jump as a possible action as long as there is no nearby ramp to the right

                if (offset != 5 && rightCeilingHeight < expectedHeight && rightUpperWallDistance > 2f && rightCeilingObject != groundObject &&
                    (!rightWall.gameObject() || Mathf.Abs(rightCeiling.location().x - rightWall.location().x) > 1.51f || !wallIsActuallyARamp(rightWallTilt)))
                {
                    if (offset > 0)
                    {
                        possibleRightActions.Add(ceilingCheck);
                    }
                    else if (offset < 0)
                    {
                        possibleLeftActions.Add(ceilingCheck);
                    }
                    else if (offset == 0)
                    {
                        if (ceiling.location().x >= transform.position.x)
                        {
                            possibleRightActions.Add(ceilingCheck);
                        }
                        else
                        {
                            possibleLeftActions.Add(ceilingCheck);
                        }
                    }

                    jumpPlatforms.Add(ceilingCheck, "right");
                    jumpToHeight = transform.position.y + 4f;
                }

                //if bot spots an opening in the ceiling to its left or right, but there is ceiling directly to the left of the opening in the ceiling, then add this jump as a possible action
                else if (offset != -5 && leftCeilingHeight < expectedHeight && leftUpperWallDistance > 2f && leftCeilingObject != groundObject &&
                         (!leftWall.gameObject() || Mathf.Abs(leftCeiling.location().x - leftWall.location().x) > 1.51f || !wallIsActuallyARamp(leftWallTilt)))
                {
                    if (offset > 0)
                    {
                        possibleRightActions.Add(ceilingCheck);
                    }
                    else if (offset < 0)
                    {
                        possibleLeftActions.Add(ceilingCheck);
                    }
                    else if (offset == 0)
                    {
                        if (ceiling.location().x <= transform.position.x)
                        {
                            possibleLeftActions.Add(ceilingCheck);
                        }
                        else
                        {
                            possibleRightActions.Add(ceilingCheck);
                        }
                    }

                    jumpPlatforms.Add(ceilingCheck, "left");
                    jumpToHeight = transform.position.y + 4f;
                }
            }
        }

        //bot chooses where to head to
        action  = pickPossibleAction();
        endSpot = info[action].location();

        action.printColored();

        //bot heads to the place it chose
        if (action.direction == 'G')
        {
            check = 1;
            dir   = Mathf.Sign(action.x);
        }
        else if (action.direction == 'R')
        {
            check = 201;
            dir   = 1;
        }
        else if (action.direction == 'L')
        {
            check = 201;
            dir   = -1;
        }
        else if (action.direction == 'C')
        {
            dir   = Mathf.Sign(action.x);
            check = 301;
        }

        rig.velocity = new Vector2(botSpeed * dir, rig.velocity.y);
        actionsTakenToExecutePath();
    }
Exemple #3
0
    //---------------------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------------------

    //Now that the bot has chosen a place to reach, tell it how to get there
    private void actionsTakenToExecutePath()
    {
        //check for gaps in the way if the bot is heading far right
        if (action.x > 0 && action.direction == 'G')
        {
            for (int i = 1; i < action.x; i++)
            {
                EnvInfo nextRaycast = info[new EnvKey('G', i, action.y)];

                //some gap is in the way, so the bot will remember its coordinate to jump over it
                if (nextRaycast.location().y < info[action].location().y - 0.1f)
                {
                    check                 = 2;
                    jumpCoordinate        = nextRaycast.location().x;
                    ceilingCheckAboveJump = new EnvKey('C', i, action.y);
                    break;
                }
            }
        }

        //check for gaps in the way if the bot is heading far left
        if (action.x < 0 && action.direction == 'G')
        {
            for (int i = -1; i > action.x; i--)
            {
                EnvInfo nextRaycast = info[new EnvKey('G', i, action.y)];

                //some gap is in the way, so the bot will remember its coordinate to jump over it
                if (nextRaycast.location().y < info[action].location().y - 0.1f)
                {
                    check                 = 2;
                    jumpCoordinate        = nextRaycast.location().x;
                    ceilingCheckAboveJump = new EnvKey('C', i, action.y);
                    break;
                }
            }
        }

        //if there is a gap in the way as the bot heads left or right
        if (action.x != 0 && action.direction == 'G' && check == 2)
        {
            dontJump = false;

            //if there is a ceiling in the way, the bot will jump when its closer to its end destination to avoid head butting into the ceiling
            if (info[new EnvKey(ceilingCheckAboveJump.direction, ceilingCheckAboveJump.x + (int)Mathf.Sign(action.x), ceilingCheckAboveJump.y)].location().y < transform.position.y + 2f)
            {
                dontJump = true;
            }
        }

        //if heading left or right in a hallway, define the spot where the bot must refigure out what to do
        if (action.direction == 'R')
        {
            endSpot = new Vector2(info[action].location().x - 2, 0);
        }

        if (action.direction == 'L')
        {
            endSpot = new Vector2(info[action].location().x + 2, 0);
        }
    }