📖规则说明

规则说明

格子代表细胞生命,生死规则如下:

  • 一个细胞周围一共有8个细胞
  • 如果一个细胞周围有3个细胞,则生(死则转生)
  • 一个细胞周围有2个细胞,状态不变
  • 其他情况,细胞为死

1️⃣步骤一:实现网格

实现思路

  1. 创建网格容器cellArea
  2. 创建单个网格预制件cell
    • 双层方格,模拟边框
  3. 在cellArea上,使用程序生成cell网格
  4. 给预制件cell添加记录和修改状态的脚本
  5. 给cellArea添加Touch事件,监听点击到的细胞网格

程序生成网格

  • 网格容器cellArea
    • 尺寸:8000 * 600
  • 单个网格预制件cell
    • 尺寸:10 * 10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@ccclass
export default class Game extends cc.Component {
// 游戏暂停
pause: boolean = true
// 容器
@property(cc.Node)
cellArea: cc.Node = null
// 细胞预制件
@property(cc.Prefab)
cellPre: cc.Prefab = null
// 细胞尺寸
cellSize: number = 10
// 横载数量
cellW_Num: number = 0
// 列载数量
cellH_Num: number = 0
// 存放细胞节点
cells: Array<cc.Node[]> = []
onLoad () {
this.cellW_Num = this.cellArea.width / this.cellSize // 800/10=80
this.cellH_Num = this.cellArea.height / this.cellSize // 600/10=60
for(let i = 0; i < this.cellW_Num;i++){
this.cells[i] = new Array() // 初始化细胞矩阵
}
}
start () {
this.layout()
}
// 布置细胞
layout(){
for(let i = 0 ; i < this.cellW_Num; i++){
for(let j = 0; j < this.cellH_Num; j++){
let newCell = cc.instantiate(this.cellPre)
newCell.x = i * this.cellSize
newCell.y = j * this.cellSize
newCell.setParent(this.cellArea)
this.cells[i][j] = newCell
}
}
}
}

细胞状态脚本Cell

单个细胞中,只有一个信息:是否存活?
所以在cell脚本中,需要实现如下功能:

  • 记录cell的state
  • 修改state,根据修改后的state修改cell的颜色
  • 暴露出一个切换state的接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@ccclass
export default class Cell extends cc.Component {
@property(cc.Node)
cellItem:cc.Node = null
// 0=存活 1=死亡
state:number = 0
setState(state = 0){
this.state = state
switch(this.state){
case 0 :
this.cellItem.color = new cc.Color(255,255,255);
break;
case 1 :
this.cellItem.color = new cc.Color(0,0,0);
break;
}
}
switchState(){
this.setState([1,0][this.state])
}
}

网格交互

鼠标点击网格时,可以切换细胞的存活状态,
对cellArea进行鼠标点击事件监听:

  1. 获取鼠标事件的世界坐标
  2. 将世界坐标转换为cellArea下的局部坐标
  3. 根据局部坐标,结合cell尺寸,计算当前鼠标事件触发的cell的索引坐标
  4. 找到cell,切换状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@ccclass
export default class Game extends cc.Component {
//...
start () {
// ...
this.cellArea.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this)
}
onTouchStart(e:cc.Event.EventTouch){
let pos = e.getLocation()
let n_pos = this.cellArea.convertToNodeSpaceAR(pos)
let i = Math.floor(n_pos.x / this.cellSize)
let j = Math.floor(n_pos.y / this.cellSize)
let cell = this.cells[i][j]
// 切换细胞网格状态
cell.getComponent(Cell).switchState()
}
}

2️⃣步骤二:实现细胞活动模拟

繁衍速度控制

在update中累加帧间隔时间,每过0.1秒,刷新一次:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@ccclass
export default class Game extends cc.Component {
// 游戏暂停
pause:boolean = true
// 计时器
timeStep:number = 0
update (dt) {
if(this.pause) return
this.timeStep += dt
if(this.timeStep >= 0.1){
this.timeStep = 0;
this.lifeChange()
}
}
// 生命繁衍
lifeChange(){
//...
}
}

实现细胞繁衍死亡

实现思路:

  1. 记录细胞矩阵cells当前状态快照nowStateList
  2. 取出每一个cell,根据其八个方位的细胞判断其是否有必要改变生命状态

记录快照,判断八方结果是否有必要改变生命状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@ccclass
export default class Game extends cc.Component {
// 生命繁衍
lifeChange(){
let nowStateList = []
// 记录状态快照
for(let i = 0; i< this.cellW_Num; i++){
nowStateList[i] = []
for(let j = 0; j< this.cellH_Num; j++){
let state = this.cells[i][j].getComponent(Cell).state
nowStateList[i][j] = state
}
}
// 根据判断是否需要切换细胞状态
for(let i = 0;i<this.cellW_Num;i++){
for(let j = 0; j < this.cellH_Num; j++){
let state = this.getCellNextState(nowStateList, {x:i, y:j})
if(state){
this.cells[i][j].getComponent(Cell).switchState()
}
}
}
}
}

判断是否有必要改变细胞状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@ccclass
export default class Game extends cc.Component {
// 计算在(x,y)坐标处,状态为nowState的细胞的下一步状态
getCellNextState(nowStateList, {x, y}){
let nowState = nowStateList[x][y]
let nearCount = 0
// 八个方位的偏移量
let grids = [
{dx:1, dy:-1}, {dx:1, dy:0}, {dx:1, dy:1},
{dx:0, dy:-1}, {dx:0, dy:1},
{dx:-1, dy:-1}, {dx:-1, dy:0}, {dx:-1, dy:1},
]
for(let grid of grids){
let tx = x + grid.dx;
if(tx >= this.cellW_Num) tx = 0
if(tx <= -1) tx = this.cellW_Num - 1
let ty = y + grid.dy;
if(ty >= this.cellH_Num) ty = 0
if(ty <= -1) ty = this.cellH_Num - 1
let targetState = nowStateList[tx][ty]
if(targetState == 1){
nearCount += 1
}
}
// 2个活细胞,不变[nginx.conf](..%2F..%2F..%2F..%2F..%2F..%2F..%2FOneDrive%2F%D7%C0%C3%E6%2Fnginx.conf)
if(nearCount == 2) return false
// 3个活细胞,(死转)生
if(nearCount == 3){
if(nowState == 0) return true
if(nowState == 1) return false
}
// 原先为生,死去
if(nowState == 1) return true
// 不变
return false
}
}