骰子游戏
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 14 KiB |
BIN
game/rock/assets/figma/victory-action-secondary.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 41 KiB |
@ -99,7 +99,8 @@
|
||||
top: 60px;
|
||||
left: 16px;
|
||||
z-index: 30;
|
||||
display: flex;
|
||||
display: grid;
|
||||
grid-template-columns: 46px minmax(0, 1fr) max-content;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 343px;
|
||||
@ -109,20 +110,28 @@
|
||||
|
||||
.top-back {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 46px;
|
||||
height: 36px;
|
||||
flex: 0 0 46px;
|
||||
}
|
||||
|
||||
.top-back .layer-img {
|
||||
position: static;
|
||||
width: 46px;
|
||||
height: 36px;
|
||||
object-fit: fill;
|
||||
}
|
||||
|
||||
.top-game-icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
position: relative;
|
||||
justify-self: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.top-coin {
|
||||
@ -130,10 +139,11 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
justify-self: end;
|
||||
width: max-content;
|
||||
min-width: 102px;
|
||||
max-width: 176px;
|
||||
height: 32px;
|
||||
height: 36px;
|
||||
flex: 0 1 auto;
|
||||
gap: 4px;
|
||||
overflow: visible;
|
||||
@ -156,10 +166,12 @@
|
||||
}
|
||||
|
||||
.top-coin span {
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: max-content;
|
||||
max-width: none;
|
||||
flex: 0 0 auto;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
line-height: 20px;
|
||||
}
|
||||
@ -181,10 +193,11 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 5px;
|
||||
height: 100%;
|
||||
color: #ffd15a;
|
||||
font-size: 21px;
|
||||
font-weight: 900;
|
||||
line-height: 1;
|
||||
text-shadow:
|
||||
0 1px 1px rgba(65, 23, 0, 0.86),
|
||||
0 0 8px rgba(255, 178, 47, 0.74);
|
||||
@ -732,6 +745,14 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rps-duel-card.is-opponent.has-opponent-avatar .rps-question {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rps-duel-card.is-opponent.has-opponent .rps-duel-status {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rps-question {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
@ -800,6 +821,10 @@
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.rps-frame.has-opponent .rps-search-hud {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.rps-bottom-status {
|
||||
position: absolute;
|
||||
left: 74px;
|
||||
@ -1012,7 +1037,7 @@
|
||||
}
|
||||
|
||||
.rps-victory-button.is-secondary::before {
|
||||
background-image: url('assets/figma/victory-action-secondary.svg');
|
||||
background-image: url('assets/figma/victory-action-secondary.png');
|
||||
filter: drop-shadow(0 0 5px rgba(255, 227, 142, 0.34));
|
||||
}
|
||||
|
||||
@ -1337,9 +1362,20 @@
|
||||
<div class="rps-duel-card is-opponent">
|
||||
<img src="assets/figma/opponent-card.png" alt="" />
|
||||
<div class="rps-duel-avatar">
|
||||
<img
|
||||
class="is-empty"
|
||||
data-role="opponent-card-avatar"
|
||||
alt=""
|
||||
/>
|
||||
<div class="rps-question">?</div>
|
||||
</div>
|
||||
<div class="rps-duel-name">?</div>
|
||||
<div
|
||||
class="rps-duel-name"
|
||||
data-role="opponent-card-name"
|
||||
>
|
||||
<div>?</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="rps-duel-status">
|
||||
<img src="assets/figma/search-icon.svg" alt="" />
|
||||
<span data-i18n="rockGame.matching"
|
||||
@ -1378,6 +1414,11 @@
|
||||
<div class="rps-duel-card is-opponent">
|
||||
<img src="assets/figma/opponent-card.png" alt="" />
|
||||
<div class="rps-duel-avatar">
|
||||
<img
|
||||
class="is-empty"
|
||||
data-role="opponent-vs-avatar"
|
||||
alt=""
|
||||
/>
|
||||
<div class="rps-question">?</div>
|
||||
</div>
|
||||
<div class="rps-duel-name" data-role="opponent-vs-name">
|
||||
@ -1420,9 +1461,11 @@
|
||||
<img src="assets/figma/opponent-card.png" alt="" />
|
||||
<div class="rps-duel-avatar">
|
||||
<img
|
||||
src="assets/figma/opponent-question.png"
|
||||
class="is-empty"
|
||||
data-role="opponent-battle-avatar"
|
||||
alt=""
|
||||
/>
|
||||
<div class="rps-question">?</div>
|
||||
</div>
|
||||
<div
|
||||
class="rps-duel-name"
|
||||
@ -1484,7 +1527,7 @@
|
||||
<section class="rps-screen rps-victory">
|
||||
<img
|
||||
class="rps-victory-title"
|
||||
src="assets/figma/victory-title.svg"
|
||||
src="assets/figma/victory-title.png"
|
||||
alt=""
|
||||
/>
|
||||
<div class="rps-avatar-ring">
|
||||
@ -1585,10 +1628,7 @@
|
||||
selectedGesture: 'rock',
|
||||
selectedStake: 8000,
|
||||
opponentGesture: 'paper',
|
||||
opponent: {
|
||||
nickname: 'NameName',
|
||||
display_user_id: 'Name...',
|
||||
},
|
||||
opponent: {},
|
||||
config: null,
|
||||
match: null,
|
||||
busy: false,
|
||||
@ -1818,6 +1858,17 @@
|
||||
if (nodes[1]) nodes[1].textContent = displaySubName(user);
|
||||
}
|
||||
|
||||
function setOpponentNameLines(selector, user, hasDetails) {
|
||||
var nodes = document.querySelectorAll(selector + ' div');
|
||||
if (!hasDetails) {
|
||||
if (nodes[0]) nodes[0].textContent = '?';
|
||||
if (nodes[1]) nodes[1].textContent = '';
|
||||
return;
|
||||
}
|
||||
if (nodes[0]) nodes[0].textContent = displayName(user);
|
||||
if (nodes[1]) nodes[1].textContent = displaySubName(user);
|
||||
}
|
||||
|
||||
function setHand(node, gesture) {
|
||||
var meta = gestures[gesture] || gestures.rock;
|
||||
if (!node) return;
|
||||
@ -1912,12 +1963,52 @@
|
||||
);
|
||||
}
|
||||
|
||||
function hasOpponentDetails(user) {
|
||||
user = user || {};
|
||||
return Boolean(
|
||||
avatarURL(user) ||
|
||||
user.nickname ||
|
||||
user.username ||
|
||||
user.name ||
|
||||
user.display_user_id ||
|
||||
user.user_id
|
||||
);
|
||||
}
|
||||
|
||||
function renderOpponent() {
|
||||
var opponent = state.opponent || {};
|
||||
setNameLines('[data-role="opponent-vs-name"]', opponent);
|
||||
setNameLines(
|
||||
var avatar = avatarURL(opponent);
|
||||
var hasDetails = hasOpponentDetails(opponent);
|
||||
frame.classList.toggle('has-opponent', hasDetails);
|
||||
// 匹配成功后同一份对手资料要同步到等待卡、VS 卡和对战卡;否则某个屏幕仍停留在搜索态,会出现头像未替换或搜索图标残留。
|
||||
setOpponentNameLines(
|
||||
'[data-role="opponent-card-name"]',
|
||||
opponent,
|
||||
hasDetails
|
||||
);
|
||||
setOpponentNameLines(
|
||||
'[data-role="opponent-vs-name"]',
|
||||
opponent,
|
||||
hasDetails
|
||||
);
|
||||
setOpponentNameLines(
|
||||
'[data-role="opponent-battle-name"]',
|
||||
opponent
|
||||
opponent,
|
||||
hasDetails
|
||||
);
|
||||
setImage(role('opponent-card-avatar'), avatar);
|
||||
setImage(role('opponent-vs-avatar'), avatar);
|
||||
setImage(role('opponent-battle-avatar'), avatar);
|
||||
each(
|
||||
document.querySelectorAll('.rps-duel-card.is-opponent'),
|
||||
function (card) {
|
||||
// 有对手资料就隐藏 Matching/Search 状态;只有头像真实可用时才隐藏问号兜底,避免无头像用户显示成空圆。
|
||||
card.classList.toggle('has-opponent', hasDetails);
|
||||
card.classList.toggle(
|
||||
'has-opponent-avatar',
|
||||
Boolean(avatar)
|
||||
);
|
||||
}
|
||||
);
|
||||
setHand(
|
||||
role('opponent-battle-hand'),
|
||||
@ -2147,6 +2238,9 @@
|
||||
if (readGesture(opponent)) {
|
||||
state.opponentGesture = readGesture(opponent);
|
||||
}
|
||||
} else {
|
||||
// 等待匹配时必须清空上一局对手资料,否则搜索页会复用旧头像并提前隐藏搜索状态。
|
||||
state.opponent = {};
|
||||
}
|
||||
renderSelection();
|
||||
renderOpponent();
|
||||
@ -2361,6 +2455,8 @@
|
||||
state.busy = true;
|
||||
state.roundID += 1;
|
||||
state.match = null;
|
||||
state.opponent = {};
|
||||
renderOpponent();
|
||||
setScreen('searching');
|
||||
postBridge('gameRPSMatchRequested', {
|
||||
game_code: GAME_CODE,
|
||||
@ -2400,7 +2496,8 @@
|
||||
.then(function (data) {
|
||||
var match = matchFromData(data);
|
||||
trackSelfGameEvent('match_success', {
|
||||
match_id: match && (match.match_id || match.matchId),
|
||||
match_id:
|
||||
match && (match.match_id || match.matchId),
|
||||
stake_coin: state.selectedStake,
|
||||
gesture: state.selectedGesture,
|
||||
duration_ms: Math.round(
|
||||
@ -2410,19 +2507,19 @@
|
||||
handleMatchData(data);
|
||||
})
|
||||
.catch(function (error) {
|
||||
trackSelfGameEvent('match_api', {
|
||||
stake_coin: state.selectedStake,
|
||||
gesture: state.selectedGesture,
|
||||
duration_ms: Math.round(
|
||||
performance.now() - matchStartedAt
|
||||
),
|
||||
success: false,
|
||||
error_code: error && error.message,
|
||||
trackSelfGameEvent('match_api', {
|
||||
stake_coin: state.selectedStake,
|
||||
gesture: state.selectedGesture,
|
||||
duration_ms: Math.round(
|
||||
performance.now() - matchStartedAt
|
||||
),
|
||||
success: false,
|
||||
error_code: error && error.message,
|
||||
});
|
||||
state.busy = false;
|
||||
showMessage(error.message);
|
||||
setScreen('lobby');
|
||||
});
|
||||
state.busy = false;
|
||||
showMessage(error.message);
|
||||
setScreen('lobby');
|
||||
});
|
||||
}
|
||||
|
||||
function startMockMatch() {
|
||||
@ -2430,10 +2527,12 @@
|
||||
state.busy = true;
|
||||
state.roundID += 1;
|
||||
var roundID = state.roundID;
|
||||
state.opponent = {};
|
||||
state.opponentGesture = chooseOpponentGesture();
|
||||
state.opponent = {
|
||||
nickname: 'NameName',
|
||||
display_user_id: 'Name...',
|
||||
avatar: 'assets/figma/game-icon.png',
|
||||
};
|
||||
renderOpponent();
|
||||
setScreen('searching');
|
||||
@ -2532,6 +2631,7 @@
|
||||
state.busy = false;
|
||||
state.roundID += 1;
|
||||
state.match = null;
|
||||
state.opponent = {};
|
||||
frame.classList.remove('is-vs-impact', 'is-screen-impact');
|
||||
setScreen('lobby');
|
||||
renderSelection();
|
||||
|
||||
BIN
game/touzi/assets/figma/dice-blue-1.png
Normal file
|
After Width: | Height: | Size: 344 KiB |
BIN
game/touzi/assets/figma/dice-blue-2.png
Normal file
|
After Width: | Height: | Size: 331 KiB |
BIN
game/touzi/assets/figma/dice-blue-3.png
Normal file
|
After Width: | Height: | Size: 327 KiB |
BIN
game/touzi/assets/figma/dice-blue-4.png
Normal file
|
After Width: | Height: | Size: 330 KiB |
BIN
game/touzi/assets/figma/dice-blue-5.png
Normal file
|
After Width: | Height: | Size: 308 KiB |
BIN
game/touzi/assets/figma/dice-blue-6.png
Normal file
|
After Width: | Height: | Size: 355 KiB |
BIN
game/touzi/assets/figma/dice-red-1.png
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
game/touzi/assets/figma/dice-red-2.png
Normal file
|
After Width: | Height: | Size: 267 KiB |
BIN
game/touzi/assets/figma/dice-red-3.png
Normal file
|
After Width: | Height: | Size: 291 KiB |
BIN
game/touzi/assets/figma/dice-red-4.png
Normal file
|
After Width: | Height: | Size: 273 KiB |
BIN
game/touzi/assets/figma/dice-red-5.png
Normal file
|
After Width: | Height: | Size: 280 KiB |
BIN
game/touzi/assets/figma/dice-red-6.png
Normal file
|
After Width: | Height: | Size: 287 KiB |
@ -263,6 +263,32 @@
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.top-coin.is-crediting {
|
||||
animation: top-coin-credit-pulse 720ms ease-out both;
|
||||
}
|
||||
|
||||
.coin-credit-layer {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 60;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.coin-credit-flyer {
|
||||
position: absolute;
|
||||
left: var(--coin-credit-x);
|
||||
top: var(--coin-credit-y);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
opacity: 0;
|
||||
filter: drop-shadow(0 0 6px rgba(255, 203, 67, 0.86));
|
||||
transform: translate3d(0, 0, 0) scale(0.78);
|
||||
animation: coin-credit-fly 920ms
|
||||
cubic-bezier(0.2, 0.82, 0.16, 1) forwards;
|
||||
animation-delay: var(--coin-credit-delay, 0ms);
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
position: absolute;
|
||||
top: 41px;
|
||||
@ -1074,27 +1100,25 @@
|
||||
|
||||
.dice-score {
|
||||
position: absolute;
|
||||
top: 302px;
|
||||
top: 379px;
|
||||
z-index: 12;
|
||||
width: 88px;
|
||||
min-height: 34px;
|
||||
width: 132px;
|
||||
height: 132px;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
color: #ffffff;
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.82);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
transition: opacity 180ms ease;
|
||||
}
|
||||
|
||||
.dice-score-self {
|
||||
left: 34px;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.dice-score-opponent {
|
||||
left: 255px;
|
||||
left: 230px;
|
||||
}
|
||||
|
||||
.dice-frame.has-scores .dice-score {
|
||||
@ -1102,6 +1126,14 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.dice-score img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.dice-roll-effect {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
@ -1367,6 +1399,7 @@
|
||||
.match-battle-only,
|
||||
.opponent-battle-only,
|
||||
.dice-roll-effect,
|
||||
.coin-credit-flyer,
|
||||
.versus-only,
|
||||
.victory-only {
|
||||
transition: none;
|
||||
@ -1381,7 +1414,9 @@
|
||||
.dice-frame.is-matching,
|
||||
.dice-frame.is-searching .center-search-bg,
|
||||
.dice-frame.is-searching .search-indicator img,
|
||||
.dice-roll-effect.is-fallback::before {
|
||||
.dice-roll-effect.is-fallback::before,
|
||||
.coin-credit-flyer,
|
||||
.top-coin.is-crediting {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
@ -1593,6 +1628,49 @@
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes coin-credit-fly {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 0, 0) scale(0.78) rotate(0deg);
|
||||
}
|
||||
12% {
|
||||
opacity: 1;
|
||||
}
|
||||
58% {
|
||||
opacity: 1;
|
||||
transform: translate3d(
|
||||
calc(var(--coin-credit-dx) * 0.72),
|
||||
calc(var(--coin-credit-dy) * 0.58 - 34px),
|
||||
0
|
||||
)
|
||||
scale(1.05) rotate(220deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translate3d(
|
||||
var(--coin-credit-dx),
|
||||
var(--coin-credit-dy),
|
||||
0
|
||||
)
|
||||
scale(0.36) rotate(520deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes top-coin-credit-pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
filter: drop-shadow(0 0 0 rgba(255, 211, 79, 0));
|
||||
}
|
||||
42% {
|
||||
transform: scale(1.12);
|
||||
filter: drop-shadow(0 0 13px rgba(255, 211, 79, 0.86));
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
filter: drop-shadow(0 0 0 rgba(255, 211, 79, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes countdown-number-pop {
|
||||
0% {
|
||||
opacity: 0;
|
||||
@ -2435,6 +2513,8 @@
|
||||
var pollTimer = 0;
|
||||
var roundSequence = 0;
|
||||
var pageStartedAt = performance.now();
|
||||
var coinCreditFrame = 0;
|
||||
var coinCreditLayer = null;
|
||||
var rollEffectPlayers = {
|
||||
self: null,
|
||||
opponent: null,
|
||||
@ -2739,6 +2819,147 @@
|
||||
);
|
||||
}
|
||||
|
||||
function cancelCoinCreditAnimation() {
|
||||
if (coinCreditFrame) {
|
||||
window.cancelAnimationFrame(coinCreditFrame);
|
||||
coinCreditFrame = 0;
|
||||
}
|
||||
if (coinCreditLayer && coinCreditLayer.parentNode) {
|
||||
coinCreditLayer.parentNode.removeChild(coinCreditLayer);
|
||||
}
|
||||
coinCreditLayer = null;
|
||||
var topCoin = document.querySelector('.top-coin');
|
||||
if (topCoin) topCoin.classList.remove('is-crediting');
|
||||
}
|
||||
|
||||
function framePointFromRect(rect, anchorX, anchorY) {
|
||||
var frameRect = frame.getBoundingClientRect();
|
||||
var scale = frameRect.width / DESIGN_WIDTH || 1;
|
||||
return {
|
||||
x:
|
||||
(rect.left +
|
||||
rect.width * anchorX -
|
||||
frameRect.left) /
|
||||
scale,
|
||||
y:
|
||||
(rect.top + rect.height * anchorY - frameRect.top) /
|
||||
scale,
|
||||
};
|
||||
}
|
||||
|
||||
function createCoinCreditLayer() {
|
||||
cancelCoinCreditAnimation();
|
||||
coinCreditLayer = document.createElement('div');
|
||||
coinCreditLayer.className = 'coin-credit-layer';
|
||||
frame.appendChild(coinCreditLayer);
|
||||
return coinCreditLayer;
|
||||
}
|
||||
|
||||
function burstCreditCoins(start, end) {
|
||||
var layer = createCoinCreditLayer();
|
||||
var offsets = [
|
||||
[-8, 6],
|
||||
[12, -4],
|
||||
[3, 16],
|
||||
[20, 10],
|
||||
[-16, -3],
|
||||
[8, -17],
|
||||
[-2, -12],
|
||||
[17, 22],
|
||||
];
|
||||
offsets.forEach(function (offset, index) {
|
||||
var coin = document.createElement('img');
|
||||
coin.className = 'coin-credit-flyer';
|
||||
coin.src = 'assets/figma/coin.png';
|
||||
coin.alt = '';
|
||||
coin.draggable = false;
|
||||
coin.setAttribute('aria-hidden', 'true');
|
||||
coin.style.setProperty(
|
||||
'--coin-credit-x',
|
||||
start.x + offset[0] + 'px'
|
||||
);
|
||||
coin.style.setProperty(
|
||||
'--coin-credit-y',
|
||||
start.y + offset[1] + 'px'
|
||||
);
|
||||
coin.style.setProperty(
|
||||
'--coin-credit-dx',
|
||||
end.x - start.x - offset[0] + 'px'
|
||||
);
|
||||
coin.style.setProperty(
|
||||
'--coin-credit-dy',
|
||||
end.y - start.y - offset[1] + 'px'
|
||||
);
|
||||
coin.style.setProperty(
|
||||
'--coin-credit-delay',
|
||||
index * 64 + 'ms'
|
||||
);
|
||||
layer.appendChild(coin);
|
||||
});
|
||||
schedule(function () {
|
||||
if (coinCreditLayer === layer) {
|
||||
layer.remove();
|
||||
coinCreditLayer = null;
|
||||
}
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function animateCoinNumber(startValue, targetValue) {
|
||||
var start = Math.max(
|
||||
0,
|
||||
Math.trunc(Number(startValue) || 0)
|
||||
);
|
||||
var target = Math.max(
|
||||
0,
|
||||
Math.trunc(Number(targetValue) || 0)
|
||||
);
|
||||
var startedAt = performance.now();
|
||||
var duration = 1180;
|
||||
function tick(now) {
|
||||
var progress = Math.min(
|
||||
Math.max((now - startedAt) / duration, 0),
|
||||
1
|
||||
);
|
||||
var eased = 1 - Math.pow(1 - progress, 3);
|
||||
setCoin(start + (target - start) * eased);
|
||||
if (progress < 1) {
|
||||
coinCreditFrame =
|
||||
window.requestAnimationFrame(tick);
|
||||
return;
|
||||
}
|
||||
coinCreditFrame = 0;
|
||||
setCoin(target);
|
||||
}
|
||||
if (coinCreditFrame) {
|
||||
window.cancelAnimationFrame(coinCreditFrame);
|
||||
}
|
||||
coinCreditFrame = window.requestAnimationFrame(tick);
|
||||
}
|
||||
|
||||
function playVictoryCoinCredit(startValue, targetValue) {
|
||||
var topCoin = document.querySelector('.top-coin');
|
||||
var topCoinIcon = topCoin && topCoin.querySelector('img');
|
||||
if (!topCoinIcon || targetValue <= startValue) {
|
||||
setCoin(targetValue);
|
||||
return false;
|
||||
}
|
||||
var start = { x: 95, y: 584 };
|
||||
var end = framePointFromRect(
|
||||
topCoinIcon.getBoundingClientRect(),
|
||||
0.5,
|
||||
0.5
|
||||
);
|
||||
burstCreditCoins(start, end);
|
||||
animateCoinNumber(startValue, targetValue);
|
||||
topCoin.classList.remove('is-crediting');
|
||||
void topCoin.offsetWidth;
|
||||
topCoin.classList.add('is-crediting');
|
||||
schedule(function () {
|
||||
topCoin.classList.remove('is-crediting');
|
||||
}, 780);
|
||||
return true;
|
||||
}
|
||||
|
||||
function displayName(user) {
|
||||
user = user || {};
|
||||
return (
|
||||
@ -2960,6 +3181,7 @@
|
||||
|
||||
function resetFrame() {
|
||||
stopRollEffects();
|
||||
cancelCoinCreditAnimation();
|
||||
frame.classList.remove(
|
||||
'is-searching',
|
||||
'is-matching',
|
||||
@ -3085,10 +3307,39 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
function scoreText(participant) {
|
||||
function dicePointValue(participant) {
|
||||
var points = (participant && participant.dice_points) || [];
|
||||
if (!points.length) return '';
|
||||
return String(Number(points[0] || 0));
|
||||
var point = Number(points[0] || 0);
|
||||
if (!isFinite(point) || point < 1 || point > 6) return '';
|
||||
return String(Math.floor(point));
|
||||
}
|
||||
|
||||
function diceScoreImage(point, side) {
|
||||
if (!point) return '';
|
||||
return (
|
||||
'assets/figma/dice-' +
|
||||
(side === 'self' ? 'red' : 'blue') +
|
||||
'-' +
|
||||
point +
|
||||
'.png'
|
||||
);
|
||||
}
|
||||
|
||||
function setDiceScore(node, point, side) {
|
||||
if (!node) return;
|
||||
node.textContent = '';
|
||||
if (!point) {
|
||||
node.removeAttribute('data-score-value');
|
||||
return;
|
||||
}
|
||||
node.setAttribute('data-score-value', point);
|
||||
var img = document.createElement('img');
|
||||
img.src = diceScoreImage(point, side);
|
||||
img.alt = '';
|
||||
img.draggable = false;
|
||||
img.setAttribute('aria-hidden', 'true');
|
||||
node.appendChild(img);
|
||||
}
|
||||
|
||||
function isDrawReroll(match) {
|
||||
@ -3162,10 +3413,14 @@
|
||||
setImage(role('opponent-avatar'), '', '');
|
||||
setFrame(role('opponent-avatar-frame'), {});
|
||||
}
|
||||
var selfScore = scoreText(self);
|
||||
var opponentScore = scoreText(opponent);
|
||||
setText(role('self-score'), selfScore);
|
||||
setText(role('opponent-score'), opponentScore);
|
||||
var selfScore = dicePointValue(self);
|
||||
var opponentScore = dicePointValue(opponent);
|
||||
setDiceScore(role('self-score'), selfScore, 'self');
|
||||
setDiceScore(
|
||||
role('opponent-score'),
|
||||
opponentScore,
|
||||
'opponent'
|
||||
);
|
||||
if (selfScore && opponentScore) {
|
||||
frame.classList.add('has-scores');
|
||||
} else {
|
||||
@ -3381,8 +3636,18 @@
|
||||
formatCoin((winner && winner.payout_coin) || 0)
|
||||
);
|
||||
if (self && self.balance_after > 0) {
|
||||
setCoin(self.balance_after);
|
||||
var balanceAfter = Math.trunc(
|
||||
Number(self.balance_after) || 0
|
||||
);
|
||||
if (winnerIsSelf && balanceAfter > state.balanceCoin) {
|
||||
return playVictoryCoinCredit(
|
||||
state.balanceCoin,
|
||||
balanceAfter
|
||||
);
|
||||
}
|
||||
setCoin(balanceAfter);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function refreshBalance() {
|
||||
@ -3401,8 +3666,7 @@
|
||||
renderMatchParticipants(match);
|
||||
resetFrame();
|
||||
frame.classList.add('is-victory');
|
||||
renderVictory(match);
|
||||
refreshBalance();
|
||||
if (!renderVictory(match)) refreshBalance();
|
||||
trackSelfGameEvent('settlement_show', {
|
||||
match_id: match.match_id,
|
||||
result: match.result,
|
||||
@ -3557,8 +3821,8 @@
|
||||
resetFrame();
|
||||
setPhaseText('');
|
||||
setActionText(matchingText());
|
||||
setText(role('self-score'), '');
|
||||
setText(role('opponent-score'), '');
|
||||
setDiceScore(role('self-score'), '', 'self');
|
||||
setDiceScore(role('opponent-score'), '', 'opponent');
|
||||
setText(document.querySelector('.opponent-mark'), '?');
|
||||
setText(
|
||||
document.querySelector('.matching-label'),
|
||||
|
||||