方块消除
一.引擎
游戏工程地址在文末
开发:unity3d 2020.1.1
音乐:au
美术:ps
二.游戏流程
图示
游戏
主要分为两个大的部分:
游戏部分:
市面上的方块消除游戏主要分为:
1.方块生成区
2.游戏放置区
UI部分:
UI部分我们统一使用我们自己封装的DLFramwork框架管理!
三.研发阶段
1.导入框架DLFramwork
这个是自己封装的框架!主要作用是封装了一些通用的内容,比如音频系统,ui系统,数据存储系统,游戏系统等等
2.Game游戏入口
这里我强调一点,我们写代码尽量拥有自己的名称空间,不然多人开发的时候容易乱!我的是DLAM什么意思呢,你们猜猜??(文末有注解)
Game脚本是整个游戏的唯一入口:
Init函数:初始化框架
Onstart函数:通过框架创建游戏
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DLBASE;
namespace DLAM
{
public class Game : GameBase
{
public override void _Init()
{
SysManager.InitSys();
SysManager.LoadSys<GameSys>(SysEnum.GameSys);
SysManager.LoadSys<UISys>(SysEnum.GameSys);
SysManager.LoadSys<AudioSys>(SysEnum.GameSys);
SysManager.LoadSys<GameDataSys>(SysEnum.GameSys);
}
public override void _OnStart()
{
GameMgr gameMgr = SysManager.GetSys<GameSys>(SysEnum.GameSys).CreatGame<GameMgr>();
gameMgr.InitMgr();
gameMgr.StartMgr();
}
}
}
3.GameMgr游戏管理类
这个类是通过游戏系统创建出来的,所以我继承了GameSys基类和IMgr接口
主要用来管理游戏进程,管理其他的管理器!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DLBASE;
namespace DLAM
{
/// <summary>
/// 游戏管理类
/// </summary>
public class GameMgr : GameSys, IMgr
{
public GameBoradMgr GameBoradMgr;
public OperatingMgr OperatingMgr;
public EffectMgr EffectMgr;
public void InitMgr()
{
GameBoradMgr = new GameBoradMgr();
OperatingMgr = new OperatingMgr();
EffectMgr = new EffectMgr();
GameBoradMgr.InitMgr();
OperatingMgr.InitMgr();
}
public void StartMgr()
{
GameBoradMgr.StartMgr();
OperatingMgr.StartMgr();
}
public void UpdateMgr()
{
}
public void EndMgr()
{
}
}
}
4.BlockMgr主要提供可供全局访问的方块数组,是静态类
这个类里面的元素在GameBoradMgr管理类里面初始化,方便在游戏存储的时候访问
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DLAM
{
public static class BlockMgr
{
//游戏方块
public static Block[,] Block;
//游戏背景
public static BlockBg[,] BlockBg;
//当前剩余的可放置的方块
public static int BlockIndex = 3;
}
}
5.GameBoradMgr 游戏区管理类
这个类主要用来管理游戏填充区域,主要用来生成游戏背景和游戏方块
Block方块类
基础类,主要是修改方块的基础类型,包括类型,颜色,等等
namespace DLAM
{
public class Block : GameBase
{
public SpriteRenderer m_Sprite;
private Vector2 m_Pos;
public void InitBlock(int type,Vector2 pos)
{
}
public void SetArrayPos(Vector2 pos)
{
m_Pos = pos;
}
public Vector2 GetArrayPos()
{
return m_Pos;
}
public void UpLayer()
{
m_Sprite.sortingOrder = 100;
}
public void DownLayer()
{
m_Sprite.sortingOrder = 10;
}
}
}
BlockBg方块背景类
方块背景类,主要修改方块背景的虚线框,是否填充,数组位置等等
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DLBASE;
namespace DLAM
{
public class BlockBg : GameBase
{
public GameObject m_Bg;
public GameObject m_White;
private Vector2 m_Pos;
private bool m_Isfill;
public void SetArrayPos(Vector2 pos)
{
m_Pos = pos;
}
public Vector2 GetArrayPos()
{
return m_Pos;
}
public void ShowHightBox()
{
m_White.SetActive(true);
}
public void CloseHightBox()
{
m_White.SetActive(false);
}
public bool GetFill()
{
return m_Isfill;
}
public void SetFill(bool isfill)
{
m_Isfill = isfill;
}
}
}
区域管理类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DLAM
{
/// <summary>
/// 游戏区域管理类
/// </summary>
public class GameBoradMgr : IMgr
{
public void InitMgr()
{
BlockMgr.Block = new Block[GameConfig.Row,GameConfig.Col];
BlockMgr.BlockBg = new BlockBg[GameConfig.Row, GameConfig.Col];
}
public void StartMgr()
{
for (int row = 0; row < BlockMgr.BlockBg.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.BlockBg.GetLength(1); col++)
{
float start = -(BlockMgr.BlockBg.GetLength(0) - 1) * GameConfig.Distance / 2;
float end = -(BlockMgr.BlockBg.GetLength(1) - 1) * GameConfig.Distance / 2;
GameObject go = Object.Instantiate(GameRoot.Ins.BlockBG);
go.transform.SetParent(GameRoot.Ins.BlockParent, false);
go.transform.localPosition = new Vector3(col * GameConfig.Distance + start, row * GameConfig.Distance + end, 0);
go.transform.localScale = new Vector3(GameConfig.BGScale, GameConfig.BGScale, GameConfig.BGScale);
Vector2 pos = new Vector2(row, col);
BlockBg blockBg = go.GetComponent<BlockBg>();
blockBg.SetArrayPos(pos);
BlockMgr.BlockBg[row, col] = blockBg;
}
}
}
public void UpdateMgr()
{
}
public void EndMgr()
{
}
}
}
BlockDrag 方块拖动检测
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DLBASE;
using System;
namespace DLAM
{
public class BlockDrag : GameBase
{
public List<Block> Blocks;
private int[,] m_Block;
private int m_Id;
private int m_State;
private int m_Dir;
private Vector3 m_OldPos;
private Action<Transform, List<Block>> m_DragBlock;
private Action<Transform, List<Block>> m_DragBlockEnd;
public override void _Init()
{
m_OldPos = transform.localPosition;
}
public void InitBlock(int[,] blockconfig,int id,int state,int dir)
{
m_Block = blockconfig;
m_Id = id;
m_State = state;
m_Dir = dir;
}
public override void _OnMouseDown()
{
}
public void UpLayer()
{
for (int i = 0; i < Blocks.Count; i++)
{
Blocks[i].UpLayer();
}
}
public void DownLayer()
{
for (int i = 0; i < Blocks.Count; i++)
{
Blocks[i].DownLayer();
}
}
public override void _OnMouseDrag()
{
UpLayer();
Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
pos = new Vector3(pos.x, pos.y, transform.position.z);
transform.localPosition = pos;
transform.localScale = Vector3.one;
m_DragBlock?.Invoke(transform, Blocks);
}
public override void _OnMouseUp()
{
DownLayer();
ResetBlock();
m_DragBlockEnd?.Invoke(transform, Blocks);
}
public void ResetBlock()
{
transform.localPosition = m_OldPos;
transform.localScale = new Vector3(0.7f, 0.7f, 0.7f);
}
public void DragBlock(Action<Transform, List<Block>> drag)
{
m_DragBlock += drag;
}
public void DragBlockEnd(Action<Transform, List<Block>> dragend)
{
m_DragBlockEnd += dragend;
}
}
}
6.OperatingMgr 操控区域管理类
这个类主要用来管理游戏操作区域
拖动 (DragBlockHundler)
拖动方块检测,根据当前拖动的方块与界面背景的方块位置,判断当前是否显示可以填充
for (int row = 0; row < BlockMgr.BlockBg.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.BlockBg.GetLength(1); col++)
{
for (int index = 0; index < blocks.Count; index++)
{
float x = t.position.x + blocks[index].transform.localPosition.x;
float y = t.position.y + blocks[index].transform.localPosition.y;
float targetx = GameRoot.Ins.BlockParent.transform.position.x + BlockMgr.BlockBg[row, col].transform.localPosition.x;
float targety = GameRoot.Ins.BlockParent.transform.position.y + BlockMgr.BlockBg[row, col].transform.localPosition.y;
float xdis = Mathf.Abs(x - targetx);
float ydis = Mathf.Abs(y - targety);
if (xdis <= m_Offset && ydis <= m_Offset)
{
if (!BlockMgr.BlockBg[row, col].GetFill())
{
m_SearchBlockBG.Add(BlockMgr.BlockBg[row, col]);
}
else
{
BlockMgr.BlockBg[row, col].ShowHightBox();
}
break;
}
else
{
BlockMgr.BlockBg[row, col].CloseHightBox();
}
}
}
显示虚线框(ShowHightBox)
/// <summary>
/// 显示虚线框
/// </summary>
private void ShowHightBox(List<Block> blocks)
{
//数量不对,不显示虚线框
if (blocks.Count != m_SearchBlockBG.Count)
{
for (int i = 0; i < m_SearchBlockBG.Count; i++)
{
m_SearchBlockBG[i].CloseHightBox();
}
return;
};
//显示虚线框
for (int i = 0; i < m_SearchBlockBG.Count; i++)
{
m_SearchBlockBG[i].ShowHightBox();
}
}
拖动完成(DragBlockEndHundler)
private void DragBlockEndHundler(Transform t, List<Block> blocks)
{
FillBlock(blocks);
CloseAllBgHightBox();
}
填充方块(FillBlock)
/// <summary>
/// 填充方块
/// </summary>
private void FillBlock(List<Block> blocks)
{
//判断找到的格子是否和当前选择的数量一样,一样填充,不一样,则不填充
if (blocks.Count != m_SearchBlockBG.Count) return;
for (int i = 0; i < m_SearchBlockBG.Count; i++)
{
blocks[i].transform.SetParent(GameRoot.Ins.BlockParent);
blocks[i].transform.position = m_SearchBlockBG[i].transform.position;
blocks[i].SetArrayPos(m_SearchBlockBG[i].GetArrayPos());
blocks[i].transform.localScale = new Vector3(GameConfig.BlockScale, GameConfig.BlockScale, GameConfig.BlockScale);
m_SearchBlockBG[i].SetFill(true);
int row = (int)m_SearchBlockBG[i].GetArrayPos().x;
int col = (int)m_SearchBlockBG[i].GetArrayPos().y;
BlockMgr.Block[row, col] = blocks[i];
}
SearchEliminateBlock();
SysManager.ObjectBase.StartCortinueGO(EliminateBlock());
//填充成功,则计数器减
BlockMgr.BlockIndex--;
if (BlockMgr.BlockIndex == 0)
{
BlockMgr.BlockIndex = 3;
}
ReBuildNewBlock();
}
找到可消除的方块(SearchEliminateBlock)
/// <summary>
/// 找到可消除行和列
/// </summary>
private void SearchEliminateBlock()
{
m_ClearRowBlockList.Clear();
m_ClearColBlockList.Clear();
for (int row = 0; row < BlockMgr.Block.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.Block.GetLength(1); col++)
{
if (BlockMgr.Block[row, col] == null) break;
if (col == BlockMgr.Block.GetLength(1) - 1)
{
m_ClearRowBlockList.Add(row);
}
}
}
for (int col = 0; col < BlockMgr.Block.GetLength(1); col++)
{
for (int row = 0; row < BlockMgr.Block.GetLength(0); row++)
{
if (BlockMgr.Block[row, col] == null) break;
if (row == BlockMgr.Block.GetLength(0) - 1)
{
m_ClearColBlockList.Add(col);
}
}
}
}
消除方块(EliminateBlock)
/// <summary>
/// 直接消除
/// </summary>
private IEnumerator EliminateBlock()
{
for (int row = 0; row < m_ClearRowBlockList.Count; row++)
{
for (int col = 0; col < BlockMgr.Block.GetLength(1); col++)
{
int currentrow = m_ClearRowBlockList[row];
GameObject go = BlockMgr.Block[m_ClearRowBlockList[row], col].gameObject;
SysManager.ObjectBase.DestoryGO(go);
BlockMgr.BlockBg[m_ClearRowBlockList[row], col].SetFill(false);
yield return new WaitForSeconds(0.02f);
}
}
for (int row = 0; row < BlockMgr.Block.GetLength(0); row++)
{
for (int col = 0; col < m_ClearColBlockList.Count; col++)
{
int currentcol = m_ClearColBlockList[col];
if (BlockMgr.Block[row, m_ClearColBlockList[col]] != null)
{
GameObject go = BlockMgr.Block[row, m_ClearColBlockList[col]].gameObject;
SysManager.ObjectBase.DestoryGO(go);
BlockMgr.BlockBg[row, m_ClearColBlockList[col]].SetFill(false);
}
yield return new WaitForSeconds(0.02f);
}
}
}
重新构建三个新的方块(ReBuildNewBlock)
/// <summary>
/// 重新构建新的方块
/// </summary>
private void ReBuildNewBlock()
{
//当前还未消除完成
if (BlockMgr.BlockIndex != 3) return;
int type = Random.Range(0, BlockConfig.Block.Length);
int state = Random.Range(0, 5);
int dir = Random.Range(0, 4);
BuildBlock(m_Left, type, state, dir);
type = Random.Range(0, BlockConfig.Block.Length);
state = Random.Range(0, 5);
dir = Random.Range(0, 4);
BuildBlock(m_Mid, type, state, dir);
type = Random.Range(0, BlockConfig.Block.Length);
state = Random.Range(0, 5);
dir = Random.Range(0, 4);
BuildBlock(m_Right, type, state, dir);
}
构建方块(BuildBlock)
构建方块需要传入:方块类型,方块颜色类型,方块方向 后续做刷新道具和旋转道具的时候可以使用这个方法
/// <summary>
/// 生成方块
/// </summary>
/// <param name="id">方块配置id</param>
/// <param name="state">方块颜色类型</param>
/// <param name="dir">方块方向</param>
private void BuildBlock(BlockDrag blockDrag, int id, int state, int dir)
{
blockDrag.Blocks.Clear();
int[,] blockArray = GameUtlis.SetMtrixDir(BlockConfig.Block[id], dir);
blockDrag.InitBlock(blockArray, id, state, dir);
for (int row = 0; row < blockArray.GetLength(0); row++)
{
for (int col = 0; col < blockArray.GetLength(1); col++)
{
if (blockArray[row, col] == 1)
{
GameObject go = Object.Instantiate(GameRoot.Ins.Block);
go.transform.SetParent(blockDrag.transform, false);
float start = -(blockArray.GetLength(0) - 1) * GameConfig.Distance / 2;
float end = -(blockArray.GetLength(1) - 1) * GameConfig.Distance / 2;
go.transform.localPosition = new Vector3(row * GameConfig.Distance + start, col * GameConfig.Distance + end, 0);
go.transform.localScale = new Vector3(GameConfig.BlockScale, GameConfig.BlockScale, GameConfig.BlockScale);
Block block = go.GetComponent<Block>();
Vector2 pos = new Vector2(col, row);
block.InitBlock(id, pos);
blockDrag.Blocks.Add(block);
}
}
}
}
死亡判断(EndAllGames)
NoFillBoard函数用来判断单个物体是否可填充
主要思想:用方块的二维数组扫一下界面布局的二维数组,判断是否有可填充的位置,如果有则retrun!
/// <summary>
/// 所有对象都无法填充判断
/// </summary>
private void EndAllGames()
{
m_LeftOver = false;
m_RightOver = false;
m_MidOver = false;
m_LeftOver = NoFillBoard(m_Left.Blocks);
m_MidOver = NoFillBoard(m_Mid.Blocks);
m_RightOver = NoFillBoard(m_Right.Blocks);
if (m_LeftOver && m_MidOver && m_RightOver)
{
EndGame();
return;
}
}
/// <summary>
/// 游戏结束
/// </summary>
private void EndGame()
{
Debug.Log("游戏结束!!!");
}
/// <summary>
/// 是否可以填充判断
/// </summary>
private bool NoFillBoard(List<Block> blocks)
{
if (blocks == null) return false;
if (blocks.Count == 0) return true;
for (int row = 0; row < BlockMgr.BlockBg.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.BlockBg.GetLength(1); col++)
{
for (int i = 0; i < blocks.Count; i++)
{
int blockrow = (int)blocks[i].GetArrayPos().x + row;
int blockcol = (int)blocks[i].GetArrayPos().y + col;
if (blockrow > BlockMgr.BlockBg.GetLength(0) - 1 || blockcol > BlockMgr.BlockBg.GetLength(1) - 1) break;
if (BlockMgr.BlockBg[blockrow, blockcol].GetFill())
{
break;
}
if (i == blocks.Count - 1)
{
//还可以消除
return false;
}
}
if (row == BlockMgr.BlockBg.GetLength(0) - 1 && col == BlockMgr.BlockBg.GetLength(1) - 1)
{
//无法消除
return true;
}
}
}
return false;
}
重新开始游戏(ResetGame)
/// <summary>
/// 重新开始游戏
/// </summary>
private void ResetGame()
{
//这里简单的方式留给你们,删除或者回收界面上的方块和可操作的方块,重置背景填充
}
完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DLBASE;
namespace DLAM
{
/// <summary>
/// 游戏操作区域管理类
/// </summary>
public class OperatingMgr : IMgr
{
private BlockDrag m_Left;
private BlockDrag m_Mid;
private BlockDrag m_Right;
private List<BlockBg> m_SearchBlockBG;
private float m_Offset = 3;
private List<int> m_ClearRowBlockList;
private List<int> m_ClearColBlockList;
private bool m_LeftOver;
private bool m_MidOver;
private bool m_RightOver;
public void InitMgr()
{
m_Left = GameRoot.Ins.Left.GetComponent<BlockDrag>();
m_Mid = GameRoot.Ins.Mid.GetComponent<BlockDrag>();
m_Right = GameRoot.Ins.Right.GetComponent<BlockDrag>();
m_Left.DragBlock(DragBlockHundler);
m_Mid.DragBlock(DragBlockHundler);
m_Right.DragBlock(DragBlockHundler);
m_Left.DragBlockEnd(DragBlockEndHundler);
m_Mid.DragBlockEnd(DragBlockEndHundler);
m_Right.DragBlockEnd(DragBlockEndHundler);
m_SearchBlockBG = new List<BlockBg>();
m_ClearRowBlockList = new List<int>();
m_ClearColBlockList = new List<int>();
}
public void StartMgr()
{
ReBuildNewBlock();
}
private void DragBlockHundler(Transform t, List<Block> blocks)
{
m_SearchBlockBG.Clear();
for (int row = 0; row < BlockMgr.BlockBg.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.BlockBg.GetLength(1); col++)
{
for (int index = 0; index < blocks.Count; index++)
{
float x = t.position.x + blocks[index].transform.localPosition.x;
float y = t.position.y + blocks[index].transform.localPosition.y;
float targetx = GameRoot.Ins.BlockParent.transform.position.x + BlockMgr.BlockBg[row, col].transform.localPosition.x;
float targety = GameRoot.Ins.BlockParent.transform.position.y + BlockMgr.BlockBg[row, col].transform.localPosition.y;
float xdis = Mathf.Abs(x - targetx);
float ydis = Mathf.Abs(y - targety);
if (xdis <= m_Offset && ydis <= m_Offset)
{
if (!BlockMgr.BlockBg[row, col].GetFill())
{
m_SearchBlockBG.Add(BlockMgr.BlockBg[row, col]);
}
break;
}
else
{
BlockMgr.BlockBg[row, col].CloseHightBox();
}
}
}
}
ShowHightBox(blocks);
}
/// <summary>
/// 显示虚线框
/// </summary>
private void ShowHightBox(List<Block> blocks)
{
//数量不对,不显示虚线框
if (blocks.Count != m_SearchBlockBG.Count)
{
for (int i = 0; i < m_SearchBlockBG.Count; i++)
{
m_SearchBlockBG[i].CloseHightBox();
}
return;
};
//显示虚线框
for (int i = 0; i < m_SearchBlockBG.Count; i++)
{
m_SearchBlockBG[i].ShowHightBox();
}
}
private void DragBlockEndHundler(Transform t, List<Block> blocks)
{
FillBlock(blocks);
CloseAllBgHightBox();
}
/// <summary>
/// 填充方块
/// </summary>
private void FillBlock(List<Block> blocks)
{
//判断找到的格子是否和当前选择的数量一样,一样填充,不一样,则不填充
if (blocks.Count != m_SearchBlockBG.Count) return;
for (int i = 0; i < m_SearchBlockBG.Count; i++)
{
blocks[i].transform.SetParent(GameRoot.Ins.BlockParent);
blocks[i].transform.position = m_SearchBlockBG[i].transform.position;
blocks[i].SetArrayPos(m_SearchBlockBG[i].GetArrayPos());
blocks[i].transform.localScale = new Vector3(GameConfig.BlockScale, GameConfig.BlockScale, GameConfig.BlockScale);
m_SearchBlockBG[i].SetFill(true);
int row = (int)m_SearchBlockBG[i].GetArrayPos().x;
int col = (int)m_SearchBlockBG[i].GetArrayPos().y;
BlockMgr.Block[row, col] = blocks[i];
}
blocks.Clear();
SearchEliminateBlock();
SysManager.ObjectBase.StartCortinueGO(EliminateBlock());
//填充成功,则计数器减
BlockMgr.BlockIndex--;
if (BlockMgr.BlockIndex == 0)
{
BlockMgr.BlockIndex = 3;
}
ReBuildNewBlock();
EndAllGames();
}
/// <summary>
/// 找到可消除行和列
/// </summary>
private void SearchEliminateBlock()
{
m_ClearRowBlockList.Clear();
m_ClearColBlockList.Clear();
for (int row = 0; row < BlockMgr.Block.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.Block.GetLength(1); col++)
{
if (BlockMgr.Block[row, col] == null) break;
if (col == BlockMgr.Block.GetLength(1) - 1)
{
m_ClearRowBlockList.Add(row);
}
}
}
for (int col = 0; col < BlockMgr.Block.GetLength(1); col++)
{
for (int row = 0; row < BlockMgr.Block.GetLength(0); row++)
{
if (BlockMgr.Block[row, col] == null) break;
if (row == BlockMgr.Block.GetLength(0) - 1)
{
m_ClearColBlockList.Add(col);
}
}
}
}
/// <summary>
/// 直接消除
/// </summary>
private IEnumerator EliminateBlock()
{
for (int row = 0; row < m_ClearRowBlockList.Count; row++)
{
for (int col = 0; col < BlockMgr.Block.GetLength(1); col++)
{
int currentrow = m_ClearRowBlockList[row];
GameObject go = BlockMgr.Block[m_ClearRowBlockList[row], col].gameObject;
SysManager.ObjectBase.DestoryGO(go);
BlockMgr.BlockBg[m_ClearRowBlockList[row], col].SetFill(false);
yield return new WaitForSeconds(0.02f);
}
}
for (int row = 0; row < BlockMgr.Block.GetLength(0); row++)
{
for (int col = 0; col < m_ClearColBlockList.Count; col++)
{
int currentcol = m_ClearColBlockList[col];
if (BlockMgr.Block[row, m_ClearColBlockList[col]] != null)
{
GameObject go = BlockMgr.Block[row, m_ClearColBlockList[col]].gameObject;
SysManager.ObjectBase.DestoryGO(go);
BlockMgr.BlockBg[row, m_ClearColBlockList[col]].SetFill(false);
}
yield return new WaitForSeconds(0.02f);
}
}
}
/// <summary>
/// 生成方块
/// </summary>
/// <param name="id">方块配置id</param>
/// <param name="state">方块颜色类型</param>
/// <param name="dir">方块方向</param>
private void BuildBlock(BlockDrag blockDrag, int id, int state, int dir)
{
blockDrag.Blocks.Clear();
int[,] blockArray = GameUtlis.SetMtrixDir(BlockConfig.Block[id], dir);
blockDrag.InitBlock(blockArray, id, state, dir);
for (int row = 0; row < blockArray.GetLength(0); row++)
{
for (int col = 0; col < blockArray.GetLength(1); col++)
{
if (blockArray[row, col] == 1)
{
GameObject go = Object.Instantiate(GameRoot.Ins.Block);
go.transform.SetParent(blockDrag.transform, false);
float start = -(blockArray.GetLength(0) - 1) * GameConfig.Distance / 2;
float end = -(blockArray.GetLength(1) - 1) * GameConfig.Distance / 2;
go.transform.localPosition = new Vector3(row * GameConfig.Distance + start, col * GameConfig.Distance + end, 0);
go.transform.localScale = new Vector3(GameConfig.BlockScale, GameConfig.BlockScale, GameConfig.BlockScale);
Block block = go.GetComponent<Block>();
Vector2 pos = new Vector2(col, row);
block.InitBlock(id, pos);
blockDrag.Blocks.Add(block);
}
}
}
}
/// <summary>
/// 重新构建新的方块
/// </summary>
private void ReBuildNewBlock()
{
//当前还未消除完成
if (BlockMgr.BlockIndex != 3) return;
int type = Random.Range(0, BlockConfig.Block.Length);
int state = Random.Range(0, 5);
int dir = Random.Range(0, 4);
BuildBlock(m_Left, type, state, dir);
type = Random.Range(0, BlockConfig.Block.Length);
state = Random.Range(0, 5);
dir = Random.Range(0, 4);
BuildBlock(m_Mid, type, state, dir);
type = Random.Range(0, BlockConfig.Block.Length);
state = Random.Range(0, 5);
dir = Random.Range(0, 4);
BuildBlock(m_Right, type, state, dir);
}
/// <summary>
/// 关闭所有虚线框
/// </summary>
private void CloseAllBgHightBox()
{
for (int i = 0; i < BlockMgr.BlockBg.GetLength(0); i++)
{
for (int j = 0; j < BlockMgr.BlockBg.GetLength(0); j++)
{
BlockMgr.BlockBg[i, j].CloseHightBox();
}
}
}
/// <summary>
/// 所有对象都无法填充判断
/// </summary>
private void EndAllGames()
{
m_LeftOver = false;
m_RightOver = false;
m_MidOver = false;
m_LeftOver = NoFillBoard(m_Left.Blocks);
m_MidOver = NoFillBoard(m_Mid.Blocks);
m_RightOver = NoFillBoard(m_Right.Blocks);
if (m_LeftOver && m_MidOver && m_RightOver)
{
EndGame();
return;
}
}
/// <summary>
/// 游戏结束
/// </summary>
private void EndGame()
{
Debug.Log("游戏结束!!!");
}
/// <summary>
/// 是否可以填充判断
/// </summary>
private bool NoFillBoard(List<Block> blocks)
{
if (blocks == null) return false;
if (blocks.Count == 0) return true;
for (int row = 0; row < BlockMgr.BlockBg.GetLength(0); row++)
{
for (int col = 0; col < BlockMgr.BlockBg.GetLength(1); col++)
{
for (int i = 0; i < blocks.Count; i++)
{
int blockrow = (int)blocks[i].GetArrayPos().x + row;
int blockcol = (int)blocks[i].GetArrayPos().y + col;
if (blockrow > BlockMgr.BlockBg.GetLength(0) - 1 || blockcol > BlockMgr.BlockBg.GetLength(1) - 1) break;
if (BlockMgr.BlockBg[blockrow, blockcol].GetFill())
{
break;
}
if (i == blocks.Count - 1)
{
//还可以消除
return false;
}
}
if (row == BlockMgr.BlockBg.GetLength(0) - 1 && col == BlockMgr.BlockBg.GetLength(1) - 1)
{
//无法消除
return true;
}
}
}
return false;
}
public void UpdateMgr()
{
}
public void EndMgr()
{
}
}
}
7.EffectMgr 特效管理类
这个类主要用来管理游戏特效,消除方块的时候调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DLAM
{
/// <summary>
/// 特效管理类
/// </summary>
public class EffectMgr : IMgr
{
public void ShowBlockEffect()
{
Debug.Log("展示特效!!!");
}
public void EndMgr()
{
}
public void InitMgr()
{
}
public void StartMgr()
{
}
public void UpdateMgr()
{
}
}
}
8.GameConfig和BlockConfig配置类
GameConfig游戏基础配置类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DLAM
{
public static class GameConfig
{
public static int Col = 10;
public static int Row = 10;
public static float Distance = 6;
public static float BGScale = 6;
public static float BlockScale = 12;
}
}
BlockConfig方块配置类
主要是用二维数组代表方块的样式,根据二维数组来生成方块,可以想象一下,一个个方块其实就是一个个的数组!
namespace DLAM
{
public class BlockConfig
{
//单格子方块
public static int[,] OBlock = new int[1, 1] { { 1 } };
//两个格子
public static int[,] OTBlock = new int[2, 1] { { 1 }, { 1 } };
public static int[,] OCBlock = new int[3, 1] { { 1 }, { 1 }, { 1 } };
public static int[,] ODBlock = new int[4, 1] { { 1 }, { 1 }, { 1 }, { 1 } };
public static int[,] OEBlock = new int[5, 1] { { 1 }, { 1 }, { 1 }, { 1 }, { 1 } };
public static int[,] MTBlock = new int[2, 2] { { 1, 1 }, { 1, 1 } };
public static int[,] MTTBlock = new int[2, 3] { { 1, 1, 1 }, { 1, 1, 1 } };
public static int[,] ZLBlock = new int[2, 2] { { 1, 1 }, { 1, 0 } };
//Z形状
public static int[,] ZBlock = new int[2, 3] { { 1, 1, 0 }, { 0, 1, 1 } };
//反Z形状
public static int[,] RZBlock = new int[2, 3] { { 0, 1, 1 }, { 1, 1, 0 } };
//T形状
public static int[,] TBlock = new int[2, 3] { { 0, 1, 0 }, { 1, 1, 1 } };
//7形状
public static int[,] LBlock = new int[3, 3] { { 1, 1, 1 }, { 1, 0, 0 }, { 1, 0, 0 } };
//反7
public static int[,] RLBlock = new int[3, 3] { { 1, 0, 0 }, { 1, 0, 0 }, { 1, 1, 1 } };
public static int[,] DLBlock = new int[3, 2] { { 1, 1 }, { 1, 0 }, { 1, 0 } };
public static int[,] DLRBlock = new int[3, 2] { { 1, 1 }, { 0, 1 }, { 0, 1 } };
//田字
public static int[,] MBlock = new int[3, 3] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };
}
}
9.GameUtlis工具类
这个类主要封装了旋转二维数组的函数,方便全局使用
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DLAM
{
public static class GameUtlis
{
/// <summary>
/// 转置矩阵
/// </summary>
/// <returns></returns>
public static int[,] TransposeMtrix(int[,] matrix)
{
int[,] array = new int[matrix.GetLength(1), matrix.GetLength(0)];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
array[matrix.GetLength(1) - 1 - j,i] = matrix[i, j];
}
}
return array;
}
public static int[,] TurnMtrix(int[,] matrix)
{
int[,] array = new int[matrix.GetLength(0), matrix.GetLength(1)];
if(matrix.GetLength(0)==1|| matrix.GetLength(1) == 1)
{
return matrix;
}
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
array[i, j] = matrix[matrix.GetLength(0) - 1 - i, matrix.GetLength(1) - 1 - j];
}
}
return array;
}
public static int[,] ChangeMtrixDir(int[,] matrix, int dir)
{
int[,] blocks = new int[0, 0];
switch (dir)
{
case 0:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
break;
case 1:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
break;
case 2:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
break;
case 3:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
break;
}
return blocks;
}
public static int[,] SetMtrixDir(int[,] matrix, int dir)
{
int[,] blocks = new int[0, 0];
switch (dir)
{
case 0:
blocks = matrix;
break;
case 1:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
break;
case 2:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
blocks = GameUtlis.TransposeMtrix(blocks);
blocks = TurnMtrix(blocks);
break;
case 3:
blocks = GameUtlis.TransposeMtrix(matrix);
blocks = TurnMtrix(blocks);
blocks = GameUtlis.TransposeMtrix(blocks);
blocks = TurnMtrix(blocks);
blocks = GameUtlis.TransposeMtrix(blocks);
blocks = TurnMtrix(blocks);
break;
case 4:
blocks = matrix;
break;
}
return blocks;
}
public static IEnumerator Wait(float time,Action callback)
{
yield return new WaitForSeconds(time);
callback?.Invoke();
}
public static void RandomNumber(float prcent,Action sucess,Action fail)
{
float num = UnityEngine.Random.Range(0, 100);
if (num > prcent)
{
fail?.Invoke();
}
else
{
sucess?.Invoke();
}
}
}
}
11.项目结构
10.最终效果
DLAM是哆啦A梦的意思!!哈哈因为生活中朋友都叫我大雄!