/**

* main类中加载场景
* 创建游戏场景
* Create a game scene
*/
private createGameScene() {
MtwGame.Instance.init(this.stage);
}

/**

*-----------------------------------------场景类--------------------------------

*/

class MtwGame {

public constructor() {
}
private static _instance: MtwGame;

public static get Instance(): MtwGame {
if (this._instance == null || this._instance == undefined) {
this._instance = new MtwGame();
}
return this._instance;
}

public stage: egret.Stage;
// X ↓; Y →
public mapTitle: Array<Array<number>>;
//障碍
public mapObstacle: Array<Array<number>> = [

[1, 4], [2, 4], [3, 4], [4, 4], [5, 4], [6, 4], [7, 4], [8, 4],
[9, 4], [10, 4], [11, 4], [12, 4], [13, 4], [14, 4],//[15, 4],

[12, 3],
[12, 2],

[2, 8], [3, 8], [4, 8], [5, 8], [6, 8], [7, 8], [8, 8],
[9, 8], [10, 8], [11, 8], [12, 8], [13, 8], [14, 8], [15, 8],

[1, 12], [2, 12], [3, 12], [4, 12], [5, 12], [6, 12], [7, 12], [8, 12],
[9, 12], [10, 12], [11, 12], [12, 12], [13, 12], [14, 12], //[15, 12],

[2, 14], [3, 14], [4, 14], [5, 14], [6, 14], [7, 14], //[8, 14],
[9, 14], [10, 14], [11, 14], [12, 14], [13, 14], [14, 14], [15, 14],
];
public path: Array<Array<number>>;
public width: number = 20;
public strokeWid: number = 3;
public color1: number = 0x00000;//线和阻挡的颜色
public color2: number = 0xe60b0b;//路径的颜色
// public color3: number = 0x00000;

public showTxt: eui.Label;
public showTxt2: eui.Label;
public x1: eui.EditableText;
public y1: eui.EditableText;
public x2: eui.EditableText;
public y2: eui.EditableText;
pathRect = [];//用于存储路径方块,便于管理
map: aStar;

//初始化舞台
public init(stage: egret.Stage): void {
this.stage = stage;
this.initMap(17, 17);//输入地图的长宽(格子个数)
this.initmenu();
this.initBlock();
this.findPath(2, 2, 15, 15);
}
/**初始化菜单*/
protected initmenu(): void {
let shp: egret.Shape = new egret.Shape();
shp.graphics.beginFill(0xffffff, 1);
shp.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight);
shp.graphics.endFill();
this.stage.addChild(shp);

this.x1 = new eui.EditableText();
this.stage.addChild(this.x1);
this.x1.text = "请输入x1";
this.x1.y = 700;

this.y1 = new eui.EditableText();
this.stage.addChild(this.y1);
this.y1.text = "请输入y1";
this.y1.y = 740;

this.x2 = new eui.EditableText();
this.stage.addChild(this.x2);
this.x2.text = "请输入x2";
this.x2.y = 780;

this.y2 = new eui.EditableText();
this.stage.addChild(this.y2);
this.y2.text = "请输入y2";
this.y2.y = 820;

this.x1.x = this.y1.x = this.x2.x = this.y2.x = 30;
this.x1.textColor = this.y1.textColor = this.x2.textColor = this.y2.textColor = 0x0;
this.x1.size = this.y1.size = this.x2.size = this.y2.size = 22;

this.showTxt = new eui.Label();
this.stage.addChild(this.showTxt);

this.showTxt2 = new eui.Label();
this.stage.addChild(this.showTxt2);
this.showTxt2.text = "重新生成路径";
this.showTxt.size = 24
this.showTxt2.size = 32;
this.showTxt.textAlign = this.showTxt2.textAlign = "center";
this.showTxt.fontFamily = this.showTxt2.fontFamily = "SimHei";
this.showTxt.textColor = this.showTxt2.textColor = 0xf3c382;
this.showTxt.strokeColor = this.showTxt2.strokeColor = 0x0;
this.showTxt.stroke = this.showTxt2.stroke = 1;
this.showTxt.width = this.showTxt2.width = Math.floor(this.stage.stageWidth / 3 * 2);
this.showTxt.x = this.showTxt2.x = this.stage.stageWidth - this.showTxt.width >> 1;
this.showTxt2.y = 680;
this.showTxt2.addEventListener(egret.TouchEvent.TOUCH_END, this.touchHandler, this);
}
/**重新寻路*/
protected touchHandler(evt: egret.TouchEvent): void {
if (Number(this.x1.text) && Number(this.y1.text) && Number(this.x2.text) && Number(this.y2.text)) {
this.showTxt.text = "";
if (this.tt > 0)
clearInterval(this.tt);
this.findPath(Number(this.x1.text), Number(this.y1.text), Number(this.x2.text), Number(this.y2.text));
} else {
this.showTxt.text = "请重新选择起点和终点";
}

}
/**开始寻路*/
protected findPath(x1: number, y1: number, x2: number, y2: number): void {

let returns = this.map.getPath(x1, y1, x2, y2);//输入起点和终点(2,2),(5,5)
if (typeof returns == "string") {
this.path = null;
this.showTxt.text = returns + ",请重新选择起点和终点";
} else {
this.path = returns;
}
this.showTxt.y = this.stage.stageHeight - 250 - this.showTxt.height;
//显示路径
this.initPath();
}
/**渲染地图*/
protected initBlock(): void {
//横
for (let i = 0; i < this.mapTitle.length + 1; i++) {
let y = i * (this.width + this.strokeWid);
this.setLine(0, y, this.stage.stageWidth, y)
}
//竖
for (let i = 0; i < this.mapTitle[0].length + 1; i++) {
let x = i * (this.width + this.strokeWid);
let height = this.width * this.mapTitle[0].length + this.strokeWid * (this.mapTitle[0].length + 1)
this.setLine(x, 0, x, height)
}
//阻挡点
for (let i = 0; i < this.mapTitle.length; i++) {
for (let j = 0; j < this.mapTitle[i].length; j++) {
if (this.mapTitle[i][j] == 1) {
this.setRect(this.strokeWid * (j + 1) + this.width * j, this.strokeWid * (i + 1) + this.width * i, this.color1, 0.8)
}
}
}
}
tt;
/**
* 将路径显示在地图上
*/
protected initPath(): void {
if (this.pathRect.length > 0) {
for (let i = 0; i < this.pathRect.length; i++) {
this.stage.removeChild(this.pathRect[i]);
}
this.pathRect = [];
}
if (this.path && this.path.length > 0) {
let i = 0;
this.tt = setInterval(() => {
if (!this.path[i]) {
clearInterval(this.tt);
return;
}
let x = this.strokeWid * (this.path[i][1] + 1) + this.width * this.path[i][1];
let y = this.strokeWid * (this.path[i][0] + 1) + this.width * this.path[i][0];
this.setRect(x, y, this.color2, 0.3, true);
i++;
}, 50);
}

// for (let i = 0; i < this.path.length; i++) {
// let x = this.strokeWid * (this.path[i][1] + 1) + this.width * this.path[i][1];
// let y = this.strokeWid * (this.path[i][0] + 1) + this.width * this.path[i][0];
// this.setRect(x, y, this.color2, 0.3, true)
// }
}

