Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Neos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
love_飞影
Neos
Commits
4f900064
Commit
4f900064
authored
Dec 25, 2022
by
Chunchi Che
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat/ui/select_place' into 'main'
Feat/ui/select place See merge request
mycard/Neos!50
parents
3bef189a
44ee48ca
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
321 additions
and
27 deletions
+321
-27
src/api/ocgcore/ocgAdapter/ctos/ctosGameMsgResponse/mod.ts
src/api/ocgcore/ocgAdapter/ctos/ctosGameMsgResponse/mod.ts
+6
-0
src/api/ocgcore/ocgAdapter/ctos/ctosGameMsgResponse/selectPlace.ts
...cgcore/ocgAdapter/ctos/ctosGameMsgResponse/selectPlace.ts
+14
-0
src/api/ocgcore/ocgAdapter/util.ts
src/api/ocgcore/ocgAdapter/util.ts
+41
-0
src/api/ocgcore/ocgHelper.ts
src/api/ocgcore/ocgHelper.ts
+19
-0
src/reducers/duel/handsSlice.ts
src/reducers/duel/handsSlice.ts
+1
-1
src/reducers/duel/mod.ts
src/reducers/duel/mod.ts
+21
-0
src/reducers/duel/monstersSlice.ts
src/reducers/duel/monstersSlice.ts
+86
-0
src/reducers/duel/util.ts
src/reducers/duel/util.ts
+16
-3
src/service/duel/selectPlace.ts
src/service/duel/selectPlace.ts
+18
-2
src/service/duel/start.ts
src/service/duel/start.ts
+3
-1
src/ui/Duel/extraMonsters.ts
src/ui/Duel/extraMonsters.ts
+5
-2
src/ui/Duel/magics.ts
src/ui/Duel/magics.ts
+5
-2
src/ui/Duel/mod.tsx
src/ui/Duel/mod.tsx
+4
-2
src/ui/Duel/monsters.ts
src/ui/Duel/monsters.ts
+82
-14
No files found.
src/api/ocgcore/ocgAdapter/ctos/ctosGameMsgResponse/mod.ts
View file @
4f900064
...
@@ -2,6 +2,7 @@ import { ygopro } from "../../../idl/ocgcore";
...
@@ -2,6 +2,7 @@ import { ygopro } from "../../../idl/ocgcore";
import
{
YgoProPacket
}
from
"
../../packet
"
;
import
{
YgoProPacket
}
from
"
../../packet
"
;
import
{
CTOS_RESPONSE
}
from
"
../../protoDecl
"
;
import
{
CTOS_RESPONSE
}
from
"
../../protoDecl
"
;
import
adaptSelectIdleCmdResponse
from
"
./selectIdleCmd
"
;
import
adaptSelectIdleCmdResponse
from
"
./selectIdleCmd
"
;
import
adaptSelectPlaceResponse
from
"
./selectPlace
"
;
/*
/*
* CTOS CTOS_RESPONSE
* CTOS CTOS_RESPONSE
...
@@ -22,6 +23,11 @@ export default class CtosResponsePacket extends YgoProPacket {
...
@@ -22,6 +23,11 @@ export default class CtosResponsePacket extends YgoProPacket {
break
;
break
;
}
}
case
"
select_place
"
:
{
extraData
=
adaptSelectPlaceResponse
(
response
.
select_place
);
break
;
}
default
:
{
default
:
{
break
;
break
;
}
}
...
...
src/api/ocgcore/ocgAdapter/ctos/ctosGameMsgResponse/selectPlace.ts
0 → 100644
View file @
4f900064
import
{
ygopro
}
from
"
../../../idl/ocgcore
"
;
import
{
BufferWriter
}
from
"
../../bufferIO
"
;
import
{
cardZoneToNumber
}
from
"
../../util
"
;
export
default
(
response
:
ygopro
.
CtosGameMsgResponse
.
SelectPlaceResponse
)
=>
{
const
array
=
new
Uint8Array
(
3
);
const
writer
=
new
BufferWriter
(
array
,
true
);
writer
.
writeUint8
(
response
.
player
);
writer
.
writeUint8
(
cardZoneToNumber
(
response
.
zone
));
writer
.
writeUint8
(
response
.
sequence
);
return
array
;
};
src/api/ocgcore/ocgAdapter/util.ts
View file @
4f900064
...
@@ -2,6 +2,9 @@
...
@@ -2,6 +2,9 @@
* 一些基础函数。
* 一些基础函数。
*
*
* */
* */
import
{
ygopro
}
from
"
../idl/ocgcore
"
;
export
const
UTF16_BUFFER_MAX_LEN
=
20
;
export
const
UTF16_BUFFER_MAX_LEN
=
20
;
const
FILLING_TOKEN
:
number
=
0xcccc
;
const
FILLING_TOKEN
:
number
=
0xcccc
;
...
@@ -72,3 +75,41 @@ export function utf8ArrayToStr(array: Uint8Array) {
...
@@ -72,3 +75,41 @@ export function utf8ArrayToStr(array: Uint8Array) {
return
out
;
return
out
;
}
}
export
function
cardZoneToNumber
(
zone
:
ygopro
.
CardZone
):
number
{
switch
(
zone
)
{
case
ygopro
.
CardZone
.
DECK
:
{
return
0x01
;
}
case
ygopro
.
CardZone
.
HAND
:
{
return
0x02
;
}
case
ygopro
.
CardZone
.
MZONE
:
{
return
0x04
;
}
case
ygopro
.
CardZone
.
SZONE
:
{
return
0x08
;
}
case
ygopro
.
CardZone
.
GRAVE
:
{
return
0x10
;
}
case
ygopro
.
CardZone
.
REMOVED
:
{
return
0x20
;
}
case
ygopro
.
CardZone
.
EXTRA
:
{
return
0x40
;
}
case
ygopro
.
CardZone
.
OVERLAY
:
{
return
0x80
;
}
case
ygopro
.
CardZone
.
ONFIELD
:
{
return
0x0c
;
}
case
ygopro
.
CardZone
.
FZONE
:
{
return
0x100
;
}
case
ygopro
.
CardZone
.
PZONE
:
{
return
0x200
;
}
}
}
src/api/ocgcore/ocgHelper.ts
View file @
4f900064
...
@@ -131,3 +131,22 @@ export function sendSelectIdleCmdResponse(value: number) {
...
@@ -131,3 +131,22 @@ export function sendSelectIdleCmdResponse(value: number) {
socketMiddleWare
({
cmd
:
socketCmd
.
SEND
,
payload
});
socketMiddleWare
({
cmd
:
socketCmd
.
SEND
,
payload
});
}
}
export
function
sendSelectPlaceResponse
(
value
:
{
controler
:
number
;
zone
:
ygopro
.
CardZone
;
sequence
:
number
;
})
{
const
response
=
new
ygopro
.
YgoCtosMsg
({
ctos_response
:
new
ygopro
.
CtosGameMsgResponse
({
select_place
:
new
ygopro
.
CtosGameMsgResponse
.
SelectPlaceResponse
({
player
:
value
.
controler
,
zone
:
value
.
zone
,
sequence
:
value
.
sequence
,
}),
}),
});
const
payload
=
new
GameMsgResponse
(
response
).
serialize
();
socketMiddleWare
({
cmd
:
socketCmd
.
SEND
,
payload
});
}
src/reducers/duel/handsSlice.ts
View file @
4f900064
...
@@ -126,7 +126,7 @@ export const addHandsInteractivityImpl: CaseReducer<
...
@@ -126,7 +126,7 @@ export const addHandsInteractivityImpl: CaseReducer<
PayloadAction
<
{
PayloadAction
<
{
player
:
number
;
player
:
number
;
index
:
number
;
index
:
number
;
interactivity
:
Interactivity
;
interactivity
:
Interactivity
<
number
>
;
}
>
}
>
>
=
(
state
,
action
)
=>
{
>
=
(
state
,
action
)
=>
{
const
player
=
action
.
payload
.
player
;
const
player
=
action
.
payload
.
player
;
...
...
src/reducers/duel/mod.ts
View file @
4f900064
...
@@ -23,17 +23,30 @@ import {
...
@@ -23,17 +23,30 @@ import {
setCardModalImgUrlImpl
,
setCardModalImgUrlImpl
,
setCardModalInteractiviesImpl
,
setCardModalInteractiviesImpl
,
}
from
"
./modalSlice
"
;
}
from
"
./modalSlice
"
;
import
{
MonsterState
,
initMonstersImpl
,
addMonsterPlaceSelectAbleImpl
,
clearMonsterSelectInfoImpl
,
}
from
"
./monstersSlice
"
;
export
interface
DuelState
{
export
interface
DuelState
{
selfType
?:
number
;
selfType
?:
number
;
meInitInfo
?:
InitInfo
;
// 自己的初始状态
meInitInfo
?:
InitInfo
;
// 自己的初始状态
opInitInfo
?:
InitInfo
;
// 对手的初始状态
opInitInfo
?:
InitInfo
;
// 对手的初始状态
meHands
?:
Hands
;
// 自己的手牌
meHands
?:
Hands
;
// 自己的手牌
opHands
?:
Hands
;
// 对手的手牌
opHands
?:
Hands
;
// 对手的手牌
meMonsters
?:
MonsterState
;
// 自己的怪兽区状态
opMonsters
?:
MonsterState
;
// 对手的怪兽区状态
meTimeLimit
?:
TimeLimit
;
// 自己的计时
meTimeLimit
?:
TimeLimit
;
// 自己的计时
opTimeLimit
?:
TimeLimit
;
// 对手的计时
opTimeLimit
?:
TimeLimit
;
// 对手的计时
meHint
?:
HintState
;
// 自己的提示
meHint
?:
HintState
;
// 自己的提示
opHint
?:
HintState
;
// 对手的提示
opHint
?:
HintState
;
// 对手的提示
currentPlayer
?:
number
;
// 当前的操作方
currentPlayer
?:
number
;
// 当前的操作方
currentPhase
?:
string
;
// 当前的阶段
currentPhase
?:
string
;
// 当前的阶段
...
@@ -63,6 +76,11 @@ const duelSlice = createSlice({
...
@@ -63,6 +76,11 @@ const duelSlice = createSlice({
clearHandsInteractivity
:
clearHandsInteractivityImpl
,
clearHandsInteractivity
:
clearHandsInteractivityImpl
,
addHandsInteractivity
:
addHandsInteractivityImpl
,
addHandsInteractivity
:
addHandsInteractivityImpl
,
// 怪兽区相关`Reducer`
initMonsters
:
initMonstersImpl
,
addMonsterPlaceSelectAble
:
addMonsterPlaceSelectAbleImpl
,
clearMonsterSelectInfo
:
clearMonsterSelectInfoImpl
,
// UI相关`Reducer`
// UI相关`Reducer`
setCardModalIsOpen
:
setCardModalIsOpenImpl
,
setCardModalIsOpen
:
setCardModalIsOpenImpl
,
setCardModalText
:
setCardModalTextImpl
,
setCardModalText
:
setCardModalTextImpl
,
...
@@ -87,6 +105,9 @@ export const {
...
@@ -87,6 +105,9 @@ export const {
setCardModalText
,
setCardModalText
,
setCardModalImgUrl
,
setCardModalImgUrl
,
setCardModalInteractivies
,
setCardModalInteractivies
,
initMonsters
,
addMonsterPlaceSelectAble
,
clearMonsterSelectInfo
,
}
=
duelSlice
.
actions
;
}
=
duelSlice
.
actions
;
export
const
selectDuelHsStart
=
(
state
:
RootState
)
=>
{
export
const
selectDuelHsStart
=
(
state
:
RootState
)
=>
{
return
state
.
duel
.
meInitInfo
!=
null
;
return
state
.
duel
.
meInitInfo
!=
null
;
...
...
src/reducers/duel/monstersSlice.ts
0 → 100644
View file @
4f900064
import
{
judgeSelf
,
Monster
,
InteractType
}
from
"
./util
"
;
import
{
PayloadAction
,
CaseReducer
}
from
"
@reduxjs/toolkit
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
RootState
}
from
"
../../store
"
;
export
interface
MonsterState
{
monsters
:
Monster
[];
}
// 初始化自己的怪兽区状态
export
const
initMonstersImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
number
>>
=
(
state
,
action
)
=>
{
const
player
=
action
.
payload
;
const
monsters
=
{
monsters
:
[
{
sequence
:
0
,
},
{
sequence
:
1
,
},
{
sequence
:
2
,
},
{
sequence
:
3
,
},
{
sequence
:
4
,
},
],
};
if
(
judgeSelf
(
player
,
state
))
{
state
.
meMonsters
=
monsters
;
}
else
{
state
.
opMonsters
=
monsters
;
}
};
export
const
addMonsterPlaceSelectAbleImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
[
number
,
number
]
>
>
=
(
state
,
action
)
=>
{
const
controler
=
action
.
payload
[
0
];
const
sequence
=
action
.
payload
[
1
];
const
monsters
=
judgeSelf
(
controler
,
state
)
?
state
.
meMonsters
:
state
.
opMonsters
;
if
(
monsters
)
{
for
(
const
monster
of
monsters
.
monsters
)
{
if
(
monster
.
sequence
==
sequence
)
{
monster
.
selectInfo
=
{
interactType
:
InteractType
.
PLACE_SELECTABLE
,
response
:
{
controler
,
zone
:
ygopro
.
CardZone
.
MZONE
,
sequence
,
},
};
}
}
}
};
export
const
clearMonsterSelectInfoImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
number
>
>
=
(
state
,
action
)
=>
{
const
player
=
action
.
payload
;
const
monsters
=
judgeSelf
(
player
,
state
)
?
state
.
meMonsters
:
state
.
opMonsters
;
if
(
monsters
)
{
monsters
.
monsters
=
[];
}
};
export
const
selectMeMonsters
=
(
state
:
RootState
)
=>
state
.
duel
.
meMonsters
||
{
monsters
:
[]
};
src/reducers/duel/util.ts
View file @
4f900064
...
@@ -6,6 +6,7 @@
...
@@ -6,6 +6,7 @@
import
{
CardMeta
}
from
"
../../api/cards
"
;
import
{
CardMeta
}
from
"
../../api/cards
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
Draft
}
from
"
@reduxjs/toolkit
"
;
import
{
Draft
}
from
"
@reduxjs/toolkit
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
/*
/*
* 通过`player`和`selfType`判断是应该处理自己还是对手
* 通过`player`和`selfType`判断是应该处理自己还是对手
...
@@ -30,7 +31,7 @@ export function judgeSelf(player: number, state: Draft<DuelState>): boolean {
...
@@ -30,7 +31,7 @@ export function judgeSelf(player: number, state: Draft<DuelState>): boolean {
export
interface
Card
{
export
interface
Card
{
meta
:
CardMeta
;
meta
:
CardMeta
;
transform
:
CardTransform
;
transform
:
CardTransform
;
interactivities
:
Interactivity
[];
interactivities
:
Interactivity
<
number
>
[];
}
}
interface
CardTransform
{
interface
CardTransform
{
...
@@ -59,12 +60,24 @@ export enum InteractType {
...
@@ -59,12 +60,24 @@ export enum InteractType {
SSET
=
5
,
SSET
=
5
,
// 可发动效果
// 可发动效果
ACTIVATE
=
6
,
ACTIVATE
=
6
,
// 可作为位置选择
PLACE_SELECTABLE
=
7
,
}
}
export
interface
Interactivity
{
export
interface
Interactivity
<
T
>
{
interactType
:
InteractType
;
interactType
:
InteractType
;
// 如果`interactType`是`ACTIVATE`,这个字段是对应的效果编号
// 如果`interactType`是`ACTIVATE`,这个字段是对应的效果编号
activateIndex
?:
number
;
activateIndex
?:
number
;
// 用户点击后,需要回传给服务端的`response`
// 用户点击后,需要回传给服务端的`response`
response
:
number
;
response
:
T
;
}
export
interface
Monster
{
sequence
:
number
;
occupant
?:
CardMeta
;
selectInfo
?:
Interactivity
<
{
controler
:
number
;
zone
:
ygopro
.
CardZone
;
sequence
:
number
;
}
>
;
}
}
src/service/duel/selectPlace.ts
View file @
4f900064
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
AppDispatch
}
from
"
../../store
"
;
import
{
AppDispatch
}
from
"
../../store
"
;
import
MsgSelectPlace
=
ygopro
.
StocGameMessage
.
MsgSelectPlace
;
import
MsgSelectPlace
=
ygopro
.
StocGameMessage
.
MsgSelectPlace
;
import
{
addMonsterPlaceSelectAble
}
from
"
../../reducers/duel/mod
"
;
export
default
(
selectPlace
:
MsgSelectPlace
,
dispatch
:
AppDispatch
)
=>
{
export
default
(
selectPlace
:
MsgSelectPlace
,
dispatch
:
AppDispatch
)
=>
{
// TODO
if
(
selectPlace
.
count
!=
1
)
{
console
.
warn
(
`Unhandled case:
${
selectPlace
}
`
);
console
.
log
(
selectPlace
);
return
;
}
for
(
const
place
of
selectPlace
.
places
)
{
switch
(
place
.
zone
)
{
case
ygopro
.
CardZone
.
MZONE
:
{
dispatch
(
addMonsterPlaceSelectAble
([
place
.
controler
,
place
.
sequence
]));
break
;
}
default
:
{
console
.
warn
(
`Unhandled zoneType:
${
place
.
zone
}
`
);
}
}
}
};
};
src/service/duel/start.ts
View file @
4f900064
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
AppDispatch
}
from
"
../../store
"
;
import
{
AppDispatch
}
from
"
../../store
"
;
import
{
infoInit
,
setSelfType
}
from
"
../../reducers/duel/mod
"
;
import
{
infoInit
,
setSelfType
,
initMonsters
}
from
"
../../reducers/duel/mod
"
;
export
default
(
export
default
(
start
:
ygopro
.
StocGameMessage
.
MsgStart
,
start
:
ygopro
.
StocGameMessage
.
MsgStart
,
...
@@ -27,4 +27,6 @@ export default (
...
@@ -27,4 +27,6 @@ export default (
},
},
])
])
);
);
dispatch
(
initMonsters
(
0
));
dispatch
(
initMonsters
(
1
));
};
};
src/ui/Duel/extraMonsters.ts
View file @
4f900064
...
@@ -6,7 +6,7 @@ export default (scene: BABYLON.Scene) => {
...
@@ -6,7 +6,7 @@ export default (scene: BABYLON.Scene) => {
const
shape
=
CONFIG
.
CardSlotShape
();
const
shape
=
CONFIG
.
CardSlotShape
();
for
(
let
i
in
xs
)
{
for
(
let
i
in
xs
)
{
const
slot
=
BABYLON
.
MeshBuilder
.
Create
Box
(
const
slot
=
BABYLON
.
MeshBuilder
.
Create
Plane
(
`extraMonster
${
i
}
`
,
`extraMonster
${
i
}
`
,
shape
,
shape
,
scene
scene
...
@@ -24,7 +24,10 @@ export default (scene: BABYLON.Scene) => {
...
@@ -24,7 +24,10 @@ export default (scene: BABYLON.Scene) => {
"
extraMonsterMaterial
"
,
"
extraMonsterMaterial
"
,
scene
scene
);
);
extraMonsterMaterial
.
diffuseColor
=
CONFIG
.
extraMonsterColor
();
extraMonsterMaterial
.
diffuseTexture
=
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_slot.png`
);
extraMonsterMaterial
.
diffuseTexture
.
hasAlpha
=
true
;
slot
.
material
=
extraMonsterMaterial
;
slot
.
material
=
extraMonsterMaterial
;
}
}
};
};
src/ui/Duel/magics.ts
View file @
4f900064
...
@@ -7,7 +7,7 @@ export default (scene: BABYLON.Scene) => {
...
@@ -7,7 +7,7 @@ export default (scene: BABYLON.Scene) => {
const
shape
=
CONFIG
.
CardSlotShape
();
const
shape
=
CONFIG
.
CardSlotShape
();
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
slot
=
BABYLON
.
MeshBuilder
.
Create
Box
(
`magic
${
i
}
`
,
shape
,
scene
);
const
slot
=
BABYLON
.
MeshBuilder
.
Create
Plane
(
`magic
${
i
}
`
,
shape
,
scene
);
// 位置
// 位置
slot
.
position
=
new
BABYLON
.
Vector3
(
slot
.
position
=
new
BABYLON
.
Vector3
(
left
+
gap
*
i
,
left
+
gap
*
i
,
...
@@ -18,7 +18,10 @@ export default (scene: BABYLON.Scene) => {
...
@@ -18,7 +18,10 @@ export default (scene: BABYLON.Scene) => {
slot
.
rotation
=
CONFIG
.
CardSlotRotation
();
slot
.
rotation
=
CONFIG
.
CardSlotRotation
();
// 材质
// 材质
const
magicMaterial
=
new
BABYLON
.
StandardMaterial
(
"
magicMaterial
"
,
scene
);
const
magicMaterial
=
new
BABYLON
.
StandardMaterial
(
"
magicMaterial
"
,
scene
);
magicMaterial
.
diffuseColor
=
CONFIG
.
MagicColor
();
magicMaterial
.
diffuseTexture
=
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_slot.png`
);
magicMaterial
.
diffuseTexture
.
hasAlpha
=
true
;
slot
.
material
=
magicMaterial
;
slot
.
material
=
magicMaterial
;
}
}
};
};
src/ui/Duel/mod.tsx
View file @
4f900064
...
@@ -21,6 +21,7 @@ import { selectCurrentPlayer } from "../../reducers/duel/turnSlice";
...
@@ -21,6 +21,7 @@ import { selectCurrentPlayer } from "../../reducers/duel/turnSlice";
import
CardModal
from
"
./cardModal
"
;
import
CardModal
from
"
./cardModal
"
;
import
HintNotification
from
"
./hintNotification
"
;
import
HintNotification
from
"
./hintNotification
"
;
import
{
selectMeHands
}
from
"
../../reducers/duel/handsSlice
"
;
import
{
selectMeHands
}
from
"
../../reducers/duel/handsSlice
"
;
import
{
selectMeMonsters
}
from
"
../../reducers/duel/monstersSlice
"
;
// CONFIG
// CONFIG
...
@@ -28,6 +29,7 @@ const Duel = () => {
...
@@ -28,6 +29,7 @@ const Duel = () => {
// ----- 数据获取 -----
// ----- 数据获取 -----
const
hands
=
useAppSelector
(
selectMeHands
).
cards
;
const
hands
=
useAppSelector
(
selectMeHands
).
cards
;
const
monsters
=
useAppSelector
(
selectMeMonsters
).
monsters
;
const
currentPlayer
=
useAppSelector
(
selectCurrentPlayer
);
const
currentPlayer
=
useAppSelector
(
selectCurrentPlayer
);
// ----- WebGL渲染 -----
// ----- WebGL渲染 -----
...
@@ -60,7 +62,7 @@ const Duel = () => {
...
@@ -60,7 +62,7 @@ const Duel = () => {
renderMagics
(
scene
);
renderMagics
(
scene
);
// 怪兽区
// 怪兽区
renderMonsters
(
scene
);
renderMonsters
(
monsters
,
scene
);
// 创建额外怪兽区
// 创建额外怪兽区
renderExtraMonsters
(
scene
);
renderExtraMonsters
(
scene
);
...
@@ -105,7 +107,7 @@ const Duel = () => {
...
@@ -105,7 +107,7 @@ const Duel = () => {
engine
.
runRenderLoop
(()
=>
{
engine
.
runRenderLoop
(()
=>
{
scene
.
render
();
scene
.
render
();
});
});
},
[
canvasRef
,
hands
,
currentPlayer
]);
},
[
canvasRef
,
hands
,
monsters
,
currentPlayer
]);
// FIXME: 这里需要优化,应该分组件按需渲染
useEffect
(()
=>
{
useEffect
(()
=>
{
// 监听状态变化,并实现动画
// 监听状态变化,并实现动画
...
...
src/ui/Duel/monsters.ts
View file @
4f900064
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
{
Monster
}
from
"
../../reducers/duel/util
"
;
import
{
clearMonsterSelectInfo
}
from
"
../../reducers/duel/mod
"
;
import
{
store
}
from
"
../../store
"
;
import
{
sendSelectPlaceResponse
}
from
"
../../api/ocgcore/ocgHelper
"
;
export
default
(
scene
:
BABYLON
.
Scene
)
=>
{
export
default
(
monsters
:
Monster
[],
scene
:
BABYLON
.
Scene
)
=>
{
const
left
=
-
2.15
;
const
left
=
-
2.15
;
const
gap
=
1.05
;
const
gap
=
1.05
;
const
shape
=
CONFIG
.
CardSlotShape
();
const
shape
=
CONFIG
.
CardSlotShape
();
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
for
(
const
monster
of
monsters
)
{
const
slot
=
BABYLON
.
MeshBuilder
.
CreateBox
(
`monster
${
i
}
`
,
shape
,
scene
);
const
slot
=
BABYLON
.
MeshBuilder
.
CreatePlane
(
// 位置
`monster
${
monster
.
sequence
}
`
,
slot
.
position
=
new
BABYLON
.
Vector3
(
shape
,
left
+
gap
*
i
,
scene
shape
.
depth
/
2
+
CONFIG
.
Floating
,
-
1.35
);
);
// 位置
setupMonsterTransform
(
slot
,
monster
,
left
,
gap
,
shape
);
// 旋转
// 旋转
slot
.
rotation
=
CONFIG
.
CardSlotRotation
();
slot
.
rotation
=
CONFIG
.
CardSlotRotation
();
// 材质
// 材质
const
monsterMaterial
=
new
BABYLON
.
StandardMaterial
(
setupMonsterMaterial
(
slot
,
monster
,
scene
);
"
monsterMaterial
"
,
// 高亮
scene
setupHintEdge
(
slot
,
monster
);
);
// 事件管理
monsterMaterial
.
diffuseColor
=
CONFIG
.
MonsterColor
();
setupMonsterAction
(
slot
,
monster
,
scene
);
slot
.
material
=
monsterMaterial
;
}
}
};
};
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
));
}
}
)
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment