做一个简单的射靶游戏

简介

就是。。一个简单的射靶游戏, 有随机的风向,越接近靶心分数越高。

对象处理

我们。。需要一支箭和一个靶。。
靶由5个圆柱体拼接而成,然后在父对象那里挂载刚体主件,5个子对象分别挂载mesh collider组件
这里写图片描述
箭由箭头(圆柱体),箭身(圆柱体),箭尾(两个相交的平面)构建而成
这里写图片描述
同样,父对象挂刚体,子对象挂碰撞器,然后。。我们就可以写代码啦。。

UML

其实这个UML图跟上次的打飞碟的 UML图大同小异,就把Disk改为Arrow就行啦
这里写图片描述

代码

这里就只展示跟之前不同的部分
DiskData对应ArrowScript

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

public class ArrowScript : MonoBehaviour {
    public string shootring;
    private ScoreRecorder recorder;

    void OnTriggerEnter(Collider other) {
        shootring = other.gameObject.tag;
        Destroy(GetComponent<Rigidbody>());
        recorder.Record(shootring);
    }

    void Awake() {
        recorder = (ScoreRecorder)FindObjectOfType(typeof(ScoreRecorder));
    }
}

记分系统稍微改改

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

public class ScoreRecorder : MonoBehaviour {
    private float score;

    public float getScore() {
        return score;
    }

    public void Record(string target_ring) {
        switch (target_ring) {
        case "Ring10": score += 10; break;
        case "Ring8": score += 8; break;
        case "Ring6": score += 6; break;
        case "Ring4": score += 4; break;
        case "Ring2": score += 2; break;
        }
    }

    public void Reset() {
        score = 0;
    }
}

UI加入风速

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

public interface IUserAction {
    void shoot();
}

public class UserGUI : MonoBehaviour {
    private IUserAction action;
    private float width, height;
    private string countDownTitle;
    public RoundActionManager actionmanager;

    void Start() {
        countDownTitle = "Start";
        action = Director.getInstance().currentSceneController as IUserAction;
    }

    float castw(float scale) {
        return (Screen.width - width) / scale;
    }

    float casth(float scale) {
        return (Screen.height - height) / scale;
    }

    void OnGUI() {
        width = Screen.width / 12;
        height = Screen.height / 12;

        GUI.Label(new Rect(castw(2f)+20, casth(6f) - 20, 50, 50), ((RoundController)Director.getInstance().currentSceneController).leaveSeconds.ToString());
        GUI.Button(new Rect(580, 10, 80, 30), ((RoundController)Director.getInstance().currentSceneController).scoreRecorder.getScore().ToString());

        if (Director.getInstance().currentSceneController.state != State.WIN && Director.getInstance().currentSceneController.state != State.LOSE
            && GUI.Button(new Rect(10, 10, 80, 30), countDownTitle)) {

            if (countDownTitle == "Start") {
                countDownTitle = "Pause";
                Director.getInstance().currentSceneController.Resume();
            } else {
                countDownTitle = "Start";
                Director.getInstance().currentSceneController.Pause();
            }
        }

        if (Director.getInstance().currentSceneController.state == State.WIN) {
            if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Win!")) Director.getInstance().currentSceneController.Restart();
        } else if (Director.getInstance().currentSceneController.state == State.LOSE) {
            if (GUI.Button(new Rect(castw(2f), casth(6f), width, height), "Lose!")) Director.getInstance().currentSceneController.Restart();
        }
    }

    public Text windforce;
    public Text winddirection;

    void Update() {

        action.shoot();
        float force = actionmanager.getWindForce();
        if (force < 0)
            winddirection.text = "风向 : 左";
        else if (force > 0)
            winddirection.text = "风向 : 右";
        else
            winddirection.text = "风向 : 无";

        windforce.text = "风力 : " + actionmanager.getWindForce();
        action.shoot();
    }
}

动作管理器

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

public class RoundActionManager : SSActionManager, ISSActionCallback {
    public RoundController scene;
    private float speed = 20.0f;
    private float force = 0f;

    public void shootArrowAction(GameObject arrow, Vector3 dir) {
        arrow.transform.position = new Vector3(0, 0, -9);
        arrow.transform.up = dir;
        arrow.GetComponent<Rigidbody>().velocity = dir * speed;
    }

