在上一節(jié)中趾代,盡管已經(jīng)堆疊了一大堆方塊,但因為沒有消除那些已經(jīng)填滿的行丰辣,所以屏幕最終會被填滿撒强,游戲就無法繼續(xù)了。
這一節(jié)笙什,我們來消除滿行飘哨。
01.分析
有兩種消除方案:
- 一行行掃描,掃描到滿行時琐凭,執(zhí)行消除芽隆,然后繼續(xù)掃描下一行
- 一行行掃描,先記錄所有需要消除的行统屈,掃描完成后胚吁,執(zhí)行消除
我選擇第二種方案,至于原因愁憔,我感覺這樣分工更明確腕扶。
如何掃描:一行一行掃描,如果在行中遇到空的點吨掌,則跳到下一行半抱。如果掃描到了一行中的最后一個點脓恕,還沒有遇到空的點,就說明該行已經(jīng)被填滿了窿侈,將該行的行號記錄在需要消除的行中炼幔。所有行掃描完成后,掃描結(jié)束史简。
如何消除:遍歷需要消除的行乃秀,將對應(yīng)的點從固定方塊中移除。
消除完成后乘瓤,就會出現(xiàn)空行环形,需要下移空行上面的方塊。
02.代碼實現(xiàn)
02.01 先為導(dǎo)演添加一個成員衙傀,記錄需要消除的行號列表:
List<int> _needClearLines; // 記錄需要消除的行
然后在初始化游戲方法中初始化此成員:
_needClearLines = new List<int>();
02.02 添加方法抬吟,填充需要消除的行:
// 填充需要消除的行
void FillNeedClearLines()
{
for (int line = 0; line < 20; line++)
{
for (int list = 0; list < 10; list++)
{
if (_defaultLayer.IsCanSee(new MyPoint(line, list)))
{
// 如果不是該行的最后一個點,則掃描該行的下一個點
if (list != 9) continue;
// 如果該行的點全都掃描到了统抬,說明該行需要消除
else _needClearLines.Add(line);
}
// 如果掃描到空點火本,則退出該行的掃描,掃描下一行
else break;
}
}
}
02.03 消除滿行
因為需要刪除圖層中顯示數(shù)據(jù)中的點聪建,所以在圖層類中添加一個移除點方法:
// 移除點
public void RemovePoint(int line, int list)
{
int index = 0;
foreach (var point in ViewData)
{
if (point._line == line && point._list == list) break;
index++;
}
ViewData.RemoveAt(index);
}
回到導(dǎo)演類钙畔,添加消除滿行方法:
// 消除滿行
void ClearFullLines()
{
// 遍歷行
foreach (var lineNumber in _needClearLines)
{
// 移除該行上所有的點
for (int list = 0; list < 10; list++)
{
_defaultLayer.RemovePoint(lineNumber, list);
}
}
_needClearLines.Clear();
// 刷新屏幕
_screenMain.RefreshScreen();
}
02.04 填補消除后的行
取名是一個非常頭疼的工作,要名副其實金麸,而且不能與其他方法名混淆擎析,也不能引起歧義,雖然說可以添加注釋挥下,但不能依賴注釋揍魂,更好的方法名才是我們需要的。
經(jīng)過一番思索棚瘟,感覺還是使用“填補消除后的行”更合適现斋,就是感覺太長了,如果你有更好的名字偎蘸,請留言告訴我庄蹋。
那么,方法名為:FillUpClearedLine()
填補原理:按從上至下填充迷雪,就是說限书,依次將最頂端的空行上的點下移:
// 填補消除后的行
void FillUpClearedLine()
{
while (_needClearLines.Count > 0)
{
int line = _needClearLines[_needClearLines.Count - 1];
List<MyPoint> fixedPoints = _defaultLayer.ViewData;
for (int index = 0; index < fixedPoints.Count; index++)
{
// 將高于當(dāng)前行的點下移一格
if (fixedPoints[index]._line > line)
{
fixedPoints[index] = new My-Point(fixedPoints[index]._line - 1, fixedPoints[index]._list);
}
}
_needClearLines.RemoveAt(_needClearLines.Count - 1);
_screenMain.RefreshScreen();
}
}
02.05 在游戲核心邏輯中調(diào)用
// 游戲核心邏輯
void GameCore()
{
if (!MoveDownBlock())
{
// 先固定方塊
FixActiveBlock();
// 計算需要消除的行
FillNeedClearLines();
// 如有需要消除的行
if (_needClearLines.Count > 0)
{
// 消除行
ClearFullLines();
// 填補消除后的行
FillUpClearedLine();
}
// 創(chuàng)建新方塊
CreateNewBlock();
}
}
好了,經(jīng)過一番折騰章咧,功能終于實現(xiàn)了蔗包,不過,目前的消除動作幾乎是在一瞬間就完成了慧邮,太生硬了调限,接下來,我們將為其添加一些動畫误澳。
代碼鏈接:https://pan.baidu.com/s/1reST9ttihP_u4uQJ0SSwgg
提取碼:o5f2