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
b1fba04e
Commit
b1fba04e
authored
Mar 31, 2024
by
Chunchi Che
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat/ui/chain' into 'main'
添加连锁特效(第一期) See merge request
mycard/Neos!357
parents
89b0e9c9
a1f58c83
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
204 additions
and
16 deletions
+204
-16
neos-assets/chain.png
neos-assets/chain.png
+0
-0
src/stores/placeStore.ts
src/stores/placeStore.ts
+2
-1
src/ui/Duel/Main.tsx
src/ui/Duel/Main.tsx
+2
-0
src/ui/Duel/PlayMat/Bg/index.tsx
src/ui/Duel/PlayMat/Bg/index.tsx
+43
-15
src/ui/Duel/PlayMat/HandChain/index.module.scss
src/ui/Duel/PlayMat/HandChain/index.module.scss
+18
-0
src/ui/Duel/PlayMat/HandChain/index.tsx
src/ui/Duel/PlayMat/HandChain/index.tsx
+33
-0
src/ui/Shared/Chain/index.module.scss
src/ui/Shared/Chain/index.module.scss
+60
-0
src/ui/Shared/Chain/index.tsx
src/ui/Shared/Chain/index.tsx
+45
-0
src/ui/Shared/index.ts
src/ui/Shared/index.ts
+1
-0
No files found.
neos-assets/chain.png
0 → 100644
View file @
b1fba04e
9.68 KB
src/stores/placeStore.ts
View file @
b1fba04e
...
...
@@ -20,7 +20,8 @@ const { MZONE, SZONE, HAND, GRAVE, REMOVED, EXTRA } = ygopro.CardZone;
export
interface
BlockState
{
interactivity
?:
PlaceInteractivity
;
// 互动性
disabled
:
boolean
;
// 是否被禁用
chainIndex
:
number
[];
// 当前位置上的连锁序号。YGOPRO和MASTER DUEL的连锁都是和位置绑定的,因此在`PlaceStore`中记录连锁状态。
chainIndex
:
number
[]
/* 当前位置上的连锁序号。
YGOPRO和MASTER DUEL的连锁都是和位置绑定的,因此在`PlaceStore`中记录连锁状态。*/
;
}
const
genPLaces
=
(
n
:
number
):
BlockState
[]
=>
...
...
src/ui/Duel/Main.tsx
View file @
b1fba04e
...
...
@@ -20,6 +20,7 @@ import {
}
from
"
./Message
"
;
import
{
LifeBar
,
Mat
,
Menu
,
Underlying
}
from
"
./PlayMat
"
;
import
{
ChatBox
}
from
"
./PlayMat/ChatBox
"
;
import
{
HandChain
}
from
"
./PlayMat/HandChain
"
;
export
const
Component
:
React
.
FC
=
()
=>
{
const
{
stage
}
=
useSnapshot
(
sideStore
);
...
...
@@ -59,6 +60,7 @@ export const Component: React.FC = () => {
<
SimpleSelectCardsModal
/>
<
EndModal
/>
<
ChatBox
/>
<
HandChain
/>
</>
);
};
...
...
src/ui/Duel/PlayMat/Bg/index.tsx
View file @
b1fba04e
...
...
@@ -9,20 +9,25 @@ import {
type
PlaceInteractivity
,
placeStore
,
}
from
"
@/stores
"
;
import
{
BgChain
,
ChainProps
}
from
"
@/ui/Shared
"
;
import
styles
from
"
./index.module.scss
"
;
const
{
MZONE
,
SZONE
,
EXTRA
,
GRAVE
,
REMOVED
}
=
ygopro
.
CardZone
;
const
BgBlock
:
React
.
FC
<
React
.
HTMLProps
<
HTMLDivElement
>
&
{
disabled
?:
boolean
;
highlight
?:
boolean
;
glowing
?:
boolean
;
chains
:
ChainProps
;
}
>
=
({
disabled
=
false
,
highlight
=
false
,
glowing
=
false
,
className
,
chains
,
...
rest
})
=>
(
<
div
...
...
@@ -34,6 +39,7 @@ const BgBlock: React.FC<
>
{
<
DecoTriangles
/>
}
{
<
DisabledCross
disabled=
{
disabled
}
/>
}
{
<
BgChain
{
...
chains
}
/>
}
</
div
>
);
...
...
@@ -53,6 +59,8 @@ const BgExtraRow: React.FC<{
}
}
disabled=
{
meSnap
[
i
].
disabled
||
opSnap
[
i
].
disabled
}
highlight=
{
!!
meSnap
[
i
].
interactivity
||
!!
opSnap
[
i
].
interactivity
}
/* FIXME */
chains=
{
{
chains
:
meSnap
[
i
].
chainIndex
.
concat
(
opSnap
[
i
].
chainIndex
)
}
}
/>
))
}
</
div
>
...
...
@@ -72,6 +80,7 @@ const BgRow: React.FC<{
onClick=
{
()
=>
onBlockClick
(
snap
[
i
].
interactivity
)
}
disabled=
{
snap
[
i
].
disabled
}
highlight=
{
!!
snap
[
i
].
interactivity
}
chains=
{
{
chains
:
snap
[
i
].
chainIndex
}
}
/>
))
}
</
div
>
...
...
@@ -84,27 +93,46 @@ const BgOtherBlocks: React.FC<{ op?: boolean }> = ({ op }) => {
!!
cardStore
.
at
(
zone
,
meController
)
.
reduce
((
sum
,
c
)
=>
(
sum
+=
c
.
idleInteractivities
.
length
),
0
);
const
glowingExtra
=
judgeGlowing
(
ygopro
.
CardZone
.
EXTRA
);
const
glowingGraveyard
=
judgeGlowing
(
ygopro
.
CardZone
.
GRAVE
);
const
glowingBanish
=
judgeGlowing
(
ygopro
.
CardZone
.
REMOVED
);
const
glowingExtra
=
judgeGlowing
(
EXTRA
);
const
glowingGraveyard
=
judgeGlowing
(
GRAVE
);
const
glowingBanish
=
judgeGlowing
(
REMOVED
);
const
snap
=
useSnapshot
(
placeStore
.
inner
);
const
field
=
op
?
snap
[
ygopro
.
CardZone
.
SZONE
].
op
[
5
]
:
snap
[
ygopro
.
CardZone
.
SZONE
].
me
[
5
];
const
field
=
op
?
snap
[
SZONE
].
op
[
5
]
:
snap
[
SZONE
].
me
[
5
];
const
grave
=
op
?
snap
[
GRAVE
].
op
:
snap
[
GRAVE
].
me
;
const
removed
=
op
?
snap
[
REMOVED
].
op
:
snap
[
REMOVED
].
me
;
const
extra
=
op
?
snap
[
EXTRA
].
op
:
snap
[
EXTRA
].
me
;
const
genChains
=
(
states
:
Snapshot
<
BlockState
[]
>
)
=>
{
const
chains
:
number
[]
=
states
.
flatMap
((
state
)
=>
state
.
chainIndex
);
chains
.
sort
();
return
chains
;
};
return
(
<
div
className=
{
classnames
(
styles
[
"
other-blocks
"
],
{
[
styles
.
op
]:
op
})
}
>
<
BgBlock
className=
{
styles
.
banish
}
glowing=
{
!
op
&&
glowingBanish
}
/>
<
BgBlock
className=
{
styles
.
graveyard
}
glowing=
{
!
op
&&
glowingGraveyard
}
/>
<
BgBlock
className=
{
styles
.
banish
}
glowing=
{
!
op
&&
glowingBanish
}
chains=
{
{
chains
:
genChains
(
removed
),
banish
:
true
,
op
}
}
/>
<
BgBlock
className=
{
styles
.
graveyard
}
glowing=
{
!
op
&&
glowingGraveyard
}
chains=
{
{
chains
:
genChains
(
grave
),
graveyard
:
true
,
op
}
}
/>
<
BgBlock
className=
{
styles
.
field
}
onClick=
{
()
=>
onBlockClick
(
field
.
interactivity
)
}
disabled=
{
field
.
disabled
}
highlight=
{
!!
field
.
interactivity
}
chains=
{
{
chains
:
field
.
chainIndex
,
field
:
true
,
op
}
}
/>
<
BgBlock
className=
{
styles
.
deck
}
/>
<
BgBlock
className=
{
styles
.
deck
}
chains=
{
{
chains
:
[]
}
}
/>
<
BgBlock
className=
{
classnames
(
styles
.
deck
,
styles
[
"
extra-deck
"
])
}
glowing=
{
!
op
&&
glowingExtra
}
chains=
{
{
chains
:
genChains
(
extra
),
extra
:
true
,
op
}
}
/>
</
div
>
);
...
...
@@ -114,14 +142,14 @@ export const Bg: React.FC = () => {
const
snap
=
useSnapshot
(
placeStore
.
inner
);
return
(
<
div
className=
{
styles
[
"
mat-bg
"
]
}
>
<
BgRow
snap=
{
snap
[
ygopro
.
CardZone
.
SZONE
].
op
}
szone
opponent
/>
<
BgRow
snap=
{
snap
[
ygopro
.
CardZone
.
MZONE
].
op
}
opponent
/>
<
BgRow
snap=
{
snap
[
SZONE
].
op
}
szone
opponent
/>
<
BgRow
snap=
{
snap
[
MZONE
].
op
}
opponent
/>
<
BgExtraRow
meSnap=
{
snap
[
ygopro
.
CardZone
.
MZONE
].
me
.
slice
(
5
,
7
)
}
opSnap=
{
snap
[
ygopro
.
CardZone
.
MZONE
].
op
.
slice
(
5
,
7
)
}
meSnap=
{
snap
[
MZONE
].
me
.
slice
(
5
,
7
)
}
opSnap=
{
snap
[
MZONE
].
op
.
slice
(
5
,
7
)
}
/>
<
BgRow
snap=
{
snap
[
ygopro
.
CardZone
.
MZONE
].
me
}
/>
<
BgRow
snap=
{
snap
[
ygopro
.
CardZone
.
SZONE
].
me
}
szone
/>
<
BgRow
snap=
{
snap
[
MZONE
].
me
}
/>
<
BgRow
snap=
{
snap
[
SZONE
].
me
}
szone
/>
<
BgOtherBlocks
/>
<
BgOtherBlocks
op
/>
</
div
>
...
...
src/ui/Duel/PlayMat/HandChain/index.module.scss
0 → 100644
View file @
b1fba04e
.container
{
position
:
fixed
;
display
:
flex
;
overflow
:
hidden
;
z-index
:
2
;
.me
{
position
:
fixed
;
bottom
:
1rem
;
right
:
50%
;
}
.op
{
position
:
fixed
;
top
:
1rem
;
left
:
50%
;
}
}
src/ui/Duel/PlayMat/HandChain/index.tsx
0 → 100644
View file @
b1fba04e
import
{
type
INTERNAL_Snapshot
as
Snapshot
,
useSnapshot
}
from
"
valtio
"
;
import
{
ygopro
}
from
"
@/api
"
;
import
{
BlockState
,
placeStore
}
from
"
@/stores
"
;
import
{
BgChain
}
from
"
@/ui/Shared
"
;
import
styles
from
"
./index.module.scss
"
;
const
{
HAND
}
=
ygopro
.
CardZone
;
export
const
HandChain
:
React
.
FC
=
()
=>
{
const
snap
=
useSnapshot
(
placeStore
.
inner
);
const
me
=
snap
[
HAND
].
me
;
const
op
=
snap
[
HAND
].
op
;
const
genChains
=
(
states
:
Snapshot
<
BlockState
[]
>
)
=>
{
const
chains
:
number
[]
=
states
.
flatMap
((
state
)
=>
state
.
chainIndex
);
chains
.
sort
();
return
chains
;
};
return
(
<
div
className=
{
styles
.
container
}
>
<
div
className=
{
styles
.
me
}
>
<
BgChain
chains=
{
genChains
(
me
)
}
/>
</
div
>
<
div
className=
{
styles
.
op
}
>
<
BgChain
chains=
{
genChains
(
op
)
}
op
/>
</
div
>
</
div
>
);
};
src/ui/Shared/Chain/index.module.scss
0 → 100644
View file @
b1fba04e
.container
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
min-width
:
8rem
;
max-width
:
10rem
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
z-index
:
2
;
pointer-events
:
none
;
}
.banish
,
.graveyard
{
left
:
100%
;
}
.field
,
.extra-deck
{
right
:
100%
;
}
.op
{
transform
:
rotate
(
180deg
);
}
.chain
{
position
:
relative
;
width
:
50%
;
height
:
50%
;
display
:
flex
;
img
{
width
:
100%
;
height
:
100%
;
object-fit
:
contain
;
animation
:
rotate
5s
linear
infinite
;
}
.text
{
position
:
absolute
;
font-size
:
2rem
;
font-weight
:
bold
;
top
:
50%
;
left
:
50%
;
-webkit-text-stroke
:
1px
black
;
transform
:
translate
(
-50%
,
-50%
);
}
@keyframes
rotate
{
from
{
transform
:
rotate
(
0deg
);
}
to
{
transform
:
rotate
(
360deg
);
}
}
}
src/ui/Shared/Chain/index.tsx
0 → 100644
View file @
b1fba04e
import
classnames
from
"
classnames
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
styles
from
"
./index.module.scss
"
;
const
{
assetsPath
}
=
useConfig
();
export
interface
ChainProps
{
chains
:
readonly
number
[];
banish
?:
boolean
;
graveyard
?:
boolean
;
extra
?:
boolean
;
field
?:
boolean
;
op
?:
boolean
;
}
/* 这里有个妥协的实现:墓地,除外区,额外卡组的连锁图标会被卡片遮挡,原因不明,
* 因此这里暂时采取移动一个身位的方式进行解决。最好的解决方案应该是UI上连锁图标和
* 场地解耦。 */
export
const
BgChain
:
React
.
FC
<
ChainProps
>
=
({
chains
,
banish
,
graveyard
,
extra
,
field
,
op
,
})
=>
(
<
div
className=
{
classnames
(
styles
.
container
,
{
[
styles
.
banish
]:
banish
,
[
styles
.
graveyard
]:
graveyard
,
[
styles
[
"
extra-deck
"
]]:
extra
,
[
styles
.
field
]:
field
,
[
styles
.
op
]:
op
,
})
}
>
{
chains
.
map
((
chain
)
=>
(
<
div
className=
{
styles
.
chain
}
key=
{
chain
}
>
<
img
src=
{
`${assetsPath}/chain.png`
}
/>
<
div
className=
{
styles
.
text
}
>
{
chain
}
</
div
>
</
div
>
))
}
</
div
>
);
src/ui/Shared/index.ts
View file @
b1fba04e
export
*
from
"
./Background
"
;
export
*
from
"
./CardEffectText
"
;
export
*
from
"
./Chain
"
;
export
*
from
"
./chatHook
"
;
export
*
from
"
./css
"
;
export
*
from
"
./DeckCard
"
;
...
...
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