gamekit777 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -16,32 +16,41 @@
|
|
|
16
16
|
const { game } = inst;
|
|
17
17
|
|
|
18
18
|
const label = (s: 'heads' | 'tails') => (s === 'heads' ? '正' : '反');
|
|
19
|
+
const money = (minor: number) => (minor / 100).toFixed(2);
|
|
19
20
|
</script>
|
|
20
21
|
|
|
21
|
-
<div class="game"
|
|
22
|
+
<div class="game">
|
|
22
23
|
<p class="head">押 <b>{label(game.side)}</b> · 猜中赔 {MULT.toFixed(2)}×</p>
|
|
23
24
|
|
|
24
25
|
<div class="coin" class:spin={game.live} aria-live="polite">
|
|
25
26
|
<span>{label(game.face)}</span>
|
|
26
27
|
</div>
|
|
27
28
|
|
|
28
|
-
<p class="foot" class:win={game.last?.win}>
|
|
29
|
+
<p class="foot" class:win={game.last?.win} class:lose={game.last && !game.last.win}>
|
|
29
30
|
{#if game.phase === 'over' && game.last}
|
|
30
|
-
{game.last.win ?
|
|
31
|
+
{game.last.win ? '猜中了' : '没猜中'}
|
|
31
32
|
{:else if game.live}
|
|
32
33
|
抛出中…
|
|
33
34
|
{:else}
|
|
34
35
|
在左边选一面,下注开始
|
|
35
36
|
{/if}
|
|
36
37
|
</p>
|
|
38
|
+
|
|
39
|
+
<!-- 赢了弹一下就走:不遮画面、不用点。key 到局号,连赢两局是两次弹出而不是一次拉长 -->
|
|
40
|
+
{#if game.toast}
|
|
41
|
+
{#key game.toast.id}
|
|
42
|
+
<div class="toast" style:animation-duration="{game.toast.ms}ms" aria-hidden="true">
|
|
43
|
+
<b>{game.toast.mult.toFixed(2)}×</b><span>+{money(game.toast.payout)}</span>
|
|
44
|
+
</div>
|
|
45
|
+
{/key}
|
|
46
|
+
{/if}
|
|
37
47
|
</div>
|
|
38
48
|
|
|
39
49
|
<style>
|
|
50
|
+
/* 不写 border-radius:外框和裁切归平台容器,游戏只管自己那块内容 */
|
|
40
51
|
.game{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;
|
|
41
|
-
height:100%;min-height:240px;padding:28px;
|
|
52
|
+
height:100%;min-height:240px;padding:28px;
|
|
42
53
|
background:var(--bg);color:var(--ink);font-family:var(--txt)}
|
|
43
|
-
.game.flash::after{content:"";position:absolute;inset:0;pointer-events:none;border-radius:16px;
|
|
44
|
-
background:var(--win);animation:flash var(--d-flash,500ms) ease-out forwards}
|
|
45
54
|
.head{margin:0;font-size:13px;color:var(--dim)}
|
|
46
55
|
.head b{color:var(--ink);font-size:16px}
|
|
47
56
|
.coin{display:grid;place-items:center;width:104px;height:104px;border-radius:50%;
|
|
@@ -50,5 +59,14 @@
|
|
|
50
59
|
.coin.spin{animation:pulse 420ms ease-in-out infinite}
|
|
51
60
|
.foot{margin:0;min-height:1.5em;font-size:13px;color:var(--dim)}
|
|
52
61
|
.foot.win{color:var(--win);font-weight:700}
|
|
53
|
-
|
|
62
|
+
.foot.lose{color:var(--lose)}
|
|
63
|
+
|
|
64
|
+
.toast{position:absolute;left:50%;top:22%;transform:translate(-50%,0);pointer-events:none;
|
|
65
|
+
display:flex;align-items:baseline;gap:10px;padding:10px 22px 12px;border-radius:18px;
|
|
66
|
+
background:var(--panel);color:var(--ink);box-shadow:0 0 0 3px var(--win),0 10px 30px rgba(0,0,0,.45);
|
|
67
|
+
animation:toast 1400ms ease-out forwards}
|
|
68
|
+
.toast b{font-family:var(--num);font-size:34px;line-height:1;color:var(--win)}
|
|
69
|
+
.toast span{font-family:var(--num);font-size:16px;color:var(--ink)}
|
|
70
|
+
|
|
71
|
+
@media (prefers-reduced-motion:reduce){.coin.spin{animation:none}.toast{animation-name:toastStill}}
|
|
54
72
|
</style>
|
|
@@ -34,6 +34,8 @@ export class Game {
|
|
|
34
34
|
face = $state<'heads' | 'tails'>('heads');
|
|
35
35
|
last = $state<__PASCAL__Outcome | null>(null);
|
|
36
36
|
lastPayout = $state(0);
|
|
37
|
+
/** 赢面小弹窗。id 让连赢两局弹两次;ms 是它的存活时间,到点自己清空 */
|
|
38
|
+
toast = $state<{ id: number; mult: number; payout: number; ms: number } | null>(null);
|
|
37
39
|
|
|
38
40
|
live = $derived(this.phase === 'playing');
|
|
39
41
|
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
/* 名字起得通用没关系:namespace-css 插件会在构建时把它们改成 <name>-<游戏 id>,
|
|
2
2
|
同页两个游戏才不会互相覆盖 */
|
|
3
|
-
@keyframes flash{from{opacity:.5}to{opacity:0}}
|
|
4
3
|
@keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.1)}}
|
|
4
|
+
/* 赢面小弹窗:弹出 → 停住 → 淡出。时长由演出按 turbo 决定,写在 style 上 */
|
|
5
|
+
@keyframes toast{
|
|
6
|
+
0%{opacity:0;transform:translate(-50%,10px) scale(.86)}
|
|
7
|
+
14%{opacity:1;transform:translate(-50%,0) scale(1.04)}
|
|
8
|
+
22%{transform:translate(-50%,0) scale(1)}
|
|
9
|
+
78%{opacity:1;transform:translate(-50%,0)}
|
|
10
|
+
100%{opacity:0;transform:translate(-50%,-10px)}
|
|
11
|
+
}
|
|
12
|
+
/* 减少动态效果:不动,只是出现再消失 */
|
|
13
|
+
@keyframes toastStill{0%,85%{opacity:1}100%{opacity:0}}
|
|
@@ -33,4 +33,13 @@ export async function present(
|
|
|
33
33
|
game.last = o;
|
|
34
34
|
game.lastPayout = payout;
|
|
35
35
|
game.phase = 'over';
|
|
36
|
+
|
|
37
|
+
/* 赢了弹一个小窗,到点自己消失。present 不等它——弹窗是余韵,不该拖慢下一注(自动模式尤其)。
|
|
38
|
+
清空前核对 id:这期间可能已经又赢了一局,别把新的那个一起抹掉 */
|
|
39
|
+
if (o.win) {
|
|
40
|
+
const ms = instant ? 900 : game.turbo ? 1000 : 1600;
|
|
41
|
+
game.toast = { id, mult: o.mult, payout, ms };
|
|
42
|
+
// 比 id 不比引用:$state 存进去的是 Proxy,读出来和原对象不相等
|
|
43
|
+
setTimeout(() => { if (game.toast?.id === id) game.toast = null; }, ms);
|
|
44
|
+
}
|
|
36
45
|
}
|