From 73b3fa2f7e97ea151e7bf32a379c563274f16c29 Mon Sep 17 00:00:00 2001 From: pj90 Date: Sun, 9 Aug 2026 22:12:39 +0530 Subject: [PATCH] Added Punarjanma button on Pralaya Screen. And fixed vocabulary in game. --- ...etanaJaagrita.mp3 => chetanaaJaagrita.mp3} | Bin audio/{drishti.mp3 => drishtee.mp3} | Bin audio/jagritaBreath.mp3 | Bin 48044 -> 0 bytes ...purnaSamarpana.mp3 => poornaSamarpana.mp3} | Bin ...dhaBandhana.mp3 => praarabdhaBandhana.mp3} | Bin audio/{prarambha.mp3 => praarambha.mp3} | Bin index.html | 56 +++--- src/audio.js | 64 +++---- src/engine.js | 157 ++++++++--------- src/i18n.js | 118 ++++++------- src/karma.js | 28 +-- src/main.js | 159 +++++++++--------- src/physics.js | 2 +- src/render.js | 30 ++-- src/{shastra.js => shaashtra.js} | 48 +++--- src/state.js | 26 +-- src/touch.js | 2 +- src/tutorial.js | 6 +- style.css | 36 ++-- 19 files changed, 377 insertions(+), 355 deletions(-) rename audio/{chetanaJaagrita.mp3 => chetanaaJaagrita.mp3} (100%) rename audio/{drishti.mp3 => drishtee.mp3} (100%) delete mode 100644 audio/jagritaBreath.mp3 rename audio/{purnaSamarpana.mp3 => poornaSamarpana.mp3} (100%) rename audio/{prarabdhaBandhana.mp3 => praarabdhaBandhana.mp3} (100%) rename audio/{prarambha.mp3 => praarambha.mp3} (100%) rename src/{shastra.js => shaashtra.js} (90%) diff --git a/audio/chetanaJaagrita.mp3 b/audio/chetanaaJaagrita.mp3 similarity index 100% rename from audio/chetanaJaagrita.mp3 rename to audio/chetanaaJaagrita.mp3 diff --git a/audio/drishti.mp3 b/audio/drishtee.mp3 similarity index 100% rename from audio/drishti.mp3 rename to audio/drishtee.mp3 diff --git a/audio/jagritaBreath.mp3 b/audio/jagritaBreath.mp3 deleted file mode 100644 index fc88bf4e098ce0bdc1205c4f06284d5fa3f0ca52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48044 zcmZsi1yoy6x95}K2~gafpv7H_yA%sfi@RHk2MF#i1&VudhZZRmFYZvFxD_eV0)>I^ z&CHs&-ki0Pv+uh1+;#KIKK9@HD#`L91D*?=j<&YkQ;iJ(AgP*pTMO`T@N#f-asB7y ze|HI%O|9?~8&e`Va%!{W_6#&o)2cTkLV&UKul2B07LYY|Dx%dQx#U-TWl~mL< zwRH_m-kMw4*gLtnd%gGZ4+;(qkBo{zNw|X>r2nqZ$qQs zr>5r?msZz*ZtWf%o}6C%zWVd`?&0}Ko*((S{%-{elKijZPWT{0U(Vy*tSkVCHvpL1 zmjr;7d%&Ln0H9(MuhL#UvmGX?o!CurEGW`S2EeAu5qoMp_JfLw>iH(9PxXH{ zVkLe*|4abVi>LBz$p4Q^o*O;i1xWH9d!_a9@$nwnW*AQ5bN=J``u};$^7l{W`4q`h zefDf{ojsNR*FZMg7{@usIpX*O)c1^mx5R4l`m@ucsJ;NlBMM0ALlu=2l{6ZL*l67~rpi7Z(t`Tn3^Df~i7B2>V*-8Z;)^R!m zJgAi9bJO0Z7XQbPd9tOHq`_eFD1M9|t4PchrQtz60035%VMnojv=t5oZL(3M<}`6c zG)=k~sc~2fv7Mo1UGwAZk6v{%GdlXfCt6IeJpEAIRnf~`<72$=P~qg_8cA2jtO_VM zJh#%Kc-t=kbcp~tD}C=rxPw7#)rDl;ixiof3vow`KOhPjP#6Wh976&^IvWgucg>-a zPijTL-rL>-=q?T4i?um^PA-(gV-Cm*hsLyMA~TD@v%R&Wt9NYZlmFmVznfRzI;U`+-`KiG1plp(TotwADMOrzY6v zx(K`XM3Skpa^dqxc4(nU`H3(~DWsRsl!kMse2Vou$;e{V3aodN2w4l(L<3BKt*$2C{WvZBLYk=5notF|DJ+>VtEHRy#xD6{Qy)U zSY=K3o*n^F7Ow4kqbDuRqeCtEcG!uxtK4G+v;W~Dp-b}e2)~L2U}3`*&{5>;&{^G^ zG~7Z2K;x`j%Hk<`N$D-c27tn9Vqg_e)jRsQ+5%EYmPbT$EhU3 zE_Lu|cYuKc7Z*Qf0Na*_mHo@8%e@x);NE{imfJChBNb_3jkJ4CxI2gp%%P!^6}txj zK%|g*RQi2=v~wOE_?k6+BSs`Xd2?KE1lLb5VfpFQYE09CIg?-4h5&+#OWa;pF5G?! zX?!Mof8QQo6b!Mfm$;P^WYk~$1P)3|#f2)f(%E0hU_)#ZF1kM84nhh8!*PHWqh)PW2h2VHf5 zEVTf%w0gdw*q$x99S1C+j<MRPh@P3h90tvith!^r`EFd=C+5YUw(25Tlz~Bz~i4lS8Z?bk;VPHO?~%9 zEK7kKXTN6T#s;BEiG^TCq&j3R%uH)>H-eT1T7yEcJ~KHAZXCCMPLVIJ+|&PS zc>ur*X8eA~s4~J*ko9OeEC_}+D(z*u?}vqzdu3!|QJu24j5fK$A*hm@XC2qQweME(GIaa6L{s5qBVrkeW}6NyFRcO_}$O1C)$=C;Dl&coSQykDfJ z)h`RGuxjGFFnv(T%69;OY(9+D{vwV}au_BDAMW7k7_MZOB|&r^;`auDx;&7Wh1n_ zfk}pd>9^fGM$Ww7z`(7WAv}T(∾8k}|M#SLYZHqS-#0?e#8fExCFrO%q4?`PIqq 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

a^^f6&8k#RBlAP9WiU@vy2 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 YTZ(P-0MLuzo8v43{_jiq|4)Md0hDe0<^TWy diff --git a/audio/purnaSamarpana.mp3 b/audio/poornaSamarpana.mp3 similarity index 100% rename from audio/purnaSamarpana.mp3 rename to audio/poornaSamarpana.mp3 diff --git a/audio/prarabdhaBandhana.mp3 b/audio/praarabdhaBandhana.mp3 similarity index 100% rename from audio/prarabdhaBandhana.mp3 rename to audio/praarabdhaBandhana.mp3 diff --git a/audio/prarambha.mp3 b/audio/praarambha.mp3 similarity index 100% rename from audio/prarambha.mp3 rename to audio/praarambha.mp3 diff --git a/index.html b/index.html index 5cd5249..3e5b50b 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@ - + @@ -19,7 +19,7 @@ - +

🌿 0
🥀 0
-
📜 0
+
📜 0
@@ -62,7 +62,7 @@
♻️ 0
😴
☀️
-
🤲
+
🤲
@@ -106,7 +106,7 @@ - +
🛠️
@@ -135,6 +135,16 @@ style="font-family:'Rajdhani',sans-serif;font-size:15px;line-height:1.8;color:rgba(255,255,255,0.55);max-width:80%;font-weight:500;">

'R' दबाएं जीवन रथ को पुनः आरंभ करने के लिए

+ + @@ -147,29 +157,29 @@

॥ स्तम्भन ॥

- -
-
- -
+ +
+
+ +

॥ शास्त्र ॥

रथ का ज्ञान

