一、前期准备
unity3d不用说了 我感觉各个版本差别不是太大
棋盘的图片素材
黑子和白子的图片素材
新建工程(2d)
新建文件夹导入图片素材 多选
在Inspector窗口中取消Generate Physics Shape Filter Mope选择Ponit(点过滤/无过滤器)
Inspector窗口详情可见
二、显示棋盘
创建图片组件 GameObject - UI - Image(或者直接在Hierarchy窗口右键) Image的名字更改为Board
将棋盘的图片拖进Source Image 同时调整图片的尺寸为560*560(实际证明不调整大小 后面会出问题 而且不同的图片 后面的算法要自行调整)
点击Canvas
Canvas-Render Mode 调整摄像机 Screen Space - Camera 并选择Main Camera
Canvas-Render Mode 详见
Canvas Scale (详见)
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,不会去子物体中去寻找。
点击事件的后续代码 后面再说
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脚本后面会说)