Unity作业3

1、简答并用程序验证

  • 游戏对象运动的本质是什么?

游戏运动本质就是使用矩阵变换(平移、旋转、缩放)改变游戏对象的空间属性。

  • 实现物体的抛物线运动。
public class move1 : MonoBehaviour
{

    private float g = 0.25f;
    private float vx = 2, vy = 1;

    void Update()
    {
        this.transform.position += vx * Vector3.left * Time.deltaTime;
        this.transform.position += vy * Vector3.up * Time.deltaTime;
        vy -= g * Time.deltaTime;
    }
}

2、编程实践

游戏中的事物:

  • 河岸
  • 牧师(priest)
  • 魔鬼(devil)

玩家动作表:

游戏状态 动作 响应
已结束 左键单击重新开始按钮 重新开始游戏
进行中 左键单击人物 在船和其靠近的岸边之间移动(船上最多两人)
左键单击船 如果船上有人物(牧师或魔鬼均可),则船移动到另一端

制作游戏预制:

(船、魔鬼、牧师的模型采用开源资源,分别来自:Lowpoly paper boats、Devil、Supercyan Character Pack Free Sample)

初始化代码:

public class Main : MonoBehaviour
{
    public static MainController controller;
    public static UI ui;
    void Start()
    {
        Object.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Sea"), new Vector3(1.78064036f, 0.428083658f, -2.58708763f), Quaternion.identity);
        controller = new MainController();
        (gameObject.AddComponent(typeof(UI)) as UI).controller = controller;
    }
}

 
MVC架构:

  • Model:Entity、Boat

Entity为人物类,Devil类和Priest类继承人物类

public class Entity
{
    private GameObject obj;
    public int loc; // 位置,0:右岸,1:左岸,2:船上
    public int n;
    public Entity(GameObject obj, int n)
    {
        this.obj = obj;
        this.n = n;
    }
    public void MoveTo(Vector3 vec)
    {
        obj.transform.position = vec;
    }
    public void Rotate()
    {
        if (loc == 0) obj.transform.rotation = Quaternion.Euler(new Vector3(0, -90, 0));
        else if (loc == 1) obj.transform.rotation = Quaternion.Euler(new Vector3(0, 90, 0));
    }
}

public class Devil : Entity
{
    public Devil(GameObject obj, int n) : base(obj, n)
    { }
}

public class Priest : Entity
{
    public Priest(GameObject obj, int n) : base(obj, n)
    { }
}

Boat为船类 

public class Boat
{
    public GameObject obj;
    public int loc; // 位置,0:右边,1:左边
    public Entity left, right;
    public Vector3 leftLoc, rightLoc;
    public Boat(GameObject obj, int loc, Vector3 rightLoc, Vector3 leftLoc)
    {
        this.obj = obj;
        this.loc = loc;
        this.leftLoc = leftLoc;
        this.rightLoc = rightLoc;
    }
    public void DownEntity(Entity e)
    {
        if (e == left)
        {
            left = null;
        }
        else if (e == right)
        {
            right = null;
        }
    }
    public bool Empty()
    {
        return left == null && right == null;
    }
    public void Move()
    {
        if (Empty()) return;
        if (loc == 0)
        {
            obj.transform.position = leftLoc;
            moveEntity();
            loc = 1;
        }
        else
        {
            obj.transform.position = rightLoc;
            moveEntity();
            loc = 0;
        }
    }
    public bool ToLeft(Entity e)
    {
        if (left == null)
        {
            left = e;
            moveEntity();
            return true;
        }
        return false;
    }
    public bool ToRight(Entity e)
    {
        if (right == null)
        {
            right = e;
            moveEntity();
            return true;
        }
        return false;
    }
    private void moveEntity()
    {
        if (left != null) left.MoveTo(obj.transform.position + new Vector3(0, 0, 0.5f));
        if (right != null) right.MoveTo(obj.transform.position + new Vector3(0, 0, -0.5f));
    }

    public void Reset()
    {
        this.right = this.left = null;
        this.loc = 0;
        obj.transform.position = rightLoc;
    }
}
  • View:UI、ClickBoat、ClickEntity

用户交互界面,UI用于显示GUI以及侦听用户点击按钮事件,ClickBoat、ClickEntity用于侦听用户点击人物和船的事件

public class UI : MonoBehaviour
{
    public MainController controller;
    void OnGUI()
    {
        var style = new GUIStyle("button") { fontSize = 20 };
        bool r;
        if (controller.status == 1)
        {
            r = GUI.Button(new Rect(Screen.width / 2 - 130, Screen.height / 2 - 35, 260, 70), "成功! 单击此处重新开始", style);
        }
        else if (controller.status == 2)
        {
            r = GUI.Button(new Rect(Screen.width / 2 - 130, Screen.height / 2 - 35, 260, 70), "失败! 单击此处重新开始", style);
        }
        else return;
        if (r) controller.Restart();
    }

}
public class ClickEntityAction : MonoBehaviour
{
    public MainController controller;
    public Entity entity;
    void OnMouseDown()
    {
        controller.MoveEntity(entity);
    }
}
public class ClickBoatAction : MonoBehaviour
{
    public MainController controller;
    void OnMouseDown()
    {
        controller.MoveBoat();
    }
}
  • Controller:MainController

