Unity3d小案例——五子棋(一)

时间:2024-03-03 11:54:41

转自https://www.imooc.com/learn/636 

该教程为视频版,动手实践了一下然后复习一下

一、前期准备

unity3d不用说了 我感觉各个版本差别不是太大

棋盘的图片素材

 

 黑子和白子的图片素材

新建工程(2d)

新建文件夹导入图片素材  多选

在Inspector窗口中取消Generate Physics Shape  Filter Mope选择Ponit(点过滤/无过滤器)

 

 Inspector窗口详情可见 https://blog.csdn.net/u012632851/article/details/75063748

 

二、显示棋盘

 

创建图片组件 GameObject - UI - Image(或者直接在Hierarchy窗口右键) Image的名字更改为Board

将棋盘的图片拖进Source Image 同时调整图片的尺寸为560*560(实际证明不调整大小 后面会出问题 而且不同的图片 后面的算法要自行调整)

 

点击Canvas

 Canvas-Render Mode 调整摄像机 Screen Space - Camera 并选择Main Camera 

Canvas-Render Mode 详见https://blog.csdn.net/fdyshlk/article/details/78509909

Canvas Scale (详见https://www.cnblogs.com/morning-lee/p/7135782.html

UI Scale Mode 选择 Scale with Screen Size 根据屏幕大小定标(根据载体的分辨率来布局,会随屏幕分辨率的变化而变化。)

 Reference Resolution(参考分辨率)调整为常见的1280*720

Screen Match Mode(屏幕匹配模式) 按height匹配 即拉到最右

 

 最后调整board的坐标 PosX PosY 即可在Scene窗口看到棋盘

 

 

 

 

 三、交叉点

 

让每一个交叉点都被设置好为一个button 点击即放子

实际效果如图所示 棋盘被15*15个button布满 点击交叉点会有反应

 

 具体做法

首先创建一个button GameObject-UI-button

Source Image设置none 颜色设置红色半透明(或者其他你喜欢的 都是为了测试)

button大小设置为40*40 棋盘一个格子的大小

 

 

 接下来新建一个脚本 Cross  这个脚本用来存放每一个交叉点的坐标(GridX,GridY) 

GetCompoment <T>()从当前游戏对象获取组件T,只在当前游戏对象中获取,没得到的就返回null,不会去子物体中去寻找。

给button添加一个点击事件 使用Lambda表达式 (Lambda表达式详解 https://www.jianshu.com/p/e033cb93d99d

点击事件的后续代码 后面再说

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

public class Cross : MonoBehaviour
{

    //交叉点的坐标
    public int GridX;
    public int GridY;

    public MainLoop mainLoop;

    // Use this for initialization
    void Start()
    {
        GetComponent<Button>().onClick.AddListener(() =>
        {
            mainLoop.OnClick(this);
        });
    }
}

 

脚本写好拖拽到Hieraichy窗口上的button,把button改名cross制作成一个prefab(拖拽到Project窗口即可),然后delete掉Hieraichy窗口的button

现在一个交叉点制作 然后需要在整个棋盘上铺满所有的交叉点

新建一个脚本 ChessBoard (视频里用的是Board)

这个脚本的关键是 把Cross动态的铺满

关键代码

pos.x = -halfSize + x * crossSize;
pos.y = -halfSize + y * crossSize;

完整代码

 1 using System.Collections;
 2 using System.Collections.Generic;
 3 using UnityEngine;
 4 
 5 
 6 //把Cross动态排列到棋盘上
 7 public class ChessBoard : MonoBehaviour {
 8 
 9     public GameObject crossPrefab;
10 
11     
12     const float crossSize = 40;//crossPrefab的大小
13 
14     public const int crossCount = 15; //棋盘一行有15个交叉点
15 
16     public const int size = 560; //棋盘大小 
17 
18     public const int halfSize = size / 2;  //棋盘大小的一半
19 
20     Dictionary<int,Cross> _crossMap = new Dictionary<int, Cross>();   //存储每个交叉点按钮的信息
21 
22     static int MakeKey(int x,int y)
23     {
24         return x * 10000 + y;
25     }
26 
27     public  void Reset()
28     {
29 
30         //删掉board下所有子物体
31         foreach (Transform child in gameObject.transform)
32         {
33             GameObject.Destroy(child.gameObject);
34         }
35 
36         var mainLoop = GetComponent<MainLoop>();
37 
38         _crossMap.Clear();
39 
40         for(int x = 0; x < crossCount; x++)
41         {
42             for(int y = 0; y < crossCount; y++)
43             {
44                 //初始化prefab
45                 var crossObject = GameObject.Instantiate<GameObject>(crossPrefab);
46 
47                 // 归属于本层对象下
48                 crossObject.transform.SetParent(gameObject.transform);
49 
50                 // 复位缩放
51                 crossObject.transform.localScale = Vector3.one;  
52 
53                 //设置位置
54                 var pos = crossObject.transform.localPosition;
55                 pos.x = -halfSize + x * crossSize;
56                 pos.y = -halfSize + y * crossSize;
57                 pos.z = 1;
58                 crossObject.transform.localPosition = pos;
59 
60                 //记录信息
61                 var cross = crossObject.GetComponent<Cross>();
62                 cross.GridX = x;
63                 cross.GridY = y;
64                 cross.mainLoop = mainLoop;
65                 _crossMap.Add(MakeKey(x, y), cross);
66 
67             }
68         }
69     }
70     //取出Cross
71     public Cross GetCross(int x,int y)
72     {
73         Cross cross;
74         if (_crossMap.TryGetValue(MakeKey(x, y), out cross))
75         {
76             return cross;
77         }
78         return null;
79 
80     }
81 
82     // Use this for initialization
83     void Start () {
84         Reset();
85     }
86     
87     // Update is called once per frame
88     void Update () {
89         
90     }
91 }
ChessBoard

然后将脚本拖拽到Hieraichy窗口的棋盘下

(Mainloop脚本后面会说)