/**
* 初始化地图
* */
protected initMap(w: number, h: number): void {
if (w < 2 || h < 2) console.error("地图格子长宽数不对");
this.mapTitle = [];
for (let i = 0; i < h; i++) {
this.mapTitle.push([]);
for (let j = 0; j < w; j++) {
if (i == 0 || j == 0 || i == h - 1 || j == w - 1) {
this.mapTitle[i][j] = 1;
} else {
this.mapTitle[i][j] = 0;
}
}
}
this.width = (this.stage.stageWidth - (this.mapTitle[0].length + 1) * this.strokeWid) / this.mapTitle[0].length;
this.map = new aStar(this.mapTitle);
this.initObstacle();
for (let i in this.mapObstacle) {
this.map.update(this.mapObstacle[i][0], this.mapObstacle[i][1], true)
}
}
/**
* 将障碍显示在地图上
* */
protected initObstacle(): void {
for (let i = 0; i < this.mapObstacle.length; i++) {
if (this.mapObstacle[i][0] < this.mapTitle.length - 1 && this.mapObstacle[i][0] > 0
&& this.mapObstacle[i][1] < this.mapTitle[0].length - 1 && this.mapObstacle[i][1] > 0)
this.mapTitle[this.mapObstacle[i][0]][this.mapObstacle[i][1]] = 1;
}
}

