feat: 支持道具、攻击特效

This commit is contained in:
richarjiang
2025-10-10 10:06:55 +08:00
parent cce130755c
commit d6d612949e
241 changed files with 16480 additions and 1285 deletions

View File

@@ -1,7 +1,11 @@
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource, Sprite, director } from 'cc';
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource, Sprite, director, PhysicsSystem2D, EPhysics2DDrawFlags } from 'cc';
import { TiledMapPathfinder } from './TiledMapPathfinder';
const { ccclass, property } = _decorator;
// PhysicsSystem2D.instance.debugDrawFlags =
// EPhysics2DDrawFlags.Aabb |
// EPhysics2DDrawFlags.Shape;
@ccclass('PlayerController')
export class PlayerController extends Component {
@property(Canvas)
@@ -38,10 +42,10 @@ export class PlayerController extends Component {
mapHeight: number = 2560; // 地图高度
@property({ tooltip: '玩家与怪物进入战斗时的理想距离' })
attackPreferredDistance: number = 80;
attackPreferredDistance: number = 10;
@property({ tooltip: '允许的距离误差范围,超出后会进行位置调整' })
attackDistanceTolerance: number = 20;
attackDistanceTolerance: number = 10;
private isMoving: boolean = false;
private isAttacking: boolean = false;
@@ -273,8 +277,8 @@ export class PlayerController extends Component {
// 限制位置
const clampedPosition = position.clone();
clampedPosition.x = Math.max(-mapHalfWidth, Math.min(mapHalfWidth, position.x));
clampedPosition.y = Math.max(-mapHalfHeight, Math.min(mapHalfHeight, position.y));
// clampedPosition.x = Math.max(-mapHalfWidth, Math.min(mapHalfWidth, position.x));
// clampedPosition.y = Math.max(-mapHalfHeight, Math.min(mapHalfHeight, position.y));
return clampedPosition;
}
@@ -422,6 +426,8 @@ export class PlayerController extends Component {
console.log('碰撞检测', selfCollider.node.name, otherCollider.node.name);
if (otherCollider.node.name.startsWith('guai_')) {
this.handleAttack(otherCollider);
} else if (otherCollider.node.name.startsWith('box_')) {
this.handleBoxCollision(otherCollider);
}
}
@@ -439,9 +445,9 @@ export class PlayerController extends Component {
this.stopMovement();
this.scheduleOnce(() => {
this.adjustPositionsForAttack(otherCollider.node);
}, 0);
// this.scheduleOnce(() => {
// this.adjustPositionsForAttack(otherCollider.node);
// }, 0);
@@ -483,14 +489,20 @@ export class PlayerController extends Component {
if (monsterAnimation) {
monsterAnimation.play(`${otherCollider.node.name}_attack`);
}
// this.switchAnimation(this.currentDirection === 3 ? 'attack3' : 'attack5');
this.switchAnimation('attack3');
this.switchAnimation(this.currentDirection === 3 ? 'attack3' : 'attack5');
// this.switchAnimation('attack3');
// 1.2秒后判定攻击结果
this.scheduleOnce(async () => {
// 比较生命值,判断输赢
console.log('判定攻击结果玩家HP:', playerHp, '怪物HP:', monsterHp);
if (playerHp >= monsterHp) {
const hit = otherCollider.node.getChildByName('Hit')
if (hit) {
hit.active = true;
}
this.hasWinTimes++
// 玩家获胜
console.log('玩家获胜!更新玩家生命值为:', playerHp + monsterHp);
@@ -519,7 +531,7 @@ export class PlayerController extends Component {
otherCollider.node?.destroy();
if (this.hasWinTimes === 10) {
if (this.hasWinTimes === 7) {
this.isWin = true
this.showBonusPopup()
}
@@ -570,6 +582,65 @@ export class PlayerController extends Component {
}, 1.2);
}
private handleBoxCollision(otherCollider: Collider2D) {
if (!this.player) {
return;
}
const boxNode = otherCollider.node;
if (!boxNode || !boxNode.isValid) {
return;
}
// 防止重复触发
otherCollider.enabled = false;
const playerHpNode = this.player.getChildByName('hp');
const boxHpNode = boxNode.getChildByName('hp');
if (!playerHpNode || !boxHpNode) {
console.warn('未找到玩家或宝箱的hp节点', playerHpNode, boxHpNode);
return;
}
const playerLabel = playerHpNode.getComponent(Label);
const boxLabel = boxHpNode.getComponent(Label);
if (!playerLabel || !boxLabel) {
console.warn('未找到玩家或宝箱的hp标签组件');
return;
}
const rewardValue = parseInt(boxLabel.string) || 0;
const animNode = boxNode.getChildByName('Anim');
const animation = animNode ? animNode.getComponent(Animation) : null;
const finalizeBoxOpen = () => {
if (!playerLabel.isValid) {
return;
}
const currentPlayerHp = parseInt(playerLabel.string) || 0;
const updatedPlayerHp = currentPlayerHp + rewardValue;
playerLabel.string = updatedPlayerHp.toString();
this.playLabelEmphasisAnimation(playerLabel);
if (boxNode && boxNode.isValid) {
boxNode.destroy();
}
};
if (animation) {
animation.play('open');
animation.once(Animation.EventType.FINISHED, () => {
finalizeBoxOpen();
});
} else {
finalizeBoxOpen();
}
}
private adjustPositionsForAttack(monsterNode: Node) {
if (!this.player || !monsterNode) {
return;