-
- -
-
-
-
- - -
+
+
diff --git a/src/audio.js b/src/audio.js index 70a9642..322dbea 100644 --- a/src/audio.js +++ b/src/audio.js @@ -19,7 +19,7 @@ * ── बाहरी निर्भरताएँ (injected callbacks) ───────────────── * Audio.setGameStateGetter(fn) * fn() → { isGameStarted, gameOver, won, isPaused, - * isShastraVisible, chetanaaJaagrita } + * isShaashtraVisible, chetanaaJaagrita } * * Audio.setVibrateCallback(fn) * fn(weakMagnitude, strongMagnitude, duration) → void @@ -32,7 +32,7 @@ * // पेज-लोड पर एक बार: * Audio.setGameStateGetter(() => ({ * isGameStarted, gameOver, won, isPaused, - * isShastraVisible, chetanaaJaagrita + * isShaashtraVisible, chetanaaJaagrita * })); * Audio.setVibrateCallback(vibrateGamepad); * Audio.setReadinessGetters({ @@ -98,11 +98,11 @@ const SUSHUPTI_SWAANSA_DUCK_REDUCTION = 0.20; * हल्के SFX कम। */ const DUCK_STRENGTH = new Map([ - ['purnaSamarpana', 0.60], - ['drishti', 0.35], + ['poornaSamarpana', 0.60], + ['drishtee', 0.35], ['andhakaara', 0.40], ['shuvha', 0.50], - ['ashuvha', 0.55], + ['ashuvha', 0.55], ['jaapa', 0.55], ['samarpita', 0.45], ['naamaSamarpita', 0.55], @@ -120,7 +120,7 @@ const DUCK_STRENGTH = new Map([ ['punyaBandhana', 0.40], ['bandhanaMukta', 0.35], ['naama', 0.45], - ['antimaCharana', 0.35], + ['antimaCharana', 0.35], ['kripa', 0.50], ['shankhaDhwani', 0.45], ['jyotiDhwani', 0.40], @@ -179,12 +179,12 @@ class AudioManager { jyotiDhwani: null, // B-press ज्योति shankhaPrapta: null, // शंख-संग्रह jyotiPrapta: null, // ज्योति-संग्रह - purnaSamarpana: null, // पूर्ण-समर्पण - drishti: null, // दृष्टि लौटी + poornaSamarpana: null, // पूर्ण-समर्पण + drishtee: null, // दृष्टि लौटी andhakaara: null, // पाप-अंधकार // Batch-2 (deferred — भारी / देर से ज़रूरी) bgMusic: null, // पृष्ठभूमि संगीत (~6.5MB) - chetanaJaagrita: null, // चेतना-जागृति + chetanaaJaagrita: null, // चेतना-जागृति pralaya: null, // प्रलय jaagritaSwaansa: null, // अंतरिक्ष-श्वास (ambient loop) moksha: null, // मोक्ष-विजय @@ -244,7 +244,7 @@ class AudioManager { // ── Injected callbacks ────────────────────────────── /** * () => { isGameStarted, gameOver, won, isPaused, - * isShastraVisible, chetanaaJaagrita } + * isShaashtraVisible, chetanaaJaagrita } */ this._getGameState = null; @@ -268,7 +268,7 @@ class AudioManager { * circular dependency को callback pattern से हल करता है। * * @param {Function} fn — () => { isGameStarted, gameOver, won, - * isPaused, isShastraVisible, chetanaaJaagrita } + * isPaused, isShaashtraVisible, chetanaaJaagrita } */ setGameStateGetter(fn) { this._getGameState = fn; @@ -455,19 +455,19 @@ class AudioManager { this._vibrate?.(0.10, 0.05, 50); break; - case 'purnaSamarpana': + case 'poornaSamarpana': // अंतिम चरण में समस्त नाम-समर्पण (एक बार/जीवन-चक्र) - buf.purnaSamarpana - ? this._playBufferedSound(buf.purnaSamarpana, ctx.destination, 0.65) + buf.poornaSamarpana + ? this._playBufferedSound(buf.poornaSamarpana, ctx.destination, 0.65) : this._playTone(987.77, 0.14, 'sine', 0.04, 1567.98); this._vibrate?.(0.20, 0.25, 130); break; // ── दृष्टि / अंधकार ──────────────────────────── - case 'drishti': + case 'drishtee': // पाप-अंधकार (ashuvhaKarma≥3) से बाहर आने पर - buf.drishti - ? this._playBufferedSound(buf.drishti, ctx.destination, 0.55) + buf.drishtee + ? this._playBufferedSound(buf.drishtee, ctx.destination, 0.55) : this._playTone(880, 0.10, 'sine', 0.03, 1318.51); this._vibrate?.(0.10, 0.08, 60); break; @@ -627,10 +627,10 @@ class AudioManager { // ── चेतना-जागृति (fade-in envelope) ──────────── case 'chetana': // समर्पित≥50 पर एक बार — पूरी buffer-duration तक प्राकृतिक रूप से बजे - if (buf.chetanaJaagrita) { + if (buf.chetanaaJaagrita) { const cNow = ctx.currentTime; const cSrc = ctx.createBufferSource(); - cSrc.buffer = buf.chetanaJaagrita; + cSrc.buffer = buf.chetanaaJaagrita; const cGain = ctx.createGain(); cGain.gain.setValueAtTime(0.0001, cNow); cGain.gain.exponentialRampToValueAtTime(0.7, cNow + 0.05); // हल्का fade-in @@ -639,7 +639,7 @@ class AudioManager { cSrc.start(cNow); // premature stop() नहीं — पूरी duration तक बजे (शास्त्र-संगत) } else { - console.warn('⚠️ chetanaJaagrita.mp3 लोड नहीं हुई — ./audio/chetanaJaagrita.mp3 path जाँचें'); + console.warn('⚠️ chetanaaJaagrita.mp3 लोड नहीं हुई — ./audio/chetanaaJaagrita.mp3 path जाँचें'); } break; @@ -774,7 +774,7 @@ class AudioManager { } // ── jaagritaSwaansa — gameplay-gated, सांस-सिंक ── - // 🛠️ बग-फिक्स: पहले pause/shastra/pralaya/moksha में भी बजती थी + // 🛠️ बग-फिक्स: पहले pause/shaashtra/pralaya/moksha में भी बजती थी if (this._jaagritaSwaansaGain) { const swaansaVol = JAAGRITA_SWAANSA_VOLUME * (1 - BG_SWAANSA_MOD_RANGE + bp * BG_SWAANSA_MOD_RANGE); @@ -783,7 +783,7 @@ class AudioManager { } // ── sushuptiSwaansa — gameplay-gated, सांस-सिंक (pre-chetanaaJaagrita) ── - // 🛠️ बग-फिक्स: shathendriya जैसा gameplay-gating — pause/shastra पर मौन + // 🛠️ बग-फिक्स: shathendriya जैसा gameplay-gating — pause/shaashtra पर मौन if (this._sushuptiSwaansaGain) { const dreamVol = SUSHUPTI_SWAANSA_VOLUME * (1 - BG_SWAANSA_MOD_RANGE + bp * BG_SWAANSA_MOD_RANGE); @@ -827,7 +827,7 @@ class AudioManager { } /** - * punahaPrarambha() में बुलाएँ — jaagritaSwaansa बंद करें। + * punahaPraarambha() में बुलाएँ — jaagritaSwaansa बंद करें। * अगले जीवन में chetanaaJaagrita होने पर दोबारा शुरू होगी। * (replaces stopJaagritaSwaansaLayer()) */ @@ -842,8 +842,8 @@ class AudioManager { } /** - * punahaPrarambha() में बुलाएँ — नए जीवन-चक्र के लिए sushuptiSwaansa फिर शुरू। - * (replaces startSushuptiSwaansaLayer() public call in punahaPrarambha) + * punahaPraarambha() में बुलाएँ — नए जीवन-चक्र के लिए sushuptiSwaansa फिर शुरू। + * (replaces startSushuptiSwaansaLayer() public call in punahaPraarambha) */ startJaagritaSwaansaLayer() { @@ -883,7 +883,7 @@ class AudioManager { _isActiveGameplay() { const s = this._getGameState?.(); if (!s) return false; - return s.isGameStarted && !s.gameOver && !s.won && !s.isPaused && !s.isShastraVisible; + return s.isGameStarted && !s.gameOver && !s.won && !s.isPaused && !s.isShaashtraVisible; } // ── Synth / buffer playback ───────────────────────────── @@ -1047,7 +1047,7 @@ class AudioManager { { url: './audio/shathendriya.mp3', key: 'shathendriya'}, { url: './audio/sushuptiSwaansa.mp3', key: 'sushuptiSwaansa'}, { url: './audio/timer.mp3', key: 'timer'}, - { url: './audio/prarabdhaBandhana.mp3', key: 'prarabdhaBandhana'}, + { url: './audio/praarabdhaBandhana.mp3', key: 'prarabdhaBandhana'}, { url: './audio/paapaBandhana.mp3', key: 'paapaBandhana'}, { url: './audio/punyaBandhana.mp3', key: 'punyaBandhana'}, { url: './audio/bandhanaMukta.mp3', key: 'bandhanaMukta'}, @@ -1059,9 +1059,9 @@ class AudioManager { { url: './audio/shankhaDhwani.mp3', key: 'shankhaDhwani'}, { url: './audio/jyotiDhwani.mp3', key: 'jyotiDhwani'}, { url: './audio/jyotiPrapta.mp3', key: 'jyotiPrapta'}, - { url: './audio/drishti.mp3', key: 'drishti'}, + { url: './audio/drishtee.mp3', key: 'drishtee'}, { url: './audio/shankhaPrapta.mp3', key: 'shankhaPrapta'}, - { url: './audio/purnaSamarpana.mp3', key: 'purnaSamarpana'}, + { url: './audio/poornaSamarpana.mp3', key: 'poornaSamarpana'}, { url: './audio/andhakaara.mp3', key: 'andhakaara'} ]; @@ -1107,7 +1107,7 @@ class AudioManager { }; const [bg, chetana, pralaya, jaagritaSwaansa, moksha, antimaCharana] = await Promise.all([ _loadAmbient('./audio/bgMusic.mp3'), - _loadAmbient('./audio/chetanaJaagrita.mp3'), + _loadAmbient('./audio/chetanaaJaagrita.mp3'), _loadAmbient('./audio/pralaya.mp3'), _loadAmbient('./audio/jaagritaSwaansa.mp3'), _loadAmbient('./audio/moksha.mp3'), @@ -1116,7 +1116,7 @@ class AudioManager { Object.assign(this.audioBuffers, { bgMusic: bg, - chetanaJaagrita: chetana, + chetanaaJaagrita: chetana, pralaya, jaagritaSwaansa, moksha, @@ -1230,7 +1230,7 @@ class AudioManager { this._jaagritaSwaansaGain = this.audioCtx.createGain(); // 🛠️ बग-फिक्स: node बनने के तुरंत बाद isActiveGameplay() check — - // ताकि pause/shastra के दौरान node बनते ही पूर्ण-स्तर gain न मिले + // ताकि pause/shaashtra के दौरान node बनते ही पूर्ण-स्तर gain न मिले const initVol = this._isActiveGameplay() ? JAAGRITA_SWAANSA_VOLUME : 0; this._jaagritaSwaansaGain.gain.setValueAtTime(initVol, now); this._jaagritaSwaansaGain.connect(this._bgMasterGain); diff --git a/src/engine.js b/src/engine.js index 5048535..fc2b471 100644 --- a/src/engine.js +++ b/src/engine.js @@ -121,21 +121,21 @@ export class KarmaEngine { this.shuvhaKarma = 0; // पुण्य (सक्रिय) this.ashuvhaKarma = 0; // पाप (सक्रिय) this.activeNaam = 0; // ॐ नाम (उपयोग-योग्य) - this.prarabdha = 0; // प्रारब्ध (संचित — सिर्फ़ 10-नाम से भस्म) - this.prarabdhaTimer = 0; // भोग-countdown (frames); पुनर्जन्म पर persist, R-reset पर शून्य - this.prarabdhaGatiModifier = 1.0; // पूर्व-जन्म के punya×paap का संचित गति-भार + this.praarabdha = 0; // प्रारब्ध (संचित — सिर्फ़ 10-नाम से भस्म) + this.praarabdhaTimer = 0; // भोग-countdown (frames); पुनर्जन्म पर persist, R-reset पर शून्य + this.praarabdhaGatiModifier = 1.0; // पूर्व-जन्म के punya×paap का संचित गति-भार this._currentGatiModifier = 1.0; // इस जन्म का live ashuvha×shuvha modifier (rebirth पर snapshot) persist, R-reset पर शून्य - this._prarabdhaTimerPulseAccum = 0; // orbit pulse accumulator + this._praarabdhaTimerPulseAccum = 0; // orbit pulse accumulator this.samarpita = 0; // समर्पित (lifetime) this.punaraJanmaCount = 0; // पुनर्जन्म गिनती - this.isKarmaImmune = false; // purnaSamarpana के बाद अस्थायी कर्म-रक्षा + this.isKarmaImmune = false; // poornaSamarpana के बाद अस्थायी कर्म-रक्षा this.kripa = 0; // कृपा (अनुग्रह) this.shankha = 0; // शंख resource this.jyoti = 0; // ज्योति resource // ── Spiritual State ────────────────────────────────── this.chetanaaJaagrita = false; // मोक्ष की प्रामाणिक शर्त - this.purnaSamarpana = false; // अंतिम-चरण में समस्त नाम समर्पित + this.poornaSamarpana = false; // अंतिम-चरण में समस्त नाम समर्पित this.jaapaNaama = "राधा"; // नाम-जाप पर floating text this.isNaamaJaapa = false; // क्या अभी नाम-जाप-वलय सक्रिय है? this.naamaGhera = 0; // नाम-जाप-वलय की वर्तमान त्रिज्या @@ -151,8 +151,8 @@ export class KarmaEngine { this.gameOver = false; this.isPaused = false; this.won = false; - this.isShastraVisible = false; - this.wasAlreadyPaused = false; // shastra खुलने से पहले का pause-state + this.isShaashtraVisible = false; + this.wasAlreadyPaused = false; // shaashtra खुलने से पहले का pause-state // ── Visual / Animation State ───────────────────────── this.smoothSize = 60; // player body-size (lerped) @@ -225,8 +225,8 @@ export class KarmaEngine { // ── Audio/sound edge-detection flags ───────────────── this._prevGoodKarmaForSound = 0; this._prevBadKarmaForSound = 0; - this._prevPrarabdhaForSound = 0; - this._prevPurnaSamarpana = false; + this._prevPraarabdhaForSound = 0; + this._prevPoornaSamarpana = false; this._prevDrishtiClear = true; this._prevPulledHorseIndex = -1; this._mayaConsumedWhilePulling = false; @@ -240,7 +240,7 @@ export class KarmaEngine { // ── Timer sound flags ──────────────────────────────── this._timerSoundPlayed = false; this._timerTickAccumulator = 0; - this._lastPrarabdhaAlertSecond = -1; + this._lastPraarabdhaAlertSecond = -1; // ── Contextual alert edge-detection (Issue #9) ─────── this._prevSamaya200 = false; // samaya < 200 one-shot warning @@ -250,15 +250,15 @@ export class KarmaEngine { this._samarpitaMilestones = new Set(); // milestone tracking: 10, 25, 50 // ── HUD animation state ────────────────────────────── - this._oldStats = { naama:-1, punya:-1, paap:-1, prarabdha:-1, samarpita:-1, + this._oldStats = { naama:-1, punya:-1, paap:-1, praarabdha:-1, samarpita:-1, punaraJanma:-1, gatee:"-1", kripa:-1, chetana:"", - shankha:-1, drishti:"", purnaSamarpana:"", jyoti:-1 }; - this._uiScales = { naama:1, punya:1, paap:1, prarabdha:1, samarpita:1, + shankha:-1, drishti:"", poornaSamarpana:"", jyoti:-1 }; + this._uiScales = { naama:1, punya:1, paap:1, praarabdha:1, samarpita:1, punaraJanma:1, gatee:1, kripa:1, chetana:1, - shankha:1, drishti:1, purnaSamarpana:1, jyoti:1 }; - this._uiGlows = { naama:0, punya:0, paap:0, prarabdha:0, samarpita:0, + shankha:1, drishti:1, poornaSamarpana:1, jyoti:1 }; + this._uiGlows = { naama:0, punya:0, paap:0, praarabdha:0, samarpita:0, punaraJanma:0, gatee:0, kripa:0, chetana:0, - shankha:0, drishti:0, purnaSamarpana:0, jyoti:0 }; + shankha:0, drishti:0, poornaSamarpana:0, jyoti:0 }; // ── Alert Queue System (Issue #10) ─────────────────── /** Canvas alert queue — max 4 active cards */ @@ -291,11 +291,11 @@ export class KarmaEngine { /** * DOM element references inject करें। - * @param {Object} UI — { naama, punya, paap, prarabdha, samarpita, + * @param {Object} UI — { naama, punya, paap, praarabdha, samarpita, * punaraJanma, kripa, shankha, jyoti, drishti, - * purnaSamarpana, chetana, samayaVal, swaansaVal, + * poornaSamarpana, chetana, samayaVal, swaansaVal, * gatee, alertBox, overlay, overlayTitle, - * overlaySubtitle, viraamaOverlay, shastraOverlay, + * overlaySubtitle, viraamaOverlay, shaashtraOverlay, * container } */ setUI(UI) { @@ -374,7 +374,7 @@ export class KarmaEngine { * @param {number} frameNow — performance.now() timestamp */ update(dt, keys, frameNow) { - if (this.gameOver || this.isPaused || this.isShastraVisible) return; + if (this.gameOver || this.isPaused || this.isShaashtraVisible) return; // ── 1. Outer-orbit counts sync (karma.js) ──────────── this._syncOrbitCounts(); @@ -404,11 +404,11 @@ export class KarmaEngine { this._prevGoodKarmaForSound = this.shuvhaKarma; this._prevBadKarmaForSound = this.ashuvhaKarma; - if (this.prarabdha > 0 && this._prevPrarabdhaForSound === 0) - this._cb.playSound?.('prarabdhaBandhana'); - if (this.prarabdha === 0 && this._prevPrarabdhaForSound > 0) + if (this.praarabdha > 0 && this._prevPraarabdhaForSound === 0) + this._cb.playSound?.('praarabdhaBandhana'); + if (this.praarabdha === 0 && this._prevPraarabdhaForSound > 0) this._cb.playSound?.('bandhanaMukta'); - this._prevPrarabdhaForSound = this.prarabdha; + this._prevPraarabdhaForSound = this.praarabdha; // ── 5. कृपा-माइलस्टोन edge-detection ──────────────── if (this.activeNaam > this._prevActiveNaamForKripa) @@ -432,12 +432,12 @@ export class KarmaEngine { } // ── 6. पूर्ण-समर्पण edge-detection ────────────────── - if (this.purnaSamarpana && !this._prevPurnaSamarpana) { - this._cb.playSound?.('purnaSamarpana'); + if (this.poornaSamarpana && !this._prevPoornaSamarpana) { + this._cb.playSound?.('poornaSamarpana'); this._addFloatingText("🙌", "#ffe9a8", { alpha:1.5, vy:-3, isBigName:true }); } - this._prevPurnaSamarpana = this.purnaSamarpana; + this._prevPoornaSamarpana = this.poornaSamarpana; // ── 7. दृष्टि/अंधकार edge-detection ───────────────── const isDrishtiClear = this.ashuvhaKarma < 3; @@ -659,7 +659,7 @@ export class KarmaEngine { // वलय पूर्ण — नाम-शक्ति जाँचें // ⚠️ शास्त्र-संगत (Issue #11): प्रारब्ध नाम-जाप से नष्ट नहीं होता। - // activeNaam >= 10 होने पर prarabdhaTimer 2× गति से घटता है (§22.5)। + // activeNaam >= 10 होने पर praarabdhaTimer 2× गति से घटता है (§22.5)। if (this.naamaGhera > NAAMA_JAAP_MAX_RADIUS) { this.isNaamaJaapa = false; this.naamaGhera = 0; this._alertKey('naamaJapa', '🌿', 'achievement'); @@ -715,16 +715,16 @@ export class KarmaEngine { // इस frame का combined modifier — rebirth पर snapshot हेतु store this._currentGatiModifier = ashuvhaTimeModifier * shuvhaTimeModifier; // प्रारब्ध-modifier = पूर्व-जन्मों के punya×paap का संचित भार - const prarabdhaModifier = this.prarabdha > 0 ? this.prarabdhaGatiModifier : 1.0; + const praarabdhaModifier = this.praarabdha > 0 ? this.praarabdhaGatiModifier : 1.0; if (!this.swaansaSamapta) { // ── Bug 6 fix: प्रारब्ध का ×1.15 samaya penalty (शास्त्र-संगत) ── - // prarabdha=0 → 1.0×; prarabdha=1 → 1.15×; prarabdha=5 → ≈2.01× - // cap: MAX 3.0× (prarabdha≈9 से ऊपर) — game over न हो instantly - const prarabdhaSamayaMul = this.prarabdha > 0 - ? Math.min(3.0, Math.pow(1.15, this.prarabdha)) + // praarabdha=0 → 1.0×; praarabdha=1 → 1.15×; praarabdha=5 → ≈2.01× + // cap: MAX 3.0× (praarabdha≈9 से ऊपर) — game over न हो instantly + const praarabdhaSamayaMul = this.praarabdha > 0 + ? Math.min(3.0, Math.pow(1.15, this.praarabdha)) : 1.0; - this.samaya -= 0.8 * ashuvhaTimeModifier * shuvhaTimeModifier * prarabdhaSamayaMul * dt; this.swaansaTimer += dt; + this.samaya -= 0.8 * ashuvhaTimeModifier * shuvhaTimeModifier * praarabdhaSamayaMul * dt; this.swaansaTimer += dt; if (this.swaansaTimer >= 360) { this.swaansaTimer -= 360; if (this.swaansa > 0) this.swaansa--; @@ -738,7 +738,7 @@ export class KarmaEngine { if (this._UI?.swaansaVal?.innerText !== swaansaDisplay && this._UI?.swaansaVal) this._UI.swaansaVal.innerText = swaansaDisplay; - const currentWarpVal = (ashuvhaTimeModifier * shuvhaTimeModifier * prarabdhaModifier * 100).toFixed(0); this._updateStatWithPulse(this._UI?.gatee, 'gatee', currentWarpVal, '⚡', '%'); + const currentWarpVal = (ashuvhaTimeModifier * shuvhaTimeModifier * praarabdhaModifier * 100).toFixed(0); this._updateStatWithPulse(this._UI?.gatee, 'gatee', currentWarpVal, '⚡', '%'); if (this.samaya <= 0) { this.samaya = 0; this.swaansa = 0; this.swaansaSamapta = true; @@ -769,13 +769,13 @@ export class KarmaEngine { // ── 18. Stars & sparkles movement ───────────────────── this.stars.forEach(star => { if (!this.swaansaSamapta) { - star.y += star.speed * (ashuvhaTimeModifier * shuvhaTimeModifier * prarabdhaModifier + 0.1) * dt; + star.y += star.speed * (ashuvhaTimeModifier * shuvhaTimeModifier * praarabdhaModifier + 0.1) * dt; if (star.y > this.HEIGHT) { star.y = this.HUD_TOP_Y; star.x = Math.random() * this.WIDTH; } } }); this.tunnelSparkles.forEach(sparkle => { if (!this.swaansaSamapta) { - sparkle.y -= sparkle.speed * (ashuvhaTimeModifier * shuvhaTimeModifier * prarabdhaModifier + 0.2) * dt; sparkle.alpha += sparkle.fadeSpeed * dt; + sparkle.y -= sparkle.speed * (ashuvhaTimeModifier * shuvhaTimeModifier * praarabdhaModifier + 0.2) * dt; sparkle.alpha += sparkle.fadeSpeed * dt; if (sparkle.alpha > 0.9 || sparkle.alpha < 0.2) sparkle.fadeSpeed = -sparkle.fadeSpeed; if (sparkle.y < 0) { sparkle.y = this.HEIGHT; @@ -842,24 +842,24 @@ export class KarmaEngine { if (this.outerOrbits[2]?.glowTimer > 0) this.outerOrbits[2].glowTimer -= dt; // ── 22.5. प्रारब्ध-भोग countdown — "प्रारब्धं भुज्यते एव" (Issue #11) ─ - if (this.prarabdhaTimer > 0) { + if (this.praarabdhaTimer > 0) { // orbit pulse — हर second 📜 हल्की चमके - this._prarabdhaTimerPulseAccum += dt; - if (this._prarabdhaTimerPulseAccum >= 60) { - this._prarabdhaTimerPulseAccum -= 60; + this._praarabdhaTimerPulseAccum += dt; + if (this._praarabdhaTimerPulseAccum >= 60) { + this._praarabdhaTimerPulseAccum -= 60; if (this.outerOrbits[2]) this.outerOrbits[2].glowTimer = 18; } - // ── prarabdha unit घटाने का logic ── - const prevPrarabdha = this.prarabdha; - // Bhog penalty: prarabdha endure करते समय samaya थोड़ा तेज़ घटे - this.prarabdhaTimer = Math.max(0, this.prarabdhaTimer - dt); - const newPrarabdha = this.prarabdhaTimer > 0 - ? Math.ceil(this.prarabdhaTimer / PRARABDHA_BHOG_FRAMES) : 0; + // ── praarabdha unit घटाने का logic ── + const prevPraarabdha = this.praarabdha; + // Bhog penalty: praarabdha endure करते समय samaya थोड़ा तेज़ घटे + this.praarabdhaTimer = Math.max(0, this.praarabdhaTimer - dt); + const newPraarabdha = this.praarabdhaTimer > 0 + ? Math.ceil(this.praarabdhaTimer / PRARABDHA_BHOG_FRAMES) : 0; - if (newPrarabdha < prevPrarabdha) { - this.prarabdha = newPrarabdha; - if (this.prarabdha > 0) { + if (newPraarabdha < prevPraarabdha) { + this.praarabdha = newPraarabdha; + if (this.praarabdha > 0) { // ── unit घटा — explosion + alert (alert flooding नहीं, unit-change पर ही) ── this._createExplosion( this.player.x + this.player.width / 2, @@ -867,18 +867,18 @@ export class KarmaEngine { "#a78bfa" ); this._addFloatingText("-📜", "#a78bfa", { vy: -2.5, isBigName: true }); - this._alertKey('prarabdhaBhoga', '📜', 'info', { n: this.prarabdha }); + this._alertKey('praarabdhaBhoga', '📜', 'info', { n: this.praarabdha }); this._cb.playSound?.('bandhanaMukta'); } else { // ── पूर्ण मुक्ति ── - this.prarabdhaTimer = 0; + this.praarabdhaTimer = 0; this._createExplosion( this.player.x + this.player.width / 2, this.player.y + this.player.height / 2, "#e879f9" ); - this._addFloatingText(t('notify.prarabdhaMukta'), "#e879f9", { vy: -2.8, isBigName: true }); - this._alertKey('prarabdhaMukta', '📜', 'achievement'); + this._addFloatingText(t('notify.praarabdhaMukta'), "#e879f9", { vy: -2.8, isBigName: true }); + this._alertKey('praarabdhaMukta', '📜', 'achievement'); this._cb.playSound?.('bandhanaMukta'); this._triggerGlow("#e879f9"); } @@ -920,17 +920,17 @@ export class KarmaEngine { /** * शास्त्र overlay toggle। - * main.js से toggleShastra() में बुलाएँ। + * main.js से toggleShaashtra() में बुलाएँ। */ - toggleShastra() { + toggleShaashtra() { if (this._UI?.viraamaOverlay?.style.display === 'flex') { this._UI.viraamaOverlay.style.display = 'none'; } - this.isShastraVisible = !this.isShastraVisible; - if (this._UI?.shastraOverlay) { - this._UI.shastraOverlay.style.display = this.isShastraVisible ? 'flex' : 'none'; + this.isShaashtraVisible = !this.isShaashtraVisible; + if (this._UI?.shaashtraOverlay) { + this._UI.shaashtraOverlay.style.display = this.isShaashtraVisible ? 'flex' : 'none'; } - if (this.isShastraVisible) { + if (this.isShaashtraVisible) { this.wasAlreadyPaused = this.isPaused; this.isPaused = true; this._cb.playSound?.('viraama'); @@ -966,6 +966,8 @@ export class KarmaEngine { `${t('end.punarjanmaLabel')} ` + `${this.punaraJanmaCount}`; if (reason === "FORCE STOPPED") { + // प्रलय — पुनर्जन्म बटन दिखाएँ + if (this._UI?.punarjanmaBtn) this._UI.punarjanmaBtn.style.display = 'inline-block'; if (this._UI?.overlayTitle) { this._UI.overlayTitle.innerText = t('end.pralaya.title'); this._UI.overlayTitle.style.fontFamily = "'Noto Sans Devanagari', sans-serif"; @@ -980,11 +982,10 @@ export class KarmaEngine { COUNT_HTML + CREDIT; } } else if (this.won) { + // मोक्ष — पुनर्जन्म शास्त्र-विरुद्ध; बटन छिपाएँ + if (this._UI?.punarjanmaBtn) this._UI.punarjanmaBtn.style.display = 'none'; if (this._UI?.overlayTitle) { this._UI.overlayTitle.innerText = t('end.moksha.title'); - // ⚠️ BUG FIX: प्रलय शाखा fontFamily बदलती है, पर यह शाखा उसे - // कभी रीसेट नहीं करती थी — प्रलय के बाद मोक्ष देखने पर - // शीर्षक ग़लत font में रह जाता था। अब स्पष्ट रूप से सेट। this._UI.overlayTitle.style.fontFamily = "'Noto Sans Devanagari', sans-serif"; this._UI.overlayTitle.style.color = "#ffffff"; } @@ -1004,6 +1005,8 @@ export class KarmaEngine { } this._cb.playSound?.('vijaya'); } else { + // संसार-पुनर्जन्म — पुनर्जन्म बटन दिखाएँ + if (this._UI?.punarjanmaBtn) this._UI.punarjanmaBtn.style.display = 'inline-block'; if (this._UI?.overlayTitle) { this._UI.overlayTitle.innerText = t('end.rebirth.title'); this._UI.overlayTitle.style.fontFamily = "'Noto Sans Devanagari', sans-serif"; @@ -1021,12 +1024,12 @@ export class KarmaEngine { } /** - * punahaPrarambha (R-key / restart-btn) — सम्पूर्ण reset। + * punahaPraarambha (R-key / restart-btn) — सम्पूर्ण reset। */ reset() { // ── Karma reset ── - this.prarabdha = 0; this.prarabdhaTimer = 0; this.shuvhaKarma = 0; this.ashuvhaKarma = 0; - this.prarabdhaGatiModifier = 1.0; this._currentGatiModifier = 1.0; this.activeNaam = 0; this.samarpita = 0; this.punaraJanmaCount = 0; + this.praarabdha = 0; this.praarabdhaTimer = 0; this.shuvhaKarma = 0; this.ashuvhaKarma = 0; + this.praarabdhaGatiModifier = 1.0; this._currentGatiModifier = 1.0; this.activeNaam = 0; this.samarpita = 0; this.punaraJanmaCount = 0; this.isKarmaImmune = false; this.kripa = 0; this.shankha = 0; this.jyoti = 0; // ── Alert queue reset ── this.alertQueue = []; this._nextAlertId = 0; @@ -1037,19 +1040,19 @@ export class KarmaEngine { if (this._UI?.swaansaVal) this._UI.swaansaVal.innerText = `10`; // ── Spiritual state reset ── - this.chetanaaJaagrita = false; this.purnaSamarpana = false; + this.chetanaaJaagrita = false; this.poornaSamarpana = false; // ── Edge-detection flags reset ── - this._prevPurnaSamarpana = false; this._prevDrishtiClear = true; + this._prevPoornaSamarpana = false; this._prevDrishtiClear = true; this._prevGoodKarmaForSound = 0; this._prevBadKarmaForSound = 0; - this._prevPrarabdhaForSound = 0; + this._prevPraarabdhaForSound = 0; this._prevActiveNaamForKripa = 0; this._prevSamarpitaForKripa = 0; this._naamaSinceLastKripa = 0; this._samarpitaSinceLastKripa = 0; this._prevPulledHorseIndex = -1; this._mayaConsumedWhilePulling = false; // ── Timer flags reset ── this._timerSoundPlayed = false; this._timerTickAccumulator = 0; - this._lastPrarabdhaAlertSecond = -1; + this._lastPraarabdhaAlertSecond = -1; // ── Contextual alert flags reset (Issue #9) ── this._prevSamaya200 = false; @@ -1082,8 +1085,8 @@ export class KarmaEngine { this._cb.startSushuptiSwaansaLayer?.(); // ── HUD cache invalidate ── - this._oldStats = { purnaSamarpana:"", naama:-1, punya:-1, paap:-1, - prarabdha:-1, samarpita:-1, punaraJanma:-1, + this._oldStats = { poornaSamarpana:"", naama:-1, punya:-1, paap:-1, + praarabdha:-1, samarpita:-1, punaraJanma:-1, gatee:"-1", kripa:-1, chetana:"", shankha:-1, drishti:"", jyoti:-1 }; // ── UI reset ── @@ -1113,8 +1116,8 @@ export class KarmaEngine { shuvhaKarma: this.shuvhaKarma, ashuvhaKarma: this.ashuvhaKarma, activeNaam: this.activeNaam, - prarabdha: this.prarabdha, - prarabdhaTimer: this.prarabdhaTimer, + praarabdha: this.praarabdha, + praarabdhaTimer: this.praarabdhaTimer, samarpita: this.samarpita, punaraJanmaCount: this.punaraJanmaCount, kripa: this.kripa, @@ -1122,7 +1125,7 @@ export class KarmaEngine { jyoti: this.jyoti, // Spiritual chetanaaJaagrita: this.chetanaaJaagrita, - purnaSamarpana: this.purnaSamarpana, + poornaSamarpana: this.poornaSamarpana, // Time samaya: this.samaya, swaansa: this.swaansa, @@ -1132,7 +1135,7 @@ export class KarmaEngine { gameOver: this.gameOver, isPaused: this.isPaused, won: this.won, - isShastraVisible: this.isShastraVisible, + isShaashtraVisible: this.isShaashtraVisible, // Visual player: this.player, smoothSize: this.smoothSize, diff --git a/src/i18n.js b/src/i18n.js index 1286841..e43c53b 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -16,8 +16,8 @@ const STRINGS = { 'viraama.resume': 'जारी रखें', 'viraama.restart': 'पुनः आरंभ', 'viraama.quit': 'छोड़ें', - 'shastra.title': '॥ शास्त्र ॥', - 'shastra.subtitle':'रथ का ज्ञान', + 'shaashtra.title': '॥ शास्त्र ॥', + 'shaashtra.subtitle':'रथ का ज्ञान', 'tutorial.dismiss':'ENTER / TAP to continue', 'loading.text': 'रथ तैयार हो रहा है...', 'alert.samaya200.title': 'समय समाप्त होने वाला है', @@ -38,12 +38,12 @@ const STRINGS = { 'alert.chakravaataShankha.subtitle': 'Y दबाएँ — शंख-ध्वनि से नष्ट करें!', 'alert.chakravaataNone.subtitle': 'शंख संग्रह करें — अभी सुरक्षा नहीं।', 'alert.drishti.title': 'दृष्टि अवरुद्ध', - 'alert.drishtiJyoti.subtitle': 'B दबाएँ — ज्योति से अंधकार भगाएँ।', + 'alert.drishtiVisionb.subtitle': 'B दबाएँ — ज्योति से अंधकार भगाएँ।', 'alert.drishtiNone.subtitle': 'ज्योति संग्रह करें — पाप का अंधकार बढ़ा।', - 'alert.prarabdhaBhoga.title': 'एक प्रारब्ध भोग लिया', - 'alert.prarabdhaBhoga.subtitle': '{n} शेष।', - 'alert.prarabdhaMukta.title': 'प्रारब्ध से मुक्ति', - 'alert.prarabdhaMukta.subtitle': 'पूर्ण भोग संपन्न!', + 'alert.praarabdhaBhoga.title': 'एक प्रारब्ध भोग लिया', + 'alert.praarabdhaBhoga.subtitle': '{n} शेष।', + 'alert.praarabdhaMukta.title': 'प्रारब्ध से मुक्ति', + 'alert.praarabdhaMukta.subtitle': 'पूर्ण भोग संपन्न!', 'alert.gamepad.title': 'गेमपैड जुड़ा', 'alert.gamepad.subtitle': 'नियंत्रण सक्रिय।', 'alert.paused.title': 'खेल स्तम्भित', @@ -68,16 +68,16 @@ const STRINGS = { 'alert.errNaamaAbsent.subtitle': 'नाम जाप के लिए नाम की आवश्यकता है!', 'alert.errShankhaAbsent.title': 'शंख-शक्ति समाप्त', 'alert.errShankhaAbsent.subtitle': 'पहले शंख संग्रह करें।', - 'alert.errJyotiAbsent.title': 'ज्योति-शक्ति समाप्त', - 'alert.errJyotiAbsent.subtitle': 'पहले ज्योति संग्रह करें।', + 'alert.errVisionbAbsent.title': 'ज्योति-शक्ति समाप्त', + 'alert.errVisionbAbsent.subtitle': 'पहले ज्योति संग्रह करें।', 'alert.errSamarpanaPhase.title': 'समर्पण अस्वीकृत', 'alert.errSamarpanaPhase.subtitle': "नाम समर्पण केवल 'अंतिम चरण' में संभव है।", 'alert.errSamarpanaNoNaam.title': 'समर्पण अस्वीकृत', 'alert.errSamarpanaNoNaam.subtitle': 'समर्पण हेतु नाम शेष नहीं है।', 'alert.errSamarpanaTunnel.title': 'समर्पण अस्वीकृत', 'alert.errSamarpanaTunnel.subtitle': 'नाम समर्पण करने के लिए आपको भक्ति-मार्ग के अंदर होना चाहिए।', - 'alert.errPrarabdhaMax.title': 'प्रारब्ध सीमा', - 'alert.errPrarabdhaMax.subtitle': 'अधिकतम {n} — नया बोझ असंभव।', + 'alert.errPraarabdhaMax.title': 'प्रारब्ध सीमा', + 'alert.errPraarabdhaMax.subtitle': 'अधिकतम {n} — नया बोझ असंभव।', // ── पुनर्जन्म ── 'alert.punarjanmaApavitra.title': 'अपवित्र पुनर्जन्म', 'alert.punarjanmaApavitra.subtitle': 'कर्म असंतुलित रह गया, चक्र जारी है...', @@ -140,10 +140,10 @@ const STRINGS = { 'tutorial.tunnel.task': 'स्क्रीन के मध्य में चमकता भक्ति-मार्ग दिखेगा।\nउसमें प्रवेश करो।', 'tutorial.tunnel.hint': 'भक्ति-मार्ग में नाम-समर्पण (↑) संभव होता है।', - 'tutorial.prarabdha.credit': '— स्कन्द पुराण', - 'tutorial.prarabdha.meaning': '', - 'tutorial.prarabdha.task': 'प्रारब्ध भोगना ही पड़ता है — टाला नहीं जा सकता।\nमृत्यु पर प्रारब्ध +१ जुड़ता है। धैर्य रखो।\n\n"ENTER" दबाओ — यात्रा शुरू हो!', - 'tutorial.prarabdha.hint': 'पुण्य, नाम, और समर्पण से मोक्ष मिलता है।', + 'tutorial.praarabdha.credit': '— स्कन्द पुराण', + 'tutorial.praarabdha.meaning': '', + 'tutorial.praarabdha.task': 'प्रारब्ध भोगना ही पड़ता है — टाला नहीं जा सकता।\nमृत्यु पर प्रारब्ध +१ जुड़ता है। धैर्य रखो।\n\n"ENTER" दबाओ — यात्रा शुरू हो!', + 'tutorial.praarabdha.hint': 'पुण्य, नाम, और समर्पण से मोक्ष मिलता है।', // ── अंत-स्क्रीन (End screens) ── // ⚠️ केवल पाठ — CSS/styles code में रहते हैं, यहाँ कभी नहीं। @@ -174,16 +174,17 @@ const STRINGS = { // ── HUD canvas text ── 'hud.finalPhase': 'अंतिम चरण', 'hud.punyaTimerLabel': 'पुण्य +', - 'hud.prarabdhaTimerLabel': 'प्रारब्ध {n} शेष', + 'hud.praarabdhaTimerLabel': 'प्रारब्ध {n} शेष', // ── notify overlay ── - 'notify.prarabdhaMukta': '📜🔥 मुक्त!', + 'notify.praarabdhaMukta': '📜🔥 मुक्त!', // ── end screens ── 'end.punarjanmaLabel': 'पुनर्जन्म:', 'end.moksha.samayaLabel': 'मोक्ष 🌿', 'end.restartHint': "'R' दबाएं जीवन रथ को पुनः आरंभ करने के लिए", + 'end.punarjanmaBtn': '♻️ पुनर्जन्म', // ── शास्त्र-ग्रंथ (navigation) ── - 'shastra.next': 'अगला [ {page} / {total} ]', - 'shastra.prev': 'पिछला [ {page} / {total} ]', + 'shaashtra.next': 'अगला [ {page} / {total} ]', + 'shaashtra.prev': 'पिछला [ {page} / {total} ]', }, en: { 'start.title': 'MOKSHA', @@ -195,11 +196,11 @@ const STRINGS = { 'start.pageDescription': 'Moksha - Break free from the cycle of life and death.', 'start.tutorialButton': '🕉️ Get Guru-diksha', 'viraama.title': '॥ PAUSED ॥', - 'viraama.resume': 'Resume', - 'viraama.restart': 'Restart', - 'viraama.quit': 'Quit', - 'shastra.title': '॥ Shaastra ॥', - 'shastra.subtitle':'Knowledge of the Chariot', + 'viraama.resume': 'Keep Dreaming', + 'viraama.restart': 'New Dream', + 'viraama.quit': 'Wake Up', + 'shaashtra.title': '॥ Shaastra ॥', + 'shaashtra.subtitle':'Knowledge of the Chariot', 'tutorial.dismiss':'ENTER / TAP to continue', 'loading.text': 'Preparing the chariot...', 'alert.samaya200.title': 'Samaya (time) is running out', @@ -215,17 +216,17 @@ const STRINGS = { 'alert.samarpita.title': '{n} Samarpita!', 'alert.samarpita10.subtitle': 'First milestone — the path of surrender opens.', 'alert.samarpita25.subtitle': 'Well done! Keep acting without attachment.', - 'alert.samarpita50.subtitle': 'Remarkable! Moving toward complete Vairagya.', + 'alert.samarpita50.subtitle': 'Remarkable! Moving toward complete Vairaagya.', 'alert.chakravaata.title': 'Chakravata (storm) near', 'alert.chakravaataShankha.subtitle': 'Press Y — destroy it with the Shankha!', 'alert.chakravaataNone.subtitle': 'Gather a Shankha — you are unprotected.', 'alert.drishti.title': 'Vision obscured', - 'alert.drishtiJyoti.subtitle': 'Press B — dispel the dark with Jyoti.', - 'alert.drishtiNone.subtitle': 'Gather Jyoti — the dark of Papa is growing.', - 'alert.prarabdhaBhoga.title': 'One Prarabdha endured', - 'alert.prarabdhaBhoga.subtitle': '{n} remaining.', - 'alert.prarabdhaMukta.title': 'Freed from Prarabdha', - 'alert.prarabdhaMukta.subtitle': 'The enduring is complete!', + 'alert.drishtiVisionb.subtitle': 'Press B — dispel the dark with Visionb.', + 'alert.drishtiNone.subtitle': 'Gather Visionb — the dark of Papa is growing.', + 'alert.praarabdhaBhoga.title': 'One Praarabdha endured', + 'alert.praarabdhaBhoga.subtitle': '{n} remaining.', + 'alert.praarabdhaMukta.title': 'Freed from Praarabdha', + 'alert.praarabdhaMukta.subtitle': 'The enduring is complete!', 'alert.gamepad.title': 'Gamepad connected', 'alert.gamepad.subtitle': 'Controls active.', 'alert.paused.title': 'Game paused', @@ -238,38 +239,38 @@ const STRINGS = { 'alert.bandhanaPaapaMukta.subtitle': 'Inauspicious karma burnt — the soul is pure.', 'alert.bandhanaPaapaShesha.title': 'Papa-bondage', 'alert.bandhanaPaapaShesha.subtitle': '{n} remaining — 5 more Naama needed.', - 'alert.kripaSamarpita.title': 'Kripa (grace)', + 'alert.kripaSamarpita.title': 'Blessing (grace)', 'alert.kripaSamarpita.subtitle': 'All worldly Punya and Papa have been surrendered.', - 'alert.kripaSimple.title': 'Kripa received', + 'alert.kripaSimple.title': 'Blessing received', 'alert.kripaSimple.subtitle': '', - 'alert.shankhaPrapta.title': 'Shankha (conch) received', - 'alert.jyotiPrapta.title': 'Jyoti (lamp) received', + 'alert.shankhaPrapta.title': 'Conch received', + 'alert.jyotiPrapta.title': 'Vision received', 'alert.shankhaPrapta.subtitle': 'Keep it safe — it quells the Chakravata.', 'alert.jyotiPrapta.subtitle': 'Press B to spread light in the darkness.', 'alert.errNaamaAbsent.title': 'Cannot chant', 'alert.errNaamaAbsent.subtitle': 'Naama-Japa requires collected Naama!', 'alert.errShankhaAbsent.title': 'No Shankha left', 'alert.errShankhaAbsent.subtitle': 'Gather a Shankha first.', - 'alert.errJyotiAbsent.title': 'No Jyoti left', - 'alert.errJyotiAbsent.subtitle': 'Gather a Jyoti first.', + 'alert.errVisionbAbsent.title': 'No Visionb left', + 'alert.errVisionbAbsent.subtitle': 'Gather a Visionb first.', 'alert.errSamarpanaPhase.title': 'Samarpana refused', 'alert.errSamarpanaPhase.subtitle': 'Naama-Samarpana is possible only in the final phase.', 'alert.errSamarpanaNoNaam.title': 'Samarpana refused', 'alert.errSamarpanaNoNaam.subtitle': 'No Naama left to surrender.', 'alert.errSamarpanaTunnel.title': 'Samarpana refused', 'alert.errSamarpanaTunnel.subtitle': 'You must be inside the Bhakti path to surrender the Naama.', - 'alert.errPrarabdhaMax.title': 'Prarabdha limit', - 'alert.errPrarabdhaMax.subtitle': 'Maximum {n} — no further burden possible.', + 'alert.errPraarabdhaMax.title': 'Praarabdha limit', + 'alert.errPraarabdhaMax.subtitle': 'Maximum {n} — no further burden possible.', // ── Rebirth ── - 'alert.punarjanmaApavitra.title': 'Impure Punarjanma', + 'alert.punarjanmaApavitra.title': 'Impure Rebirth', 'alert.punarjanmaApavitra.subtitle': 'Karma remained unbalanced; the cycle continues...', - 'alert.punarjanmaPavitra.title': 'Pure Punarjanma', + 'alert.punarjanmaPavitra.title': 'Pure Rebirth', 'alert.punarjanmaPavitra.subtitle': 'Karma was pure, but the journey stayed unfinished.', - 'alert.punarjanmaNaya.title': 'Pure Punarjanma', + 'alert.punarjanmaNaya.title': 'Pure Rebirth', 'alert.punarjanmaNaya.subtitle': 'A new journey begins.', - 'alert.kripaAtirikta.title': 'Extra Kripa', - 'alert.kripaAtirikta.subtitle': 'Entering the new life carrying Kripa!', + 'alert.kripaAtirikta.title': 'Extra Blessing', + 'alert.kripaAtirikta.subtitle': 'Entering the new life carrying Blessing!', // ── Actions ── 'alert.naamaSumirana.title': 'Naama-Sumirana', @@ -282,15 +283,15 @@ const STRINGS = { 'alert.punyaPrapta.subtitle': "The charioteer's mind accepted good deeds.", 'alert.ashuvha.title': 'Papa strikes', 'alert.ashuvha.subtitle': 'The chariot was struck by inauspicious karma!', - 'alert.naamaSamarpita.title': 'Naama surrendered', + 'alert.naamaSamarpita.title': 'Poorna surrendered', 'alert.naamaSamarpita.subtitle': '+{n} received.', - 'alert.vairaagya.title': 'Vairagya (detachment)', + 'alert.vairaagya.title': 'Vairaagya (detachment)', 'alert.vairaagya.subtitle': 'The charioteer refused the lure of Punya.', 'alert.shankhaNaada.title': 'Shankha-nada', 'alert.shankhaNaada.subtitle': 'White light is spreading...', 'alert.shankhaChakra.title': 'Shankha-nada', 'alert.shankhaChakra.subtitle': 'The Chakravata was surrendered.', - 'alert.jyotiJali.title': 'Jyoti lit', + 'alert.jyotiJali.title': 'Visionb lit', 'alert.jyotiJali.subtitle': 'Light is spreading in the dark of Papa...', 'alert.brahmandaKshitija.title': 'Cosmic horizon', 'alert.brahmandaKshitija.subtitle': 'Time stands still — the moment of decision.', @@ -314,7 +315,7 @@ const STRINGS = { 'tutorial.maya.hint': 'Recognising Maya — that is the first step.', 'tutorial.jaapa.credit': '— Raamacharitmaanasa', - 'tutorial.jaapa.meaning': 'By chanting the Naama, auspiciousness arises in all ten directions.', + 'tutorial.jaapa.meaning': 'Naama brings auspiciousness in all ten directions.', 'tutorial.jaapa.task': 'Chant the Naama.\nKeyboard: SPACE | Gamepad: RT\n(works only when Naama has been collected)', 'tutorial.jaapa.hint': 'The Naama alone protects — chant it again and again.', @@ -323,13 +324,13 @@ const STRINGS = { 'tutorial.tunnel.task': 'A glowing Bhakti path appears in the middle of the screen.\nEnter it.', 'tutorial.tunnel.hint': 'Naama-Samarpana (↑) is possible within the Bhakti path.', - 'tutorial.prarabdha.credit': '— Skanda Purana', - 'tutorial.prarabdha.meaning': 'Papa wanes through enduring; impurity wanes through tapas.', - 'tutorial.prarabdha.task': 'Prarabdha must be endured — it cannot be avoided.\nOn death, Prarabdha increases by 1. Be patient.\n\nPress "ENTER" — let the journey begin!', - 'tutorial.prarabdha.hint': 'Moksha comes through Punya, Naama, and Samarpana.', + 'tutorial.praarabdha.credit': '— Skanda Purana', + 'tutorial.praarabdha.meaning': 'Papa wanes through enduring; impurity wanes through tapas.', + 'tutorial.praarabdha.task': 'Praarabdha must be endured — it cannot be avoided.\nOn death, Praarabdha increases by 1. Be patient.\n\nPress "ENTER" — let the journey begin!', + 'tutorial.praarabdha.hint': 'Moksha comes through Punya, Naama, and Samarpana.', // ── End screens ── - 'end.pralaya.title': '🛑 PRALAYA 🛑', + 'end.pralaya.title': '🛑 WOKE UP 🛑', 'end.pralaya.lead': 'Journey abandoned:', 'end.pralaya.line1': 'The charioteer let go of the chariot midway.', 'end.pralaya.stats': 'State of mind — Punya: {punya} | Papa: {paap}', @@ -342,7 +343,7 @@ const STRINGS = { 'end.moksha.heading': 'Beyond the gunas and beyond karma', 'end.moksha.line3': 'A rare realisation! The charioteer held the horses of the senses still, and freed the mind wholly from attachment.', - 'end.rebirth.title': 'Punarjanma in the world', + 'end.rebirth.title': 'Rebirth in the world', 'end.rebirth.lead': 'The reins of Moha (delusion):', 'end.rebirth.paap': 'Your ({n}) Papa blinded the charioteer.', 'end.rebirth.punya': 'The mind grew attached to your ({n}) Punya.', @@ -351,15 +352,16 @@ const STRINGS = { // ── HUD canvas text ── 'hud.finalPhase': 'Final Phase', 'hud.punyaTimerLabel': 'Punya +', - 'hud.prarabdhaTimerLabel': 'Prarabdha {n} remaining', + 'hud.praarabdhaTimerLabel': 'Praarabdha {n} remaining', // ── notify overlay ── - 'notify.prarabdhaMukta': '📜🔥 Freed!', + 'notify.praarabdhaMukta': '📜🔥 Freed!', // ── end screens ── 'end.punarjanmaLabel': 'Rebirths:', 'end.moksha.samayaLabel': 'Moksha 🌿', 'end.restartHint': "Press 'R' to restart the life chariot", - 'shastra.next': 'Next [ {page} / {total} ]', - 'shastra.prev': 'Back [ {page} / {total} ]', + 'end.punarjanmaBtn': '♻️ Punarjanma', + 'shaashtra.next': 'Next [ {page} / {total} ]', + 'shaashtra.prev': 'Back [ {page} / {total} ]', }, }; diff --git a/src/karma.js b/src/karma.js index 1abe11d..aadb577 100644 --- a/src/karma.js +++ b/src/karma.js @@ -42,7 +42,7 @@ export const KarmaMixin = { _syncOrbitCounts() { this.outerOrbits[0].count = this.shuvhaKarma; this.outerOrbits[1].count = this.ashuvhaKarma; - this.outerOrbits[2].count = this.prarabdha; + this.outerOrbits[2].count = this.praarabdha; this.outerOrbits[3].count = this.activeNaam; this.outerOrbits[4].count = this.kripa; this.outerOrbits[5].count = this.shankha; @@ -63,9 +63,9 @@ export const KarmaMixin = { this.shuvhaKarma === 0 && this.ashuvhaKarma === 0 && !this._pendingGoodKarma && - this.prarabdha === 0 && + this.praarabdha === 0 && this.chetanaaJaagrita && - this.purnaSamarpana + this.poornaSamarpana ) { if (this._UI?.samayaVal) this._UI.samayaVal.innerText = t('end.moksha.samayaLabel'); if (this._UI?.swaansaVal) this._UI.swaansaVal.innerText = `0`; if (!this.gameOver) { @@ -82,7 +82,7 @@ export const KarmaMixin = { this.activeNaam >= 20 || this.samarpita >= 30 || this.chetanaaJaagrita ); // ── Bug 5 fix: pendingGoodKarma clear करने से पहले capture करें ── - // पहले false किया → hasSanchitaKarma में already false → prarabdha +1 miss + // पहले false किया → hasSanchitaKarma में already false → praarabdha +1 miss const _hadPendingKarma = this._pendingGoodKarma; // ── pendingGoodKarma साफ करें — प्रारब्ध में count नहीं जोड़ेंगे ── @@ -98,24 +98,24 @@ export const KarmaMixin = { // एक जन्म का भार = एक प्रारब्ध। // _hadPendingKarma: captured value — clear होने से पहले का सच const hasSanchitaKarma = (this.shuvhaKarma > 0 || this.ashuvhaKarma > 0 || _hadPendingKarma); - const prevPrarabdha = this.prarabdha; + const prevPraarabdha = this.praarabdha; if (hasSanchitaKarma) { - this.prarabdha = Math.min(MAX_PRARABDHA, this.prarabdha + 1); + this.praarabdha = Math.min(MAX_PRARABDHA, this.praarabdha + 1); } - const actualAdded = this.prarabdha - prevPrarabdha; + const actualAdded = this.praarabdha - prevPraarabdha; if (actualAdded > 0) { - this.prarabdhaTimer += PRARABDHA_BHOG_FRAMES; // सदा 1× — +1 प्रारब्ध = 1 भोग-चक्र + this.praarabdhaTimer += PRARABDHA_BHOG_FRAMES; // सदा 1× — +1 प्रारब्ध = 1 भोग-चक्र this._addFloatingText(`+1 📜`, "#a78bfa"); } // cap hit होने पर player को सूचित करें if (hasSanchitaKarma && actualAdded === 0) { - this._alertKey('errPrarabdhaMax', '⚠️', 'warning', { n: MAX_PRARABDHA }); + this._alertKey('errPraarabdhaMax', '⚠️', 'warning', { n: MAX_PRARABDHA }); } - // पूर्व-जन्म का gati-भार prarabdha में store करें — multiply (हर जन्म का बोझ जुड़े) - this.prarabdhaGatiModifier *= this._currentGatiModifier; + // पूर्व-जन्म का gati-भार praarabdha में store करें — multiply (हर जन्म का बोझ जुड़े) + this.praarabdhaGatiModifier *= this._currentGatiModifier; // 0 तक न जाने दें — minimum gati 1% बनाए रखें - this.prarabdhaGatiModifier = Math.max(0.01, this.prarabdhaGatiModifier); + this.praarabdhaGatiModifier = Math.max(0.01, this.praarabdhaGatiModifier); this.ashuvhaKarma = 0; this.shuvhaKarma = 0; this.punaraJanmaCount++; this._triggerBlast("#f87171"); this.samaya = SAMAYA_PRAARAMBHIKA; @@ -133,7 +133,7 @@ export const KarmaMixin = { // चेतना जागृत है तो पुनर्जन्म पर भी कर्म-रक्षा बनी रहे this.isKarmaImmune = this.chetanaaJaagrita; - this.purnaSamarpana = false; + this.poornaSamarpana = false; if (isApavitra) { this._alertKey('punarjanmaApavitra', '♻️', 'warning'); @@ -468,7 +468,7 @@ export const KarmaMixin = { this.activeNaam = 0; this.shankha = 0; this.jyoti = 0; - this.purnaSamarpana = true; + this.poornaSamarpana = true; this.isKarmaImmune = true; this._addFloatingText(`+${gained} ॐ🙏`, "#ffff00", { alpha:1.5, vy:-2, isBigName:true, yOffset:-10 }); this._alertKey('naamaSamarpita', '🌿', 'achievement', { n: gained }); diff --git a/src/main.js b/src/main.js index cccef36..4cab04b 100644 --- a/src/main.js +++ b/src/main.js @@ -14,7 +14,7 @@ * • Event listeners (keyboard, gamepad, buttons, wheel) * • scaleGame() / debounce() * • Gamepad module (pollGamepad, vibrateGamepad, etc.) - * • Shastra navigation (toggleShastra, updateShastraPage) + * • Shaashtra navigation (toggleShaashtra, updateShaashtraPage) * • draw() — engine.getState() + Renderer calls * • gameLoop() — रा॒फ़ loop * • Start-screen poller @@ -26,7 +26,7 @@ import { Renderer } from './render.js'; import { KarmaEngine, SAMAYA_PRAARAMBHIKA } from './engine.js'; import Audio from './audio.js'; import { TutorialManager } from './tutorial.js'; -import { renderShastraPage } from './shastra.js'; +import { renderShaashtraPage } from './shaashtra.js'; import { TouchControls } from './touch.js'; const AM = Audio; // ====================== CANVAS SETUP ====================== @@ -50,14 +50,14 @@ const UI = { naama: document.getElementById('naama'), punya: document.getElementById('punya'), paap: document.getElementById('paap'), - prarabdha: document.getElementById('prarabdha'), + praarabdha: document.getElementById('praarabdha'), samarpita: document.getElementById('samarpita'), punaraJanma: document.getElementById('punaraJanma'), kripa: document.getElementById('kripa'), shankha: document.getElementById('shankha'), jyoti: document.getElementById('jyoti'), drishti: document.getElementById('drishti'), - purnaSamarpana: document.getElementById('purnaSamarpana'), + poornaSamarpana: document.getElementById('poornaSamarpana'), chetana: document.getElementById('chetana'), samayaVal: document.getElementById('ui-samaya-val'), swaansaVal: document.getElementById('ui-swaansa-val'), @@ -67,7 +67,8 @@ const UI = { overlayTitle: document.getElementById('overlay-title'), overlaySubtitle: document.getElementById('overlay-subtitle'), viraamaOverlay: document.getElementById('viraama-overlay'), - shastraOverlay: document.getElementById('shastra-overlay'), + shaashtraOverlay: document.getElementById('shaashtra-overlay'), + punarjanmaBtn: document.getElementById('punarjanma-btn'), }; // ====================== ENGINE INIT ====================== @@ -107,10 +108,10 @@ let isFontsReady = false; let isScaleGameDone = false; // ====================== SHASTRA STATE ====================== -let currentShastraPage = 1; +let currentShaashtraPage = 1; // 🛠️ key-repeat बिना continuous scroll (dpad-stick जैसी consistency) -let shastraKeyState = { up: false, down: false }; -const shastraBody = document.getElementById('shastra-body'); // one time cashe +let shaashtraKeyState = { up: false, down: false }; +const shaashtraBody = document.getElementById('shaashtra-body'); // one time cashe // ====================== GAMEPAD MODULE ====================== const GAMEPAD_DEADZONE = 0.18; @@ -154,14 +155,14 @@ function handleDiscreteButton(gp, buttonIndex, keyName) { } /** edge-triggered helper for any boolean condition */ -function handleShastraDirection(stateKey, isActiveNow, onRise) { +function handleShaashtraDirection(stateKey, isActiveNow, onRise) { const wasActive = !!gpButtonStates[stateKey]; if (isActiveNow && !wasActive) onRise(); gpButtonStates[stateKey] = isActiveNow; } /** शास्त्र-नेविगेशन (shared between pollGamepad + pollGamepadOnStartScreen) */ -function handleShastraGamepadNav(gp) { +function handleShaashtraGamepadNav(gp) { const stickX = gp.axes[0] || 0; const stickY = gp.axes[1] || 0; const dpadLeft = !!gp.buttons[GAMEPAD_BUTTON.DPAD_LEFT]?.pressed; @@ -172,14 +173,14 @@ function handleShastraGamepadNav(gp) { const left = (stickX < -GAMEPAD_DEADZONE) || dpadLeft; const right = (stickX > GAMEPAD_DEADZONE) || dpadRight; - handleShastraDirection('shastra_left', left, () => dispatchKey('keydown', 'ArrowLeft')); - handleShastraDirection('shastra_right', right, () => dispatchKey('keydown', 'ArrowRight')); - handleShastraDirection('shastra_dpad_up', dpadUp, () => dispatchKey('keydown', 'PageUp')); - handleShastraDirection('shastra_dpad_down', dpadDown,() => dispatchKey('keydown', 'PageDown')); + handleShaashtraDirection('shaashtra_left', left, () => dispatchKey('keydown', 'ArrowLeft')); + handleShaashtraDirection('shaashtra_right', right, () => dispatchKey('keydown', 'ArrowRight')); + handleShaashtraDirection('shaashtra_dpad_up', dpadUp, () => dispatchKey('keydown', 'PageUp')); + handleShaashtraDirection('shaashtra_dpad_down', dpadDown,() => dispatchKey('keydown', 'PageDown')); // Analog stick → smooth scroll (collision-free) if (stickY < -GAMEPAD_DEADZONE || stickY > GAMEPAD_DEADZONE) { - const body = document.getElementById('shastra-body'); + const body = document.getElementById('shaashtra-body'); if (body) body.scrollTop += stickY * 6 * 2; } } @@ -207,8 +208,8 @@ function pollGamepad() { } gpButtonStates['_tut_start'] = _tStartPressed; - if (engine.isShastraVisible) { - handleShastraGamepadNav(gp); + if (engine.isShaashtraVisible) { + handleShaashtraGamepadNav(gp); keys['arrowleft'] = false; keys['arrowright'] = false; } else { // Movement @@ -230,7 +231,7 @@ function pollGamepad() { // ====================== SHASTRA UI ====================== -function updateShastraPage() { +function updateShaashtraPage() { const lang = getLang(); const TOTAL = 3; @@ -238,62 +239,62 @@ function updateShastraPage() { // dataset.lang से जाँचते हैं कि यह page पहले से इसी भाषा में तो नहीं; // वरना हर nav-click पर व्यर्थ innerHTML लिखना पड़ता। for (let p = 1; p <= TOTAL; p++) { - const el = document.getElementById(`shastra-page-${p}`); + const el = document.getElementById(`shaashtra-page-${p}`); if (el && el.dataset.lang !== lang) { - el.innerHTML = renderShastraPage(p - 1, lang); // 0-based index + el.innerHTML = renderShaashtraPage(p - 1, lang); // 0-based index el.dataset.lang = lang; } } for (let p = 1; p <= 3; p++) { - document.getElementById(`shastra-page-${p}`)?.classList.remove('active'); + document.getElementById(`shaashtra-page-${p}`)?.classList.remove('active'); } - document.getElementById(`shastra-page-${currentShastraPage}`)?.classList.add('active'); - const navBtn = document.getElementById('shastra-nav-btn'); + document.getElementById(`shaashtra-page-${currentShaashtraPage}`)?.classList.add('active'); + const navBtn = document.getElementById('shaashtra-nav-btn'); if (navBtn) { - const key = currentShastraPage < TOTAL ? 'shastra.next' : 'shastra.prev'; - navBtn.textContent = t(key, { page: currentShastraPage, total: TOTAL }); + const key = currentShaashtraPage < TOTAL ? 'shaashtra.next' : 'shaashtra.prev'; + navBtn.textContent = t(key, { page: currentShaashtraPage, total: TOTAL }); } } /** * शास्त्र toggle — engine state + DOM overlay एक साथ update। - * (DRY: ESC key, shastra-help-btn, shastra-close-btn तीनों यही बुलाते हैं) + * (DRY: ESC key, shaashtra-help-btn, shaashtra-close-btn तीनों यही बुलाते हैं) */ -function toggleShastra() { - engine.toggleShastra(); // engine internal state update - if (engine.isShastraVisible) { - touch.block('shastra'); +function toggleShaashtra() { + engine.toggleShaashtra(); // engine internal state update + if (engine.isShaashtraVisible) { + touch.block('shaashtra'); // overlay DOM - currentShastraPage = 1; updateShastraPage(); + currentShaashtraPage = 1; updateShaashtraPage(); // keys reassign नहीं — TouchControls reference safe रहे Object.keys(keys).forEach(k => { keys[k] = false; }); touch.clearAll(); } else { - touch.unblock('shastra'); + touch.unblock('shaashtra'); Object.keys(keys).forEach(k => { keys[k] = false; }); touch.clearAll(); - // engine.toggleShastra() already restores pause state correctly. + // engine.toggleShaashtra() already restores pause state correctly. // Only reset lastTime when the game is actually unpaused. if (!engine.isPaused) { - lastTime = performance.now(); // Shastra में बिताया time → dt spike रोकें + lastTime = performance.now(); // Shaashtra में बिताया time → dt spike रोकें } } } // ====================== CONTINUOUS SHASTRA SCROLL ====================== // ArrowUp/Down को OS key-repeat पर निर्भर न रखकर — held-flag से smooth scroll -let _shastraScrollRafId = null; -function continuousShastraScrollLoop() { - if (engine.isShastraVisible) { - const body = document.getElementById('shastra-body'); +let _shaashtraScrollRafId = null; +function continuousShaashtraScrollLoop() { + if (engine.isShaashtraVisible) { + const body = document.getElementById('shaashtra-body'); if(body) { - if (shastraKeyState.up) body.scrollTop -= 6; - if (shastraKeyState.down) body.scrollTop += 6; + if (shaashtraKeyState.up) body.scrollTop -= 6; + if (shaashtraKeyState.down) body.scrollTop += 6; } } - _shastraScrollRafId = requestAnimationFrame(continuousShastraScrollLoop); + _shaashtraScrollRafId = requestAnimationFrame(continuousShaashtraScrollLoop); } -_shastraScrollRafId = requestAnimationFrame(continuousShastraScrollLoop); +_shaashtraScrollRafId = requestAnimationFrame(continuousShaashtraScrollLoop); // ====================== UTILITY ====================== function debounce(func, delay) { @@ -333,11 +334,11 @@ window.addEventListener('orientationchange', () => setTimeout(scaleGame, 300)); // ====================== EVENT LISTENERS ====================== -// ── Wheel (shastra scroll) ── +// ── Wheel (shaashtra scroll) ── window.addEventListener('wheel', (e) => { - if (!engine.isShastraVisible) return; + if (!engine.isShaashtraVisible) return; e.preventDefault(); - const body = document.getElementById('shastra-body'); + const body = document.getElementById('shaashtra-body'); if (body) body.scrollTop += e.deltaY; // direct — collision-free }, { passive: false }); @@ -345,7 +346,7 @@ window.addEventListener('wheel', (e) => { window.addEventListener('keydown', (e) => { const key = e.key.toLowerCase(); - if (!isGameStarted && key !== 'escape' && !engine.isShastraVisible) return; + if (!isGameStarted && key !== 'escape' && !engine.isShaashtraVisible) return; AM?.ensureAudio(); if (['arrowup','arrowdown','arrowleft','arrowright',' ','q','f','r','escape','enter','pageup','pagedown'].includes(key)) { @@ -356,17 +357,17 @@ window.addEventListener('keydown', (e) => { if (key === 'enter') { tutorial.dismiss(); return; } if (key === 'escape') { if (!tutorial.isDone()) { tutorial.skip(); return; } - toggleShastra(); return; + toggleShaashtra(); return; } - if (engine.isShastraVisible) { - const body = document.getElementById('shastra-body'); - if (key === 'arrowleft' && currentShastraPage > 1) { currentShastraPage--; updateShastraPage(); if (body) body.scrollTop = 0; } - if (key === 'arrowright' && currentShastraPage < 3) { currentShastraPage++; updateShastraPage(); if (body) body.scrollTop = 0; } - if (key === 'arrowup') shastraKeyState.up = true; - if (key === 'arrowdown') shastraKeyState.down = true; + if (engine.isShaashtraVisible) { + const body = document.getElementById('shaashtra-body'); + if (key === 'arrowleft' && currentShaashtraPage > 1) { currentShaashtraPage--; updateShaashtraPage(); if (body) body.scrollTop = 0; } + if (key === 'arrowright' && currentShaashtraPage < 3) { currentShaashtraPage++; updateShaashtraPage(); if (body) body.scrollTop = 0; } + if (key === 'arrowup') shaashtraKeyState.up = true; + if (key === 'arrowdown') shaashtraKeyState.down = true; if (key === 'pageup') { if (body) body.scrollTop -= body.clientHeight * 0.9; } if (key === 'pagedown') { if (body) body.scrollTop += body.clientHeight * 0.9; } return; @@ -396,8 +397,8 @@ window.addEventListener('keydown', (e) => { window.addEventListener('keyup', (e) => { const key = e.key.toLowerCase(); keys[key] = false; - if (key === 'arrowup') shastraKeyState.up = false; - if (key === 'arrowdown') shastraKeyState.down = false; + if (key === 'arrowup') shaashtraKeyState.up = false; + if (key === 'arrowdown') shaashtraKeyState.down = false; }); window.addEventListener('blur', () => { @@ -437,7 +438,7 @@ window.addEventListener('gamepaddisconnected', (e) => { document.addEventListener('visibilitychange', () => { if (document.hidden && isGameStarted && !engine.gameOver && !engine.won && - !engine.isPaused && !engine.isShastraVisible) { + !engine.isPaused && !engine.isShaashtraVisible) { engine.isPaused = true; if (UI.viraamaOverlay) UI.viraamaOverlay.style.display = 'flex'; AM?.playSound('viraama'); @@ -456,6 +457,10 @@ document.getElementById('restart-btn')?.addEventListener('click', () => { UI.viraamaOverlay.style.display = 'none'; engine.reset(); lastTime = performance.now(); }); +// ── पुनर्जन्म बटन (end screen) — प्रलय/पुनर्जन्म के बाद नया चक्र ── +document.getElementById('punarjanma-btn')?.addEventListener('click', () => { + engine.reset(); lastTime = performance.now(); +}); document.getElementById('quit-btn')?.addEventListener('click', () => { UI.viraamaOverlay.style.display = 'none'; engine.actionPralaya(); @@ -463,16 +468,16 @@ document.getElementById('quit-btn')?.addEventListener('click', () => { document.getElementById('music-toggle-btn')?.addEventListener('click', () => { AM?.ensureAudio(); AM?.toggleBgMusic(); }); -document.getElementById('shastra-help-btn')?.addEventListener('click', () => { - AM?.ensureAudio(); toggleShastra(); +document.getElementById('shaashtra-help-btn')?.addEventListener('click', () => { + AM?.ensureAudio(); toggleShaashtra(); }); -document.getElementById('shastra-close-btn')?.addEventListener('click', () => { - toggleShastra(); +document.getElementById('shaashtra-close-btn')?.addEventListener('click', () => { + toggleShaashtra(); }); -document.getElementById('shastra-nav-btn')?.addEventListener('click', () => { - currentShastraPage = currentShastraPage < 3 ? currentShastraPage + 1 : 1; - updateShastraPage(); - const body = document.getElementById('shastra-body'); +document.getElementById('shaashtra-nav-btn')?.addEventListener('click', () => { + currentShaashtraPage = currentShaashtraPage < 3 ? currentShaashtraPage + 1 : 1; + updateShaashtraPage(); + const body = document.getElementById('shaashtra-body'); if (body) body.scrollTop = 0; }); document.getElementById('music-volume-slider')?.addEventListener('input', (e) => { @@ -525,7 +530,7 @@ lastTime = performance.now(); function gameLoop(ts) { pollGamepad(); - if (!engine.isPaused && !engine.gameOver && !engine.won && !engine.isShastraVisible) { + if (!engine.isPaused && !engine.gameOver && !engine.won && !engine.isShaashtraVisible) { const rawDt = Math.min((ts - lastTime) / (1000 / 60), 2); // tutorial card visible होने पर slow-motion (dt × 0.3) const dt = tutorial.isSlowMode() ? rawDt * 0.3 : rawDt; @@ -592,9 +597,11 @@ function applyStartScreenLanguage() { metaDescription?.setAttribute('content', t('start.pageDescription')); hindiLabel?.classList.toggle('active', !isEnglish); englishLabel?.classList.toggle('active', isEnglish); - updateShastraPage(); // शास्त्र content भी language के अनुसार update करें - const restartHintEl = document.getElementById('restart-hint-text'); + updateShaashtraPage(); // शास्त्र content भी language के अनुसार update करें + const restartHintEl = document.getElementById('restart-hint-text'); if (restartHintEl) restartHintEl.textContent = t('end.restartHint'); + const punarjBtnEl = document.getElementById('punarjanma-btn'); + if (punarjBtnEl) punarjBtnEl.textContent = t('end.punarjanmaBtn'); // ── Pause (स्तम्भन) overlay — भाषा के अनुसार update ── const viraamaTitle = document.querySelector('.viraama-content h2'); @@ -606,11 +613,11 @@ function applyStartScreenLanguage() { if (restartBtnEl) restartBtnEl.textContent = t('viraama.restart'); if (quitBtn) quitBtn.textContent = t('viraama.quit'); - // ── Shastra overlay header — भाषा के अनुसार update ── - const shastraH2 = document.querySelector('#shastra-overlay .shastra-header h2'); - const shastraP = document.querySelector('#shastra-overlay .shastra-header p'); - if (shastraH2) shastraH2.textContent = t('shastra.title'); - if (shastraP) shastraP.textContent = t('shastra.subtitle'); + // ── Shaashtra overlay header — भाषा के अनुसार update ── + const shaashtraH2 = document.querySelector('#shaashtra-overlay .shaashtra-header h2'); + const shaashtraP = document.querySelector('#shaashtra-overlay .shaashtra-header p'); + if (shaashtraH2) shaashtraH2.textContent = t('shaashtra.title'); + if (shaashtraP) shaashtraP.textContent = t('shaashtra.subtitle'); // ── Loading overlay text — भाषा के अनुसार update ── const loadingText = document.getElementById('loading-overlay-text'); @@ -651,7 +658,7 @@ function pollGamepadOnStartScreen() { const startRise = startPressed && !startScreenGpState.start; startScreenGpState.start = startPressed; - if (startRise && !engine.isShastraVisible) { + if (startRise && !engine.isShaashtraVisible) { gpButtonStates[GAMEPAD_BUTTON.START] = true; startBtn?.click(); } @@ -662,7 +669,7 @@ function pollGamepadOnStartScreen() { startScreenGpState.back = backPressed; if (backRise) dispatchKey('keydown', 'Escape'); - if (engine.isShastraVisible) handleShastraGamepadNav(gp); + if (engine.isShaashtraVisible) handleShaashtraGamepadNav(gp); } requestAnimationFrame(pollGamepadOnStartScreen); @@ -707,7 +714,7 @@ AM?.setGameStateProvider?.(() => ({ gameOver: engine.gameOver, won: engine.won, isPaused: engine.isPaused, - isShastraVisible: engine.isShastraVisible, + isShaashtraVisible: engine.isShaashtraVisible, chetanaaJaagrita: engine.chetanaaJaagrita, })); // पुराना API compatibility @@ -716,7 +723,7 @@ AM?.setGameStateGetter?.(() => ({ gameOver: engine.gameOver, won: engine.won, isPaused: engine.isPaused, - isShastraVisible: engine.isShastraVisible, + isShaashtraVisible: engine.isShaashtraVisible, chetanaaJaagrita: engine.chetanaaJaagrita, })); AM?.setVibrateGamepad?.(vibrateGamepad); diff --git a/src/physics.js b/src/physics.js index 6125441..acdef3b 100644 --- a/src/physics.js +++ b/src/physics.js @@ -55,7 +55,7 @@ export const PhysicsMixin = { /** * सभी glow-rings निष्क्रिय/reset करें। - * punahaPrarambha (reset) में प्रयुक्त। + * punahaPraarambha (reset) में प्रयुक्त। */ _resetAllGlowRings() { for (let key in this.glowRings) { diff --git a/src/render.js b/src/render.js index 8d7f478..0942ae1 100644 --- a/src/render.js +++ b/src/render.js @@ -177,12 +177,12 @@ function drawKarmaChain(cx, baseY, color, strength = 1, isHeavy = false, frameNo ctx.save(); let swayPeriod = isHeavy ? 480 : 200; let pulse = Math.sin(frameNow / swayPeriod) * (isHeavy ? 7 : 5); - // prarabdha chain — orbits से visually अलग करने हेतु Y नीचे shift + // praarabdha chain — orbits से visually अलग करने हेतु Y नीचे shift let weightDropOffset = isHeavy ? (strength * 12) + 8 : 0; let y = baseY + pulse + weightDropOffset; let fontSize = isHeavy ? (32 + strength * 16) : (22 + strength * 14); - // prarabdha chain subtle opacity — orbit rings से distinguish हो + // praarabdha chain subtle opacity — orbit rings से distinguish हो ctx.globalAlpha = isHeavy ? 0.72 : 1.0; ctx.font = `${fontSize}px sans-serif`; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.shadowColor = color; ctx.shadowBlur = isHeavy ? (28 + strength * 22) : (25 + strength * 20); @@ -422,13 +422,13 @@ export const Renderer = { WIDTH, HEIGHT, TUNNEL_X, TUNNEL_WIDTH, SAMAYA_PRAARAMBHIKA, frameNow, shakeTimer, samaya, swaansaSamapta, stars, tunnelSparkles, particlePool, glowEffectPool, player, smoothSize, glowRings, - shuvhaKarma, ashuvhaKarma, prarabdha, activeNaam, kripa, shankha, jyoti, - samarpita, punaraJanmaCount, chetanaaJaagrita, purnaSamarpana, chainSlots, + shuvhaKarma, ashuvhaKarma, praarabdha, activeNaam, kripa, shankha, jyoti, + samarpita, punaraJanmaCount, chetanaaJaagrita, poornaSamarpana, chainSlots, finalHorsePositions, pulledHorseIndex, pulledHorseX, pulledHorseY, isPaused, gameOver, mayaPool, pendingGoodKarma, punyaTimer, pendingGoodKarmaCount, floatingTextPool, isNaamaJaapa, naamaGhera, outerOrbits, notifyTimer, notifyText, swaansaTimer, swaansa, - naamaGlowTimer, bodyGlowTimer, bodyGlowColor, prarabdhaTimer, + naamaGlowTimer, bodyGlowTimer, bodyGlowColor, praarabdhaTimer, alertQueue } = state; @@ -526,7 +526,7 @@ export const Renderer = { let activeChainCount = 0; if (shuvhaKarma > 0) { let s = chainSlots[activeChainCount++]; s.active = true; s.color = "#32ff32"; s.strength = Math.min(1, shuvhaKarma / 5); s.isHeavy = false; } if (ashuvhaKarma > 0) { let s = chainSlots[activeChainCount++]; s.active = true; s.color = "#ff3232"; s.strength = Math.min(1, ashuvhaKarma / 5); s.isHeavy = false; } - if (prarabdha > 0) { let s = chainSlots[activeChainCount++]; s.active = true; s.color = "#8b0000"; s.strength = Math.min(1, prarabdha / 10); s.isHeavy = true; } + if (praarabdha > 0) { let s = chainSlots[activeChainCount++]; s.active = true; s.color = "#8b0000"; s.strength = Math.min(1, praarabdha / 10); s.isHeavy = true; } for (let i = activeChainCount; i < chainSlots.length; i++) chainSlots[i].active = false; drawCenteredRow(cx, cy + 50, activeChainCount, CHAIN_GAP, (chainCx, chainCy, i) => { @@ -689,10 +689,10 @@ export const Renderer = { } ctx.textAlign = "left"; }); - // ── punyaTimer + prarabdhaTimer — player के ऊपर, side-by-side ── + // ── punyaTimer + praarabdhaTimer — player के ऊपर, side-by-side ── { const hasPunya = pendingGoodKarma && !gameOver; - const hasPrarabdha = prarabdhaTimer > 0 && prarabdha > 0 && !gameOver; + const hasPraarabdha = praarabdhaTimer > 0 && praarabdha > 0 && !gameOver; // player के ऊपर position — chains/maya से दूर const HALF_GAP = 52; @@ -700,7 +700,7 @@ export const Renderer = { const PILL_W = 96; const PILL_H = 48; const PILL_R = 10; if (hasPunya) { - const timerCx = hasPrarabdha ? cx - HALF_GAP : cx; + const timerCx = hasPraarabdha ? cx - HALF_GAP : cx; const secondsLeft = Math.ceil(punyaTimer / 60); const pulse = (Math.sin(frameNow / 150) + 1) / 2; ctx.save(); @@ -727,9 +727,9 @@ export const Renderer = { ctx.restore(); } - if (hasPrarabdha) { + if (hasPraarabdha) { const timerCx = hasPunya ? cx + HALF_GAP : cx; - const secLeft = Math.ceil(prarabdhaTimer / 60); + const secLeft = Math.ceil(praarabdhaTimer / 60); const pulse = (Math.sin(frameNow / 150) + 1) / 2; ctx.save(); // pill background @@ -744,7 +744,7 @@ export const Renderer = { ctx.font = "700 9px 'Orbitron', sans-serif"; ctx.fillStyle = "rgba(200, 180, 255, 0.85)"; ctx.shadowBlur = 0; - ctx.fillText(t('hud.prarabdhaTimerLabel', { n: prarabdha }), timerCx, baseY - 13); + ctx.fillText(t('hud.praarabdhaTimerLabel', { n: praarabdha }), timerCx, baseY - 13); // countdown ctx.font = "900 " + (20 + pulse * 3) + "px 'Orbitron', sans-serif"; ctx.fillStyle = "#ffffff"; @@ -1049,12 +1049,12 @@ export const Renderer = { let innerOrbit = [ chetanaaJaagrita ? "👁️" : "😴", ashuvhaKarma >= 3 ? "⚫" : "☀️", - purnaSamarpana ? "🙌" : "🤲" + poornaSamarpana ? "🙌" : "🤲" ]; if (punaraJanmaCount > 0) innerOrbit.push("♻️"); if (shuvhaKarma > 0) innerOrbit.push("🌿"); if (ashuvhaKarma > 0) innerOrbit.push("🥀"); - if (prarabdha > 0) innerOrbit.push("📜"); + if (praarabdha > 0) innerOrbit.push("📜"); if (activeNaam > 0) innerOrbit.push("ॐ"); if (kripa > 0) innerOrbit.push("✋"); if (shankha > 0) innerOrbit.push("🐚"); @@ -1084,7 +1084,7 @@ export const Renderer = { ctx.save(); let extraGlow = (orbit.glowTimer && orbit.glowTimer > 0) ? (orbit.glowTimer / 60) * 22 : 0; // 📜 प्रारब्ध orbit — भोग-timer सक्रिय होने पर subtle pulse glow - if (o === 2 && prarabdhaTimer > 0) { + if (o === 2 && praarabdhaTimer > 0) { extraGlow += (Math.sin(frameNow / 300) * 0.5 + 0.5) * 12; } // extraGlow cap — over-bright orbit clutter रोकें diff --git a/src/shastra.js b/src/shaashtra.js similarity index 90% rename from src/shastra.js rename to src/shaashtra.js index 3cb989e..5eed493 100644 --- a/src/shastra.js +++ b/src/shaashtra.js @@ -1,6 +1,6 @@ /** * ============================================================ - * src/shastra.js — मोक्ष शास्त्र-ग्रंथ (Wisdom Scroll) + * src/shaashtra.js — मोक्ष शास्त्र-ग्रंथ (Wisdom Scroll) * ============================================================ * * ESC / BACK पर खुलने वाला दार्शनिक विवेचन — 3 pages। @@ -36,20 +36,20 @@ export const SHASTRA_SHLOKAS = { en: 'The fire of knowledge reduces all karmas to ashes.', }, }, - kathaRatha: { + kathoRatha: { text: 'आत्मानं रथिनं विद्धि शरीरं रथमेव तु।\nबुद्धिं तु सारथिं विद्धि मनः प्रग्रहमेव च॥', - credit: { hi: 'कठोपनिषद् १.३.३', en: 'Katha Upanishad 1.3.3' }, + credit: { hi: 'कठोपनिषद् १.३.३', en: 'Katho Upanishad 1.3.3' }, meaning: { hi: '', en: 'Know the Atman as the rider, the body as the chariot; know the Buddhi as the charioteer, and the mind as the reins.', }, }, - prarabdha: { + praarabdha: { text: 'प्रारब्धं भुज्यते एव', credit: { hi: '', en: '' }, meaning: { hi: '', - en: 'Prarabdha must indeed be undergone.', + en: 'Praarabdha must indeed be undergone.', }, }, tamaso: { @@ -79,10 +79,10 @@ const PAGE_1 = { title: '🌀 Cosmology 🌀', blocks: [ { type: 'para', text: 'Your journey through time and space is guided by a divine chariot. The chariot is the symbol of the path a soul travels toward Moksha, crossing the karmic winds of Samsara.' }, - { type: 'para', text: 'Every act you perform — Punya or Papa — bears fruit as a distortion of time (gati). Both Punya and Papa slow the chariot; both are bondage. Papa strikes the chariot directly (tremor and clouded vision), while Punya leads the mind astray through alluring temptation.' }, + { type: 'para', text: 'Every act you perform — Punya or Paapa — bears fruit as a distortion of time (gati). Both Punya and Paapa slow the chariot; both are bondage. Paapa strikes the chariot directly (tremor and clouded vision), while Punya leads the mind astray through alluring temptation.' }, { type: 'term', label: '🌬️ Swaansa (breath)', text: 'The symbol of remaining lifespan — the count of breaths left in this cycle of life.' }, { type: 'term', label: '⚖️ Cosmic horizon — the moment of decision', text: 'When Samaya reaches zero, that is the moment of decision. If at that instant the soul is wholly free of karma, Chetana is awakened (Samarpita ≥ 50), and full Naama-Samarpana (⬆️ / W) has been offered — only then is Moksha attained. Otherwise, Punarjanma follows.' }, - { type: 'term', label: '👁️ Chetana-Jagriti — karmic immunity', text: 'When Chetana awakens, the karmic effect of Maya falls to zero. Karma no longer binds an awakened soul.' }, + { type: 'term', label: '👁️ Chetana-Jaagriti — karmic immunity', text: 'When Chetana awakens, the karmic effect of Maya falls to zero. Karma no longer binds an awakened soul.' }, { type: 'shloka', id: 'gita437' }, ], }, @@ -119,7 +119,7 @@ const PAGE_2 = { { type: 'term', label: 'ॐ नाम', text: 'मोक्ष प्राप्ति का सबसे बड़ा सहायक।' }, { type: 'term', label: '✋ कृपा', text: '२० नाम पर १ कृपा। कृपा बढ़ने से पाप-माया घटती है।' }, { type: 'term', label: '📜 प्रारब्ध', text: 'प्रत्येक पुनर्जन्म पर — चाहे संचित कर्म कितना भी हो — प्रारब्ध केवल +1 बढ़ता है। समय को ×1.15 तेज़ करता है। अधिकतम 15। १० नाम से भोग-गति २× होती है।' }, - { type: 'shloka', id: 'prarabdha' }, + { type: 'shloka', id: 'praarabdha' }, { type: 'term', label: '👁️ चेतना-जागृति', text: '५० समर्पित पूर्ण होने पर चेतना जागती है — कर्म-माया का प्रभाव शून्य होता है। मोक्ष-पथ की प्रामाणिक शर्त।' }, ], }, @@ -132,29 +132,29 @@ const PAGE_2 = { { type: 'term', label: '🪷 Vairagya : ⬇️ / X | S', text: 'Refuse the lure of Punya — let go of attachment.' }, { type: 'term', label: '🌊 Pralaya : LB/L1 | Q', text: 'Invoke dissolution — abandon the chariot willingly.' }, { type: 'term', label: '♻️ Pure Punarjanma : LT/L2 | R', text: 'A new life with the entire karmic load set to zero.' }, - { type: 'term', label: '📖 Shastra : BACK | ESC', text: 'The door to Brahma-jnana. Time stands still.' }, + { type: 'term', label: '📖 Shaashtra : BACK | ESC', text: 'The door to Brahma-jnana. Time stands still.' }, { type: 'term', label: '⏸️ Stambhana (pause) : START | F', text: 'Hold the cosmic flow for a moment.' }, { type: 'term', label: '🐚 Shankha (quells the storm) : Y | GAMEPAD Y', text: 'Destroy the Maya-Chakravaata with the sound of the conch.' }, { type: 'note', text: 'The Yantra path — for when Naama is unavailable.', color: '#7dd3fc' }, - { type: 'term', label: '🪔 Jyoti (light of sight) : B | GAMEPAD B', text: 'Regain vision in the darkness of Papa.' }, - { type: 'note', text: 'Vision is obscured once Papa ≥ 3.', color: '#ffe932' }, + { type: 'term', label: '🪔 Jyoti (light of sight) : B | GAMEPAD B', text: 'Regain vision in the darkness of Paapa.' }, + { type: 'note', text: 'Vision is obscured once Paapa ≥ 3.', color: '#ffe932' }, // ── Final phase ── { type: 'heading', text: '🏔️ The Final Phase 🏔️' }, { type: 'term', label: '🙏 Samarpita (50)', text: 'Chetana awakens — the path toward Moksha opens.' }, - { type: 'term', label: '🌌 The Bhakti path', text: '1 Naama → burns Punya | 5 Naama → burns Papa | 10 Naama → burns Prarabdha.' }, - { type: 'term', label: 'ॐ 🙌 Purna-Samarpana : ⬆️ | RB/R1 | W', text: 'Surrender completely while inside the Bhakti path.' }, + { type: 'term', label: '🌌 The Bhakti path', text: '1 Naama → burns Punya | 5 Naama → burns Paapa | 10 Naama → burns Praarabdha.' }, + { type: 'term', label: 'ॐ 🙌 Poorna-Samarpana : ⬆️ | RB/R1 | W', text: 'Surrender completely while inside the Bhakti path.' }, { type: 'note', text: '⚠️ Only during the final phase (Samaya < 100s).', color: '#ff3232' }, // ── Fruits of karma ── { type: 'heading', text: '⏳ Fruits of Karma ⏳' }, { type: 'term', label: '🌿 Punya', text: 'Good deeds — pleasant, yet bondage.' }, - { type: 'term', label: '🥀 Papa', text: 'Ill deeds — a strike, and clouded vision.' }, + { type: 'term', label: '🥀 Paapa', text: 'Ill deeds — a strike, and clouded vision.' }, { type: 'term', label: 'ॐ Naama', text: 'The greatest aid in attaining Moksha.' }, - { type: 'term', label: '✋ Kripa', text: '1 Kripa for every 20 Naama. As Kripa grows, the Maya of Papa wanes.' }, - { type: 'term', label: '📜 Prarabdha', text: 'At every rebirth — however great the accumulated karma — Prarabdha rises by only +1. It hastens Samaya by ×1.15. Maximum 15. With 10 Naama the rate of enduring doubles.' }, - { type: 'shloka', id: 'prarabdha' }, - { type: 'term', label: '👁️ Chetana-Jagriti', text: 'On completing 50 Samarpita, Chetana awakens — the effect of karmic Maya falls to zero. The authentic condition of the path to Moksha.' }, + { type: 'term', label: '✋ Kripa', text: '1 Kripa for every 20 Naama. As Kripa grows, the Maya of Paapa wanes.' }, + { type: 'term', label: '📜 Praarabdha', text: 'At every rebirth — however great the accumulated karma — Praarabdha rises by only +1. It hastens Samaya by ×1.15. Maximum 15. With 10 Naama the rate of enduring doubles.' }, + { type: 'shloka', id: 'praarabdha' }, + { type: 'term', label: '👁️ Chetana-Jaagriti', text: 'On completing 50 Samarpita, Chetana awakens — the effect of karmic Maya falls to zero. The authentic condition of the path to Moksha.' }, ], }, }; @@ -163,7 +163,7 @@ const PAGE_3 = { hi: { title: '👁️ प्रतीकवाद 👁️', blocks: [ - { type: 'shloka', id: 'kathaRatha' }, + { type: 'shloka', id: 'kathoRatha' }, { type: 'term', label: '🐎 छह घोड़े (छह इंद्रियाँ)', text: 'स्वचालित रूप से सांसारिक वस्तुओं की ओर खींचते हैं।' }, { type: 'term', label: '🪢 लगाम (मन)', text: 'षडिन्द्रिय संतुलन की ओर यात्रा करता सूक्ष्म तत्त्व।' }, { type: 'term', label: '☸️ रथ (शरीर)', text: 'आत्मा को ले जाने वाला स्थूल रूप।' }, @@ -179,16 +179,16 @@ const PAGE_3 = { en: { title: '👁️ Symbolism 👁️', blocks: [ - { type: 'shloka', id: 'kathaRatha' }, + { type: 'shloka', id: 'kathoRatha' }, { type: 'term', label: '🐎 Six horses (the six senses)', text: 'They pull of their own accord toward worldly objects.' }, { type: 'term', label: '🪢 Reins (the mind)', text: 'The subtle element travelling toward balance among the six senses.' }, { type: 'term', label: '☸️ Chariot (the body)', text: 'The gross form that carries the soul.' }, { type: 'term', label: '🪈 Charioteer (Buddhi)', text: 'The active charioteer holding the reins of the senses.' }, { type: 'term', label: '🪔 Passenger (Atman)', text: 'The divine conscious energy seated in the causal body.' }, - { type: 'term', label: 'ॐ Naama (self-remembrance)', text: 'The pure energy that burns Prarabdha to ash.' }, + { type: 'term', label: 'ॐ Naama (self-remembrance)', text: 'The pure energy that burns Praarabdha to ash.' }, { type: 'term', label: '🌬️ Swaansa (remaining lifespan)', text: 'Every breath carries you nearer the last.' }, { type: 'term', label: '🐚 Shankha (the Yantra path)', text: 'When Naama-Japa is not possible, the sound of the conch pierces the Maya-Chakravaata — the delusion of the world destroyed by the power of Yantra.' }, - { type: 'term', label: '🪔 Jyoti (the path of light)', text: 'In the darkness of Papa, Jyoti restores sight.' }, + { type: 'term', label: '🪔 Jyoti (the path of light)', text: 'In the darkness of Paapa, Jyoti restores sight.' }, { type: 'shloka', id: 'tamaso' }, ], }, @@ -210,13 +210,13 @@ function escapeHtml(s) { } /** - * renderShastraPage — एक page का HTML बनाएँ। + * renderShaashtraPage — एक page का HTML बनाएँ। * * @param {number} pageIndex — 0-based * @param {string} lang — 'hi' | 'en' * @returns {string} — HTML string */ -export function renderShastraPage(pageIndex, lang) { +export function renderShaashtraPage(pageIndex, lang) { const page = SHASTRA_PAGES[pageIndex]?.[lang] ?? SHASTRA_PAGES[pageIndex]?.hi; // fallback if (!page) return ''; diff --git a/src/state.js b/src/state.js index e91569e..262cc76 100644 --- a/src/state.js +++ b/src/state.js @@ -130,16 +130,16 @@ export const StateMixin = { this._updateStatWithPulse(this._UI.paap, 'paap', this.ashuvhaKarma, '🥀'); - // 📜 prarabdha — bhog-timer active होने पर live countdown दिखे - if (this._UI?.prarabdha) { - const bhogSec = this.prarabdhaTimer > 0 - ? ` ⏱${Math.ceil(this.prarabdhaTimer / 60)}s` : ''; - const newDisplay = `📜 ${this.prarabdha}${bhogSec}`; - if (this._UI.prarabdha.textContent !== newDisplay) { - this._UI.prarabdha.textContent = newDisplay; - this._uiScales.prarabdha = 1.15; - this._uiGlows.prarabdha = 1.0; - this._oldStats.prarabdha = this.prarabdha; + // 📜 praarabdha — bhog-timer active होने पर live countdown दिखे + if (this._UI?.praarabdha) { + const bhogSec = this.praarabdhaTimer > 0 + ? ` ⏱${Math.ceil(this.praarabdhaTimer / 60)}s` : ''; + const newDisplay = `📜 ${this.praarabdha}${bhogSec}`; + if (this._UI.praarabdha.textContent !== newDisplay) { + this._UI.praarabdha.textContent = newDisplay; + this._uiScales.praarabdha = 1.15; + this._uiGlows.praarabdha = 1.0; + this._oldStats.praarabdha = this.praarabdha; } } @@ -154,14 +154,14 @@ export const StateMixin = { this.chetanaaJaagrita ? "👁️" : "😴", ""); this._updateStatWithPulse(this._UI.drishti, 'drishti', this.ashuvhaKarma >= 3 ? "⚫" : "☀️", ""); - this._updateStatWithPulse(this._UI.purnaSamarpana, 'purnaSamarpana', - this.purnaSamarpana ? "🙌" : "🤲", ""); + this._updateStatWithPulse(this._UI.poornaSamarpana, 'poornaSamarpana', + this.poornaSamarpana ? "🙌" : "🤲", ""); }, /** HUD scale/glow animation एक frame advance करें */ _updateHUDAnimations(dt) { const uiKeys = [ - 'purnaSamarpana', 'naama', 'punya', 'paap', 'prarabdha', + 'poornaSamarpana', 'naama', 'punya', 'paap', 'praarabdha', 'samarpita', 'punaraJanma', 'gatee', 'chetana', 'shankha', 'drishti', 'jyoti', 'kripa', ]; diff --git a/src/touch.js b/src/touch.js index ea8d6d6..86e563c 100644 --- a/src/touch.js +++ b/src/touch.js @@ -118,7 +118,7 @@ export class TouchControls { */ /** * किसी कारण से controls block करें (hide)। - * @param {string} reason — 'start' | 'tutorial' | 'shastra' | 'viraama' | 'end' + * @param {string} reason — 'start' | 'tutorial' | 'shaashtra' | 'viraama' | 'end' */ block(reason) { if (!this._active) return; diff --git a/src/tutorial.js b/src/tutorial.js index a0c5abf..fac8593 100644 --- a/src/tutorial.js +++ b/src/tutorial.js @@ -18,7 +18,7 @@ * 1: maya — naama माया पहचानो * 2: jaapa — नाम-जाप करो (ENTER) * 3: tunnel — भक्ति-मार्ग में जाओ - * 4: prarabdha — प्रारब्ध ज्ञान (info card, dismiss = complete) + * 4: praarabdha — प्रारब्ध ज्ञान (info card, dismiss = complete) * * ── main.js में उपयोग ──────────────────────────────────────── * import { TutorialManager } from './tutorial.js'; @@ -77,7 +77,7 @@ const TUTORIAL_STEPS = [ dismissToComplete: false, }, { - id: 'prarabdha', + id: 'praarabdha', shloka: 'भोगेन क्षीयते पापं, तपसा क्षीयते मलः।', forceSpawn: null, dismissToComplete: true, // dismiss = tutorial complete @@ -233,7 +233,7 @@ export class TutorialManager { break; } - case 'prarabdha': + case 'praarabdha': // dismiss-only step — checkCompletion यहाँ कभी नहीं चलता // (_cardVisible = true रहेगा dismiss तक) break; diff --git a/style.css b/style.css index 8b32283..415a06e 100644 --- a/style.css +++ b/style.css @@ -251,7 +251,7 @@ button.hud-icon-btn:hover { #naama { color: #ffffff; } /* ॐ नाम — शुद्ध श्वेत */ #punya { color: #32ff80; } /* 🌿 पुण्य — दिव्य हरा */ #paap { color: #ff2244; } /* 🥀 पाप — रक्त-वर्ण */ -#prarabdha { color: #a78bfa; } /* 📜 प्रारब्ध — नील-बैंगनी */ +#praarabdha { color: #a78bfa; } /* 📜 प्रारब्ध — नील-बैंगनी */ #samarpita { color: #fb923c; } /* 🙏 समर्पित — नारंगी */ #punaraJanma { color: #f87171; } /* ♻️ जन्म — गुलाबी-लाल */ #kripa { color: #ffe9a8; } /* ✋ कृपा — सोनारंग */ @@ -259,7 +259,7 @@ button.hud-icon-btn:hover { #jyoti { color: #ffe932; } /* 🪔 ज्योति — सुवर्ण-पीत */ #chetana { color: #2dd4bf; } /* 👁️ चेतना — वैदूर्य-हरा */ #drishti { color: #facc15; } /* ☀️ दृष्टि — तेज-पीत */ -#purnaSamarpana { color: #e879f9; } /* 🙌 पूर्ण — दिव्य-नील */ +#poornaSamarpana { color: #e879f9; } /* 🙌 पूर्ण — दिव्य-नील */ /* ====================== PAUSE (VIRAAMA) OVERLAY ====================== */ #viraama-overlay { @@ -315,7 +315,7 @@ button.hud-icon-btn:hover { } /* ====================== SHASTRA OVERLAY ====================== */ -#shastra-overlay { +#shaashtra-overlay { position: absolute; top: 0; left: 0; @@ -332,7 +332,7 @@ button.hud-icon-btn:hover { /* z-index:20 था → start-screen (z-index:50) के पीछे छुप जाता था — अब सभी overlays से ऊँचा */ } -.shastra-content { +.shaashtra-content { position: relative; width: 100%; height: 100%; @@ -352,7 +352,7 @@ button.hud-icon-btn:hover { } /* शास्त्र बंद करने का स्पष्ट बटन */ -#shastra-close-btn { +#shaashtra-close-btn { position: absolute; top: 14px; right: 16px; @@ -370,18 +370,18 @@ button.hud-icon-btn:hover { z-index: 1; } -#shastra-close-btn:hover { +#shaashtra-close-btn:hover { background: rgba(255, 120, 30, 0.28); box-shadow: 0 0 12px rgba(255, 120, 30, 0.5); } -.shastra-header { +.shaashtra-header { border-bottom: 1px solid rgba(255, 136, 0, 0.3); padding-bottom: 10px; margin-bottom: 15px; } -.shastra-header h2 { +.shaashtra-header h2 { font-family: 'Orbitron', sans-serif; font-size: 32px; margin: 0; @@ -389,13 +389,13 @@ button.hud-icon-btn:hover { text-shadow: 0 0 10px rgba(255, 215, 0, 0.7); } -.shastra-header p { +.shaashtra-header p { margin: 5px 0 0 0; color: #ccc; font-style: italic; } -.shastra-body { +.shaashtra-body { flex: 1; overflow-y: auto; padding: 10px 20px; @@ -409,20 +409,20 @@ button.hud-icon-btn:hover { scrollbar-width: none; } -.shastra-body::-webkit-scrollbar { +.shaashtra-body::-webkit-scrollbar { display: none; } -.shastra-page { +.shaashtra-page { display: none; animation: fadeIn 0.4s ease-in-out; } -.shastra-page.active { +.shaashtra-page.active { display: block; } -.shastra-page h3 { +.shaashtra-page h3 { font-family: 'Orbitron', sans-serif; color: #ffa600; border-bottom: 1px solid rgba(255, 255, 255, 0.1); @@ -430,11 +430,11 @@ button.hud-icon-btn:hover { margin-bottom: 15px; } -.shastra-page p strong { +.shaashtra-page p strong { color: #ffa600; } -.shastra-footer { +.shaashtra-footer { display: flex; justify-content: space-between; align-items: center; @@ -442,7 +442,7 @@ button.hud-icon-btn:hover { border-top: 1px solid rgba(255, 136, 0, 0.3); } -.shastra-footer button { +.shaashtra-footer button { background: rgba(255, 136, 0, 0.15); color: #ffa600; font-family: 'Orbitron', sans-serif; @@ -456,7 +456,7 @@ button.hud-icon-btn:hover { text-align: center; } -.shastra-footer button:hover { +.shaashtra-footer button:hover { background: rgba(255, 120, 30, 0.25); filter: drop-shadow(0 0 8px rgba(255, 120, 30, 0.6)); }