📖实现思路

实现思路

  1. 将一张完整的纹理分割成4*4的方块
  2. 给每个方块随机分配位置
  3. 针对每个方块的开始移动、移动中、移动结束事件执行指定操作
  4. 每次移动之后,检测拼图是否完成

💻代码实现

方块预制体组件Block

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@ccclass
export default class Block extends cc.Component {
startPos:cc.Vec3 = null
initialIndex:{row:Number, col:Number} = {
row:0,
col:0
}
protected onLoad(): void {
this.node.on(cc.Node.EventType.TOUCH_START, this.touchStart, this)
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.touchMove, this)
this.node.on(cc.Node.EventType.TOUCH_END, this.touchEnd, this)
}
protected onDestroy(): void {
this.node.off(cc.Node.EventType.TOUCH_START, this.touchStart, this)
this.node.off(cc.Node.EventType.TOUCH_MOVE, this.touchMove, this)
this.node.off(cc.Node.EventType.TOUCH_END, this.touchEnd, this)
}
// 选中碎片开始移动,碎片透明度降低,层级升高,记录碎片初始坐标
touchStart(e:cc.Event.EventTouch){
this.node.opacity = 128
this.node.zIndex = 1
this.startPos = this.node.position
}
// 碎片移动中,=
touchMove(e:cc.Event.EventTouch){
this.node.x += e.getDeltaX()
this.node.y += e.getDeltaY()
}
// 碎片移动结束,透明度和层级恢复
touchEnd(e:cc.Event.EventTouch){
this.node.opacity = 255
this.node.zIndex = 0
// 获取碎片当前坐标的序号坐标
let targetIndex = this.getIndex(this.node.position)
let originIndex = this.getIndex(this.startPos)
try{
// 交换2个碎片的坐标和在数组中的位置
let targetNode = window.blockArray[targetIndex.row][targetIndex.col]
this.node.setPosition(targetNode.position)
targetNode.setPosition(this.startPos)
window.blockArray[targetIndex.row][targetIndex.col] = this.node
window.blockArray[originIndex.row][originIndex.col] = targetNode
window.checkOver()
}catch(error){
this.node.setPosition(this.startPos)
}
}
// 像素坐标转序号坐标
getIndex(position:cc.Vec3){
return {
col:Math.floor(Math.abs(position.x / this.node.width + 0.5)),
row:Math.floor(Math.abs(position.y / this.node.height - 0.5))
}
}
// 初始化预制体
init(picTexture:cc.Texture2D, pos:{x:number, y:number}){
let sprite = this.node.getComponent(cc.Sprite)
let width = this.node.width
let height = this.node.height
// 切割纹理
let frame = new cc.SpriteFrame(picTexture, cc.rect(pos.x * width, pos.y * height, width, height))
sprite.spriteFrame = frame;
}
}

游戏组件Game

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@ccclass
export default class Game extends cc.Component {

@property(cc.Prefab)
// 碎片预制体
blockPrefab:cc.Prefab = null
blockArray:Array<cc.Node[]> = []
// 碎片尺寸
blockSize : number = 720 / 4
win:Boolean = false
start () {
window.blockArray = this.blockArray
window.checkOver = this.checkOver
// 动态加载拼图图片
cc.resources.load('img/cats',cc.Texture2D,(error:Error,assets:cc.Texture2D)=>{
if(error){
console.log(error)
return
}
for(let row = 0; row < 4; row++){
this.blockArray[row] = []
for(let col = 0; col < 4; col ++){
let newBlock = cc.instantiate(this.blockPrefab)
newBlock.getComponent(Block).initialIndex.row = row
newBlock.getComponent(Block).initialIndex.col = col
newBlock.getComponent(Block).init(assets,{x:col, y:row})
newBlock.setPosition(new cc.Vec2(this.blockSize * col, -this.blockSize * row))
this.node.addChild(newBlock)
this.blockArray[row][col] = newBlock


}
}
this.randomBlock()
})
}
// 检查游戏是否结束
checkOver(){
if(this.win) return
try{
for(let row = 0; row<4; row++){
for(let col = 0; col<4; col++){
let node = this.blockArray[row][col]
let block = node.getComponent(Block)
let curPos = block.getIndex(node.position)
if(curPos.row != block.initialIndex.row || curPos.col != block.initialIndex.col){
return
}
}
}
this.win = true
setTimeout(()=>{
alert("You Win!")
},300)
}catch(err){
console.log(err)
}
}
// 打乱碎片顺序
randomBlock(){
for(let row = 0; row<4; row++){
for(let col = 0; col<4; col++){
let exRow = Math.floor(Math.random() * 4) // 0-4
let exCol = Math.floor(Math.random() * 4) // 0-4
let exNode = this.blockArray[exRow][exCol]
let curNode = this.blockArray[row][col]

let tempPos = exNode.position
exNode.setPosition(curNode.position)
curNode.setPosition(tempPos)

this.blockArray[exRow][exCol] = curNode
this.blockArray[row][col] = exNode
}
}
}
}