Unity3D-打飞碟

游戏介绍

(注:之后希望在此项目基础上修改为动画可变的小游戏,于是采用了水果模型代替飞碟)

游戏有 10个 round,每个 round 都包括若干次trial;
每个 trial 的飞碟(水果)的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。飞碟根据飞碟样式分别记为1-3分,分数越高,平均移动速度越快;
每个 trial 的飞碟有随机性,总体难度随 round 上升,体现为增加所有样式飞碟的速度,要求分数提高;
鼠标点中飞碟即可得分。

每个round有目标分数,达到了则离开晋级下一关,未达到则游戏失败。

(测试下来难度还是非常高的,可以一试,改为切水果或许能更具游玩性)

打飞碟作业


代码仓库:派大星星行/Unity3D_LAB3

游戏结构:

参考设计模式:

57857fd0a97b4a038a1b893cb5fb945a.png

本个实验结构较为简单,没有采用动作分类等模式,设计模式如下,随后展示部分重要代码:

a08518b7edd54619a35c11503f6b0813.png

 

1.工厂模式

该项目的核心在于使用对象池实现带缓冲的创建、销毁对象的工厂模式。

创建对象的工厂模式是一种软件设计模式,用于封装对象的实例化过程。它通过提供一个公共的接口或基类来创建对象,而不是直接调用对象的构造函数。这样可以使代码更加灵活、可扩展和可维护。

首先,我们使用list结构首先了工厂中的对象池。

        使用对象池是在工厂模式中常见的一种技术手段。对象池包含两个主要部分:正在使用的对象池和空闲对象池。

        正在使用的对象池存储当前正在被使用的对象实例。这些对象已经通过工厂方法创建并提供给客户端使用。当客户端不再需要某个对象时,该对象将被释放并返回到空闲对象池中,以供其他客户端重新使用。

        空闲对象池存储可以被重复使用的对象实例。这些对象已经被创建并初始化,但当前没有被任何客户端使用。通过将这些对象存储在空闲对象池中,可以避免频繁地创建和销毁对象,从而提高性能和效率。

public class DiskFactory : MonoBehaviour

{

 

    private List<GameObject> free = new List<GameObject>();

    private List<GameObject> used = new List<GameObject>();

        然后在工厂中利用对象池,定义创建、“销毁”产品的工厂方法,提供产品接口。

代码中没有展示的DiskAttributes是承载disk基本属性及点击控制的自定义组件。

    public void GetDisk(int round)

    {

        GameObject disk;

        if (free.Count != 0)

        {

            disk = free[0];

            free.Remove(disk);

        }

        else

        {

            rand = new System.Random();

            int IScore = rand.Next(1, 4);

            if (IScore == 1)

                disk = GameObject.Instantiate(Resources.Load("Banana", typeof(GameObject))) as GameObject;

            else if (IScore == 2)

                disk = GameObject.Instantiate(Resources.Load("Hamburger", typeof(GameObject))) as GameObject;

            else

                disk = GameObject.Instantiate(Resources.Load("Cheese", typeof(GameObject))) as GameObject;

            disk.AddComponent<DiskAttributes>();

            disk.GetComponent<DiskAttributes>().score = IScore;

            disk.GetComponent<DiskAttributes>().fdisk = disk;

        }

 

        Rigidbody rb = disk.GetComponent<Rigidbody>();

        rb.useGravity = true;

 

        float initialSpeed = 10f; // 初始速度

        // initialSpeed = initialSpeed*(1f + ((float)round)/10);

        float angle = 75f; // 发射角度

        float randomX = Random.Range(-8f, 6f);

        float randomZ = Random.Range(-3f, -4f);

 

        // 将角度转换为弧度

        float radianAngle = angle * Mathf.Deg2Rad;

 

        // 水平速度和垂直速度

        float horizontalSpeed = initialSpeed * Mathf.Cos(radianAngle);

        float verticalSpeed = initialSpeed * Mathf.Sin(radianAngle) *(1.25f + ((float)round)/15);

       

        // 施加初始速度的力

        Vector3 launchVelocity = new Vector3(-horizontalSpeed, verticalSpeed, 0f);

        if (randomX < 0)

        {

            launchVelocity.x = -launchVelocity.x; // 将向左抛的物体的水平速度取反

        }

        rb.velocity = launchVelocity;


 

        disk.transform.position = new Vector3(randomX, -3.6f, randomZ);

        used.Add(disk);

        disk.SetActive(true);

    }

 

