コード例 #1
0
    protected virtual IEnumerator MoveToCoroutine(List <Vector3> targets, SpringAction action, IInteractable source)
    {
        // Can we continue already started move animation?
        if (skeletonAnim.AnimationName != "walk")
        {
            skeletonAnim.AnimationState.SetAnimation(0, "walk", true).timeScale = AnimationSpeed;
        }

        while (targets.Count > 0)
        {
            if (transform.position.x < targets[0].x) // Going right
            {
                skeletonAnim.skeleton.FlipX = false;
            }
            else // Going left
            {
                skeletonAnim.skeleton.FlipX = true;
            }
            while (Vector3.Distance(transform.position, targets[0]) > 0.05f)
            {
                transform.position = Vector3.MoveTowards(transform.position, targets[0], Speed * Time.deltaTime);
                ScaleCharacter();
                yield return(null);
            }
            //update current area while moving
            int diff = SceneController.Instance.targetAreaIndex - SceneController.Instance.currentAreaIndex;
            if (diff != 0)
            {
                if (diff > 0)
                {
                    SceneController.Instance.currentAreaIndex++;
                }
                else
                {
                    SceneController.Instance.currentAreaIndex--;
                }
            }
            targets.RemoveAt(0);
        }

        if (source != null && source.orientation != Orientation.UNSPECIFIED)
        {
            if (source.orientation == Orientation.LEFT)
            {
                skeletonAnim.skeleton.FlipX = true;
            }
            else
            {
                skeletonAnim.skeleton.FlipX = false;
            }
        }

        skeletonAnim.AnimationState.SetAnimation(0, "idle", true);

        //calls action after reaching the destination
        if (action != null)
        {
            StateManager.Instance.DispatchAction(action, source);
        }
    }
コード例 #2
0
    void Awake()
    {
        if (LeftPages.Length != RightPages.Length)
        {
            throw new System.Exception("Number of left and right pages must be equal.");
        }
        TotalPages = LeftPages.Length;

        StopReading = new SpringAction(StopReadingAction, null, null);
        FadeIn      = new List <Coroutine>();
    }
コード例 #3
0
ファイル: StateManager.cs プロジェクト: PujaDev/Spring
    /// <summary>
    /// Changes game state depending on dispatched action.
    /// Notifies subscribed changables about these changes.
    /// </summary>
    /// <param name="action">Dispatched action</param>
    /// <param name="actionSource">Interactable that dispatched action</param>
    public void DispatchAction(SpringAction action, IInteractable actionSource = null)
    {
        var newState = State;

        foreach (var reducer in reducers)
        {
            newState = reducer.Reduce(newState, action, actionSource);
        }

        var differences = newState.CompareChanges(State);
        var changed     = differences.Count != 0;

        if (DebugLog)
        {
            Debug.Log("Action " + action.Type);
            if (changed)
            {
                foreach (var d in differences)
                {
                    Debug.Log(d.Value.Count + " changes in " + d.Key);
                    foreach (var change in d.Value)
                    {
                        Debug.Log(change);
                    }
                }
            }
            else
            {
                Debug.Log("No changes.");
            }
        }

        if (!changed)
        {
            return;
        }

        foreach (var changable in Changables)
        {
            changable.OnStateChanged(newState, State);
        }

        State = newState;

        if (!Debug.isDebugBuild)
        {
            File.Delete(SaveDirectory + stateNumToFile(StateNum));
        }


        StateNum++;

        saveStateToFile();
    }
コード例 #4
0
    public void MoveTo(List <Vector3> targets, SpringAction action, IInteractable source)
    {
        if (!Busy)
        {
            if (move != null)
            {
                StopCoroutine(move);
            }

            move = StartCoroutine(MoveToCoroutine(targets, action, source));
        }
    }
