perf: 支持相机运镜
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource } from 'cc';
|
||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource, Sprite } from 'cc';
|
||||
import { TiledMapPathfinder } from './TiledMapPathfinder';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -13,6 +13,9 @@ export class PlayerController extends Component {
|
||||
@property(Node)
|
||||
bonus: Node | null = null;
|
||||
|
||||
@property(Node)
|
||||
bonusWuqi: Node | null = null;
|
||||
|
||||
@property(Camera)
|
||||
camera: Camera | null = null; // 主摄像机
|
||||
|
||||
@@ -49,6 +52,9 @@ export class PlayerController extends Component {
|
||||
private props: Node[] = [];
|
||||
|
||||
private guideNode: Node | null = null;
|
||||
private activePopup: Node | null = null;
|
||||
private activePopupName: string | null = null;
|
||||
private pendingPopupHide: (() => void) | null = null;
|
||||
|
||||
onLoad() {
|
||||
this.guideNode = this.canvas.node.getChildByName('Guide');
|
||||
@@ -65,11 +71,15 @@ export class PlayerController extends Component {
|
||||
|
||||
this.initProps();
|
||||
// this.showBonusPopup()
|
||||
// this.scheduleOnce(() => {
|
||||
// this.showBonusPopup()
|
||||
// }, 5);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
// 移除触摸事件
|
||||
input.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
|
||||
this.clearPopupHideSchedule();
|
||||
}
|
||||
|
||||
start() {
|
||||
@@ -134,6 +144,11 @@ export class PlayerController extends Component {
|
||||
}
|
||||
|
||||
private onTouchStart(event: EventTouch) {
|
||||
if (this.activePopup) {
|
||||
this.hideActivePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.player || !this.camera || !this.pathfinder || this.isAttacking || this.isGameOver || this.isWin) return;
|
||||
|
||||
this.guideNode.active = false;
|
||||
@@ -626,6 +641,7 @@ export class PlayerController extends Component {
|
||||
// 所有动画完成后,播放升级动画并设置升级状态
|
||||
this.playLevelUpAnimation();
|
||||
this.isUpgraded = true;
|
||||
this.showWeaponBonusPopup();
|
||||
console.log('所有道具飞行动画完成,玩家已升级,后续动画将使用升级版本');
|
||||
}
|
||||
|
||||
@@ -663,64 +679,60 @@ export class PlayerController extends Component {
|
||||
* 根据当前镜头位置和正交高度,将奖励节点正确缩放并移动到画面正中间
|
||||
*/
|
||||
public showBonusPopup() {
|
||||
if (!this.bonus || !this.camera || !this.canvas) {
|
||||
console.warn('奖励节点、相机或画布未设置,无法显示奖励弹窗');
|
||||
this.showPopupAtCameraCenter(this.bonus, '奖励弹窗');
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出武器奖励
|
||||
*/
|
||||
public showWeaponBonusPopup() {
|
||||
this.showPopupAtCameraCenter(this.bonusWuqi, '武器奖励');
|
||||
}
|
||||
|
||||
private showPopupAtCameraCenter(popup: Node | null, nameForLog: string) {
|
||||
if (!popup || !this.camera || !this.canvas) {
|
||||
console.warn(`${nameForLog}节点、相机或画布未设置,无法显示${nameForLog}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保奖励节点是激活状态
|
||||
this.bonus.active = true;
|
||||
this.clearPopupHideSchedule();
|
||||
|
||||
popup.active = true;
|
||||
|
||||
// 获取相机位置,相机所在的世界坐标就是当前屏幕的中心
|
||||
const cameraPos = this.camera.node.position;
|
||||
const orthoHeight = this.camera.orthoHeight;
|
||||
|
||||
// 直接将弹窗设置到相机位置(屏幕中心)
|
||||
this.bonus.setPosition(cameraPos.x, cameraPos.y, 0);
|
||||
popup.setPosition(cameraPos.x, cameraPos.y, 0);
|
||||
|
||||
// 计算合适的缩放比例,确保弹窗在不同正交高度下都能正确显示
|
||||
// 基础缩放比例
|
||||
const baseScale = 1.0;
|
||||
|
||||
// 根据正交高度调整缩放,确保弹窗大小合适
|
||||
// 假设标准正交高度为500,以此为基准进行缩放
|
||||
const baseScale = 0.8;
|
||||
const standardOrthoHeight = 500;
|
||||
const scaleRatio = standardOrthoHeight / orthoHeight;
|
||||
const finalScale = baseScale * scaleRatio;
|
||||
|
||||
// 设置奖励节点的缩放
|
||||
this.bonus.setScale(finalScale, finalScale, 1);
|
||||
popup.setScale(finalScale, finalScale, 1);
|
||||
|
||||
// 添加弹窗出现动画
|
||||
this.playBonusPopupAnimation();
|
||||
this.activePopup = popup;
|
||||
this.activePopupName = nameForLog;
|
||||
|
||||
// 监听领取按钮
|
||||
const receiveButton = this.bonus.getChildByName('Receive');
|
||||
const bonusWuqi = this.bonus.getChildByName('BonusWuqi');
|
||||
const bonusAnim = this.bonus.getChildByName('BonusAnim');
|
||||
console.log('this.bonus', this.bonus);
|
||||
if (receiveButton) {
|
||||
receiveButton.on('click', () => {
|
||||
bonusAnim.active = false
|
||||
bonusWuqi.active = true
|
||||
}, this);
|
||||
}
|
||||
this.playPopupAppearAnimation(popup, nameForLog);
|
||||
|
||||
this.pendingPopupHide = () => {
|
||||
this.pendingPopupHide = null;
|
||||
this.hideActivePopup();
|
||||
};
|
||||
|
||||
this.scheduleOnce(this.pendingPopupHide, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放奖励弹窗出现动画
|
||||
*/
|
||||
private playBonusPopupAnimation() {
|
||||
if (!this.bonus) return;
|
||||
private playPopupAppearAnimation(popup: Node, nameForLog: string) {
|
||||
const originalScale = popup.scale.clone();
|
||||
|
||||
// 保存原始缩放
|
||||
const originalScale = this.bonus.scale.clone();
|
||||
popup.setScale(0.1, 0.1, 1);
|
||||
|
||||
// 初始状态设置为很小
|
||||
this.bonus.setScale(0.1, 0.1, 1);
|
||||
|
||||
// 创建弹窗弹出动画
|
||||
tween(this.bonus)
|
||||
tween(popup)
|
||||
.to(0.3, {
|
||||
scale: new Vec3(originalScale.x * 1.2, originalScale.y * 1.2, originalScale.z)
|
||||
}, {
|
||||
@@ -732,7 +744,7 @@ export class PlayerController extends Component {
|
||||
easing: 'sineInOut'
|
||||
})
|
||||
.call(() => {
|
||||
console.log('奖励弹窗显示完成');
|
||||
console.log(`${nameForLog}显示完成`);
|
||||
})
|
||||
.start();
|
||||
}
|
||||
@@ -743,17 +755,52 @@ export class PlayerController extends Component {
|
||||
public hideBonusPopup() {
|
||||
if (!this.bonus) return;
|
||||
|
||||
// 创建弹窗消失动画
|
||||
tween(this.bonus)
|
||||
if (this.activePopup === this.bonus) {
|
||||
this.hideActivePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.bonus.active) return;
|
||||
|
||||
this.hidePopupWithAnimation(this.bonus, '奖励弹窗');
|
||||
}
|
||||
|
||||
private hideActivePopup() {
|
||||
if (!this.activePopup) {
|
||||
return;
|
||||
}
|
||||
|
||||
const popupToHide = this.activePopup;
|
||||
const nameForLog = this.activePopupName || '弹窗';
|
||||
|
||||
this.clearPopupHideSchedule();
|
||||
|
||||
this.activePopup = null;
|
||||
this.activePopupName = null;
|
||||
|
||||
this.hidePopupWithAnimation(popupToHide, nameForLog);
|
||||
}
|
||||
|
||||
private hidePopupWithAnimation(popup: Node, nameForLog: string) {
|
||||
tween(popup).stop();
|
||||
|
||||
tween(popup)
|
||||
.to(0.2, {
|
||||
scale: new Vec3(0.1, 0.1, 1)
|
||||
}, {
|
||||
easing: 'backIn'
|
||||
})
|
||||
.call(() => {
|
||||
this.bonus.active = false;
|
||||
console.log('奖励弹窗已隐藏');
|
||||
popup.active = false;
|
||||
console.log(`${nameForLog}已隐藏`);
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
||||
private clearPopupHideSchedule() {
|
||||
if (this.pendingPopupHide) {
|
||||
this.unschedule(this.pendingPopupHide);
|
||||
this.pendingPopupHide = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user