一、框架视图
二、关键脚本
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;
}
}
}