Commit 85edf087 authored by Chunchi Che's avatar Chunchi Che

add Card interface

parent 29d6bb2e
Pipeline #18288 passed with stages
in 2 minutes and 24 seconds
import axios from "axios"; import axios from "axios";
export interface CardMeta { interface CardMeta {
id: number; id: number;
data: { data: {
ot?: number; ot?: number;
...@@ -17,6 +17,9 @@ export interface CardMeta { ...@@ -17,6 +17,9 @@ export interface CardMeta {
types?: string; types?: string;
desc?: string; desc?: string;
}; };
}
interface CardTransform {
position?: { position?: {
x: number; x: number;
y: number; y: number;
...@@ -29,6 +32,14 @@ export interface CardMeta { ...@@ -29,6 +32,14 @@ export interface CardMeta {
}; };
} }
/*
* `Neos`中表示卡牌的通用结构
* */
export interface Card {
meta: CardMeta;
transform: CardTransform;
}
/* /*
* 返回卡片元数据 * 返回卡片元数据
* *
......
...@@ -6,11 +6,11 @@ import { ...@@ -6,11 +6,11 @@ import {
} from "@reduxjs/toolkit"; } from "@reduxjs/toolkit";
import { DuelState } from "./mod"; import { DuelState } from "./mod";
import { RootState } from "../../store"; import { RootState } from "../../store";
import { CardMeta, fetchCard } from "../../api/cards"; import { Card, fetchCard } from "../../api/cards";
import * as UICONFIG from "../../config/ui"; import * as UICONFIG from "../../config/ui";
export interface Hands { export interface Hands {
cards: CardMeta[]; cards: Card[];
} }
// 自己增加手牌 // 自己增加手牌
...@@ -19,7 +19,7 @@ export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = ( ...@@ -19,7 +19,7 @@ export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
action action
) => { ) => {
const cards = action.payload.map((id) => { const cards = action.payload.map((id) => {
return { id, data: {}, text: {} }; return { meta: { id, data: {}, text: {} }, transform: {} };
}); });
if (state.meHands) { if (state.meHands) {
...@@ -28,20 +28,7 @@ export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = ( ...@@ -28,20 +28,7 @@ export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state.meHands = { cards }; state.meHands = { cards };
} }
// 更新手牌的位置和旋转信息 setHandsTransform(state.meHands.cards);
const groundShape = UICONFIG.GroundShape();
const handShape = UICONFIG.HandShape();
const gap = groundShape.width / (state.meHands.cards.length - 1);
const left = -(groundShape.width / 2);
state.meHands.cards.forEach((hand, idx, _) => {
hand.position = {
x: left + gap * idx,
y: handShape.height / 2,
z: -(groundShape.height / 2) - 1,
};
hand.rotation = UICONFIG.HandRotation();
});
}; };
// 对手增加手牌 // 对手增加手牌
...@@ -50,7 +37,7 @@ export const opAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = ( ...@@ -50,7 +37,7 @@ export const opAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
action action
) => { ) => {
const cards = action.payload.map((id) => { const cards = action.payload.map((id) => {
return { id, data: {}, text: {} }; return { meta: { id, data: {}, text: {} }, transform: {} };
}); });
if (state.opHands) { if (state.opHands) {
state.opHands.cards = state.opHands.cards.concat(cards); state.opHands.cards = state.opHands.cards.concat(cards);
...@@ -73,15 +60,47 @@ export const fetchMeHandsMeta = createAsyncThunk( ...@@ -73,15 +60,47 @@ export const fetchMeHandsMeta = createAsyncThunk(
export const meHandsCase = (builder: ActionReducerMapBuilder<DuelState>) => { export const meHandsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchMeHandsMeta.fulfilled, (state, action) => { builder.addCase(fetchMeHandsMeta.fulfilled, (state, action) => {
// TODO: 合法性校验 // TODO: 合法性校验
const cards = action.payload; const cardMetas = action.payload;
if (state.meHands) { if (state.meHands) {
state.meHands.cards = cards; for (let meta of cardMetas) {
for (let hand of state.meHands.cards) {
if (hand.meta.id === meta.id) {
hand.meta = meta;
}
}
}
} else { } else {
state.meHands = { cards }; state.meHands = {
cards: cardMetas.map((meta) => {
return { meta, transform: {} };
}),
};
setHandsTransform(state.meHands.cards);
} }
}); });
}; };
// 更新手牌的位置和旋转信息
function setHandsTransform(hands: Card[]): void {
const groundShape = UICONFIG.GroundShape();
const handShape = UICONFIG.HandShape();
const gap = groundShape.width / (hands.length - 1);
const left = -(groundShape.width / 2);
hands.forEach((hand, idx, _) => {
hand.transform.position = {
x: left + gap * idx,
y: handShape.height / 2,
z: -(groundShape.height / 2) - 1,
};
const rotation = UICONFIG.HandRotation();
hand.transform.rotation = { x: rotation.x, y: rotation.y, z: rotation.z };
});
}
export const selectMeHands = (state: RootState) => export const selectMeHands = (state: RootState) =>
state.duel.meHands || { cards: [] }; state.duel.meHands || { cards: [] };
export const selectOpHands = (state: RootState) => export const selectOpHands = (state: RootState) =>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
import React from "react"; import React from "react";
import type { RootState } from "../../store"; import type { RootState } from "../../store";
import { CardMeta } from "../../api/cards"; import { Card } from "../../api/cards";
/* /*
* 通用的决斗界面抽象接口 * 通用的决斗界面抽象接口
...@@ -26,7 +26,7 @@ export interface IDuelPlate { ...@@ -26,7 +26,7 @@ export interface IDuelPlate {
// 渲染接口,返回一个React组件 // 渲染接口,返回一个React组件
render(): React.ReactElement; render(): React.ReactElement;
// 注册手牌selector // 注册手牌selector
registerHands(selector: TypeSelector<CardMeta[]>): void; registerHands(selector: TypeSelector<Card[]>): void;
} }
export interface TypeSelector<T> { export interface TypeSelector<T> {
......
import * as BABYLON from "@babylonjs/core"; import * as BABYLON from "@babylonjs/core";
import * as CONFIG from "../../../config/ui"; import * as CONFIG from "../../../config/ui";
import { CardMeta } from "../../../api/cards"; import { Card } from "../../../api/cards";
export default (hands: CardMeta[], scene: BABYLON.Scene) => { export default (hands: Card[], scene: BABYLON.Scene) => {
const handShape = CONFIG.HandShape(); const handShape = CONFIG.HandShape();
hands.forEach((item, idx, _) => { hands.forEach((item, idx, _) => {
const hand = BABYLON.MeshBuilder.CreatePlane( const hand = BABYLON.MeshBuilder.CreatePlane(
...@@ -12,20 +12,20 @@ export default (hands: CardMeta[], scene: BABYLON.Scene) => { ...@@ -12,20 +12,20 @@ export default (hands: CardMeta[], scene: BABYLON.Scene) => {
); );
// 位置 // 位置
hand.position = new BABYLON.Vector3( hand.position = new BABYLON.Vector3(
item.position?.x, item.transform.position?.x,
item.position?.y, item.transform.position?.y,
item.position?.z item.transform.position?.z
); );
hand.rotation = new BABYLON.Vector3( hand.rotation = new BABYLON.Vector3(
item.rotation?.x, item.transform.rotation?.x,
item.rotation?.y, item.transform.rotation?.y,
item.rotation?.z item.transform.rotation?.z
); );
// 材质 // 材质
const handMaterial = new BABYLON.StandardMaterial("handMaterial", scene); const handMaterial = new BABYLON.StandardMaterial("handMaterial", scene);
// 材质贴纸 // 材质贴纸
handMaterial.diffuseTexture = new BABYLON.Texture( handMaterial.diffuseTexture = new BABYLON.Texture(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${item.id}.jpg`, `https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${item.meta.id}.jpg`,
scene scene
); );
hand.material = handMaterial; hand.material = handMaterial;
......
...@@ -17,12 +17,12 @@ import renderCemetery from "./cemetery"; ...@@ -17,12 +17,12 @@ import renderCemetery from "./cemetery";
import renderExclusion from "./exclusion"; import renderExclusion from "./exclusion";
import renderField from "./field"; import renderField from "./field";
import * as CONFIG from "../../../config/ui"; import * as CONFIG from "../../../config/ui";
import { CardMeta } from "../../../api/cards"; import { Card } from "../../../api/cards";
// CONFIG // CONFIG
export default class SimpleDuelPlateImpl implements IDuelPlate { export default class SimpleDuelPlateImpl implements IDuelPlate {
handsSelector?: TypeSelector<CardMeta[]>; handsSelector?: TypeSelector<Card[]>;
constructor() {} constructor() {}
...@@ -110,10 +110,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate { ...@@ -110,10 +110,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
useEffect(() => { useEffect(() => {
// 监听状态变化,并实现动画 // 监听状态变化,并实现动画
const onHandsChange = ( const onHandsChange = (prev_hands: Card[] | null, cur_hands: Card[]) => {
prev_hands: CardMeta[] | null,
cur_hands: CardMeta[]
) => {
console.log(prev_hands, "change to", cur_hands); console.log(prev_hands, "change to", cur_hands);
}; };
...@@ -136,7 +133,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate { ...@@ -136,7 +133,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
); );
} }
registerHands(selector: TypeSelector<CardMeta[]>): void { registerHands(selector: TypeSelector<Card[]>): void {
this.handsSelector = selector; this.handsSelector = selector;
} }
} }
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