就那么随手一写代码质量不高,纯粹写demo。
const { ccclass, property } = cc._decorator;
const cost1: number = 10
const cost2: number = 14
const childMap: Array<Array<number>> = [
[-1, 0],
[-1, -1],
[0, -1],
[1, -1],
[1, 0],
[1, 1],
[0, 1],
[-1, 1]
]
@ccclass
export default class NewClass extends cc.Component {
@property(cc.Integer)
mapWidth: number = 10
@property(cc.Integer)
mapHeight: number = 10
@property(cc.SpriteFrame)
normalNode: cc.SpriteFrame = null
startNode: cc.Node = null
endNode: cc.Node = null
mapArr: Array<Array<number>> = []
nodeArr: Array<Array<cc.Node>> = []
openTable: Object = {}
closeTable: Object = {}
// LIFE-CYCLE CALLBACKS:
oderIdx: number = 2
// onLoad () {}
start() {
this.generiteMap()
}
generiteMap() {
let x = -1334 / 2 + 62 / 2 + 20
let y = 750 / 2 - 62 / 2 - 20
for (let i = 0; i < this.mapHeight; ++i) {
this.mapArr.push([])
this.nodeArr.push([])
for (let j = 0; j < this.mapWidth; ++j) {
let node = new cc.Node()
node.parent = this.node
let cp = node.addComponent(cc.Sprite)
cp.spriteFrame = this.normalNode
let n = Math.round(Math.random() * 3)
if (n == 0) {
node.color = cc.color(0, 0, 0, 255)
} else {
node.addComponent(cc.Button)
node.on('click', function (e) {
if (this.startNode && this.endNode && this.oderIdx % 2 == 0) {
this.startNode.color = cc.Color.WHITE
this.endNode.color = cc.Color.WHITE
}
if (this.oderIdx % 2 == 0) {
node.color = cc.Color.GREEN
this.startNode = node
} else {
this.endNode = node
node.color = cc.Color.BLUE
this.startFinding()
}
++this.oderIdx
}, this)
}
this.nodeArr[i].push(node)
this.mapArr[i].push(n)
node.position = cc.v2(x + (node.width + 10) * j, y - (node.height + 10) * i)
}
}
}
startFinding(): void {
let startPos = this.getIdxByNode(this.startNode)
let endPos = this.getIdxByNode(this.endNode)
let result:Object = null
let found:boolean = false
this.insertToOpen(this.generiteChild(startPos,startPos,endPos))
while(Object.keys(this.openTable).length > 0){
let cPoint = this.getBestPointInOpen()
if(cPoint['point']['x'] == endPos.x && cPoint['point']['y'] == endPos.y){
found = true
result = cPoint
break
}
this.removeInOpen(cPoint)
this.insertToClose(cPoint)
let children = this.generiteChildren(cPoint['point'],endPos)
let currentPoint = cPoint['point']
for(let pt of children){
let point = pt['point']
if(!this.inOpen(pt['point'])){
cc.log(cPoint['point']['x'], cPoint['point']['y'],'open')
let g = Math.abs(point.x - currentPoint.x) + Math.abs(point.y - currentPoint.y) <= 1 ? cost1 : cost2
let h = Math.pow(Math.abs(point.x - endPos.x) + 1, 2) + Math.pow(Math.abs(point.y - endPos.y) + 1, 2)
let f = g + h
cPoint['g'] = g
cPoint['f'] = f
cPoint['h'] = h
pt['parent'] = cPoint
this.insertToOpen(pt)
}else {
cc.log(cPoint['point']['x'], cPoint['point']['y'], 'close')
let g = Math.abs(point.x - currentPoint.x) + Math.abs(point.y - currentPoint.y) <= 1 ? cost1 : cost2
if(pt['g'] > g){
pt['g'] = g
pt['f'] = g + pt['h']
pt['parent'] = cPoint
}
}
}
if(this.inOpen(endPos)){
result = this.openTable['x'+endPos.x +'y'+endPos.y]
}
}
while(result.hasOwnProperty('parent')){
let p = result['point']
if(p.x != endPos.x || p.y != endPos.y)
this.nodeArr[p.x][p.y].color = cc.Color.MAGENTA
result = result['parent']
}
}
getIdxByNode(node: cc.Node) {
let x = -1334 / 2 + 62 / 2 + 20
let y = 750 / 2 - 62 / 2 - 20
let p = node.position
y = (y - p.y) / (62 + 10)
x = (p.x - x) / (62 + 10)
return cc.v2(Math.floor(y), Math.floor(x))
}
insertToTable(table: Object, pt: Object) {
table['x' + pt['point']['x'] + 'y' + pt['point']['y']] = pt
}
insertToOpen(pt: Object) {
this.insertToTable(this.openTable, pt)
}
insertToClose(pt: Object) {
this.insertToTable(this.closeTable, pt)
}
removeInOpen(pt:Object){
delete this.openTable['x'+pt['point']['x'] + 'y' + pt['point']['y']]
}
inOpen(pt: cc.Vec2) {
return this.openTable.hasOwnProperty('x' + pt.x + 'y' + pt.y)
}
inClose(pt: cc.Vec2) {
return this.closeTable.hasOwnProperty('x' + pt.x + 'y' + pt.y)
}
validPoint(pt: cc.Vec2) {
return pt.x >= 0 && pt.x < this.mapHeight &&
pt.y >= 0 && pt.y < this.mapWidth && this.mapArr[pt.x][pt.y] != 0
}
getBestPointInOpen(){
let max:number = Number.MAX_VALUE
let result:Object = null
for(let i in this.openTable){
let obj = this.openTable[i]
if(obj['f'] < max){
max = obj['f']
result = obj
}
}
return result
}
generiteChildren(pt: cc.Vec2,endp:cc.Vec2) {
let result: Array<Object> = []
for(let i of childMap){
let p = cc.v2(pt.x + i[0] , pt.y + i[1])
if(this.validPoint(p) &&! this.inClose(p)){
result.push(this.generiteChild(p,pt,endp))
}
}
return result
}
generiteChild(pt: cc.Vec2, startPos: cc.Vec2, endPos: cc.Vec2) {
let g = Math.abs(pt.x - startPos.x) + Math.abs(pt.y - startPos.y) <= 1 ? cost1 : cost2
let h = Math.pow(Math.abs(pt.x - endPos.x) + 1 , 2) + Math.pow(Math.abs(pt.y - endPos.y) + 1, 2)
let f = g + h
return {
g: g,
h: h,
f: f,
point: pt
}
}
// update (dt) {}
}