Unity3D学习(8)之射箭游戏

射箭游戏:
靶对象为 5 环,按环计分,最内环为5分,最外环为1分,出靶则-2分;
箭对象,射中后要插在靶上;
游戏无限轮,每轮10 trials达到要求分数即可进入下一轮
增强要求:
    添加一个风向和强度标志,提高难度
游戏成品图

首先讲下靶的建立,新建一个空对象,下面挂上5个圆柱体,让他们粗细不一方便触发器触发判断相应的分数。弓和箭则是我上网下载的模型
 
首先编写Target.js
public class Target : MonoBehaviour {
    public int num;//每个靶都有特定的分数
    public Emit3 EmitDisk;
    public ShootController sceneController;//场记
    public void Start()
    {
        sceneController = (ShootController)SSDirector.getInstance().currentScenceController;
    }
    void OnTriggerEnter(Collider other)
    {
        Debug.Log(other.gameObject.tag);
        if (other.gameObject.tag == "Arrow")
        {
            if (!other.gameObject.GetComponent<DiskData3>().hit)
            {
                other.gameObject.GetComponent<DiskData3>().hit = true;
                Debug.Log(num);
                sceneController.score += num;//加分
            }
            EmitDisk = (Emit3)other.gameObject.GetComponent<DiskData3>().action;
            //print(this.gameObject);
            other.gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;//插在箭靶上
            EmitDisk.Destory();//动作完成
        }
    }
}
我们可以直接复用SSDirector,SSAction,SSActionManager,Singleton。这些我就不列出内容了,之前的博客有。
我们需要编写ShootControler
public class ShootController : MonoBehaviour, ISceneController, IUserAction
{
    public ShootAction actionManager { get; set; }
    public DiskFactory1 factory { get; set; }
    public GameObject Arrow;
    public GameObject Bow;
    public Emit3 EmitDisk;
    public int score = 0;
    public int round = 0;//轮数
    public int game = 0;//记录游戏进行情况
    public int num = 0;//换风的方向
    public int time = 0;//每轮箭的个数
    public Text GameText;//倒计时文本
    public Text FinalText;//结束文本
    public Text RoundText;//轮数文本
    public Text ScoreText;//分数文本
    public Text WindText;//风向文本
    private string Horizontal = "";
    private string Vertical = "";
    public static float directionX;
    public static float directionY;
    public int CoolTimes = 3; //准备时间
    void Awake()
    //创建导演实例并载入资源
    {
        SSDirector director = SSDirector.getInstance();
        director.setFPS(60);
        director.currentScenceController = this;
        director.currentScenceController.LoadResources();
    }
    // Use this for initialization
    void Start () {
        round = 1;
        directionX = Random.Range(-1, 1);//设置风的水平方向
        directionY = Random.Range(-1, 1);//设置风的竖直方向
    }
	
