AR开发实战Vuforia项目之俄罗斯方块(虚拟按钮的应用)上

一、框架视图

AR开发实战Vuforia项目之俄罗斯方块(虚拟按钮的应用)上_第1张图片

二、关键脚本

VBInputEvent

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;//引用命名空间

public class VBInputEvent : MonoBehaviour,IVirtualButtonEventHandler {

    [HideInInspector]
    //0,1,2,3 表示 null left right rotate
    public int whichButton = 0; //选择的是哪一个虚拟按钮

    //单例模式
    private static VBInputEvent _instance;

    //属性
    public static VBInputEvent Instance {

        get {
            return _instance;
        }
    }


    void Awake() {

        _instance = this; //单例模式赋值
    }


    void Start () {

        //找到所有的虚拟按钮 并逐一注册虚拟按钮事件
        VirtualButtonBehaviour[] vbs = transform.GetComponentsInChildren();
        for (int i = 0; i < vbs.Length; i++)
        {
            vbs[i].RegisterEventHandler(this);
        }

    }
    
    
    void Update () {
        
    }

    /// 
    /// 虚拟按钮点击时候触发事件
    /// 
    /// 
    public void OnButtonPressed(VirtualButtonBehaviour vb)
    {
        switch (vb.VirtualButtonName)
        {
            case "Left":
                whichButton = 1;
                break;
            case "Right":
                whichButton = 2;
                break;
            case "Rotate":
                whichButton = 3;
                break;
            default:
                break;
        }

    }

    /// 
    /// 虚拟按钮松开
    /// 
    /// 
    public void OnButtonReleased(VirtualButtonBehaviour vb)
    {
        whichButton = 0;
    }
}

MyTrackableEventHandler

/*==============================================================================
Copyright (c) 2017 PTC Inc. All Rights Reserved.

Copyright (c) 2010-2014 Qualcomm Connected Experiences, Inc.
All Rights Reserved.
Confidential and Proprietary - Protected under copyright and other laws.
==============================================================================*/

using UnityEngine;
using Vuforia;

/// 
///     A custom handler that implements the ITrackableEventHandler interface.
/// 
public class MyTrackableEventHandler : MonoBehaviour, ITrackableEventHandler
{


    public GameObject arObject;

    #region PRIVATE_MEMBER_VARIABLES

    protected TrackableBehaviour mTrackableBehaviour;

    #endregion // PRIVATE_MEMBER_VARIABLES

    #region UNTIY_MONOBEHAVIOUR_METHODS

    protected virtual void Start()
    {
        mTrackableBehaviour = GetComponent();
        if (mTrackableBehaviour)
            mTrackableBehaviour.RegisterTrackableEventHandler(this);



        //自动对焦功能
        Vuforia.CameraDevice.Instance.SetFocusMode(Vuforia.CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);

        
    }

    #endregion // UNTIY_MONOBEHAVIOUR_METHODS

    #region PUBLIC_METHODS

    /// 
    ///     Implementation of the ITrackableEventHandler function called when the
    ///     tracking state changes.
    /// 
    public void OnTrackableStateChanged(
        TrackableBehaviour.Status previousStatus,
        TrackableBehaviour.Status newStatus)
    {
        if (newStatus == TrackableBehaviour.Status.DETECTED ||
            newStatus == TrackableBehaviour.Status.TRACKED ||
            newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
        {
            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
            OnTrackingFound();
        }
        else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
                 newStatus == TrackableBehaviour.Status.NOT_FOUND)
        {
            Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
            OnTrackingLost();
        }
        else
        {
            // For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
            // Vuforia is starting, but tracking has not been lost or found yet
            // Call OnTrackingLost() to hide the augmentations
            OnTrackingLost();
        }
    }

    #endregion // PUBLIC_METHODS

    #region PRIVATE_METHODS



    protected virtual void OnTrackingFound()
    {
        arObject.SetActive(true);  //发现的时候设置为true
    }


    protected virtual void OnTrackingLost()
    {
        arObject.SetActive(false);
    }

    #endregion // PRIVATE_METHODS
}

Spanwer

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


/// 
/// 方块生成器
/// 
public class Spanwer : MonoBehaviour {

    public GameObject[] standbyGroup;  //跟积分面板一样 持有生成的方块一样  顺序一样  外部拖进去

    

    void Start () {
        SpanwerNext(); //一开始先调用此方法
    }
    
    

    void Update () {
        
    }


    /// 
    /// 生成游戏方块 
    /// 
    public void SpanwerNext() {

        //播放音效
        gameObject.transform.GetComponent().Play();
        //注意获取预制体的方法  非静态也可以调用此方法
        GameObject go = Instantiate(standbyGroup[FindObjectOfType().Next()], transform.position , Quaternion.identity);
        //设置父类对象
        go.transform.parent = this.transform;

        Debug.Log("GoName:::"+go.name);

    }
}

GameManager

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

/// 
/// 游戏管理器
/// 
public class GameManager : MonoBehaviour {

    
    private int score = 0; //定义初始分数
    public Text scoreTxt;  //分数文本

