Commit dcf03b35 authored by timel's avatar timel Committed by Chunchi Che

feat: basic animation

parent 0874d5ff
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
"antd": "^5.4.0", "antd": "^5.4.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"eventemitter3": "^5.0.1",
"google-protobuf": "^3.21.2", "google-protobuf": "^3.21.2",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
...@@ -8945,9 +8946,9 @@ ...@@ -8945,9 +8946,9 @@
} }
}, },
"node_modules/eventemitter3": { "node_modules/eventemitter3": {
"version": "4.0.7", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
}, },
"node_modules/events": { "node_modules/events": {
"version": "3.3.0", "version": "3.3.0",
...@@ -11299,6 +11300,11 @@ ...@@ -11299,6 +11300,11 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/http-proxy/node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"node_modules/http-signature": { "node_modules/http-signature": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
...@@ -35195,9 +35201,9 @@ ...@@ -35195,9 +35201,9 @@
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
}, },
"eventemitter3": { "eventemitter3": {
"version": "4.0.7", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="
}, },
"events": { "events": {
"version": "3.3.0", "version": "3.3.0",
...@@ -36888,6 +36894,13 @@ ...@@ -36888,6 +36894,13 @@
"eventemitter3": "^4.0.0", "eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0", "follow-redirects": "^1.0.0",
"requires-port": "^1.0.0" "requires-port": "^1.0.0"
},
"dependencies": {
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
}
} }
}, },
"http-proxy-agent": { "http-proxy-agent": {
/// <reference types="react-scripts" /> /// <reference types="react-scripts" />
/// <reference types="vite/client" /> /// <reference types="vite/client" />
/// <reference types="eventemitter3" />
interface ImportMetaEnv { interface ImportMetaEnv {
readonly VITE_IS_AI_MODE: boolean; readonly VITE_IS_AI_MODE: boolean;
...@@ -13,3 +14,9 @@ interface ImportMeta { ...@@ -13,3 +14,9 @@ interface ImportMeta {
// 定义一个全局的myExtraDeckCodes变量 // 定义一个全局的myExtraDeckCodes变量
declare var myExtraDeckCodes: number[]; declare var myExtraDeckCodes: number[];
import { EventEmitter } from "eventemitter3";
declare global {
var eventBus: EventEmitter;
}
...@@ -27,6 +27,10 @@ import { BrowserRouter } from "react-router-dom"; ...@@ -27,6 +27,10 @@ import { BrowserRouter } from "react-router-dom";
import Neos from "./ui/Neos"; import Neos from "./ui/Neos";
import { EventEmitter } from "eventemitter3";
window.eventBus = new EventEmitter();
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement document.getElementById("root") as HTMLElement
); );
......
...@@ -155,7 +155,7 @@ button:focus-visible { ...@@ -155,7 +155,7 @@ button:focus-visible {
.block { .block {
width: var(--block-width); width: var(--block-width);
height: var(--block-height); height: var(--block-height);
background-color: #333; /* background-color: #333; */
cursor: pointer; cursor: pointer;
animation: glow calc(var(--highlight-interval) * var(--highlight-on)) ease-out animation: glow calc(var(--highlight-interval) * var(--highlight-on)) ease-out
infinite alternate; infinite alternate;
......
...@@ -17,13 +17,15 @@ import Mat from "./PlayMat"; ...@@ -17,13 +17,15 @@ import Mat from "./PlayMat";
import { Test } from "./Test"; import { Test } from "./Test";
import { Mat as NewMat } from "./NewPlayMat"; import { Mat as NewMat } from "./NewPlayMat";
import { Menu } from "./NewPlayMat/Menu";
const NeosDuel = () => { const NeosDuel = () => {
return ( return (
<> <>
<Alert /> <Alert />
{/* <Test /> */} {/* <Test /> */}
<Mat /> {/* <Mat /> */}
<Menu />
<NewMat /> <NewMat />
<CardModal /> <CardModal />
<CardListModal /> <CardListModal />
......
...@@ -5,6 +5,7 @@ section#mat { ...@@ -5,6 +5,7 @@ section#mat {
row-gap: var(--row-gap); row-gap: var(--row-gap);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background-color: transparent;
.bg-row { .bg-row {
display: flex; display: flex;
column-gap: var(--col-gap); column-gap: var(--col-gap);
...@@ -14,7 +15,8 @@ section#mat { ...@@ -14,7 +15,8 @@ section#mat {
.block { .block {
height: var(--block-height-m); height: var(--block-height-m);
width: var(--block-width); width: var(--block-width);
background-color: rgba(128, 128, 128, 0.447); // background-color: rgba(128, 128, 128, 0.447);
box-shadow: 0 0 0 1px purple;
&.extra { &.extra {
margin-inline: calc(var(--block-width) / 2 + var(--col-gap) / 2); margin-inline: calc(var(--block-width) / 2 + var(--col-gap) / 2);
} }
......
...@@ -6,6 +6,29 @@ section#mat { ...@@ -6,6 +6,29 @@ section#mat {
--card-height: 100px; --card-height: 100px;
height: var(--card-height); height: var(--card-height);
aspect-ratio: var(--card-ratio); aspect-ratio: var(--card-ratio);
background-color: red; transform-style: preserve-3d;
.card-img-wrap {
transform-style: preserve-3d;
position: relative;
height: 100%;
width: 100%;
transform: rotateY(calc(var(--ry) * 1deg));
.card-cover,
.card-back {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.card-cover {
z-index: 1;
transform: translateZ(0.5px);
}
.card-back {
z-index: 0;
transform: translateZ(0px);
}
}
} }
} }
import React, { type FC } from "react"; import React, { type CSSProperties, type FC } from "react";
import classnames from "classnames"; import classnames from "classnames";
import { CardType, cardStore, isMe } from "@/stores"; import { CardType, cardStore, isMe } from "@/stores";
import "./index.scss"; import "./index.scss";
import { useSnapshot, INTERNAL_Snapshot as Snapshot } from "valtio"; import { useSnapshot, INTERNAL_Snapshot as Snapshot } from "valtio";
import { watch } from "valtio/utils"; import { watch } from "valtio/utils";
import { useSpringRef, useSpring, animated, to } from "@react-spring/web"; import { useSpringRef, useSpring, animated, to, CSS } from "@react-spring/web";
import { matConfig } from "../utils"; import { matConfig } from "../utils";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { useConfig } from "@/config";
const NeosConfig = useConfig();
const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE, OVERLAY } = const { HAND, GRAVE, REMOVED, DECK, EXTRA, MZONE, SZONE, TZONE, OVERLAY } =
ygopro.CardZone; ygopro.CardZone;
...@@ -22,12 +25,15 @@ const { ...@@ -22,12 +25,15 @@ const {
HAND_MARGIN_TOP, HAND_MARGIN_TOP,
HAND_CARD_HEIGHT, HAND_CARD_HEIGHT,
HAND_CIRCLE_CENTER_OFFSET_Y, HAND_CIRCLE_CENTER_OFFSET_Y,
DECK_OFFSET_X,
DECK_OFFSET_Y,
DECK_ROTATE_Z,
} = matConfig; } = matConfig;
export const Card: FC<{ idx: number }> = React.memo(({ idx }) => { export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
const state = cardStore.inner[idx]; const state = cardStore.inner[idx];
const snap = useSnapshot(state); const snap = useSnapshot(state);
const inintialCoord = calcCoordinate(state, !isMe(state.controller)); const inintialCoord = calcCoordinate(state, false);
const api = useSpringRef(); const api = useSpringRef();
const props = useSpring({ const props = useSpring({
ref: api, ref: api,
...@@ -41,9 +47,8 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => { ...@@ -41,9 +47,8 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
height: inintialCoord.height, height: inintialCoord.height,
}, },
}); });
watch((get) => { const reloadPosition = (report: boolean) => {
const { zone, sequence, controller, xyzMonster } = get(state); const coord = calcCoordinate(state, report);
const coord = calcCoordinate(state, !isMe(state.controller));
api.start({ api.start({
to: { to: {
x: coord.translateX, x: coord.translateX,
...@@ -55,12 +60,28 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => { ...@@ -55,12 +60,28 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
height: coord.height, height: coord.height,
}, },
}); });
};
watch((get) => {
const { zone, sequence, controller, xyzMonster } = get(state);
reloadPosition(true);
}); });
// 在别的手卡更改时候,刷新这张手卡
eventBus.on(
"reload-hands",
({ sequence, controller }: { sequence: number; controller: number }) => {
if (state.sequence !== sequence && state.controller === controller) {
reloadPosition(false);
// console.warn('reload')
}
}
);
return ( return (
<animated.div <animated.div
className="mat-card" className="mat-card"
style={{ style={
{
transform: to( transform: to(
[ [
props.x, props.x,
...@@ -73,22 +94,27 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => { ...@@ -73,22 +94,27 @@ export const Card: FC<{ idx: number }> = React.memo(({ idx }) => {
(x, y, z, rx, ry, rz) => (x, y, z, rx, ry, rz) =>
`translate3d(${x}px, ${y}px, ${z}px) rotateX(${rx}deg) rotateZ(${rz}deg)` `translate3d(${x}px, ${y}px, ${z}px) rotateX(${rx}deg) rotateZ(${rz}deg)`
), ),
"--ry": props.rotateY,
height: props.height, height: props.height,
}} } as any as CSSProperties
}
> >
{snap.text.name} <div className="card-img-wrap">
{(Math.random() * 1000).toFixed()} <img className="card-cover" src={getCardImgUrl(snap.code)} alt="" />
<img className="card-back" src={getCardImgUrl(0, true)} alt="" />
</div>
</animated.div> </animated.div>
); );
}); });
function calcCoordinate( function calcCoordinate(
{ zone, sequence, position, xyzMonster, controller }: CardType, { zone, sequence, position, xyzMonster, controller }: CardType,
opponent: boolean report: boolean
) { ) {
const opponent = !isMe(controller);
const res = { const res = {
translateX: 0, translateX: -BLOCK_WIDTH.value,
translateY: 0, translateY: BLOCK_HEIGHT_M.value + BLOCK_HEIGHT_S.value + ROW_GAP.value * 2,
translateZ: 0, translateZ: 0,
rotateX: 0, rotateX: 0,
rotateY: 0, rotateY: 0,
...@@ -130,6 +156,16 @@ function calcCoordinate( ...@@ -130,6 +156,16 @@ function calcCoordinate(
res.rotateZ = opponent ? 180 : 0; res.rotateZ = opponent ? 180 : 0;
res.rotateZ += defense ? 90 : 0; res.rotateZ += defense ? 90 : 0;
res.rotateY = [
ygopro.CardPosition.FACEDOWN,
ygopro.CardPosition.FACEDOWN_ATTACK,
ygopro.CardPosition.FACEDOWN_DEFENSE,
].includes(_position ?? 5)
? 180
: res.rotateY;
res.rotateY = [DECK, EXTRA].includes(zone) ? 180 : 0;
zone === HAND && (res.rotateY = opponent ? 180 : 0);
res.height = defense res.height = defense
? BLOCK_WIDTH.value ? BLOCK_WIDTH.value
: zone === MZONE : zone === MZONE
...@@ -147,19 +183,26 @@ function calcCoordinate( ...@@ -147,19 +183,26 @@ function calcCoordinate(
BLOCK_HEIGHT_S.value * Math.ceil(row / 4); BLOCK_HEIGHT_S.value * Math.ceil(row / 4);
} }
if (zone === HAND && isMe(controller)) { if (zone === HAND) {
// 得刷新除了这个卡以外所有的自己的手卡
if (report) {
eventBus.emit("reload-hands", {
controller,
sequence,
});
}
// 手卡会有很复杂的计算... // 手卡会有很复杂的计算...
// 暂时先看成是我的手卡
const hand_circle_center_x = const hand_circle_center_x =
(5 * BLOCK_WIDTH.value + 4 * COL_GAP.value) / 2; (5 * BLOCK_WIDTH.value + 4 * COL_GAP.value) / 2;
const hand_circle_center_y = const hand_circle_center_y =
2 * BLOCK_HEIGHT_M.value + (3 * BLOCK_HEIGHT_M.value +
2 * BLOCK_HEIGHT_S.value + 2 * BLOCK_HEIGHT_S.value +
4 * ROW_GAP.value + 4 * ROW_GAP.value) *
HAND_MARGIN_TOP.value + Number(!opponent) +
(HAND_MARGIN_TOP.value +
HAND_CARD_HEIGHT.value + HAND_CARD_HEIGHT.value +
HAND_CIRCLE_CENTER_OFFSET_Y.value; HAND_CIRCLE_CENTER_OFFSET_Y.value) *
(opponent ? -1 : 1);
const hand_card_width = CARD_RATIO.value * HAND_CARD_HEIGHT.value; const hand_card_width = CARD_RATIO.value * HAND_CARD_HEIGHT.value;
const THETA = const THETA =
2 * 2 *
...@@ -167,7 +210,8 @@ function calcCoordinate( ...@@ -167,7 +210,8 @@ function calcCoordinate(
hand_card_width / hand_card_width /
2 / 2 /
(HAND_CIRCLE_CENTER_OFFSET_Y.value + HAND_CARD_HEIGHT.value) (HAND_CIRCLE_CENTER_OFFSET_Y.value + HAND_CARD_HEIGHT.value)
); ) *
0.9;
// 接下来计算每一张手卡 // 接下来计算每一张手卡
const hands_length = cardStore.at(HAND, controller).length; const hands_length = cardStore.at(HAND, controller).length;
const angle = (sequence - (hands_length - 1) / 2) * THETA; const angle = (sequence - (hands_length - 1) / 2) * THETA;
...@@ -175,14 +219,44 @@ function calcCoordinate( ...@@ -175,14 +219,44 @@ function calcCoordinate(
const negativeX = Math.sin(angle) * r - hand_card_width / 2; const negativeX = Math.sin(angle) * r - hand_card_width / 2;
const negativeY = Math.cos(angle) * r + HAND_CARD_HEIGHT.value / 2; const negativeY = Math.cos(angle) * r + HAND_CARD_HEIGHT.value / 2;
const x = hand_circle_center_x + negativeX; const x = hand_circle_center_x + negativeX;
const y = hand_circle_center_y - negativeY; const y =
hand_circle_center_y -
negativeY * (opponent ? -1 : 1) -
Number(opponent) * HAND_CARD_HEIGHT.value;
res.translateX = x; res.translateX = x;
res.translateY = y; res.translateY = y;
res.translateZ = 50; res.translateZ = 50;
res.rotateZ = (angle * 180) / Math.PI; res.rotateZ =
((angle * 180) / Math.PI) * (opponent ? -1 : 1) + (opponent ? 180 : 0);
res.rotateX = -PLANE_ROTATE_X.value; res.rotateX = -PLANE_ROTATE_X.value;
} }
if (zone === DECK || zone === EXTRA) {
const leftX = -DECK_OFFSET_X.value;
const rightX =
DECK_OFFSET_X.value +
5 * BLOCK_WIDTH.value +
4 * COL_GAP.value -
CARD_RATIO.value * res.height;
const topY = -DECK_OFFSET_Y.value;
const bottomY =
DECK_OFFSET_Y.value +
3 * BLOCK_HEIGHT_M.value +
2 * BLOCK_HEIGHT_S.value +
4 * ROW_GAP.value -
BLOCK_HEIGHT_S.value;
res.translateX = opponent ? leftX : rightX;
res.translateY = opponent ? topY : bottomY;
if (zone === EXTRA) {
res.translateX = opponent ? rightX : leftX;
}
res.rotateZ = opponent ? -DECK_ROTATE_Z.value : 180 - DECK_ROTATE_Z.value;
if (zone === EXTRA) {
res.rotateZ = opponent ? DECK_ROTATE_Z.value : DECK_ROTATE_Z.value;
}
res.translateZ = sequence;
}
return res; return res;
} }
...@@ -195,3 +269,14 @@ const posHelper: Record<number, number> = { ...@@ -195,3 +269,14 @@ const posHelper: Record<number, number> = {
5: 6, 5: 6,
6: 5, 6: 5,
}; };
function getCardImgUrl(code: number, back = false) {
const ASSETS_BASE =
import.meta.env.BASE_URL == "/"
? NeosConfig.assetsPath
: import.meta.env.BASE_URL + NeosConfig.assetsPath;
if (back) {
return ASSETS_BASE + "/card_back.jpg";
}
return NeosConfig.cardImgUrl + "/" + code + ".jpg";
}
section#mat { section#mat {
margin-top: 200px; margin-top: 200px;
padding-top: 50px; // 先不管 后面调整 // padding-top: 50px; // 先不管 后面调整
position: relative; position: relative;
#camera { #camera {
height: 100%; height: 100%;
...@@ -9,11 +9,11 @@ section#mat { ...@@ -9,11 +9,11 @@ section#mat {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
perspective: var(--perspective); perspective: var(--perspective);
transform-style: preserve-3d;
} }
#plane { #plane {
transform: translateX(0) translateY(0) translateZ(0) transform: translateX(0) translateY(0) translateZ(0)
rotateX(var(--plane-rotate-x)); rotateX(var(--plane-rotate-x));
width: fit-content; width: fit-content;
transform-style: preserve-3d;
} }
} }
...@@ -17,16 +17,14 @@ export const Mat: FC = () => { ...@@ -17,16 +17,14 @@ export const Mat: FC = () => {
id="mat" id="mat"
style={{ style={{
width: "100%", width: "100%",
// height: "100vh",
backgroundColor: "black",
...toCssProperties(matConfig), ...toCssProperties(matConfig),
}} }}
> >
<Plane> <Plane>
<Bg /> <Bg />
{snap.map((cardSnap, i) => {snap.map((cardSnap, i) => (
cardSnap.zone ? <Card key={i} idx={i} /> : null <Card key={i} idx={i} />
)} ))}
</Plane> </Plane>
</section> </section>
); );
......
import "@/styles/mat.css";
import Icon from "@ant-design/icons";
import { Button, Modal } from "antd";
import { ReactComponent as BattleSvg } from "neos-assets/crossed-swords.svg";
import { ReactComponent as EpSvg } from "neos-assets/power-button.svg";
import { ReactComponent as Main2Svg } from "neos-assets/sword-in-stone.svg";
import { ReactComponent as SurrenderSvg } from "neos-assets/truce.svg";
import React, { useState } from "react";
import { useSnapshot } from "valtio";
import {
sendSelectBattleCmdResponse,
sendSelectIdleCmdResponse,
sendSurrender,
} from "@/api";
import {
clearAllIdleInteractivities as clearAllIdleInteractivities,
matStore,
} from "@/stores";
const IconSize = "150%";
const PhaseButton = (props: {
text: string;
enable: boolean;
onClick: () => void;
icon?: React.ReactNode;
}) => {
return (
<Button
icon={props.icon}
disabled={!props.enable}
onClick={props.onClick}
size="large"
>
{props.text}
</Button>
);
};
const { phase } = matStore;
export const Menu = () => {
const snapPhase = useSnapshot(phase);
const enableBp = snapPhase.enableBp;
const enableM2 = snapPhase.enableM2;
const enableEp = snapPhase.enableEp;
const currentPhase = snapPhase.currentPhase;
const [modalOpen, setModalOpen] = useState(false);
const response =
currentPhase === "BATTLE_START" ||
currentPhase === "BATTLE_STEP" ||
currentPhase === "DAMAGE" ||
currentPhase === "DAMAGE_GAL" ||
currentPhase === "BATTLE"
? 3
: 7;
const onBp = () => {
sendSelectIdleCmdResponse(6);
clearAllIdleInteractivities(0); // 为什么要clear两次?
clearAllIdleInteractivities(0);
phase.enableBp = false;
};
const onM2 = () => {
sendSelectBattleCmdResponse(2);
clearAllIdleInteractivities(0);
clearAllIdleInteractivities(0);
phase.enableM2 = false;
};
const onEp = () => {
sendSelectIdleCmdResponse(response);
clearAllIdleInteractivities(0);
clearAllIdleInteractivities(0);
phase.enableEp = false;
};
const onSurrender = () => {
setModalOpen(true);
};
return (
<div id="controller">
<PhaseButton
icon={<Icon component={BattleSvg} style={{ fontSize: IconSize }} />}
enable={enableBp}
text="战斗阶段"
onClick={onBp}
/>
<PhaseButton
icon={<Icon component={Main2Svg} style={{ fontSize: IconSize }} />}
enable={enableM2}
text="主要阶段2"
onClick={onM2}
/>
<PhaseButton
icon={<Icon component={EpSvg} style={{ fontSize: IconSize }} />}
enable={enableEp}
text="结束回合"
onClick={onEp}
/>
<PhaseButton
icon={<Icon component={SurrenderSvg} style={{ fontSize: IconSize }} />}
enable={true}
text="投降"
onClick={onSurrender}
/>
<Modal
title="是否确认要投降?"
open={modalOpen}
closable={false}
footer={
<>
<Button
onClick={() => {
sendSurrender();
setModalOpen(false);
}}
>
Yes
</Button>
<Button
onClick={() => {
setModalOpen(false);
}}
>
No
</Button>
</>
}
/>
</div>
);
};
...@@ -25,7 +25,7 @@ export const matConfig = { ...@@ -25,7 +25,7 @@ export const matConfig = {
unit: UNIT.PX, unit: UNIT.PX,
}, },
PLANE_ROTATE_X: { PLANE_ROTATE_X: {
value: 20, value: 0,
unit: UNIT.DEG, unit: UNIT.DEG,
}, },
BLOCK_WIDTH: { BLOCK_WIDTH: {
...@@ -57,11 +57,23 @@ export const matConfig = { ...@@ -57,11 +57,23 @@ export const matConfig = {
unit: UNIT.PX, unit: UNIT.PX,
}, },
HAND_CIRCLE_CENTER_OFFSET_Y: { HAND_CIRCLE_CENTER_OFFSET_Y: {
value: 800, value: 2000,
unit: UNIT.PX, unit: UNIT.PX,
}, },
HAND_CARD_HEIGHT: { HAND_CARD_HEIGHT: {
value: 120, value: 120,
unit: UNIT.PX, unit: UNIT.PX,
}, },
DECK_OFFSET_X: {
value: 140,
unit: UNIT.PX,
},
DECK_OFFSET_Y: {
value: 80,
unit: UNIT.PX,
},
DECK_ROTATE_Z: {
value: 30,
unit: UNIT.DEG,
},
}; };
// import { EventEmitter } from "eventemitter3";
// window.eventBus = new EventEmitter();
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