首页 > 代码库 > Bow & Arrow

Bow & Arrow

技术分享

技术分享

技术分享
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEditor;

/// <summary>
/// 游戏控制
/// </summary>
public class bowAndArrow : MonoBehaviour {
    
    /// <summary>
    /// Ray
    /// </summary>
    private Ray mouseRay1;
    /// <summary>
    /// RaycastHit
    /// </summary>
    private RaycastHit rayHit;

    /// <summary>
    /// 射线击中的x轴位置
    /// </summary>
    private float posX;
    /// <summary>
    /// 射线击中的y轴位置
    /// </summary>
    private float posY;


    /// <summary>
    /// 弓绳
    /// </summary>
    public GameObject bowString;
    /// <summary>
    ////// </summary>
    GameObject arrow;
    /// <summary>
    /// 箭预设
    /// </summary>
    public GameObject arrowPrefab;
    /// <summary>
    /// 用来作为射出的箭的父物体
    /// </summary>
    public GameObject gameManager;    
    /// <summary>
    /// 伤害文本
    /// </summary>
    public GameObject risingText;
    /// <summary>
    /// 目标
    /// </summary>
    public GameObject target;

    /// <summary>
    /// 拉弓的声音
    /// </summary>
    public AudioClip stringPull;
    /// <summary>
    /// 放箭的声音
    /// </summary>
    public AudioClip stringRelease;
    /// <summary>
    /// 箭飞行的声音
    /// </summary>
    public AudioClip arrowSwoosh;

    /// <summary>
    /// 拉弓的声音是否已播放
    /// </summary>
    bool stringPullSoundPlayed;
    /// <summary>
    /// 放箭的声音是否已播放
    /// </summary>
    bool stringReleaseSoundPlayed;
    /// <summary>
    /// 箭飞行的声音是否已播放
    /// </summary>
    bool arrowSwooshSoundPlayed;

    /// <summary>
    /// 弓的位置
    /// </summary>
    private List<Vector3> bowStringPosition;
    /// <summary>
    /// 弓的线条渲染器
    /// </summary>
    LineRenderer bowStringLinerenderer;


    float arrowStartX;
    float length;

    /// <summary>
    /// 箭是否已射出
    /// </summary>
    bool arrowShot;
    /// <summary>
    /// 箭是否准备好
    /// </summary>
    bool arrowPrepared;

    // position of the line renderers middle part 
    Vector3 stringPullout;
    Vector3 stringRestPosition = new Vector3 (-0.44f, -0.06f, 2f);

    /// <summary>
    /// 游戏状态
    /// </summary>
    public enum GameStates {
        /// <summary>
        /// 目录
        /// </summary>
        menu, 
        /// <summary>
        /// 教程
        /// </summary>
        instructions,
        /// <summary>
        /// 游戏中
        /// </summary>
        game,
        /// <summary>
        /// 游戏结束
        /// </summary>
        over,
        /// <summary>
        /// 最高分
        /// </summary>
        hiscore,
    };

    /// <summary>
    /// 游戏状态
    /// </summary>
    public GameStates gameState = GameStates.menu;

    /// <summary>
    /// 目录面板
    /// </summary>
    public Canvas menuCanvas;
    /// <summary>
    /// 指示面板
    /// </summary>
    public Canvas instructionsCanvas;
    /// <summary>
    /// 最高分面板
    /// </summary>
    public Canvas highscoreCanvas;
    /// <summary>
    /// 游戏面板
    /// </summary>
    public Canvas gameCanvas;
    /// <summary>
    /// 游戏结束面板
    /// </summary>
    public Canvas gameOverCanvas;

    /// <summary>
    /// 箭的数量文本
    /// </summary>
    public Text arrowText;
    /// <summary>
    /// 得分文本
    /// </summary>
    public Text scoreText;
    /// <summary>
    /// 最后得分文本
    /// </summary>
    public Text endscoreText;
    /// <summary>
    /// 最高得分
    /// </summary>
    public Text actualHighscoreText;
    /// <summary>
    /// 新的最高得分
    /// </summary>
    public Text newHighscoreText;
    /// <summary>
    /// 新的最高得分提示文本
    /// </summary>
    public Text newHighText;

    /// <summary>
    /// 每局能使用的箭数量
    /// </summary>
    public int arrows = 20;
    /// <summary>
    /// 实际得分
    /// </summary>
    public int score = 0;


