作业要求
- 游戏内容: 井字棋 或 贷款计算器 或 简单计算器 等等
- 技术限制: 仅允许使用?IMGUI?构建 UI
- 作业目的:
- 了解 OnGUI() 事件,提升 debug 能力
- 提升阅读 API 文档能力?
游戏预览
start开始游戏:
游戏结束,restart可重新开始游戏:
前置知识学习
OnGUI
查阅官方文档可得 :OnGUI:?Called multiple times per frame in response to GUI events. The Layout and Repaint events are processed first, followed by a Layout and keyboard/mouse event for each input event.
即OnGUI每帧都会调用多次,先处理布局和重绘事件,再处理输入引起的布局、鼠标键盘事件。
GUI相关脚本
查阅脚本文档:GUI.Buttonhttps://docs.unity3d.com/ScriptReference/GUI.Button.htmlGUI.Labelhttps://docs.unity3d.com/ScriptReference/GUI.Label.htmlRecthttps://docs.unity3d.com/ScriptReference/Rect.html其中Rect原点为左上,向右为正x,向下为正y。
分析设计
该游戏不需要实际的GameObject,事务逻辑通过OnGUI即可进行处理,所以使用一个空GameObject挂载一个脚本就可以完成游戏的编写。
棋盘通过矩阵来表示,UI实现使用GUI.Button。OnGUI每一帧都会执行,因此每次执行的逻辑是:
- 判断是否开始游戏,绘制start\restart按钮,按下按钮触发相应事件
- 判断游戏是否结束
- 根据矩阵绘制棋盘,按下按钮触发相应事件
使用ECS,将实体、部件、系统三者分离,因此代码主要分为OnGUI负责交互与呈现,win、remake、start负责逻辑,变量负责数据。
代码实现
变量
private int[, ] matrix = new int[3, 3]; // 矩阵表示九个格子
private int player = 1; // 当前下棋玩家
private bool start = false; // 游戏是否开始
?start
void Start()
{
remake(); // 重置游戏
}
remake
重置关于游戏的各种变量。
void remake()
{
start = false;
player = 1;
for(int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
matrix[i, j] = 0; // 重置棋盘
}
}
}
win
判断是否有玩家胜利、平局、继续游戏。
int win()
{
// 计算行的和是否为3或-3判断胜利
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += matrix[i, j];
}
if (sum == 3)
{
return 1;
}
else if (sum == -3)
{
return 2;
}
}
// 计算列的和是否为3或-3判断胜利
for (int i = 0; i < 3; i++)
{
int sum = 0;
for (int j = 0; j < 3; j++)
{
sum += matrix[j, i];
}
if (sum == 3)
{
return 1;
}
else if (sum == -3)
{
return 2;
}
}
// 计算对角线的和是否为3或-3判断胜利
int lr = matrix[0, 0] + matrix[1, 1] + matrix[2, 2];
int rl = matrix[2, 0] + matrix[1, 1] + matrix[0, 2];
if (lr == 3 || rl == 3)
{
return 1;
}
else if (lr == -3 || rl == -3)
{
return 2;
}
// 若棋盘未满,继续游戏
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (matrix[i, j] == 0)
{
return 0;
}
}
}
// 棋盘满则平局
return 3;
}
OnGUI
绘制棋盘、按钮。
private void OnGUI()
{
// start和restart按钮
if (start)
{
if (GUI.Button(new Rect(0, 300, 100, 50), "restart"))
{
remake();
}
}
else
{
if(GUI.Button(new Rect(0, 300, 100, 50), "start"))
{
start = true;
}
}
// 判断游戏是否结束
int res = win();
if (res == 3) // 平局
{
GUI.Label(new Rect(0, 350, 100, 50), "draw");
}
else if (res == 1) // X赢
{
GUI.Label(new Rect(0, 350, 100, 50), "X win");
}
else if (res == 2) // O赢
{
GUI.Label(new Rect(0, 350, 100, 50), "O win");
}
// 绘制棋盘
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (matrix[i, j] == 1) //X子
{
GUI.Button(new Rect(100 * i, 100 * j, 100, 100), "X");
}
else if (matrix[i, j] == -1) // O子
{
GUI.Button(new Rect(100 * i, 100 * j, 100, 100), "O");
}
else // 空格子
{
if (GUI.Button(new Rect(100 * i, 100 * j, 100, 100), ""))
{
if (start) // 下子,并更改玩家
{
matrix[i, j] = player;
player = -player;
}
}
}
}
}
}
总结
- 了解OnGUI事件,学习如何使用Button、Label编写按钮与标签;
- ?通过项目阅读了Unity的相关文档;
- 将ECS简单运用到项目中,实现三者分离。
|