import "./flipper.css"; function importAll(r) { let obj = {}; r.keys().forEach((key) => { obj[key.replace("./", "").replace(".png", "")] = r(key); }); return obj; } const images = importAll(require.context("./", false, /\.(png|jpe?g|svg)$/)); const cardNames = "abcdefghabcdefgh"; export default class Game { duration = 1000; constructor({ containerId, onLose, onWon }) { Object.assign(this, { container: document.getElementById(containerId), onLose, onWon, }); this.addBg(); this.init(); } init() { Object.assign(this, { steps: 25, score: 0, }); this.shuffleCards(); this.update(); } update() { this.scoreEl.textContent = this.score; this.stepEl.textContent = this.steps; } setSize() { Object.assign(this, { width: this.container.clientWidth, height: this.container.clientHeight, }); this.scoreEl.style.fontSize = (this.width / 2160) * 100 + "px"; this.scoreEl.style.lineHeight = (this.width / 2160) * 116 + "px"; this.stepEl.style.fontSize = (this.width / 2160) * 100 + "px"; this.stepEl.style.lineHeight = (this.width / 2160) * 116 + "px"; } addBg() { this.scoreEl = document.createElement("div"); this.scoreEl.className = "meta l"; this.stepEl = document.createElement("div"); this.stepEl.className = "meta r"; const bg = document.createElement("div"); bg.className = "flipper"; this.cardsContainer = bg; this.container.appendChild(bg); this.setSize(); bg.appendChild(this.scoreEl); bg.appendChild(this.stepEl); this.resizeListener = window.addEventListener("resize", () => { this.setSize(); }); this.cards = Array.from(cardNames).map((name) => { const url = images[name]; const card = document.createElement("div"); card.className = "card"; card.setAttribute("data-name", name); const front = document.createElement("div"); front.className = "front"; front.style.backgroundImage = `url(${url})`; card.appendChild(front); const back = document.createElement("div"); back.className = "back"; card.appendChild(back); return card; }); this.cards.forEach((card) => { this.cardsContainer.appendChild(card); }); this.cards.forEach((card) => { card.addEventListener("click", this.flip.bind(this, card)); }); } pause() {} resume() {} restart() { this.init(); } dispose() { window.removeEventListener("resize", this.resizeListener); } shuffleCards() { this.cards.forEach((card) => { const randomNumber = Math.floor(Math.random() * this.cards.length) + 1; card.classList.remove("has-match"); card.classList.remove("flipped"); setTimeout(() => { card.style.order = `${randomNumber}`; }, 400); }); } checkAllCards() { if (this.cards.every((card) => card.classList.contains("has-match"))) { this.onWon && this.onWon(); setTimeout(() => { this.restart(); }, this.duration); } } stopEvent() { this.cardsContainer.classList.add("no-event"); setTimeout(() => { this.cardsContainer.classList.remove("no-event"); }, this.duration); } checkIfMatched(firstCard, secondCard) { if (firstCard.dataset.name === secondCard.dataset.name) { this.score += 20; firstCard.classList.remove("flipped"); secondCard.classList.remove("flipped"); firstCard.classList.add("has-match"); secondCard.classList.add("has-match"); this.checkAllCards(); } else { setTimeout(() => { firstCard.classList.remove("flipped"); secondCard.classList.remove("flipped"); }, this.duration); } } flip(selectedCard) { this.steps--; if (this.steps < 0) { this.onLose && this.onLose(); this.restart(); } selectedCard.classList.add("flipped"); const flippedCards = this.cards.filter((card) => card.classList.contains("flipped") ); if (flippedCards.length === 2) { this.stopEvent(); this.checkIfMatched(flippedCards[0], flippedCards[1]); } this.update(); } }