控制器,接受用户交互界面的输入并调用模型和视图去完成用户的需求

public class MainController
{
    private const int NUM = 3;

    public int status = 0; // 0:正常,1:成功,2:失败

    private Devil[] devils;
    private Priest[] priests;

    private Vector3[] leftVector, rightVector;
    private Vector3 leftBoat, rightBoat;

    private int priestNum, devilNum;
    private Boat boat;

    public MainController()
    {
        devils = new Devil[NUM];
        priests = new Priest[NUM];
        leftVector = new Vector3[2 * NUM];
        rightVector = new Vector3[2 * NUM];
        rightBoat = new Vector3(3.7f, 0.5f, 0);
        leftBoat = new Vector3(-3.6f, 0.5f, 0);

        priestNum = 3;
        devilNum = 3;

        boat = new Boat(Object.Instantiate(
                Resources.Load<GameObject>("Prefabs/Boat"),
                rightBoat, Quaternion.identity) as GameObject, 0, rightBoat, leftBoat);
        ClickBoatAction clickBoat = boat.obj.AddComponent(typeof(ClickBoatAction)) as ClickBoatAction;
        clickBoat.controller = this;

        for (int i = 0; i < 2 * NUM; i++)
        {
            int x = 7 + i;
            rightVector[i] = new Vector3(x, 2, 0);
            leftVector[i] = new Vector3(-x, 2, 0);
        }

        for (int i = 0; i < NUM; i++)
        {
            GameObject obj = Object.Instantiate(
                Resources.Load<GameObject>("Prefabs/Priest"),
                rightVector[i], Quaternion.Euler(0, -90, 0)) as GameObject;
            ClickEntityAction click = obj.AddComponent(typeof(ClickEntityAction)) as ClickEntityAction;
            priests[i] = new Priest(obj, i);
            click.controller = this;
            click.entity = priests[i];

            obj = Object.Instantiate(
                Resources.Load<GameObject>("Prefabs/Devil"),
                rightVector[3 + i], Quaternion.Euler(0, -90, 0)) as GameObject;
            click = obj.AddComponent(typeof(ClickEntityAction)) as ClickEntityAction;
            devils[i] = new Devil(obj, 3 + i);
            click.controller = this;
            click.entity = devils[i];
        }

    }
    public void Restart()
    {
        priestNum = 3;
        devilNum = 3;
        for (int i = 0; i < NUM; i++)
        {
            priests[i].loc = 0;
            devils[i].loc = 0;
            priests[i].MoveTo(rightVector[i]);
            devils[i].MoveTo(rightVector[3 + i]);
            priests[i].Rotate();
            devils[i].Rotate();
        }
        this.boat.Reset();
        status = 0;
    }

    private void moveToBoat(Entity e)
    {
        if(boat.ToLeft(e) || boat.ToRight(e))
        {
            e.loc = 2;
        }
    }

    private void moveFromBoat(Entity e)
    {
        int loc = boat.loc;
        Vector3[] vec = (loc == 0 ? rightVector : leftVector);
        e.MoveTo(vec[e.n]);
        e.loc = loc;
        e.Rotate();
        boat.DownEntity(e);

        int leftPriestNum = NUM - priestNum, leftDevilNum = NUM - devilNum;
        if (leftPriestNum == NUM && leftDevilNum == NUM && boat.Empty())
        {
            status = 1;
        }
    }

    public void MoveBoat()
    {
        if (status != 0) return;
        boat.Move();
        int rightDeta = (boat.loc == 0 ? 1 : -1);
        if (boat.left as Priest != null)
        {
            priestNum += rightDeta;
        }
        if (boat.right as Priest != null)
        {
            priestNum += rightDeta;
        }
        if (boat.left as Devil != null)
        {
            devilNum += rightDeta;
        }
        if (boat.right as Devil != null)
        {
            devilNum += rightDeta;
        }

        int leftPriestNum = NUM - priestNum, leftDevilNum = NUM - devilNum;
        if ((devilNum > priestNum || leftDevilNum > leftPriestNum) && priestNum != NUM && leftPriestNum != NUM)
        {
            status = 2;
        }
    }

    public void MoveEntity(Entity e)
    {
        if (status != 0) return;
        if (e.loc == boat.loc)
        {
            moveToBoat(e);
        }
        else if (e.loc == 2)
        {
            moveFromBoat(e);
        }
    }
}

演示:

开始游戏

开始游戏

 左键单击操作人物和船

游戏失败

 游戏成功

 

 

文章来源地址https://uudwc.com/A/P3Xo

阅读剩余 90%

原文地址:https://blog.csdn.net/lingyouuuuu/article/details/127478254

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年06月14日 21:48
Unity用户手册2020.3(三)
下一篇 2023年06月14日 21:48