feat: 为英雄和怪物添加下落入场动画
- 在 MissionHeroComp 和 MissionMonComp 中定义下落高度常量 - 修改英雄和怪物的加载方法,接受目标落地高度参数 - 使用 Tween 实现平滑下落动画,下落距离越大持续时间越长 - 下落期间禁用移动和碰撞器,落地后恢复 - 为怪物添加随机下落高度偏移,减轻重叠感
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D} from "cc";
|
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D, tween, Tween} from "cc";
|
||||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
@@ -39,7 +39,7 @@ export class Hero extends ecs.Entity {
|
|||||||
|
|
||||||
|
|
||||||
/** 加载角色 */
|
/** 加载角色 */
|
||||||
load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001) {
|
load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001, dropToY:number = pos.y) {
|
||||||
scale = 1
|
scale = 1
|
||||||
// 查找空闲英雄槽位
|
// 查找空闲英雄槽位
|
||||||
let size=1
|
let size=1
|
||||||
@@ -95,7 +95,24 @@ export class Hero extends ecs.Entity {
|
|||||||
const move = this.get(MoveComp);
|
const move = this.get(MoveComp);
|
||||||
move.direction = 1; // 向右移动
|
move.direction = 1; // 向右移动
|
||||||
move.targetX = resolveFormationTargetX(model.fac, model.type);
|
move.targetX = resolveFormationTargetX(model.fac, model.type);
|
||||||
move.baseY = pos.y;
|
move.baseY = dropToY;
|
||||||
|
move.moving = false;
|
||||||
|
const dropDistance = Math.abs(pos.y - dropToY);
|
||||||
|
const dropDuration = Math.max(0.18, Math.min(0.38, dropDistance / 1200));
|
||||||
|
Tween.stopAllByTarget(node);
|
||||||
|
tween(node)
|
||||||
|
.to(dropDuration, { position: v3(pos.x, dropToY, 0) })
|
||||||
|
.call(() => {
|
||||||
|
if (!node || !node.isValid) return;
|
||||||
|
node.setPosition(pos.x, dropToY, 0);
|
||||||
|
move.moving = true;
|
||||||
|
if (collider) {
|
||||||
|
collider.enabled = true;
|
||||||
|
collider.group = BoxSet.HERO;
|
||||||
|
collider.apply();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
smc.vmdata.mission_data.hero_num++
|
smc.vmdata.mission_data.hero_num++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D, NodePool} from "cc";
|
import { instantiate, Node, Prefab, Vec3 ,v3,resources,SpriteFrame,Sprite,SpriteAtlas, BoxCollider2D, NodePool, tween, Tween} from "cc";
|
||||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
import { smc } from "../common/SingletonModuleComp";
|
||||||
@@ -103,7 +103,7 @@ export class Monster extends ecs.Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 加载角色 */
|
/** 加载角色 */
|
||||||
load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001, is_boss:boolean=false) {
|
load(pos: Vec3 = Vec3.ZERO,scale:number = 1,uuid:number=1001, is_boss:boolean=false, dropToY:number = pos.y) {
|
||||||
scale=-1
|
scale=-1
|
||||||
let size=1
|
let size=1
|
||||||
var scene = smc.map.MapView.scene;
|
var scene = smc.map.MapView.scene;
|
||||||
@@ -120,15 +120,7 @@ export class Monster extends ecs.Entity {
|
|||||||
var view = node.getComponent(HeroViewComp)!;
|
var view = node.getComponent(HeroViewComp)!;
|
||||||
const collider = node.getComponent(BoxCollider2D);
|
const collider = node.getComponent(BoxCollider2D);
|
||||||
if (collider) {
|
if (collider) {
|
||||||
// 先禁用,下一帧启用,确保物理系统能正确注册新激活的节点
|
collider.enabled = false;
|
||||||
collider.enabled = false;
|
|
||||||
view.scheduleOnce(() => {
|
|
||||||
if (node && node.isValid) {
|
|
||||||
collider.enabled = true;
|
|
||||||
collider.group = BoxSet.MONSTER; // 确保碰撞组正确
|
|
||||||
collider.apply(); // 强制应用更改(如果需要)
|
|
||||||
}
|
|
||||||
}, 0); // 0延迟等于下一帧执行
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node.setScale(size*node.scale.x,size*node.scale.y);
|
node.setScale(size*node.scale.x,size*node.scale.y);
|
||||||
@@ -170,7 +162,24 @@ export class Monster extends ecs.Entity {
|
|||||||
move.reset();
|
move.reset();
|
||||||
move.direction = -1; // 向左移动
|
move.direction = -1; // 向左移动
|
||||||
move.targetX = Math.max(-320, Math.min(320, pos.x));
|
move.targetX = Math.max(-320, Math.min(320, pos.x));
|
||||||
move.baseY = pos.y;
|
move.baseY = dropToY;
|
||||||
|
move.moving = false;
|
||||||
|
const dropDistance = Math.abs(pos.y - dropToY);
|
||||||
|
const dropDuration = Math.max(0.18, Math.min(0.38, dropDistance / 1200));
|
||||||
|
Tween.stopAllByTarget(node);
|
||||||
|
tween(node)
|
||||||
|
.to(dropDuration, { position: v3(pos.x, dropToY, 0) })
|
||||||
|
.call(() => {
|
||||||
|
if (!node || !node.isValid) return;
|
||||||
|
node.setPosition(pos.x, dropToY, 0);
|
||||||
|
move.moving = true;
|
||||||
|
if (collider) {
|
||||||
|
collider.enabled = true;
|
||||||
|
collider.group = BoxSet.MONSTER;
|
||||||
|
collider.apply();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.start();
|
||||||
smc.vmdata.mission_data.mon_num++
|
smc.vmdata.mission_data.mon_num++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const { ccclass, property } = _decorator;
|
|||||||
@ccclass('MissionHeroCompComp')
|
@ccclass('MissionHeroCompComp')
|
||||||
@ecs.register('MissionHeroComp', false)
|
@ecs.register('MissionHeroComp', false)
|
||||||
export class MissionHeroCompComp extends CCComp {
|
export class MissionHeroCompComp extends CCComp {
|
||||||
|
private static readonly HERO_DROP_HEIGHT = 260
|
||||||
timer:Timer=new Timer(2)
|
timer:Timer=new Timer(2)
|
||||||
Friend_is_dead:boolean=false
|
Friend_is_dead:boolean=false
|
||||||
current_hero_uuid:number=0
|
current_hero_uuid:number=0
|
||||||
@@ -59,8 +60,9 @@ export class MissionHeroCompComp extends CCComp {
|
|||||||
let hero_pos=0
|
let hero_pos=0
|
||||||
let hero = ecs.getEntity<Hero>(Hero);
|
let hero = ecs.getEntity<Hero>(Hero);
|
||||||
let scale = 1
|
let scale = 1
|
||||||
let pos:Vec3 = HeroPos[hero_pos].pos;
|
let landingPos:Vec3 = HeroPos[hero_pos].pos;
|
||||||
hero.load(pos,scale,uuid);
|
let spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
|
||||||
|
hero.load(spawnPos,scale,uuid,landingPos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,4 +72,4 @@ export class MissionHeroCompComp extends CCComp {
|
|||||||
reset() {
|
reset() {
|
||||||
// this.node.destroy();
|
// this.node.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const { ccclass, property } = _decorator;
|
|||||||
@ecs.register('MissionMonComp', false)
|
@ecs.register('MissionMonComp', false)
|
||||||
export class MissionMonCompComp extends CCComp {
|
export class MissionMonCompComp extends CCComp {
|
||||||
private static readonly BOSS_RENDER_PRIORITY = 1000000;
|
private static readonly BOSS_RENDER_PRIORITY = 1000000;
|
||||||
|
private static readonly MON_DROP_HEIGHT = 300;
|
||||||
@property({ tooltip: "是否启用调试日志" })
|
@property({ tooltip: "是否启用调试日志" })
|
||||||
private debugMode: boolean = false;
|
private debugMode: boolean = false;
|
||||||
|
|
||||||
@@ -195,11 +196,13 @@ export class MissionMonCompComp extends CCComp {
|
|||||||
let mon = ecs.getEntity<Monster>(Monster);
|
let mon = ecs.getEntity<Monster>(Monster);
|
||||||
let scale = -1;
|
let scale = -1;
|
||||||
// 按生成序号做横向错列,减轻重叠感
|
// 按生成序号做横向错列,减轻重叠感
|
||||||
let pos: Vec3 = v3(MonStart.START_X, BoxSet.GAME_LINE, 0);
|
const landingY = BoxSet.GAME_LINE + (isBoss ? 6 : 0);
|
||||||
|
const dropOffset = MissionMonCompComp.MON_DROP_HEIGHT + Math.floor(Math.random() * 40);
|
||||||
|
let pos: Vec3 = v3(MonStart.START_X, landingY + dropOffset, 0);
|
||||||
// 递增全局生成顺序,做溢出保护
|
// 递增全局生成顺序,做溢出保护
|
||||||
this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999;
|
this.globalSpawnOrder = (this.globalSpawnOrder + 1) % 999;
|
||||||
|
|
||||||
mon.load(pos, scale, uuid, isBoss);
|
mon.load(pos, scale, uuid, isBoss, landingY);
|
||||||
const move = mon.get(MoveComp);
|
const move = mon.get(MoveComp);
|
||||||
if (move) {
|
if (move) {
|
||||||
move.spawnOrder = isBoss
|
move.spawnOrder = isBoss
|
||||||
|
|||||||
Reference in New Issue
Block a user