    /// <summary>
    /// 重置游戏
    /// </summary>
    void resetGame() {
        arrows = 20;
        score = 0;
        //如果没有找到arrow,创建新的arrow
        if (GameObject.Find("arrow") == null)
            createArrow (true);
    }


    void Start () {
        //设置ui显隐
        menuCanvas.enabled = true;
        instructionsCanvas.enabled = false;
        highscoreCanvas.enabled = false;
        gameCanvas.enabled = false;
        gameOverCanvas.enabled = false;

        
        initScore ();

        createArrow (true);


        bowStringLinerenderer = bowString.AddComponent<LineRenderer>();
        bowStringLinerenderer.SetVertexCount(3);
        bowStringLinerenderer.SetWidth(0.05F, 0.05F);
        bowStringLinerenderer.useWorldSpace = false;
        bowStringLinerenderer.material = Resources.Load ("Materials/bowStringMaterial") as Material;
        bowStringPosition = new List<Vector3> ();
        bowStringPosition.Add(new Vector3 (-0.44f, 1.43f, 2f));
        bowStringPosition.Add(new Vector3 (-0.44f, -0.06f, 2f));
        bowStringPosition.Add(new Vector3 (-0.43f, -1.32f, 2f));
        bowStringLinerenderer.SetPosition (0, bowStringPosition [0]);
        bowStringLinerenderer.SetPosition (1, bowStringPosition [1]);
        bowStringLinerenderer.SetPosition (2, bowStringPosition [2]);
        arrowStartX = 0.7f;

        stringPullout = stringRestPosition;
    }



    void Update () {
        //检查游戏状态
        switch (gameState) {
        //目录状态,按下esc 退出游戏
        case GameStates.menu:
            if (Input.GetKeyDown(KeyCode.Escape)) {
#if UNITY_EDITOR
                EditorApplication.isPlaying = false;
#else
                Application.Quit();
#endif
            }
            break;

        case GameStates.game:
            
            showArrows();
            showScore();

            //按下esc 显示目录
            if (Input.GetKeyDown(KeyCode.Escape)) {
                showMenu();
            }

            //如果按下鼠标左键
            if (Input.GetMouseButton(0)) {
                //播放拉弓的声音
                if (!stringPullSoundPlayed) {

                    GetComponent<AudioSource>().PlayOneShot(stringPull);
                    stringPullSoundPlayed = true;
                }

                prepareArrow();
            }

            //如果鼠标抬起且箭已准备就绪
            if (Input.GetMouseButtonUp (0) && arrowPrepared) {
                //播放放箭的声音
                if (!stringReleaseSoundPlayed) {
                    GetComponent<AudioSource>().PlayOneShot(stringRelease);
                    stringReleaseSoundPlayed = true;
                }
                //播放箭飞行的声音
                if (!arrowSwooshSoundPlayed) {
                    GetComponent<AudioSource>().PlayOneShot(arrowSwoosh);
                    arrowSwooshSoundPlayed = true;
                }
                shootArrow();
            }
            drawBowString();
            break;
        case GameStates.instructions:
            break;
        case GameStates.over:
            break;
        case GameStates.hiscore:
            break;
        }
    }


    
    /// <summary>
    /// 初始化得分
    /// </summary>
    public void initScore() {
        if (!PlayerPrefs.HasKey ("Score"))
            PlayerPrefs.SetInt ("Score", 0);
    }

    /// <summary>
    /// 显示得分
    /// </summary>
    public void showScore() {
        scoreText.text = "Score: " + score.ToString();
    }

    /// <summary>
    /// 显示箭数量
    /// </summary>
    public void showArrows() {
        arrowText.text = "Arrows: " + arrows.ToString ();
    }


    /// <summary>
    /// 创建箭
    /// </summary>
    /// <param name="hitTarget">是否击中目标</param>
    public void createArrow(bool hitTarget) {
        Camera.main.GetComponent<camMovement> ().resetCamera ();

        stringPullSoundPlayed = false;
        stringReleaseSoundPlayed = false;
        arrowSwooshSoundPlayed = false;

        //如果还有可使用的箭
        if (arrows > 0) {
            //如果击中目标,随机设置目标的位置
            if (hitTarget) {
                float x = Random.Range(-1f,8f);
                float y = Random.Range(-3f,3f);
                Vector3 position = target.transform.position;
                position.x = x;
                position.y = y;
                target.transform.position = position;
            }
            
            //创建一个新箭
            this.transform.localRotation = Quaternion.identity;
            arrow = Instantiate (arrowPrefab, Vector3.zero, Quaternion.identity) as GameObject;
            arrow.name = "arrow";
            arrow.transform.localScale = this.transform.localScale;
            arrow.transform.localPosition = this.transform.position + new Vector3 (0.7f, 0, 0);
            arrow.transform.localRotation = this.transform.localRotation;
            arrow.transform.parent = this.transform;

            arrow.GetComponent<rotateArrow> ().setBow (gameObject);
            arrowShot = false;
            arrowPrepared = false;

            arrows --;
        }
        else {
            gameState = GameStates.over;
            gameOverCanvas.enabled = true;
            endscoreText.text = "You shot all the arrows and scored " + score + " points.";
        }
    }

    /// <summary>
    /// 射箭
    /// </summary>
    public void shootArrow() {
        if (arrow.GetComponent<Rigidbody>() == null) {
            arrowShot = true;
            arrow.AddComponent<Rigidbody>();
            arrow.transform.parent = gameManager.transform;
            arrow.GetComponent<Rigidbody>().AddForce (Quaternion.Euler (new Vector3(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y,transform.rotation.eulerAngles.z))*new Vector3(25f*length,0,0), ForceMode.VelocityChange);
        }
        arrowPrepared = false;
        stringPullout = stringRestPosition;

        Camera.main.GetComponent<camMovement> ().resetCamera ();
        Camera.main.GetComponent<camMovement> ().setArrow (arrow);

    }


    /// <summary>
    /// 准备弓箭
    /// </summary>
    public void prepareArrow() {
        
        mouseRay1 = Camera.main.ScreenPointToRay(Input.mousePosition);

        if (Physics.Raycast(mouseRay1, out rayHit, 1000f) && arrowShot == false)
        {
            posX = this.rayHit.point.x;
            posY = this.rayHit.point.y;

            Vector2 mousePos = new Vector2(transform.position.x-posX,transform.position.y-posY);
            float angleZ = Mathf.Atan2(mousePos.y,mousePos.x)*Mathf.Rad2Deg;
            transform.eulerAngles = new Vector3(0,0,angleZ);

            length = mousePos.magnitude / 3f;
            length = Mathf.Clamp(length,0,1);

            stringPullout = new Vector3(-(0.44f+length), -0.06f, 2f);

            Vector3 arrowPosition = arrow.transform.localPosition;
            arrowPosition.x = (arrowStartX - length);
            arrow.transform.localPosition = arrowPosition;
        }
        arrowPrepared = true;
    }



    /// <summary>
    /// 画弓绳
    /// </summary>
    public void drawBowString() {
        bowStringLinerenderer = bowString.GetComponent<LineRenderer>();
        bowStringLinerenderer.SetPosition (0, bowStringPosition [0]);
        bowStringLinerenderer.SetPosition (1, stringPullout);
        bowStringLinerenderer.SetPosition (2, bowStringPosition [2]);
    }
    

    /// <summary>
    /// 设置得分
    /// </summary>
    /// <param name="points">分数</param>
    public void setPoints(int points){
        
        score += points;
        //如果得分是50
        if (points == 50) {
            //加一可用弓数量
            arrows++;

            //创建提示文本
            GameObject rt1 = (GameObject)Instantiate(risingText, new Vector3(0,0,0),Quaternion.identity);
            rt1.transform.position = this.transform.position + new Vector3(0,0,0);
            rt1.transform.name = "rt1";
            rt1.GetComponent<TextMesh>().text= "Bonus arrow";
        }
    }

    /// <summary>
    /// 隐藏指引面板
    /// </summary>
    public void showInstructions() {
        menuCanvas.enabled = false;
        instructionsCanvas.enabled = true;
    }


    /// <summary>
    /// 显示指引面板
    /// </summary>
    public void hideInstructions() {
        menuCanvas.enabled = true;
        instructionsCanvas.enabled = false;
    }


    /// <summary>
    /// 显示最高得分
    /// </summary>
    public void showHighscore() {
        menuCanvas.enabled = false;
        highscoreCanvas.enabled = true;
        actualHighscoreText.text = "Actual Hiscore: " + PlayerPrefs.GetInt ("Score") + " points";
        newHighscoreText.text = "Your Score: " + score + " points";
        if (score > PlayerPrefs.GetInt("Score"))
            newHighText.enabled = true;
        else
            newHighText.enabled = false;
    }


