3D游戏设计第四次作业——牧师与恶魔

#视频链接牧师与恶魔

#github链接https://github.com/someoneLikeC/PriADev

游戏介绍

游戏名称:牧师与恶魔

游戏规则介绍:有三个牧师正在押送三个恶魔,现在他们到了一条河前,河面上有一艘船,船上只能承载两个人。我们要控制牧师将恶魔押送过河。值得注意的是:当河的一岸牧师的数量少于恶魔时,恶魔将杀死牧师,押送任务就失败了,船上必须至少有一个人才能移动。聪明的你需要想办法帮助牧师成功完成此次押送任务。

规则表

当前状态玩家操作结果
牧师或恶魔在岸边,船上有空位玩家点击靠近船一侧岸上的相应的恶魔按钮或牧师相应的恶魔或牧师上船
牧师或恶魔在船上玩家点击船上的恶魔或牧师对于的按钮恶魔或牧师上靠近船的岸
其中一侧的恶魔的数量大于牧师的数量——显示玩家输
恶魔和牧师全部到河边另一侧——

显示玩家赢

船上有人且船未移动玩家点击开船按钮船开往另一侧

在开始实现游戏之前先创建一个Resources文件夹,再在其中创建三个文件夹,Prefabs,Scripts,Materials

游戏对象

形状:Cube

名称:River

缩放参数:X:10; Y:1; Z:6

河岸

形状:Cube

名称:Bank

缩放参数:X:10; Y:1; Z:2

牧师(不同牧师只是颜色不同)

形状:Cube

名称:Priest

缩放参数:X:0.5; Y:1; Z:0.5

恶魔(不同恶魔只是颜色不同)

形状:Capsule

名称:Devil

缩放参数:X:0.5; Y:0.5; Z:0.5

形状:Cube

名称:Boat

缩放参数:X:0.5; Y:0.25; Z:1.5

将所有对象都做成预制体。创建步骤如下(以创建河为例):

1. 创建对象:

 

在红框区域鼠标右键点击,选择立方体

创建完成后,在检查器中调整他的位置与大小。

将方块重命名为River

2. 给对象加颜色

在红框处点击鼠标右键

在创建中选择材质,命名为riverColor

在检查器中点击箭头所指位置,在取色框内选择自己喜欢的颜色

将材质通过点击鼠标左键不松手拖动到River上即可

3. 创建对象预制体(就是提前制作好的东西,需要的时候可以直接用)

将River拖到箭头所指的位置即可

完成后将场景中的River删除

设计过程

UML图

具体实现

controller

SSDirector.cs

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

public class SSDirector : System.Object
{
    // singlton 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];

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

    // loading resources for the first scence
    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 && banks[1].Dnum + D == 3)
            {
                userGUI.Win();
            }
            else if ((banks[0].Dnum + D > banks[0].Pnum + P && banks[0].Pnum != 0) || (banks[1].Dnum + D > banks[1].Pnum + P && 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 && banks[1].Dnum + D == 3)
            {
                userGUI.Win();
            }
            else if ((banks[0].Dnum > banks[0].Pnum && banks[0].Pnum != 0) || (banks[1].Dnum > banks[1].Pnum && 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;
    public Bank(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), "重新开始")) {
            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), "牧师" + i + "上/下船"))
                    {
                        MoveRole(GetComponent<FirstController>().devilsAndpriests[i], GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
                    }
                }

                else
                {
                    if (GUI.Button(new Rect(20, 60 + i * 35, 100, 30), "恶魔" + (i - 3) + "上/下船"))
                    {
                        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), "开船")) CrossRiver(GetComponent<FirstController>().boat, GetComponent<FirstController>().banks);
            }
        }else if(state == 0)
        {
            GUI.Box(new Rect(375, 150, 100, 100), "你赢了");
        }else if(state == 1)
        {
            GUI.Box(new Rect(375, 150, 100, 100), "你输了");
        }
    }
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值