egret 简单的一笔画算法,在wing中可以直接跑(以后玩这类游戏就有个作弊器了)
Posted 都斌大苏打
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了egret 简单的一笔画算法,在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, 3], [2, 3], [3, 3], [4, 3], [5, 3], [6, 3],
[2, 5], [3, 5], [4, 5], [5, 5], [6, 5],
];
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 showTxt2: eui.Label;
pathRect = [];//用于存储路径方块,便于管理
map: MapClass;
point = {};//用于存储阻挡点方块,便于管理
//初始化舞台
public init(stage: egret.Stage): void {
this.stage = stage;
this.initMap(8, 8);//输入地图的长宽(格子个数)
this.initmenu();
this.initBlock();
}
/**点击添加或删除阻挡点*/
protected addObstacle(evt: egret.TouchEvent): void {
let x = Math.floor(Math.floor(evt.localY) / (this.strokeWid + this.width));
let y = Math.floor(Math.floor(evt.localX) / (this.strokeWid + this.width));
let name = x + "_" + y;
if (this.point[name]) {
this.stage.removeChild(this.point[name]);
delete this.point[name];
this.map.update(x, y, false);
} else {
let xx = this.strokeWid * (y + 1) + this.width * y;
let yy = this.strokeWid * (x + 1) + this.width * x;
this.setRect(xx, yy, this.color1, 0.8, name);
this.map.update(x, y, true);
}
}
/**初始化菜单*/
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);
let shp1: eui.Rect = new eui.Rect();
shp1.fillAlpha = 0.2;
shp1.width = shp1.height = this.stage.stageWidth;
this.stage.addChild(shp1);
shp1.addEventListener(egret.TouchEvent.TOUCH_END, this.addObstacle, this);
this.showTxt2 = new eui.Label();
this.stage.addChild(this.showTxt2);
this.showTxt2.text = "重新生成路径";
this.showTxt2.size = 32;
this.showTxt2.textAlign = "center";
this.showTxt2.fontFamily = "SimHei";
this.showTxt2.textColor = 0xf3c382;
this.showTxt2.strokeColor = 0x0;
this.showTxt2.stroke = 1;
this.showTxt2.width = Math.floor(this.stage.stageWidth / 3 * 2);
this.showTxt2.x = this.stage.stageWidth - this.showTxt2.width >> 1;
this.showTxt2.y = 680;
this.showTxt2.addEventListener(egret.TouchEvent.TOUCH_END, this.touchHandler, this);
}
/**重新寻路*/
protected touchHandler(evt: egret.TouchEvent): void {
if (this.tt > 0)
clearInterval(this.tt);
this.findPath();
}
/**开始寻路*/
protected findPath(): void {
let returns = this.map.getPath();//输入起点和终点(2,2),(5,5)
this.path = returns;
//显示路径
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, i + "_" + j);
}
}
}
}
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, this.path[i][0] + "_" + this.path[i][1], true);
i++;
}, 50);
}
}
/**
* 初始化地图
* */
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 MapClass(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.touchEnabled = false;
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, name: string, bool: boolean = false): egret.Shape {
var shp: egret.Shape = new egret.Shape();
shp.touchEnabled = false;
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);//记录路径
} else {
this.point[name] = shp;//记录阻挡点
}
return shp;
}
}
//================================================寻路的类(核心代码)===============================================
class MapClass {
public closeArr: { [pos: string]: number };//已经用过的格子
public openArr: { [pos: string]: Array<number> };//可以走的格子
public Arr: { [pos: string]: number };//所有的格子
public pathArr: Array<Array<number>>;//当前的只能连1路奇点
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];
}
}
}
count: number;//迭代次数
allCount: number;
/**
* 获得最短路径;
* x1,y1是起点;x2,y2是终点
*/
public getPath(): any {
this.closeArr = {};
this.openArr = {};
this.count = 0;
this.pathArr = [];
for (let key in this.Arr) {
if (this.Arr[key] == 0)
this.openArr[key] = [Number(key.split("_")[0]), Number(key.split("_")[1])]
}
this.allCount = Object.keys(this.openArr).length;
if(this.returnOneStrockes())
return this.pathArr;
else{
console.log("不能一笔画完");
}
}
public jiArr: Array<Array<number>>;//当前的只能连1路奇点
public ouArr: Array<Array<number>>;//记录偶点
/**
* 判断this.openArr里面的奇点的情况
* 返回能否一步走完
*/
public returnOneStrockes(): boolean {
if (Object.keys(this.openArr).length == 1) {
for(let key in this.openArr){
this.pathArr.push([this.openArr[key][0],this.openArr[key][1]]);
}
return true;
}
this.count++;
if (this.count > this.allCount)//每个格子都走一遍时,表示不能一笔画
return false
this.jiArr = [];
this.ouArr = [];
for (let key in this.openArr) {
let four = this.getfour(this.openArr[key][0], this.openArr[key][1]);
if (four.length % 2 == 1) {//记录奇点
if (four.length == 1) {
this.jiArr.push([this.openArr[key][0], this.openArr[key][1]])
}
}
if (four.length % 2 == 0) {//记录偶点
this.ouArr.push([this.openArr[key][0], this.openArr[key][1]])
}
if (four.length == 0 && Object.keys(this.openArr).length > 1) //1.还有多个点时,就存在无路的点
return false;
if (this.jiArr.length > 2)//2.一路的奇点最多存在两个
return false
}
if (this.jiArr.length % 2 != 0 && this.jiArr.length != 1)//3.偶数个奇点时//奇数个奇点时,必须存在一个一路的奇点
return false;
if (Object.keys(this.openArr).length > 0 && this.jiArr.length > 0) {//存在奇点
let xy: Array<number> = [this.jiArr[0][0], this.jiArr[0][1]];
if (this.pathArr.length != 0) {//刚开始寻路时,以第一个奇点为起点
let lastP: Array<number> = [this.pathArr[this.pathArr.length - 1][0], this.pathArr[this.pathArr.length - 1][1]];
let four = this.getfour(lastP[0], lastP[1]);
if (four.length == 1) {
xy = four[0];
} else {
let ouXy: Array<number> = [];
let jiStr: Array<string> = this.toStringArr(this.jiArr);
let ouStr: Array<string> = this.toStringArr(this.ouArr);
for (let i in four) {
let fours:string = four[i].join("#");
if (jiStr.indexOf(fours) > -1) {
xy = [four[i][0], four[i][1]];
}
if (ouStr.indexOf(fours) > -1 && ouXy == []) {
ouXy = [four[i][0], four[i][1]];
}
}
if (!xy) xy = ouXy;
}
}
this.pathArr.push([xy[0], xy[1]]);
delete this.openArr[xy[0] + "_" + xy[1]];
this.closeArr[xy[0] + "_" + xy[1]] = 1;
return this.returnOneStrockes();
} else {//全为偶点
let xy: Array<number> = [this.ouArr[0][0], this.ouArr[0][1]];
if (this.pathArr.length != 0) {//刚开始寻路时,以第一个偶点为起点
let lastP: Array<number> = [this.pathArr[this.pathArr.length - 1][0], this.pathArr[this.pathArr.length - 1][1]];
xy = this.getfour(lastP[0], lastP[1])[0];
}
this.pathArr.push([xy[0], xy[1]]);
delete this.openArr[xy[0] + "_" + xy[1]];
this.closeArr[xy[0] + "_" + xy[1]] = 1;
return this.returnOneStrockes();
}
}
public toStringArr(arr:Array<Array<number>>):Array<string>{
let strArr:Array<string> = [];
for(let i in arr){
strArr.push(arr[i].join("#"))
}
return strArr;
}
//获得四个方向的格子[x,y,]
public getfour(x1: number, y1: number): Array<Array<number>> {
let siGe: Array<Array<number>> = [];
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]);
if (this.Arr[str2] == 0 && !this.closeArr[str2])
siGe.push([x1 - 1, y1]);
if (this.Arr[str3] == 0 && !this.closeArr[str3])
siGe.push([x1, y1 + 1]);
if (this.Arr[str4] == 0 && !this.closeArr[str4])
siGe.push([x1, y1 - 1]);
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 简单的一笔画算法,在wing中可以直接跑(以后玩这类游戏就有个作弊器了)的主要内容,如果未能解决你的问题,请参考以下文章