Unity 3D游戏编程与设计-井字棋

技术基础:

本此实践主要使用unity 自带的即时模式GUI(IMGUI)完成游戏设计。IMGUI是Unity主要基于GameObject的UI的完全独立功能系统, 是一个代码驱动的GUI系统。它通过在任何实现它的脚本上调用OnGUI函数来驱动。例如,下面代码:

void OnGUI() {

if (GUILayout.Button("Press Me")) Debug.Log("Hello!");

}

结果是,它将显示下面一个按钮:

当我们要创建IMGUI元素,必须编写进入名为OnGUI的特殊函数的代码,OnGUI()函数就会在每个帧中调用 - 就像Update()函数一样,将元素绘制到屏幕上。

游戏设计思路:

游戏的关键部分是创建一个棋盘,并且当玩家在下棋时,点击棋盘位置可以根据角色不同,填充”X“或者”O“。每下一步棋,程序能够自动检测游戏结果。

1. 关于棋盘,我们可以通过将9个button排列为3*3的阵列来表示,所有格子的状态用3*3的二维数组表示,0-该格为空、1-放置了player1的棋子,2-放置player2的棋子

2. 利用button的特性和OnGUI()函数每帧都会被调用,我们可以点击棋格(button)时,可以设置保存棋格状态的数组,如当turn为1,点击空格时,该格对应状态设为1。并且设置对应关系,根据棋格状态显示不同内容

3. 每走完一步棋,判断该棋子在横向,竖向,对角线方向上是否有三个相同对象连成线,从而判断游戏结果

检查

UI设计

UI基于GUI方法的固定显示方式

游戏效果展示

字体内容用GUI.Label显示,可以设置字体的颜色和大小。参数本身提供了一个Rect()函数。Rect()定义了四个属性:最左侧位置最顶层位置总宽度总高度, 坐标系是基于左上角的。例如Rect(10,20,300,100)定义一个Rectangle,从坐标:10,20开始,到坐标310,120结束。

显示文本内容

设置字体

button可以用来显示文本或图像,当点击button时,或触发相应的事件

在本实践中,button中显示图片时,图片不能完全填充button,效果比较难看。本实践设置了下button的格式:首先,在代码中声明一个GUIStyle属性,然后将它应用于button上面,在设置button的背景色为白色

实验代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TicTacToe : MonoBehaviour
{
    private int turn = 1;//1-player1,0-player2
    private int [,] board = new int [3,3];//记录棋盘状态
    private int result = 0;//0-游戏中,1-player1获胜,2-player2获胜,3-平局
    //button样式设置
    public GUIStyle customButton;//背景设置为白色,优化button图片显示
    //声明背景图片和棋子图片内容
    public Texture2D backgroundImg;
    public Texture2D img1;
    public Texture2D img2;

    
    void Reset()
    {
        //重置结果,清空棋盘内容
        result = 0;
        turn = 1;
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                board[i, j] = 0;
    }
    void Start()
    {
        Reset();
    }
    
    void OnGUI()
    {
        //GUIStyle
        //标题字体样式
        GUIStyle fontStyle1 = new GUIStyle();
        fontStyle1.normal.background = null;
        fontStyle1.normal.textColor = new Color(100, 100, 0);
        fontStyle1.fontSize = 20;

        //文本字体格式
        GUIStyle fontStyle2 = new GUIStyle();
        fontStyle2.normal.background = null;
        fontStyle2.normal.textColor = new Color(0, 1, 0);
        fontStyle2.fontSize = 15;


        //player
        //设置背景
        GUI.Label(new Rect(0, 0, 720, 405), backgroundImg);
        GUI.Label(new Rect(190, 15, 100, 100), "Welcome to TicTacToe",fontStyle1);
        //显示2个玩家
        GUI.Label(new Rect(50, 50, 50, 50), img1);
        GUI.Label(new Rect(120, 75, 100, 50), "Player1",fontStyle2);
        GUI.Label(new Rect(50, 120, 50, 50), img2);
        GUI.Label(new Rect(120, 145, 100, 50), "Player2",fontStyle2);
        //显示当前走棋的玩家
        GUI.Label(new Rect(30, 25, 100, 50), "Turn:",fontStyle2);
        if (turn == 1)
            GUI.Label(new Rect(30, 60, 100, 50), ">",fontStyle2);
        else
            GUI.Label(new Rect(30, 130, 100, 50), ">",fontStyle2);

        if (GUI.Button(new Rect(250, 60, 70, 50), "RESET"))
            Reset();

        //刷新棋盘
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++) {
                if (board[i, j] == 1)
                    GUI.Button(new Rect(210 + i * 50, 140 + j * 50, 50, 50), img1, customButton);
                if (board[i, j] == 2)
                    GUI.Button(new Rect(210 + i * 50, 140 + j * 50, 50, 50), img2, customButton);
                if(GUI.Button(new Rect(210 + i * 50, 140 + j * 50, 50, 50), ""))
                {
                    if(result == 0)
                    {
                        if (turn == 1)
                            board[i, j] = 1;
                        else
                            board[i, j] = 2;
                        turn = 1 - turn;
                    }
                }
            }

        //显示结果
        GUI.Label(new Rect(50, 210, 100, 50), "Result:",fontStyle2);
        result = check();
        if (result == 1)
            GUI.Label(new Rect(105, 210, 100, 50), "Player1 wins!",fontStyle2);
        else if(result == 2)
            GUI.Label(new Rect(105, 210, 100, 50), "Player2 wins!",fontStyle2);
        else if(result == 3)
            GUI.Label(new Rect(105, 210, 100, 50), "No one wins!",fontStyle2);
        else
        {
            GUI.Label(new Rect(105, 210, 100, 50), "playing...",fontStyle2);
        }

        //检查游戏结果
        int check()
        {
            int count = 0;
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    if (board[i, j] != 0)
                        count++;
                }
    
            for (int i = 0; i < 3; ++i)
            {
                if (board[i, 0] != 0 && board[i, 0] == board[i, 1] && board[i, 1] == board[i, 2])
                    return board[i, 0];
            }
            for (int j = 0; j < 3; ++j)
            {
                if (board[0, j] != 0 && board[0, j] == board[1, j] && board[1, j] == board[2, j])
                    return board[0, j];
            }
            if (board[1, 1] != 0 
                && board[0, 0] == board[1, 1] && board[1, 1] == board[2, 2] 
                ||board[0, 2] == board[1, 1] && board[1, 1] == board[2, 0])
                return board[1, 1];

            if (count == 9)
                return 3;
            return 0;
        }    
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值