    public AudioSource bgm; //声效

    /// 
    /// 加分的方法
    /// 
    /// 
    public void SetScore(int line) {

        int currentAddScore=(int)Mathf.Pow(line,2);  //行数的2次方

        score += currentAddScore; //分数相加

        if (currentAddScore>0)  //判断当前分数是否大于0
        {
            gameObject.transform.GetComponents()[0].Play();  //播放加分的声效
        }

        scoreTxt.text = "Score:" + '\n' + score.ToString(); //换行
    }

    /// 
    /// 游戏结束的方法
    /// 
    public void SetGameOver() {
        scoreTxt.text = "Game Over!";  //弹出提示
        gameObject.transform.GetComponents()[1].Play(); //播放游戏结束声效
        Time.timeScale = 0; //游戏暂停
        bgm.Stop(); //声效停止播放

    }




}

MyGrid

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

public class MyGrid : MonoBehaviour {

    //单例模式
    private static MyGrid _instance;
    //单例属性
    public static MyGrid Instance {

        get
        {

            return _instance;
        }
    }
    /// 
    /// 单例赋值 
    /// 
    void Awake() {
        _instance = this;
    }

    //定义长宽
    public static int w = 10;
    public static int h = 20;

    //存放所有子物体  已经生成的在游戏场景中的方块
    public Transform[,] grid = new Transform[w,h];



    /// 
    /// 改变旋转
    /// 
    /// 
    /// 
    public Vector2 RoundVector2(Vector2 pos) {

        return new Vector2(Mathf.Round(pos.x),Mathf.Round(pos.y));

    }

    /// 
    /// 判断是否在里面
    /// 
    /// 
    /// 
    public bool IsInside(Vector2 pos) {

        return (pos.x>=0&&pos.x=0); //不能越出边界

    }

    /// 
    /// 是否满行
    /// 
    /// 
    /// 
    public bool IsRowFull(int y) {

        for (int x = 0; x < 2; x++)
        {
            if (grid[x,y]==null)
            {
                return false;
            }
        }

        return true;
    }

    /// 
    /// 删除行
    /// 
    public void DeleteRow(int y) {
        for (int x = 0; x < w; x++)
        {
            Destroy(grid[x,y].gameObject);
            grid[x,y]=null;
        }
    }


    /// 
    /// 减少行 方块往下降一行
    /// 
    public void DecreaseRow(int y) {
        for (int x = 0; x < w; x++)
        {
            if (grid[x,y]!=null)
            {
                grid[x, y - 1] = grid[x, y];
                grid[x, y] = null;
                grid[x, y - 1].position += new Vector3(0,-1,0); //每次下降一
            }
        }

    }


    /// 
    /// 减少行
    /// 
    /// 
    public void DecreaseRowAbove(int y) {

        for (int i = y; i < h; i++)
        {
            DecreaseRow(i);
        }
    }

    /// 
    /// 删除满行 并调用加分的方法
    /// 
    public void DeleteFullRows() {

        int currentLine = 0;

        for (int y = 0; y < h; y++)
        {
            if (IsRowFull(y))
            {
                currentLine++;
                DeleteRow(y);
                DecreaseRowAbove(y+1);
                y--;
            }
        }

        FindObjectOfType().SetScore(currentLine); //寻找这个类中加分的方法


    }

}

Queue

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


/// 
/// 注意脚本执行顺序
/// 
public class Queue : MonoBehaviour {

    public GameObject[] standbyGroup; //存贮方块的数组


    private int[] showGroup; //显示的数组

    public int sgLimit=2; //限制的数量  面板只显示两个提示

    private float timeFrame = 1.0f; //显示计时器   就是1秒走一步的意思

    //外部访问的属性
    public float TimeFrame {

        get {

            return timeFrame;
        }
    }



    void Start () {

        //设置数组的长度
        showGroup = new int[sgLimit];
        FillShowGroup(); //一开始调用 因为一开始就显示
    }
    
    
    void Update () {
        
    }

    /// 
    /// 获取下一个方块坐标的函数  生成游戏对象的方法
    /// 
    /// 
    public int Next() {

        int currentPieces = showGroup[0];  //接收第一个 并返回
        FlushShowGroup();
        FillShowGroup(sgLimit-1);
        return currentPieces;
    }


    /// 
    /// 将积分面板上的第一个游戏对象显示到正式的游戏框架中去
    /// 
    private void FlushShowGroup() {
        //将队列头移除到正式的游戏面板当中
        GameObject[] currentPieces = GameObject.FindGameObjectsWithTag("ShowGroup"); //找到所有方块
        Destroy(currentPieces[0]); //删除积分面板的第一个
        MoveUp(); //方块向上移
    }