コード例 #5
0
    public override GameState Reduce(GameState state, SpringAction action, IInteractable source = null)
    {
        switch (action.Type)
        {
        case ActionType.GIVE_MONEY_TO_SHRINE:
        {
            var used = new HashSet <int>(state.HubaForest.UsedItems);
            used.Add((int)HubaForestInventory.ItemIds.Coin);

            GameState s = state.Set(state.HubaForest.SetUsedItems(used));
            return(s.Set(s.HubaForest.SetIsHubaBlessed(true)));
        }

        case ActionType.BUY_IN_FOREST:
        {
            InventoryAnimator.Instance.Animate();

            // Pickup whatever was bought
            int item     = (int)action.Data;
            var pickedUp = new HashSet <int>(state.HubaForest.PickedUpItems);
            pickedUp.Add(item);

            // Pay with coin
            var used = new HashSet <int>(state.HubaForest.UsedItems);
            used.Add((int)HubaForestInventory.ItemIds.Coin);

            GameState s = state.Set(state.HubaForest.SetPickedUpItems(pickedUp));
            return(s.Set(s.HubaForest.SetUsedItems(used)));
        }

        case ActionType.START_READING_MAP:
            return(state.Set(state.HubaForest.SetIsReadingMap(true)));

        case ActionType.STOP_READING_MAP:
            return(state.Set(state.HubaForest.SetIsReadingMap(false)));

        case ActionType.GO_TO_FOREST:
            return(state.Set(state.HubaForest.SetIsInForest(true)));

        case ActionType.GO_FOREST_LEFT:
            return(GoForestCrossroads(state, ForestSSC.Direction.Left));

        case ActionType.GO_FOREST_RIGHT:
            return(GoForestCrossroads(state, ForestSSC.Direction.Right));

        case ActionType.START_FOREST_SCENE:
            return(state.Set(state.HubaForest.SetIsSceneStarted(true)));
        }

        return(state);
    }
