Commit ad72505b authored by timel's avatar timel

fix: a very important fix on animation

parent c24f8465
......@@ -14,13 +14,13 @@ const getEnd = (task: Task) => `${task}-end`;
/** 在组件之中注册方法 */
const register = <T extends unknown[]>(
task: Task,
fn: (...args: T) => Promise<void>
fn: (...args: T) => Promise<boolean>
) => {
eventEmitter.on(
task,
async ({ taskId, args }: { taskId: string; args: T }) => {
await fn(...args);
eventEmitter.emit(getEnd(task), taskId);
const result = await fn(...args);
if (result) eventEmitter.emit(getEnd(task), taskId);
}
);
};
......
import { ygopro } from "@/api";
import { sleep } from "@/infra";
import { cardStore, fetchEsHintMeta } from "@/stores";
import { callCardAttack } from "@/ui/Duel/PlayMat/Card";
......@@ -29,6 +28,4 @@ export default async (attack: ygopro.StocGameMessage.MsgAttack) => {
} else {
console.warn(`<Attack>attacker from ${attack.attacker_location} is null`);
}
await sleep(2000);
};
import { fetchCard, ygopro } from "@/api";
import { eventbus, sleep, Task } from "@/infra";
import { eventbus, Task } from "@/infra";
import { cardStore, fetchEsHintMeta, matStore } from "@/stores";
export default async (chaining: ygopro.StocGameMessage.MsgChaining) => {
......@@ -29,10 +29,6 @@ export default async (chaining: ygopro.StocGameMessage.MsgChaining) => {
// 发动效果动画
await eventbus.call(Task.Focus, target.uuid);
console.color("blue")(`${target.meta.text.name} chaining`);
// 临时办法,这里延迟800ms
// 长期:需要实现动画序列,一个动画完成后才执行下一个动画
await sleep(800);
} else {
console.warn(`<Chaining>target from ${location} is null`);
}
......
import { fetchCard, ygopro } from "@/api";
import { eventbus, sleep, Task } from "@/infra";
import { eventbus, Task } from "@/infra";
import { cardStore } from "@/stores";
export default async (confirmCards: ygopro.StocGameMessage.MsgConfirmCards) => {
......@@ -15,9 +15,6 @@ export default async (confirmCards: ygopro.StocGameMessage.MsgConfirmCards) => {
target.meta = meta;
// 动画
await eventbus.call(Task.Focus, target.uuid);
// 临时措施,延迟一会,让动画逐个展示
// 长期:需要实现动画序列,一个动画完成后才执行下一个动画
await sleep(500);
} else {
console.warn(`card of ${card} is null`);
}
......
import { ygopro } from "@/api";
import { sleep } from "@/infra";
import { matStore } from "@/stores";
import { showWaiting } from "@/ui/Duel/Message";
......@@ -142,8 +141,6 @@ async function _handleGameMsg(pb: ygopro.YgoStocMsg) {
}
case "move": {
await onMsgMove(msg.move);
await sleep(500);
break;
}
case "select_card": {
......@@ -268,7 +265,6 @@ async function _handleGameMsg(pb: ygopro.YgoStocMsg) {
}
case "chaining": {
await onMsgChaining(msg.chaining);
break;
}
case "chain_solved": {
......
......@@ -14,27 +14,29 @@ export default async (shuffleHandExtra: MsgShuffleHandExtra) => {
hash.get(code)?.push(sequence);
});
for (const card of cards) {
const sequences = hash.get(card.code);
if (sequences !== undefined) {
const sequence = sequences.pop();
if (sequence !== undefined) {
card.location.sequence = sequence;
hash.set(card.code, sequences);
Promise.all(
cards.map(async (card) => {
const sequences = hash.get(card.code);
if (sequences !== undefined) {
const sequence = sequences.pop();
if (sequence !== undefined) {
card.location.sequence = sequence;
hash.set(card.code, sequences);
// 触发动画
await callCardMove(card.uuid);
// 触发动画
await callCardMove(card.uuid);
} else {
console.warn(
`<ShuffleHandExtra>sequence poped is none, controller=${controller}, code=${card.code}, sequence=${sequence}`
);
}
} else {
console.warn(
`<ShuffleHandExtra>sequence poped is none, controller=${controller}, code=${card.code}, sequence=${sequence}`
`<ShuffleHandExtra>target from records is null, controller=${controller}, cards=${cards.map(
(card) => card.code
)}, codes=${codes}`
);
}
} else {
console.warn(
`<ShuffleHandExtra>target from records is null, controller=${controller}, cards=${cards.map(
(card) => card.code
)}, codes=${codes}`
);
}
}
})
);
};
......@@ -18,33 +18,36 @@ export default async (shuffleSetCard: MsgShuffleSetCard) => {
}
const count = from_locations.length;
for (let i = 0; i < count; i++) {
const from = from_locations[i];
const target = cardStore.at(from.zone, from.controller, from.sequence);
if (target) {
// 设置code为0,洗切后的code会由`UpdateData`指定
target.code = 0;
target.meta.id = 0;
target.meta.text.id = 0;
} else {
console.warn(`<ShuffleSetCard>target from ${from} is null`);
}
// 处理超量
const overlay_location = overlay_locations[i];
if (overlay_location.zone > 0) {
// 如果没有超量素材,后端会全传0
for (const overlay of cardStore.findOverlay(
from.zone,
from.controller,
from.sequence
)) {
// 更新sequence
overlay.location.sequence = overlay_location.sequence;
// 渲染动画
await callCardMove(overlay.uuid);
// 这里其实有个疑惑,如果超量素材也跟着洗切的话,洗切的意义好像就没有了,感觉算是个k社没想好的设计?
Promise.all(
Array.from({ length: count }).map(async (_, i) => {
const from = from_locations[i];
const target = cardStore.at(from.zone, from.controller, from.sequence);
if (target) {
// 设置code为0,洗切后的code会由`UpdateData`指定
target.code = 0;
target.meta.id = 0;
target.meta.text.id = 0;
} else {
console.warn(`<ShuffleSetCard>target from ${from} is null`);
}
}
}
// 处理超量
const overlay_location = overlay_locations[i];
if (overlay_location.zone > 0) {
// 如果没有超量素材,后端会全传0
for (const overlay of cardStore.findOverlay(
from.zone,
from.controller,
from.sequence
)) {
// 更新sequence
overlay.location.sequence = overlay_location.sequence;
// 渲染动画
await callCardMove(overlay.uuid);
// 这里其实有个疑惑,如果超量素材也跟着洗切的话,洗切的意义好像就没有了,感觉算是个k社没想好的设计?
}
}
})
);
};
......@@ -82,7 +82,8 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
eventbus.register(task, async (uuid, ...rest: T) => {
if (uuid === card.uuid) {
await fn(...rest);
}
return true;
} else return false;
});
};
......@@ -93,7 +94,7 @@ export const Card: React.FC<{ idx: number }> = React.memo(({ idx }) => {
register(Task.Focus, async () => {
setClassFocus(true);
setTimeout(() => setClassFocus(false), 1000);
setTimeout(() => setClassFocus(false), 1000); // TODO: 这儿为啥要这么写呢
await focus({ card, api });
});
......@@ -345,9 +346,8 @@ const handleEffectActivation = (
const call =
<Options,>(task: Task) =>
async (uuid: string, options?: Options extends {} ? Options : never) => {
(uuid: string, options?: Options extends {} ? Options : never) =>
eventbus.call(task, uuid, options);
};
export const callCardMove = call<MoveOptions>(Task.Move);
export const callCardFocus = call(Task.Focus);
......
......@@ -11,19 +11,14 @@ export const focus = async (props: { card: CardType; api: SpringApi }) => {
card.location.zone == ygopro.CardZone.HAND ||
card.location.zone == ygopro.CardZone.DECK
) {
const current = api.current[0].get();
const current = { ...api.current[0].get() };
await asyncStart(api)({
y: current.y + (matStore.isMe(card.location.controller) ? -1 : 1) * 120, // TODO: 放到config之中
ry: 0,
// rz: 0,
z: current.z + 50,
});
await asyncStart(api)({
y: current.y,
ry: current.ry,
rz: current.rz,
z: current.z,
});
await asyncStart(api)(current);
} else {
await asyncStart(api)({
focusScale: 1.5,
......
import { type SpringConfig, type SpringRef } from "@react-spring/web";
import { getCardImgUrl } from "@/ui/Shared";
export const asyncStart = <T extends {}>(api: SpringRef<T>) => {
return (p: Partial<T> & { config?: SpringConfig }) =>
new Promise((resolve) => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment