diff --git a/src/npc/move.ts b/src/npc/move.ts index a1b73e0..29e2670 100644 --- a/src/npc/move.ts +++ b/src/npc/move.ts @@ -1,4 +1,4 @@ -import { NPCState } from '../utils/types' +import { NPCLerpType, NPCState } from '../utils/types' import { NPC } from './npc' @Component('npclerpData') @@ -10,10 +10,12 @@ export class NPCLerpData { totalDuration: number = 0 speed: number[] = [] loop: boolean = false + type: NPCLerpType = NPCLerpType.SMOOTH_PATH //default onFinishCallback?: () => void onReachedPointCallback?: () => void - constructor(path: Vector3[]) { + constructor(path: Vector3[],type:NPCLerpType=NPCLerpType.SMOOTH_PATH) { this.path = path + if(type !== undefined) this.type = type NPCWalkSystem.createAndAddToEngine() } @@ -31,37 +33,87 @@ export class NPCWalkSystem implements ISystem { update(dt: number) { for (let npcE of walkingNPCGroup.entities) { const npc = (npcE as NPC) + //try{ if (npc.state == NPCState.FOLLOWPATH) { let transform = npc.getComponent(Transform) let path = npc.getComponent(NPCLerpData) - if (path.fraction < 1) { + + if(path.type !== undefined && path.type == NPCLerpType.SMOOTH_PATH){ + //stop exactly at each point + if (path.fraction < 1) { + path.fraction += dt * path.speed[path.origin] + + //if fraction goes over 1 push it back to 1? + + transform.position = Vector3.Lerp( + path.path[path.origin], + path.path[path.target], + path.fraction + ) + } else { + path.origin = path.target + path.target += 1 + if (path.target >= path.path.length) { + if (path.loop) { + path.target = 0 + } else { + npc.stopWalking() + if (path.onFinishCallback) { + path.onFinishCallback() + } + path.fraction = 1 + return + } + } else if (path.onReachedPointCallback) { + path.onReachedPointCallback() + } + path.fraction = 0 //starts on this point + transform.lookAt(path.path[path.target]) + } + }else{ + //default follow, smooth but with low FPS could cut corners + //always increment fraction path.fraction += dt * path.speed[path.origin] + + if(path.fraction >= 1){ + path.origin = path.target + const tartInc = Math.max(1,Math.floor( path.fraction )) + path.target += tartInc + if (path.target >= path.path.length) { + if (path.loop) { + path.target = 0 + } else { + //path.target = path.path.length - 1 + npc.stopWalking() + if (path.onFinishCallback) { + path.onFinishCallback() + } + path.fraction = 1 + return + } + } else if (path.onReachedPointCallback) { + path.onReachedPointCallback() + } + path.fraction -= tartInc + //TODO consider lerping look at + if (path.target < path.path.length) { + transform.lookAt(path.path[path.target]) + } + } + } + //if reached target + if (path.target < path.path.length) { transform.position = Vector3.Lerp( path.path[path.origin], path.path[path.target], path.fraction ) - } else { - path.origin = path.target - path.target += 1 - if (path.target >= path.path.length) { - if (path.loop) { - path.target = 0 - } else { - npc.stopWalking() - if (path.onFinishCallback) { - path.onFinishCallback() - } - path.fraction = 1 - return - } - } else if (path.onReachedPointCallback) { - path.onReachedPointCallback() - } - path.fraction = 0 - transform.lookAt(path.path[path.target]) } } + /*}catch(e){ + debugger + log("npc.utils.NPCWalkSystem throw error",e) + }*/ } } diff --git a/src/npc/npc.ts b/src/npc/npc.ts index 4486248..dec0990 100644 --- a/src/npc/npc.ts +++ b/src/npc/npc.ts @@ -62,13 +62,15 @@ export class NPC extends Entity { this.dialog = new DialogWindow( typeof data.portrait === `string` ? { path: data.portrait } : data.portrait, data && data.darkUI ? data.darkUI : false, - data.dialogSound ? data.dialogSound : undefined + data.dialogSound ? data.dialogSound : undefined, + data && data.dialogCustomTheme ? data.dialogCustomTheme : undefined ) } else { this.dialog = new DialogWindow( undefined, data && data.darkUI ? data.darkUI : false, - data && data.dialogSound ? data.dialogSound : undefined + data && data.dialogSound ? data.dialogSound : undefined, + data && data.dialogCustomTheme ? data.dialogCustomTheme : undefined ) } @@ -194,7 +196,7 @@ export class NPC extends Entity { } if (data && data.path) { - this.addComponent(new NPCLerpData(data.path ? data.path : [])) + this.addComponent(new NPCLerpData(data.path ? data.path : [],data.pathLerpType)) this.getComponent(NPCLerpData).loop = true this.followPath() @@ -355,7 +357,7 @@ export class NPC extends Entity { if (!data) { return } - this.addComponent(new NPCLerpData(data.path ? data.path : [])) + this.addComponent(new NPCLerpData(data.path ? data.path : [],data.pathLerpType)) } if (this.faceUser) { diff --git a/src/utils/types.ts b/src/utils/types.ts index a39e6da..4e5f01a 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -135,9 +135,11 @@ export type NPCData = { coolDownDuration?: number hoverText?: string dialogSound?: string + dialogCustomTheme?: Texture walkingAnim?: string walkingSpeed?: number path?: Vector3[] + pathLerpType?: NPCLerpType textBubble?: boolean bubbleHeight?: number noUI?: boolean @@ -165,6 +167,7 @@ export type FollowPathData = { totalDuration?: number speed?: number path?: Vector3[] + pathLerpType?: NPCLerpType onFinishCallback?: () => void onReachedPointCallback?: () => void } @@ -213,3 +216,9 @@ export enum NPCState { FOLLOWPATH = 'followPath' //FOLLOWPLAYER = 'followPlayer' } + + +export enum NPCLerpType { + SMOOTH_PATH = 'smooth', //will follow the path but can cut sharp corners + RIGID_PATH = 'rigid', //will ensure each corner is hit +}