egret 简单的四方向的a星寻路,在wing中可以直接跑
/**
* 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中可以直接跑的更多相关文章
- 用简单直白的方式讲解A星寻路算法原理
很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...
- egret 简单的一笔画算法,在wing中可以直接跑(以后玩这类游戏就有个作弊器了)
/** * 在Main中创建游戏场景 * Create a game scene */ private createGameScene() { MtwGame.Instance.init(this.s ...
- 基于Unity的A星寻路算法(绝对简单完整版本)
前言 在上一篇文章,介绍了网格地图的实现方式,基于该文章,我们来实现一个A星寻路的算法,最终实现的效果为: 项目源码已上传Github:AStarNavigate 在阅读本篇文章,如果你对于里面提到的 ...
- MySQL之单表查询 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER BY 八 限制查询的记录数:LIMIT 九 使用正则表达式查询
MySQL之单表查询 阅读目录 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER B ...
- 使用 Tye 辅助开发 k8s 应用竟如此简单(四)
续上篇,这篇我们来进一步探索 Tye 更多的使用方法.本篇我们来了解一下如何在 Tye 中如何进行日志的统一管理. Newbe.Claptrap 是一个用于轻松应对并发问题的分布式开发框架.如果您是首 ...
- 【Android】基于A星寻路算法的简单迷宫应用
简介 基于[漫画算法-小灰的算法之旅]上的A星寻路算法,开发的一个Demo.目前实现后退.重新载入.路径提示.地图刷新等功能.没有做太多的性能优化,算是深化对A星寻路算法的理解. 界面预览: 初始化: ...
- [转载]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% ...
- A星寻路算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- A星寻路算法(A* Search Algorithm)
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
随机推荐
- 第二课丶pygame
学号:2017*****1024 姓名:王劲松 我的码云贪吃蛇项目仓库:https://gitee.com/Danieljs/sesnake 分析游戏中的备注和问题:10分钟 游戏名称.分数改动:3分 ...
- Java基础学习-标识符
1.标识符的作用 -给包.类.方法.变量等起名字 2.组成规则 -这里的字符采用的是Unicode字符集,所以包括英文大小写字母,中文字符,数字字符等.不建议使用汉字. -下划 ...
- Elasticsearch .net client NEST 5.x 使用总结
目录: Elasticsearch .net client NEST 5.x 使用总结 elasticsearch_.net_client_nest2.x_到_5.x常用方法属性差异 Elastics ...
- LeetCode120-Triangle-数组,动态规划
题目描述 Problem Description: Given a triangle, find the minimum path sum from top to bottom. Each ste ...
- php动态获取网页图片路径~
<?phpheader("Content-type:text/html;charset=utf-8"); 请求的url $url = 'http://dsc.taobaocd ...
- leetcode02大数相加
惭愧惭愧,这道题居然卡了两天,犯了一堆错误,现在一一总结 错误 头一天我看给的测试用例误以为输入是数组,做了半天也无法输出链表的正确格式,后来把输入当成链表,才正确了 我没看到编辑器给了一套链表,自己 ...
- 关于虹软人脸识别SDK的接入
背景: 虹软的人脸识别还是不错的,在官方注册一个账号,成为开发者,下载SDK的jar包,在开发者中心,找一个demo就可以开始做了,安装里边的逻辑,先看理解代码,然后就可以控制代码,完成自己想要的功能 ...
- vbuffer.hpp
//vov #ifndef VBUFFER_HPP #define VBUFFER_HPP #include <iostream> #include <deque> #incl ...
- Evaluate X and Y returned from the differential equation solvers using printput frequency in Python的代码
把内容过程中经常用到的一些内容段做个备份,如下的内容是关于Evaluate X and Y returned from the differential equation solvers using ...
- Unity --- 设置选择的图片的格式
static void Setting(string assetPath, int maxSize, TextureImporterFormat androidFormat, TextureImpor ...