	// Update is called once per frame
	void Update () {
        RoundText.text = "Round:" + round.ToString();//显示轮数
        ScoreText.text = "Score:" + score.ToString();//本来应该写一个记分员的但我偷懒写在场记这里
        if(directionX > 0)
        {
            Horizontal = "EAST";
        }
        else if(directionX < 0)
        {
            Horizontal = "WEST";
        }
        if (directionY > 0)
        {
            Vertical = "NORTH";
        }
        else if(directionY < 0)
        {
            Vertical = "SOUTH";
        }                                                                                               根据大小显示相应的东南西北
        WindText.text = "WindDirection: " + Vertical + " " + Horizontal;
        if(time == 10)
        {   //每轮10箭判断分数是否达标
            if(score > 35 * round)
            {
                round++;
                time = 0;
                num = 0;
            }
            else
            {
                GameOver();
                game = 2;
            }
        }
        if (num == 3)//每3个箭变一次风的方向
        {
            num = 0;
            directionX = Random.Range(-1, 1);
            directionY = Random.Range(-1, 1);
        }
    }                                                                                               
    public void GameOver()
    {
        FinalText.text = "Game Over!!!";
    }                                                                                               
    public void StartGame()
    {
        num = 0;
        if (game == 0)
        {
            game = 3;
            StartCoroutine(waitForOneSecond());
        }
    }                                                                                               
    public IEnumerator waitForOneSecond()
    {
        while (CoolTimes >= 0 && game == 3)
        {
            GameText.text = CoolTimes.ToString();
            print("还剩" + CoolTimes);
            yield return new WaitForSeconds(1);
            CoolTimes--;
        }
        GameText.text = "";
        game = 1;
    }                                                                                               
    public void ReStart()
    {
        SceneManager.LoadScene("task2");
        game = 0;
    }                                                                                               
    public void ShowDetail()
    {
        GUI.Label(new Rect(220, 50, 350, 250), "Press Enter to Emit a Arrow,10 Arrow for each round.Press up,down,left,right to change your position.Try to get Good Grade!!!");
    }                                                                                               
    public void hit()
    {
        if(game == 1)
        {
            actionManager.playArrow();
            num++;
            time++;
        }
    }                                                                                               //载入资源
    public void LoadResources()
    {
        Instantiate(Resources.Load("prefabs/Target"));
        Arrow =  Instantiate(Resources.Load("prefabs/Arrow01"))as GameObject;
        Bow = Instantiate(Resources.Load("prefabs/Bow01")) as GameObject;
        Arrow.transform.parent = Bow.transform;
        Arrow.transform.localEulerAngles = new Vector3(90, 0, -90);
    }
}
再写Diskfactory1
public class DiskFactory1 : MonoBehaviour {
    private static DiskFactory1 _instance;
    public ShootController sceneControler { get; set; }
    public Recorder scoreRecorder;
    GameObject arrow;
    public List<GameObject> used;
    public List<GameObject> free;
    private void Awake()
    {
        if (_instance == null)
        {
            _instance = Singleton<DiskFactory1>.Instance;
            _instance.used = new List<GameObject>();
            _instance.free = new List<GameObject>();
        }
    }
    // Use this for initialization
    void Start () {
        sceneControler = (ShootController)SSDirector.getInstance().currentScenceController;
        sceneControler.factory = this;
        arrow = Instantiate(Resources.Load("prefabs/Arrow01")) as GameObject;
        arrow.transform.parent = sceneControler.Bow.transform;
        arrow.transform.localEulerAngles = new Vector3(90, 0, -90);
        free.Add(sceneControler.Arrow);
    }
    public GameObject getArrow(int round)
    {
        GameObject newArrow;
        if (free.Count == 0)
        {
            newArrow = GameObject.Instantiate(Resources.Load("prefabs/Arrow01")) as GameObject;
        }
        else
        {
            newArrow = free[0];
            free.Remove(free[0]);
        }
        newArrow.transform.position = arrow.transform.position;
        newArrow.transform.parent = sceneControler.Bow.transform;
        newArrow.transform.localEulerAngles = new Vector3(90, 0, -90);
        used.Add(newArrow);
        return newArrow;
    }
    public void freeArrow(GameObject arrow1)
    {
        for (int i = 0; i < used.Count; i++)
        {
            if (used[i] == arrow1)
            {
                used.Remove(arrow1);
                arrow1.SetActive(true);
                free.Add(arrow1);
            }
        }
        return;
    }
}


然后编写ShootActionManager
public class ShootActionManager : SSActionManager, ISSActionCallback, ShootAction
{
    public ShootController sceneController;
    public DiskFactory1 ArrowFactory;
    public Recorder scoreRecorder;
    public GameObject Arrow;
    public Emit3 EmitArrow;
    protected void Start()
    {
        sceneController = (ShootController)SSDirector.getInstance().currentScenceController;
        ArrowFactory = sceneController.factory;
        sceneController.actionManager = this;
    }

