mirror of
https://github.com/genxium/DelayNoMore
synced 2025-10-09 00:26:39 +00:00
Added frame anim compatibility for AttackingCharacter.
This commit is contained in:
@@ -49,54 +49,48 @@ cc.Class({
|
||||
this.animComp = this.effAnimNode.getComponent(dragonBones.ArmatureDisplay);
|
||||
if (!this.animComp) {
|
||||
this.animComp = this.effAnimNode.getComponent(cc.Animation);
|
||||
this.effAnimNode.anchorY = 0.0; // Otherwise the frame anim will show with an incorrect y-offset even if the collider boundaries are all correct!
|
||||
}
|
||||
this.effAnimNode.active = true;
|
||||
},
|
||||
|
||||
updateCharacterAnim(rdfPlayer, prevRdfPlayer, forceAnimSwitch) {
|
||||
if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
||||
const underlyingAnimationCtrl = this.animComp._armature.animation; // ALWAYS use the dragonBones api instead of ccc's wrapper!
|
||||
// Update directions
|
||||
if (this.animComp && this.animComp.node) {
|
||||
if (0 > rdfPlayer.dirX) {
|
||||
this.animComp.node.scaleX = (-1.0);
|
||||
} else if (0 < rdfPlayer.dirX) {
|
||||
this.animComp.node.scaleX = (1.0);
|
||||
}
|
||||
}
|
||||
// As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.characterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation.
|
||||
|
||||
// Update per character state
|
||||
let newCharacterState = rdfPlayer.characterState;
|
||||
const newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
|
||||
const playingAnimName = underlyingAnimationCtrl.lastAnimationName;
|
||||
const isPlaying = underlyingAnimationCtrl.isPlaying;
|
||||
|
||||
// As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.characterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation.
|
||||
// It turns out that "prevRdfPlayer.characterState" is not useful in this function :)
|
||||
if (newAnimName == playingAnimName && window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
|
||||
// No need to interrupt
|
||||
// console.warn(`JoinIndex=${rdfPlayer.joinIndex}, not interrupting ${newAnimName} while the playing anim is also ${playingAnimName}, player rdf changed from: ${null == prevRdfPlayer ? null : JSON.stringify(prevRdfPlayer)}, , to: ${JSON.stringify(rdfPlayer)}`);
|
||||
return;
|
||||
// Update directions
|
||||
if (this.animComp && this.animComp.node) {
|
||||
if (0 > rdfPlayer.dirX) {
|
||||
this.animComp.node.scaleX = (-1.0);
|
||||
} else if (0 < rdfPlayer.dirX) {
|
||||
this.animComp.node.scaleX = (1.0);
|
||||
}
|
||||
this._interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl);
|
||||
}
|
||||
},
|
||||
|
||||
_interruptPlayingAnimAndPlayNewAnimFrame(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl) {
|
||||
if (window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
|
||||
// No "framesToRecover"
|
||||
// console.warn(`JoinIndex=${rdfPlayer.joinIndex}, playing new ${newAnimName} from the beginning: while the playing anim is ${playAnimation}, player rdf changed from: ${null == prevRdfPlayer ? null : JSON.stringify(prevRdfPlayer)}, , to: ${JSON.stringify(rdfPlayer)}`);
|
||||
underlyingAnimationCtrl.gotoAndPlayByFrame(newAnimName, 0, -1);
|
||||
let newCharacterState = rdfPlayer.characterState;
|
||||
const newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
|
||||
let playingAnimName = null;
|
||||
let underlyingAnimationCtrl = null;
|
||||
|
||||
if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
||||
underlyingAnimationCtrl = this.animComp._armature.animation; // ALWAYS use the dragonBones api instead of ccc's wrapper!
|
||||
playingAnimName = underlyingAnimationCtrl.lastAnimationName;
|
||||
} else {
|
||||
underlyingAnimationCtrl = this.animComp.currentClip;
|
||||
playingAnimName = (!underlyingAnimationCtrl ? null : underlyingAnimationCtrl.name);
|
||||
}
|
||||
|
||||
// It turns out that "prevRdfPlayer.characterState" is not useful in this function :)
|
||||
if (newAnimName == playingAnimName && window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
|
||||
// No need to interrupt
|
||||
// console.warn(`JoinIndex=${rdfPlayer.joinIndex}, not interrupting ${newAnimName} while the playing anim is also ${playingAnimName}, player rdf changed from: ${null == prevRdfPlayer ? null : JSON.stringify(prevRdfPlayer)}, , to: ${JSON.stringify(rdfPlayer)}`);
|
||||
return;
|
||||
}
|
||||
const animationData = underlyingAnimationCtrl._animations[newAnimName];
|
||||
let fromAnimFrame = (animationData.frameCount - rdfPlayer.framesToRecover);
|
||||
if (fromAnimFrame > 0) {
|
||||
} else if (fromAnimFrame < 0) {
|
||||
// For Atk1 or Atk2, it's possible that the "meleeBullet.recoveryFrames" is configured to be slightly larger than corresponding animation duration frames
|
||||
fromAnimFrame = 0;
|
||||
|
||||
if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
||||
this._interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl);
|
||||
} else {
|
||||
this._interruptPlayingAnimAndPlayNewAnimFrameAnim(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName);
|
||||
}
|
||||
underlyingAnimationCtrl.gotoAndPlayByFrame(newAnimName, fromAnimFrame, 1);
|
||||
},
|
||||
|
||||
_interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl) {
|
||||
@@ -107,12 +101,29 @@ cc.Class({
|
||||
} else {
|
||||
const animationData = underlyingAnimationCtrl._animations[newAnimName];
|
||||
let fromAnimFrame = (animationData.frameCount - rdfPlayer.framesToRecover);
|
||||
if (fromAnimFrame > 0) {
|
||||
} else if (fromAnimFrame < 0) {
|
||||
if (fromAnimFrame < 0) {
|
||||
// For Atk1 or Atk2, it's possible that the "meleeBullet.recoveryFrames" is configured to be slightly larger than corresponding animation duration frames
|
||||
fromAnimFrame = 0;
|
||||
}
|
||||
underlyingAnimationCtrl.gotoAndPlayByFrame(newAnimName, fromAnimFrame, 1);
|
||||
}
|
||||
},
|
||||
|
||||
_interruptPlayingAnimAndPlayNewAnimFrameAnim(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName) {
|
||||
if (window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
|
||||
// No "framesToRecover"
|
||||
// console.warn(`JoinIndex=${rdfPlayer.joinIndex}, playing new ${newAnimName} from the beginning: while the playing anim is ${playAnimation}, player rdf changed from: ${null == prevRdfPlayer ? null : JSON.stringify(prevRdfPlayer)}, , to: ${JSON.stringify(rdfPlayer)}`);
|
||||
this.animComp.play(newAnimName, 0);
|
||||
return;
|
||||
}
|
||||
// The "playTimes" counterpart is managed by each "cc.AnimationClip.wrapMode", already preset in the editor.
|
||||
const targetClip = this.animComp.getClips()[newCharacterState]; // The clips follow the exact order in ATK_CHARACTER_STATE
|
||||
let fromTime = (targetClip.duration - rdfPlayer.framesToRecover / targetClip.sample); // TODO: Anyway to avoid using division here?
|
||||
if (fromTime < 0) {
|
||||
// For Atk1 or Atk2, it's possible that the "meleeBullet.recoveryFrames" is configured to be slightly larger than corresponding animation duration frames
|
||||
fromTime = 0;
|
||||
}
|
||||
this.animComp.play(newAnimName, fromTime);
|
||||
},
|
||||
|
||||
});
|
||||
|
@@ -761,9 +761,9 @@ cc.Class({
|
||||
const [wx, wy] = self.virtualGridToWorldPos(vx, vy);
|
||||
newPlayerNode.setPosition(wx, wy);
|
||||
playerScriptIns.mapNode = self.node;
|
||||
const d = playerDownsyncInfo.colliderRadius * 2,
|
||||
[x0, y0] = self.virtualGridToPolygonColliderAnchorPos(vx, vy, playerDownsyncInfo.colliderRadius, playerDownsyncInfo.colliderRadius),
|
||||
pts = [[0, 0], [d, 0], [d, d], [0, d]];
|
||||
const colliderWidth = playerDownsyncInfo.colliderRadius * 2, colliderHeight = playerDownsyncInfo.colliderRadius * 3;
|
||||
const [x0, y0] = self.virtualGridToPolygonColliderAnchorPos(vx, vy, colliderWidth, colliderHeight),
|
||||
pts = [[0, 0], [colliderWidth, 0], [colliderWidth, colliderHeight], [0, colliderHeight]];
|
||||
|
||||
const newPlayerCollider = self.collisionSys.createPolygon(x0, y0, pts);
|
||||
const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex;
|
||||
|
@@ -54,7 +54,7 @@ cc.Class({
|
||||
hitboxOffset: 12.0, // should be about the radius of the PlayerCollider
|
||||
hitboxSize: {
|
||||
x: 23.0,
|
||||
y: 20.0,
|
||||
y: 32.0,
|
||||
},
|
||||
|
||||
// for defender
|
||||
@@ -151,7 +151,7 @@ cc.Class({
|
||||
id: 11,
|
||||
joinIndex: 2,
|
||||
virtualGridX: 80 * self.worldToVirtualGridRatio,
|
||||
virtualGridY: 40 * self.worldToVirtualGridRatio,
|
||||
virtualGridY: 0 * self.worldToVirtualGridRatio,
|
||||
speed: 1 * self.worldToVirtualGridRatio,
|
||||
colliderRadius: 12,
|
||||
characterState: window.ATK_CHARACTER_STATE.Idle1[0],
|
||||
@@ -162,7 +162,7 @@ cc.Class({
|
||||
}
|
||||
});
|
||||
self.selfPlayerInfo = {
|
||||
id: 10
|
||||
id: 11
|
||||
};
|
||||
self._initPlayerRichInfoDict(startRdf.players);
|
||||
self.onRoomDownsyncFrame(startRdf);
|
||||
|
Reference in New Issue
Block a user