    /// <summary>
    /// 隐藏最高得分
    /// </summary>
    public void hideHighScore() {
        menuCanvas.enabled = true;
        highscoreCanvas.enabled = false;
        if (score > PlayerPrefs.GetInt ("Score")) {
            PlayerPrefs.SetInt("Score",score);
        }
        resetGame();
    }

    /// <summary>
    /// 检查最高分
    /// </summary>
    public void checkHighScore() {
        gameOverCanvas.enabled = false;
        if (score > PlayerPrefs.GetInt ("Score")) {
            showHighscore();
        }
        else {
            menuCanvas.enabled = true;
            resetGame();
        }
    }

    /// <summary>
    /// 开始游戏
    /// </summary>
    public void startGame() {
        menuCanvas.enabled = false;
        highscoreCanvas.enabled = false;
        instructionsCanvas.enabled = false;
        gameCanvas.enabled = true;
        gameState = GameStates.game;
    }

    /// <summary>
    /// 显示目录
    /// </summary>
    public void showMenu() {
        menuCanvas.enabled = true;
        gameState = GameStates.menu;
        resetGame ();
    }
}
bowAndArrow
技术分享
using UnityEngine;
using System.Collections;

/// <summary>
/// 控制弓箭
/// </summary>
public class rotateArrow : MonoBehaviour {

    /// <summary>
    /// 是否已经
    /// </summary>
    bool collisionOccurred;

    /// <summary>
    /// 箭的头部
    /// </summary>
    public GameObject arrowHead;
    /// <summary>
    /// 伤害文本
    /// </summary>
    public GameObject risingText;
    /// <summary>
    ////// </summary>
    public GameObject bow;

    /// <summary>
    /// 击中目标的声音
    /// </summary>
    public AudioClip targetHit;

    /// <summary>
    /// 透明度
    /// </summary>
    float alpha;
    /// <summary>
    /// 剩余时间
    /// </summary>
    float   life_loss;
    /// <summary>
    /// 颜色
    /// </summary>
    public Color color = Color.white;

    void Start () {
        
        float duration = 2f;
        life_loss = 1f / duration;
        alpha = 1f;
    }



    void Update () {
        //刚体不为空
        if (transform.GetComponent<Rigidbody>() != null) {
            //速度不为0
            if (GetComponent<Rigidbody>().velocity != Vector3.zero) {
                //获取速度
                Vector3 vel = GetComponent<Rigidbody>().velocity;
                //计算旋转角度
                float angleZ = Mathf.Atan2(vel.y,vel.x)*Mathf.Rad2Deg;
                float angleY = Mathf.Atan2(vel.z,vel.x)*Mathf.Rad2Deg;
                //沿着弓箭的轨道旋转箭
                transform.eulerAngles = new Vector3(0,-angleY,angleZ);
            }
        }

        //如果发生了碰撞
        if (collisionOccurred) {
            //改变透明度和颜色
            alpha -= Time.deltaTime * life_loss;
            GetComponent<Renderer>().material.color = new Color(color.r,color.g,color.b,alpha);
            
            //如果透明度为0,删除物体
            if (alpha <= 0f) {
                //创建新的箭
                bow.GetComponent<bowAndArrow>().createArrow(true);
                Destroy(gameObject);
            }
        }
    }