    public void wind(GameObject arrow, float time) {   
        if(time % 2 == 0) force = UnityEngine.Random.Range(-30, 30);
        if(arrow != null && arrow.GetComponent<Rigidbody>() != null) {
            arrow.GetComponent<Rigidbody>().AddForce(new Vector3(force, 0, 0), ForceMode.Force);
        }
    }

    public float getWindForce() {
        return force;
    }

    protected void Start() {
        scene = (RoundController)Director.getInstance().currentSceneController;
        scene.actionManager = this;
    }

    protected new void Update() {
        base.Update();
    }

    public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0,
        string strParam = null,
        Object objectParam = null) {
    }
}

控制器

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

public enum State { WIN, LOSE, PAUSE, CONTINUE, START };

public class RoundController : MonoBehaviour, IUserAction, ISceneController {

    public ArrowFactory arrowFactory;
    public RoundActionManager actionManager;
    public ScoreRecorder scoreRecorder;
    public List<GameObject> arrow;
    public GameObject new_arrow;
    public GameObject target;

    public State state { get; set; }
    public int leaveSeconds;
    IEnumerator DoCountDown() {
        while (leaveSeconds >= 0) {
            yield return new WaitForSeconds(1);
            leaveSeconds--;
        }
    }

    void Awake() {
        Director director = Director.getInstance();
        director.setFPS(60);
        director.currentSceneController = this;
        Director.getInstance().currentSceneController.state = State.PAUSE;

        arrowFactory = Singleton<ArrowFactory>.Instance;
        scoreRecorder = Singleton<ScoreRecorder>.Instance;

        state = State.PAUSE;
        leaveSeconds = 60;
    }

    void Start () {
        actionManager = GetComponent<RoundActionManager>() as RoundActionManager;
        LoadResources();
    }

    void Update() {
        RecycleArrow ();
        Judge(); 
    }

    private void FixedUpdate() {
        actionManager.wind(new_arrow, leaveSeconds);
    }

    public void LoadResources() {
        Camera.main.transform.position = new Vector3(0, 0, -10);
        target =  GameObject.Instantiate(Resources.Load("Prefabs/Target")) as GameObject;
        target.transform.position = new Vector3(0, 0, 3);
    }

    public void shoot() {
        if (Input.GetMouseButtonDown(0) && (state == State.START || state == State.CONTINUE)) {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            new_arrow = arrowFactory.GetArrow();
            arrow.Add(new_arrow);

            actionManager.shootArrowAction(new_arrow, ray.direction);
        }
    }

    public void RecycleArrow() {
        for(int i = 0; i < arrow.Count; i++) {
            if(arrow[i].transform.position.y < -10 || arrow[i].transform.position.z > 15) {
                arrowFactory.FreeArrow(arrow[i]);
                arrow.Remove(arrow[i]);
            }
        }
    }

    public void Judge() {
        if (leaveSeconds == 0 && scoreRecorder.getScore() < 100) {
            StopAllCoroutines();
            state = State.LOSE;
        }
        else if ((leaveSeconds > 0 && scoreRecorder.getScore() >= 100)) {
            StopAllCoroutines();
            state = State.WIN;
        }

    }

    public void Pause() {
        state = State.PAUSE;
        StopAllCoroutines();
        for (int i = 0; i < arrow.Count; i++) {
            arrow [i].SetActive (false);
        }
    }

    public void Resume() {
        StartCoroutine(DoCountDown());  
        state = State.CONTINUE;
        for (int i = 0; i < arrow.Count; i++) {
            arrow[i].SetActive(true);
        }
    }

    public void Restart() {
        scoreRecorder.Reset();
        Application.LoadLevel(Application.loadedLevelName);
        Director.getInstance().currentSceneController.state = State.START;
    }

}

工厂模式

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

public class ArrowFactory : MonoBehaviour {

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

    public GameObject GetArrow() {
        GameObject a_arrow;
        if (free.Count > 0) {
            a_arrow = free[0];
            free.Remove(free[0]);
        } else {
            a_arrow = GameObject.Instantiate(Resources.Load("prefabs/Arrow")) as GameObject;
        }
        a_arrow.SetActive(true);
        used.Add(a_arrow);
        return a_arrow;
    }

    public void FreeArrow(GameObject disk) {
        for(int i = 0; i < used.Count; i++) {
            if(used[i] == disk) {
                disk.SetActive(false);
                used.Remove(used[i]);
                free.Add(disk);
            }
        }
    }
}

大概就这么多啦,还是得说一句。。这个框架实在是好用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值