The fourth assignment of 3D game design – Priest and Demon

#videolinkpriestanddemon

#github link https://github.com/someoneLikeC/PriADev

Game introduction

Game Name: Priests and Demons

Game rules introduction: There are three priests escorting three demons. Now they have arrived in front of a river. There is a boat on the river, which can only carry two people. We have to control the priest to escort the demon across the river. It is worth noting that when the number of priests on one side of the river is less than that of demons, the demons will kill the priests, the escort mission will fail, and there must be at least one person on the boat to move. You need to be smart and think of ways to help the priest successfully complete this escort mission.

Rule table

td>

Current status Player operation Result
The priest or demon is on the shore, and there are vacancies on the boat The player clicks the corresponding demon button or priest on the shore near the side of the boat The corresponding demon or priest gets on the boat
The priest or demon is on the boat The player clicks the button for the demon or priest on the boat The demon or priest is on the shore near the boat
The number of demons on one side is greater than the number of priests Indicates that the player loses
The devil and the priest all went to the other side of the river

Show player wins

There are people on the boat and the boat is not moving The player clicks the ship button The ship sails to the other side

Before starting to implement the game, first create a Resources folder, and then create three folders in it, Prefabs, Scripts, and Materials

GameObject

River

Shape: Cube

Name: River

Scaling parameters: X:10; Y:1; Z:6

River Bank

Shape: Cube

Name: Bank

Scaling parameters: X:10; Y:1; Z:2

Pastor (different pastors just have different colors)

Shape: Cube

Name:Priest

Scaling parameters: X:0.5; Y:1; Z:0.5

Devil (different demons just have different colors)

Shape: Capsule

Name: Devil

Scaling parameters: X:0.5; Y:0.5; Z:0.5

Boat

Shape: Cube

Name: Boat

Scaling parameters: X:0.5; Y:0.25; Z:1.5

Make all objects into prefabs. The creation steps are as follows (taking creating a river as an example):

1. Create the object:

Right-click on the red box area and select Cube

Once created, adjust its position and size in the inspector.

Rename the block to River

2. Add color to objects

Right click on the red box

Select the material in creation and name it riverColor

Click where the arrow points in the inspector and select your favorite color in the color picker box

Just click the left mouse button and drag the material to the River.

3. Create object prefabs (things that are made in advance and can be used directly when needed)

Drag the River to the location pointed by the arrow

After completion, delete River from the scene

Design process

UML diagram

Detailed implementation

controller

SSDirector.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SSDirector : System.Object
{
    // singleton instance
    private static SSDirector _instance;

    public ISceneController currentSceneController { get; set; }

    // https://blog.csdn.net/qiaoquan3/article/details/51339242
    public bool Paused { get { return Time.timeScale == 0; } set { Time.timeScale = value ? 0 : 1; } }

    // get instance anytime anywhare!
    public static SSDirector getInstance()
    {
        if (_instance == null)
        {
            _instance = new SSDirector();
        }
        return _instance;
    }

    public int getFPS()
    {
        return Application.targetFrameRate;
    }

    public void setFPS(int fps)
    {
        Application.targetFrameRate = fps;
    }

    public void NextScene()
    {
        Debug.Log("Waiting next Scene now...");
#if UNITY_EDITOR
        UnityEditor.EditorApplication.isPlaying = false;
        //UnityEditor.EditorApplication.Exit(0);
#else
        Application.Quit();
#endif
    }
}

ISceneController.cs

using System;

/// <summary>
/// Abstact Scene Controller. Interface between scene controllers and the director
/// </summary>
public interface ISceneController
{
    void LoadResources();
    Role[] getRole();
    void Reset();
}

FirstController.cs

using UnityEngine;

public class FirstController : MonoBehaviour,ISceneController
{
    public river river;
    public Boat boat;
    public Bank[] banks = new Bank[2];
    public Role[] devilsAndpriests = new Role[6];

    voidAwake()
    {
        
        SSDirector director = SSDirector.getInstance();
        director.setFPS(60);
        director.currentSceneController = this;
        director.currentSceneController.LoadResources();
        
    }

    // loading resources for the first scene
    public void LoadResources()
    {
        river = new River();
        boat = new Boat();
        for (int i = 0; i < 2; i + + )
        {
            banks[i] = new Bank(i);
            banks[i].SetName("bank" + i);
        }
        for(int i = 0; i < 3; i + + )
        {
            devilsAndpriests[i] = new Role("Priest", new Vector3(2 + i, 0.5f, -3.5f));
            devilsAndpriests[i].SetName("priest" + i);
            devilsAndpriests[i].SetPosition(devilsAndpriests[i].posRight);
        }
        for (int i = 0; i < 3; i + + )
        {
            devilsAndpriests[i + 3] = new Role("Devil", new Vector3(-4 + i, 0.5f, -3.5f));
            devilsAndpriests[i + 3].SetName("devil" + i);
            devilsAndpriests[i + 3].SetPosition(devilsAndpriests[i + 3].posRight);
        }
    }

