Introduced config.js for easy multi-game maintenance

This commit is contained in:
Sterling Archer committed 2026-05-31 12:45:35 -07:00
1 parent e4b30117ed
commit f68ab48c58
5 files changed
+68 -33

No files matched your search

+33
View File
@@ -0,0 +1,33 @@
const CONFIG = {
gameName: 'PokéSQL',
subject: 'SQL',
examName: 'SQL',
townName: 'SQL Town',
saveKey: 'pokesql_save_v2',
titleText: 'SQL',
titleEdition: '★ SQL TRAINER ★',
titleFooter: 'PokéSQL v1.0 · SQL · github.com/JustinOros',
townNameUpper:'SQL TOWN',
continueLogoSuffix: 'SQL',
expLabel: 'SQL EXP',
battleMove: 'SQL KNOWLEDGE',
battleMiss: 'SQL QUERY',
completeMsg: "You've conquered SQL Town and mastered Microsoft T-SQL! Your SQL journey is just beginning — more towns and exams await!",
badges: [
'🥉 SQL EXPLORER — Q25',
'🥈 SQL APPRENTICE — Q50',
'🥇 SQL PRACTITIONER — Q75',
'🏆 SQL CHAMPION — Q100',
],
milestones: {
25: { badge: '🥉 SQL EXPLORER', stars: '★ ★ ☆ ☆' },
50: { badge: '🥈 SQL APPRENTICE', stars: '★ ★ ★ ☆' },
75: { badge: '🥇 SQL PRACTITIONER', stars: '★ ★ ★ ★' },
},
introLines: [
"Hello {name}! Welcome to PokéSQL, the world of SQL training! My name is Professor Oak, the SQL Professor!",
"Your mission? Journey through SQL Town, challenge SQL masters, and conquer 100 database questions to become the ultimate SQL Trainer!",
"But first... every trainer needs a partner Pokémon! Let's choose yours, {name}!",
],
namePrompt: "Hello there! Welcome to PokéSQL! My name is Professor Oak — the SQL Professor. Now tell me, what is your name?",
};
+3 -20
View File
@@ -1,16 +1,3 @@
const CONFIG = {
gameName: 'PokéSQL',
subject: 'SQL',
examName: 'SQL',
townName: 'SQL Town',
saveKey: 'pokesql_save_v2',
introLines: [
"Hello {name}! Welcome to PokéSQL, the world of SQL training! My name is Professor Oak, the SQL Professor!",
"Your mission? Journey through SQL Town, challenge SQL masters, and conquer 100 database questions to become the ultimate SQL Trainer!",
"But first... every trainer needs a partner Pokémon! Let's choose yours, {name}!",
],
namePrompt: "Hello there! Welcome to PokéSQL! My name is Professor Oak — the SQL Professor. Now tell me, what is your name?",
};
const ALL_POKEMON = [ const ALL_POKEMON = [
{ name:'Charmander', emoji:'🔥', type:'Fire' }, { name:'Charmander', emoji:'🔥', type:'Fire' },
@@ -106,13 +93,9 @@ const INTRO_MSGS = CONFIG.introLines.map(text => ({ speaker:'PROFESSOR OAK', npc
const CORRECT_FB = ["That's right!","Excellent work!","Perfect!","Outstanding!","Correct!","You're a natural!","Great answer!","Spot on!","Impressive!","Well done!"]; const CORRECT_FB = ["That's right!","Excellent work!","Perfect!","Outstanding!","Correct!","You're a natural!","Great answer!","Spot on!","Impressive!","Well done!"];
const WRONG_FB = ["Not quite...","Hmm, that's not it.","Try again next time!","Almost...","Not this time!"]; const WRONG_FB = ["Not quite...","Hmm, that's not it.","Try again next time!","Almost...","Not this time!"];
const MILESTONES = {
25: { badge:'🥉 CLOUD EXPLORER', stars:'★ ★ ☆ ☆' },
50: { badge:'🥈 AZURE APPRENTICE', stars:'★ ★ ★ ☆' },
75: { badge:'🥇 CLOUD PRACTITIONER', stars:'★ ★ ★ ★' },
};
const SAVE_KEY = CONFIG.saveKey; const SAVE_KEY = CONFIG.saveKey;
const MILESTONES = CONFIG.milestones;
function saveGame(s) { function saveGame(s) {
try { localStorage.setItem(SAVE_KEY, JSON.stringify({ try { localStorage.setItem(SAVE_KEY, JSON.stringify({
@@ -2028,7 +2011,7 @@ class Game {
const msg = document.getElementById('battle-anim-msg'); const msg = document.getElementById('battle-anim-msg');
if (correct) { if (correct) {
msg.textContent = `${playerPoke.name} used SQL KNOWLEDGE!`; msg.textContent = `${playerPoke.name} used ${CONFIG.battleMove}!`;
SFX.attack(); SFX.attack();
setTimeout(() => { setTimeout(() => {
npcHp.style.width = '0%'; npcHp.style.width = '0%';
@@ -2044,7 +2027,7 @@ class Game {
this.showResult(true, q); this.showResult(true, q);
}, 2200); }, 2200);
} else { } else {
msg.textContent = `${playerPoke.name} used SQL QUERY... but it missed!`; msg.textContent = `${playerPoke.name} used ${CONFIG.battleMiss}... but it missed!`;
SFX.attack(); SFX.attack();
setTimeout(() => { setTimeout(() => {
msg.textContent = `${npcPoke.name} used COUNTER ATTACK!`; msg.textContent = `${npcPoke.name} used COUNTER ATTACK!`;
+31 -12
View File
@@ -7,7 +7,7 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="theme-color" content="#0a0520"> <meta name="theme-color" content="#0a0520">
<title>PokéSQL — Lean SQL</title> <title id="page-title">PokéSQL — Learn SQL</title>
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
</head> </head>
@@ -28,19 +28,19 @@
<div class="title-stars"></div> <div class="title-stars"></div>
<div class="title-main"> <div class="title-main">
<div class="title-logo"> <div class="title-logo">
<span class="title-poke">POKÉ</span><span class="title-sql">SQL</span> <span class="title-poke">POKÉ</span><span class="title-game" id="title-game-text">SQL</span>
</div> </div>
<div class="title-edition">★ SQL TRAINER ★</div> <div class="title-edition" id="title-edition-text">★ SQL TRAINER ★</div>
<div class="title-tap blink">PRESS START</div> <div class="title-tap blink">PRESS START</div>
</div> </div>
<div class="title-footer">PokéSQL v1.0 · SQL · github.com/JustinOros</div> <div class="title-footer" id="title-footer-text">PokéSQL v1.0 · SQL · github.com/JustinOros</div>
</div> </div>
</div> </div>
<!-- CONTINUE OR NEW GAME --> <!-- CONTINUE OR NEW GAME -->
<div id="screen-continue" class="screen"> <div id="screen-continue" class="screen">
<div class="continue-bg"> <div class="continue-bg">
<div class="continue-logo">POKÉ<span>SQL</span></div> <div class="continue-logo">POKÉ<span id="continue-logo-text">SQL</span></div>
<div class="continue-card" id="continue-card"> <div class="continue-card" id="continue-card">
<div class="continue-card-header">📂 CONTINUE</div> <div class="continue-card-header">📂 CONTINUE</div>
<div class="save-row"><span class="save-lbl">TRAINER</span><span class="save-val" id="save-name-disp">—</span></div> <div class="save-row"><span class="save-lbl">TRAINER</span><span class="save-val" id="save-name-disp">—</span></div>
@@ -142,7 +142,7 @@
<div class="map-header"> <div class="map-header">
<div class="map-left"> <div class="map-left">
<span class="map-pin">📍</span> <span class="map-pin">📍</span>
<span class="map-town-name">SQL TOWN</span> <span class="map-town-name" id="map-town-name-text">SQL TOWN</span>
</div> </div>
<div class="map-center"> <div class="map-center">
<div class="prog-bar-outer"><div class="prog-bar-inner" id="map-prog-bar"></div></div> <div class="prog-bar-outer"><div class="prog-bar-inner" id="map-prog-bar"></div></div>
@@ -260,7 +260,7 @@
<div class="levelup-box"> <div class="levelup-box">
<div class="lu-stars blink" id="lu-stars">★ BADGE EARNED! ★</div> <div class="lu-stars blink" id="lu-stars">★ BADGE EARNED! ★</div>
<div class="lu-sprite"><div class="lu-player-sprite"></div></div> <div class="lu-sprite"><div class="lu-player-sprite"></div></div>
<div class="lu-text"><span id="lu-name">ASH</span> gained SQL EXP!</div> <div class="lu-text"><span id="lu-name">ASH</span> gained <span id="exp-label-text">SQL EXP</span>!</div>
<div class="lu-badge" id="lu-badge">🏅 CLOUD TRAINEE</div> <div class="lu-badge" id="lu-badge">🏅 CLOUD TRAINEE</div>
<div class="lu-prog-wrap"> <div class="lu-prog-wrap">
<div class="lu-prog-outer"><div class="lu-prog-inner" id="lu-prog-inner"></div></div> <div class="lu-prog-outer"><div class="lu-prog-inner" id="lu-prog-inner"></div></div>
@@ -277,14 +277,14 @@
<div class="complete-trophy">🏆</div> <div class="complete-trophy">🏆</div>
<div class="complete-title">CHAMPION!</div> <div class="complete-title">CHAMPION!</div>
<div class="complete-name" id="complete-name">ASH</div> <div class="complete-name" id="complete-name">ASH</div>
<p class="complete-msg">You've conquered SQL Town and mastered Microsoft T-SQL! Your SQL journey is just beginning — more towns and exams await!</p> <p class="complete-msg"><span id="complete-msg-text">You've conquered SQL Town and mastered Microsoft T-SQL! Your SQL journey is just beginning — more towns and exams await!</span></p>
<div class="complete-stats" id="complete-stats"></div> <div class="complete-stats" id="complete-stats"></div>
<div class="complete-pokemon" id="complete-pokemon"></div> <div class="complete-pokemon" id="complete-pokemon"></div>
<div class="complete-badges"> <div class="complete-badges">
<div class="badge-row">🥉 SQL EXPLORER — Q25</div> <div class="badge-row"><span id="badge-1">🥉 SQL EXPLORER — Q25</span></div>
<div class="badge-row">🥈 SQL APPRENTICE — Q50</div> <div class="badge-row"><span id="badge-2">🥈 SQL APPRENTICE — Q50</span></div>
<div class="badge-row">🥇 SQL PRACTITIONER — Q75</div> <div class="badge-row"><span id="badge-3">🥇 SQL PRACTITIONER — Q75</span></div>
<div class="badge-row">🏆 SQL CHAMPION — Q100</div> <div class="badge-row"><span id="badge-4">🏆 SQL CHAMPION — Q100</span></div>
<div class="badge-row">🗺️ More towns & exams coming soon...</div> <div class="badge-row">🗺️ More towns & exams coming soon...</div>
</div> </div>
<button class="btn-pixel btn-red btn-full" id="btn-play-again">▶ PLAY AGAIN</button> <button class="btn-pixel btn-red btn-full" id="btn-play-again">▶ PLAY AGAIN</button>
@@ -316,6 +316,25 @@
</div> </div>
<div id="toast" class="toast hidden"></div> <div id="toast" class="toast hidden"></div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const set = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; };
set('title-game-text', CONFIG.titleText);
set('title-edition-text', CONFIG.titleEdition);
set('title-footer-text', CONFIG.titleFooter);
set('continue-logo-text', CONFIG.continueLogoSuffix);
set('map-town-name-text', CONFIG.townNameUpper);
set('exp-label-text', CONFIG.expLabel);
set('complete-msg-text', CONFIG.completeMsg);
if (CONFIG.badges) {
CONFIG.badges.forEach((b, i) => set(`badge-${i+1}`, b));
}
set('page-title', CONFIG.gameName + ' — Learn ' + CONFIG.subject);
document.title = CONFIG.gameName + ' — Learn ' + CONFIG.subject;
});
</script>
<script src="config.js"></script>
<script src="game.js"></script> <script src="game.js"></script>
</body> </body>
</html> </html>
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -379,7 +379,7 @@ html, body {
.title-main { text-align:center; z-index:1; padding:24px 16px; } .title-main { text-align:center; z-index:1; padding:24px 16px; }
.title-logo { margin-bottom:16px; line-height:1; } .title-logo { margin-bottom:16px; line-height:1; }
.title-poke { font-size:clamp(22px,7.5vw,38px); color:var(--yellow); text-shadow:4px 4px 0 #7a5800,0 0 24px rgba(248,192,48,.5); animation:goldShimmer 3s ease-in-out infinite; display:inline-block; } .title-poke { font-size:clamp(22px,7.5vw,38px); color:var(--yellow); text-shadow:4px 4px 0 #7a5800,0 0 24px rgba(248,192,48,.5); animation:goldShimmer 3s ease-in-out infinite; display:inline-block; }
.title-sql { font-size:clamp(22px,7.5vw,38px); color:#60c8ff; text-shadow:4px 4px 0 #003d70,0 0 24px rgba(96,200,255,.5); display:inline-block; animation:blueShimmer 3s ease-in-out infinite; } .title-game { font-size:clamp(22px,7.5vw,38px); color:#60c8ff; text-shadow:4px 4px 0 #003d70,0 0 24px rgba(96,200,255,.5); display:inline-block; animation:blueShimmer 3s ease-in-out infinite; }
.title-sub { font-size:clamp(6px,1.8vw,8px); color:rgba(255,255,255,.75); letter-spacing:1px; margin:10px 0 6px; } .title-sub { font-size:clamp(6px,1.8vw,8px); color:rgba(255,255,255,.75); letter-spacing:1px; margin:10px 0 6px; }
.title-edition { font-size:clamp(5.5px,1.6vw,7px); color:var(--yellow); margin-bottom:24px; animation:goldShimmer 3s ease-in-out infinite; } .title-edition { font-size:clamp(5.5px,1.6vw,7px); color:var(--yellow); margin-bottom:24px; animation:goldShimmer 3s ease-in-out infinite; }
.title-deco { font-size:clamp(22px,6vw,32px); margin-bottom:28px; display:flex; gap:16px; justify-content:center; } .title-deco { font-size:clamp(22px,6vw,32px); margin-bottom:28px; display:flex; gap:16px; justify-content:center; }