Adding intro to the app with a skip button
This commit is contained in:
@@ -17,6 +17,9 @@ let authProfile = null
|
||||
let leaderboardScope = "hour"
|
||||
let latestLeaderboardRows = []
|
||||
let lastDefinition = null
|
||||
let introDismissed = false
|
||||
let pendingInteractionStart = false
|
||||
let introTimers = []
|
||||
|
||||
const WORD_LENGTH = 5
|
||||
const MAX_GUESSES = 6
|
||||
@@ -26,6 +29,25 @@ const STATS_KEY = "fancy-wordle-stats-v2"
|
||||
const LOCAL_ROUND_KEY = "fancy-wordle-hourly-round-v1"
|
||||
const PLAY_INTERVAL_MS = 60 * 60 * 1000
|
||||
const GUESS_TIMEOUT_MS = 10000
|
||||
const INTRO_DURATION_MS = 5200
|
||||
const INTRO_LETTER_SETS = [
|
||||
["D", "E", "S", "I", "G", "N"],
|
||||
["C", "A", "M", "E", "R", "A"],
|
||||
["A", "S", "P", "E", "C", "T"],
|
||||
["W", "O", "R", "D", "L", "E"]
|
||||
]
|
||||
const INTRO_STATUS_SETS = [
|
||||
["wrong", "wrong", "wrong", "wrong", "wrong", "wrong"],
|
||||
["wrong", "misplaced", "wrong", "misplaced", "wrong", "wrong"],
|
||||
["misplaced", "wrong", "misplaced", "wrong", "wrong", "misplaced"],
|
||||
["correct", "correct", "correct", "correct", "correct", "correct"]
|
||||
]
|
||||
const INTRO_SOUND_EVENTS = [
|
||||
[280, "flip-start"],
|
||||
[1280, "misplaced-pass"],
|
||||
[2460, "answer-lock"],
|
||||
[3720, "logo-lock"]
|
||||
]
|
||||
const KEY_ROWS = ["QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM"]
|
||||
const FALLBACK_TARGET_WORDS = [
|
||||
"about",
|
||||
@@ -102,6 +124,10 @@ const guessBars = document.getElementById("guess-bars")
|
||||
const statsDefinition = document.getElementById("stats-definition")
|
||||
const resetStatsButton = document.getElementById("reset-stats")
|
||||
const shareResultsButton = document.getElementById("share-results")
|
||||
const introOverlay = document.getElementById("intro-overlay")
|
||||
const introSkipButton = document.getElementById("intro-skip")
|
||||
const introTileRow = document.getElementById("intro-tiles")
|
||||
const introTiles = Array.from(document.querySelectorAll(".intro-tile"))
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initializeGame, { once: true })
|
||||
@@ -113,6 +139,7 @@ async function initializeGame() {
|
||||
if (hasInitialized) return
|
||||
hasInitialized = true
|
||||
|
||||
initializeIntro()
|
||||
createBoard()
|
||||
createKeyboard()
|
||||
restoreTheme()
|
||||
@@ -132,6 +159,111 @@ async function initializeGame() {
|
||||
await startHourlyRound()
|
||||
}
|
||||
|
||||
function initializeIntro() {
|
||||
if (!introOverlay || introTiles.length === 0) {
|
||||
introDismissed = true
|
||||
document.body.classList.remove("intro-active")
|
||||
return
|
||||
}
|
||||
|
||||
if (introOverlay.dataset.initialized) return
|
||||
introOverlay.dataset.initialized = "true"
|
||||
introDismissed = false
|
||||
document.body.classList.add("intro-active")
|
||||
introSkipButton?.addEventListener("click", dismissIntro)
|
||||
|
||||
if (prefersReducedMotion()) {
|
||||
setIntroFrame(INTRO_LETTER_SETS.length - 1, false)
|
||||
introTileRow?.classList.add("is-solved", "is-logo")
|
||||
introTimers.push(setTimeout(dismissIntro, 700))
|
||||
return
|
||||
}
|
||||
|
||||
scheduleIntroSequence()
|
||||
introTimers.push(setTimeout(dismissIntro, INTRO_DURATION_MS))
|
||||
}
|
||||
|
||||
function prefersReducedMotion() {
|
||||
return window.matchMedia?.("(prefers-reduced-motion: reduce)").matches
|
||||
}
|
||||
|
||||
function setIntroTile(tile, letter, status) {
|
||||
const letterElement = tile.querySelector(".intro-letter")
|
||||
tile.dataset.status = status
|
||||
if (letterElement) letterElement.textContent = letter
|
||||
}
|
||||
|
||||
function flipIntroTile(tile, letter, status, delay) {
|
||||
introTimers.push(setTimeout(() => {
|
||||
tile.classList.add("is-flipping")
|
||||
introTimers.push(setTimeout(() => setIntroTile(tile, letter, status), 130))
|
||||
introTimers.push(setTimeout(() => tile.classList.remove("is-flipping"), 285))
|
||||
}, delay))
|
||||
}
|
||||
|
||||
function setIntroFrame(frameIndex, animate = true) {
|
||||
introTiles.forEach((tile, index) => {
|
||||
const letter = INTRO_LETTER_SETS[frameIndex][index]
|
||||
const status = INTRO_STATUS_SETS[frameIndex][index]
|
||||
if (animate) {
|
||||
flipIntroTile(tile, letter, status, index * 58)
|
||||
return
|
||||
}
|
||||
|
||||
tile.classList.remove("is-flipping")
|
||||
setIntroTile(tile, letter, status)
|
||||
})
|
||||
|
||||
if (frameIndex === INTRO_LETTER_SETS.length - 1) {
|
||||
introTimers.push(setTimeout(() => introTileRow?.classList.add("is-solved"), 420))
|
||||
introTimers.push(setTimeout(() => introTileRow?.classList.add("is-logo"), 1180))
|
||||
}
|
||||
}
|
||||
|
||||
function dispatchIntroSoundCue(name) {
|
||||
window.dispatchEvent(new CustomEvent("wordleIntro:soundCue", { detail: { name } }))
|
||||
}
|
||||
|
||||
function scheduleIntroSequence() {
|
||||
clearIntroTimers()
|
||||
introTileRow?.classList.remove("is-solved", "is-logo")
|
||||
setIntroFrame(0, false)
|
||||
|
||||
const frameTimes = [880, 1720, 2580]
|
||||
frameTimes.forEach((time, index) => {
|
||||
introTimers.push(setTimeout(() => setIntroFrame(index + 1, true), time))
|
||||
})
|
||||
|
||||
INTRO_SOUND_EVENTS.forEach(([time, name]) => {
|
||||
introTimers.push(setTimeout(() => dispatchIntroSoundCue(name), time))
|
||||
})
|
||||
}
|
||||
|
||||
function clearIntroTimers() {
|
||||
introTimers.forEach(clearTimeout)
|
||||
introTimers = []
|
||||
}
|
||||
|
||||
function dismissIntro() {
|
||||
if (introDismissed) return
|
||||
|
||||
introDismissed = true
|
||||
clearIntroTimers()
|
||||
setIntroFrame(INTRO_LETTER_SETS.length - 1, false)
|
||||
introTileRow?.classList.add("is-solved", "is-logo")
|
||||
introOverlay?.classList.add("is-dismissing")
|
||||
document.body.classList.remove("intro-active")
|
||||
|
||||
setTimeout(() => {
|
||||
if (introOverlay) introOverlay.hidden = true
|
||||
}, 540)
|
||||
|
||||
if (pendingInteractionStart && !gameFinished) {
|
||||
pendingInteractionStart = false
|
||||
startInteraction()
|
||||
}
|
||||
}
|
||||
|
||||
async function loadWordLists() {
|
||||
targetWords = await loadWordList("targetWords")
|
||||
|
||||
@@ -755,6 +887,12 @@ async function signOut() {
|
||||
}
|
||||
|
||||
function startInteraction() {
|
||||
if (!introDismissed) {
|
||||
pendingInteractionStart = true
|
||||
return
|
||||
}
|
||||
|
||||
pendingInteractionStart = false
|
||||
stopInteraction()
|
||||
document.addEventListener("click", handleMouseClick)
|
||||
document.addEventListener("keydown", handleKeyPress)
|
||||
|
||||
Reference in New Issue
Block a user