在UNITY中使用面向对象+DMC实现“牧师与魔鬼”

        牧师与魔鬼是一款益智游戏。河边有三个牧师和三个魔鬼。他们都想去这条河的对岸,但只有一艘船,这艘船每次只能载两个人。而且必须有一个人把船从一边开到另一边。如果神父的人数超过了河两边的魔鬼,他们就会被杀死,游戏就结束了。

表现形式:白色方块为牧师,红色方块为魔鬼,棕色矩形为船

交互模式:通过点击游戏实体进行交互,点击牧师或魔鬼,可以进行上下船。通过点击船,可以让船过河。如果船上没有牧师或魔鬼,则无法过河。如果船上已经有两人,则无法上船。

游戏的加载方式:通过创建空对象,挂载场记脚本,在场记的awake方法中进行资源加载。

面向对象设计:有一个单例导演类SSDirector和一个场记类FirstController,还有一个挂载在恶魔和牧师上的PositionInfo脚本。SSDirector和场记交互,场记和游戏对象交互。FirstController实现接口ISceneController,并保存在导演中以供全局访问。

代码如下:

PositionInfo:

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


public interface ISceneController
{//场记接口
    void LoadResources();
    void GameOver(bool win);
    void GameRestart();
    float getBoatPosition();
}
public class SSDirector : System.Object
{
    private static SSDirector instance;
    public ISceneController currentSceneController { get; set;}//记录并提供当前场记的访问
    public static SSDirector getInstance()//提供单例的访问
    {
        if (instance == null)
        {
            instance = new SSDirector();
        }
        return instance;
    }
    public void setFPS(int fps)//提供fps设置
    {
        Application.targetFrameRate = fps;
    }
}

 FirstController

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;

public class FirstController : MonoBehaviour, ISceneController
{
    //需要在unity中将主摄像机拖入
    public GameObject cam;
    //MVC的模型部分
    public GameObject boatObject,leftShore,rightShore,river;//场景元素和船
    public float boatPosition;//船的z坐标
    public int boatArea;//船所在区域(1为左,2为右)
    public GameObject[] left;//左岸的角色
    public GameObject[] right;//右岸的角色
    public GameObject[] boat;//船上的角色
    int leftCount;
    int rightCount;
    int boatCount;
    int leftDevil, rightDevil, leftPriest, rightPriest;//左右的牧师和恶魔数量
    bool gameover;//游戏结束
    bool win;//true为赢,false为输

    public float getBoatPosition()//提供船的z坐标查询
    {
        return boatPosition;
    }

    public void Awake()
    {
        SSDirector director = SSDirector.getInstance();
        director.setFPS(60);
        director.currentSceneController = this;
        director.currentSceneController.LoadResources();
    }

    public void LoadResources()
    {
        left = new GameObject[6];
        right = new GameObject[6];
        boat = new GameObject[2];
        rightCount = 0;
        boatCount = 0;
        leftDevil = 3; rightDevil = 0; leftPriest = 3; rightPriest = 0;
        //加载资源文件,创建游戏对象
        GameObject devil = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/devil"));
        devil.GetComponent<PositionInfo>().UpdatePosition(1, 0);
        left[0] = devil;
        devil.name = "DEVIL";
        GameObject devil2=Instantiate(devil);
        devil2.GetComponent<PositionInfo>().UpdatePosition(1, 1);
        left[1] = devil2;
        devil2.name = "DEVIL";
        GameObject devil3 = Instantiate(devil);
        devil3.GetComponent<PositionInfo>().UpdatePosition(1, 2);
        left[2] = devil3;
        devil3.name = "DEVIL";
        GameObject priest = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/priest"));
        priest.GetComponent<PositionInfo>().UpdatePosition(1, 3);
        left[3] = priest;
        priest.name = "PRIEST";
        GameObject priest2 = Instantiate(priest);
        priest2.GetComponent<PositionInfo>().UpdatePosition(1, 4);
        left[4] = priest2;
        priest2.name = "PRIEST";
        GameObject priest3 = Instantiate(priest);
        priest3.GetComponent<PositionInfo>().UpdatePosition(1, 5);
        left[5] = priest3;
        priest3.name = "PRIEST";
        boatObject = Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/boat"),new Vector3(0,0,-3), Quaternion.identity);
        boatObject.name = "BOAT";
        boatPosition = -3;
        boatArea = 1;
        leftShore=Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/shore"), new Vector3(0, 0, -13), Quaternion.identity);
        rightShore=Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/shore"), new Vector3(0, 0, 13), Quaternion.identity);
        river=Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/water"), new Vector3(0, 0, 0), Quaternion.identity);
    }

    public void GameOver(bool win)
    {
        Debug.Log("WIN");
        Debug.Log("LOST");
        gameover = true;
        this.win = win;
    }

    public void GameRestart()
    {
        for (int i = 0; i < 6; i++)
        {
            if (left[i])
                Destroy(left[i]);
            if (right[i])
                Destroy(right[i]);
        }
        if (boat[0])
            Destroy(boat[0]);
        if (boat[1])
            Destroy(boat[1]);
        Destroy(leftShore);
        Destroy(rightShore);
        Destroy(river);
        Destroy(boatObject);
        LoadResources();
        gameover = false;
    }