    public void FreeDisk(GameObject disk)

    {

        Rigidbody rigidbody = disk.GetComponent<Rigidbody>();

 

        // 停止飞碟的运动并重置速度

        rigidbody.Sleep();

        disk.SetActive(false);

        //将位置和大小恢复到预制

        disk.transform.position = new Vector3(0f, -10f, 0f);

        // Debug.Log("free disk");

        used.Remove(disk);

        free.Add(disk);

    }

 

    }

 

2.ScoreController

作为计分的专职场记,为更高层的控制器提供分数记录、重置、查询接口。不在乎分数外的转换细节。

public class ScoreController : MonoBehaviour

{

    private int score;

    public ScoreController(){

        score = 0;

    }

    public void reset(){

        score = 0;

    }

    public void Start(){

        reset();

    }

   

    public void Record(int s)

    {

        score += s;

    }

    public int GetScore(){

        return score;

    }

 

}

3.RoundController

作为轮次转换的专职场记,拥有一个分数场记对象,根据当前局数制定转换条件与游戏参数,根据其分数场记判断游戏状态。为核心控制器。

public class RoundController : MonoBehaviour

{

    private ScoreController scoreController;

    public int targetScore; // 每轮所需达到的目标分数

    public float roundDuration; // 每轮的时间限制

 

    public int currentRound; // 当前关卡

    public float timer; // 计时器

    public bool isGameOver; // 游戏是否结束

    public string StateTip;

 

    public RoundController(){

        targetScore = (4 + 8) * 2;

        roundDuration = 25f;

        currentRound = 1;

        timer = 0f;

        isGameOver = false;

        scoreController = new ScoreController();

        StateTip = "在水果落地前抓住它!";

    }

 

    public void SetRoundController(int round){

        targetScore = (round*4 + 8) * 2;

        roundDuration = 25f;

        currentRound = round;

        timer = 0f;

        isGameOver = false;

        scoreController.reset();

        StateTip = "在水果落地前抓住它!";

    }

 

    public void Record(int s){

        scoreController.Record(s);

    }

 

    public int GetScore(){

        return scoreController.GetScore();

    }

    public bool CheckGameState(){

        if(timer > roundDuration){

            if(scoreController.GetScore() >= targetScore){

                if(currentRound == 10){

                    isGameOver = true;

                    StateTip = "恭喜你完成全部关卡!";

                    return isGameOver;

                }

                SetRoundController(currentRound + 1);

                isGameOver = false;

                return isGameOver;

            }else{

                isGameOver = true;

                StateTip = "太多水果掉在地上,你的挑战失败了!";

                return isGameOver;

            }

        }

        return isGameOver;

    }

 

}

4.firstController

场景的主控制器,负责使用单例对象使用飞碟工厂的接口驱动游戏,初始化roundControl等控制器,挂载userGUI视图,实现游戏场景的更新。(其余代码请查阅仓库)

public class FirstController : MonoBehaviour

{

    private RoundController roundController;

    private GUIView view;

 

    public void Record(int s){

        roundController.Record(s);

    }


 

    void Awake()

    {

        // 创建ScoreController实例并分配给scoreController属性

        roundController = new RoundController();

 

        // 设置单例对象中只有唯一一个主控制器

        SingleObject instance = SingleObject.getInstance();

        instance.SetMainController(this);

        instance.SetDiskFactory(new DiskFactory());

        view = gameObject.AddComponent<GUIView>() as GUIView;

        view.SetView(roundController);

    }

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值