切水果小游戏

这几天跟着视频学做了一个切水果的游戏(用UGUI做的),有点粗糙记录一下。~在导入一些素材包的时候发现一些prefab丢失了,变成了白纸 ( 可能是我的unity版本有点低了╮(╯▽╰)╭)
切水果小游戏_第1张图片
1.png
切水果小游戏_第2张图片
2.png
没办法只能自己动手做几个预设了(apple lemon watermelon以及一些特效)ps:特效没接触过看了下网上的介绍自己尝试着做几个出来 - -

OK,Let's do it!

一、开始页面搭建
1、调整画布以及基本的界面布置
切水果小游戏_第3张图片
3.png

这里我将SoundButton和SoundSlider都放在一个空物体里面,方便管理以及锚点设置。


切水果小游戏_第4张图片
4.png
2、添加一个脚本用来注册点击事件、音量控制、声音播放。

ps:值得一提的是,平时我们注册点击事件都是写一个方法,然后将其拖拽到Button组件的OnClick里实现,这里可以通过监听的方式简化我们的操作。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class UIStart : MonoBehaviour {
    /// 
    /// 开始按钮
    /// 
    private Button PlayButton;

    /// 
    /// 声音按钮
    /// 
    public Button SoundButton;

    /// 
    /// 添加背景音乐
    /// 
    public  AudioSource Audio_Bg;

    /// 
    ///声音的图片 
    /// 
    public Sprite[] soundSprites;

    private Image soundImg;

    /// 
    /// 控制音量滑块
    /// 
    public  Slider soundSlider;

    void Start () {
        getComponents();
        PlayButton.onClick.AddListener(PlayClick);//注册点击事件的第三种方法。监听
        SoundButton.onClick.AddListener(SoundClick);
    }

    void Destory()
    {
        PlayButton.onClick.RemoveListener(PlayClick);
        SoundButton.onClick.RemoveListener(SoundClick);
    }
    /// 
    /// 寻找组件
    /// 
    private void getComponents()
    {
        PlayButton = transform.Find("StartButton").GetComponent

public Sprite[] soundSprites;
private Image soundImg;
这两个字段用于展现静音和开启音乐的效果(2张图片)。

二、游戏界面内容
切水果小游戏_第5张图片
5.png
1、设置背景图片--Background
2、实现发射水果

创建一个空物体Spawner,将其摆放在Bg的中下位置也就是水果发射的初始地点,为其添加一个Box Collider组件用于销毁游戏物体节省内存。
创建一个脚本实现水果、炸弹发射。

using UnityEngine;
using System.Collections;
using UnityEngine;
//本脚本功能为产生水果、炸弹以及销毁超出屏幕的预制体
//产生水果时间、水果发射(速度、方向、反重力)、产生多个水果、

/// 
/// 产生水果、炸弹
/// 
public class Spawn : MonoBehaviour {

    [Header("水果的预设")]
    public GameObject[] Fruits;
    [Header("炸弹的预设")]
    public GameObject Bomb;

    public AudioSource audioSource;
    //产生水果的时间
    float spawnTime = 3f;
    //计时
    float currentTime = 0f;

    bool isPlaying = true;

    void Update () {
        if (!isPlaying)
        {
            return;
        }
        
        currentTime += Time.deltaTime;
        if (currentTime >= spawnTime)
        {
            //产生多个水果
            int fruitCount = Random.Range(1, 5);
            for (int i = 0; i < fruitCount; i++)
            {
                //到时间产生水果
                onSpawn(true);
            }

            //生成炸弹
            int bombNum = Random.Range(0, 100);
            if (bombNum > 70)
            {
                onSpawn(false);
            }
            currentTime = 0f;
        }

    }

    private int tmpZ = 0; //临时存储生成体的Z坐标,前提要保证生成体的Z坐标不会超出摄像机。

    /// 
    /// 产生水果
    /// 
    private void onSpawn(bool isFruit)
    {
        //播放音乐
        this.audioSource.Play();
        //x范围在(-8.4,8.4)之间[生成物UI可显示的范围]
        //y : transform.pos.y
        float x = Random.Range(-8.4f, 8.4f);
        float y = transform.position.y;
        float z = tmpZ;

        //保证生成体的Z坐标不会超出摄像机。(摄像机的Z轴坐标为-12.)
        tmpZ -= 2;
        if (tmpZ <= -10)
        {
            tmpZ = 0;
        }
        //定义一个随机数(水果号码)
        int fruitIndex = Random.Range(0, Fruits.Length);

        GameObject go;
        if (isFruit)
        {
            go = Instantiate(Fruits[fruitIndex], new Vector3(x, y, z), Random.rotation) as GameObject;
        }
        else 
        {
            go = Instantiate(Bomb, new Vector3(x, y, z), Random.rotation) as GameObject;
        }
            //给与一个反重力初始速度,飞行方向相反的
            Vector3 velocity = new Vector3(-x * Random.Range(0.2f, 0.8f), -Physics.gravity.y * Random.Range(1.2f, 1.5f));

            Rigidbody rigidbody = go.GetComponent();
            rigidbody.velocity = velocity;
        
    }
    /// 
    /// 销毁产生的物体
    /// 
    /// 
    private void OnCollisionEnter(Collision other)
    {
        Destroy(other.gameObject);
    }
}

3、生成刀痕

刀痕的生成用Line Renderer

切水果小游戏_第6张图片
6.png

LineRenderer里的Positions 是记录鼠标在滑动的时候记录下来的实时坐标。通过坐标来连成线。
代码中的head和last,分别是每一帧鼠标所在的位置,和上一帧鼠标所在的位置,这个的确有点绕需要自己多理解一下。(鼠标移动的时候每一帧都有变化。)

切水果小游戏_第7张图片
7.png
using UnityEngine;
using System.Collections;

//产生刀痕
//产生射线
public class MouseControl : MonoBehaviour {
    
    /// 
    /// 直线渲染器
    /// 
    [SerializeField]
    private LineRenderer lineRenderer;

    /// 
    /// 播放声音
    /// 
    [SerializeField]
    private AudioSource audioSource;

    /// 
    /// 首次按下鼠标
    /// 
    private bool firstMouseDown = false;

    /// 
    /// 一直按住鼠标
    /// 
    private bool onMouseDown = false;

    /// 
    /// 用于存放渲染器位置坐标
    /// 
    private Vector3[] positions = new Vector3[10];

    /// 
    /// 对渲染直线坐标个数的统计
    /// 
    private int posCount = 0;

    /// 
    /// 存储鼠标按下的第一帧位置
    /// 
    private Vector3 head;

    /// 
    /// 存储上一帧鼠标所在的位置
    /// 
    private Vector3 last;

    void Update () {

        if(Input.GetMouseButtonDown(0))
        {
            firstMouseDown = true;
            onMouseDown = true;
            audioSource.Play();
        }
        if(Input.GetMouseButtonUp(0))
        {
            onMouseDown = false;
        }
        OnDrawLine();
        firstMouseDown = false;
    }

    /// 
    /// 画线
    /// 
    private void OnDrawLine()
    {
        if (firstMouseDown)
        {
            posCount = 0;
            head = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            last = head;
        }
        if (onMouseDown)
        {
            head = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            //根据首次按下时与上一次鼠标的位置的距离来判断是否画线。
            if (Vector3.Distance(head, last) > 0.01f)
            {
                setPositions(head);
                posCount++;
                //发射一条射线
                OnDrawRay(head);
            }
            last = head;
        }
        else
        {
            //放鼠标松开时,清空坐标
            positions = new Vector3[10];
        }
        changePosition(positions);
    }

    /// 
    /// 用来存储坐标
    /// 
    private void setPositions(Vector3 pos)
    {
        
        pos.z = 0;
        if (posCount <= 9)
        {
            for (int i = posCount; i < 10; i++)
            {
                positions[i] = pos;
            }
        }
        else
        {
            //坐标个数大于10,将坐标往上挤,将最新的赋值给第十个坐标[下标为9]
            for (int i = 0; i < 9; i++)
            {
                positions[i] = positions[i + 1];
                positions[9] = pos;
            }
        }
    }

    /// 
    /// 发射射线
    /// 
    private void OnDrawRay(Vector3 worldPos)
    {
        Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
        Ray ray = Camera.main.ScreenPointToRay(screenPos);
        
        ////如果射线检测单一物体时用以下方法
        //RaycastHit hit ;
        //if(Physics.Raycast(ray,out hit))
        //{
        //    //执行内容
        //}

        //由于检测到的物体不止一个所以用hits[] 来检测
        RaycastHit[] hits = Physics.RaycastAll(ray);
        for (int i = 0; i < hits.Length; i++)
        {
            //Destroy(hits[i].collider.gameObject);
            hits[i].collider.gameObject.SendMessage("Oncut",SendMessageOptions.DontRequireReceiver);
        }
    }

    /// 
    /// 改变坐标
    /// 
    /// 
    private void changePosition(Vector3[] positions)
    {
        lineRenderer.SetPositions(positions);
    }
}

效果图:
切水果小游戏_第8张图片
8.png
4、实现水果切半以及特效。
切水果小游戏_第9张图片
9.png

在每一个完成的水果上添加一个脚本叫ObjectControl

using UnityEngine;
using System.Collections;

/// 
/// 物体控制脚本
/// 
public class ObjectControl : MonoBehaviour {
    /// 
    /// 生成一半水果
    /// 
    public  GameObject halfFruit;

    public GameObject Splash;

    public GameObject SplashFlat;

    public GameObject BombSplash;

    public AudioClip Clip;

    private bool dead = false;

    public void Oncut()
    {
        //保证只切割一次
        if (dead) 
        {
            return;
        }
        if (gameObject.name.Contains("Bomb"))
        {
            GameObject bSplash = Instantiate(BombSplash, transform.position, Quaternion.identity)as GameObject;
            ScoreEditor.Instance_.ReduceScore(20);
            Destroy(bSplash,3.0f);
        }
        else
        {
            //实例化2个切半的水果
            for (int i = 0; i < 2; i++)
            {
                GameObject go = Instantiate(halfFruit, transform.position, Random.rotation) as GameObject;
                go.GetComponent().AddForce(Random.onUnitSphere * 5f, ForceMode.Impulse);
                Destroy(go, 2.0f);
            }
            //生成特效

            GameObject Splash1 = Instantiate(Splash, transform.position, Quaternion.identity)as GameObject;
            GameObject Splash2 = Instantiate(SplashFlat, transform.position, Quaternion.identity) as GameObject;
            Destroy(Splash1, 3.0f);
            Destroy(Splash2, 3.0f);
            ScoreEditor.Instance_.AddScore(10);
        }

        AudioSource.PlayClipAtPoint(Clip, transform.position);
        Destroy(gameObject);
        dead = true;
    }
}

5、得分UI以及倒计时
加分与减分:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class ScoreEditor : MonoBehaviour {

    public static ScoreEditor Instance_ = null;

    void Awake()
    {
        Instance_ = this;
    }

    [SerializeField]
    public Text txtScore;

    private int score = 0;

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

    public  void AddScore(int Score)
    {
        score += Score;
        txtScore.text = score.ToString();
    }

    public void ReduceScore(int Score)
    {
        score -= Score;
        if (score <= 0)
        {
            SceneManager.LoadScene("Gameover");
        }
        txtScore.text = score.ToString();

        
    }
}
倒计时:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
/// 
/// 倒计时脚本
/// 
public class showTime : MonoBehaviour
{

    public float time_All = 300;//计时的总时间(单位秒)  
    public float time_Left;//剩余时间  
    public bool isPauseTime = false;
    public Text time;
    // Use this for initialization  
    void Start()
    {
        time_Left = time_All;
    }

    // Update is called once per frame  
    void Update()
    {
        if (!isPauseTime)
        {
            if (time_Left > 0)
                StartTimer();
            else
            {
                SceneManager.LoadScene("Gameover");
            }
        }

    }
    
    ///   
    /// 获取总的时间字符串  
    ///   
    string GetTime(float time)
    {
        return GetMinute(time) + GetSecond(time);

    }

    ///   
    /// 获取小时  
    ///   
    string GetHour(float time)
    {
        int timer = (int)(time / 3600);
        string timerStr;
        if (timer < 10)
            timerStr = "0" + timer.ToString() + ":";
        else
            timerStr = timer.ToString() + ":";
        return timerStr;
    }
    ///   
    ///获取分钟   
    ///   
    string GetMinute(float time)
    {
        int timer = (int)((time % 3600) / 60);
        string timerStr;
        if (timer < 10)
            timerStr = "0" + timer.ToString() + ":";
        else
            timerStr = timer.ToString() + ":";
        return timerStr;
    }
    ///   
    /// 获取秒  
    ///   
    string GetSecond(float time)
    {
        int timer = (int)((time % 3600) % 60);
        string timerStr;
        if (timer < 10)
            timerStr = "0" + timer.ToString();
        else
            timerStr = timer.ToString();

        return timerStr;
    }
}
三、结束界面与数据保存
切水果小游戏_第10张图片
10.png

代码:

using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class Gameover : MonoBehaviour {

    public Text text;
    public Text nowScore;
    public Text bestScore;

    void Start()
    {
        getScore();
    }

    void Update()
    {
    }

    private void getScore()
    {
       
        text.text = ScoreEditor.Instance_.txtScore.text;
        bestScore.text = text.text;
        bstScore(int.Parse(text.text));
        
    }
    private void bstScore(int NowScore)
    {
        
        int bstScore = PlayerPrefs.GetInt("sr", 0);
        Debug.Log(bstScore);

        if (NowScore > bstScore)
        {
            bstScore = NowScore;
        }
        PlayerPrefs.SetInt("sr", bstScore);
        bestScore.text = bstScore.ToString();
    }
    public void OnClick()
    {
        SceneManager.LoadScene("play");

    }

}

NowScore对应上图中“你的分数”里面的text
BestScore对应上图中“你的最高分数”里面的text


11.png

结束,写的很乱,只是以后自己方便看-。- 哈哈哈。

你可能感兴趣的:(切水果小游戏)