//划线
public setLine(x: number, y: number, x1: number, y1: number): egret.Shape {
var shp: egret.Shape = new egret.Shape();
shp.graphics.lineStyle(this.strokeWid, this.color1);
shp.graphics.moveTo(x, y);
shp.graphics.lineTo(x1, y1);
shp.graphics.endFill();
this.stage.addChild(shp);
return shp;
}
//划块
protected setRect(x: number, y: number, col: number, alpha: number = 1, bool: boolean = false): egret.Shape {
var shp: egret.Shape = new egret.Shape();
shp.graphics.beginFill(col, alpha);
shp.graphics.drawRect(x, y, this.width, this.width);
shp.graphics.endFill();
this.stage.addChild(shp);
if (bool) {
this.pathRect.push(shp);
}
return shp;
}

//每次显示器的宽高变化时,重新渲染
protected onResizeHandler(e: egret.Event): void {
if (this.showTxt) this.showTxt.x = this.stage.stageWidth - this.showTxt.width >> 1;
if (this.showTxt) this.showTxt.y = this.stage.stageHeight - 50 - this.showTxt.height;
}
}

/**

*----------------------------------------------------------寻路--------------------------------------------------------------------

*/

//F:G和H的和,一般走最小值//G:A到该方块的距离//H:该方块到B的最近距离(不管有没有障碍物)
class aStar {
public closeArr: { [pos: string]: number };//不能走的格子
public openArr: { [pos: string]: Array<number> };//可以走的格子
public Arr: { [pos: string]: number };//所有的格子
openObj;//记录所有用过的格子的信息,用于最后找到终点后的寻路

public constructor(mapArr: Array<Array<number>>) {
this.Arr = {};
for (let i = 0; i < mapArr.length; i++) {
for (let j = 0; j < mapArr.length; j++) {
this.Arr[i + "_" + j] = mapArr[i][j];
}
}
}
/**
* 获得最短路径;
* x1,y1是起点;x2,y2是终点
*/
public getPath(x1: number, y1: number, x2: number, y2: number): any {
this.closeArr = {};
this.openObj = {};
this.openArr = {}
this.openArr[x1+"_"+y1] = [x1, y1, 0];//x,y,G
let curP = [];
let count = 0;//循环次数
let fourP;
let lastFNum:string = "";
if (this.Arr[x1 + "_" + y1] == 1 || this.Arr[x2 + "_" + y2] == 1) {
return "起点和终点不能是障碍物";
}
if (x1 ==x2 &&y2 == y1) {
return "起点和终点不能是同一个点";
}
if (this.Arr[x1 + "_" + y1] == null || this.Arr[x2 + "_" + y2] == null) {
return "起点和终点只能选中图中的格子";
}
let startTime: number = egret.getTimer();
for (; ;) {
lastFNum = this.getLastFNum(x2, y2);
curP = this.openArr[lastFNum];
count++;
if (curP[0] == x2 && curP[1] == y2) {
//生成路径
let ab = [[x2, y2]];
for (let i = 0; i < Object.keys(this.openObj).length; i++) {
let infor = this.openObj[ab[ab.length - 1][0] + "_" + ab[ab.length - 1][1]];
if (!infor) {//没有父节点的就是起点
console.log("找到最短的路了,终点是(" + x2 + "," + y2 + "),需要走" + ab.length + "步", "主循环" + count + "次");
console.log("计算所用时间:" + (egret.getTimer() - startTime));
return ab.reverse();
}
ab.push([infor[3], infor[4]]);
}
return ab.reverse();
}
//将格子加到close,并从open中删除
this.closeArr[curP[0] + "_" + curP[1]] = 1;
delete this.openArr[lastFNum];

fourP = this.getfour(curP[0], curP[1], curP[2])//获取四个方向的格子
if (fourP && fourP.length > 0) {
for (let i = 0; i < fourP.length; i++) {
let names:string = fourP[i][0]+"_"+fourP[i][1];
if(!this.openArr[names])
this.openArr[names] = fourP[i];
else{
//记录G小的数据
this.openArr[names] = fourP[i][2]<this.openArr[names][2]?fourP[i]:this.openArr[names];
}
}
}
this.getPointInfor();
if (Object.keys(this.openArr).length==0) {
console.log("死路一条", "主循环" + count + "次");
console.log("计算所用时间:" + (egret.getTimer() - startTime));
return "死路一条";
}
}
}

/**
* 获得估计路径长度;不管障碍物;
* x1,y1是起点;x2,y2是终点
*/
public getLastPath(x1: number, y1: number, x2: number, y2: number): number {
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
}
/**
* 获得f最小的格子;
*
*/
public getLastFNum(x2: number, y2: number): string {
let lastf: number;
let g: number;
let h: number;
let name:string;
for (let i in this.openArr) {
g = this.openArr[i][2];
h = this.getLastPath(this.openArr[i][0], this.openArr[i][1], x2, y2);
if (!lastf) {
lastf = g + h;
name = i;
} else {
if (g + h < lastf) {
lastf = g + h;
name = i;
}
}
}
return name;
}
/**
* 所有用过的点的信息
* 同时去重
*/
public getPointInfor(): void {
let point = [];
let newOpenArr = [];
for (let i in this.openArr) {
point = this.openArr[i];
if (!this.openObj[i])//新的点
this.openObj[i] = point;
else {
if (point[2] < this.openObj[i][2]) {
this.openObj[i] = point;
}
}
}
}
//获得四个方向的格子[x,y,]
public getfour(x1: number, y1: number, g: number): any {
let siGe = [];
let i = g + 1;
let str1: string = x1 + 1 + "_" + y1;
let str2: string = x1 - 1 + "_" + y1;
let str3: string = x1 + "_" + (y1 + 1);
let str4: string = x1 + "_" + (y1 - 1);
if (this.Arr[str1] == 0 && !this.closeArr[str1])
siGe.push([x1 + 1, y1, i, x1, y1]);
if (this.Arr[str2] == 0 && !this.closeArr[str2])
siGe.push([x1 - 1, y1, i, x1, y1]);
if (this.Arr[str3] == 0 && !this.closeArr[str3])
siGe.push([x1, y1 + 1, i, x1, y1]);
if (this.Arr[str4] == 0 && !this.closeArr[str4])
siGe.push([x1, y1 - 1, i, x1, y1]);
//八方向的格子
// let str5: string = x1 + 1 + "_" + (y1 + 1);
// let str6: string = x1 + 1 + "_" + (y1 - 1);
// let str7: string = x1 - 1 + "_" + (y1 + 1);
// let str8: string = x1 - 1 + "_" + (y1 - 1);
// if (this.Arr[str5] == 0 && !this.closeArr[str5])
// siGe.push([x1 + 1, y1 + 1, i, x1, y1]);
// if (this.Arr[str6] == 0 && !this.closeArr[str6])
// siGe.push([x1 + 1, y1 - 1, i, x1, y1]);
// if (this.Arr[str7] == 0 && !this.closeArr[str7])
// siGe.push([x1 - 1, y1 + 1, i, x1, y1]);
// if (this.Arr[str8] == 0 && !this.closeArr[str8])
// siGe.push([x1 - 1, y1 - 1, i, x1, y1]);
return siGe;
}

/**更新地图的阻挡物 */
public update(x1: number, y1: number, bool: boolean): void {
this.Arr[x1 + "_" + y1] = bool ? 1 : 0;
}

public dispose(): void {
this.closeArr = null;
this.openArr = null;
this.Arr = null;
this.openObj = null;
}

}

