Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
fc-minigame
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陈冲
fc-minigame
Commits
28863a1a
Commit
28863a1a
authored
Jun 12, 2026
by
陈冲
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: 修复game5白屏,将素材整合为sprite图
parent
c29b01c5
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
68 additions
and
33 deletions
+68
-33
circle-animation.png
...d-h5/src/assets/images/game5/sprites/circle-animation.png
+0
-0
horse1-has-circle.png
...-h5/src/assets/images/game5/sprites/horse1-has-circle.png
+0
-0
horse1-no-circle.png
...d-h5/src/assets/images/game5/sprites/horse1-no-circle.png
+0
-0
horse2-has-circle.png
...-h5/src/assets/images/game5/sprites/horse2-has-circle.png
+0
-0
horse2-no-circle.png
...d-h5/src/assets/images/game5/sprites/horse2-no-circle.png
+0
-0
horse3-has-circle.png
...-h5/src/assets/images/game5/sprites/horse3-has-circle.png
+0
-0
horse3-no-circle.png
...d-h5/src/assets/images/game5/sprites/horse3-no-circle.png
+0
-0
horse4-has-circle.png
...-h5/src/assets/images/game5/sprites/horse4-has-circle.png
+0
-0
horse4-no-circle.png
...d-h5/src/assets/images/game5/sprites/horse4-no-circle.png
+0
-0
Game5.vue
frontend-h5/src/pages/game5/Game5.vue
+39
-3
PlayingView.vue
frontend-h5/src/pages/game5/views/PlayingView.vue
+29
-30
No files found.
frontend-h5/src/assets/images/game5/sprites/circle-animation.png
0 → 100644
View file @
28863a1a
56.7 KB
frontend-h5/src/assets/images/game5/sprites/horse1-has-circle.png
0 → 100644
View file @
28863a1a
215 KB
frontend-h5/src/assets/images/game5/sprites/horse1-no-circle.png
0 → 100644
View file @
28863a1a
217 KB
frontend-h5/src/assets/images/game5/sprites/horse2-has-circle.png
0 → 100644
View file @
28863a1a
244 KB
frontend-h5/src/assets/images/game5/sprites/horse2-no-circle.png
0 → 100644
View file @
28863a1a
230 KB
frontend-h5/src/assets/images/game5/sprites/horse3-has-circle.png
0 → 100644
View file @
28863a1a
245 KB
frontend-h5/src/assets/images/game5/sprites/horse3-no-circle.png
0 → 100644
View file @
28863a1a
236 KB
frontend-h5/src/assets/images/game5/sprites/horse4-has-circle.png
0 → 100644
View file @
28863a1a
258 KB
frontend-h5/src/assets/images/game5/sprites/horse4-no-circle.png
0 → 100644
View file @
28863a1a
261 KB
frontend-h5/src/pages/game5/Game5.vue
View file @
28863a1a
<
script
setup
lang=
"ts"
>
import
{
computed
,
onBeforeUnmount
,
onMounted
,
ref
}
from
'vue'
import
{
cssAssetUrl
}
from
'@/commons/assets.ts'
import
{
assetUrl
,
cssAssetUrl
}
from
'@/commons/assets.ts'
import
MobileStage
from
'@/components/MobileStage.vue'
import
{
useGameSocket
,
sendGameMessage
,
userJoinStatus
,
joinSharedRoom
}
from
'@/composables/useGameSocket'
import
LoadingView
from
'./views/LoadingView.vue'
...
...
@@ -45,11 +45,39 @@ const imageUrls = {
rule
:
cssAssetUrl
(
'game1/rule.png'
)
}
const
playingAssetUrls
=
[
assetUrl
(
'game5/second-bg.webp'
),
assetUrl
(
'game5/paodao.webp'
),
assetUrl
(
'game5/circle-bg.webp'
),
assetUrl
(
'game5/circle.webp'
),
assetUrl
(
'game5/biaoti.webp'
),
assetUrl
(
'game5/sprites/circle-animation.png'
),
assetUrl
(
'game5/sprites/horse1-no-circle.png'
),
assetUrl
(
'game5/sprites/horse2-no-circle.png'
),
assetUrl
(
'game5/sprites/horse3-no-circle.png'
),
assetUrl
(
'game5/sprites/horse4-no-circle.png'
),
]
let
playingAssetsPromise
:
Promise
<
void
>
|
undefined
function
preloadPlayingAssets
()
{
if
(
!
playingAssetsPromise
)
{
playingAssetsPromise
=
Promise
.
all
(
playingAssetUrls
.
map
(
url
=>
new
Promise
<
void
>
((
resolve
)
=>
{
const
image
=
new
Image
()
image
.
onload
=
()
=>
resolve
()
image
.
onerror
=
()
=>
resolve
()
image
.
src
=
url
}))).
then
(()
=>
undefined
)
}
return
playingAssetsPromise
}
const
wechat
=
$getWechat
()
const
currentView
=
ref
<
GameView
>
(
'loading'
)
const
isGameStarting
=
ref
(
false
)
const
stageBackground
=
computed
(()
=>
{
if
(
currentView
.
value
===
'playing'
)
{
if
(
currentView
.
value
===
'playing'
||
isGameStarting
.
value
)
{
return
`
${
imageUrls
.
playingBg
}
center/cover`
}
return
`
${
imageUrls
.
bg
}
center/cover`
...
...
@@ -148,6 +176,7 @@ function startGameCountdown(seconds = 60) {
function
showLoadingView
()
{
stopGameCountdown
()
isGameStarting
.
value
=
false
currentView
.
value
=
'loading'
setDivDescVisible
(
false
)
// alert('管理员关闭了游戏房间')
...
...
@@ -156,6 +185,7 @@ function showLoadingView() {
function
resetToLoadingView
()
{
stopGameCountdown
()
isGameStarting
.
value
=
false
if
(
guFrameTimer
)
{
window
.
clearTimeout
(
guFrameTimer
)
guFrameTimer
=
undefined
...
...
@@ -215,8 +245,13 @@ if (wechat) {
},
onGameStart
:
async
()
=>
{
showGameRule
.
value
=
false
;
await
mobileStageRef
.
value
?.
startCountdown
()
isGameStarting
.
value
=
true
await
Promise
.
all
([
mobileStageRef
.
value
?.
startCountdown
(),
preloadPlayingAssets
(),
])
startGameView
()
isGameStarting
.
value
=
false
},
onScoreSubmitted
:
(
is_save
,
data
)
=>
{
if
(
!
is_save
)
{
//非保存状态下
...
...
@@ -260,6 +295,7 @@ if (wechat) {
onMounted
(()
=>
{
document
.
title
=
'互动游戏 - 圈彩纳福'
preloadPlayingAssets
()
if
(
token
.
value
)
{
window
.
addEventListener
(
'beforeunload'
,
confirmRefresh
)
}
...
...
frontend-h5/src/pages/game5/views/PlayingView.vue
View file @
28863a1a
...
...
@@ -16,16 +16,14 @@ const emit = defineEmits<{
}
>
()
// ── 圈圈丢出动画帧 (31帧, 原图325×733 → 渲染宽165) ──
const
circleAnimFrames
=
Array
.
from
({
length
:
31
},
(
_
,
i
)
=>
assetUrl
(
`game5/circle-animation/qcnf-quan_
${
String
(
i
).
padStart
(
2
,
'0'
)}
.png`
)
)
const
circleAnimSprite
=
assetUrl
(
'game5/sprites/circle-animation.png'
)
// ── 四种马的帧 (各21帧, 原图196×204 → 渲染180×160) ──
const
horse
Frames
:
Record
<
number
,
string
[]
>
=
{}
for
(
let
h
=
1
;
h
<=
4
;
h
++
)
{
horseFrames
[
h
]
=
Array
.
from
({
length
:
21
},
(
_
,
i
)
=>
assetUrl
(
`game5/horse
${
h
}
/no-circle/qcnf-ma
${
h
}
_
${
String
(
i
).
padStart
(
2
,
'0'
)}
.png`
)
)
const
horse
Sprites
:
Record
<
number
,
string
>
=
{
1
:
assetUrl
(
'game5/sprites/horse1-no-circle.png'
),
2
:
assetUrl
(
'game5/sprites/horse2-no-circle.png'
),
3
:
assetUrl
(
'game5/sprites/horse3-no-circle.png'
),
4
:
assetUrl
(
'game5/sprites/horse4-no-circle.png'
),
}
// ── 布局常量 ──
...
...
@@ -57,6 +55,12 @@ const HORSE_FRAME_TICK = 3
const
CIRCLE_CENTER_X
=
375
const
CIRCLE_CENTER_Y
=
STAGE_HEIGHT
-
72
-
345
+
345
/
2
// 1379.5
const
CIRCLE_ANIM_WIDTH
=
165
const
CIRCLE_SPRITE_COLS
=
8
const
HORSE_SPRITE_COLS
=
7
function
spritePosition
(
frameIdx
:
number
,
cols
:
number
,
frameWidth
:
number
,
frameHeight
:
number
)
{
return
`-
${(
frameIdx
%
cols
)
*
frameWidth
}
px -
${
Math
.
floor
(
frameIdx
/
cols
)
*
frameHeight
}
px`
}
const
CIRCLE_ANIM_HEIGHT
=
Math
.
round
(
733
*
(
CIRCLE_ANIM_WIDTH
/
325
))
// ≈ 372
// ── 类型 ──
...
...
@@ -331,19 +335,11 @@ function loop(ts: number) {
}
// ── 预加载所有帧图片,避免运行时切换帧的闪烁 ──
function
preloadFrames
()
{
// 圈圈动画 31 帧
for
(
const
url
of
circleAnimFrames
)
{
const
img
=
new
Image
()
img
.
src
=
url
}
// 四种马各 21 帧
for
(
const
frames
of
Object
.
values
(
horseFrames
))
{
for
(
const
url
of
frames
)
{
function
preloadSprites
()
{
for
(
const
url
of
[
circleAnimSprite
,
...
Object
.
values
(
horseSprites
)])
{
const
img
=
new
Image
()
img
.
src
=
url
}
}
}
// ── 监听父组件倒计时,到 0 时暂停游戏 ──
...
...
@@ -356,7 +352,7 @@ watch(() => props.countdownInterval, (val) => {
})
onMounted
(()
=>
{
preload
Fram
es
()
preload
Sprit
es
()
// 先启动音频上下文(需用户首次交互后 resume,此处尝试提前激活)
try
{
getAudioContext
()
}
catch
{
/* ignore */
}
// MobileStage 已完成 3-2-1,游戏直接开始
...
...
@@ -406,11 +402,13 @@ onBeforeUnmount(() => {
:class=
"
{ 'horse-dying': horse.dying }"
:style="{ transform: `translateX(${horse.x}px)` }"
>
<img
class=
"horse-img"
:src=
"horseFrames[horse.type]?.[horse.frameIdx] ?? ''"
alt=
"horse"
/>
<div
class=
"horse-sprite"
:style=
"
{
backgroundImage: `url(${horseSprites[horse.type]})`,
backgroundPosition: spritePosition(horse.frameIdx, HORSE_SPRITE_COLS, HORSE_WIDTH, HORSE_HEIGHT),
}"
>
</div>
<div
class=
"horse-shadow"
:class=
"
{ 'shadow-dying': horse.dying }">
</div>
</div>
</
template
>
...
...
@@ -431,7 +429,8 @@ onBeforeUnmount(() => {
transform: `translate(${CIRCLE_CENTER_X - CIRCLE_ANIM_WIDTH / 2}px, ${circleThrow.y - CIRCLE_ANIM_HEIGHT / 2}px)`,
width: CIRCLE_ANIM_WIDTH + 'px',
height: CIRCLE_ANIM_HEIGHT + 'px',
backgroundImage: `url(${circleAnimFrames[circleThrow.frameIdx]})`,
backgroundImage: `url(${circleAnimSprite})`,
backgroundPosition: spritePosition(circleThrow.frameIdx, CIRCLE_SPRITE_COLS, CIRCLE_ANIM_WIDTH, CIRCLE_ANIM_HEIGHT),
}"
></div>
...
...
@@ -601,10 +600,11 @@ onBeforeUnmount(() => {
will-change
:
transform
;
}
.horse-
img
{
.horse-
sprite
{
width
:
100%
;
height
:
100%
;
object-fit
:
cover
;
background-size
:
1260px
600px
;
background-repeat
:
no-repeat
;
}
.horse-dying
{
...
...
@@ -664,12 +664,11 @@ onBeforeUnmount(() => {
position
:
absolute
;
left
:
0
;
top
:
0
;
background-position
:
center
;
background-size
:
contain
;
background-size
:
1320px
1488px
;
background-repeat
:
no-repeat
;
z-index
:
10
;
pointer-events
:
none
;
will-change
:
transform
,
background-
image
;
will-change
:
transform
,
background-
position
;
image-rendering
:
auto
;
}
...
...
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