【3D游戏】与游戏世界交互

1、编写一个简单的鼠标打飞碟(Hit UFO)游戏
  • 游戏内容要求:
    1. 游戏有n个round,每个round都包括10次trial;
    2. 每个trial的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该round的ruler控制;
    3. 每个trial的飞碟有随机性,总体难度随round上升;
    4. 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。
  • 游戏的要求:
    • 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源Singleton模板类
    • 尽可能使用前面MVC结构实现人机交互与游戏模型分离
游戏规则
  • 按空格开始新Trial,场景中会有随机颜色飞碟由随机的角度和速度发射出来。
  • 鼠标点击飞碟使其爆炸,每成功打爆一个飞碟加100分。
  • 打爆当前Trial中的所有飞碟才可以进入下一Trial,一个Round共10个Trial。
SceneController
  • 接口IUserAction中包含有发射飞碟和打爆飞碟两个用户行为
	public interface IUserAction {
        void launchUFO();
        void hitUFO(Vector3 mousePos);
    }
  • 接口IGameStatusOp中包含有记分员需要调用的方法,加减分数和获取回合数
    public interface IGameStatusOp {
        int getRoundNum();
        void addScore();
        void subScore();
    }
  • 场景单实例
	private static SceneController instance;    //单实例         
    public static SceneController getInstance() {
        if (instance == null) instance = new SceneController();
        return instance;
    }
UFOFactory

由于飞碟对象需要频繁地创建和销毁,我们使用带缓存的工厂模式管理不同飞碟的生产和回收,用两个列表分别缓存使用中的飞碟和空闲飞碟。detectingLandingUFOs()检测飞碟是否落地,RecyclingUFO()检测飞碟是否被击中,这两种情况下飞碟都会被工厂回收。当需要发射飞碟时就查找freeUFOList,找不到则创建新的飞碟。

public class UFOFactory : System.Object {
    private static UFOFactory instance;                                        //单实例
    private List<GameObject> usedUFOList = new List<GameObject>();            //使用列表
    private List<GameObject> freeUFOList = new List<GameObject>();           //空闲列表
    private GameObject UFOItem;

    public static UFOFactory getInstance() {
        if (instance == null) instance = new UFOFactory();
        return instance;
    }

    public GameObject getUFO() {
        if(freeUFOList.Count == 0) {
            GameObject newUFO = Camera.Instantiate(UFOItem);
            usedUFOList.Add(newUFO);
            return newUFO;
        }
        else {
            GameObject oldUFO = freeUFOList[0];
            freeUFOList.RemoveAt(0);
            oldUFO.SetActive(true);
            usedUFOList.Add(oldUFO);
            return oldUFO;
        }
    }

    public void detectLandingUFOs() {
        for(int i = 0; i < usedUFOList.Count; i++) {
            if(usedUFOList[i].transform.position.y <= -8) {
                usedUFOList[i].GetComponent<Rigidbody>().velocity = Vector3.zero;
                usedUFOList[i].SetActive(false);
                freeUFOList.Add(usedUFOList[i]);
                usedUFOList.Remove(usedUFOList[i]);
                i--;
            }
        }
    }

    public void RecyclingUFO(GameObject UFOObject) {
        UFOObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
        UFOObject.SetActive(false);
        freeUFOList.Add(UFOObject);
        usedUFOList.Remove(UFOObject);
    }
    
    public bool isLaunching() {
        return (usedUFOList.Count > 0);
    }

    public void initItems(GameObject ufoItem) {
        UFOItem = ufoItem;
    }
}
StatusController

记分员受场记SceneController的调度,提供加分、减分、自动进入下一Round的功能,也实现了 打爆当前Trial中的所有飞碟才可以进入下一Trial 这一规则。

	public int getRoundNum() { return roundNum; }

    void addRoundNum() {
        roundNum++;
        roundText.GetComponent<Text>().text = "Round: " + roundNum + " Trial: " + trialNum;
    }

    public int getScore() {
        return score;
    }

    public int getTrialNum() { return trialNum; }

    public void addScore() {
        score += 100;
        scoreText.GetComponent<Text>().text = "Score: " + score + " / " + scoreUpBound;

        Debug.Log(scoreUpBound);

        if (score >= scoreUpBound) {
            trialNum++;
            updateScoreUpBound();
            roundText.GetComponent<Text>().text = "Round: " + roundNum + " Trial: " + trialNum;
            resetScore();
            showTipsText();
        }
        if (trialNum > 10) {
            addRoundNum();
            trialNum = 1;
            roundText.GetComponent<Text>().text = "Round: " + roundNum + " Trial: " + trialNum;
            updateScoreUpBound();
            resetScore();
            showTipsText();
        }
    }

    private void updateScoreUpBound() {
        scoreUpBound = trialNum > 3 ? 300 : trialNum * 100;
    }

    private void showTipsText() {
        TipsText.GetComponent<Text>().text = "Round " + roundNum + ": Trial " + trialNum + "!";
        TipsText.SetActive(true);
        StartCoroutine(waitForSomeTimeAndDisappearTipsText());
    }

    IEnumerator waitForSomeTimeAndDisappearTipsText() {
        yield return new WaitForSeconds(TIPS_TEXT_SHOW_TIME);
        TipsText.SetActive(false);
    }

    public void resetScore() {
        score = 0;
        scoreText.GetComponent<Text>().text = "Score: " + score + " / " + scoreUpBound;
    }

    public void subScore() {
        score = score >= 100 ? score - 100 : 0;
        scoreText.GetComponent<Text>().text = "Score: " + score + " / " + scoreUpBound;
    }
UFOController

作为飞碟管理者,实现每个trial发射的飞碟的色彩、发射位置、速度、角度、同时出现的个数都可能不同,并判定用户控制鼠标的动作是否打中了飞碟,并且添加了打爆飞碟时的爆炸特效。

UserInterface

作为用户交互的接口,实现检测鼠标点击和检测按下空格两个方法。

void Update () {
        if (Input.GetMouseButtonDown(0)) {
            Vector3 mousePos = Input.mousePosition;
            action.hitUFO(mousePos);
        }
        if (Input.GetKeyDown(KeyCode.Space)) {
            action.launchUFO();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值