甜品消消乐知识点总结
本片博客介绍生活中常见的三消游戏的一些做法和知识点O(∩_∩)O哈哈~
Unity 开发单位是以米为单位的,所以当不知道物体大小时 可以新建一个cube 方块做对比
格子在甜品下面,所以同等layer 层 我们依旧可以把order in layer 设置为-1
在设置背景时,基本上可以把背景放的稍微大点 防止某些情况下曝光
可以选中私有静态类实例那一行 按快捷键Ctrl + R + E 来实现属性的快速编写
根据双层for循环生成的格子设置XY轴一般都会这样
因为中心点在中间
由于甜品是从上往下掉的 ,所以Y 一直在减小 所以可以调整为
GameObject chocolate = Instantiate(gridPrefab, CorrectPositon(x, y), Quaternion.identity);
chocolate.transform.SetParent(transform);
public Vector3 CorrectPositon(int x, int y)
{
//实际需要实例化巧克力块的X位置=GameManager位置的X坐标-大网格长度的一半+行列对应的X坐标
//实际需要实例化巧克力块的Y位置=GameManager位置的Y坐标+大网格高度的一半-行列对应的Y坐标
return new Vector3(transform.position.x - xColumn / 2f + x, transform.position.y + yRow / 2f - y);
}
当使用到字典时 我们希望在面板上能看到相关数据
则我们可以先创建字典
然后创建相应结构体 最后定义一个list
然后在Start里面给字典把list 上的值赋给字典
[System.Serializable]
这行保证我们的结构体可以序列化
赋值阶段
void Start()
{
//字典的实例化
sweetPrefabDict = new Dictionary<SweetsType, GameObject>();
for (int i = 0; i < sweetPrefabs.Length; i++)
{
if (!sweetPrefabDict.ContainsKey(sweetPrefabs[i].type))
{
sweetPrefabDict.Add(sweetPrefabs[i].type, sweetPrefabs[i].prefab);
}
}
}
二维数组的定义方式
如果枚举是定义在类内部 则需要使用类名点枚举名才能获取到
private GameManager.SweetsType type;
糖果的初始化
隐藏该变量在面板上的显示
设置可以调的数字 长度和宽度
//分步填充
public bool Fill()
{
bool filledNotFinished = false;//判断本次填充是否完成(一次遍历是指当前格子里的所有可移动的甜品都判断一次)
//因为我们甜品是由上往下生成的,我们的甜品是由上往下掉落的。所以我们需要从下往上遍历,但是我们不需要遍历最后一行 ,
//因为最后一行的下一行没有甜品 所以从yRow-2 并且是倒着for 循环遍历
for (int y = yRow-2; y >=0; y--) //每行
{
for (int x = 0; x < xColumn; x++) //每列
{
GameSweet sweet = sweets[x, y];//得到当前元素位置的甜品对象
if (sweet.CanMove())//如果无法移动,则无法往下填充(比如饼干这些)
{
GameSweet sweetBelow = sweets[x, y + 1]; //获取当前遍历到的糖果的下一行
if (sweetBelow.Type==SweetsType.EMPTY)//垂直填充 (如果是空 则说明可以被上面一行的糖果填充)
{
Destroy(sweetBelow.gameObject); //删除当前下面那行的空糖果
sweet.MovedComponent.Move(x, y + 1,fillTime); //将糖果移动到下一行
sweets[x, y + 1] = sweet; //把下一行的坐标 设为当前糖果
CreateNewSweet(x, y, SweetsType.EMPTY); //把原先坐标的引用设置为空
filledNotFinished = true; //单个填充完成
}
else //斜向填充 如果下面的不为空 则判断左下 和 右下 是否为空
{
for (int down = -1; down <= 1; down++) //(当前X -1 0 1 分别得到左下 正下 右下)
{
if (down != 0) //(正下不考虑)
{
int downX = x + down; //拿到左下和右下的X值
if (downX >= 0 && downX < xColumn) //如果左下右下不超过边界
{
GameSweet downSweet = sweets[downX, y + 1]; //拿到左下或右下的甜品
if (downSweet.Type == SweetsType.EMPTY) //如果是空则可以填充
{
bool canfill = true;//用来判断垂直填充是否可以满足填充要求 也就是左下和右下有没有可以掉落的甜品
for (int aboveY = y; aboveY >= 0; aboveY--) //遍历填充的甜品上方有没可以掉的甜品
{
GameSweet sweetAbove = sweets[downX, aboveY]; //获取这些上方的甜品
if (sweetAbove.CanMove()) //如果这些甜品可以掉落,不是饼干
{
break; //就不去填了
}
else if (!sweetAbove.CanMove() && sweetAbove.Type != SweetsType.EMPTY) //否则如果是饼干或者空
{
canfill = false; //左下右下上方不能自己填充
break;
}
}
if (!canfill)
{
Destroy(downSweet.gameObject); //删除掉需要填充的地方的空格子
sweet.MovedComponent.Move(downX, y + 1, fillTime); //将甜品移到目标位置
sweets[downX, y + 1] = sweet; //设置引用
CreateNewSweet(x, y, SweetsType.EMPTY);//原位置新生成一个空甜品
filledNotFinished = true; //没有完成填充
break;
}
}
}
}
}
}
}
}
}
//最上排的特殊情况
for (int x = 0; x < xColumn; x++)
{
GameSweet sweet = sweets[x, 0];
if (sweet.Type==SweetsType.EMPTY)
{
//在最上排的上一排再生成甜品
GameObject newSweet= Instantiate(sweetPrefabDict[SweetsType.NORMAL], CorrectPositon(x, -1), Quaternion.identity);
newSweet.transform.parent = transform;
sweets[x, 0] = newSweet.GetComponent<GameSweet>();
sweets[x, 0].Init(x, -1, this, SweetsType.NORMAL);
sweets[x, 0].MovedComponent.Move(x, 0,fillTime);
sweets[x, 0].ColoredComponent.SetColor((ColorSweet.ColorType)Random.Range(0, sweets[x, 0].ColoredComponent.NumColors));
filledNotFinished = true;
}
}
return filledNotFinished;
}
//全部填充的方法
public IEnumerator AllFill()
{
bool needRefill = true;
while (needRefill)
{
yield return new WaitForSeconds(fillTime);
while (Fill()) //判断时会执行Fill 方法 如Fill 填充了则返回true while 执行完又会判断Fill 方法
{
yield return new WaitForSeconds(fillTime);
}
//清除所有我们已经匹配好的甜品
needRefill= ClearAllMatchedSweet();
}
}
每个甜品都会检测
当点击时 代表自己是先选中的 对象1
当Enter 时代表自己是从其他地方移过来的 也就是要交换的对象2
松开时就12交换
做销毁动画时
我们创建了一个帧动画 如果只希望在甜品销毁时播放这个动画 那么这个动画就不能为默认动画,必须新建一个默认动画来作为默认动画
行匹配和列匹配 以及 L 和 T 型匹配逻辑
算法
//匹配方法
public List<GameSweet> MatchSweets(GameSweet sweet,int newX,int newY)
{
if (sweet.CanColor())
{
ColorSweet.ColorType color = sweet.ColoredComponent.Color;
List<GameSweet> matchRowSweets = new List<GameSweet>();
List<GameSweet> matchLineSweets = new List<GameSweet>();
List<GameSweet> finishedMatchingSweets = new List<GameSweet>();
//行匹配
matchRowSweets.Add(sweet);
//i=0代表往左,i=1代表往右
for (int i = 0; i <=1; i++)
{
for (int xDistance = 1; xDistance < xColumn; xDistance++)
{
int x;
if (i==0)
{
x = newX - xDistance;
}
else
{
x = newX + xDistance;
}
if (x<0||x>=xColumn)
{
break;
}
if (sweets[x,newY].CanColor()&&sweets[x,newY].ColoredComponent.Color==color)
{
matchRowSweets.Add(sweets[x, newY]);
}
else
{
break;
}
}
}
if (matchRowSweets.Count>=3)
{
for (int i = 0; i < matchRowSweets.Count; i++)
{
finishedMatchingSweets.Add(matchRowSweets[i]);
}
}
//L T型匹配
//检查一下当前行遍历列表中的元素数量是否大于3
if (matchRowSweets.Count>=3)
{
for (int i = 0; i < matchRowSweets.Count; i++)
{
//行匹配列表中满足匹配条件的每个元素上下依次进行列遍历
// 0代表上方 1代表下方
for (int j = 0; j <=1; j++)
{
for (int yDistance = 1; yDistance < yRow; yDistance++)
{
int y;
if (j==0)
{
y = newY - yDistance;
}
else
{
y = newY + yDistance;
}
if (y<0||y>=yRow)
{
break;
}
if (sweets[matchRowSweets[i].X,y].CanColor()&&sweets[matchRowSweets[i].X,y].ColoredComponent.Color==color)
{
matchLineSweets.Add(sweets[matchRowSweets[i].X, y]);
}
else
{
break;
}
}
}
if (matchLineSweets.Count<2)
{
matchLineSweets.Clear();
}
else
{
for (int j = 0; j < matchLineSweets.Count; j++)
{
finishedMatchingSweets.Add(matchLineSweets[j]);
}
break;
}
}
}
if (finishedMatchingSweets.Count>=3)
{
return finishedMatchingSweets;
}
matchRowSweets.Clear();
matchLineSweets.Clear();
matchLineSweets.Add(sweet);
//列匹配
//i=0代表往左,i=1代表往右
for (int i = 0; i <= 1; i++)
{
for (int yDistance = 1; yDistance < yRow; yDistance++)
{
int y;
if (i == 0)
{
y = newY - yDistance;
}
else
{
y = newY + yDistance;
}
if (y < 0 || y >= yRow)
{
break;
}
if (sweets[newX, y].CanColor() && sweets[newX, y].ColoredComponent.Color == color)
{
matchLineSweets.Add(sweets[newX, y]);
}
else
{
break;
}
}
}
if (matchLineSweets.Count >= 3)
{
for (int i = 0; i < matchLineSweets.Count; i++)
{
finishedMatchingSweets.Add(matchLineSweets[i]);
}
}
//L T型匹配
//检查一下当前行遍历列表中的元素数量是否大于3
if (matchLineSweets.Count >= 3)
{
for (int i = 0; i < matchLineSweets.Count; i++)
{
//行匹配列表中满足匹配条件的每个元素上下依次进行列遍历
// 0代表上方 1代表下方
for (int j = 0; j <= 1; j++)
{
for (int xDistance= 1; xDistance < xColumn; xDistance++)
{
int x;
if (j == 0)
{
x = newY - xDistance;
}
else
{
x = newY + xDistance;
}
if (x < 0 || x >= xColumn)
{
break;
}
if (sweets[x, matchLineSweets[i].Y].CanColor() && sweets[x, matchLineSweets[i].Y].ColoredComponent.Color == color)
{
matchRowSweets.Add(sweets[x, matchLineSweets[i].Y]);
}
else
{
break;
}
}
}
if (matchRowSweets.Count < 2)
{
matchRowSweets.Clear();
}
else
{
for (int j = 0; j < matchRowSweets.Count; j++)
{
finishedMatchingSweets.Add(matchRowSweets[j]);
}
break;
}
}
}
if (finishedMatchingSweets.Count >= 3)
{
return finishedMatchingSweets;
}
}
return null;
}
计时器
快捷格式化方法
Tostring(“0”) 取整数
Tostring(“0.0”) 保留一位小数
如果想让数字加的明显 可以设置每0.05秒分数加1
if (addScoreTime<=0.05f)
{
addScoreTime += Time.deltaTime;
}
else
{
if (currentScore<playerScore)
{
currentScore++;
playerScoreText.text = currentScore.ToString();
addScoreTime = 0;
}
}