//代码还有很多可以优化,但怕忘记,先存到这里

//简单优化了一波

egret 简单的四方向的a星寻路,在wing中可以直接跑的更多相关文章

  1. 用简单直白的方式讲解A星寻路算法原理

    很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...

  2. egret 简单的一笔画算法,在wing中可以直接跑(以后玩这类游戏就有个作弊器了)

    /** * 在Main中创建游戏场景 * Create a game scene */ private createGameScene() { MtwGame.Instance.init(this.s ...

  3. 基于Unity的A星寻路算法(绝对简单完整版本)

    前言 在上一篇文章,介绍了网格地图的实现方式,基于该文章,我们来实现一个A星寻路的算法,最终实现的效果为: 项目源码已上传Github:AStarNavigate 在阅读本篇文章,如果你对于里面提到的 ...

  4. MySQL之单表查询 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER BY 八 限制查询的记录数:LIMIT 九 使用正则表达式查询

    MySQL之单表查询 阅读目录 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER B ...

  5. 使用 Tye 辅助开发 k8s 应用竟如此简单(四)

    续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中如何进行日志的统一管理. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首 ...

  6. 【Android】基于A星寻路算法的简单迷宫应用

    简介 基于[漫画算法-小灰的算法之旅]上的A星寻路算法,开发的一个Demo.目前实现后退.重新载入.路径提示.地图刷新等功能.没有做太多的性能优化,算是深化对A星寻路算法的理解. 界面预览: 初始化: ...

  7. [转载]A星寻路算法介绍

    转载自:http://www.raywenderlich.com/zh-hans/21503/a%E6%98%9F%E5%AF%BB%E8%B7%AF%E7%AE%97%E6%B3%95%E4%BB% ...

  8. A星寻路算法介绍

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  9. A星寻路算法(A* Search Algorithm)

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

随机推荐

  1. 【新特性】JDK1.6

    一.Desktop类和SystemTray类 在JDK6中 ,AWT新增加了两个类:Desktop和SystemTray. 前者可以用来打开系统默认浏览器浏览指定的URL,打开系统默认邮件客户端给指定 ...

  2. JavaScript 数组去重方法总结

    1.遍历数组法: 这应该是最简单的去重方法(实现思路:新建一新数组,遍历数组,值不在新数组就加入该新数组中) // 遍历数组去重法 function unique(arr){ var _arr = [ ...

  3. Vue小项目二手书商城:(二)axios前后端数据交互

    实现内容: 写路由接口(express) axios取数据 一.写接口 1.我们要在前端取到后端的数据(之前写的data.json)可以用vue-resourse或者用axios,在vue2之后官方就 ...

  4. Windows 下Jenkins进程误删,如何重启

    手残误删了Jenkins运行的java进程,结果.... 用管理员身份启动cmd 然后进入jenkins目录.运行 net start jenkins 否则会报系统错误5 延伸: net stop j ...

  5. python多版本共存

    根据环境变量的顺序调用python,pip等程序 将python.exe修改为python2.exe(或python3.exe)后可以通过不同的名字调用不同版本的python 注意修改Anaconda ...

  6. git1使用步骤初始化拉取修改提交推送

    Git 使用 git init 命令来初始化一个 Git 仓库,Git 的很多命令都需要在 Git 的仓库中运行,所以 git init 是使用 Git 的第一个命令. 在执行完成 git init  ...

  7. DAY 30 网络编程基础

    一.软件开发架构 1.c/s架构 c:客户端 s:服务端 2.b/s架构 b:浏览器 c:服务器 手机端:好像C/S架构比较火,其实不然,微信小程序.支付宝第三方接口 B/S架构的优点是统一接口 PC ...

  8. MySQL存储过程 CASE语句

    MySQL存储过程  CASE语句 除了IF语句,MySQL提供了一个替代的条件语句CASE. MySQL CASE语句使代码更加可读和高效. CASE语句有两种形式:简单的搜索CASE语句. 简单C ...

  9. linux命令 常用

    1.linux手动连接主机ssh '主机地址' 2.编辑 vi 查看i 编辑esc 退出编辑:wq 保存退出:q 直接退出 3. linux 防火墙 centOS7 firewall-cmd --sa ...

  10. DB9针和DB25针串口的引脚定义

    <设备监控技术详解>第3章串口设备监控,本章着力介绍串口交换机和串口联网方式.本节为大家介绍标准25针串口的引脚定义. 作者:李瑞民来源:机械工业出版社 3.3 串口线的制作和转换 串口的 ...