    protected new void Update()
    {
        base.Update();
    }                                                                                               
    public void playArrow()
    {
        EmitArrow = Emit3.GetSSAction();
        Arrow = ArrowFactory.getArrow(sceneController.round);
        this.RunAction(Arrow, EmitArrow, this);
        Arrow.GetComponent<DiskData3>().action = EmitArrow;
    }                                                                                               
    public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
        int intParam = 0, string strParam = null, Object objectParam = null)
    {
        ArrowFactory.freeArrow(source.gameobject);
        Debug.Log("free");
        source.gameobject.GetComponent<DiskData3>().hit = false;
    }
}

ShootAction接口
public interface ShootAction
{
    void playArrow();
}

Emit3
public class Emit3 : SSAction
{
    int count = 0;
    bool enableEmit = true;
    Vector3 force;
    public ShootController sceneControler = (ShootController)SSDirector.getInstance().currentScenceController;
    public static Emit3 GetSSAction()
    {
        Emit3 action = ScriptableObject.CreateInstance<Emit3>();
        return action;
    }
    // Use this for initialization
    public override void Start()
    {
        force = new Vector3(0, 0.3f, 2);
        gameobject.transform.parent = null;
	}

    // Update is called once per frame
    public override void Update()
    {
		
	}

    public void Destory()
    {
        this.destroy = true;
        this.callback.SSActionEvent(this);
        Destroy(gameobject.GetComponent<BoxCollider>());
    }

    public override void FixedUpdate()
    {
        count++;
        if (!this.destroy)
        {
            if (enableEmit)
            {
                gameobject.GetComponent<Rigidbody>().velocity = Vector3.zero;
                gameobject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
                enableEmit = false;
            }
        }
        if(count == 60) //60帧之后才加碰撞器
        {
            gameobject.AddComponent<BoxCollider>();
        }
    }
}

UserGUI
public class UserGUI1 : MonoBehaviour {
    private IUserAction action;
    public bool isButtonDown = false;
    // Use this for initialization
    void Start()
    {
        action = SSDirector.getInstance().currentScenceController as IUserAction;
    }
    void OnGUI()
    {
        GUIStyle fontstyle1 = new GUIStyle();
        fontstyle1.fontSize = 50;
        fontstyle1.normal.textColor = new Color(255, 255, 255);
        if (GUI.RepeatButton(new Rect(0, 0, 120, 40), "Shooting"))
        {
            action.ShowDetail();
        }
        if (GUI.Button(new Rect(0, 60, 120, 40), "STARTGAME"))
        {
            action.StartGame();
        }
        if (GUI.Button(new Rect(0, 120, 120, 40), "RESTART"))
        {
            action.ReStart();
        }
        if (Input.GetMouseButtonDown(0) && !isButtonDown)
        {
            action.hit();
            isButtonDown = true;
        }
        else if(Input.GetMouseButtonDown(0) && isButtonDown)
        {
            isButtonDown = false;
        }
    }
}

为了弓移动我编写了MoveBow
public class MoveBow : MonoBehaviour {
    public float speedX = 0.01f;
    public float speedY = 0.01f;
    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
        float translationY = Input.GetAxis("Vertical") * speedY;
        float translationX = Input.GetAxis("Horizontal") * speedY;
        translationY *= Time.deltaTime;
        translationX *= Time.deltaTime;
        transform.Translate(0, translationY, 0);
        transform.Translate(0, 0, -translationX);
    }
}

为了产生风,在箭与靶之间加了透明区域的触发器,在触发器内会产生风
public class CreatWind : MonoBehaviour {
    public ShootController sceneController;
    public void Start()
    {
        sceneController = (ShootController)SSDirector.getInstance().currentScenceController;
    }
    private void OnTriggerStay(Collider other)
    {
        if (other.gameObject.tag == "Arrow")
        {
            other.gameObject.GetComponent<Rigidbody>().AddForce(new Vector3(ShootController.directionX * sceneController.round, ShootController.directionY * sceneController.round, 0));
            Debug.Log("wind");
        }
    }
}

这样就大功告成了~~~
有兴趣的可以去我的GIthub看,这是 传送门

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值