    /// 
    /// 向上升
    /// 
    private void MoveUp(int i=0) {
        //递归 依次向上升
        if (i
    /// 将方块都显示在积分面板上 递归方式 把积分面板填满
    /// 
    /// 
    private void FillShowGroup(int i=0) {  //for循环
        if (i
    /// 选择方块,显示在积分面板上
    /// 
    /// 
    private void AddToShowGroup(int i) {

        showGroup[i] = Random.Range(0,standbyGroup.Length); //随机这数组里面的任意一下标

        GameObject go = Instantiate(standbyGroup[showGroup[i]], transform.position + new Vector3(0,i*-5,-1),Quaternion.identity); //实例化游戏物体

        go.transform.parent = this.transform; //实例化出来的方块设置父类对象
    }
}

ARGroups

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

/// 
/// 每一个方块挂载的脚本
/// 
public class ARGroups : MonoBehaviour {


    public float freezingTime = 0.5f; //冻结时间

    private float pressingButtonTime = 0f;  //松开时间

    private float lastFallTime = 0; //丢落时间

    void Start () {
        //一开始不是有效位置 先销毁   方块生成不合法 意思就是碰到生成点  游戏结束
        if (!IsValidGridPos())
        {
            FindObjectOfType().SetGameOver();
            Destroy(this.gameObject);
        }
    }
    
    
    void Update () {

        //监听按下的是哪个按钮
        if (VBInputEvent.Instance.whichButton==1) //按下左键
        {

            pressingButtonTime += Time.deltaTime;

            if (pressingButtonTime>freezingTime)  //判断按下的时间超过冻结时间  
            {
                //移动
                transform.position -= new Vector3(1,0,0);

                if (IsValidGridPos()) //判断是否有效位置  检查合法性   合法更新位置
                {
                    UpDateGrid();  //更新组件
                }
                else    //  不合法退回一个位置
                {
                    transform.position += new Vector3(1,0,0); //位置X轴加1
                }

                pressingButtonTime = 0; //执行完事件重新归零
            }

        }

        if (VBInputEvent.Instance.whichButton==2)   //按下右键
        {
            pressingButtonTime += Time.deltaTime;

            if (pressingButtonTime>freezingTime)
            {
                transform.position += new Vector3(1,0,0);

                if (IsValidGridPos())
                {
                    UpDateGrid();
                }
                else
                {
                    transform.position -= new Vector3(1,0,0);
                }

                pressingButtonTime = 0;
            }
        }

        if (VBInputEvent.Instance.whichButton==3)  //按下旋转按钮
        {
            pressingButtonTime += Time.deltaTime;

            if (pressingButtonTime>freezingTime)
            {
                //旋转
                transform.Rotate(0,0,-90);

                if (IsValidGridPos())
                {
                    UpDateGrid();
                }
                else
                {
                    transform.Rotate(0,0,90);
                }

                pressingButtonTime = 0;
            }


        }


        Fall(); //执行掉落的方法



    }

    /// 
    /// 掉落
    /// 
    void Fall() {

        //当前时间 - 上次掉落时间 是否大于设置的时间 间隔 

        if ((Time.time-lastFallTime)>FindObjectOfType().TimeFrame)
        {

            transform.position -= new Vector3(0,1,0);  //下落一格

            if (IsValidGridPos())  //是否为有效位置  是否合法
            {
                UpDateGrid();
            }
            else    //不合法退回去一个位置 
            {
                transform.position += new Vector3(0,1,0);

                MyGrid.Instance.DeleteFullRows(); //执行删除的方法  下落之后可能满格 执行删除的方法
                FindObjectOfType().SpanwerNext();  //执行生成下一个方块的函数

                enabled = false;
            }

            lastFallTime = Time.time;  //掉落时间重新赋值

        }


    }

    /// 
    /// 是否有效位置
    /// 
    /// 
    private bool IsValidGridPos() {

        foreach (Transform child in transform)
        {
            Vector2 v = MyGrid.Instance.RoundVector2(child.position);

            if (!MyGrid.Instance.IsInside(v))  //是否在边界里面  传递的参数是方块下的每一个子物体的位置
            {
                Debug.Log("检查!方法是否调用了"+this.gameObject.name);
                return false;
            }

            if (MyGrid.Instance.grid[(int)v.x,(int)v.y]!=null&&MyGrid.Instance.grid[(int)v.x,(int)v.y].parent!=this.transform)  //是否碰到其他方块
            {
                Debug.Log("不在有效范围内:"+gameObject.name);
                return false;
            }


        }
        return true;//如果上面判断没有问题就返回真的
    }

    /// 
    /// 更新显示方块的位置
    /// 
    private void UpDateGrid() {

        //循环数组  移除相关方块
        for (int x = 0; x < MyGrid.w; x++)
        {
            for (int y = 0; y < MyGrid.h; y++)
            {
                if (MyGrid.Instance.grid[x,y]!=null)
                {
                    if (MyGrid.Instance.grid[x,y].parent==transform)
                    {
                        MyGrid.Instance.grid[x, y] = null;
                    }
                }

            }
        }


        //重组相关方块  遍历下所有的子物体
        foreach (Transform child in transform)
        {
            Vector2 v = MyGrid.Instance.RoundVector2(child.position);

            MyGrid.Instance.grid[(int)v.x,(int)v.y]=child;
        }
    }
}

三、效果展示

你可能感兴趣的:(AR开发实战Vuforia项目之俄罗斯方块(虚拟按钮的应用)上)