    void OnCollisionEnter(Collision other) {
        //击中的位置 y轴
        float y;
        //得分
        int actScore = 0;

        //如果发生了碰撞
        if (collisionOccurred) {
            //固定箭的位置
            transform.position = new Vector3(other.transform.position.x,transform.position.y,transform.position.z);
            return;
        }

        ///如果碰到边界,销毁箭
        if (other.transform.name == "Cube") {
            bow.GetComponent<bowAndArrow>().createArrow(false);
            Destroy(gameObject);
        }

        //如果碰到了目标
        if (other.transform.name == "target") {
            //播放声音
            GetComponent<AudioSource>().PlayOneShot(targetHit);
            //让速度归零
            GetComponent<Rigidbody>().velocity = Vector3.zero;
            //让刚体不受重力影响
            GetComponent<Rigidbody>().isKinematic = true;
            //让刚体不能发生旋转和位移
            transform.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
            //设置标志位为true
            collisionOccurred = true;
            //隐藏箭头
            arrowHead.SetActive(false);
            
            //修改y轴位置    
            y = other.contacts[0].point.y;
            y = y - other.transform.position.y;

            //射中白圈
            if (y < 1.48557f && y > -1.48691f)
                actScore = 10;
            //射中黑圈
            if (y < 1.36906f && y > -1.45483f)
                actScore = 20;
            //射中篮圈
            if (y < 0.9470826f && y > -1.021649f)
                actScore = 30;
            //射中红圈
            if (y < 0.6095f && y > -0.760f)
                actScore = 40;
            //射中金圈
            if (y < 0.34f && y > -0.53f)
                actScore = 50;

            //创建得分文本
            GameObject rt = (GameObject)Instantiate(risingText, new Vector3(0,0,0),Quaternion.identity);
            rt.transform.position = other.transform.position + new Vector3(-1,1,0);
            rt.transform.name = "rt";
            rt.GetComponent<TextMesh>().text= "+"+actScore;

            bow.GetComponent<bowAndArrow>().setPoints(actScore);
        }
    }

    /// <summary>
    /// 设置弓
    /// </summary>
    /// <param name="_bow"></param>
    public void setBow(GameObject _bow) {
        bow = _bow;
    }
}
rotateArrow
技术分享
using UnityEngine;
using System.Collections;

/// <summary>
/// 相机移动
/// </summary>
public class camMovement : MonoBehaviour {
    /// <summary>
    /// 弓箭
    /// </summary>
    public GameObject arrow;

    void Start () {
        arrow = null;
    }

    public void setArrow(GameObject _arrow) {
        arrow = _arrow;
    }

    /// <summary>
    /// 重置相机位置
    /// </summary>
    public void resetCamera() {
        transform.position = new Vector3 (0, 0, -9.32f);
    }

    void Update () {
        //让摄像机跟随箭头移动
        if (arrow != null) {
            Vector3 position = transform.position;
            float z = position.z;
            position = Vector3.Lerp (transform.position, arrow.transform.position, Time.deltaTime);
            position.z = z;
            transform.position = position;
        }
    }
}
camMovement
技术分享
using UnityEngine;
using System.Collections;


/// <summary>
/// 云层移动
/// </summary>
public class cloudMove : MonoBehaviour {

    /// <summary>
    /// 移动速度
    /// </summary>
    public float speed;
    
    
    void Update () {
        //获得当前位置
        Vector3 position = transform.position;
        //设置新的x值
        position.x += speed;
        //如果超出边界,重新移动到起始位置
        if (position.x > 12f)
            position.x = -12f;
        //设置新的位置
        transform.position = position;
    }
}
cloudMove
技术分享
using UnityEngine;
using System.Collections;

/// <summary>
/// 向上飘的文字
/// </summary>
[RequireComponent(typeof(TextMesh))]
public class RisingText : MonoBehaviour
{
    /// <summary>
    /// 移动的增量
    /// </summary>
    Vector3 crds_delta;
    /// <summary>
    /// 透明度
    /// </summary>
    float   alpha;
    /// <summary>
    /// 每秒减少的透明度
    /// </summary>
    float   life_loss;
    /// <summary>
    /// 相机
    /// </summary>
    Camera  cam;
    
    /// <summary>
    /// 颜色
    /// </summary>
    public Color color = Color.white;
    
    
    void Start()
    {
        //初始透明度
        alpha = 1f;
        cam = GameObject.Find("Main Camera").GetComponent<Camera>();
        //增量设置为向上
        crds_delta = new Vector3(0f, 1f, 0f);
        life_loss = 0.5f;
    }
    
    void Update () 
    {
        //向上移动
        transform.Translate(crds_delta * Time.deltaTime, Space.World);
        
        //修改颜色
        alpha -= Time.deltaTime * life_loss;
        GetComponent<Renderer>().material.color = new Color(color.r,color.g,color.b,alpha);
        
        //如果完全透明,删除物体
        if (alpha <= 0f) Destroy(gameObject);
        
        //让物体朝向相机
        transform.LookAt(cam.transform.position);
        transform.rotation = cam.transform.rotation;        
    }
}
RisingText

视频:https://pan.baidu.com/s/1nva2xWt

项目:https://pan.baidu.com/s/1nvc4t9R

Bow & Arrow