first
This commit is contained in:
35
assets/script/Main.ts
Normal file
35
assets/script/Main.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-07-03 16:13:17
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-17 13:43:02
|
||||
*/
|
||||
import { profiler, _decorator } from 'cc';
|
||||
import { DEBUG } from 'cc/env';
|
||||
import { oops } from '../../extensions/oops-plugin-framework/assets/core/Oops';
|
||||
import { Root } from '../../extensions/oops-plugin-framework/assets/core/Root';
|
||||
import { ecs } from '../../extensions/oops-plugin-framework/assets/libs/ecs/ECS';
|
||||
import { UIConfigData } from './game/common/config/GameUIConfig';
|
||||
import { smc } from './game/common/SingletonModuleComp';
|
||||
import { Initialize } from './game/initialize/Initialize';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('Main')
|
||||
export class Main extends Root {
|
||||
start() {
|
||||
if (DEBUG) profiler.showStats();
|
||||
}
|
||||
|
||||
protected async run() {
|
||||
smc.initialize = ecs.getEntity<Initialize>(Initialize);
|
||||
}
|
||||
|
||||
protected initGui() {
|
||||
oops.gui.init(UIConfigData);
|
||||
}
|
||||
|
||||
protected initEcsSystem() {
|
||||
|
||||
}
|
||||
}
|
||||
13
assets/script/Main.ts.meta
Normal file
13
assets/script/Main.ts.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "0eec0b38-aab6-45ee-89cf-95806b0fecbe",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"moduleId": "project:///assets/script/Main.js",
|
||||
"importerSettings": 4,
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
12
assets/script/game.meta
Normal file
12
assets/script/game.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "b8688d91-9274-40b5-a605-23ee4e5a4eec",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
9
assets/script/game/backup.meta
Normal file
9
assets/script/game/backup.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "0.0.1",
|
||||
"importer": "*",
|
||||
"imported": true,
|
||||
"uuid": "058e3947-1549-4999-be3f-5417729d9c1c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/common.meta
Normal file
12
assets/script/game/common.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "357b1816-e65d-47e7-938e-a74526a54b65",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
9
assets/script/game/common/GameUIBase.ts.meta
Normal file
9
assets/script/game/common/GameUIBase.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "88cd6342-234d-42f8-a10a-4b5b1d33a745",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
26
assets/script/game/common/SingletonModuleComp.ts
Normal file
26
assets/script/game/common/SingletonModuleComp.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-11-18 14:20:46
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 15:46:16
|
||||
*/
|
||||
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { Initialize } from "../initialize/Initialize";
|
||||
import { GameMap } from "../map/GameMap";
|
||||
import { Role } from "../role/Role";
|
||||
|
||||
/** 游戏模块 */
|
||||
@ecs.register('SingletonModule')
|
||||
export class SingletonModuleComp extends ecs.Comp {
|
||||
/** 游戏初始化模块 */
|
||||
initialize: Initialize = null!;
|
||||
/** 游戏地图 */
|
||||
map: GameMap = null!;
|
||||
/** 游戏主角 */
|
||||
own: Role = null;
|
||||
|
||||
reset() { }
|
||||
}
|
||||
|
||||
export var smc: SingletonModuleComp = ecs.getSingleton(SingletonModuleComp);
|
||||
9
assets/script/game/common/SingletonModuleComp.ts.meta
Normal file
9
assets/script/game/common/SingletonModuleComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "58714c1c-3ffe-4ad1-959a-82e5dfeb2dc3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/common/config.meta
Normal file
12
assets/script/game/common/config.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "7775e602-1231-4777-a927-a5cbb41c8518",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
14
assets/script/game/common/config/GameEvent.ts
Normal file
14
assets/script/game/common/config/GameEvent.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-11-23 15:28:39
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-01-26 16:42:00
|
||||
*/
|
||||
|
||||
/** 游戏事件 */
|
||||
export enum GameEvent {
|
||||
/** 游戏服务器连接成功 */
|
||||
GameServerConnected = "GameServerConnected",
|
||||
/** 登陆成功 */
|
||||
LoginSuccess = "LoginSuccess"
|
||||
}
|
||||
9
assets/script/game/common/config/GameEvent.ts.meta
Normal file
9
assets/script/game/common/config/GameEvent.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "28ac0ad6-53bf-471a-9256-ae7c8ad351a7",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
27
assets/script/game/common/config/GameUIConfig.ts
Normal file
27
assets/script/game/common/config/GameUIConfig.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Date: 2021-08-12 09:33:37
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 16:58:46
|
||||
*/
|
||||
|
||||
import { LayerType, UIConfig } from "../../../../../extensions/oops-plugin-framework/assets/core/gui/layer/LayerManager";
|
||||
|
||||
/** 界面唯一标识(方便服务器通过编号数据触发界面打开) */
|
||||
export enum UIID {
|
||||
/** 资源加载界面 */
|
||||
Loading = 1,
|
||||
/** 弹窗界面 */
|
||||
Window,
|
||||
/** 加载与延时提示界面 */
|
||||
Netinstable,
|
||||
/** 摇杆控制 */
|
||||
Role_Controller
|
||||
}
|
||||
|
||||
/** 打开界面方式的配置数据 */
|
||||
export var UIConfigData: { [key: number]: UIConfig } = {
|
||||
[UIID.Loading]: { layer: LayerType.UI, prefab: "loading/prefab/loading", bundle: "resources" },
|
||||
[UIID.Netinstable]: { layer: LayerType.PopUp, prefab: "common/prefab/netinstable" },
|
||||
[UIID.Window]: { layer: LayerType.Dialog, prefab: "common/prefab/window" },
|
||||
[UIID.Role_Controller]: { layer: LayerType.UI, prefab: "gui/prefab/role_controller" },
|
||||
}
|
||||
9
assets/script/game/common/config/GameUIConfig.ts.meta
Normal file
9
assets/script/game/common/config/GameUIConfig.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "14663cf6-fb92-4921-8ba9-c836b2667737",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
13
assets/script/game/common/config/QueryConfig.ts.meta
Normal file
13
assets/script/game/common/config/QueryConfig.ts.meta
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1f8651a4-0870-4475-ae85-d7e8b93c53b4",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"moduleId": "project:///assets/script/game/config/QueryConfig.js",
|
||||
"importerSettings": 4,
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
9
assets/script/game/common/config/UIConfig.ts.meta
Normal file
9
assets/script/game/common/config/UIConfig.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "084510dd-1c52-44e1-9bce-00633e73f0fc",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/initialize.meta
Normal file
12
assets/script/game/initialize.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "b005e8c9-418f-4529-8b5c-862aeb5977b1",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
89
assets/script/game/initialize/Initialize.ts
Normal file
89
assets/script/game/initialize/Initialize.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-11-11 17:45:23
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-17 12:38:59
|
||||
*/
|
||||
import { Node } from "cc";
|
||||
import { UICallbacks } from "../../../../extensions/oops-plugin-framework/assets/core/gui/layer/Defines";
|
||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import { AsyncQueue, NextFunction } from "../../../../extensions/oops-plugin-framework/assets/libs/collection/AsyncQueue";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { UIID } from "../common/config/GameUIConfig";
|
||||
import { LoadingViewComp } from "./view/LoadingViewComp";
|
||||
|
||||
/**
|
||||
* 游戏进入初始化模块
|
||||
* 1、热更新
|
||||
* 2、加载默认资源
|
||||
*/
|
||||
@ecs.register(`Initialize`)
|
||||
export class Initialize extends ecs.Entity {
|
||||
LoadingView!: LoadingViewComp;
|
||||
|
||||
protected init() {
|
||||
var queue: AsyncQueue = new AsyncQueue();
|
||||
|
||||
// 加载自定义资源
|
||||
this.loadCustom(queue);
|
||||
// 加载多语言包
|
||||
this.loadLanguage(queue);
|
||||
// 加载公共资源
|
||||
this.loadCommon(queue);
|
||||
// 加载游戏内容加载进度提示界面
|
||||
this.onComplete(queue);
|
||||
|
||||
queue.play();
|
||||
}
|
||||
|
||||
|
||||
/** 加载自定义内容(可选) */
|
||||
private loadCustom(queue: AsyncQueue) {
|
||||
queue.push(async (next: NextFunction, params: any, args: any) => {
|
||||
// 加载多语言对应字体
|
||||
oops.res.load("language/font/" + oops.language.current, next);
|
||||
});
|
||||
}
|
||||
|
||||
/** 加载化语言包(可选) */
|
||||
private loadLanguage(queue: AsyncQueue) {
|
||||
queue.push((next: NextFunction, params: any, args: any) => {
|
||||
// 设置默认语言
|
||||
let lan = oops.storage.get("language");
|
||||
// if (lan == null) {
|
||||
if (lan == null || lan == "") {
|
||||
lan = "zh";
|
||||
oops.storage.set("language", lan);
|
||||
}
|
||||
|
||||
// 设置语言包路径
|
||||
oops.language.pack.json = oops.config.game.languagePathJson;
|
||||
oops.language.pack.texture = oops.config.game.languagePathTexture;
|
||||
|
||||
// 加载语言包资源
|
||||
oops.language.setLanguage(lan, next);
|
||||
});
|
||||
}
|
||||
|
||||
/** 加载公共资源(必备) */
|
||||
private loadCommon(queue: AsyncQueue) {
|
||||
queue.push((next: NextFunction, params: any, args: any) => {
|
||||
oops.res.loadDir("common", next);
|
||||
});
|
||||
}
|
||||
|
||||
/** 加载完成进入游戏内容加载界面 */
|
||||
private onComplete(queue: AsyncQueue) {
|
||||
queue.complete = () => {
|
||||
var uic: UICallbacks = {
|
||||
onAdded: (node: Node, params: any) => {
|
||||
var comp = node.getComponent(LoadingViewComp) as ecs.Comp;
|
||||
this.add(comp);
|
||||
}
|
||||
};
|
||||
|
||||
// 界面管理 - 打开游戏内容资源加载进度提示界面
|
||||
oops.gui.open(UIID.Loading, null, uic);
|
||||
};
|
||||
}
|
||||
}
|
||||
9
assets/script/game/initialize/Initialize.ts.meta
Normal file
9
assets/script/game/initialize/Initialize.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "ffbce42c-e99f-48a0-8e73-ea6b756af330",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/script/game/initialize/LoadingViewComp.ts.meta
Normal file
9
assets/script/game/initialize/LoadingViewComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e316d2a4-1d8a-4f55-994c-f00db0076e7f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/initialize/view.meta
Normal file
12
assets/script/game/initialize/view.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "a36c4006-66a4-4a3e-9f87-e64b179de4e5",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
92
assets/script/game/initialize/view/LoadingViewComp.ts
Normal file
92
assets/script/game/initialize/view/LoadingViewComp.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-07-03 16:13:17
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-17 13:46:25
|
||||
*/
|
||||
import { _decorator } from "cc";
|
||||
import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCVMParentComp } from "../../../../../extensions/oops-plugin-framework/assets/module/common/CCVMParentComp";
|
||||
import { UIID } from "../../common/config/GameUIConfig";
|
||||
import { smc } from "../../common/SingletonModuleComp";
|
||||
import { GameMap } from "../../map/GameMap";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/** 游戏资源加载 */
|
||||
@ccclass('LoadingViewComp')
|
||||
@ecs.register('LoadingView', false)
|
||||
export class LoadingViewComp extends CCVMParentComp {
|
||||
/** VM 组件绑定数据 */
|
||||
data: any = {
|
||||
/** 加载资源当前进度 */
|
||||
finished: 0,
|
||||
/** 加载资源最大进度 */
|
||||
total: 0,
|
||||
/** 加载资源进度比例值 */
|
||||
progress: "",
|
||||
/** 加载流程中提示文本 */
|
||||
prompt: ""
|
||||
};
|
||||
|
||||
private progress: number = 0;
|
||||
|
||||
reset(): void {
|
||||
// 获取用户信息的多语言提示文本
|
||||
this.data.prompt = oops.language.getLangByID("loading_load_player");
|
||||
|
||||
// 关闭加载界面
|
||||
oops.gui.remove(UIID.Loading);
|
||||
|
||||
// 释放加载界面资源
|
||||
oops.res.releaseDir("loading");
|
||||
|
||||
// 加载地图
|
||||
var map = ecs.getEntity<GameMap>(GameMap);
|
||||
map.load();
|
||||
smc.map = map;
|
||||
}
|
||||
|
||||
start() {
|
||||
this.loadRes();
|
||||
}
|
||||
|
||||
/** 加载资源 */
|
||||
private async loadRes() {
|
||||
this.data.progress = 0;
|
||||
this.loadCustom();
|
||||
this.loadGameRes();
|
||||
}
|
||||
|
||||
/** 加载游戏本地JSON数据(自定义内容) */
|
||||
private loadCustom() {
|
||||
// 加载游戏本地JSON数据的多语言提示文本
|
||||
this.data.prompt = oops.language.getLangByID("loading_load_json");
|
||||
}
|
||||
|
||||
/** 加载初始游戏内容资源 */
|
||||
private loadGameRes() {
|
||||
// 加载初始游戏内容资源的多语言提示文本
|
||||
this.data.prompt = oops.language.getLangByID("loading_load_game");
|
||||
|
||||
oops.res.loadDir("game", this.onProgressCallback.bind(this), this.onCompleteCallback.bind(this));
|
||||
}
|
||||
|
||||
/** 加载进度事件 */
|
||||
private onProgressCallback(finished: number, total: number, item: any) {
|
||||
this.data.finished = finished;
|
||||
this.data.total = total;
|
||||
|
||||
var progress = finished / total;
|
||||
if (progress > this.progress) {
|
||||
this.progress = progress;
|
||||
this.data.progress = (progress * 100).toFixed(2);
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载完成事件 */
|
||||
private onCompleteCallback() {
|
||||
this.ent.remove(LoadingViewComp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "92429ca4-4e7c-450a-b706-c96e7c2568e3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/map.meta
Normal file
12
assets/script/game/map.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "9cb6ee85-b639-4a33-94fd-8d1ee03c5c52",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
36
assets/script/game/map/GameMap.ts
Normal file
36
assets/script/game/map/GameMap.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-02-12 11:02:21
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 15:20:55
|
||||
*/
|
||||
import { instantiate, Prefab } from "cc";
|
||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { MapModelComp } from "./model/MapModelComp";
|
||||
import { MapViewComp } from "./view/MapViewComp";
|
||||
|
||||
/** 游戏地图 */
|
||||
@ecs.register(`GameMap`)
|
||||
export class GameMap extends ecs.Entity {
|
||||
MapModel!: MapModelComp;
|
||||
MapView!: MapViewComp;
|
||||
|
||||
protected init(): void {
|
||||
this.addComponents<ecs.Comp>(
|
||||
MapModelComp);
|
||||
}
|
||||
|
||||
/** 加载地图显示资源 */
|
||||
load() {
|
||||
oops.res.load(this.MapModel.resPrefab, Prefab, (err: Error | null, res: Prefab) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
var map = instantiate(res);
|
||||
map.parent = oops.game.root;
|
||||
|
||||
this.add(map.getChildByName("map").getComponent(MapViewComp));
|
||||
});
|
||||
}
|
||||
}
|
||||
9
assets/script/game/map/GameMap.ts.meta
Normal file
9
assets/script/game/map/GameMap.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "d15fc8d4-c897-4a5c-a97c-b65114b41a69",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/map/model.meta
Normal file
12
assets/script/game/map/model.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "8c68118e-d594-4966-8748-7bbf4ee62ee1",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
42
assets/script/game/map/model/MapModelComp.ts
Normal file
42
assets/script/game/map/model/MapModelComp.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-08-04 15:08:34
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 15:23:20
|
||||
*/
|
||||
|
||||
import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
|
||||
@ecs.register('MapModel')
|
||||
export class MapModelComp extends ecs.Comp {
|
||||
/** 初始地图编号 */
|
||||
id: number = 1;
|
||||
|
||||
/** 地图数据配置 */
|
||||
resConfigMap: string = "config/map/map";
|
||||
|
||||
/** 地图转场点数据配置 */
|
||||
resDeliveryMap: string = "config/map/map_delivery";
|
||||
|
||||
/** 地图显示预制 */
|
||||
resPrefab: string = "game/map/map_rpg";
|
||||
|
||||
/** 地图内容资源 */
|
||||
getResContentMiniMap(mapName: string): string {
|
||||
return `content/map/${mapName}/${mapName}/miniMap/texture`;
|
||||
};
|
||||
|
||||
/** 地图瓦片资源 */
|
||||
getResContentSlices(bgName: string, key: string): string {
|
||||
return `content/map/${bgName}/${bgName}/slices/${key}/texture`;
|
||||
};
|
||||
|
||||
/** 地图数据资源 */
|
||||
getResContentData(mapName: string): string {
|
||||
return `content/map/${mapName}/${mapName}`;
|
||||
};
|
||||
|
||||
reset() {
|
||||
|
||||
}
|
||||
}
|
||||
9
assets/script/game/map/model/MapModelComp.ts.meta
Normal file
9
assets/script/game/map/model/MapModelComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "2f2380b0-3fa7-48ee-8e30-24e5d718f91e",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/map/view.meta
Normal file
12
assets/script/game/map/view.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "22e4e848-ae40-4493-ba1f-bf4cd25ec4ed",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
71
assets/script/game/map/view/MapViewComp.ts
Normal file
71
assets/script/game/map/view/MapViewComp.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { v3, Vec3, _decorator } from "cc";
|
||||
import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { CCComp } from "../../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||
import { smc } from "../../common/SingletonModuleComp";
|
||||
import { Role } from "../../role/Role";
|
||||
// import MapRoadUtils from "./map/road/MapRoadUtils";
|
||||
import { MapViewScene } from "./MapViewScene";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('MapViewComp')
|
||||
@ecs.register('MapView', false)
|
||||
export class MapViewComp extends CCComp {
|
||||
scene: MapViewScene = null!;
|
||||
|
||||
/** 是否正在转场 */
|
||||
|
||||
|
||||
/** 当前地图数据 */
|
||||
current_map: any;
|
||||
/** 转场碰撞点对象集合 */
|
||||
|
||||
|
||||
|
||||
reset(): void {
|
||||
|
||||
}
|
||||
|
||||
start() {
|
||||
this.scene = this.getComponent(MapViewScene);
|
||||
|
||||
this.addHero();
|
||||
}
|
||||
|
||||
/** 转场 */
|
||||
|
||||
|
||||
private mapLoaded() {
|
||||
|
||||
}
|
||||
|
||||
/** 添加玩家 */
|
||||
private addHero(pos?: Vec3) {
|
||||
if (pos == null) {
|
||||
this.scene.node.active = true
|
||||
smc.own = ecs.getEntity<Role>(Role);
|
||||
smc.own.load(this.aStarToVec3("0,0"), true);
|
||||
// smc.own.loadJoystick();
|
||||
|
||||
// 测试玩家
|
||||
var test = ecs.getEntity<Role>(Role);
|
||||
test.load(this.aStarToVec3("-300,0"), false);
|
||||
var test2 = ecs.getEntity<Role>(Role);
|
||||
test2.load(this.aStarToVec3("-300,300"), false);
|
||||
}
|
||||
else {
|
||||
this.scene.setPlayer(pos);
|
||||
}
|
||||
}
|
||||
|
||||
private aStarToVec3(str: string) {
|
||||
let array = str.split(",");
|
||||
let x = parseInt(array[0]);
|
||||
let y = parseInt(array[1]);
|
||||
// let p = MapRoadUtils.instance.getPixelByDerect(x, y);
|
||||
return v3(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
9
assets/script/game/map/view/MapViewComp.ts.meta
Normal file
9
assets/script/game/map/view/MapViewComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "b9f0df21-67f9-460a-8306-caf12042a78f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
94
assets/script/game/map/view/MapViewScene.ts
Normal file
94
assets/script/game/map/view/MapViewScene.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { Camera, CCBoolean, Component, EventTouch, Node, screen, Size, Texture2D, UITransform, Vec2, Vec3, view, _decorator } from "cc";
|
||||
import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import MapData from "./map/base/MapData";
|
||||
import { MapLoadModel } from "./map/base/MapLoadModel";
|
||||
import MapParams from "./map/base/MapParams";
|
||||
import Charactor from "./map/charactor/Charactor";
|
||||
import EntityLayer from "./map/layer/EntityLayer";
|
||||
import MapLayer from "./map/layer/MapLayer";
|
||||
import IRoadSeeker from "./map/road/IRoadSeeker";
|
||||
import RoadNode from "./map/road/RoadNode";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 地图场景逻辑
|
||||
* 1、地图摄像机跟随角色位置移动
|
||||
*/
|
||||
@ccclass('MapViewScene')
|
||||
export class MapViewScene extends Component {
|
||||
@property(Camera)
|
||||
public camera: Camera | null = null;
|
||||
|
||||
@property(Node)
|
||||
public layer: Node | null = null;
|
||||
|
||||
@property(MapLayer)
|
||||
public mapLayer: MapLayer | null = null;
|
||||
|
||||
@property(Node)
|
||||
public floorLayer: Node | null = null;
|
||||
|
||||
@property(EntityLayer)
|
||||
public entityLayer: EntityLayer | null = null;
|
||||
|
||||
@property(CCBoolean)
|
||||
public isFollowPlayer: boolean = true;
|
||||
|
||||
/** 2D转3D位置比例值 */
|
||||
ratio: Vec2 = new Vec2();
|
||||
|
||||
private _roadDic: { [key: string]: RoadNode } = {};
|
||||
private _roadSeeker!: IRoadSeeker;
|
||||
private _mapParams: MapParams | null = null;
|
||||
|
||||
private player: Charactor | null = null; // 主角玩家
|
||||
private targetPos: Vec3 = new Vec3(); // 摄像机位置
|
||||
private winSize!: Size; // 屏幕尺寸
|
||||
private screenCenter: Vec3 = new Vec3(); // 屏幕中心位置
|
||||
private boundary: Vec2 = new Vec2(); // 边界位置
|
||||
|
||||
setPlayer(value: Charactor | Vec3) {
|
||||
if (value instanceof Charactor) {
|
||||
this.enabled = true;
|
||||
this.player = value;
|
||||
}
|
||||
else {
|
||||
this.player!.pos = value;
|
||||
}
|
||||
}
|
||||
|
||||
onLoad() {
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
start() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private reset() {
|
||||
this.floorLayer!.removeAllChildren(); // 清除地面显示对象
|
||||
this.entityLayer!.clear(); // 清除游戏实体对象
|
||||
this.mapLayer!.clear(); // 清除地图瓦片显示对象
|
||||
this._roadDic = {};
|
||||
|
||||
|
||||
}
|
||||
|
||||
public init(mapData: MapData, bgTex: Texture2D, mapLoadModel: MapLoadModel = 1) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
update(dt: number) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
11
assets/script/game/map/view/MapViewScene.ts.meta
Normal file
11
assets/script/game/map/view/MapViewScene.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a31682ea-e44b-4122-b411-6761895ab6b0",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
12
assets/script/game/map/view/map.meta
Normal file
12
assets/script/game/map/view/map.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "316746b3-9791-4e17-a00c-f3a9be70e380",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
12
assets/script/game/map/view/map/base.meta
Normal file
12
assets/script/game/map/view/map/base.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "b0f6dc85-a76e-4bdf-a11c-d1b518f80db5",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
16
assets/script/game/map/view/map/base/MapData.ts
Normal file
16
assets/script/game/map/view/map/base/MapData.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { MapType } from "./MapType";
|
||||
|
||||
export default class MapData {
|
||||
public name: string = "";
|
||||
public bgName: string = "";
|
||||
public type: MapType = MapType.angle45;
|
||||
public mapWidth: number = 0;
|
||||
public mapHeight: number = 0;
|
||||
public nodeWidth: number = 0;
|
||||
public nodeHeight: number = 0;
|
||||
public roadDataArr: number[][] = [];
|
||||
//public row:number = 0;
|
||||
//public col:number = 0;
|
||||
|
||||
public mapItems: object[] = [];
|
||||
}
|
||||
11
assets/script/game/map/view/map/base/MapData.ts.meta
Normal file
11
assets/script/game/map/view/map/base/MapData.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a0091b9b-c39d-45b0-bcec-3f5a5c6258bf",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
14
assets/script/game/map/view/map/base/MapLoadModel.ts
Normal file
14
assets/script/game/map/view/map/base/MapLoadModel.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* 地图加载模式
|
||||
*/
|
||||
export enum MapLoadModel {
|
||||
/**
|
||||
* 单张地图加载
|
||||
*/
|
||||
single = 0,
|
||||
|
||||
/**
|
||||
* 分切片加载
|
||||
*/
|
||||
slices = 1,
|
||||
}
|
||||
11
assets/script/game/map/view/map/base/MapLoadModel.ts.meta
Normal file
11
assets/script/game/map/view/map/base/MapLoadModel.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "2f328b5a-8e30-4411-a6d1-997689a315a7",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
74
assets/script/game/map/view/map/base/MapParams.ts
Normal file
74
assets/script/game/map/view/map/base/MapParams.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
import { MapType } from "./MapType";
|
||||
import { MapLoadModel } from "./MapLoadModel";
|
||||
import { Texture2D } from "cc";
|
||||
|
||||
/**
|
||||
* 地图参数
|
||||
*/
|
||||
export default class MapParams {
|
||||
/**
|
||||
* 地图名称
|
||||
*/
|
||||
public name: string = "";
|
||||
|
||||
/**
|
||||
* 底图资源名称
|
||||
*/
|
||||
public bgName: string = "";
|
||||
|
||||
/**
|
||||
* 地图类型
|
||||
*/
|
||||
public mapType: MapType = MapType.angle45;
|
||||
|
||||
/**
|
||||
* 地图宽
|
||||
*/
|
||||
public mapWidth: number = 750;
|
||||
|
||||
/**
|
||||
* 地图高
|
||||
*/
|
||||
public mapHeight: number = 1600;
|
||||
|
||||
/**
|
||||
* 地图单元格宽
|
||||
*/
|
||||
public ceilWidth: number = 75;
|
||||
|
||||
/**
|
||||
* 地图单元格高
|
||||
*/
|
||||
public ceilHeight: number = 75;
|
||||
|
||||
/**
|
||||
* 地图视野宽
|
||||
*/
|
||||
public viewWidth: number = 750;
|
||||
|
||||
/**
|
||||
* 地图视野高
|
||||
*/
|
||||
public viewHeight: number = 1334;
|
||||
|
||||
/**
|
||||
* 地图切片宽
|
||||
*/
|
||||
public sliceWidth: number = 256;
|
||||
|
||||
/**
|
||||
* 地图切片高
|
||||
*/
|
||||
public sliceHeight: number = 256;
|
||||
|
||||
/**
|
||||
* 底图加载模式,是单张还是切片加载
|
||||
*/
|
||||
public mapLoadModel: MapLoadModel = MapLoadModel.single;
|
||||
|
||||
/**
|
||||
* 地图底图
|
||||
*/
|
||||
public bgTex: Texture2D | null = null;
|
||||
}
|
||||
11
assets/script/game/map/view/map/base/MapParams.ts.meta
Normal file
11
assets/script/game/map/view/map/base/MapParams.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "6b00edff-eb4a-4dcb-af47-ad707888c9b8",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
6
assets/script/game/map/view/map/base/MapType.ts
Normal file
6
assets/script/game/map/view/map/base/MapType.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
export enum MapType {
|
||||
angle45 = 0,
|
||||
angle90 = 1,
|
||||
honeycomb = 2,
|
||||
}
|
||||
11
assets/script/game/map/view/map/base/MapType.ts.meta
Normal file
11
assets/script/game/map/view/map/base/MapType.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "967a1a19-a1dd-4241-81d7-a92f041c19e9",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
12
assets/script/game/map/view/map/charactor.meta
Normal file
12
assets/script/game/map/view/map/charactor.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "f58752f0-7320-4a2f-b7a3-d4d59e42c1f6",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
146
assets/script/game/map/view/map/charactor/Charactor.ts
Normal file
146
assets/script/game/map/view/map/charactor/Charactor.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import { Component, game, Vec3, _decorator } from 'cc';
|
||||
import { MapViewScene } from '../../MapViewScene';
|
||||
import RoadNode from '../road/RoadNode';
|
||||
import { RoadType } from '../road/RoadType';
|
||||
import { ICharactorClip } from './ICharactorClip';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
export enum CharactorState {
|
||||
Idle = 0,
|
||||
Run = 1
|
||||
}
|
||||
|
||||
export enum CharactorDirection {
|
||||
none = -1,
|
||||
bottom = 0,
|
||||
left_bottom = 1,
|
||||
left = 2,
|
||||
left_up = 3,
|
||||
up = 4,
|
||||
right_up = 5,
|
||||
right = 6,
|
||||
right_bottom = 7
|
||||
}
|
||||
|
||||
/**
|
||||
* 场景角色
|
||||
*/
|
||||
@ccclass('Charactor')
|
||||
export default class Charactor extends Component {
|
||||
/** 优化后的路点移动 */
|
||||
static WalkRoadNode: string = "WalkRoadNode";
|
||||
/** 移动到新的一个格子路点 */
|
||||
static NextRoadNode: string = "NextRoadNode";
|
||||
|
||||
private _direction: CharactorDirection = CharactorDirection.bottom;
|
||||
public get direction(): CharactorDirection {
|
||||
return this._direction;
|
||||
}
|
||||
public set direction(value: CharactorDirection) {
|
||||
this._direction = value;
|
||||
// this.clip.setDirection(value);
|
||||
}
|
||||
|
||||
private _state: CharactorState = 0;
|
||||
public get state(): CharactorState {
|
||||
return this._state;
|
||||
}
|
||||
public set state(value: CharactorState) {
|
||||
this._state = value;
|
||||
// this.clip.setState(value);
|
||||
}
|
||||
|
||||
private _alpha: number = 1;
|
||||
public get alpha(): number {
|
||||
return this._alpha;
|
||||
}
|
||||
public set alpha(value: number) {
|
||||
this._alpha = value;
|
||||
// this.clip.setAlpha(value);
|
||||
}
|
||||
|
||||
private _zIndex: number = 0;
|
||||
/** 深度排序 */
|
||||
public get zIndex(): number {
|
||||
return this._zIndex;
|
||||
}
|
||||
|
||||
private _pos!: Vec3;
|
||||
/** 玩家地图上的位置 */
|
||||
public get pos(): Vec3 {
|
||||
return this._pos;
|
||||
}
|
||||
public set pos(value: Vec3) {
|
||||
this._pos = value;
|
||||
// this.clip.setPos(value);
|
||||
}
|
||||
|
||||
public sceneMap: MapViewScene = null!;
|
||||
public clip!: ICharactorClip;
|
||||
public moving: boolean = false;
|
||||
public joystic: boolean = false;
|
||||
public joystic_dir: Vec3 = new Vec3();
|
||||
public moveSpeed: number = 200;
|
||||
|
||||
/**
|
||||
* 玩家当前所站在的地图节点
|
||||
*/
|
||||
private _currentNode!: RoadNode;
|
||||
private _moveAngle: number = 0;
|
||||
private _roadNodeArr: RoadNode[] = [];
|
||||
private _nodeIndex: number = 0;
|
||||
|
||||
start() {
|
||||
this.direction = CharactorDirection.bottom;
|
||||
this.state = CharactorState.Idle;
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
|
||||
}
|
||||
|
||||
joystick(dir: Vec3) {
|
||||
if (this.moving) {
|
||||
this.moving = false;
|
||||
this._roadNodeArr.splice(0, this._roadNodeArr.length);
|
||||
}
|
||||
|
||||
if (dir.strictEquals(Vec3.ZERO)) {
|
||||
this.joystic = false;
|
||||
this.state = CharactorState.Idle;
|
||||
}
|
||||
else {
|
||||
this.joystic = true;
|
||||
this.state = CharactorState.Run;
|
||||
}
|
||||
this.joystic_dir.set(dir);
|
||||
}
|
||||
|
||||
public updateZIndex() {
|
||||
this._zIndex = this.sceneMap.mapLayer!.height - this._pos.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private walk() {
|
||||
if (this._nodeIndex < this._roadNodeArr.length - 1) {
|
||||
this._nodeIndex++;
|
||||
|
||||
// 移动一个路点事件
|
||||
this.node.emit(Charactor.WalkRoadNode, this._roadNodeArr[this._nodeIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
public move() {
|
||||
this.joystic = false;
|
||||
|
||||
this.moving = true;
|
||||
this.state = CharactorState.Run;
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.moving = false;
|
||||
this.state = CharactorState.Idle;
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/charactor/Charactor.ts.meta
Normal file
11
assets/script/game/map/view/map/charactor/Charactor.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "cbc1684f-2e32-4088-a784-3c147c9b6f31",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
10
assets/script/game/map/view/map/charactor/ICharactorClip.ts
Normal file
10
assets/script/game/map/view/map/charactor/ICharactorClip.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { EventTouch, Vec3 } from "cc";
|
||||
import { CharactorDirection, CharactorState } from "./Charactor";
|
||||
|
||||
export interface ICharactorClip {
|
||||
setDirection(value: CharactorDirection): void;
|
||||
setState(value: CharactorState): void;
|
||||
setAlpha(value: number): void;
|
||||
setPos(value: Vec3): void;
|
||||
checkTouch(event: EventTouch): boolean;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "977105e0-d01b-402a-b649-080e33733218",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
230
assets/script/game/map/view/map/charactor/MovieClip.ts
Normal file
230
assets/script/game/map/view/map/charactor/MovieClip.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
import { CCBoolean, CCFloat, CCInteger, Component, Rect, Size, Sprite, SpriteFrame, Texture2D, UITransform, Vec2, _decorator } from 'cc';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 动画播放器
|
||||
* @author 落日故人 QQ 583051842
|
||||
*
|
||||
*/
|
||||
@ccclass('MovieClip')
|
||||
export default class MovieClip extends Component {
|
||||
/** Sprite渲染器 */
|
||||
protected m_sprite: Sprite | null = null;;
|
||||
|
||||
/** 动画计时间隔 每隔0.1s更新一帧 */
|
||||
protected timer: number = 0.1;
|
||||
|
||||
/** 播放 时间 间隔 */
|
||||
@property({ type: CCFloat })
|
||||
public interval: number = 0.1;
|
||||
|
||||
/** 贴图文件名 */
|
||||
@property({ type: Texture2D })
|
||||
public texture: Texture2D | null = null;
|
||||
|
||||
/** 播放次数 */
|
||||
@property({ type: CCInteger })
|
||||
public playTimes: number = 0;
|
||||
|
||||
@property({ type: CCInteger })
|
||||
public row: number = 4;
|
||||
|
||||
/** 图片切割成几列 */
|
||||
@property({ type: CCInteger })
|
||||
public col: number = 4;
|
||||
|
||||
@property({ type: CCInteger })
|
||||
public rowIndex: number = 0;
|
||||
|
||||
@property(CCBoolean)
|
||||
public isAll: boolean = false;
|
||||
|
||||
@property(CCBoolean)
|
||||
public autoPlayOnLoad: boolean = true;
|
||||
|
||||
/** 播放完自动销毁 */
|
||||
@property(CCBoolean)
|
||||
public autoDestroy: boolean = false;
|
||||
|
||||
@property(CCFloat)
|
||||
public begin: number = 0;
|
||||
|
||||
@property(CCFloat)
|
||||
public end: number = 0;
|
||||
|
||||
/** 动画帧数 */
|
||||
public totalFrame: number = 8;
|
||||
|
||||
/** 当前帧数 */
|
||||
public currentFrame: number = 0;
|
||||
|
||||
/** 当前播放了第几次 */
|
||||
private currentTimes: number = 0;
|
||||
|
||||
/** 影片是否在跑动中 */
|
||||
public running: boolean = true;
|
||||
|
||||
//private _direction:number = 1;
|
||||
|
||||
private _playIndex: number = 0;
|
||||
private _pieceWidth: number = 0;
|
||||
private _pieceHeight: number = 0;
|
||||
private _bitmapArr: SpriteFrame[][] = [];
|
||||
|
||||
onLoad() {
|
||||
//this. m_clips = new SpriteFrame[this.row][this.col];
|
||||
//Texture2D tex = Resources.Load<Texture2D>("Image/Avatar/" + m_sprite_name);
|
||||
|
||||
//this.begin = 0;
|
||||
|
||||
if (this.end == 0) {
|
||||
this.end = this.col;
|
||||
}
|
||||
|
||||
this.rowIndex = this.clamp(this.rowIndex, 0, this.row - 1);
|
||||
|
||||
this._pieceWidth = this.texture!.width / this.col;
|
||||
this._pieceHeight = this.texture!.height / this.row;
|
||||
|
||||
this.m_sprite = this.getComponent(Sprite);
|
||||
|
||||
if (!this.m_sprite) {
|
||||
this.m_sprite = this.addComponent(Sprite);
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.row; i++) {
|
||||
this._bitmapArr[i] = [];
|
||||
|
||||
for (var j = 0; j < this.col; j++) {
|
||||
var spriteFrame: SpriteFrame = new SpriteFrame();
|
||||
spriteFrame.texture = this.texture!;
|
||||
spriteFrame.rect = new Rect(j * this._pieceWidth, i * this._pieceHeight, this._pieceWidth, this._pieceHeight);
|
||||
spriteFrame.rotated = false;
|
||||
spriteFrame.offset = new Vec2(0, 0);
|
||||
spriteFrame.originalSize = new Size(this._pieceWidth, this._pieceHeight);
|
||||
this._bitmapArr[i][j] = spriteFrame;
|
||||
}
|
||||
}
|
||||
|
||||
this.m_sprite!.spriteFrame = this._bitmapArr[this.rowIndex][0];
|
||||
this.m_sprite!.spriteFrame.width
|
||||
|
||||
var uiTransform = this.getComponent(UITransform);
|
||||
|
||||
if (uiTransform) {
|
||||
uiTransform.width = this._pieceWidth;
|
||||
uiTransform.height = this._pieceHeight;
|
||||
}
|
||||
|
||||
this.timer = 0;
|
||||
this.running = this.autoPlayOnLoad;
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
if (!this.running)
|
||||
return;
|
||||
|
||||
if (this.playTimes != 0 && this.currentTimes == this.playTimes) {
|
||||
this.running = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.timer -= dt;
|
||||
|
||||
if (this.timer <= 0) {
|
||||
this.timer = this.interval;
|
||||
this.currentFrame = this.currentFrame % this.col;
|
||||
|
||||
this.playAction();
|
||||
|
||||
this.currentFrame++;
|
||||
if (this.currentFrame == this.col) {
|
||||
|
||||
if (this.isAll) {
|
||||
this.rowIndex++;
|
||||
if (this.rowIndex == this.row) {
|
||||
this.currentTimes++;
|
||||
this.node.emit("completeTimes");
|
||||
|
||||
if (this.playTimes != 0 && this.currentTimes == this.playTimes) {
|
||||
this.node.emit("complete");
|
||||
|
||||
if (this.autoDestroy) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.rowIndex %= this.row;
|
||||
}
|
||||
else {
|
||||
this.currentTimes++;
|
||||
this.node.emit("completeTimes");
|
||||
|
||||
if (this.playTimes != 0 && this.currentTimes == this.playTimes) {
|
||||
this.node.emit("complete");
|
||||
|
||||
if (this.autoDestroy) {
|
||||
this.node.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private playAction() {
|
||||
this.rowIndex = this.clamp(this.rowIndex, 0, this.row - 1);
|
||||
this._playIndex = this._playIndex % (this.end - this.begin) + this.begin;
|
||||
this.m_sprite!.spriteFrame = this._bitmapArr[this.rowIndex][this._playIndex];
|
||||
//this.m_sprite.spriteFrame.setRect(this.rect);
|
||||
|
||||
this._playIndex++;
|
||||
}
|
||||
|
||||
/** 播放影片 */
|
||||
public play() {
|
||||
this.running = true;
|
||||
}
|
||||
|
||||
/** 停止播放影片 */
|
||||
public stop() {
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳帧播放
|
||||
* @param frame 帧
|
||||
*/
|
||||
public gotoAndPlay(frame: number) {
|
||||
this.running = true;
|
||||
this._playIndex = frame;
|
||||
this._playIndex = this.clamp(this._playIndex, 0, this.col - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳帧停止
|
||||
* @param frame 帧
|
||||
*/
|
||||
public gotoAndStop(frame: number) {
|
||||
this.running = false;
|
||||
|
||||
this._playIndex = frame;
|
||||
this._playIndex = this.clamp(this._playIndex, 0, this.col - 1);
|
||||
|
||||
this.m_sprite!.spriteFrame = this._bitmapArr[this.rowIndex][this._playIndex];
|
||||
}
|
||||
|
||||
public clamp(value: number, minLimit: number, maxLimit: number) {
|
||||
if (value < minLimit) {
|
||||
return minLimit;
|
||||
}
|
||||
|
||||
if (value > maxLimit) {
|
||||
return maxLimit;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/charactor/MovieClip.ts.meta
Normal file
11
assets/script/game/map/view/map/charactor/MovieClip.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "cb924b7b-003d-4995-a223-f41612b1d87c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
12
assets/script/game/map/view/map/layer.meta
Normal file
12
assets/script/game/map/view/map/layer.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "7c59804e-f894-4753-97cb-ffe0d43e52d6",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
39
assets/script/game/map/view/map/layer/EntityLayer.ts
Normal file
39
assets/script/game/map/view/map/layer/EntityLayer.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-08-04 15:22:33
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2023-05-12 18:04:45
|
||||
*/
|
||||
import { Component, Node, _decorator } from 'cc';
|
||||
import { Timer } from '../../../../../../../extensions/oops-plugin-framework/assets/core/common/timer/Timer';
|
||||
import Charactor from '../charactor/Charactor';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 物体层
|
||||
* 注:
|
||||
* 1、这里的深度排序,如果有性能问题,可考虑修改为非每帧排序
|
||||
* 2、如果全3D世界显示角色相关显示对象,则不需要2D深度排序,只引用2D地图上的位置信息
|
||||
*/
|
||||
@ccclass('EntityLayer')
|
||||
export default class EntityLayer extends Component {
|
||||
private timer: Timer = new Timer(0.2);
|
||||
|
||||
update(dt: number) {
|
||||
if (this.timer.update(dt))
|
||||
this.node.children.sort(this.zIndexSort);
|
||||
}
|
||||
|
||||
private zIndexSort(a: Node, b: Node) {
|
||||
let a_zIndex = a.getComponent(Charactor)!.zIndex;
|
||||
let b_zIndex = b.getComponent(Charactor)!.zIndex;
|
||||
return a_zIndex - b_zIndex;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
this.node.children.forEach(n => {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/layer/EntityLayer.ts.meta
Normal file
11
assets/script/game/map/view/map/layer/EntityLayer.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "6639aca8-e031-4a65-8094-d8e059cf26fe",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
134
assets/script/game/map/view/map/layer/MapLayer.ts
Normal file
134
assets/script/game/map/view/map/layer/MapLayer.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { Component, Layers, Node, Sprite, SpriteFrame, Texture2D, UITransform, Vec3, _decorator } from 'cc';
|
||||
import { oops } from '../../../../../../../extensions/oops-plugin-framework/assets/core/Oops';
|
||||
import { LayerUtil } from '../../../../../../../extensions/oops-plugin-framework/assets/core/utils/LayerUtil';
|
||||
import { smc } from '../../../../common/SingletonModuleComp';
|
||||
import { MapLoadModel } from '../base/MapLoadModel';
|
||||
import MapParams from '../base/MapParams';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 地图层
|
||||
* @author 落日故人 QQ 583051842
|
||||
*
|
||||
*/
|
||||
@ccclass('MapLayer')
|
||||
export default class MapLayer extends Component {
|
||||
/** 切割小图片集 */
|
||||
private _sliceImgDic: { [key: string]: Sprite | null } = {};
|
||||
private _mapParams: MapParams | null = null;
|
||||
|
||||
@property(Sprite)
|
||||
private bgImg: Sprite | null = null;
|
||||
|
||||
public init(mapParams: MapParams): void {
|
||||
this._mapParams = mapParams;
|
||||
|
||||
if (!this.bgImg) {
|
||||
var bgNode: Node = new Node();
|
||||
this.node.addChild(bgNode);
|
||||
bgNode.layer = Layers.Enum.UI_2D;
|
||||
|
||||
this.bgImg = bgNode.addComponent(Sprite);
|
||||
this.bgImg.sizeMode = Sprite.SizeMode.RAW;
|
||||
bgNode.getComponent(UITransform)!.anchorX = 0;
|
||||
bgNode.getComponent(UITransform)!.anchorY = 0;
|
||||
}
|
||||
|
||||
var spriteFrame: SpriteFrame = new SpriteFrame();
|
||||
spriteFrame.texture = this._mapParams.bgTex!;
|
||||
|
||||
this.bgImg.spriteFrame = spriteFrame;
|
||||
|
||||
//如果是马赛克小地图,则需要把小地图缩放成原始地图一样大小
|
||||
if (mapParams.mapLoadModel == MapLoadModel.slices) {
|
||||
this.bgImg.getComponent(UITransform)!.width = mapParams.mapWidth;
|
||||
this.bgImg.getComponent(UITransform)!.height = mapParams.mapHeight;
|
||||
}
|
||||
|
||||
this.getComponent(UITransform)!.width = this.width;
|
||||
this.getComponent(UITransform)!.height = this.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据视图区域加载小地图
|
||||
* @param px 滚动视图左上角的x坐标
|
||||
* @param py 滚动视图左上角的y坐标
|
||||
*
|
||||
*/
|
||||
public loadSliceImage(px: number, py: number): void {
|
||||
// var iy1: number = Math.floor(py / this._mapParams!.sliceHeight);
|
||||
// var iy2: number = Math.floor((py + this._mapParams!.viewHeight) / this._mapParams!.sliceHeight);
|
||||
|
||||
// var jx1: number = Math.floor(px / this._mapParams!.sliceWidth);
|
||||
// var jx2: number = Math.floor((px + this._mapParams!.viewWidth) / this._mapParams!.sliceWidth);
|
||||
|
||||
// var key: string;
|
||||
|
||||
// for (var i: number = iy1; i <= iy2; i++) {
|
||||
// for (var j: number = jx1; j <= jx2; j++) {
|
||||
// key = (i + 1) + "_" + (j + 1); // 图片的索引是从1开始的,所以要加1
|
||||
|
||||
// if (!this._sliceImgDic[key]) {
|
||||
// let bitmap: Sprite = this.getSliceSprite(key)
|
||||
// this._sliceImgDic[key] = bitmap;
|
||||
// this.node.addChild(bitmap.node);
|
||||
// bitmap.node.position = new Vec3(j * this._mapParams!.sliceWidth, i * this._mapParams!.sliceHeight, 0)
|
||||
|
||||
// // var path: string = `maps/${this._mapParams!.bgName}/${this._mapParams!.bgName}/slices/${key}/texture`;
|
||||
// // oops.res.load("remote", path, Texture2D, (error: Error | null, tex: Texture2D) => {
|
||||
// var path: string = smc.map.MapModel.getResContentSlices(this._mapParams!.bgName, key);
|
||||
// oops.res.load(path, Texture2D, (error: Error | null, tex: Texture2D) => {
|
||||
// if (error) {
|
||||
// console.error(error);
|
||||
// }
|
||||
// var spriteFrame: SpriteFrame = new SpriteFrame();
|
||||
// spriteFrame.texture = tex;
|
||||
// bitmap.spriteFrame = spriteFrame;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private getSliceSprite(name: string) {
|
||||
var node: Node = new Node(name);
|
||||
node.layer = LayerUtil.MAP.mask; // Layers.Enum.UI_2D;
|
||||
var sprite: Sprite = node.addComponent(Sprite);
|
||||
sprite.sizeMode = Sprite.SizeMode.RAW;
|
||||
node.getComponent(UITransform)!.anchorX = 0;
|
||||
node.getComponent(UITransform)!.anchorY = 0;
|
||||
return sprite;
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this.bgImg!.spriteFrame = null;
|
||||
|
||||
for (var key in this._sliceImgDic) {
|
||||
var sprite: Sprite | null = this._sliceImgDic[key];
|
||||
sprite && sprite.node.destroy();
|
||||
this._sliceImgDic[key] = null;
|
||||
delete this._sliceImgDic[key];
|
||||
}
|
||||
}
|
||||
|
||||
public get bgImage(): Sprite {
|
||||
return this.bgImg!;
|
||||
}
|
||||
|
||||
public get width(): number {
|
||||
if (this.bgImg) {
|
||||
return this.bgImg.getComponent(UITransform)!.width;
|
||||
}
|
||||
|
||||
return this._mapParams!.viewWidth;
|
||||
}
|
||||
|
||||
public get height(): number {
|
||||
if (this.bgImg) {
|
||||
return this.bgImg.getComponent(UITransform)!.height;
|
||||
}
|
||||
|
||||
return this._mapParams!.viewHeight;
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/layer/MapLayer.ts.meta
Normal file
11
assets/script/game/map/view/map/layer/MapLayer.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "753fb70a-638e-44d4-b736-f8696df44858",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
12
assets/script/game/map/view/map/road.meta
Normal file
12
assets/script/game/map/view/map/road.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "76609af6-ff56-411b-a2e5-b6a6027fb037",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
613
assets/script/game/map/view/map/road/AStarRoadSeeker.ts
Normal file
613
assets/script/game/map/view/map/road/AStarRoadSeeker.ts
Normal file
@@ -0,0 +1,613 @@
|
||||
import RoadNode from "./RoadNode";
|
||||
import IRoadSeeker from "./IRoadSeeker";
|
||||
import BinaryTreeNode from "./BinaryTreeNode";
|
||||
|
||||
/**
|
||||
* A*寻路算法
|
||||
* @author 落日故人 QQ 583051842
|
||||
*
|
||||
*/
|
||||
export default class AStarRoadSeeker implements IRoadSeeker {
|
||||
/**
|
||||
* 横向移动一个格子的代价
|
||||
*/
|
||||
private COST_STRAIGHT: number = 10;
|
||||
|
||||
/**
|
||||
* 斜向移动一个格子的代价
|
||||
*/
|
||||
private COST_DIAGONAL: number = 14;
|
||||
|
||||
/**
|
||||
* 最大搜寻步骤数,超过这个值时表示找不到目标
|
||||
*/
|
||||
private maxStep: number = 15000;
|
||||
|
||||
/**
|
||||
* 开启列表
|
||||
*/
|
||||
private _openlist: Array<RoadNode>;
|
||||
|
||||
/**
|
||||
*关闭列表
|
||||
*/
|
||||
private _closelist: Array<RoadNode>;
|
||||
|
||||
/**
|
||||
* 二叉堆存储结构
|
||||
*/
|
||||
private _binaryTreeNode: BinaryTreeNode = new BinaryTreeNode();
|
||||
|
||||
/**
|
||||
*开始节点
|
||||
*/
|
||||
private _startNode: RoadNode;
|
||||
|
||||
/**
|
||||
*当前检索节点
|
||||
*/
|
||||
private _currentNode: RoadNode;
|
||||
|
||||
/**
|
||||
*目标节点
|
||||
*/
|
||||
private _targetNode: RoadNode;
|
||||
|
||||
/**
|
||||
*地图路点数据
|
||||
*/
|
||||
private _roadNodes: { [key: number]: RoadNode };
|
||||
|
||||
/**
|
||||
*用于检索一个节点周围8个点的向量数组
|
||||
*/
|
||||
private _round: number[][] = [[0, -1], [1, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1]]
|
||||
|
||||
private handle: number = -1;
|
||||
|
||||
/**
|
||||
* 是否优化路径
|
||||
*/
|
||||
private optimize: boolean = true;
|
||||
|
||||
public constructor(roadNodes: { [key: string]: RoadNode }) {
|
||||
this._roadNodes = roadNodes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*寻路入口方法
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public seekPath(startNode: RoadNode, targetNode: RoadNode): Array<RoadNode> {
|
||||
this._startNode = startNode;
|
||||
this._currentNode = startNode;
|
||||
this._targetNode = targetNode;
|
||||
|
||||
if (!this._startNode || !this._targetNode)
|
||||
return [];
|
||||
|
||||
if (this._targetNode.value == 1) {
|
||||
console.log("目标不可达到:");
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
this._startNode.g = 0; //重置起始节点的g值
|
||||
this._startNode.resetTree(); //清除起始节点原有的二叉堆关联关系
|
||||
|
||||
this._binaryTreeNode.refleshTag(); //刷新二叉堆tag,用于后面判断是不是属于当前次的寻路
|
||||
//this._binaryTreeNode.addTreeNode(this._startNode); //把起始节点设置为二叉堆结构的根节点
|
||||
|
||||
var step: number = 0;
|
||||
|
||||
while (true) {
|
||||
if (step > this.maxStep) {
|
||||
// console.log("没找到目标计算步骤为:", step);
|
||||
return [];
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
this.searchRoundNodes(this._currentNode);
|
||||
|
||||
if (this._binaryTreeNode.isTreeNull()) //二叉堆树里已经没有任何可搜寻的点了,则寻路结束,每找到目标
|
||||
{
|
||||
// console.log("没找到目标计算步骤为:", step);
|
||||
return [];
|
||||
}
|
||||
|
||||
this._currentNode = this._binaryTreeNode.getMin_F_Node();
|
||||
|
||||
if (this._currentNode == this._targetNode) {
|
||||
// console.log("找到目标计算步骤为:", step);
|
||||
return this.getPath();
|
||||
}
|
||||
else {
|
||||
this._binaryTreeNode.setRoadNodeInCloseList(this._currentNode);//打入关闭列表标记
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*寻路入口方法 如果没有寻到目标,则返回离目标最近的路径
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public seekPath2(startNode: RoadNode, targetNode: RoadNode): Array<RoadNode> {
|
||||
this._startNode = startNode;
|
||||
this._currentNode = startNode;
|
||||
this._targetNode = targetNode;
|
||||
|
||||
if (!this._startNode || !this._targetNode)
|
||||
return [];
|
||||
|
||||
|
||||
var newMaxStep: number = this.maxStep;
|
||||
|
||||
if (!this.isPassNode(this._targetNode)) {
|
||||
//如果不能直达目标,最大寻路步骤 = 为两点间的预估距离的2倍
|
||||
newMaxStep = (Math.abs(this._targetNode.cx - this._startNode.cx) + Math.abs(this._targetNode.cy - this._startNode.cy)) * 2;
|
||||
if (newMaxStep > this.maxStep) {
|
||||
newMaxStep = this.maxStep;
|
||||
}
|
||||
}
|
||||
|
||||
this._startNode.g = 0; //重置起始节点的g值
|
||||
this._startNode.resetTree(); //清除起始节点原有的二叉堆关联关系
|
||||
|
||||
this._binaryTreeNode.refleshTag(); //刷新二叉堆tag,用于后面判断是不是属于当前次的寻路
|
||||
//this._binaryTreeNode.addTreeNode(this._startNode); //把起始节点设置为二叉堆结构的根节点
|
||||
|
||||
var step: number = 0;
|
||||
|
||||
var closestNode: RoadNode = null; //距离目标最近的路点
|
||||
|
||||
while (true) {
|
||||
if (step > newMaxStep) {
|
||||
// console.log("没找到目标计算步骤为:", step);
|
||||
return this.seekPath(startNode, closestNode);
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
this.searchRoundNodes(this._currentNode);
|
||||
|
||||
if (this._binaryTreeNode.isTreeNull()) //二叉堆树里已经没有任何可搜寻的点了,则寻路结束,没找到目标
|
||||
{
|
||||
// console.log("没找到目标计算步骤为:", step);
|
||||
return this.seekPath(startNode, closestNode);
|
||||
}
|
||||
|
||||
this._currentNode = this._binaryTreeNode.getMin_F_Node();
|
||||
|
||||
|
||||
if (closestNode == null) {
|
||||
closestNode = this._currentNode;
|
||||
}
|
||||
else {
|
||||
if (this._currentNode.h < closestNode.h) {
|
||||
closestNode = this._currentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._currentNode == this._targetNode) {
|
||||
// console.log("找到目标计算步骤为:", step);
|
||||
return this.getPath();
|
||||
}
|
||||
else {
|
||||
this._binaryTreeNode.setRoadNodeInCloseList(this._currentNode);//打入关闭列表标记
|
||||
}
|
||||
}
|
||||
|
||||
return this.seekPath(startNode, closestNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对路节点进行排序
|
||||
* @param node1
|
||||
* @param node2
|
||||
*/
|
||||
private sortNode(node1: RoadNode, node2: RoadNode) {
|
||||
if (node1.f < node2.f) {
|
||||
return -1;
|
||||
}
|
||||
else if (node1.f > node2.f) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得最终寻路到的所有路点
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private getPath(): Array<RoadNode> {
|
||||
var nodeArr: Array<RoadNode> = [];
|
||||
|
||||
var node: RoadNode = this._targetNode;
|
||||
|
||||
while (node != this._startNode) {
|
||||
nodeArr.unshift(node);
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
nodeArr.unshift(this._startNode);
|
||||
|
||||
if (!this.optimize) {
|
||||
return nodeArr;
|
||||
}
|
||||
|
||||
//第一阶段优化: 对横,竖,正斜进行优化
|
||||
//把多个节点连在一起的,横向或者斜向的一连串点,除两边的点保留
|
||||
for (var i: number = 1; i < nodeArr.length - 1; i++) {
|
||||
var preNode: RoadNode = nodeArr[i - 1] as RoadNode;
|
||||
var midNode: RoadNode = nodeArr[i] as RoadNode;
|
||||
var nextNode: RoadNode = nodeArr[i + 1] as RoadNode;
|
||||
|
||||
var bool1: Boolean = midNode.cx == preNode.cx && midNode.cx == nextNode.cx;
|
||||
var bool2: Boolean = midNode.cy == preNode.cy && midNode.cy == nextNode.cy;
|
||||
var bool3: Boolean = ((midNode.cx - preNode.cx) / (midNode.cy - preNode.cy)) * ((nextNode.cx - midNode.cx) / (nextNode.cy - midNode.cy)) == 1
|
||||
|
||||
if (bool1 || bool2 || bool3) {
|
||||
nodeArr.splice(i, 1)
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
//return nodeArr;
|
||||
|
||||
//第二阶段优化:对不在横,竖,正斜的格子进行优化
|
||||
for (var i: number = 0; i < nodeArr.length - 2; i++) {
|
||||
var startNode: RoadNode = nodeArr[i] as RoadNode;
|
||||
var optimizeNode: RoadNode = null;
|
||||
|
||||
//优先从尾部对比,如果能直达就把中间多余的路点删掉
|
||||
for (var j: number = nodeArr.length - 1; j > i + 1; j--) {
|
||||
var targetNode: RoadNode = nodeArr[j] as RoadNode;
|
||||
|
||||
//在第一阶段优已经优化过横,竖,正斜了,所以再出现是肯定不能优化的,可以忽略
|
||||
if (startNode.cx == targetNode.cx || startNode.cy == targetNode.cy || Math.abs(targetNode.cx - startNode.cx) == Math.abs(targetNode.cy - startNode.cy)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isArriveBetweenTwoNodes(startNode, targetNode)) {
|
||||
optimizeNode = targetNode;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (optimizeNode) {
|
||||
var optimizeLen: number = j - i - 1;
|
||||
nodeArr.splice(i + 1, optimizeLen);
|
||||
}
|
||||
}
|
||||
return nodeArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 两点之间是否可到达
|
||||
*/
|
||||
private isArriveBetweenTwoNodes(startNode: RoadNode, targetNode: RoadNode): boolean {
|
||||
if (startNode == targetNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var disX: number = Math.abs(targetNode.cx - startNode.cx);
|
||||
var disY: number = Math.abs(targetNode.cy - startNode.cy);
|
||||
|
||||
var dirX = 0;
|
||||
|
||||
if (targetNode.cx > startNode.cx) {
|
||||
dirX = 1;
|
||||
}
|
||||
else if (targetNode.cx < startNode.cx) {
|
||||
dirX = -1;
|
||||
}
|
||||
|
||||
var dirY = 0;
|
||||
|
||||
if (targetNode.cy > startNode.cy) {
|
||||
dirY = 1;
|
||||
}
|
||||
else if (targetNode.cy < startNode.cy) {
|
||||
dirY = -1;
|
||||
}
|
||||
|
||||
var rx: number = 0;
|
||||
var ry: number = 0;
|
||||
var intNum: number = 0;
|
||||
var decimal: number = 0;
|
||||
|
||||
if (disX > disY) {
|
||||
var rate: number = disY / disX;
|
||||
|
||||
for (var i = 0; i < disX; i++) {
|
||||
ry = startNode.cy + i * dirY * rate;
|
||||
intNum = Math.floor(ry);
|
||||
decimal = ry % 1;
|
||||
|
||||
var cx1: number = startNode.cx + i * dirX;
|
||||
var cy1: number = decimal <= 0.5 ? intNum : intNum + 1;
|
||||
|
||||
|
||||
ry = startNode.cy + (i + 1) * dirY * rate;
|
||||
intNum = Math.floor(ry);
|
||||
decimal = ry % 1;
|
||||
|
||||
var cx2: number = startNode.cx + (i + 1) * dirX;
|
||||
var cy2: number = decimal <= 0.5 ? intNum : intNum + 1;
|
||||
|
||||
var node1: RoadNode = this._roadNodes[cx1 + "_" + cy1] as RoadNode;
|
||||
var node2: RoadNode = this._roadNodes[cx2 + "_" + cy2] as RoadNode;
|
||||
|
||||
//cc.log(i + " :: " + node1.cy," yy ",startNode.cy + i * rate,ry % 1);
|
||||
|
||||
if (!this.isCrossAtAdjacentNodes(node1, node2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
var rate: number = disX / disY;
|
||||
|
||||
for (var i = 0; i < disY; i++) {
|
||||
rx = i * dirX * rate;
|
||||
intNum = dirX > 0 ? Math.floor(startNode.cx + rx) : Math.ceil(startNode.cx + rx);
|
||||
decimal = Math.abs(rx % 1);
|
||||
|
||||
var cx1: number = decimal <= 0.5 ? intNum : intNum + 1 * dirX;
|
||||
var cy1: number = startNode.cy + i * dirY;
|
||||
|
||||
|
||||
rx = (i + 1) * dirX * rate;
|
||||
intNum = dirX > 0 ? Math.floor(startNode.cx + rx) : Math.ceil(startNode.cx + rx);
|
||||
decimal = Math.abs(rx % 1);
|
||||
|
||||
var cx2: number = decimal <= 0.5 ? intNum : intNum + 1 * dirX;
|
||||
var cy2: number = startNode.cy + (i + 1) * dirY;
|
||||
|
||||
var node1: RoadNode = this._roadNodes[cx1 + "_" + cy1] as RoadNode;
|
||||
var node2: RoadNode = this._roadNodes[cx2 + "_" + cy2] as RoadNode;
|
||||
|
||||
if (!this.isCrossAtAdjacentNodes(node1, node2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个相邻的点是否可通过
|
||||
* @param node1
|
||||
* @param node2
|
||||
*/
|
||||
private isCrossAtAdjacentNodes(node1: RoadNode, node2: RoadNode): boolean {
|
||||
if (node1 == node2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//两个点只要有一个点不能通过就不能通过
|
||||
if (!this.isPassNode(node1) || !this.isPassNode(node2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var dirX = node2.cx - node1.cx;
|
||||
var dirY = node2.cy - node1.cy
|
||||
|
||||
//如果不是相邻的两个点 则不能通过
|
||||
if (Math.abs(dirX) > 1 || Math.abs(dirY) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//如果相邻的点是在同一行,或者同一列,则判定为可通过
|
||||
if ((node1.cx == node2.cx) || (node1.cy == node2.cy)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//只剩对角情况了
|
||||
if (
|
||||
this.isPassNode(this._roadNodes[node1.cx + "_" + (node1.cy + dirY)]) &&
|
||||
this.isPassNode(this._roadNodes[(node1.cx + dirX) + "_" + node1.cy])
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是可通过的点
|
||||
* @param node
|
||||
*/
|
||||
private isPassNode(node: RoadNode): boolean {
|
||||
if (!node || node.value == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*测试寻路步骤
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public testSeekPathStep(startNode: RoadNode, targetNode: RoadNode, callback: Function, target: any, time: number = 100): void {
|
||||
this._startNode = startNode;
|
||||
this._currentNode = startNode;
|
||||
this._targetNode = targetNode;
|
||||
|
||||
if (this._targetNode.value == 1)
|
||||
return;
|
||||
|
||||
this._startNode.g = 0; //重置起始节点的g值
|
||||
this._startNode.resetTree(); //清除起始节点原有的二叉堆关联关系
|
||||
|
||||
this._binaryTreeNode.refleshTag(); //刷新二叉堆tag,用于后面判断是不是属于当前次的寻路
|
||||
//this._binaryTreeNode.addTreeNode(this._startNode); //把起始节点设置为二叉堆结构的根节点
|
||||
|
||||
this._closelist = [];
|
||||
|
||||
var step: number = 0;
|
||||
|
||||
clearInterval(this.handle);
|
||||
this.handle = setInterval(() => {
|
||||
if (step > this.maxStep) {
|
||||
// console.log("没找到目标计算步骤为:", step);
|
||||
clearInterval(this.handle);
|
||||
return;
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
this.searchRoundNodes(this._currentNode);
|
||||
|
||||
if (this._binaryTreeNode.isTreeNull()) //二叉堆树里已经没有任何可搜寻的点了,则寻路结束,每找到目标
|
||||
{
|
||||
// console.log("没找到目标计算步骤为:", step);
|
||||
clearInterval(this.handle);
|
||||
return;
|
||||
}
|
||||
|
||||
this._currentNode = this._binaryTreeNode.getMin_F_Node();
|
||||
|
||||
if (this._currentNode == this._targetNode) {
|
||||
// console.log("找到目标计算步骤为:", step);
|
||||
clearInterval(this.handle);
|
||||
|
||||
this._openlist = this._binaryTreeNode.getOpenList();
|
||||
callback.apply(target, [this._startNode, this._targetNode, this._currentNode, this._openlist, this._closelist, this.getPath()]);
|
||||
}
|
||||
else {
|
||||
this._binaryTreeNode.setRoadNodeInCloseList(this._currentNode);//打入关闭列表标记
|
||||
this._openlist = this._binaryTreeNode.getOpenList();
|
||||
this._closelist.push(this._currentNode);
|
||||
callback.apply(target, [this._startNode, this._targetNode, this._currentNode, this._openlist, this._closelist, null]);
|
||||
}
|
||||
|
||||
}, time);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*查找一个节点周围可通过的点
|
||||
* @param node
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private searchRoundNodes(node: RoadNode): void {
|
||||
for (var i: number = 0; i < this._round.length; i++) {
|
||||
var cx: number = node.cx + this._round[i][0];
|
||||
var cy: number = node.cy + this._round[i][1];
|
||||
var node2: RoadNode = this._roadNodes[cx + "_" + cy] as RoadNode
|
||||
|
||||
if (node2 != null && node2 != this._startNode && node2.value != 1 && !this.isInCloseList(node2) && !this.inInCorner(node2)) {
|
||||
this.setNodeF(node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*设置节点的F值
|
||||
* @param node
|
||||
*
|
||||
*/
|
||||
public setNodeF(node: RoadNode): void {
|
||||
var g: number;
|
||||
|
||||
if (node.cx == this._currentNode.cx || node.cy == this._currentNode.cy) {
|
||||
g = this._currentNode.g + this.COST_STRAIGHT;
|
||||
}
|
||||
else {
|
||||
g = this._currentNode.g + this.COST_DIAGONAL;
|
||||
}
|
||||
|
||||
if (this.isInOpenList(node)) {
|
||||
if (g < node.g) {
|
||||
node.g = g;
|
||||
|
||||
node.parent = this._currentNode;
|
||||
node.h = (Math.abs(this._targetNode.cx - node.cx) + Math.abs(this._targetNode.cy - node.cy)) * this.COST_STRAIGHT;
|
||||
node.f = node.g + node.h;
|
||||
|
||||
//节点的g值已经改变,把节点先从二堆叉树结构中删除,再重新添加进二堆叉树
|
||||
this._binaryTreeNode.removeTreeNode(node);
|
||||
this._binaryTreeNode.addTreeNode(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
node.g = g;
|
||||
|
||||
this._binaryTreeNode.setRoadNodeInOpenList(node);//给节点打入开放列表的标志
|
||||
node.resetTree();
|
||||
|
||||
node.parent = this._currentNode;
|
||||
node.h = (Math.abs(this._targetNode.cx - node.cx) + Math.abs(this._targetNode.cy - node.cy)) * this.COST_STRAIGHT;
|
||||
node.f = node.g + node.h;
|
||||
|
||||
this._binaryTreeNode.addTreeNode(node);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*节点是否在开启列表
|
||||
* @param node
|
||||
* @return
|
||||
*/
|
||||
private isInOpenList(node: RoadNode): Boolean {
|
||||
return this._binaryTreeNode.isInOpenList(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点是否在关闭列表
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
private isInCloseList(node: RoadNode): Boolean {
|
||||
return this._binaryTreeNode.isInCloseList(node);
|
||||
}
|
||||
|
||||
/**
|
||||
*节点是否在拐角处
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private inInCorner(node: RoadNode): Boolean {
|
||||
if (node.cx == this._currentNode.cx || node.cy == this._currentNode.cy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var node1: RoadNode = this._roadNodes[this._currentNode.cx + "_" + node.cy] as RoadNode;
|
||||
var node2: RoadNode = this._roadNodes[node.cx + "_" + this._currentNode.cy] as RoadNode;
|
||||
|
||||
if (this.isPassNode(node1) && this.isPassNode(node2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._roadNodes = null;
|
||||
this._round = null;
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/road/AStarRoadSeeker.ts.meta
Normal file
11
assets/script/game/map/view/map/road/AStarRoadSeeker.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a3a19dc4-7645-485a-80e0-b49fdb062b00",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
836
assets/script/game/map/view/map/road/AstarHoneycombRoadSeeker.ts
Normal file
836
assets/script/game/map/view/map/road/AstarHoneycombRoadSeeker.ts
Normal file
@@ -0,0 +1,836 @@
|
||||
import BinaryTreeNode from "./BinaryTreeNode";
|
||||
import IRoadSeeker from "./IRoadSeeker";
|
||||
import RoadNode from "./RoadNode";
|
||||
|
||||
/**
|
||||
* 六边形 A*寻路算法
|
||||
* @author 落日故人 QQ 583051842
|
||||
*
|
||||
*/
|
||||
export default class AstarHoneycombRoadSeeker implements IRoadSeeker {
|
||||
/**
|
||||
* 横向移动一个格子的代价
|
||||
*/
|
||||
private COST_STRAIGHT: number = 10;
|
||||
|
||||
/**
|
||||
* 斜向移动一个格子的代价
|
||||
*/
|
||||
private COST_DIAGONAL: number = 10;
|
||||
|
||||
/**
|
||||
* 最大搜寻步骤数,超过这个值时表示找不到目标
|
||||
*/
|
||||
private maxStep: number = 15000;
|
||||
|
||||
/**
|
||||
* 开启列表
|
||||
*/
|
||||
private _openlist: Array<RoadNode>;
|
||||
|
||||
/**
|
||||
*关闭列表
|
||||
*/
|
||||
private _closelist: Array<RoadNode>;
|
||||
|
||||
/**
|
||||
* 二叉堆存储结构
|
||||
*/
|
||||
private _binaryTreeNode: BinaryTreeNode = new BinaryTreeNode();
|
||||
|
||||
/**
|
||||
*开始节点
|
||||
*/
|
||||
private _startNode: RoadNode;
|
||||
|
||||
/**
|
||||
*当前检索节点
|
||||
*/
|
||||
private _currentNode: RoadNode;
|
||||
|
||||
/**
|
||||
*目标节点
|
||||
*/
|
||||
private _targetNode: RoadNode;
|
||||
|
||||
/**
|
||||
*地图路点数据
|
||||
*/
|
||||
private _roadNodes: { [key: number]: RoadNode };
|
||||
|
||||
/**
|
||||
*用于检索一个节点周围6个点的向量数组 格子列数为偶数时使用
|
||||
*/
|
||||
private _round1: number[][] = [[0, -1], [1, -1], [1, 0], [0, 1], [-1, 0], [-1, -1]];
|
||||
/**
|
||||
*用于检索一个节点周围6个点的向量数组 格子列数为奇数时使用
|
||||
*/
|
||||
private _round2: number[][] = [[0, -1], [1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0]];
|
||||
|
||||
private handle: number = -1;
|
||||
|
||||
/**
|
||||
* 是否优化路径
|
||||
*/
|
||||
private optimize: boolean = true;
|
||||
|
||||
public constructor(roadNodes: { [key: string]: RoadNode }) {
|
||||
this._roadNodes = roadNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
*寻路入口方法
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public seekPath(startNode: RoadNode, targetNode: RoadNode): Array<RoadNode> {
|
||||
this._startNode = startNode;
|
||||
this._currentNode = startNode;
|
||||
this._targetNode = targetNode;
|
||||
|
||||
if (!this._startNode || !this._targetNode)
|
||||
return [];
|
||||
|
||||
if (this._targetNode.value == 1) {
|
||||
console.log("目标不可达到:");
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
this._startNode.g = 0; //重置起始节点的g值
|
||||
this._startNode.resetTree(); //清除起始节点原有的二叉堆关联关系
|
||||
|
||||
this._binaryTreeNode.refleshTag(); //刷新二叉堆tag,用于后面判断是不是属于当前次的寻路
|
||||
//this._binaryTreeNode.addTreeNode(this._startNode); //把起始节点设置为二叉堆结构的根节点
|
||||
|
||||
var step: number = 0;
|
||||
|
||||
while (true) {
|
||||
if (step > this.maxStep) {
|
||||
console.log("没找到目标计算步骤为:", step);
|
||||
return [];
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
this.searchRoundNodes(this._currentNode);
|
||||
|
||||
if (this._binaryTreeNode.isTreeNull()) //二叉堆树里已经没有任何可搜寻的点了,则寻路结束,每找到目标
|
||||
{
|
||||
console.log("没找到目标计算步骤为:", step);
|
||||
return [];
|
||||
}
|
||||
|
||||
this._currentNode = this._binaryTreeNode.getMin_F_Node();
|
||||
|
||||
if (this._currentNode == this._targetNode) {
|
||||
console.log("找到目标计算步骤为:", step);
|
||||
return this.getPath();
|
||||
}
|
||||
else {
|
||||
this._binaryTreeNode.setRoadNodeInCloseList(this._currentNode);//打入关闭列表标记
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*寻路入口方法 如果没有寻到目标,则返回离目标最近的路径
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public seekPath2(startNode: RoadNode, targetNode: RoadNode): Array<RoadNode> {
|
||||
this._startNode = startNode;
|
||||
this._currentNode = startNode;
|
||||
this._targetNode = targetNode;
|
||||
|
||||
if (!this._startNode || !this._targetNode)
|
||||
return [];
|
||||
|
||||
var newMaxStep: number = this.maxStep;
|
||||
|
||||
if (!this.isPassNode(this._targetNode)) {
|
||||
//如果不能直达目标,最大寻路步骤 = 为两点间的预估距离的2倍
|
||||
newMaxStep = (Math.abs(this._targetNode.cx - this._startNode.cx) + Math.abs(this._targetNode.cy - this._startNode.cy)) * 2;
|
||||
if (newMaxStep > this.maxStep) {
|
||||
newMaxStep = this.maxStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this._startNode.g = 0; //重置起始节点的g值
|
||||
this._startNode.resetTree(); //清除起始节点原有的二叉堆关联关系
|
||||
|
||||
this._binaryTreeNode.refleshTag(); //刷新二叉堆tag,用于后面判断是不是属于当前次的寻路
|
||||
//this._binaryTreeNode.addTreeNode(this._startNode); //把起始节点设置为二叉堆结构的根节点
|
||||
|
||||
var step: number = 0;
|
||||
|
||||
var closestNode: RoadNode = null; //距离目标最近的路点
|
||||
|
||||
while (true) {
|
||||
if (step > newMaxStep) {
|
||||
console.log("没找到目标计算步骤为:", step);
|
||||
return this.seekPath(startNode, closestNode);
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
this.searchRoundNodes(this._currentNode);
|
||||
|
||||
if (this._binaryTreeNode.isTreeNull()) { //二叉堆树里已经没有任何可搜寻的点了,则寻路结束,没找到目标
|
||||
console.log("没找到目标计算步骤为:", step);
|
||||
return this.seekPath(startNode, closestNode);
|
||||
}
|
||||
|
||||
this._currentNode = this._binaryTreeNode.getMin_F_Node();
|
||||
|
||||
if (closestNode == null) {
|
||||
closestNode = this._currentNode;
|
||||
}
|
||||
else {
|
||||
if (this._currentNode.h < closestNode.h) {
|
||||
closestNode = this._currentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._currentNode == this._targetNode) {
|
||||
console.log("找到目标计算步骤为:", step);
|
||||
return this.getPath();
|
||||
}
|
||||
else {
|
||||
this._binaryTreeNode.setRoadNodeInCloseList(this._currentNode);//打入关闭列表标记
|
||||
}
|
||||
}
|
||||
|
||||
return this.seekPath(startNode, closestNode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对路节点进行排序
|
||||
* @param node1
|
||||
* @param node2
|
||||
*/
|
||||
private sortNode(node1: RoadNode, node2: RoadNode) {
|
||||
if (node1.f < node2.f) {
|
||||
return -1;
|
||||
}
|
||||
else if (node1.f > node2.f) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*private getPath():Array<RoadNode>
|
||||
{
|
||||
var nodeArr:Array<RoadNode> = [];
|
||||
|
||||
var node:RoadNode = this._targetNode;
|
||||
|
||||
while(node != this._startNode)
|
||||
{
|
||||
nodeArr.unshift(node);
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
nodeArr.unshift(this._startNode);
|
||||
|
||||
if(!this.optimize)
|
||||
{
|
||||
return nodeArr;
|
||||
}
|
||||
|
||||
//把多个节点连在一起的,横向或者斜向的一连串点,除两边的点保留
|
||||
|
||||
var preNode:RoadNode;
|
||||
var midNode:RoadNode;
|
||||
var nextNode:RoadNode;
|
||||
|
||||
for(var i:number = 1 ; i < nodeArr.length - 1 ; i++)
|
||||
{
|
||||
preNode = nodeArr[i - 1] as RoadNode;
|
||||
midNode = nodeArr[i] as RoadNode;
|
||||
nextNode = nodeArr[i + 1] as RoadNode;
|
||||
|
||||
var bool:Boolean = false;
|
||||
|
||||
var otherNode:RoadNode = null;
|
||||
|
||||
if(Math.abs(nextNode.cx - preNode.cx) == 2 && preNode.cy == nextNode.cy)
|
||||
{
|
||||
if(midNode.cx % 2 == 0)
|
||||
{
|
||||
if(midNode.cy == preNode.cy)
|
||||
{
|
||||
otherNode = this._roadNodes[midNode.cx + "_" + (midNode.cy + 1)] as RoadNode
|
||||
}else
|
||||
{
|
||||
otherNode = this._roadNodes[midNode.cx + "_" + (midNode.cy - 1)] as RoadNode
|
||||
}
|
||||
|
||||
}else
|
||||
{
|
||||
if(midNode.cy == preNode.cy)
|
||||
{
|
||||
otherNode = this._roadNodes[midNode.cx + "_" + (midNode.cy - 1)] as RoadNode
|
||||
}else
|
||||
{
|
||||
otherNode = this._roadNodes[midNode.cx + "_" + (midNode.cy + 1)] as RoadNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(otherNode)
|
||||
bool = otherNode.value != 1 ? true : false;
|
||||
|
||||
if(bool)
|
||||
{
|
||||
nodeArr.splice(i,1)
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 1 ; i < nodeArr.length - 1 ; i++)
|
||||
{
|
||||
preNode = nodeArr[i - 1] as RoadNode;
|
||||
midNode = nodeArr[i] as RoadNode;
|
||||
nextNode = nodeArr[i + 1] as RoadNode;
|
||||
|
||||
var bool1:Boolean = midNode.cx == preNode.cx && midNode.cx == nextNode.cx;
|
||||
|
||||
var bool2:Boolean = (midNode.cy == preNode.cy && midNode.cy == nextNode.cy) && ((preNode.cx % 2 == midNode.cx % 2 && midNode.cx % 2 == nextNode.cx % 2) );
|
||||
|
||||
var bool3:Boolean = preNode.cy - Math.floor(preNode.cx / 2) == midNode.cy - Math.floor(midNode.cx / 2) && midNode.cy - Math.floor(midNode.cx / 2) == nextNode.cy - Math.floor(nextNode.cx / 2);
|
||||
|
||||
var bool4:Boolean = preNode.cy + Math.ceil(preNode.cx / 2) == midNode.cy + Math.ceil(midNode.cx / 2) && midNode.cy + Math.ceil(midNode.cx / 2) == nextNode.cy + Math.ceil(nextNode.cx / 2);
|
||||
|
||||
if(bool1 || bool2 || bool3 || bool4)
|
||||
{
|
||||
nodeArr.splice(i,1)
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return nodeArr
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
*获得最终寻路到的所有路点
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private getPath(): Array<RoadNode> {
|
||||
var nodeArr: Array<RoadNode> = [];
|
||||
|
||||
var node: RoadNode = this._targetNode;
|
||||
|
||||
while (node != this._startNode) {
|
||||
nodeArr.unshift(node);
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
nodeArr.unshift(this._startNode);
|
||||
|
||||
if (!this.optimize) {
|
||||
return nodeArr;
|
||||
}
|
||||
|
||||
//把多个节点连在一起的,横向或者斜向的一连串点,除两边的点保留
|
||||
|
||||
var preNode: RoadNode;
|
||||
var midNode: RoadNode;
|
||||
var nextNode: RoadNode;
|
||||
|
||||
var preHpos: HoneyPoint;
|
||||
var midHpos: HoneyPoint;
|
||||
var nextHpos: HoneyPoint;
|
||||
|
||||
//var hround:number[][] = [[-1,-1],[-1,0],[0,1],[1,1],[1,0],[0,-1]];
|
||||
//var hround2:number[][] = [[-2,-1],[-1,1],[1,2],[2,1],[1,-1],[-1,-2]];
|
||||
|
||||
//第一阶段优化: 对横,竖,正斜进行优化
|
||||
for (i = 1; i < nodeArr.length - 1; i++) {
|
||||
preNode = nodeArr[i - 1] as RoadNode;
|
||||
midNode = nodeArr[i] as RoadNode;
|
||||
nextNode = nodeArr[i + 1] as RoadNode;
|
||||
|
||||
preHpos = this.getHoneyPoint(preNode);
|
||||
midHpos = this.getHoneyPoint(midNode);
|
||||
nextHpos = this.getHoneyPoint(nextNode);
|
||||
|
||||
var bool1: Boolean = midNode.cx == preNode.cx && midNode.cx == nextNode.cx;
|
||||
|
||||
var bool2: Boolean = (midNode.cy == preNode.cy && midNode.cy == nextNode.cy) && ((preNode.cx % 2 == midNode.cx % 2 && midNode.cx % 2 == nextNode.cx % 2));
|
||||
|
||||
var bool3: Boolean = preHpos.hx == midHpos.hx && midHpos.hx == nextHpos.hx;
|
||||
|
||||
var bool4: Boolean = preHpos.hy == midHpos.hy && midHpos.hy == nextHpos.hy;
|
||||
|
||||
if (bool1 || bool2 || bool3 || bool4) {
|
||||
nodeArr.splice(i, 1)
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
//第二阶段优化:对不在横,竖,正斜的格子进行优化
|
||||
for (var i: number = 0; i < nodeArr.length - 2; i++) {
|
||||
var startNode: RoadNode = nodeArr[i] as RoadNode;
|
||||
var optimizeNode: RoadNode = null;
|
||||
|
||||
//优先从尾部对比,如果能直达就把中间多余的路点删掉
|
||||
for (var j: number = nodeArr.length - 1; j > i + 1; j--) {
|
||||
var targetNode: RoadNode = nodeArr[j] as RoadNode;
|
||||
|
||||
if (this.isArriveBetweenTwoNodes(this.getHoneyPoint(startNode), this.getHoneyPoint(targetNode))) {
|
||||
optimizeNode = targetNode;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (optimizeNode) {
|
||||
var optimizeLen: number = j - i - 1;
|
||||
nodeArr.splice(i + 1, optimizeLen);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nodeArr
|
||||
}
|
||||
|
||||
/**
|
||||
* 两点之间是否可到达
|
||||
*/
|
||||
private isArriveBetweenTwoNodes(startPoint: HoneyPoint, targetPoint: HoneyPoint): boolean {
|
||||
if (startPoint.hx == targetPoint.hx && startPoint.hy == targetPoint.hy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var disX: number = Math.abs(targetPoint.hx - startPoint.hx);
|
||||
var disY: number = Math.abs(targetPoint.hy - startPoint.hy);
|
||||
|
||||
var dirX = 0;
|
||||
|
||||
if (targetPoint.hx > startPoint.hx) {
|
||||
dirX = 1;
|
||||
}
|
||||
else if (targetPoint.hx < startPoint.hx) {
|
||||
dirX = -1;
|
||||
}
|
||||
|
||||
var dirY = 0;
|
||||
|
||||
if (targetPoint.hy > startPoint.hy) {
|
||||
dirY = 1;
|
||||
}
|
||||
else if (targetPoint.hy < startPoint.hy) {
|
||||
dirY = -1;
|
||||
}
|
||||
|
||||
var rx: number = 0;
|
||||
var ry: number = 0;
|
||||
var intNum: number = 0;
|
||||
var decimal: number = 0;
|
||||
|
||||
if (disX > disY) {
|
||||
var rate: number = disY / disX;
|
||||
|
||||
for (var i = 0; i < disX; i += 2) {
|
||||
ry = i * dirY * rate;
|
||||
intNum = dirY > 0 ? Math.floor(startPoint.hy + ry) : Math.ceil(startPoint.hy + ry);
|
||||
decimal = Math.abs(ry % 1);
|
||||
|
||||
var hpoint1: HoneyPoint = new HoneyPoint();
|
||||
hpoint1.hx = startPoint.hx + i * dirX;
|
||||
hpoint1.hy = decimal <= 0.5 ? intNum : intNum + 1 * dirY;
|
||||
|
||||
//cc.log(i + " :: " ,hpoint1.hx, hpoint1.hy," yy ",startPoint.hy + i * dirY * rate,ry % 1,rate,intNum,decimal,dirY,ry);
|
||||
|
||||
ry = (i + 1) * dirY * rate;
|
||||
intNum = dirY > 0 ? Math.floor(startPoint.hy + ry) : Math.ceil(startPoint.hy + ry);
|
||||
decimal = Math.abs(ry % 1);
|
||||
|
||||
var hpoint2: HoneyPoint = new HoneyPoint();
|
||||
hpoint2.hx = startPoint.hx + (i + 1) * dirX;
|
||||
hpoint2.hy = decimal <= 0.5 ? intNum : intNum + 1 * dirY;
|
||||
|
||||
ry = (i + 2) * dirY * rate;
|
||||
intNum = dirY > 0 ? Math.floor(startPoint.hy + ry) : Math.ceil(startPoint.hy + ry);
|
||||
decimal = Math.abs(ry % 1);
|
||||
|
||||
var hpoint3: HoneyPoint = new HoneyPoint();
|
||||
hpoint3.hx = startPoint.hx + (i + 2) * dirX;
|
||||
hpoint3.hy = decimal <= 0.5 ? intNum : intNum + 1 * dirY;
|
||||
|
||||
if (!this.isCrossAtAdjacentNodes(startPoint, targetPoint, hpoint1, hpoint2, hpoint3)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var rate: number = disX / disY;
|
||||
|
||||
for (var i = 0; i < disY; i += 2) {
|
||||
rx = i * dirX * rate;
|
||||
intNum = dirX > 0 ? Math.floor(startPoint.hx + rx) : Math.ceil(startPoint.hx + rx);
|
||||
decimal = Math.abs(rx % 1);
|
||||
|
||||
var hpoint1: HoneyPoint = new HoneyPoint();
|
||||
hpoint1.hx = decimal <= 0.5 ? intNum : intNum + 1 * dirX;
|
||||
hpoint1.hy = startPoint.hy + i * dirY;
|
||||
|
||||
rx = (i + 1) * dirX * rate;
|
||||
intNum = dirX > 0 ? Math.floor(startPoint.hx + rx) : Math.ceil(startPoint.hx + rx);
|
||||
decimal = Math.abs(rx % 1);
|
||||
|
||||
var hpoint2: HoneyPoint = new HoneyPoint();
|
||||
hpoint2.hx = decimal <= 0.5 ? intNum : intNum + 1 * dirX;
|
||||
hpoint2.hy = startPoint.hy + (i + 1) * dirY;
|
||||
|
||||
rx = (i + 2) * dirX * rate;
|
||||
intNum = dirX > 0 ? Math.floor(startPoint.hx + rx) : Math.ceil(startPoint.hx + rx);
|
||||
decimal = Math.abs(rx % 1);
|
||||
|
||||
var hpoint3: HoneyPoint = new HoneyPoint();
|
||||
hpoint3.hx = decimal <= 0.5 ? intNum : intNum + 1 * dirX;
|
||||
hpoint3.hy = startPoint.hy + (i + 2) * dirY;
|
||||
|
||||
if (!this.isCrossAtAdjacentNodes(startPoint, targetPoint, hpoint1, hpoint2, hpoint3)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断三个相邻的点是否可通过
|
||||
* @param node1
|
||||
* @param node2
|
||||
*/
|
||||
private isCrossAtAdjacentNodes(startPoint: HoneyPoint, targetPoint: HoneyPoint, hpoint1: HoneyPoint, hpoint2: HoneyPoint, hpoint3: HoneyPoint): boolean {
|
||||
var node1: RoadNode = this.getNodeByHoneyPoint(hpoint1.hx, hpoint1.hy);
|
||||
var node2: RoadNode = this.getNodeByHoneyPoint(hpoint2.hx, hpoint2.hy);
|
||||
var node3: RoadNode = this.getNodeByHoneyPoint(hpoint3.hx, hpoint3.hy); // 节点3主要用做路径方向的判断
|
||||
|
||||
if (node1 == node2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//前两个点只要有一个点不能通过就不能通过,节点3只做方向向导,不用考虑是否可通过和是否存在
|
||||
if (!this.isPassNode(node1) || !this.isPassNode(node2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var dirX1: number = hpoint1.hx - hpoint2.hx;
|
||||
var dirY1: number = hpoint1.hy - hpoint2.hy;
|
||||
|
||||
var dirX2: number = hpoint3.hx - hpoint2.hx;
|
||||
var dirY2: number = hpoint3.hy - hpoint2.hy;
|
||||
|
||||
//hround:number[][] = [[-1,-1],[-1,0],[0,1],[1,1],[1,0],[0,-1]]; //相邻点向量
|
||||
//[-1,1] [1,-1] //特殊相邻点向量
|
||||
|
||||
//如果不是相邻的两个点 则不能通过
|
||||
if ((Math.abs(dirX1) > 1 || Math.abs(dirY1) > 1) || (Math.abs(dirX2) > 1 || Math.abs(dirY2) > 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//特殊相邻点 特殊对待
|
||||
if (dirX1 == -dirY1) { //如果第一个点和第二个点是特殊相邻点
|
||||
if (dirX1 == -1) {
|
||||
if (!this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx - 1, hpoint2.hy)) || !this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx, hpoint2.hy + 1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx + 1, hpoint2.hy)) || !this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx, hpoint2.hy - 1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//第一个点和第二个点已经可通过,如果第二个点是终点,那么可直达
|
||||
if (hpoint2.hx == targetPoint.hx && hpoint2.hy == targetPoint.hy) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//特殊相邻点 特殊对待
|
||||
if (dirX2 == -dirY2) { //如果第二个点和第三个点是特殊相邻点
|
||||
if (dirX2 == -1) {
|
||||
if (!this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx - 1, hpoint2.hy)) || !this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx, hpoint2.hy + 1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx + 1, hpoint2.hy)) || !this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx, hpoint2.hy - 1))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//如果相邻的点和目标点在同一直线
|
||||
if (hpoint1.hx == hpoint2.hx && hpoint2.hx == hpoint3.hx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//var hround2:number[][] = [[-2,-1],[-1,1],[1,2],[2,1],[1,-1],[-1,-2]];
|
||||
|
||||
if (this.isPassNode(this.getNodeByHoneyPoint(hpoint2.hx + (dirX1 + dirX2), hpoint2.hy + (dirY1 + dirY2)))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得六边形格子坐标(以正斜角和反斜角为标准的坐标)
|
||||
* @param node
|
||||
*/
|
||||
public getHoneyPoint(node: RoadNode): HoneyPoint {
|
||||
var hx: number = node.cy + Math.ceil(node.cx / 2); //设置反斜角为x坐标
|
||||
var hy: number = node.cy - Math.floor(node.cx / 2); //设置正斜角为y坐标
|
||||
|
||||
return new HoneyPoint(hx, hy);
|
||||
}
|
||||
|
||||
public getNodeByHoneyPoint(hx: number, hy: number): RoadNode {
|
||||
var cx: number = hx - hy; //研究出来的
|
||||
var cy: number = Math.floor((hx - hy) / 2) + hy; //研究出来的
|
||||
|
||||
return this._roadNodes[cx + "_" + cy] as RoadNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得一个点周围指定方向相邻的一个点
|
||||
* @param node 制定的点
|
||||
* @param roundIndex 0是下,然后顺时针,5右下
|
||||
*/
|
||||
public getRoundNodeByIndex(node: RoadNode, roundIndex: number): RoadNode {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
roundIndex = roundIndex % 6;
|
||||
|
||||
var round: number[][];
|
||||
|
||||
node.cx % 2 == 0 ? round = this._round1 : round = this._round2;
|
||||
var cx: number = node.cx + round[roundIndex][0];
|
||||
var cy: number = node.cy + round[roundIndex][1];
|
||||
|
||||
return this._roadNodes[cx + "_" + cy] as RoadNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得一个点周围所有的相邻点
|
||||
* @param node
|
||||
*/
|
||||
public getRoundNodes(node: RoadNode): RoadNode[] {
|
||||
var round: number[][];
|
||||
|
||||
node.cx % 2 == 0 ? round = this._round1 : round = this._round2;
|
||||
|
||||
var nodeArr: RoadNode[] = [];
|
||||
|
||||
for (var i: number = 0; i < round.length; i++) {
|
||||
var cx: number = node.cx + round[i][0];
|
||||
var cy: number = node.cy + round[i][1];
|
||||
|
||||
var node2: RoadNode = this._roadNodes[cx + "_" + cy] as RoadNode;
|
||||
|
||||
nodeArr.push(node2);
|
||||
}
|
||||
|
||||
return nodeArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是可通过的点
|
||||
* @param node
|
||||
*/
|
||||
private isPassNode(node: RoadNode): boolean {
|
||||
if (!node || node.value == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*测试寻路步骤
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public testSeekPathStep(startNode: RoadNode, targetNode: RoadNode, callback: Function, target: any, time: number = 100): void {
|
||||
this._startNode = startNode;
|
||||
this._currentNode = startNode;
|
||||
this._targetNode = targetNode;
|
||||
|
||||
if (this._targetNode.value == 1)
|
||||
return;
|
||||
|
||||
this._startNode.g = 0; //重置起始节点的g值
|
||||
this._startNode.resetTree(); //清除起始节点原有的二叉堆关联关系
|
||||
|
||||
this._binaryTreeNode.refleshTag(); //刷新二叉堆tag,用于后面判断是不是属于当前次的寻路
|
||||
//this._binaryTreeNode.addTreeNode(this._startNode); //把起始节点设置为二叉堆结构的根节点
|
||||
|
||||
this._closelist = [];
|
||||
|
||||
var step: number = 0;
|
||||
|
||||
clearInterval(this.handle);
|
||||
this.handle = setInterval(() => {
|
||||
|
||||
if (step > this.maxStep) {
|
||||
console.log("没找到目标计算步骤为:", step);
|
||||
clearInterval(this.handle);
|
||||
return;
|
||||
}
|
||||
|
||||
step++;
|
||||
|
||||
this.searchRoundNodes(this._currentNode);
|
||||
|
||||
if (this._binaryTreeNode.isTreeNull()) //二叉堆树里已经没有任何可搜寻的点了,则寻路结束,每找到目标
|
||||
{
|
||||
console.log("没找到目标计算步骤为:", step);
|
||||
clearInterval(this.handle);
|
||||
return;
|
||||
}
|
||||
|
||||
this._currentNode = this._binaryTreeNode.getMin_F_Node();
|
||||
|
||||
if (this._currentNode == this._targetNode) {
|
||||
console.log("找到目标计算步骤为:", step);
|
||||
clearInterval(this.handle);
|
||||
|
||||
this._openlist = this._binaryTreeNode.getOpenList();
|
||||
callback.apply(target, [this._startNode, this._targetNode, this._currentNode, this._openlist, this._closelist, this.getPath()]);
|
||||
} else {
|
||||
this._binaryTreeNode.setRoadNodeInCloseList(this._currentNode);//打入关闭列表标记
|
||||
this._openlist = this._binaryTreeNode.getOpenList();
|
||||
this._closelist.push(this._currentNode);
|
||||
callback.apply(target, [this._startNode, this._targetNode, this._currentNode, this._openlist, this._closelist, null]);
|
||||
}
|
||||
|
||||
}, time);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*查找一个节点周围可通过的点
|
||||
* @param node
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private searchRoundNodes(node: RoadNode): void {
|
||||
var round: number[][];
|
||||
|
||||
node.cx % 2 == 0 ? round = this._round1 : round = this._round2;
|
||||
|
||||
for (var i: number = 0; i < round.length; i++) {
|
||||
var cx: number = node.cx + round[i][0];
|
||||
var cy: number = node.cy + round[i][1];
|
||||
var node2: RoadNode = this._roadNodes[cx + "_" + cy] as RoadNode;
|
||||
|
||||
if (node2 != null && node2 != this._startNode && node2.value != 1 && !this.isInCloseList(node2)) {
|
||||
this.setNodeF(node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*设置节点的F值
|
||||
* @param node
|
||||
*
|
||||
*/
|
||||
public setNodeF(node: RoadNode): void {
|
||||
var g: number;
|
||||
|
||||
if (node.cx == this._currentNode.cx || node.cy == this._currentNode.cy) {
|
||||
g = this._currentNode.g + this.COST_STRAIGHT;
|
||||
} else {
|
||||
g = this._currentNode.g + this.COST_DIAGONAL;
|
||||
}
|
||||
|
||||
if (this.isInOpenList(node)) {
|
||||
if (g < node.g) {
|
||||
node.g = g;
|
||||
|
||||
node.parent = this._currentNode;
|
||||
node.h = (Math.abs(this._targetNode.cx - node.cx) + Math.abs(this._targetNode.cy - node.cy)) * this.COST_STRAIGHT;
|
||||
node.f = node.g + node.h;
|
||||
|
||||
//节点的g值已经改变,把节点先从二堆叉树结构中删除,再重新添加进二堆叉树
|
||||
this._binaryTreeNode.removeTreeNode(node);
|
||||
this._binaryTreeNode.addTreeNode(node);
|
||||
|
||||
}
|
||||
} else {
|
||||
node.g = g;
|
||||
|
||||
this._binaryTreeNode.setRoadNodeInOpenList(node);//给节点打入开放列表的标志
|
||||
node.resetTree();
|
||||
|
||||
node.parent = this._currentNode;
|
||||
node.h = (Math.abs(this._targetNode.cx - node.cx) + Math.abs(this._targetNode.cy - node.cy)) * this.COST_STRAIGHT;
|
||||
node.f = node.g + node.h;
|
||||
|
||||
this._binaryTreeNode.addTreeNode(node);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*节点是否在开启列表
|
||||
* @param node
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
private isInOpenList(node: RoadNode): Boolean {
|
||||
return this._binaryTreeNode.isInOpenList(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点是否在关闭列表
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
private isInCloseList(node: RoadNode): Boolean {
|
||||
return this._binaryTreeNode.isInCloseList(node);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._roadNodes = null;
|
||||
this._round1 = null;
|
||||
this._round2 = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 六边形格子坐标(以正斜角和反斜角为标准的坐标)
|
||||
*/
|
||||
class HoneyPoint {
|
||||
public hx: number = 0;
|
||||
public hy: number = 0;
|
||||
|
||||
constructor(x: number = 0, y: number = 0) {
|
||||
this.hx = x;
|
||||
this.hy = y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "470f8a32-bf7c-4747-bd7d-07042bbc389e",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
252
assets/script/game/map/view/map/road/BinaryTreeNode.ts
Normal file
252
assets/script/game/map/view/map/road/BinaryTreeNode.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
import RoadNode from "./RoadNode";
|
||||
|
||||
/**
|
||||
* 二堆叉结构存储
|
||||
*/
|
||||
export default class BinaryTreeNode {
|
||||
/**
|
||||
* 当前寻路标记,用于标记节点是否属于当前次寻路运算
|
||||
*/
|
||||
public seekTag: number = 0;
|
||||
|
||||
/**
|
||||
* 开启列表根节点
|
||||
*/
|
||||
public openNode: RoadNode = null;
|
||||
|
||||
/**
|
||||
* 计数当次寻路的运算代价(用于测试数据)
|
||||
*/
|
||||
public count: number = 0;
|
||||
|
||||
/**
|
||||
* 刷新寻路tag标记,用于标记当前是哪次的寻路
|
||||
*/
|
||||
public refleshTag() {
|
||||
this.openNode = null;
|
||||
|
||||
this.count = 0;
|
||||
|
||||
this.seekTag++;
|
||||
|
||||
if (this.seekTag > 1000000000) {
|
||||
this.seekTag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 二叉堆树是否为空,即没有任何节点加入
|
||||
* @returns
|
||||
*/
|
||||
public isTreeNull() {
|
||||
return this.openNode == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把节点添加进二叉堆里
|
||||
* @param roadNode 要添加的节点
|
||||
* @param head 从哪个节点位置开始添加
|
||||
* @returns
|
||||
*/
|
||||
public addTreeNode(roadNode: RoadNode, head: RoadNode = null) {
|
||||
this.count++; //计数统计运算代价
|
||||
|
||||
if (head == null) {
|
||||
if (this.openNode == null) //如果开启节点为空,则拿首次加二叉堆的节点作为开启节点
|
||||
{
|
||||
this.openNode = roadNode;
|
||||
//console.log(this.count,"add root ",roadNode.f,roadNode.toString());
|
||||
return;
|
||||
} else //如果开启节点存在,头节点为null,默认把开启节点用于头节点
|
||||
{
|
||||
head = this.openNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (roadNode.f >= head.f) {
|
||||
if (head.right == null) {
|
||||
head.right = roadNode;
|
||||
roadNode.treeParent = head;
|
||||
//console.log(this.count,"add right ",roadNode.f,roadNode.toString());
|
||||
} else {
|
||||
this.addTreeNode(roadNode, head.right);
|
||||
}
|
||||
} else {
|
||||
if (head.left == null) {
|
||||
head.left = roadNode;
|
||||
roadNode.treeParent = head;
|
||||
//console.log(this.count,"add left ",roadNode.f,roadNode.toString());
|
||||
} else {
|
||||
this.addTreeNode(roadNode, head.left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除树节点
|
||||
* @param roadNode 要删除的节点
|
||||
*/
|
||||
public removeTreeNode(roadNode: RoadNode) {
|
||||
this.count++; //计数统计运算代价
|
||||
|
||||
if (roadNode.treeParent == null && roadNode.left == null && roadNode.right == null) //节点不在树结构中
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (roadNode.treeParent == null) //如果是根节点,优先把左子节点转换成根节点,左子节点不存在,则把右子节点转换成根节点
|
||||
{
|
||||
if (roadNode.left) {
|
||||
this.openNode = roadNode.left;
|
||||
roadNode.left.treeParent = null;
|
||||
|
||||
if (roadNode.right) {
|
||||
roadNode.right.treeParent = null;
|
||||
this.addTreeNode(roadNode.right, this.openNode);
|
||||
}
|
||||
} else if (roadNode.right) //如果没有左节点,只有右节点
|
||||
{
|
||||
this.openNode = roadNode.right;
|
||||
roadNode.right.treeParent = null;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (roadNode.treeParent.left == roadNode) //如果是左子节点
|
||||
{
|
||||
if (roadNode.right) {
|
||||
roadNode.treeParent.left = roadNode.right;
|
||||
roadNode.right.treeParent = roadNode.treeParent;
|
||||
|
||||
if (roadNode.left) {
|
||||
roadNode.left.treeParent = null;
|
||||
this.addTreeNode(roadNode.left, roadNode.right)
|
||||
}
|
||||
} else {
|
||||
roadNode.treeParent.left = roadNode.left;
|
||||
if (roadNode.left) {
|
||||
roadNode.left.treeParent = roadNode.treeParent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if (roadNode.treeParent.right == roadNode) //如果是右子节点
|
||||
{
|
||||
if (roadNode.left) {
|
||||
roadNode.treeParent.right = roadNode.left;
|
||||
roadNode.left.treeParent = roadNode.treeParent;
|
||||
|
||||
if (roadNode.right) {
|
||||
roadNode.right.treeParent = null;
|
||||
this.addTreeNode(roadNode.right, roadNode.left)
|
||||
}
|
||||
} else {
|
||||
roadNode.treeParent.right = roadNode.right;
|
||||
if (roadNode.right) {
|
||||
roadNode.right.treeParent = roadNode.treeParent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
roadNode.resetTree();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 从二叉堆结构里快速查找除f值最小的路节点
|
||||
* @param head 搜索的起始节点
|
||||
* @returns
|
||||
*/
|
||||
public getMin_F_Node(head: RoadNode = null): RoadNode {
|
||||
this.count++; //计数统计运算代价
|
||||
|
||||
if (head == null) {
|
||||
if (this.openNode == null) {
|
||||
return null;
|
||||
} else {
|
||||
head = this.openNode; //如果头节点为null,并且开启节点不为空,则头节点默认使用开启节点
|
||||
}
|
||||
}
|
||||
|
||||
if (head.left == null) {
|
||||
var minNode: RoadNode = head;
|
||||
|
||||
if (head.treeParent == null) {
|
||||
this.openNode = head.right;
|
||||
if (this.openNode) {
|
||||
this.openNode.treeParent = null;
|
||||
}
|
||||
} else {
|
||||
head.treeParent.left = head.right;
|
||||
if (head.right) {
|
||||
head.right.treeParent = head.treeParent;
|
||||
}
|
||||
}
|
||||
|
||||
return minNode;
|
||||
} else {
|
||||
return this.getMin_F_Node(head.left);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把节点加入开启列表,即打入开启列表标志
|
||||
* @param node
|
||||
*/
|
||||
public setRoadNodeInOpenList(node: RoadNode) {
|
||||
node.openTag = this.seekTag; //给节点打入开放列表的标志
|
||||
node.closeTag = 0; //关闭列表标志关闭
|
||||
}
|
||||
|
||||
/**
|
||||
* 把节点加入关闭列表,即打入关闭列表标志
|
||||
* @param node
|
||||
*/
|
||||
public setRoadNodeInCloseList(node: RoadNode) {
|
||||
node.openTag = 0; //开放列表标志关闭
|
||||
node.closeTag = this.seekTag; //给节点打入关闭列表的标志
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点是否在开启列表
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
public isInOpenList(node: RoadNode): Boolean {
|
||||
return node.openTag == this.seekTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点是否在关闭列表
|
||||
* @param node
|
||||
* @returns
|
||||
*/
|
||||
public isInCloseList(node: RoadNode): Boolean {
|
||||
return node.closeTag == this.seekTag;
|
||||
}
|
||||
|
||||
public getOpenList(): RoadNode[] {
|
||||
var openList: RoadNode[] = []
|
||||
this.seachTree(this.openNode, openList);
|
||||
return openList;
|
||||
}
|
||||
|
||||
private seachTree(head: RoadNode, openList: RoadNode[]) {
|
||||
if (head == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
openList.push(head);
|
||||
|
||||
if (head.left) {
|
||||
this.seachTree(head.left, openList);
|
||||
}
|
||||
|
||||
if (head.right) {
|
||||
this.seachTree(head.right, openList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "fbb8e89e-e776-48a5-bad2-bfbbd08cff18",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
36
assets/script/game/map/view/map/road/IRoadSeeker.ts
Normal file
36
assets/script/game/map/view/map/road/IRoadSeeker.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import RoadNode from "./RoadNode";
|
||||
|
||||
/**
|
||||
* 寻路接口
|
||||
* @author 落日故人 QQ 583051842
|
||||
*
|
||||
*/
|
||||
export default interface IRoadSeeker {
|
||||
/**
|
||||
*寻路入口方法
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
seekPath(startNode: RoadNode, targetNode: RoadNode): Array<RoadNode>;
|
||||
|
||||
/**
|
||||
*寻路入口方法 如果没有寻到目标,则返回离目标最近的路径
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
seekPath2(startNode: RoadNode, targetNode: RoadNode): Array<RoadNode>;
|
||||
|
||||
/**
|
||||
*测试寻路步骤
|
||||
* @param startNode
|
||||
* @param targetNode
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
testSeekPathStep(startNode: RoadNode, targetNode: RoadNode, callback: Function, target: any, time: number): void;
|
||||
|
||||
}
|
||||
11
assets/script/game/map/view/map/road/IRoadSeeker.ts.meta
Normal file
11
assets/script/game/map/view/map/road/IRoadSeeker.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "e4f3fe84-cffc-40ca-ac1a-e0d853f234d8",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
974
assets/script/game/map/view/map/road/MapRoadUtils.ts
Normal file
974
assets/script/game/map/view/map/road/MapRoadUtils.ts
Normal file
@@ -0,0 +1,974 @@
|
||||
import { MapType } from "../base/MapType";
|
||||
import Point from "./Point";
|
||||
import RoadNode from "./RoadNode";
|
||||
|
||||
export default class MapRoadUtils {
|
||||
|
||||
private static _instance: MapRoadUtils;
|
||||
|
||||
public static get instance(): MapRoadUtils {
|
||||
if (this._instance == null) {
|
||||
this._instance = new MapRoadUtils();
|
||||
}
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 地图宽度
|
||||
*/
|
||||
private _mapWidth: number;
|
||||
|
||||
/**
|
||||
*地图高度
|
||||
*/
|
||||
private _mapHeight: number;
|
||||
|
||||
/**
|
||||
*地图一共分成几行
|
||||
*/
|
||||
private _row: number;
|
||||
|
||||
/**
|
||||
*地图一共分成几列
|
||||
*/
|
||||
private _col: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格宽
|
||||
*/
|
||||
private _nodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格高
|
||||
*/
|
||||
private _nodeHeight: number;
|
||||
|
||||
/**
|
||||
*地图路点单元宽的一半
|
||||
*/
|
||||
private _halfNodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元高的一半
|
||||
*/
|
||||
private _halfNodeHeight: number;
|
||||
|
||||
private _mapType: number;
|
||||
|
||||
private _mapRoad: IMapRoad;
|
||||
|
||||
public updateMapInfo(mapWidth: number, mapHeight: number, nodeWidth: number, nodeHeight: number, mapType: MapType): void {
|
||||
this._mapWidth = mapWidth;
|
||||
this._mapHeight = mapHeight;
|
||||
this._nodeWidth = nodeWidth;
|
||||
this._nodeHeight = nodeHeight;
|
||||
|
||||
this._halfNodeWidth = Math.floor(this._nodeWidth / 2);
|
||||
this._halfNodeHeight = Math.floor(this._nodeHeight / 2);
|
||||
|
||||
this._mapType = mapType;
|
||||
|
||||
switch (this._mapType) {
|
||||
case MapType.angle45:
|
||||
|
||||
this._col = Math.ceil(mapWidth / this._nodeWidth);
|
||||
this._row = Math.ceil(mapHeight / this._nodeHeight) * 2;
|
||||
|
||||
this._mapRoad = new MapRoad45Angle(this._row, this._col, this._nodeWidth, this._nodeHeight, this._halfNodeWidth, this._halfNodeHeight); break;
|
||||
case MapType.angle90:
|
||||
|
||||
this._col = Math.ceil(mapWidth / this._nodeWidth);
|
||||
this._row = Math.ceil(mapHeight / this._nodeHeight);
|
||||
|
||||
this._mapRoad = new MapRoad90Angle(this._row, this._col, this._nodeWidth, this._nodeHeight, this._halfNodeWidth, this._halfNodeHeight); break;
|
||||
case MapType.honeycomb:
|
||||
|
||||
//this._nodeHeight = (this._nodeWidth / 2) * 1.732;
|
||||
|
||||
this._col = Math.ceil((this._mapWidth - this._nodeWidth / 4) / (this._nodeWidth / 4 * 6)) * 2;
|
||||
this._row = Math.ceil((this._mapHeight - this._nodeHeight / 2) / this._nodeHeight);
|
||||
|
||||
this._mapRoad = new MapRoadHoneycomb(this._row, this._col, this._nodeWidth, this._nodeHeight, this._halfNodeWidth, this._halfNodeHeight); break;
|
||||
}
|
||||
|
||||
// console.log("c r", this._col, this._row);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据地图平面像素坐标获得路节点
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByPixel(x: number, y: number): RoadNode {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getNodeByPixel(x, y);
|
||||
}
|
||||
return new RoadNode();
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点平面坐标点获得路节点
|
||||
* @param px
|
||||
* @param py
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByDerect(dx: number, dy: number): RoadNode {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getNodeByDerect(dx, dy);
|
||||
}
|
||||
return new RoadNode();
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点场景世界坐标获得路节点
|
||||
* @param wx
|
||||
* @param wy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByWorldPoint(wx: number, wy: number): RoadNode {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getNodeByWorldPoint(wx, wy);
|
||||
}
|
||||
return new RoadNode();
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标得到场景世界坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getWorldPointByPixel(x: number, y: number): Point {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getWorldPointByPixel(x, y);
|
||||
}
|
||||
return new Point();
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得像素坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByWorldPoint(cx: number, cy: number): Point {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getPixelByWorldPoint(cx, cy);
|
||||
}
|
||||
return new Point();
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标获得网格平面坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByPixel(x: number, y: number): Point {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getDerectByPixel(x, y);
|
||||
}
|
||||
return new Point();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得网格平面坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByWorldPoint(cx: number, cy: number): Point {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getDerectByWorldPoint(cx, cy);
|
||||
}
|
||||
return new Point();
|
||||
}
|
||||
|
||||
/**
|
||||
*根据网格平面坐标获得世界坐标
|
||||
* @param dx
|
||||
* @param dy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
/* public getWorldPointByDerect(dx:number,dy:number):Point
|
||||
{
|
||||
var cx:number = (dy + dx) / 2;
|
||||
var cy:number = (dy - dx) / 2 + col - 1;
|
||||
return new Point(cx,cy);
|
||||
}*/
|
||||
|
||||
public getPixelByDerect(dx: number, dy: number): Point {
|
||||
if (this._mapRoad) {
|
||||
return this._mapRoad.getPixelByDerect(dx, dy);
|
||||
}
|
||||
return new Point();
|
||||
}
|
||||
|
||||
public get mapWidth(): number {
|
||||
return this._mapWidth;
|
||||
}
|
||||
|
||||
public get mapHeight(): number {
|
||||
return this._mapHeight;
|
||||
}
|
||||
|
||||
public get nodeWidth(): number {
|
||||
return this._nodeWidth;
|
||||
}
|
||||
|
||||
public get nodeHeight(): number {
|
||||
return this._nodeHeight;
|
||||
}
|
||||
|
||||
public get row(): number {
|
||||
return this._row;
|
||||
}
|
||||
|
||||
public get col(): number {
|
||||
return this._col;
|
||||
}
|
||||
|
||||
public get halfNodeWidth(): number {
|
||||
return this._halfNodeWidth;
|
||||
}
|
||||
|
||||
public get halfNodeHeight(): number {
|
||||
return this._halfNodeHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
*地图类型 0:斜45度等视角地图, 1:90度角平面地图
|
||||
*/
|
||||
public get mapType(): number {
|
||||
return this._mapType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*地图路点处理接口
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
interface IMapRoad {
|
||||
/**
|
||||
*根据地图平面像素坐标获得路节点
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getNodeByPixel(x: number, y: number): RoadNode;
|
||||
|
||||
/**
|
||||
*根据路点平面坐标点获得路节点
|
||||
* @param px
|
||||
* @param py
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getNodeByDerect(dx: number, dy: number): RoadNode;
|
||||
|
||||
/**
|
||||
*根据路点场景世界坐标获得路节点
|
||||
* @param wx
|
||||
* @param wy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getNodeByWorldPoint(wx: number, wy: number): RoadNode;
|
||||
|
||||
|
||||
/**
|
||||
*根据像素坐标得到场景世界坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getWorldPointByPixel(x: number, y: number): Point;
|
||||
|
||||
|
||||
/**
|
||||
*根据世界坐标获得像素坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getPixelByWorldPoint(cx: number, cy: number): Point;
|
||||
|
||||
|
||||
/**
|
||||
*根据像素坐标获得网格平面坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getDerectByPixel(x: number, y: number): Point;
|
||||
|
||||
|
||||
/**
|
||||
*根据世界坐标获得网格平面坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getDerectByWorldPoint(cx: number, cy: number): Point;
|
||||
|
||||
|
||||
/**
|
||||
*根据网格平面坐标获得像素坐标
|
||||
* @param dx
|
||||
* @param dy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
getPixelByDerect(dx: number, dy: number): Point;
|
||||
}
|
||||
|
||||
/**
|
||||
*45度等视角地图路点处理接口实现
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class MapRoad45Angle implements IMapRoad {
|
||||
|
||||
/**
|
||||
*地图一共分成几行
|
||||
*/
|
||||
private _row: number;
|
||||
|
||||
/**
|
||||
*地图一共分成几列
|
||||
*/
|
||||
private _col: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格宽
|
||||
*/
|
||||
private _nodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格高
|
||||
*/
|
||||
private _nodeHeight: number;
|
||||
|
||||
/**
|
||||
*地图路点单元宽的一半
|
||||
*/
|
||||
private _halfNodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元高的一半
|
||||
*/
|
||||
private _halfNodeHeight: number;
|
||||
|
||||
public constructor(row: number, col: number, nodeWidth: number, nodeHeight: number, halfNodeWidth: number, halfNodeHeight: number) {
|
||||
this._row = row;
|
||||
this._col = col;
|
||||
this._nodeWidth = nodeWidth;
|
||||
this._nodeHeight = nodeHeight;
|
||||
this._halfNodeWidth = halfNodeWidth;
|
||||
this._halfNodeHeight = halfNodeHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据地图平面像素坐标获得路节点
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByPixel(x: number, y: number): RoadNode {
|
||||
var wPoint: Point = this.getWorldPointByPixel(x, y);
|
||||
var fPoint: Point = this.getPixelByWorldPoint(wPoint.x, wPoint.y);
|
||||
var dPoint: Point = this.getDerectByPixel(x, y);
|
||||
|
||||
var node: RoadNode = new RoadNode();
|
||||
|
||||
node.cx = wPoint.x;
|
||||
node.cy = wPoint.y;
|
||||
|
||||
node.px = fPoint.x;
|
||||
node.py = fPoint.y;
|
||||
|
||||
node.dx = dPoint.x;
|
||||
node.dy = dPoint.y;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点平面坐标点获得路节点
|
||||
* @param px
|
||||
* @param py
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByDerect(dx: number, dy: number): RoadNode {
|
||||
|
||||
var fPoint: Point = this.getPixelByDerect(dx, dy);
|
||||
var wPoint: Point = this.getWorldPointByPixel(fPoint.x, fPoint.y);
|
||||
|
||||
var node: RoadNode = new RoadNode();
|
||||
|
||||
node.cx = wPoint.x;
|
||||
node.cy = wPoint.y;
|
||||
|
||||
node.px = fPoint.x;
|
||||
node.py = fPoint.y;
|
||||
|
||||
node.dx = dx;
|
||||
node.dy = dy;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点场景世界坐标获得路节点
|
||||
* @param wx
|
||||
* @param wy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByWorldPoint(wx: number, wy: number): RoadNode {
|
||||
var point: Point = this.getPixelByWorldPoint(wx, wy)
|
||||
return this.getNodeByPixel(point.x, point.y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标得到场景世界坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getWorldPointByPixel(x: number, y: number): Point {
|
||||
var cx: number = Math.ceil(x / this._nodeWidth - 0.5 + y / this._nodeHeight) - 1;
|
||||
var cy: number = (this._col - 1) - Math.ceil(x / this._nodeWidth - 0.5 - y / this._nodeHeight);
|
||||
|
||||
return new Point(cx, cy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得像素坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByWorldPoint(cx: number, cy: number): Point {
|
||||
var x: number = Math.floor((cx + 1 - (cy - (this._col - 1))) * this._halfNodeWidth);
|
||||
var y: number = Math.floor((cx + 1 + (cy - (this._col - 1))) * this._halfNodeHeight);
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标获得网格平面坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByPixel(x: number, y: number): Point {
|
||||
var worldPoint: Point = this.getWorldPointByPixel(x, y);
|
||||
var pixelPoint: Point = this.getPixelByWorldPoint(worldPoint.x, worldPoint.y);
|
||||
var dx: number = Math.floor(pixelPoint.x / this._nodeWidth) - (pixelPoint.x % this._nodeWidth == 0 ? 1 : 0);
|
||||
var dy: number = Math.floor(pixelPoint.y / this._halfNodeHeight) - 1;
|
||||
return new Point(dx, dy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得网格平面坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByWorldPoint(cx: number, cy: number): Point {
|
||||
var dx: number = Math.floor((cx - (cy - (this._col - 1))) / 2);
|
||||
var dy: number = cx + (cy - (this._col - 1));
|
||||
return new Point(dx, dy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据网格平面坐标获得像素坐标
|
||||
* @param dx
|
||||
* @param dy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByDerect(dx: number, dy: number): Point {
|
||||
var x: number = Math.floor((dx + dy % 2) * this._nodeWidth + (1 - dy % 2) * this._halfNodeWidth);
|
||||
var y: number = Math.floor((dy + 1) * this._halfNodeHeight);
|
||||
return new Point(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*90度平面地图路点处理接口实现
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class MapRoad90Angle implements IMapRoad {
|
||||
/**
|
||||
*地图一共分成几行
|
||||
*/
|
||||
private _row: number;
|
||||
|
||||
/**
|
||||
*地图一共分成几列
|
||||
*/
|
||||
private _col: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格宽
|
||||
*/
|
||||
private _nodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格高
|
||||
*/
|
||||
private _nodeHeight: number;
|
||||
|
||||
/**
|
||||
*地图路点单元宽的一半
|
||||
*/
|
||||
private _halfNodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元高的一半
|
||||
*/
|
||||
private _halfNodeHeight: number;
|
||||
|
||||
public constructor(row: number, col: number, nodeWidth: number, nodeHeight: number, halfNodeWidth: number, halfNodeHeight: number) {
|
||||
this._row = row;
|
||||
this._col = col;
|
||||
this._nodeWidth = nodeWidth;
|
||||
this._nodeHeight = nodeHeight;
|
||||
this._halfNodeWidth = halfNodeWidth;
|
||||
this._halfNodeHeight = halfNodeHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据地图平面像素坐标获得路节点
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByPixel(x: number, y: number): RoadNode {
|
||||
var wPoint: Point = this.getWorldPointByPixel(x, y);
|
||||
var fPoint: Point = this.getPixelByWorldPoint(wPoint.x, wPoint.y);
|
||||
var dPoint: Point = this.getDerectByPixel(x, y);
|
||||
|
||||
var node: RoadNode = new RoadNode();
|
||||
|
||||
node.cx = wPoint.x;
|
||||
node.cy = wPoint.y;
|
||||
|
||||
node.px = fPoint.x;
|
||||
node.py = fPoint.y;
|
||||
|
||||
node.dx = dPoint.x;
|
||||
node.dy = dPoint.y;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点平面坐标点获得路节点
|
||||
* @param px
|
||||
* @param py
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByDerect(dx: number, dy: number): RoadNode {
|
||||
|
||||
var fPoint: Point = this.getPixelByDerect(dx, dy);
|
||||
var wPoint: Point = this.getWorldPointByPixel(fPoint.x, fPoint.y);
|
||||
|
||||
var node: RoadNode = new RoadNode();
|
||||
|
||||
node.cx = wPoint.x;
|
||||
node.cy = wPoint.y;
|
||||
|
||||
node.px = fPoint.x;
|
||||
node.py = fPoint.y;
|
||||
|
||||
node.dx = dx;
|
||||
node.dy = dy;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点场景世界坐标获得路节点
|
||||
* @param wx
|
||||
* @param wy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByWorldPoint(wx: number, wy: number): RoadNode {
|
||||
var point: Point = this.getPixelByWorldPoint(wx, wy)
|
||||
return this.getNodeByPixel(point.x, point.y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标得到场景世界坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getWorldPointByPixel(x: number, y: number): Point {
|
||||
var cx: number = Math.floor(x / this._nodeWidth);
|
||||
var cy: number = Math.floor(y / this._nodeHeight);
|
||||
|
||||
return new Point(cx, cy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得像素坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByWorldPoint(cx: number, cy: number): Point {
|
||||
var x: number = Math.floor((cx + 1) * this._nodeWidth - this._halfNodeWidth);
|
||||
var y: number = Math.floor((cy + 1) * this._nodeHeight - this._halfNodeHeight);
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标获得网格平面坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByPixel(x: number, y: number): Point {
|
||||
var dx: number = Math.floor(x / this._nodeWidth);
|
||||
var dy: number = Math.floor(y / this._nodeHeight);
|
||||
return new Point(dx, dy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得网格平面坐标 90度地图的世界坐标和网格坐标相同
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByWorldPoint(cx: number, cy: number): Point {
|
||||
return new Point(cx, cy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据网格平面坐标获得像素坐标
|
||||
* @param dx
|
||||
* @param dy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByDerect(dx: number, dy: number): Point {
|
||||
var x: number = Math.floor((dx + 1) * this._nodeWidth - this._halfNodeWidth);
|
||||
var y: number = Math.floor((dy + 1) * this._nodeHeight - this._halfNodeHeight);
|
||||
return new Point(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*蜂巢式(即正六边形)地图路点处理接口实现
|
||||
* @author Administrator
|
||||
*
|
||||
*/
|
||||
class MapRoadHoneycomb implements IMapRoad {
|
||||
/**
|
||||
*地图一共分成几行
|
||||
*/
|
||||
private _row: number;
|
||||
|
||||
/**
|
||||
*地图一共分成几列
|
||||
*/
|
||||
private _col: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格宽
|
||||
*/
|
||||
private _nodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元格高
|
||||
*/
|
||||
private _nodeHeight: number;
|
||||
|
||||
/**
|
||||
*地图路点单元宽的一半
|
||||
*/
|
||||
private _halfNodeWidth: number;
|
||||
|
||||
/**
|
||||
*地图路点单元高的一半
|
||||
*/
|
||||
private _halfNodeHeight: number;
|
||||
|
||||
/**
|
||||
* 六边形直径的4分之一
|
||||
*/
|
||||
private _nwDiv4: number;
|
||||
|
||||
/**
|
||||
* 六边形直径的半径
|
||||
*/
|
||||
private _radius: number;
|
||||
|
||||
/**
|
||||
* 六边形宽高的tan值,正六边形为1.732
|
||||
*/
|
||||
private _proportion = 1.732;
|
||||
|
||||
/**
|
||||
*蜂巢式(即正六边形)地图路点处理
|
||||
* @param row
|
||||
* @param col
|
||||
* @param nodeWidth
|
||||
* @param nodeHeight
|
||||
* @param halfNodeWidth
|
||||
* @param halfNodeHeight
|
||||
*
|
||||
*/
|
||||
public constructor(row: number, col: number, nodeWidth: number, nodeHeight: number, halfNodeWidth: number, halfNodeHeight: number) {
|
||||
this._row = row;
|
||||
this._col = col;
|
||||
this._nodeWidth = nodeWidth;
|
||||
//this._nodeHeight = (this._nodeWidth / 2) * 1.732;
|
||||
this._nodeHeight = nodeHeight;
|
||||
this._halfNodeWidth = halfNodeWidth;
|
||||
this._halfNodeHeight = halfNodeHeight;
|
||||
|
||||
this._nwDiv4 = this._nodeWidth / 4;
|
||||
this._radius = this._nwDiv4 * 4;
|
||||
|
||||
this._proportion = this._nodeHeight * 2 / this._nodeWidth;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*根据地图平面像素坐标获得路节点
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByPixel(x: number, y: number): RoadNode {
|
||||
var wPoint: Point = this.getWorldPointByPixel(x, y);
|
||||
var fPoint: Point = this.getPixelByWorldPoint(wPoint.x, wPoint.y);
|
||||
//var dPoint:Point = getDerectByPixel(x,y);
|
||||
|
||||
var node: RoadNode = new RoadNode();
|
||||
|
||||
node.cx = wPoint.x;
|
||||
node.cy = wPoint.y;
|
||||
|
||||
node.px = fPoint.x;
|
||||
node.py = fPoint.y;
|
||||
|
||||
node.dx = wPoint.x;
|
||||
node.dy = wPoint.y;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点平面坐标点获得路节点
|
||||
* @param px
|
||||
* @param py
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByDerect(dx: number, dy: number): RoadNode {
|
||||
|
||||
var fPoint: Point = this.getPixelByDerect(dx, dy);
|
||||
//var wPoint:Point = getWorldPointByPixel(fPoint.x,fPoint.y);
|
||||
|
||||
var node: RoadNode = new RoadNode();
|
||||
|
||||
node.cx = dx;
|
||||
node.cy = dy;
|
||||
|
||||
node.px = fPoint.x;
|
||||
node.py = fPoint.y;
|
||||
|
||||
node.dx = dx;
|
||||
node.dy = dy;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据路点场景世界坐标获得路节点
|
||||
* @param wx
|
||||
* @param wy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getNodeByWorldPoint(wx: number, wy: number): RoadNode {
|
||||
var point: Point = this.getPixelByWorldPoint(wx, wy)
|
||||
return this.getNodeByPixel(point.x, point.y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标得到场景世界坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getWorldPointByPixel(x: number, y: number): Point {
|
||||
var nwDiv4Index: number = Math.floor(x / this._nwDiv4); //六边形的外切矩形竖方向均等分成4分,所有的六边形外切矩形连在一起形成一个个4分之一矩形宽的区域,nwDiv4Index就是该区域的索引
|
||||
|
||||
var col: number = Math.floor(nwDiv4Index / 3); //取得临时六边形横轴的索引,根据不同的情况可能会变
|
||||
|
||||
var row: number; //六边形纵轴的索引
|
||||
|
||||
var cx: number;
|
||||
|
||||
var cy: number;
|
||||
|
||||
if ((nwDiv4Index - 1) % 6 == 0 || (nwDiv4Index - 2) % 6 == 0) {
|
||||
row = Math.floor(y / this._nodeHeight);
|
||||
cx = col;
|
||||
cy = row;
|
||||
}
|
||||
else if ((nwDiv4Index - 4) % 6 == 0 || (nwDiv4Index - 5) % 6 == 0) {
|
||||
if (y < this._nodeHeight / 2) {
|
||||
row = -1;
|
||||
} else {
|
||||
row = Math.floor((y - this._nodeHeight / 2) / this._nodeHeight);
|
||||
}
|
||||
cx = col;
|
||||
cy = row
|
||||
}
|
||||
else {
|
||||
if (col % 2 == 0) {
|
||||
//(x - 1,y - 1) (x - 1,y)
|
||||
row = Math.floor(y / this._nodeHeight);
|
||||
|
||||
if (this.testPointInHoneycomb(col, row, x, y)) {
|
||||
cx = col;
|
||||
cy = row;
|
||||
}
|
||||
else if (this.testPointInHoneycomb(col - 1, row - 1, x, y)) {
|
||||
cx = col - 1;
|
||||
cy = row - 1;
|
||||
}
|
||||
else {
|
||||
cx = col - 1;
|
||||
cy = row;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
//(x - 1,y) (x - 1,y + 1)
|
||||
if (y < this._nodeHeight / 2) {
|
||||
row = -1;
|
||||
} else {
|
||||
row = Math.floor((y - this._nodeHeight / 2) / this._nodeHeight);
|
||||
}
|
||||
|
||||
if (this.testPointInHoneycomb(col, row, x, y)) {
|
||||
cx = col;
|
||||
cy = row;
|
||||
}
|
||||
else if (this.testPointInHoneycomb(col - 1, row, x, y)) {
|
||||
cx = col - 1;
|
||||
cy = row;
|
||||
}
|
||||
else {
|
||||
cx = col - 1;
|
||||
cy = row + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Point(cx, cy);
|
||||
}
|
||||
|
||||
private testPointInHoneycomb(col: number, row: number, px: number, py: number): Boolean {
|
||||
var a: number = this._nwDiv4 * 2;
|
||||
|
||||
var point: Point = this.getPixelByWorldPoint(col, row);
|
||||
|
||||
var absX: number = Math.abs(px - point.x);
|
||||
var absY: number = Math.abs(py - point.y);
|
||||
|
||||
//return a-absX >= absY/(1.732);
|
||||
|
||||
return a - absX >= absY / this._proportion;
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得像素坐标
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByWorldPoint(cx: number, cy: number): Point {
|
||||
var x: number = Math.floor((2 + 3 * cx) / 4 * this._nodeWidth);
|
||||
var y: number = Math.floor((cy + 1 / 2 * (1 + (cx % 2))) * this._nodeHeight);
|
||||
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据像素坐标获得网格平面坐标
|
||||
* @param x
|
||||
* @param y
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByPixel(x: number, y: number): Point {
|
||||
|
||||
return this.getWorldPointByPixel(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据世界坐标获得网格平面坐标 90度地图的世界坐标和网格坐标相同
|
||||
* @param cx
|
||||
* @param cy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getDerectByWorldPoint(cx: number, cy: number): Point {
|
||||
return new Point(cx, cy);
|
||||
}
|
||||
|
||||
/**
|
||||
*根据网格平面坐标获得像素坐标
|
||||
* @param dx
|
||||
* @param dy
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public getPixelByDerect(dx: number, dy: number): Point {
|
||||
var x: number = (2 + 3 * dx) / 4 * this._nodeWidth;
|
||||
var y: number = (dy + 1 / 2 * (1 + (dx % 2))) * this._nodeHeight;
|
||||
return new Point(x, y);
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/road/MapRoadUtils.ts.meta
Normal file
11
assets/script/game/map/view/map/road/MapRoadUtils.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "38983af0-c3cc-42a2-bd83-49e6b001f888",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
9
assets/script/game/map/view/map/road/Point.ts
Normal file
9
assets/script/game/map/view/map/road/Point.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export default class Point {
|
||||
public x: number = 0;
|
||||
public y: number = 0;
|
||||
|
||||
public constructor(x: number = 0, y: number = 0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/road/Point.ts.meta
Normal file
11
assets/script/game/map/view/map/road/Point.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "520e470b-8810-4f2d-8444-cd2446965b49",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
186
assets/script/game/map/view/map/road/RoadNode.ts
Normal file
186
assets/script/game/map/view/map/road/RoadNode.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
export default class RoadNode {
|
||||
private _px: number;//像素坐标x轴
|
||||
private _py: number;//像素坐标y轴
|
||||
private _cx: number;//世界坐标x轴
|
||||
private _cy: number;//世界坐标y轴
|
||||
private _dx: number;//直角坐标x轴
|
||||
private _dy: number;//直角坐标y轴
|
||||
private _value: number = 0;//节点的值
|
||||
private _f: number = 0; //路点的f值
|
||||
private _g: number = 0; //路点的g值
|
||||
private _h: number = 0; //路点的h值
|
||||
private _parent: RoadNode = null; //路点的父节点
|
||||
|
||||
|
||||
//-------------二堆叉存储结构-----------------
|
||||
private _treeParent: RoadNode = null; //二堆叉结构的父节点
|
||||
|
||||
private _left: RoadNode = null; //二堆叉结构的左子节点
|
||||
|
||||
private _right: RoadNode = null; //二堆叉结构的右子节点
|
||||
|
||||
private _openTag: number = 0; //是否在开启列表标记
|
||||
|
||||
private _closeTag: number = 0; //是否在关闭列表标记
|
||||
|
||||
/**
|
||||
* 重置二叉堆存储信息
|
||||
*/
|
||||
public resetTree() {
|
||||
this._treeParent = null;
|
||||
this._left = null;
|
||||
this._right = null;
|
||||
}
|
||||
|
||||
public toString(): String {
|
||||
return "路点像素坐标:(" + this._px + "," + this._py + "), " +
|
||||
"路点世界坐标:(" + this._cx + "," + this._cy + "), " +
|
||||
"路点平面直角坐标:(" + this._dx + "," + this._dy + ")";
|
||||
}
|
||||
|
||||
public get px(): number {
|
||||
return this._px;
|
||||
}
|
||||
|
||||
public set px(value: number) {
|
||||
this._px = value;
|
||||
}
|
||||
|
||||
public get py(): number {
|
||||
return this._py;
|
||||
}
|
||||
|
||||
public set py(value: number) {
|
||||
this._py = value;
|
||||
}
|
||||
|
||||
public get cx(): number {
|
||||
return this._cx;
|
||||
}
|
||||
|
||||
public set cx(value: number) {
|
||||
this._cx = value;
|
||||
}
|
||||
|
||||
public get cy(): number {
|
||||
return this._cy;
|
||||
}
|
||||
|
||||
public set cy(value: number) {
|
||||
this._cy = value;
|
||||
}
|
||||
|
||||
public get dx(): number {
|
||||
return this._dx;
|
||||
}
|
||||
|
||||
public set dx(value: number) {
|
||||
this._dx = value;
|
||||
}
|
||||
|
||||
public get dy(): number {
|
||||
return this._dy;
|
||||
}
|
||||
|
||||
public set dy(value: number) {
|
||||
this._dy = value;
|
||||
}
|
||||
|
||||
public get value(): number {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
public set value(val: number) {
|
||||
this._value = val;
|
||||
}
|
||||
|
||||
public get f(): number {
|
||||
return this._f;
|
||||
}
|
||||
|
||||
public set f(value: number) {
|
||||
this._f = value;
|
||||
}
|
||||
|
||||
public get g(): number {
|
||||
return this._g;
|
||||
}
|
||||
|
||||
public set g(value: number) {
|
||||
this._g = value;
|
||||
}
|
||||
|
||||
public get h(): number {
|
||||
return this._h;
|
||||
}
|
||||
|
||||
public set h(value: number) {
|
||||
this._h = value;
|
||||
}
|
||||
|
||||
public get parent(): RoadNode {
|
||||
return this._parent;
|
||||
}
|
||||
|
||||
public set parent(value: RoadNode) {
|
||||
this._parent = value;
|
||||
}
|
||||
|
||||
|
||||
//-------------二堆叉存储结构-----------------
|
||||
|
||||
/**
|
||||
* 二堆叉结构的父节点
|
||||
*/
|
||||
public get treeParent(): RoadNode {
|
||||
return this._treeParent;
|
||||
}
|
||||
|
||||
public set treeParent(value: RoadNode) {
|
||||
this._treeParent = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 二堆叉结构的左子节点
|
||||
*/
|
||||
public get left(): RoadNode {
|
||||
return this._left;
|
||||
}
|
||||
|
||||
public set left(value: RoadNode) {
|
||||
this._left = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 二堆叉结构的右子节点
|
||||
*/
|
||||
public get right(): RoadNode {
|
||||
return this._right;
|
||||
}
|
||||
|
||||
public set right(value: RoadNode) {
|
||||
this._right = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在开启列表标记
|
||||
*/
|
||||
public get openTag(): number {
|
||||
return this._openTag;
|
||||
}
|
||||
|
||||
public set openTag(value: number) {
|
||||
this._openTag = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在关闭列表标记
|
||||
*/
|
||||
public get closeTag(): number {
|
||||
return this._closeTag;
|
||||
}
|
||||
|
||||
public set closeTag(value: number) {
|
||||
this._closeTag = value;
|
||||
}
|
||||
}
|
||||
11
assets/script/game/map/view/map/road/RoadNode.ts.meta
Normal file
11
assets/script/game/map/view/map/road/RoadNode.ts.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a55696bb-2934-4388-a1af-182ab13401ef",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"simulateGlobals": []
|
||||
}
|
||||
}
|
||||
18
assets/script/game/map/view/map/road/RoadType.ts
Normal file
18
assets/script/game/map/view/map/road/RoadType.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-08-09 16:43:23
|
||||
* @LastEditTime: 2021-08-09 18:32:54
|
||||
* @LastEditors: Please set LastEditors
|
||||
* @Description: 地形类型
|
||||
* @FilePath: \Game\assets\script\core\libs\map\road\RoadType.ts
|
||||
*/
|
||||
export enum RoadType {
|
||||
/** 标准路 */
|
||||
Road = 0,
|
||||
/** 障碍物 */
|
||||
Obstacle = 1,
|
||||
/** 班透明路 */
|
||||
RoadTransparent = 2,
|
||||
/** 隐藏点 */
|
||||
Hidden = 3
|
||||
}
|
||||
9
assets/script/game/map/view/map/road/RoadType.ts.meta
Normal file
9
assets/script/game/map/view/map/road/RoadType.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "524f315a-8ec1-44fd-95a9-555f0a57a113",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/role.meta
Normal file
12
assets/script/game/role.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "ffdd5a80-e057-4f91-92af-a86e1b26cbc6",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
73
assets/script/game/role/Role.ts
Normal file
73
assets/script/game/role/Role.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-11-18 17:47:56
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 15:43:04
|
||||
*/
|
||||
import { instantiate, Node, Prefab, Vec3 } from "cc";
|
||||
import { UICallbacks } from "../../../../extensions/oops-plugin-framework/assets/core/gui/layer/Defines";
|
||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { UIID } from "../common/config/GameUIConfig";
|
||||
import { smc } from "../common/SingletonModuleComp";
|
||||
import Charactor from "../map/view/map/charactor/Charactor";
|
||||
import { RoleModelComp } from "./model/RoleModelComp";
|
||||
import { RoleSpine } from "./view/RoleSpine";
|
||||
import { RoleViewComp } from "./view/RoleViewComp";
|
||||
import { RoleViewUIControllerComp } from "./view/RoleViewUIControllerComp";
|
||||
|
||||
/** 角色实体 */
|
||||
@ecs.register(`Role`)
|
||||
export class Role extends ecs.Entity {
|
||||
// 数据层
|
||||
RoleModel!: RoleModelComp;
|
||||
// 视图层
|
||||
RoleView!: RoleViewComp;
|
||||
RoleViewUIController!: RoleViewUIControllerComp;
|
||||
|
||||
protected init() {
|
||||
this.addComponents<ecs.Comp>(
|
||||
RoleModelComp);
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
this.remove(RoleViewComp);
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/** 加载角色 */
|
||||
load(pos: Vec3 = Vec3.ZERO, isOwn: boolean = false) {
|
||||
var path = isOwn ? "game/player/own" : "game/player/player";
|
||||
|
||||
var prefab: Prefab = oops.res.get(path, Prefab)!;
|
||||
var node = instantiate(prefab);
|
||||
var scene = smc.map.MapView.scene;
|
||||
node.parent = scene.entityLayer!.node!;
|
||||
node.setPosition(pos)
|
||||
var mv = node.getComponent(RoleViewComp)!;
|
||||
this.add(mv);
|
||||
|
||||
|
||||
var as = node.getComponent(RoleSpine);
|
||||
// as.setPlayer(pos);
|
||||
|
||||
if (isOwn) {
|
||||
smc.map.MapView.scene.setPlayer(node.getComponent(Charactor));
|
||||
}
|
||||
}
|
||||
|
||||
/** 摇撼控制 */
|
||||
loadJoystick() {
|
||||
var uic: UICallbacks = {
|
||||
onAdded: (node: Node, params: any) => {
|
||||
var comp = node.getComponent(RoleViewUIControllerComp) as ecs.Comp;
|
||||
this.add(comp);
|
||||
}
|
||||
};
|
||||
oops.gui.open(UIID.Role_Controller, null, uic);
|
||||
}
|
||||
removeJoystick() {
|
||||
oops.gui.remove(UIID.Role_Controller);
|
||||
}
|
||||
}
|
||||
9
assets/script/game/role/Role.ts.meta
Normal file
9
assets/script/game/role/Role.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "deb5a90b-5729-4a03-9f73-28ed96202f8a",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
4
assets/script/game/role/RoleEvent.ts
Normal file
4
assets/script/game/role/RoleEvent.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/** 角色模块全局事件 */
|
||||
export enum RoleEvent {
|
||||
|
||||
}
|
||||
9
assets/script/game/role/RoleEvent.ts.meta
Normal file
9
assets/script/game/role/RoleEvent.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a2e7abd7-21aa-4dfc-ab5c-6dd0dfba2a7c",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/role/bll.meta
Normal file
12
assets/script/game/role/bll.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "8164d96e-0467-4bd2-9123-8a490de8c68f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
9
assets/script/game/role/bll/RoleBattle.ts.meta
Normal file
9
assets/script/game/role/bll/RoleBattle.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "5130ca90-66bd-4c87-8db9-f9f847396454",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/role/bll/action.meta
Normal file
12
assets/script/game/role/bll/action.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "52966ec2-355b-4c89-a608-5d5f34ba8ae9",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
12
assets/script/game/role/bll/ai.meta
Normal file
12
assets/script/game/role/bll/ai.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "7bde0e45-7d4e-4cf5-b0ce-f8b6a5ca4d12",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
12
assets/script/game/role/bll/skill.meta
Normal file
12
assets/script/game/role/bll/skill.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "20fb6abb-3b0e-4361-8200-941b98891456",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
12
assets/script/game/role/model.meta
Normal file
12
assets/script/game/role/model.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "3fba28ee-42f7-4be0-a42d-776301b37fbc",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "2fc06e2a-6834-4ce6-9a7b-96eae66f0abe",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "d299c6b5-6424-4c27-ab35-013e8ad0c433",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1ca33287-9c39-44a8-b8dd-c6e0c21dd8a7",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
18
assets/script/game/role/model/RoleEnum.ts
Normal file
18
assets/script/game/role/model/RoleEnum.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-01-26 14:14:34
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-01-27 15:49:36
|
||||
*/
|
||||
|
||||
/** 角色动作名 */
|
||||
export enum RoleAnimatorType {
|
||||
/** 待机 */
|
||||
Idle = "Idle",
|
||||
/** 攻击 */
|
||||
Attack = "Attack",
|
||||
/** 受击 */
|
||||
Hurt = "Hurt",
|
||||
/** 死亡 */
|
||||
Dead = "Dead"
|
||||
}
|
||||
9
assets/script/game/role/model/RoleEnum.ts.meta
Normal file
9
assets/script/game/role/model/RoleEnum.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "a8fd6149-fa4b-4b2c-83c0-c08b3813b9f7",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/script/game/role/model/RoleEquipModelComp.ts.meta
Normal file
9
assets/script/game/role/model/RoleEquipModelComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "5c21f8a7-8fd1-4845-a777-a2e03256526b",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "b53c6b75-188b-46ae-93a9-4c1ecd6009c8",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
27
assets/script/game/role/model/RoleModelComp.ts
Normal file
27
assets/script/game/role/model/RoleModelComp.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2021-11-18 15:56:01
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-17 13:43:25
|
||||
*/
|
||||
import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
|
||||
/**
|
||||
* 角色属性数据
|
||||
*/
|
||||
@ecs.register('RoleModel')
|
||||
export class RoleModelComp extends ecs.Comp {
|
||||
/** 角色编号 */
|
||||
id: number = -1;
|
||||
|
||||
/** 角色名 */
|
||||
name: string = "oops-framework";
|
||||
|
||||
/** 动画名资源 */
|
||||
anim: string = "model1";
|
||||
|
||||
reset() {
|
||||
this.id = -1;
|
||||
this.name = "";
|
||||
}
|
||||
}
|
||||
9
assets/script/game/role/model/RoleModelComp.ts.meta
Normal file
9
assets/script/game/role/model/RoleModelComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "0b31330a-261d-4b13-a0d5-15d2727b1dbd",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "58956230-0127-4793-ad43-621ceedb7d25",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
9
assets/script/game/role/model/RoleSkillModelComp.ts.meta
Normal file
9
assets/script/game/role/model/RoleSkillModelComp.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "25e1a634-f8fe-44ca-9650-0d287532b566",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
12
assets/script/game/role/view.meta
Normal file
12
assets/script/game/role/view.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ver": "1.2.0",
|
||||
"importer": "directory",
|
||||
"imported": true,
|
||||
"uuid": "b6c9dfb2-45d4-485c-8d0e-55a7f98e324e",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {
|
||||
"compressionType": {},
|
||||
"isRemoteBundle": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "71fe316b-1691-4a24-b0b8-8c6e88938401",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
95
assets/script/game/role/view/RoleSpine.ts
Normal file
95
assets/script/game/role/view/RoleSpine.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-08-04 15:08:35
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 15:26:26
|
||||
*/
|
||||
import { Color, Component, EventTouch, sp, Vec3, _decorator } from "cc";
|
||||
import { LayerUtil } from "../../../../../extensions/oops-plugin-framework/assets/core/utils/LayerUtil";
|
||||
import { smc } from "../../common/SingletonModuleComp";
|
||||
import Charactor, { CharactorDirection, CharactorState } from "../../map/view/map/charactor/Charactor";
|
||||
import { ICharactorClip } from "../../map/view/map/charactor/ICharactorClip";
|
||||
import RoleSpineAnimator from "./RoleSpineAnimator";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* RPG SPINE角色模型
|
||||
*/
|
||||
@ccclass('RoleSpine')
|
||||
export class RoleSpine extends Component implements ICharactorClip {
|
||||
@property({ type: RoleSpineAnimator, tooltip: '动画控制器' })
|
||||
animator: RoleSpineAnimator = null!;
|
||||
|
||||
private spine!: sp.Skeleton;
|
||||
private charactor!: Charactor;
|
||||
|
||||
onLoad() {
|
||||
// 角色控制组件
|
||||
this.charactor = this.addComponent(Charactor)!;
|
||||
|
||||
this.initAnimator();
|
||||
|
||||
LayerUtil.setNodeLayer(LayerUtil.MAP, this.node);
|
||||
}
|
||||
|
||||
/** 初始化动画 */
|
||||
protected initAnimator() {
|
||||
this.spine = this.animator.getComponent(sp.Skeleton)!;
|
||||
}
|
||||
|
||||
setPlayer(pos: Vec3) {
|
||||
// var scene = smc.map.MapView.scene;
|
||||
// this.node.parent = scene.entityLayer!.node!;
|
||||
// this.charactor.clip = this;
|
||||
// this.charactor.sceneMap = scene;
|
||||
this.charactor.pos = pos;
|
||||
this.charactor.updateZIndex();
|
||||
}
|
||||
|
||||
setDirection(value: CharactorDirection): void {
|
||||
if (value > 4) {
|
||||
this.animator!.node.setScale(-1, 1, 1);
|
||||
}
|
||||
else {
|
||||
this.animator!.node.setScale(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
setState(value: CharactorState): void {
|
||||
switch (value) {
|
||||
case CharactorState.Idle:
|
||||
this.idle();
|
||||
break;
|
||||
case CharactorState.Run:
|
||||
this.walk();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setAlpha(value: number): void {
|
||||
var color: Color = this.spine.color;
|
||||
color.a = 255 * (value / 1);
|
||||
this.spine.color = color;
|
||||
}
|
||||
|
||||
setPos(value: Vec3): void {
|
||||
this.node.position = value;
|
||||
}
|
||||
|
||||
checkTouch(event: EventTouch): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
this.node.destroy();
|
||||
}
|
||||
|
||||
walk() {
|
||||
this.animator!.setNumber("Speed", 1);
|
||||
}
|
||||
|
||||
idle() {
|
||||
this.animator!.setNumber("Speed", 0);
|
||||
}
|
||||
}
|
||||
9
assets/script/game/role/view/RoleSpine.ts.meta
Normal file
9
assets/script/game/role/view/RoleSpine.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "9b5610bf-dad3-4695-bb64-92006701ea56",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
72
assets/script/game/role/view/RoleSpineAnimator.ts
Normal file
72
assets/script/game/role/view/RoleSpineAnimator.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-08-04 15:08:35
|
||||
* @LastEditors: dgflash
|
||||
* @LastEditTime: 2022-08-04 15:26:38
|
||||
*/
|
||||
import { sp, _decorator } from "cc";
|
||||
import AnimatorSpine from "../../../../../extensions/oops-plugin-framework/assets/libs/animator/AnimatorSpine";
|
||||
import Charactor, { CharactorDirection } from "../../map/view/map/charactor/Charactor";
|
||||
|
||||
const { ccclass, property, requireComponent, disallowMultiple } = _decorator;
|
||||
|
||||
/**
|
||||
* Spine状态机组件(主状态机),trackIndex为0
|
||||
*/
|
||||
@ccclass
|
||||
@disallowMultiple
|
||||
@requireComponent(sp.Skeleton)
|
||||
export default class RoleSpineAnimator extends AnimatorSpine {
|
||||
private charactor!: Charactor;
|
||||
private dir: CharactorDirection = CharactorDirection.bottom;
|
||||
private animName: string = "Stand";
|
||||
private loop: boolean = true;
|
||||
|
||||
start() {
|
||||
this.charactor = this.node.parent!.getComponent(Charactor)!;
|
||||
super.start();
|
||||
}
|
||||
|
||||
lateUpdate(dt: number) {
|
||||
if (this.dir != this.charactor.direction) {
|
||||
this.dir = this.charactor.direction;
|
||||
this.playAnimation(this.animName, this.loop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放动画
|
||||
* @override
|
||||
* @param animName 动画名
|
||||
* @param loop 是否循环播放
|
||||
*/
|
||||
protected playAnimation(animName: string, loop: boolean) {
|
||||
if (animName) {
|
||||
this.animName = animName;
|
||||
this.loop = loop;
|
||||
|
||||
animName = `huaxian/${this.getDirection(this.charactor.direction)}${animName}`;
|
||||
this._spine.setAnimation(0, animName, loop);
|
||||
}
|
||||
else {
|
||||
this._spine.clearTrack(0);
|
||||
}
|
||||
}
|
||||
|
||||
private getDirection(dir: CharactorDirection): string {
|
||||
let dirName = "";
|
||||
if (dir == CharactorDirection.up) {
|
||||
dirName = "back";
|
||||
}
|
||||
else if (dir == CharactorDirection.bottom) {
|
||||
dirName = "positive";
|
||||
}
|
||||
else if (dir == CharactorDirection.left || dir == CharactorDirection.left_up || dir == CharactorDirection.left_bottom) {
|
||||
dirName = "side";
|
||||
}
|
||||
else if (dir == CharactorDirection.right || dir == CharactorDirection.right_up || dir == CharactorDirection.right_bottom) {
|
||||
dirName = "side";
|
||||
}
|
||||
return dirName;
|
||||
}
|
||||
}
|
||||
9
assets/script/game/role/view/RoleSpineAnimator.ts.meta
Normal file
9
assets/script/game/role/view/RoleSpineAnimator.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "eb846c27-0bd3-4d9c-8261-e6ed8ac379a3",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user