    //MVC的视图部分
    void Update()
    {
        if (gameover)
        {   string str;
            if (win)
                str = "YOU WIN";
            else str = "YOU LOST";
                
            if (EditorUtility.DisplayDialog("Confirmation", str, "Yes"))
            {
                GameRestart();
            }
        }
        else if (Input.GetButtonDown("Fire1"))
        {
            Debug.Log("Fired Pressed");
            Debug.Log(Input.mousePosition);

            Vector3 mp = Input.mousePosition; //get Screen Position

            //create ray, origin is camera, and direction to mousepoint
            Camera ca;
            if (cam != null) ca = cam.GetComponent<Camera>();
            else ca = Camera.main;

            Ray ray = ca.ScreenPointToRay(Input.mousePosition);

            //Return the ray's hit
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                print(hit.transform.gameObject.name);
                ClickOn(hit.transform.gameObject);
            }
        }
    }

    //MVC的控制部分
    void ClickOn(GameObject a)
    {
        if (a.name == "DEVIL" || a.name == "PRIEST")
        {
            PositionInfo p = a.GetComponent<PositionInfo>();
            if (p.Area == 3)//Area:1-左岸,2-右岸,3-船上
            {
                if (boatArea == 1)
                {
                    int i = 0;
                    while (left[i] != null) i++;
                    GetDown(a, 1, i);
                    leftCount++;
                    boatCount--;
                }
                else if (boatArea == 2)
                {
                    int i = 0;
                    while (right[i] != null) i++;
                    GetDown(a, 2, i);
                    rightCount++;
                    boatCount--;
                }
            }
            else if (p.Area == 1)
            {
                int i;
                if (boat[0] == null)
                    i = 0;
                else if (boat[1] == null)
                    i = 1;
                else
                    return;
                leftCount--;
                boatCount++;
                GetOn(a, i);
            }
            else if (p.Area == 2)
            {
                int i;
                if (boat[0] == null)
                    i = 0;
                else if (boat[1] == null)
                    i = 1;
                else
                    return;
                rightCount--;
                boatCount++;
                GetOn(a, i);
            }
        }else if (a.name == "BOAT")
        {
            if (boatCount == 0)//船上没人不能过河
                return;
            
            if (boatArea == 1)
            {
                a.transform.position = new Vector3(0, 0, 3);
                boatPosition = 3;
                boatArea = 2;
                if (boat[0] != null)
                {
                    if (boat[0].name == "DEVIL")
                    {
                        leftDevil--;
                        rightDevil++;
                    }
                    else
                    {
                        leftPriest--;
                        rightPriest++;
                    }
                }
                if (boat[1]!=null)
                {
                    if (boat[1].name == "DEVIL")
                    {
                        leftDevil--;
                        rightDevil++;
                    }
                    else
                    {
                        leftPriest--;
                        rightPriest++;
                    }
                }
            }else if(boatArea == 2)
            {
                a.transform.position = new Vector3(0, 0, -3);
                boatPosition = -3;
                boatArea = 1;
                if (boat[0] != null)
                {
                    if (boat[0].name == "DEVIL")
                    {
                        leftDevil++;
                        rightDevil--;
                    }
                    else
                    {
                        leftPriest++;
                        rightPriest--;
                    }
                }
                if (boat[1] != null)
                {
                    if (boat[1].name == "DEVIL")
                    {
                        leftDevil++;
                        rightDevil--;
                    }
                    else
                    {
                        leftPriest++;
                        rightPriest--;
                    }
                }
            }
            checkGameOver();
        }
    }
    void checkGameOver()
    {
        //某一侧的牧师少于恶魔
        if (leftDevil > leftPriest && leftPriest != 0)
        {
            GameOver(false);
        }
        if(rightDevil >rightPriest && rightPriest != 0)
        {
            GameOver(false);
        }
        if (rightDevil+rightPriest==6)
        {
            GameOver(true);
        }
    }
    void GetOn(GameObject a,int boatSeat)//上船
    {
        a.transform.SetParent(boatObject.transform);
        PositionInfo p = a.GetComponent<PositionInfo>();
        switch (p.Area){
            case 1:
                left[p.Index] = null;
                boat[boatSeat] = a;
                p.UpdatePosition(3, boatSeat);
                break;
            case 2:
                right[p.Index] = null;
                boat[boatSeat] = a;
                p.UpdatePosition(3, boatSeat);
                break;
        }
    }
    void GetDown(GameObject a, int Area, int shoreSeat)//下船
    {
        a.transform.SetParent(null);
        PositionInfo p = a.GetComponent<PositionInfo>();
        switch (Area)
        {
            case 1:
                boat[p.Index] = null;
                left[shoreSeat] = a;
                p.UpdatePosition(1, shoreSeat);
                break;
            case 2:
                boat[p.Index] = null;
                right[shoreSeat] = a;
                p.UpdatePosition(2, shoreSeat);
                break;
        }
    }
}

SSDirector:

扫描二维码关注公众号,回复: 17281260 查看本文章
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PositionInfo : MonoBehaviour
{
    //保存位置信息(区域+下标),进行空间上的移动(三维坐标)
    public int Area {set;get;}
    public int Index {set; get;}
    public void UpdatePosition(int a,int b)
    {
        Transform t = this.gameObject.transform;
        switch (a)
        {
            case 1://左岸
                t.position=new Vector3(0,2,-7-2*b);
                break;
            case 2://右岸
                t.position = new Vector3(0,2,7+2*b);
                break;
            case 3://船
                t.position = new Vector3(0,1.25f, SSDirector.getInstance().currentSceneController.getBoatPosition()+b*1.2f-0.6f);
                break;
        }
        Area = a;
        Index = b;
    }
}

完整代码链接:unity游戏开发学习: 交作业专用,不对代码质量负责~ (gitee.com)

运行视频:unity实现牧师与魔鬼_哔哩哔哩_bilibili​​​​​​

因为使用弹窗提示游戏结束,录屏软件有些问题,视频中没有录到。 

猜你喜欢

转载自blog.csdn.net/weixin_66458735/article/details/133967547