HW3_ Priest and devil (action split)

Posted by sfullman on Mon, 18 Oct 2021 19:52:46 +0200

Mode and devil (action separate version)

1. Basic operation drill

Download Fantasy Skybox FREE and build your own game scene
Write a simple summary of the use of game objects

The game objects we use are written in resources. Because the downloaded resources are free and have not been studied in depth, the use of game objects is basically in the stage of realizing some basic actions, such as moving, running, jumping, etc, You can load and control game objects by writing simple scripts.

2. Programming practice

Priest and devil action separate version
In addition, a referee class is designed to notify the scene controller that the game is over when the game reaches the end condition.

  previously, we have implemented the MVC architecture to write the game of priest and devil, which realizes the decoupling between programs to a certain extent. However, the controller we implemented before manages too many matters of the game, such as handling user interaction events, loading game objects, realizing game rules, realizing game object movement, etc. too much content is integrated into the controller, making the controller too bloated. With the expansion of our project, the amount of code continues to increase, The controller becomes unmanageable.
  from the perspective of object-oriented and responsibility, we can use special objects to manage sports, special objects to manage game rules, and so on. Therefore, this improvement is to separate action control and rule control into a separate controller. Write an action manager to manage actions. Write a referee class to judge whether the game is over. When the game is over, notify the scene controller that the game is over.

UML class diagram of action manager

#####Concrete implementation of action separation
The action manager consists of the following six components:

  • CCActionMannager
  • CCMoveToAction
  • CCSequenceAction
  • SSAction
  • SSActionCallback
  • SSActionManager

The responsibilities and relationships of these six components are explained below:

SSAction

SSAction is the base class of all actions and contains properties that are used by all actions.

public class SSAction : ScriptableObject
{
    public bool enable = true;
    public bool destroy = false;

    public GameObject gameObject { get; set; }
    public Transform transform { get; set; }
    public ISSActionCallback callback { get; set; }

    protected SSAction()
    {

    }

    // Start is called before the first frame update
    public virtual void Start()
    {
        throw new System.NotImplementedException();
    }

    // Update is called once per frame
    public virtual void Update()
    {
        throw new System.NotImplementedException();
    }
}

CCMoveToAction

Realize simple movement, that is, the movement used in the last experiment, move an object to the target position and notify completion.

public class CCMoveToAction : SSAction
{
    //destination
    public Vector3 target;
    //speed
    public float speed;

    private CCMoveToAction()
    {

    }

    //Production function (factory mode)
    public static CCMoveToAction GetSSAction(Vector3 target, float speed)
    {
        CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();
        action.target = target;
        action.speed = speed;
        return action;
    }

    // Start is called before the first frame update
    public override void Start()
    {
        
    }

    // Update is called once per frame
    public override void Update()
    {
        //Judge whether it meets the moving conditions
        if (this.gameObject == null || this.transform.localPosition == target)
        {
            this.destroy = true;
            this.callback.SSActionEvent(this);
            return;
        }
        //move
        this.transform.localPosition = Vector3.MoveTowards(this.transform.localPosition, target, speed * Time.deltaTime);
    }
}
SSActionCallback
public interface ISSActionCallback
{
    //Callback function
    void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Competed,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null);
}

SSactionCallback is a platform for action implementation to communicate with action manager.

CCSequenceAction

Realize an action and play the action in sequence.
This is a composite class, which implements the interface of callback function. After each action in the action list is completed, the composite action class will be notified, and the composite class of the upper layer of this class will also be notified after all actions are completed. The combined object and the combined object belong to the same type, and all subsequent actions are realized through composite actions.

public class CCSequenceAction : SSAction, ISSActionCallback
{
    //Action sequence
    public List<SSAction> sequence;
    //Number of repetitions
    public int repeat = -1;
    //Action start pointer
    public int start = 0;

    //Production function (factory mode)
    public static CCSequenceAction GetSSAction(int repeat, int start, List<SSAction> sequence)
    {
        CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();
        action.repeat = repeat;
        action.start = start;
        action.sequence = sequence;
        return action;
    }

