Commit 54a8a9b8 authored by Chunchi Che's avatar Chunchi Che

clean code

parent 006bee33
import * as BABYLON from "@babylonjs/core";
import * as CONFIG from "../../config/ui";
export default (scene: BABYLON.Scene) => {
const xs = [-1.1, 1];
const shape = CONFIG.CardSlotShape();
for (let i in xs) {
const slot = BABYLON.MeshBuilder.CreatePlane(
`extraMonster${i}`,
shape,
scene
);
// 位置
slot.position = new BABYLON.Vector3(
xs[i],
shape.depth / 2 + CONFIG.Floating,
0
);
// 旋转
slot.rotation = CONFIG.CardSlotRotation();
// 材质
const extraMonsterMaterial = new BABYLON.StandardMaterial(
"extraMonsterMaterial",
scene
);
extraMonsterMaterial.diffuseTexture = new BABYLON.Texture(
`http://localhost:3030/images/card_slot.png`
);
extraMonsterMaterial.diffuseTexture.hasAlpha = true;
slot.material = extraMonsterMaterial;
}
};
import * as BABYLON from "@babylonjs/core";
import * as CONFIG from "../../config/ui";
import { Card, InteractType } from "../../reducers/duel/util";
import {
setCardModalImgUrl,
setCardModalIsOpen,
setCardModalText,
setCardModalInteractivies,
} from "../../reducers/duel/mod";
import { store } from "../../store";
export default (hands: Card[], scene: BABYLON.Scene) => {
const handShape = CONFIG.HandShape();
hands.forEach((item, idx, _) => {
const hand = BABYLON.MeshBuilder.CreatePlane(
`hand${idx}`,
handShape,
scene
);
// 位置&旋转
setupHandTransform(hand, item);
// 材质
setupHandMaterial(hand, item, scene);
// 事件管理
setupHandAction(hand, item, idx, scene);
});
};
function setupHandTransform(mesh: BABYLON.Mesh, state: Card) {
mesh.position = new BABYLON.Vector3(
state.transform.position?.x,
state.transform.position?.y,
state.transform.position?.z
);
mesh.rotation = new BABYLON.Vector3(
state.transform.rotation?.x,
state.transform.rotation?.y,
state.transform.rotation?.z
);
}
function setupHandMaterial(
mesh: BABYLON.Mesh,
state: Card,
scene: BABYLON.Scene
) {
const handMaterial = new BABYLON.StandardMaterial(
`handMaterial${state.meta.id}`,
scene
);
// 材质贴纸
handMaterial.diffuseTexture = new BABYLON.Texture(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${state.meta.id}.jpg`,
scene
);
mesh.material = handMaterial;
}
function setupHandAction(
mesh: BABYLON.Mesh,
state: Card,
_handIdx: number,
scene: BABYLON.Scene
) {
const dispatch = store.dispatch;
mesh.actionManager = new BABYLON.ActionManager(scene);
mesh.actionManager.isRecursive = true;
// 监听点击事件
mesh.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnPickTrigger,
(_event) => {
dispatch(
setCardModalText([state.meta.text.name, state.meta.text.desc])
);
dispatch(
setCardModalImgUrl(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${state.meta.id}.jpg`
)
);
dispatch(
setCardModalInteractivies(
state.interactivities.map((interactive) => {
return {
desc: interactTypeToString(interactive.interactType),
response: interactive.response,
};
})
)
);
dispatch(setCardModalIsOpen(true));
}
)
);
// 监听`Hover`事件
mesh.actionManager.registerAction(
new BABYLON.CombineAction(
{ trigger: BABYLON.ActionManager.OnPointerOverTrigger },
[
new BABYLON.SetValueAction(
{
trigger: BABYLON.ActionManager.OnPointerOverTrigger,
},
mesh,
"scaling",
CONFIG.HandHoverScaling()
),
]
)
);
// 监听`Hover`离开事件
mesh.actionManager.registerAction(
new BABYLON.CombineAction(
{ trigger: BABYLON.ActionManager.OnPointerOutTrigger },
[
new BABYLON.SetValueAction(
{
trigger: BABYLON.ActionManager.OnPointerOutTrigger,
},
mesh,
"scaling",
CONFIG.HandHoverOutScaling()
),
]
)
);
}
function interactTypeToString(t: InteractType): string {
switch (t) {
case InteractType.SUMMON: {
return "普通召唤";
}
case InteractType.SP_SUMMON: {
return "特殊召唤";
}
case InteractType.POS_CHANGE: {
return "改变表示形式";
}
case InteractType.MSET: {
return "前场放置";
}
case InteractType.SSET: {
return "后场放置";
}
case InteractType.ACTIVATE: {
return "发动效果";
}
default: {
return "未知选项";
}
}
}
import * as BABYLON from "@babylonjs/core";
import * as CONFIG from "../../config/ui";
export default (scene: BABYLON.Scene) => {
const left = -2.15;
const gap = 1.05;
const shape = CONFIG.CardSlotShape();
for (let i = 0; i < 5; i++) {
const slot = BABYLON.MeshBuilder.CreatePlane(`magic${i}`, shape, scene);
// 位置
slot.position = new BABYLON.Vector3(
left + gap * i,
shape.depth / 2 + CONFIG.Floating,
-2.6
);
// 旋转
slot.rotation = CONFIG.CardSlotRotation();
// 材质
const magicMaterial = new BABYLON.StandardMaterial("magicMaterial", scene);
magicMaterial.diffuseTexture = new BABYLON.Texture(
`http://localhost:3030/images/card_slot.png`
);
magicMaterial.diffuseTexture.hasAlpha = true;
slot.material = magicMaterial;
}
};
......@@ -9,7 +9,7 @@ import CardModal from "./cardModal";
import HintNotification from "./hintNotification";
import Magics from "./magics_";
const BabylonCanvas = () => (
const NeosDuel = () => (
<>
<ReactReduxContext.Consumer>
{({ store }) => (
......@@ -65,4 +65,4 @@ const Ground = () => {
);
};
export default BabylonCanvas;
export default NeosDuel;
/*
* 一个简洁的决斗界面实现
*
* */
import { useAppSelector } from "../../hook";
import React, { useEffect, useRef } from "react";
import { observeStore } from "../../store";
import * as BABYLON from "@babylonjs/core";
import renderHands from "./hands";
import renderMonsters from "./monsters";
import renderExtraMonsters from "./extraMonsters";
import renderMagics from "./magics";
import renderDeck from "./deck";
import renderCemetery from "./cemetery";
import renderExclusion from "./exclusion";
import renderField from "./field";
import * as CONFIG from "../../config/ui";
import { Card } from "../../reducers/duel/util";
import { selectCurrentPlayer } from "../../reducers/duel/turnSlice";
import CardModal from "./cardModal";
import HintNotification from "./hintNotification";
import { selectMeHands } from "../../reducers/duel/handsSlice";
import { selectMeMonsters } from "../../reducers/duel/monstersSlice";
// CONFIG
const Duel = () => {
// ----- 数据获取 -----
const hands = useAppSelector(selectMeHands).cards;
const monsters = useAppSelector(selectMeMonsters).monsters;
const currentPlayer = useAppSelector(selectCurrentPlayer);
// ----- WebGL渲染 -----
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
// 初始化Scene
const canvasCurrent = canvasRef.current;
const engine = new BABYLON.Engine(canvasCurrent, true);
const scene = new BABYLON.Scene(engine);
// 创建Camera
const camera = new BABYLON.FreeCamera(
"camera1",
new BABYLON.Vector3(0, 8, -10), // 俯视方向
scene
);
camera.setTarget(BABYLON.Vector3.Zero()); // 俯视向前
camera.attachControl(canvasCurrent, true);
// 创建光源
const light = new BABYLON.HemisphericLight(
"light",
new BABYLON.Vector3(1, 2.5, 1),
scene
);
light.intensity = 0.7;
// 魔法陷阱区
renderMagics(scene);
// 怪兽区
renderMonsters(monsters, scene);
// 创建额外怪兽区
renderExtraMonsters(scene);
// 创建手牌
renderHands(hands, scene);
// 创建卡组
renderDeck(scene);
// 创建墓地
renderCemetery(scene);
// 创建除外区
renderExclusion(scene);
// 创建场地
renderField(scene);
// 创建地板
const ground = BABYLON.MeshBuilder.CreateGround(
"ground",
CONFIG.GroundShape(),
scene
);
const groundMaterial = new BABYLON.StandardMaterial(
"groundMaterial",
scene
);
groundMaterial.diffuseTexture = new BABYLON.Texture(
`http://localhost:3030/images/newfield.png`
);
groundMaterial.diffuseTexture.hasAlpha = true;
ground.material = groundMaterial;
/* 一些未处理的逻辑,在这里用日志打印出来 */
// 当前操作玩家
console.log(`currentPlayer:` + currentPlayer);
// 渲染循环
engine.runRenderLoop(() => {
scene.render();
});
}, [canvasRef, hands, monsters, currentPlayer]); // FIXME: 这里需要优化,应该分组件按需渲染
useEffect(() => {
// 监听状态变化,并实现动画
const onHandsChange = (prev_hands: Card[] | null, cur_hands: Card[]) => {
console.log(prev_hands, "change to", cur_hands);
};
const unsubscribe = observeStore(
(root) => selectMeHands(root).cards,
onHandsChange
);
return () => {
// 取消监听
unsubscribe();
};
}, []);
return (
<>
<canvas
width={window.innerWidth}
height={window.innerHeight}
ref={canvasRef}
/>
<CardModal />
<HintNotification />
</>
);
};
export default Duel;
import * as BABYLON from "@babylonjs/core";
import * as CONFIG from "../../config/ui";
import { Monster } from "../../reducers/duel/util";
import { clearMonsterSelectInfo } from "../../reducers/duel/mod";
import { store } from "../../store";
import { sendSelectPlaceResponse } from "../../api/ocgcore/ocgHelper";
export default (monsters: Monster[], scene: BABYLON.Scene) => {
const left = -2.15;
const gap = 1.05;
const shape = CONFIG.CardSlotShape();
for (const monster of monsters) {
const slot = BABYLON.MeshBuilder.CreatePlane(
`monster${monster.sequence}`,
shape,
scene
);
// 位置
setupMonsterTransform(slot, monster, left, gap, shape);
// 旋转
slot.rotation = CONFIG.CardSlotRotation();
// 材质
setupMonsterMaterial(slot, monster, scene);
// 高亮
setupHintEdge(slot, monster);
// 事件管理
setupMonsterAction(slot, monster, scene);
}
};
function setupMonsterTransform(
mesh: BABYLON.Mesh,
state: Monster,
left: number,
gap: number,
shape: { width: number; height: number; depth: number }
) {
mesh.position = new BABYLON.Vector3(
left + gap * state.sequence,
shape.depth / 2 + CONFIG.Floating,
-1.35
);
}
function setupMonsterMaterial(
mesh: BABYLON.Mesh,
state: Monster,
scene: BABYLON.Scene
) {
const monsterMaterial = new BABYLON.StandardMaterial(
"monsterMaterial",
scene
);
monsterMaterial.diffuseTexture = state.occupant
? new BABYLON.Texture(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${state.occupant.id}.jpg`
)
: new BABYLON.Texture(`http://localhost:3030/images/card_slot.png`);
monsterMaterial.diffuseTexture.hasAlpha = true;
mesh.material = monsterMaterial;
}
function setupHintEdge(mesh: BABYLON.Mesh, state: Monster) {
if (state.selectInfo) {
mesh.enableEdgesRendering();
mesh.edgesWidth = 2.0;
mesh.edgesColor = BABYLON.Color4.FromColor3(BABYLON.Color3.Yellow());
} else {
mesh.disableEdgesRendering();
}
}
function setupMonsterAction(
mesh: BABYLON.Mesh,
state: Monster,
scene: BABYLON.Scene
) {
const dispatch = store.dispatch;
mesh.actionManager = new BABYLON.ActionManager(scene);
// 监听点击事件
mesh.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnPickTrigger,
(_event) => {
if (state.selectInfo) {
sendSelectPlaceResponse(state.selectInfo.response);
dispatch(clearMonsterSelectInfo(0));
dispatch(clearMonsterSelectInfo(1));
}
}
)
);
}
......@@ -3,8 +3,7 @@ import JoinRoom from "./JoinRoom";
import WaitRoom from "./WaitRoom";
import { Routes, Route } from "react-router-dom";
import Mora from "./Mora";
import Duel from "./Duel/mod";
import BabylonCanvas from "./Duel/babylon";
import NeosDuel from "./Duel/main";
export default function () {
// FIXME: 这里Mora/Duel路由应该由每个房间指定一个路径
......@@ -13,8 +12,7 @@ export default function () {
<Route path="/" element={<JoinRoom />} />
<Route path="/:player/:passWd/:ip" element={<WaitRoom />} />
<Route path="/mora" element={<Mora />} />
<Route path="/duel" element={<BabylonCanvas />} />
<Route path="/react-babylon" element={<BabylonCanvas />} />
<Route path="/duel" element={<NeosDuel />} />
</Routes>
);
}
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