    public Role[] getRole()
    {
        return devilsAndpriests;
    }

    public void Reset()
    {
        foreach(Role role in devilsAndpriests)
        {
            Destroy(role.character);
        }
        foreach(Bank bank in banks)
        {
            Destroy(bank.bank);
        }
        Destroy(boat.thisboat);
        Destroy(river.river);
        LoadResources();
    }
}

model

Role.cs

using Unity.VisualScripting;
using UnityEngine;

public class Role
{
    public bool isOnBoat;
    public bool isLeft;
    public GameObject character;
    public Vector3 posRight;
    public Vector3 posLeft;
    public Role(string name, Vector3 v)
    {
        character = Object.Instantiate(Resources.Load("Prefabs/" + name, typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
        isOnBoat = false;
        isLeft = false;
        posRight = v;
        posLeft = new Vector3(v.x, v.y, -v.z);
    }

    public void SetName(string name)
    {
        character.name = name;
    }

    public void SetPosition(Vector3 pos)
    {
        character.transform.position = pos;
    }

    public void MoveTo(Boat boat, Bank[] banks)
    {
        if (isOnBoat)
        {
            if (!isLeft)
            {
                if(character.transform.position == boat.pos1)
                {
                    boat.pos1Full = false;
                }else if(character.transform.position == boat.pos2)
                {
                    boat.pos2Full = false;
                }
                character.transform.position = posRight;
                character.transform.SetParent(null);
                isOnBoat = false;
                boat.peopleOnboat--;
                if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
                {
                    boat.P--;
                    banks[0].Pnum + + ;
                }
                else
                {
                    boat.D--;
                    banks[0].Dnum + + ;
                }
            }
            else
            {
                if (character.transform.position == boat.pos1)
                {
                    boat.pos1Full = false;
                }
                else if (character.transform.position == boat.pos2)
                {
                    boat.pos2Full = false;
                }
                character.transform.position = posLeft;
                character.transform.SetParent(null);
                isOnBoat = false;
                boat.peopleOnboat--;
                if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
                {
                    boat.P--;
                    banks[1].Pnum + + ;
                }
                else
                {
                    boat.D--;
                    banks[1].Dnum + + ;
                }
            }
        }
        else
        {
            if(boat.isLeft == isLeft)
            {
                if (!boat.pos1Full)
                {
                    character.transform.position = boat.pos1;
                    boat.pos1Full = true;
                    character.transform.SetParent(boat.thisboat.transform);
                    isOnBoat = true;
                    boat.peopleOnboat + + ;
                    if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
                    {
                        boat.P + + ;
                        if (!isLeft)
                        {
                            banks[0].Pnum--;
                        }
                        else
                        {
                            banks[1].Pnum--;
                        }
                    }
                    else
                    {
                        boat.D + + ;
                        if (!isLeft)
                        {
                            banks[0].Dnum--;
                        }
                        else
                        {
                            banks[1].Dnum--;
                        }
                    }
                }
                else if (!boat.pos2Full)
                {
                    character.transform.position = boat.pos2;
                    boat.pos2Full = true;
                    character.transform.SetParent(boat.thisboat.transform);
                    isOnBoat = true;
                    boat.peopleOnboat + + ;
                    if (character.name == "priest0" || character.name == "priest1" || character.name == "priest2")
                    {
                        boat.P + + ;
                        if (!isLeft)
                        {
                            banks[0].Pnum--;
                        }
                        else
                        {
                            banks[1].Pnum--;
                        }
                    }
                    else
                    {
                        boat.D + + ;
                        if (!isLeft)
                        {
                            banks[0].Dnum--;
                        }
                        else
                        {
                            banks[1].Dnum--;
                        }
                    }
                }
            }
        }
    }
}

River.cs

using UnityEngine;

public class River
{
    public GameObject river;
    public River()
    {
        river = Object.Instantiate(Resources.Load("Prefabs/River", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
        river.name = "river";
    }
}

Boat.cs

using UnityEngine;

public class Boat
{
    public int peopleOnboat;
    public int P;
    public int D;
    public Vector3 pos1;
    public Vector3 pos2;
    public bool pos1Full;
    public bool pos2Full;
    public GameObject thisboat;
    public bool isLeft;
    public Vector3 posLeft;
    public Vector3 posRight;
    
    public Boat()
    {
        peopleOnboat = 0;
        thisboat = Object.Instantiate(Resources.Load("Prefabs/Boat", typeof(GameObject)), new Vector3(0, 0.5f, -2.25f), Quaternion.identity, null) as GameObject;
        thisboat.name = "boat";
        pos1 = thisboat.transform.position + new Vector3(0, 0, 0.3f);
        pos2 = thisboat.transform.position + new Vector3(0, 0, -0.3f);
        pos1Full = false;
        pos2Full = false;
        isLeft = false;
        posLeft = new Vector3(0, 0.5f, 2.25f);
        posRight = new Vector3(0, 0.5f, -2.25f);
    }

    public void Move(Bank[] banks, UserGUI userGUI)
    {
        if(isLeft)
        {
            thisboat.transform.position = posRight;
            pos1 = thisboat.transform.position + new Vector3(0, 0, 0.3f);
            pos2 = thisboat.transform.position + new Vector3(0, 0, -0.3f);
            isLeft = !isLeft;
            foreach(Transform child in thisboat.transform)
            {
                Role[] roles = SSDirector.getInstance().currentSceneController.getRole();
                for (int i = 0; i < roles.Length; i + + )
                {
                    if (roles[i].character.transform == child)
                    {
                        roles[i].isLeft = !roles[i].isLeft;
                    }
                }
            }
            if (banks[1].Pnum + P == 3 & amp; & amp; banks[1].Dnum + D == 3)
            {
                userGUI.Win();
            }
            else if ((banks[0].Dnum + D > banks[0].Pnum + P & amp; & amp; banks[0].Pnum != 0) || (banks[1].Dnum + D > banks [1].Pnum + P & amp; & amp; banks[1].Pnum != 0))
            {
                userGUI.Lose();
            }
        }
        else
        {
            thisboat.transform.position = posLeft;
            pos1 = thisboat.transform.position + new Vector3(0, 0, 0.3f);
            pos2 = thisboat.transform.position + new Vector3(0, 0, -0.3f);
            isLeft = !isLeft;
            foreach (Transform child in thisboat.transform)
            {
                Role[] roles = SSDirector.getInstance().currentSceneController.getRole();
                for (int i = 0; i < roles.Length; i + + )
                {
                    if (roles[i].character.transform == child)
                    {
                        roles[i].isLeft = !roles[i].isLeft;
                    }
                }
            }
            if (banks[1].Pnum + P == 3 & amp; & amp; banks[1].Dnum + D == 3)
            {
                userGUI.Win();
            }
            else if ((banks[0].Dnum > banks[0].Pnum & amp; & amp; banks[0].Pnum != 0) || (banks[1].Dnum > banks[1].Pnum & amp; & amp; banks[1].Pnum != 0))
            {
                userGUI.Lose();
            }
        }
    }

}

Bank.cs

using UnityEngine;

public class Bank
{
    public int Pnum;
    public int Dnum;
    public bool isLeft;
    public GameObject bank;
    publicBank(int id)
    {
        bank = Object.Instantiate(Resources.Load("Prefabs/Bank", typeof(GameObject)), new Vector3(0, 0, 4.0f * (id - 0.5f) * 2), Quaternion.identity, null) as GameObject ;
        if (id == 0)
        {
            Pnum = 3;
            Dnum = 3;
            isLeft = false;
        }
        else
        {
            Pnum = 0;
            Dnum = 0;
            isLeft = true;
        }
    }

    public void SetName(string name)
    {
        bank.name = name;
    }

}

view

IUserAction

public interface IUserAction
{
    void MoveRole(Role role, Boat boat, Bank[] banks);
    void CrossRiver(Boat boat, Bank[] banks);
    void Lose();
    void Win();
    void Reset();
}

UserGUI

using UnityEngine;

public class UserGUI : MonoBehaviour,IUserAction
{
    private int state;

    public UserGUI()
    {
        state = -1;
    }

    public void Win()
    {
        state = 0;
    }

    public void Lose()
    {
        state = 1;
    }

    public void Reset()
    {
        state = -1;
    }

    public void MoveRole(Role role,Boat boat, Bank[] banks)
    {
        role.MoveTo(boat,banks);
    }

    public void CrossRiver(Boat boat, Bank[] banks)
    {
        boat.Move(banks,this);
    }

    private void OnGUI()
    {
        if (GUI.Button(new Rect(35, 25, 70, 30), "Start again")) {
            SSDirector.getInstance().currentSceneController.Reset();
            Reset();
        }
        if(state == -1)
        {
            for (int i = 0; i < GetComponent<FirstController>().devilsAndpriests.Length; i + + )
            {
                if (i < 3)
                {
                    if (GUI.Button(new Rect(20, 60 + i * 35, 100, 30), "Priest" + i + "Get on/off the boat"))
                    {
                        MoveRole(GetComponent<FirstController>().devilsAndpriests[i], GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
                    }
                }

                else
                {
                    if (GUI.Button(new Rect(20, 60 + i * 35, 100, 30), "Devil" + (i - 3) + "Get on/off the boat"))
                    {
                        MoveRole(GetComponent<FirstController>().devilsAndpriests[i], GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
                    }
                }
            }
            if(GetComponent<FirstController>().boat.peopleOnboat > 0)
            {
                if (GUI.Button(new Rect(35, 270, 70, 30), "Sail the boat")) CrossRiver(GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
            }
        }else if(state == 0)
        {
            GUI.Box(new Rect(375, 150, 100, 100), "You win");
        }else if(state == 1)
        {
            GUI.Box(new Rect(375, 150, 100, 100), "You lost");
        }
    }
}