    //Initializes the actions in the sequence
    public override void Start()
    {
        foreach (SSAction action in sequence)
        {
            action.gameObject = this.gameObject;
            action.transform = this.transform;
            action.callback = this;
            action.Start();
        }
    }

    //Actions in the run sequence
    public override void Update()
    {
        if (sequence.Count == 0)
            return;
        if (start < sequence.Count)
        {
            sequence[start].Update();
        }
    }

    //Callback processing, triggered when an action is completed
    public void SSActionEvent(SSAction source,
        SSActionEventType events = SSActionEventType.Competed,
        int Param = 0,
        string strParam = null,
        Object objectParam = null)
    {
        source.destroy = false;
        this.start++;
        if (this.start >= sequence.Count)
        {
            this.start = 0;
            if (repeat > 0)
                repeat--;
            if (repeat == 0)
            {
                this.destroy = true;
                this.callback.SSActionEvent(this);
            }
        }
    }

    void OnDestroy()
    {

    }
}

SSActionManager

It is responsible for managing all actions and action combinations, binding game objects to them and controlling the execution or deletion of actions after completion. It also implements the ISSActionCallback interface to receive information about whether actions are completed or not.

public class SSActionManager : MonoBehaviour
{
    //Action set, in dictionary form
    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
    //Waiting to be added to the action queue (the action is about to start)
    private List<SSAction> waitingAdd = new List<SSAction>();
    //Action queue waiting to be deleted (action completed)
    private List<int> waitingDelete = new List<int>();

    protected void Update()
    {
        //Save the actions in waitingAdd
        foreach (SSAction ac in waitingAdd)
            actions[ac.GetInstanceID()] = ac;
        waitingAdd.Clear();

        //Run saved events
        foreach (KeyValuePair<int, SSAction> kv in actions)
        {
            SSAction ac = kv.Value;
            if (ac.destroy)
            {
                waitingDelete.Add(ac.GetInstanceID());
            }else if (ac.enable)
            {
                ac.Update();
            }
        }

        //Destroy actions in waitingDelete
        foreach (int key in waitingDelete)
        {
            SSAction ac = actions[key];
            actions.Remove(key);
            Destroy(ac);
        }
        waitingDelete.Clear();
    }

    //Prepare to run an action, initialize the action and add it to waitingAdd
    public void RunAction(GameObject gameObject, SSAction action, ISSActionCallback manager)
    {
        action.gameObject = gameObject;
        action.transform = gameObject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }

    // Start is called before the first frame update
    protected void Start()
    {

    }

}

See project warehouse for specific code

Referee class implementation

In fact, the code of the referee class has been implemented in the last operation. Now we only need to separate the last implemented check function and write it into a class separately.

using UnityEngine;

namespace CheckApplication {
    public class Check : MonoBehaviour {
        public FirstControllor sceneController;

        protected void Start() {
            sceneController = (FirstControllor)SSDirector.GetInstance().CurrentScenceController;
            sceneController.gameStatusManager = this;
        }

        public int CheckGame() {
            //0 - the game continues, 1 - fails, 2 - succeeds
            int startPriests = (sceneController.startLand.GetRoleNum())[0];
            int startDevils = (sceneController.startLand.GetRoleNum())[1];
            int endPriests = (sceneController.endLand.GetRoleNum())[0];
            int endDevils = (sceneController.endLand.GetRoleNum())[1];
            if (endPriests + endDevils == 6) return 2;
            int[] boatNum = sceneController.boat.GetRoleNumber();
            //Plus the people on board
            if (sceneController.boat.GetBoatSign() == 1) {
                startPriests += boatNum[0];
                startDevils += boatNum[1];
            }
            else {
                endPriests += boatNum[0];
                endDevils += boatNum[1];
            }
            if ((endPriests > 0 && endPriests < endDevils) || (startPriests > 0 && startPriests < startDevils)) {
                return 1;
            }
            return 0;
        }
    }
}

Topics: Unity3d mvc