コード例 #6
0
    public bool MoveCharToObject(GameObject obj, SpringAction action = null, IInteractable interactable = null)
    {
        if (!CanCharacterMove)
        {
            if (action != null)
            {
                StateManager.Instance.DispatchAction(action, interactable);
                if (interactable != null && interactable.orientation != Orientation.UNSPECIFIED)
                {
                    GameObject.FindGameObjectWithTag("Character")
                    .GetComponent <SkeletonAnimation>()
                    .skeleton.FlipX = interactable.orientation == Orientation.LEFT;
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }

        RaycastHit2D hit = Physics2D.Raycast(obj.transform.position, -Vector2.up, Mathf.Infinity, 0 | (1 << LayerMask.NameToLayer("WalkableArea")));
        Vector2      destination;

        //Debug.Log(hit.point);
        if (hit.collider == null)
        {
            hit = Physics2D.Raycast(obj.transform.position, Vector2.up, Mathf.Infinity, 0 | (1 << LayerMask.NameToLayer("WalkableArea")));
            //Debug.Log(hit.point);
            destination    = hit.point;
            destination.y += 0.001f;
        }
        else
        {
            destination    = hit.point;
            destination.y -= 0.001f;
        }
        if (hit.collider != null)
        {
            //Debug.Log(hit.collider.name);
            CharacterInput walkableArea = hit.collider.gameObject.GetComponent <CharacterInput>();
            if (walkableArea != null)
            {
                walkableArea.MoveToPoint(destination, action, interactable);
                return(true);
            }
        }

        return(false);
    }
コード例 #7
0
ファイル: Ingredients.cs プロジェクト: PujaDev/Spring
    protected override void Awake()
    {
        base.Awake();

        TakeFlower = new SpringAction(ActionType.TAKE, "Take flower", icons[1], (int)AnnanaInventory.ItemIds.Flower);
        TakeBerry  = new SpringAction(ActionType.TAKE, "Take berry", icons[0], (int)AnnanaInventory.ItemIds.Berry);
        TakeLeaf   = new SpringAction(ActionType.TAKE, "Take leaf", icons[2], (int)AnnanaInventory.ItemIds.Leaf);
        Actions    = new List <SpringAction>
        {
            TakeFlower,
            TakeBerry,
            TakeLeaf
        };
    }
コード例 #8
0
ファイル: CharacterInput.cs プロジェクト: PujaDev/Spring
    // Calculates path for character to move along to reach destination
    public void MoveToPoint(Vector2 destination, SpringAction action = null, IInteractable source = null)
    {
        if (WalkableArea.OverlapPoint(destination)) //checks whether mouse is in the walkable area
        {
            int i;
            int target = -1;
            targets.Clear();
            for (i = 0; i < areas.Length; i++) //checks which area is the destination in
            {
                if (areas[i].OverlapPoint(destination))
                {
                    target = i;
                    break;
                }
            }
            Vector3 tmp;
            i = SceneController.Instance.currentAreaIndex;
            if (target < i) //path through areas with decreasing numbers
            {
                while (i > target)
                {
                    tmp = new Vector3(transPoints[i].position.x, transPoints[i].position.y);
                    targets.Add(tmp);
                    i--;
                }
            }
            else //path through areas with increasing numbers
            {
                while (i < target)
                {
                    tmp = new Vector3(transPoints[i + 1].position.x, transPoints[i + 1].position.y);
                    targets.Add(tmp);
                    i++;
                }
            }
            tmp = new Vector3(destination.x, destination.y);
            targets.Add(tmp);
            SceneController.Instance.targetAreaIndex = target;

            Character.MoveTo(targets, action, source);
        }
    }
コード例 #9
0
ファイル: HubaBusSceneReducer.cs プロジェクト: PujaDev/Spring
    public override GameState Reduce(GameState state, SpringAction action, IInteractable source = null)
    {
        switch (action.Type)
        {
        case ActionType.GET_ELIXIR:
        {
            InventoryAnimator.Instance.Animate();

            // Pickup whatever was delivered
            var pickedUp = new HashSet <int>(state.HubaBus.PickedUpItems);
            var elixir   = state.AnnanaHouse.OwlPackage;
            if (elixir == (int)AnnanaInventory.ItemIds.Antidote)
            {
                pickedUp.Add((int)HubaBusInventory.ItemIds.Antidote);
            }
            else if (elixir == (int)AnnanaInventory.ItemIds.Shrink)
            {
                pickedUp.Add((int)HubaBusInventory.ItemIds.Shrink);
            }
            else if (elixir == (int)AnnanaInventory.ItemIds.Invis)
            {
                pickedUp.Add((int)HubaBusInventory.ItemIds.Invis);
            }
            else if (elixir == (int)AnnanaInventory.ItemIds.Soup)
            {
                pickedUp.Add((int)HubaBusInventory.ItemIds.Soup);
            }
            else
            {
                Debug.Log("opened weird elixir");
            }

            source.gameObject.GetComponent <PackagedElixir>().TogglePackage(false);

            GameState s = state.Set(state.HubaBus.SetPickedUpItems(pickedUp));
            return(s.Set(s.HubaBus.SetisOpened(true)));
        }

        case ActionType.DELIVERY:
        {
            return(state.Set(state.HubaBus.SetisDelivered(true)));
        }

        case ActionType.ARRIVAL:
        {
            return(state.Set(state.HubaBus.SetisBusWaiting(true)));
        }

        case ActionType.DEPARTURE:
        {
            return(state.Set(state.HubaBus.SethasBusLeft(true)));
        }

        case ActionType.EXIT_HOUSE:
        {
            return(state.Set(state.HubaBus.SetisOutOfTheHouse(true)));
        }

        case ActionType.DRINK:
        {
            var used   = new HashSet <int>(state.HubaBus.UsedItems);
            var elixir = state.AnnanaHouse.OwlPackage;
            if (elixir == (int)AnnanaInventory.ItemIds.Antidote)
            {
                used.Add((int)HubaBusInventory.ItemIds.Antidote);
            }
            else if (elixir == (int)AnnanaInventory.ItemIds.Shrink)
            {
                used.Add((int)HubaBusInventory.ItemIds.Shrink);
            }
            else if (elixir == (int)AnnanaInventory.ItemIds.Invis)
            {
                used.Add((int)HubaBusInventory.ItemIds.Invis);
            }
            else if (elixir == (int)AnnanaInventory.ItemIds.Soup)
            {
                used.Add((int)HubaBusInventory.ItemIds.Soup);
            }

            GameState s = state.Set(state.HubaBus.SetUsedItems(used));
            return(s.Set(s.HubaBus.SetisDrunk(true)));
        }

        case ActionType.GET_TICKET:
        {
            var elixir = state.AnnanaHouse.OwlPackage;
            if (elixir == (int)AnnanaInventory.ItemIds.Antidote)
            {
                DialogManager.Instance.SetDialogue((int)HubaBusDialogManager.DialogueTypes.Edible);
                DialogManager.Instance.Next();
            }
            else
            {
                DialogManager.Instance.SetDialogue((int)HubaBusDialogManager.DialogueTypes.Poisonous);
                DialogManager.Instance.Next();
            }
            //source.gameObject.SetActive(false);
            return(state.Set(state.HubaBus.SetaskedForTicket(true)));
        }

        case ActionType.BUY_TICKET:
        {
            var used = new HashSet <int>(state.HubaBus.UsedItems);
            used.Add((int)HubaBusInventory.ItemIds.GoldCoins);

            GameState s = state.Set(state.HubaBus.SetUsedItems(used));
            return(s.Set(s.HubaBus.SetgetOnTheBus(true)));
        }

        case ActionType.IN_THE_BUS:
        {
            return(state.Set(state.HubaBus.SetisInTheBus(true)));
        }
        }

        return(state);
    }
コード例 #10
0
 /// <summary>
 /// Processes dispatched action. Describes how state should change
 /// based on dispatched action and current state.
 /// </summary>
 /// <param name="action">Dispatched action</param>
 /// <param name="state">Current state</param>
 /// <param name="source">Interactable that dispatched action</param>
 /// <returns>Updated state</returns>
 abstract public GameState Reduce(GameState state, SpringAction action, IInteractable source = null);
コード例 #11
0
    void OnMouseDown()
    {
        SpringAction action = new SpringAction(ExitAction, null, null);

        GameController.Instance.MoveCharToObject(gameObject, action);
    }
コード例 #12
0
    public override GameState Reduce(GameState state, SpringAction action, IInteractable source = null)
    {
        switch (action.Type)
        {
        case ActionType.TURN_ALARM_OFF:
            Bed.MoveHandAnimation();
            return(state.Set(state.AnnanaHouse.SetAlarmTurnedOff(true)));

        case ActionType.POSTPONE_ALARM:
            Bed.MoveHandAnimation();
            return(state.Set(state.AnnanaHouse.SetAlarmPostponed(true)));

        case ActionType.RESET_ALARM:
            return(state.Set(state.AnnanaHouse.SetAlarmPostponed(false)));

        case ActionType.CHANGE_CLOTHES:
        {
            string dress = (string)action.Data;
            return(state.Set(state.AnnanaHouse.SetAnnanaDress(dress)));
        }

        case ActionType.START_READING_VEGAN_BOOK:
            return(state.Set(state.AnnanaHouse.SetReadingVeganBook(true).SetReadVeganBook(true)));

        case ActionType.STOP_READING_VEGAN_BOOK:
            return(state.Set(state.AnnanaHouse.SetReadingVeganBook(false)));

        case ActionType.GO_OUTSIDE:
        {
            GameState s = state.Set(state.AnnanaHouse.SetIsOutside(true));
            return(s.Set(s.AnnanaHouse.SetIsInside(false)));
        }

        case ActionType.GO_INSIDE:
        {
            GameState s = state.Set(state.AnnanaHouse.SetIsInside(true));
            return(s.Set(s.AnnanaHouse.SetIsOutside(false)));
        }

        case ActionType.FLY_AWAY:
            return(state.Set(state.AnnanaHouse.SetFlyAway(true)));

        case ActionType.TAKE:
        {
            InventoryAnimator.Instance.Animate();
            int itemId = (int)action.Data;

            switch ((AnnanaInventory.ItemIds)itemId)
            {
            case AnnanaInventory.ItemIds.Flower:
                return(state.Set(state.AnnanaHouse.SetIsFlowerPickedUp(true)));

            case AnnanaInventory.ItemIds.CrystalBall:
                return(state.Set(state.AnnanaHouse.SetIsCrystalBallPickedUp(true)));

            case AnnanaInventory.ItemIds.EmptyVial:
                return(state.Set(state.AnnanaHouse.SetIsEmptyVialPickedUp(true)));

            case AnnanaInventory.ItemIds.Berry:
                return(state.Set(state.AnnanaHouse.SetIsBerryPickedUp(true)));

            case AnnanaInventory.ItemIds.Leaf:
                return(state.Set(state.AnnanaHouse.SetIsLeafPickedUp(true)));

            case AnnanaInventory.ItemIds.NoteAddress:
                return(state.Set(state.AnnanaHouse.SetIsAddressPickedUp(true)));
            }
            break;
        }

        case ActionType.THROW_TO_BOILER:
        {
            int itemId = (int)action.Data;

            // Throw in new item
            HashSet <int> contents = new HashSet <int>(state.AnnanaHouse.BoilerContents);
            contents.Add(itemId);

            GameState s = null;

            switch ((AnnanaInventory.ItemIds)itemId)
            {
            case AnnanaInventory.ItemIds.Flower:
                s = state.Set(state.AnnanaHouse.SetIsFlowerUsed(true));
                break;

            case AnnanaInventory.ItemIds.EmptyVial:
                s = state.Set(state.AnnanaHouse.SetIsEmptyVialUsed(true));
                break;

            case AnnanaInventory.ItemIds.Berry:
                s = state.Set(state.AnnanaHouse.SetIsBerryUsed(true));
                break;

            case AnnanaInventory.ItemIds.Leaf:
                s = state.Set(state.AnnanaHouse.SetIsLeafUsed(true));
                break;

            default:
                break;
            }

            return(s.Set(s.AnnanaHouse.SetBoilerContents(contents)));
        }

        case ActionType.EMPTY_BOILER:
            return(state.Set(state.AnnanaHouse.SetBoilerContents(new HashSet <int>())));

        case ActionType.FILL_ELIXIR:
        {
            InventoryAnimator.Instance.Animate();
            GameState s = state.Set(state.AnnanaHouse.SetIsEmptyVialUsed(true));

            HashSet <int> ingredients = state.AnnanaHouse.BoilerContents;

            var inv = Inventory.Instance as AnnanaInventory;

            var e = inv.Elixirs
                    .Where(x => x.Value.Ingredients.SetEquals(ingredients))
                    .FirstOrDefault();

            if (e.Value == null)         // Unknown elixir = soup
            {
                return(s.Set(s.AnnanaHouse.SetElixirId((int)AnnanaInventory.ElixirTypes.Soup)));
            }

            // Known elixir set it
            return(s.Set(s.AnnanaHouse.SetElixirId(e.Key)));
        }

        case ActionType.GIVE_ADDRESS_TO_OWL:
        {
            GameState s = state.Set(state.AnnanaHouse.SetIsAddressUsed(true));
            return(s.Set(s.AnnanaHouse.SetOwlHasAddress(true)));
        }

        case ActionType.GIVE_PACKAGE_TO_OWL:
        {
            // Assume only elixirs can be sent
            GameState s = state.Set(state.AnnanaHouse.SetIsElixirUsed(true));
            return(s.Set(s.AnnanaHouse.SetOwlPackage((int)action.Data)));
        }

        case ActionType.START_READING_FRIDGE_NOTE:
            return(state.Set(state.AnnanaHouse.SetIsReadingFridgeNote(true).SetDidReadFridgeNote(true)));

        case ActionType.STOP_READING_FRIDGE_NOTE:
            return(state.Set(state.AnnanaHouse.SetIsReadingFridgeNote(false)));
        }

        return(state);
    }
コード例 #13
0
ファイル: IInteractable.cs プロジェクト: PujaDev/Spring
 public bool ComeCloser(SpringAction action = null)
 {
     return(GameController.Instance.MoveCharToObject(gameObject, action, this));
 }
コード例 #14
0
    public override GameState Reduce(GameState state, SpringAction action, IInteractable source = null)
    {
        HashSet <int> newItems;

        switch (action.Type)
        {
        case ActionType.GO_OUTSIDE:
        {
            GameState s = state.Set(state.AnnanaTeaParty.SetIsOutside(true));
            return(s.Set(s.AnnanaTeaParty.SetIsInside(false)));
        }

        case ActionType.GO_INSIDE:
        {
            GameState s = state.Set(state.AnnanaTeaParty.SetIsInside(true));
            return(s.Set(s.AnnanaTeaParty.SetIsOutside(false)));
        }

        case ActionType.TAKE:
            int itemId   = (int)action.Data;
            var oldItems = state.AnnanaTeaParty.PickedUpItems;
            if (Enum.IsDefined(typeof(Item), itemId))
            {
                newItems = new HashSet <int>(oldItems);
                newItems.Add(itemId);
                if (newItems.Equals(oldItems))
                {
                    return(state);
                }

                switch ((Item)itemId)
                {
                case Item.PotEmpty:
                case Item.PotColdWater:
                case Item.PotHotWater:
                    state = state.Set(state.AnnanaTeaParty.SetTeapotOnTheTable(false).SetTeapotOnTheStove(-1));
                    break;
                }

                InventoryAnimator.Instance.Animate();
                return(state.Set(state.AnnanaTeaParty.SetPickedUpItems(newItems)));
            }
            break;

        case ActionType.FILL_TEAPOT:
        {
            InventoryAnimator.Instance.Animate();
            return(state.Set(state.AnnanaTeaParty.SetPickedUpItems(
                                 swap(state,
                                      Item.PotColdWater,
                                      Item.PotEmpty
                                      ))));
        }

        case ActionType.PUT_TEAPON_ON_THE_STOVE:
            var inventory = state.AnnanaTeaParty.PickedUpItems;
            var pots      = new Item[]
            {
                Item.PotEmpty,
                Item.PotColdWater,
                Item.PotHotWater
            };
            var heldPod = Item.None;
            int potId   = -1;
            foreach (var pot in pots)
            {
                potId++;
                if (inventory.Contains((int)pot))
                {
                    heldPod = pot;
                    break;
                }
            }
            return(state.Set(
                       state.AnnanaTeaParty.SetPickedUpItems(
                           remove(state, heldPod)
                           ).SetTeapotOnTheStove(potId)));

        case ActionType.WATER_BOILED:
            return(state.Set(state.AnnanaTeaParty.SetTeapotOnTheStove(2)));

        case ActionType.FILL_CUP:
            return(state.Set(
                       state.AnnanaTeaParty.SetPickedUpItems(
                           remove(state, (Item)action.Data
                                  )).SetWaterInTheCup((int)action.Data)));

        case ActionType.USE_TEA_BAG:
            return(state.Set(
                       state.AnnanaTeaParty.SetPickedUpItems(
                           remove(state, Item.TeaBag
                                  )).SetTeaBagInTheCup(true)));

        case ActionType.STEEP_TEA:
            return(state.Set(state.AnnanaTeaParty.SetWaterInTheCup(0)));

        case ActionType.OVERSTEEP_TEA:
            return(state.Set(state.AnnanaTeaParty.SetWaterInTheCup(3)));

        case ActionType.DRINK_TEA:
            var happy = state.AnnanaTeaParty.WaterInTheCup == 0;
            return(state.Set(
                       state.AnnanaTeaParty
                       .SetPickedUpItems(add(state, Item.Cup))
                       .SetWaterInTheCup(-1)
                       .SetDrankTea(true).SetIsHappy(happy)
                       ));

        case ActionType.WALKED_OUT:
            return(state.Set(state.AnnanaTeaParty.SetInTheKitchen(false)));

        case ActionType.TAKE_FINE:
            return(state.Set(state.AnnanaTeaParty.SetIsReadingTheFine(true).SetTookTheFine(true)));

        case ActionType.FINISH_READING_FINE:
            return(state.Set(state.AnnanaTeaParty.SetIsReadingTheFine(false)));

        case ActionType.FLY_AWAY:
            return(state.Set(state.AnnanaTeaParty.SetOwlFlownAway(true)));

        case ActionType.THROW_CUP:
            return(state.Set(state.AnnanaTeaParty.SetThrewCup(true)));

        case ActionType.UNLOCK_FRIDGE:
            LockManager.Instance.Open();
            break;

        case ActionType.FRIDGE_UNLOCKED:
            return(state.Set(state.AnnanaTeaParty.SetIsLockOpen(true)));
        }

        return(state);
    }