| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- import { _decorator, Asset, Collider, Collider2D, Component, Contact2DType, RigidBody2D, sp, Tween, tween, Vec2, Vec3 } from 'cc';
- import { endPos } from '../../../ui/main/UI_Main';
- import { LvData } from '../../LvData/LvData';
- const { ccclass, property } = _decorator;
- export enum CollisionGroups {
- DEFAULT = 0,
- wall = 1,//墙
- role = 2,//人
- stone = 3,//石头
- push = 4,//推墙
- block = 5//方块
- }
- @ccclass('Role')
- export class Role extends Component {
- spin: sp.Skeleton;
- speed = 5;
- roleBady
- roleNode
- currentState: 'normal' | 'ku' = 'normal';
- private elapsedTime: number = 0;
- @property([sp.SkeletonData])
- private SkeletonData: sp.SkeletonData[] = [];
- private spineSkeleton: sp.Skeleton = null;
- reviveMoveDistance: number = 200; // 复活移动距离
- reviveMoveDuration: number = 1; // 移动持续时间
- // 新增:记录上一帧的位置
- private lastPosition: Vec3 = new Vec3();
- // 新增:记录是否处于异常移动状态
- private isAbnormalMovement: boolean = false;
- // 新增:异常移动计数器
- private abnormalCounter: number = 0;
- async start() {
- // 记录初始位置
- this.lastPosition = this.node.position.clone();
- this.spin = this.getComponent(sp.Skeleton);
- this.roleBady = this.getComponent(RigidBody2D)
- this.roleNode = this.getComponent(Collider2D);
- if (this.roleNode) {
- this.roleBady.enabledContactListener = true;
- this.roleNode.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
- this.roleNode.on(Contact2DType.END_CONTACT, this.onEndContact, this);
- }
- this.spineSkeleton = this.node.getComponent(sp.Skeleton);
- let skinId = LvData.instance.rwpf;
- this.changeSkin(skinId);
- this.startAnimationSequence();
- }
-
- public async reviveMove() {
- // 停止当前所有动作
- Tween.stopAllByTarget(this.node);
- this.elapsedTime = 0;
- this.currentState = 'normal';
- this.isAbnormalMovement = false;
- this.abnormalCounter = 0;
-
- this.roleBady.enabledContactListener = true;
- this.roleBady.enabled = true;
-
- // 获取当前位置并应用位置限制
- const startPos = this.node.position.clone();
- startPos.x = Math.min(startPos.x, 110); // 确保起始位置不越界
- startPos.y = Math.min(startPos.y, 135); // 确保起始位置不越界
- this.node.position = startPos; // 立即应用限制
-
- // 计算目标位置(带边界限制)
- const targetPos = startPos.clone();
- targetPos.x += this.reviveMoveDistance;
-
- // 应用位置限制(确保目标位置不超过110,135)
- targetPos.x = Math.min(targetPos.x, 110);
- targetPos.y = Math.min(targetPos.y, 135);
-
- // 执行移动动画
- await new Promise<void>((resolve) => {
- tween(this.node)
- .to(this.reviveMoveDuration,
- { position: targetPos },
- {
- easing: 'linear',
- // 添加每帧位置限制(可选,根据实际需求决定)
- onUpdate: (target: any, ratio: number) => {
- const pos = this.node.position;
- const newPos = new Vec3(
- Math.min(pos.x, 110),
- Math.min(pos.y, 135),
- pos.z
- );
- this.node.setPosition(newPos);
- }
- }
- )
- .call(() => {
- // 最终位置确认(防止浮点误差)
- const finalPos = new Vec3(
- Math.min(this.node.position.x, 110),
- Math.min(this.node.position.y, 135),
- this.node.position.z
- );
- this.node.setPosition(finalPos);
- // 恢复角色动画
- this.doXianJie();
- resolve();
- })
- .start();
- });
-
- this.roleBady.enabledContactListener = true;
- }
- onBeginContact(other: Collider2D, self: Collider2D) {
- if (other.group === (1 << CollisionGroups.stone)) {
- this.doPush();
- }
- }
- public changeSkin(newSkinId: number): void {
- if (newSkinId - 1 >= 0 && newSkinId - 1 < this.SkeletonData.length) {
- this.spineSkeleton.skeletonData = this.SkeletonData[newSkinId - 1]
- this.spineSkeleton.setAnimation(0, "anim_xuixi", true);
- }
- else {
- console.error("骨骼资源索引l越界")
- }
- }
- init(time) {
- if (!time) {
- time = 1
- }
- let s = this.node.position.clone().subtract(endPos.role).length()
- this.speed = s / time
- }
- doMove(dt: number) {
- // debugger
- // 忽略无效帧时间
- if (dt <= 0) return;
- // 计算剩余距离和剩余时间
- const remainingDistance = Math.max(0, this.node.position.x - endPos.role.x);
- const remainingTime = Math.max(0, endPos.time - this.elapsedTime);
- // 动态调整速度(避免除零)
- const dynamicSpeed = remainingTime > 0 ? remainingDistance / remainingTime : 0;
- const move = dynamicSpeed * dt
- // 记录当前位置
- const currentPos = this.node.position.clone();
- // 检查是否出现异常移动
- if (this.lastPosition.x > currentPos.x && this.speed > 0) {
- this.abnormalCounter++;
- if (this.abnormalCounter > 3) {
- this.isAbnormalMovement = true;
- // 尝试重置物理状态
- this.roleBady.linearVelocity = new Vec2(0, 0);
- this.roleBady.angularVelocity = 0;
- }
- } else {
- this.abnormalCounter = 0;
- this.isAbnormalMovement = false;
- }
- // 正常移动逻辑
- if (!this.isAbnormalMovement) {
- this.node.setPosition(this.node.position.x - move, this.node.position.y);
- } else {
- this.node.setPosition(this.node.position.x - move * 1.5, this.node.position.y);
- // 短暂禁用碰撞检测以尝试解决卡住问题
- this.roleBady.enabledContactListener = false;
- setTimeout(() => {
- this.roleBady.enabledContactListener = true;
- }, 500);
- }
- // 更新上一帧位置
- this.lastPosition = this.node.position.clone();
- //console.log("角色位置: " + this.node.position.x);
- }
- onEndContact() {
- // 重置异常状态
- this.abnormalCounter = 0;
- this.isAbnormalMovement = false;
- }
- startAnimationSequence() {
- this.doRelex();
- }
- roleDie() {
- if (this.node.position.x < endPos.role.x) {
- // 禁用物理组件
- this.roleBady.enabledContactListener = false;
- //this.roleBady.enabled = false;
- // 播放死亡动画
- this.spin.loop = false;
- this.spin.animation = 'ku';
- }
- }
- doDie() {
- this.spin.animation = 'anim_ku';
- this.spin.loop = false; // 只播放一次
- this.spin.setCompleteListener(() => {
- });
- }
- doPush() {
- this.spin.animation = 'anim_tui';
- this.spin.loop = true; // 持续循环推动动画
- }
- doRelex() {
- this.currentState = 'normal';
- this.spin.animation = 'anim_xuixi';
- this.spin.loop = false; // 不循环
- this.spin.setCompleteListener(() => {
- this.doXianJie(); // 休息完成后接衔接动画
- });
- }
- doXianJie() {
- this.spin.animation = 'anim_xianjie';
- this.spin.loop = false; // 不循环
- this.spin.setCompleteListener(() => {
- this.doPush(); // 衔接完成后进入持续推动状态
- });
- }
- doFlose() {
- this.spin.animation = 'anim_f'
- this.spin.loop = true;
- this.spin.setCompleteListener(() => {
- this.doPush()
- })
- }
- doWin() {
- this.spin.animation = 'anim_v'
- this.spin.loop = true;
- this.spin.setCompleteListener(() => {
- this.doPush()
- })
- }
- doJieMian() {
- this.spin.animation = "anim_jiemian"
- this.spin.loop = true;
- }
- update(deltaTime: number) {
- // 正常移动逻辑
- this.doMove(deltaTime);
- // 时间累计检测
- if (this.currentState === 'normal') {
- this.elapsedTime += deltaTime;
- // 当剩余时间不足30秒时触发
- if (endPos.time - this.elapsedTime < 30) {
- this.currentState = 'ku';
- this.doDie(); // 切换到哭泣动画
- }
- }
- }
- }
|