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
26ff2f20
Commit
26ff2f20
authored
Jan 13, 2023
by
Chunchi Che
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat/field' into 'main'
Feat/field See merge request
mycard/Neos!73
parents
6b2d3fe5
e5e57d18
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
204 additions
and
201 deletions
+204
-201
src/reducers/duel/fieldSlice.ts
src/reducers/duel/fieldSlice.ts
+44
-0
src/reducers/duel/mod.ts
src/reducers/duel/mod.ts
+9
-0
src/service/duel/start.ts
src/service/duel/start.ts
+6
-0
src/ui/Duel/field.tsx
src/ui/Duel/field.tsx
+34
-17
src/ui/Duel/fixedSlot.tsx
src/ui/Duel/fixedSlot.tsx
+104
-0
src/ui/Duel/magics.tsx
src/ui/Duel/magics.tsx
+3
-85
src/ui/Duel/main.tsx
src/ui/Duel/main.tsx
+1
-0
src/ui/Duel/monsters.tsx
src/ui/Duel/monsters.tsx
+3
-99
No files found.
src/reducers/duel/fieldSlice.ts
0 → 100644
View file @
26ff2f20
import
{
judgeSelf
}
from
"
./util
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
RootState
}
from
"
../../store
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
PayloadAction
,
CaseReducer
}
from
"
@reduxjs/toolkit
"
;
import
{
CardState
}
from
"
./generic
"
;
export
interface
FieldState
{
inner
?:
CardState
;
}
// 初始化场地区状态
export
const
initFieldImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
number
>>
=
(
state
,
action
)
=>
{
const
player
=
action
.
payload
;
if
(
judgeSelf
(
player
,
state
))
{
state
.
meField
=
{
inner
:
{
location
:
{
controler
:
player
,
sequence
:
0
,
location
:
ygopro
.
CardZone
.
ONFIELD
,
},
idleInteractivities
:
[],
},
};
}
else
{
state
.
opField
=
{
inner
:
{
location
:
{
controler
:
player
,
sequence
:
0
,
location
:
ygopro
.
CardZone
.
ONFIELD
,
},
idleInteractivities
:
[],
},
};
}
};
export
const
selectMeField
=
(
state
:
RootState
)
=>
state
.
duel
.
meField
;
export
const
selectOpField
=
(
state
:
RootState
)
=>
state
.
duel
.
opField
;
src/reducers/duel/mod.ts
View file @
26ff2f20
...
...
@@ -62,6 +62,7 @@ import {
exclusionCase
,
}
from
"
./exclusionSlice
"
;
import
{
DeckState
,
initDeckImpl
}
from
"
./deckSlice
"
;
import
{
FieldState
,
initFieldImpl
}
from
"
./fieldSlice
"
;
export
interface
DuelState
{
selfType
?:
number
;
...
...
@@ -86,6 +87,9 @@ export interface DuelState {
meDeck
?:
DeckState
;
// 自己的卡组状态
opDeck
?:
DeckState
;
// 对手的卡组状态
meField
?:
FieldState
;
// 自己的场地区状态
opField
?:
FieldState
;
// 对手的场地区状态
meTimeLimit
?:
TimeLimit
;
// 自己的计时
opTimeLimit
?:
TimeLimit
;
// 对手的计时
...
...
@@ -146,6 +150,9 @@ const duelSlice = createSlice({
// 卡组相关`Reducer`
initDeck
:
initDeckImpl
,
// 场地区相关`Reducer`
initField
:
initFieldImpl
,
// UI相关`Reducer`
setCardModalIsOpen
:
setCardModalIsOpenImpl
,
setCardModalText
:
setCardModalTextImpl
,
...
...
@@ -214,6 +221,8 @@ export const {
setOptionModalIsOpen
,
resetOptionModal
,
initDeck
,
initExclusion
,
initField
,
}
=
duelSlice
.
actions
;
export
const
selectDuelHsStart
=
(
state
:
RootState
)
=>
{
return
state
.
duel
.
meInitInfo
!=
null
;
...
...
src/service/duel/start.ts
View file @
26ff2f20
...
...
@@ -7,6 +7,8 @@ import {
initMagics
,
initCemetery
,
initDeck
,
initExclusion
,
initField
,
}
from
"
../../reducers/duel/mod
"
;
export
default
(
...
...
@@ -42,4 +44,8 @@ export default (
dispatch
(
initCemetery
(
1
));
dispatch
(
initDeck
({
player
:
0
,
deskSize
:
start
.
deckSize1
}));
dispatch
(
initDeck
({
player
:
1
,
deskSize
:
start
.
deckSize2
}));
dispatch
(
initExclusion
(
0
));
dispatch
(
initExclusion
(
1
));
dispatch
(
initField
(
0
));
dispatch
(
initField
(
1
));
};
src/ui/Duel/field.tsx
View file @
26ff2f20
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
CONFIG
from
"
../../config/ui
"
;
import
{
useAppSelector
}
from
"
../../hook
"
;
import
{
selectMeField
,
selectOpField
}
from
"
../../reducers/duel/fieldSlice
"
;
import
FixedSlot
from
"
./fixedSlot
"
;
import
{
Depth
}
from
"
./singleSlot
"
;
const
Field
=
()
=>
{
const
shape
=
CONFIG
.
FieldSlotShape
();
const
position
=
new
BABYLON
.
Vector3
(
-
3.3
,
shape
.
depth
/
2
+
CONFIG
.
Floating
,
-
2.0
);
const
rotation
=
CONFIG
.
FieldSlotRotation
();
const
meField
=
useAppSelector
(
selectMeField
)?.
inner
;
const
opField
=
useAppSelector
(
selectOpField
)?.
inner
;
return
(
<
box
name=
"field"
width=
{
shape
.
width
}
height=
{
shape
.
height
}
depth=
{
shape
.
depth
}
position=
{
position
}
rotation=
{
rotation
}
>
<
standardMaterial
name=
"field-mat"
diffuseColor=
{
CONFIG
.
FieldColor
()
}
/>
</
box
>
<>
{
meField
?
(
<
FixedSlot
state=
{
meField
}
position=
{
fieldPosition
(
0
)
}
rotation=
{
CONFIG
.
CardSlotRotation
(
false
)
}
/>
)
:
(
<></>
)
}
{
opField
?
(
<
FixedSlot
state=
{
opField
}
position=
{
fieldPosition
(
1
)
}
rotation=
{
CONFIG
.
CardSlotRotation
(
true
)
}
/>
)
:
(
<></>
)
}
</>
);
};
const
fieldPosition
=
(
player
:
number
)
=>
{
const
x
=
player
==
0
?
-
3.3
:
3.3
;
const
y
=
Depth
/
2
+
CONFIG
.
Floating
;
const
z
=
player
==
0
?
-
2.0
:
2.0
;
return
new
BABYLON
.
Vector3
(
x
,
y
,
z
);
};
export
default
Field
;
src/ui/Duel/fixedSlot.tsx
0 → 100644
View file @
26ff2f20
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
CONFIG
from
"
../../config/ui
"
;
import
{
store
}
from
"
../../store
"
;
import
{
CardState
}
from
"
../../reducers/duel/generic
"
;
import
{
useRef
}
from
"
react
"
;
import
{
useClick
}
from
"
./hook
"
;
import
{
sendSelectPlaceResponse
}
from
"
../../api/ocgcore/ocgHelper
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
clearMonsterPlaceInteractivities
,
setCardModalImgUrl
,
setCardModalInteractivies
,
setCardModalIsOpen
,
setCardModalText
,
}
from
"
../../reducers/duel/mod
"
;
const
shape
=
CONFIG
.
CardSlotShape
();
const
FixedSlot
=
(
props
:
{
state
:
CardState
;
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
deffenseRotation
?:
BABYLON
.
Vector3
;
})
=>
{
const
planeRef
=
useRef
(
null
);
const
rotation
=
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEUP_DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
?
props
.
deffenseRotation
||
CONFIG
.
CardSlotDefenceRotation
()
:
props
.
rotation
;
const
edgesWidth
=
2.0
;
const
edgesColor
=
BABYLON
.
Color4
.
FromColor3
(
BABYLON
.
Color3
.
Yellow
());
const
dispatch
=
store
.
dispatch
;
const
faceDown
=
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_ATTACK
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN
;
useClick
(
(
_event
)
=>
{
if
(
props
.
state
.
placeInteractivities
)
{
sendSelectPlaceResponse
(
props
.
state
.
placeInteractivities
.
response
);
dispatch
(
clearMonsterPlaceInteractivities
(
0
));
dispatch
(
clearMonsterPlaceInteractivities
(
1
));
}
else
if
(
props
.
state
.
occupant
)
{
dispatch
(
setCardModalText
([
props
.
state
.
occupant
.
text
.
name
,
props
.
state
.
occupant
.
text
.
desc
,
])
);
dispatch
(
setCardModalImgUrl
(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/
${
props
.
state
.
occupant
.
id
}
.jpg`
)
);
dispatch
(
setCardModalInteractivies
([]));
// TODO
dispatch
(
setCardModalIsOpen
(
true
));
}
},
planeRef
,
[
props
.
state
]
);
return
(
<
plane
name=
{
`fixedslot-${props.state.location.sequence}`
}
ref=
{
planeRef
}
width=
{
shape
.
width
}
height=
{
shape
.
height
}
position=
{
props
.
position
}
rotation=
{
rotation
}
enableEdgesRendering
edgesWidth=
{
props
.
state
.
placeInteractivities
||
props
.
state
.
idleInteractivities
.
length
>
0
?
edgesWidth
:
0
}
edgesColor=
{
edgesColor
}
>
<
standardMaterial
name=
{
`fixedslot-mat-${props.state.location.sequence}`
}
diffuseTexture=
{
props
.
state
.
occupant
?
faceDown
?
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_back.jpg`
)
:
new
BABYLON
.
Texture
(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${props.state.occupant.id}.jpg`
)
:
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_slot.png`
)
}
alpha=
{
props
.
state
.
occupant
?
1
:
0
}
></
standardMaterial
>
</
plane
>
);
};
export
default
FixedSlot
;
src/ui/Duel/magics.tsx
View file @
26ff2f20
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
CONFIG
from
"
../../config/ui
"
;
import
{
selectMeMagics
,
selectOpMagics
}
from
"
../../reducers/duel/magicSlice
"
;
import
{
useClick
}
from
"
./hook
"
;
import
{
CardState
}
from
"
../../reducers/duel/generic
"
;
import
{
store
}
from
"
../../store
"
;
import
{
useAppSelector
}
from
"
../../hook
"
;
import
{
useRef
}
from
"
react
"
;
import
{
sendSelectPlaceResponse
}
from
"
../../api/ocgcore/ocgHelper
"
;
import
{
clearMagicPlaceInteractivities
,
setCardModalImgUrl
,
setCardModalIsOpen
,
setCardModalText
,
}
from
"
../../reducers/duel/mod
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
zip
}
from
"
./util
"
;
import
FixedSlot
from
"
./fixedSlot
"
;
// TODO: use config
const
left
=
-
2.15
;
...
...
@@ -31,7 +21,7 @@ const Magics = () => {
<>
{
zip
(
meMagics
,
meMagicPositions
).
map
(([
magic
,
position
])
=>
{
return
(
<
CMagic
<
FixedSlot
state=
{
magic
}
key=
{
magic
.
location
.
sequence
}
position=
{
position
}
...
...
@@ -41,7 +31,7 @@ const Magics = () => {
})
}
{
zip
(
opMagics
,
opMagicPositions
).
map
(([
magic
,
position
])
=>
{
return
(
<
CMagic
<
FixedSlot
state=
{
magic
}
key=
{
magic
.
location
.
sequence
}
position=
{
position
}
...
...
@@ -53,78 +43,6 @@ const Magics = () => {
);
};
const
CMagic
=
(
props
:
{
state
:
CardState
;
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
})
=>
{
const
state
=
props
.
state
;
const
planeRef
=
useRef
(
null
);
const
faceDown
=
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN
||
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_ATTACK
||
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
;
const
edgesWidth
=
2.0
;
const
edgesColor
=
BABYLON
.
Color4
.
FromColor3
(
BABYLON
.
Color3
.
Yellow
());
const
dispatch
=
store
.
dispatch
;
useClick
(
(
_event
)
=>
{
if
(
state
.
placeInteractivities
)
{
sendSelectPlaceResponse
(
state
.
placeInteractivities
.
response
);
dispatch
(
clearMagicPlaceInteractivities
(
0
));
dispatch
(
clearMagicPlaceInteractivities
(
1
));
}
else
if
(
state
.
occupant
)
{
dispatch
(
setCardModalText
([
state
.
occupant
.
text
.
name
,
state
.
occupant
.
text
.
desc
])
);
dispatch
(
setCardModalImgUrl
(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/
${
state
.
occupant
.
id
}
.jpg`
)
);
dispatch
(
setCardModalIsOpen
(
true
));
}
},
planeRef
,
[
state
]
);
return
(
<
plane
name=
{
`magic-${state.location.sequence}`
}
ref=
{
planeRef
}
width=
{
shape
.
width
}
height=
{
shape
.
height
}
position=
{
props
.
position
}
rotation=
{
props
.
rotation
}
enableEdgesRendering
edgesWidth=
{
state
.
placeInteractivities
||
state
.
idleInteractivities
.
length
>
0
?
edgesWidth
:
0
}
edgesColor=
{
edgesColor
}
>
<
standardMaterial
name=
{
`magic-mat-${props.state.location.sequence}`
}
diffuseTexture=
{
state
.
occupant
?
faceDown
?
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_back.jpg`
)
:
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`
)
}
alpha=
{
state
.
occupant
?
1
:
0
}
></
standardMaterial
>
</
plane
>
);
};
const
magicPositions
=
(
player
:
number
,
magics
:
CardState
[])
=>
{
const
x
=
(
sequence
:
number
)
=>
player
==
0
?
left
+
gap
*
sequence
:
-
left
-
gap
*
sequence
;
...
...
src/ui/Duel/main.tsx
View file @
26ff2f20
...
...
@@ -35,6 +35,7 @@ const NeosDuel = () => (
<
Deck
/>
<
Cemeteries
/>
<
Exclusion
/>
<
Field
/>
<
Ground
/>
</
Provider
>
</
Scene
>
...
...
src/ui/Duel/monsters.tsx
View file @
26ff2f20
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
CONFIG
from
"
../../config/ui
"
;
import
{
useClick
}
from
"
./hook
"
;
import
{
store
}
from
"
../../store
"
;
import
{
CardState
}
from
"
../../reducers/duel/generic
"
;
import
"
react-babylonjs
"
;
import
{
useRef
}
from
"
react
"
;
import
{
sendSelectPlaceResponse
}
from
"
../../api/ocgcore/ocgHelper
"
;
import
{
clearMonsterPlaceInteractivities
,
setCardModalImgUrl
,
setCardModalInteractivies
,
setCardModalIsOpen
,
setCardModalText
,
}
from
"
../../reducers/duel/mod
"
;
import
{
useAppSelector
}
from
"
../../hook
"
;
import
{
selectMeMonsters
,
selectOpMonsters
,
}
from
"
../../reducers/duel/monstersSlice
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
zip
}
from
"
./util
"
;
import
FixedSlot
from
"
./fixedSlot
"
;
const
shape
=
CONFIG
.
CardSlotShape
();
const
left
=
-
2.15
;
// TODO: config
...
...
@@ -35,7 +24,7 @@ const Monsters = () => {
<>
{
zip
(
meMonsters
,
meMonsterPositions
).
map
(([
monster
,
position
],
idx
)
=>
{
return
(
<
CommonMonster
<
FixedSlot
state=
{
monster
}
key=
{
idx
}
position=
{
position
}
...
...
@@ -46,7 +35,7 @@ const Monsters = () => {
})
}
{
zip
(
opMonsters
,
opMonsterPositions
).
map
(([
monster
,
position
],
idx
)
=>
{
return
(
<
CommonMonster
<
FixedSlot
state=
{
monster
}
key=
{
idx
}
position=
{
position
}
...
...
@@ -61,91 +50,6 @@ const Monsters = () => {
);
};
const
CommonMonster
=
(
props
:
{
state
:
CardState
;
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
deffenseRotation
:
BABYLON
.
Vector3
;
})
=>
{
const
planeRef
=
useRef
(
null
);
const
rotation
=
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEUP_DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
?
props
.
deffenseRotation
:
props
.
rotation
;
const
edgesWidth
=
2.0
;
const
edgesColor
=
BABYLON
.
Color4
.
FromColor3
(
BABYLON
.
Color3
.
Yellow
());
const
dispatch
=
store
.
dispatch
;
const
faceDown
=
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_ATTACK
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN
;
useClick
(
(
_event
)
=>
{
if
(
props
.
state
.
placeInteractivities
)
{
sendSelectPlaceResponse
(
props
.
state
.
placeInteractivities
.
response
);
dispatch
(
clearMonsterPlaceInteractivities
(
0
));
dispatch
(
clearMonsterPlaceInteractivities
(
1
));
}
else
if
(
props
.
state
.
occupant
)
{
dispatch
(
setCardModalText
([
props
.
state
.
occupant
.
text
.
name
,
props
.
state
.
occupant
.
text
.
desc
,
])
);
dispatch
(
setCardModalImgUrl
(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/
${
props
.
state
.
occupant
.
id
}
.jpg`
)
);
dispatch
(
setCardModalInteractivies
([]));
// TODO
dispatch
(
setCardModalIsOpen
(
true
));
}
},
planeRef
,
[
props
.
state
]
);
return
(
<
plane
name=
{
`monster-${props.state.location.sequence}`
}
ref=
{
planeRef
}
width=
{
shape
.
width
}
height=
{
shape
.
height
}
position=
{
props
.
position
}
rotation=
{
rotation
}
enableEdgesRendering
edgesWidth=
{
props
.
state
.
placeInteractivities
||
props
.
state
.
idleInteractivities
.
length
>
0
?
edgesWidth
:
0
}
edgesColor=
{
edgesColor
}
>
<
standardMaterial
name=
{
`monster-mat-${props.state.location.sequence}`
}
diffuseTexture=
{
props
.
state
.
occupant
?
faceDown
?
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_back.jpg`
)
:
new
BABYLON
.
Texture
(
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/${props.state.occupant.id}.jpg`
)
:
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_slot.png`
)
}
alpha=
{
props
.
state
.
occupant
?
1
:
0
}
></
standardMaterial
>
</
plane
>
);
};
// TODO: use props and redux
const
ExtraMonsters
=
()
=>
{
const
xs
=
[
-
1.1
,
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