mintikaryu 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +56 -0
- package/colorUtils.js +8 -0
- package/dragon.js +12 -0
- package/dragon.txt +36 -0
- package/fire.js +112 -0
- package/index.js +103 -0
- package/package.json +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2026 Aayush Anand
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 🐉 Mintikaryū - The Ancient Summoning
|
|
2
|
+
|
|
3
|
+
*A sacred CLI tool to summon the ancient dragon Mintikaryū (みんてぃかりゅう) from the deepest realms of the terminal.*
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
> *"When the digital abyss burns with the fires of ancient times, Mintikaryū shall rise to reclaim its hollow domain."*
|
|
8
|
+
|
|
9
|
+
## 📜 The Sacred Grimoire (Features)
|
|
10
|
+
|
|
11
|
+
- **The Flames of Genesis**: A dynamic, physics-based inferno simulation forged in pure ASCII, representing the primordial energies of creation.
|
|
12
|
+
- **The Gracious Ascension**: Watch in awe as Mintikaryū majestically ascends from the bottomless depths of your screen to assert absolute dominion over your terminal.
|
|
13
|
+
- **Arcane Adaptability**: The ritual seamlessly adapts to the shifting dimensions of your terminal window, preserving the ancient aesthetic undisturbed.
|
|
14
|
+
- **True Emerald Auras**: Ensorcelled with raw, true-color ANSI incantations to bathe your screen in the authentic, vibrant glow of the dragon's mythic scales.
|
|
15
|
+
|
|
16
|
+
## 🕯️ Reagents for the Ritual (Prerequisites)
|
|
17
|
+
|
|
18
|
+
- **Node.js**: The sacred runtime. Ensure you have a modern version supporting ESM modules (Node 12.20.0 or higher).
|
|
19
|
+
|
|
20
|
+
## 🔮 Forging the Pact (Installation)
|
|
21
|
+
|
|
22
|
+
To embed the `summon-dragon` incantation into your system so it may be cast anywhere within your digital kingdom, you must bind its essence globally.
|
|
23
|
+
|
|
24
|
+
Trace these arcane coordinates within the project's sanctum (root directory):
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install
|
|
28
|
+
npm link
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Once the pact is woven, you may call upon the ancient beast simply by chanting in your terminal:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
summon-dragon
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### The Solitary Invocation (Running Locally)
|
|
38
|
+
|
|
39
|
+
Should you wish to cast the spell solely within the confines of its origin folder, without forging a global pact:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install
|
|
43
|
+
node index.js
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## ⚔️ Banishing the Beast (Controls)
|
|
47
|
+
|
|
48
|
+
A dragon's presence commands heavy tolls upon the mortal realm. To banish Mintikaryū back to its slumber, sever the connection by invoking the celestial banishment sigil:
|
|
49
|
+
|
|
50
|
+
Press `CTRL + C`
|
|
51
|
+
|
|
52
|
+
## ⚒️ The Arcane Foundation
|
|
53
|
+
|
|
54
|
+
- **Node.js Subsystems**: Tapping into the raw, fundamental energies of the operating system.
|
|
55
|
+
- `cli-cursor`: Master of illusions, concealing the cursor to perfect the summoning circle.
|
|
56
|
+
- `"type": "module"`: Strict adherence to the ancient laws of modern ECMAScript.
|
package/colorUtils.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function colorize(hex, text) {
|
|
2
|
+
if (!hex) return text;
|
|
3
|
+
const hashLess = hex.startsWith('#') ? hex.slice(1) : hex;
|
|
4
|
+
const r = parseInt(hashLess.slice(0, 2), 16);
|
|
5
|
+
const g = parseInt(hashLess.slice(2, 4), 16);
|
|
6
|
+
const b = parseInt(hashLess.slice(4, 6), 16);
|
|
7
|
+
return `\x1b[38;2;${r};${g};${b}m${text}\x1b[39m`;
|
|
8
|
+
}
|
package/dragon.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const dragonArt = fs.readFileSync(join(__dirname, 'dragon.txt'), 'utf8');
|
|
9
|
+
export const dragonLines = dragonArt.split('\n');
|
|
10
|
+
|
|
11
|
+
export const dragonWidth = Math.max(...dragonLines.map(l => l.length));
|
|
12
|
+
export const dragonHeight = dragonLines.length;
|
package/dragon.txt
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⠆⠀⠀⢠⡞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
2
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡾⡇⠀⠀⠀⡿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⠟⣶⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
3
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠹⣆⠀⢠⠃⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡏⡏⠀⠘⡼⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
4
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⣦⡈⠓⢾⠀⣧⡀⠀⠀⠀⠀⠀⣤⣤⣴⣶⣦⢤⣄⡀⠀⠀⢸⠀⣧⠀⠀⢧⠘⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
5
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣦⣼⠀⡿⡏⠙⠲⠤⣀⡀⠀⠈⠙⣆⠈⠓⣄⠙⢢⡀⠈⣆⠘⢇⠀⠸⡇⠘⣆⠀⠀⠀⠀⠀⠀⠀⠀
|
|
6
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢻⠀⢸⣹⡀⠠⣀⠀⠉⠙⠲⢄⡈⣆⠀⠈⢣⡀⢱⣄⣸⢦⣤⣑⢄⡇⠀⠸⡆⠀⠀⠀⠀⠀⠀⠀
|
|
7
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠘⣇⢻⣶⣌⠙⢦⡀⠀⠀⠉⠺⢦⠀⠨⡇⠀⠙⣶⣉⣴⠛⠻⠱⣄⠀⢱⠀⠀⠀⠀⠀⠀⠀
|
|
8
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣖⣉⣇⠀⠸⡄⠹⣌⠳⣦⡙⢶⣄⠀⠀⠀⠙⢆⣟⠀⡸⠫⢿⡜⣆⠀⠀⠘⢆⠈⡆⠀⠀⠀⠀⠀⠀
|
|
9
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⠽⣿⠀⠀⠹⡄⠈⢧⡈⠻⣆⠙⣧⣀⠀⠀⠀⠹⣄⡀⠀⡜⠳⣘⡄⠀⠀⠘⣇⡇⠀⠀⠀⠀⠀⠀
|
|
10
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⣿⣛⠛⠛⠿⣦⡀⠀⠙⢤⠀⠱⣦⢽⣧⡈⢻⡇⠀⠀⢀⣹⣏⣼⡁⠀⢙⣧⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀
|
|
11
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢈⡇⠀⠀⢳⡳⣀⠀⠀⢳⡄⠈⢷⣌⣷⣠⡿⣿⣫⣿⣾⣿⣄⠀⡴⠋⠙⠳⣶⣶⢬⣿⠀⠀⠀⠀⠀⠀
|
|
12
|
+
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣤⣴⣯⣤⣤⣤⣤⣷⡈⢷⣦⡀⠙⢦⠀⣈⠛⢿⣾⣿⠋⢁⠔⠚⠻⢟⠣⠀⠔⠉⠙⢮⣙⣿⠀⠀⠀⠀⠀⠀
|
|
13
|
+
⠀⠀⠀⠀⠀⠀⣠⣾⠿⢭⡉⠀⠀⠀⠈⠉⠙⠛⣿⣦⡉⢿⣦⣌⢣⡈⢷⡀⡼⢿⡄⠈⠀⡠⠒⠚⠳⢄⠀⢀⠖⠙⢿⣿⠀⠀⠀⠀⠀⠀
|
|
14
|
+
⠀⠀⠀⠀⠀⠘⠁⠀⠀⣠⣇⣠⣤⣤⣤⣤⡴⠚⢉⣿⣿⣦⡈⠙⣷⣽⣄⣿⠃⠀⠙⢷⣼⡁⠀⡀⠐⠒⠯⣉⠀⢠⠴⣿⣆⠀⠀⠀⠀⠀
|
|
15
|
+
⠀⠀⠀⠀⠀⠀⣠⣴⡿⠛⠋⠉⠁⠉⢹⠟⠀⠀⠀⣠⣽⣿⣷⡀⠸⠿⢿⡇⠀⠀⠀⠀⢹⣷⣦⣇⠀⢀⠘⠙⠛⡇⠀⠸⣿⣿⡀⠀⠀⠀
|
|
16
|
+
⠀⠀⠀⠀⢀⣼⣯⣅⠀⠀⠀⠀⣀⡴⠋⠀⠐⠒⠉⠉⠉⠛⣿⣷⣄⡀⢸⣧⠀⠀⠀⠀⠀⢻⣿⣿⣿⣾⠀⠀⠀⠀⡄⠀⡇⠈⣧⠀⠀⠀
|
|
17
|
+
⠀⠀⠀⢀⠟⠁⠀⣸⣠⡴⠾⢿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠨⢟⣛⣿⡟⠉⢳⣄⠀⠀⠀⠀⢻⡈⠉⠻⣷⣀⠀⠀⢸⣼⣇⣧⡿⠀⠀⠀
|
|
18
|
+
⠀⠀⠀⠀⢀⡴⠞⠋⠀⠀⢠⠞⠀⠀⠀⠀⢀⣠⠤⢔⣾⣿⠿⠛⢿⢹⠁⠀⠀⠙⢷⡄⠀⠀⠀⠙⠻⣿⣿⡟⣟⠛⠁⣿⠀⣿⠁⠀⠀⠀
|
|
19
|
+
⠀⠀⠀⣰⠟⠁⠀⠀⢀⣠⠏⠀⠀⠀⣠⠖⠋⣠⣾⡟⠛⣧⠀⠀⠘⢿⡄⠀⠀⠀⠀⠳⠀⠀⠀⠀⠀⠈⢿⣇⠹⠀⠀⢸⡀⣿⠀⠀⠀⠀
|
|
20
|
+
⠀⠀⢰⣏⣄⠀⣠⣶⢿⠏⠀⠀⠀⠞⠁⣠⣾⡿⡏⠀⠀⠈⠳⣄⣀⣀⣻⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⢦⠀⠀⠘⢇⢹⠀⠀⠀⠀
|
|
21
|
+
⠀⠀⡿⠁⣰⡾⠛⠀⡜⠀⠀⠀⠀⢀⣼⡿⠃⠘⢳⡀⠀⠀⢠⠋⠳⢄⡀⠙⢦⣀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠙⠾⠀⠀⠀⠈⠋⣇⠀⠀⠀
|
|
22
|
+
⠀⠀⠁⣼⠛⠀⠀⣸⠃⠀⠀⠀⢀⣾⡟⣷⠀⠀⠀⠙⠒⠒⠚⢷⠖⠋⢉⡿⠋⠉⠓⢦⣄⠸⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡆⠀⠀
|
|
23
|
+
⠀⠀⣸⠃⠀⢀⣴⡇⠀⠀⠀⢀⣾⡟⠉⠉⢧⡀⠀⠀⠘⣆⣀⠤⢷⣶⠟⠀⠀⠀⠀⠀⠈⠱⣄⠉⠳⢤⡀⠀⠀⠀⢰⡎⠉⠲⠄⢹⠲⡄
|
|
24
|
+
⠀⠀⣧⠞⣧⣾⢿⠁⠀⠀⠀⣼⡿⡁⠀⠀⠀⠈⠹⡟⠛⠙⣆⡤⣾⡟⠀⠀⠀⠀⠀⠀⠀⠀⠈⢳⡀⠀⠙⢦⡀⠀⢀⣿⣄⠀⠀⠀⠀⢸
|
|
25
|
+
⠀⢸⠃⣰⡟⠁⣾⠀⠀⠀⢸⣿⣤⠧⣄⠀⠀⠀⢀⣱⠤⠒⠁⢠⡿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⣵⡄⢻⠀⠸⡻⣿⣄⣤⠀⠀⡼
|
|
26
|
+
⠀⠉⢸⡟⠀⠀⡿⠀⠀⠀⣿⡇⠀⠀⠀⠉⢹⡏⠉⠈⣷⠤⠴⣿⢻⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢷⠀⢧⡀⠀⠾⠀⠀⢸⢠⠇
|
|
27
|
+
⠀⠀⡿⠁⠀⠀⡇⠀⠀⢰⡟⢱⣄⠀⠀⠀⠀⢣⠤⠚⠁⠀⢰⣿⠘⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠷⣄⡉⠳⢦⣀⡤⣾⡟⠀
|
|
28
|
+
⠀⢸⣇⡤⠤⣄⡇⠀⠀⣿⡏⠉⠈⠙⠒⡖⠒⠉⢷⡀⠀⣠⢾⡟⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠛⠛⠀⠀⠀⠀⠀
|
|
29
|
+
⠀⣼⠏⠀⢀⣿⡇⠀⢀⣿⡀⠀⠀⠀⠀⠙⣆⣀⠴⠋⠉⠑⢾⡇⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
30
|
+
⠀⢹⠀⢀⣿⠏⣇⠀⢸⣿⢑⡤⣀⣀⣀⡴⠛⣇⠀⠀⠀⢀⣼⡇⠀⠸⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
31
|
+
⠀⠀⠀⣼⡏⠀⣧⠀⣼⡿⠉⠀⠈⠉⢧⡀⠀⢈⡷⠒⠒⠫⣼⡇⠀⠀⢿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
32
|
+
⠀⠀⢠⣿⣠⢦⣿⠀⣿⣧⠀⠀⠀⠀⠀⢉⣞⠉⠀⠀⠀⠀⢸⣧⠀⠀⠈⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
33
|
+
⠀⠀⠀⣿⠁⢸⣿⢰⣿⣏⡳⠤⣤⡤⠖⠉⠘⢦⡀⠀⠀⣠⡾⣿⠀⠀⠀⠸⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
34
|
+
⠀⠀⠀⠋⠀⡞⣿⢸⣿⠀⠀⠀⠈⠣⡀⠀⢀⣠⠛⠉⠉⠉⠓⣿⡄⠀⠀⠀⠘⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
35
|
+
⠀⠀⠀⠀⠀⣾⠃⣿⡇⠀⠀⠀⠀⠀⢈⣿⣏⠀⠀⠀⠀⠀⠀⠀⢸⠿⣷⡀⠀⠈⠛⢶⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
|
|
36
|
+
⠀⠀⠀⠀⢠⡇⠀⣿⣿⣦⣤⣤⣶⠟⠁⠈⠈⠳⢤⣀⣀⣀⡤⠴⠚⠚⠛⣷⡄⠀⠀⠀⠉⠛⠳⢤⣄⡀⠀⠀⠀⠀⠀⠀⠀
|
package/fire.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { colorize } from './colorUtils.js';
|
|
2
|
+
|
|
3
|
+
// 1. Softer character palette (Removed aggressive shapes)
|
|
4
|
+
const FIRE_CHARS = ' .,:;+*xX%#'.split('');
|
|
5
|
+
|
|
6
|
+
// 2. Warmer, subtler palette (More deep reds, peaks at warm amber, no harsh white)
|
|
7
|
+
const COLORS = [
|
|
8
|
+
null,
|
|
9
|
+
'#1a0000', '#330000', '#4d0000', '#660000', '#800000',
|
|
10
|
+
'#991a00', '#b33300', '#cc4d00', '#e66600', '#ff8000',
|
|
11
|
+
'#ff9933', '#ffb366', '#ffcc99'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export class FireSystem {
|
|
15
|
+
constructor(width, height) {
|
|
16
|
+
this.width = width;
|
|
17
|
+
this.height = height;
|
|
18
|
+
|
|
19
|
+
this.firePixels = new Array(this.width * this.height).fill(0);
|
|
20
|
+
this.initBottomRow();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
resize(width, height) {
|
|
24
|
+
this.width = width;
|
|
25
|
+
this.height = height;
|
|
26
|
+
this.firePixels = new Array(this.width * this.height).fill(0);
|
|
27
|
+
this.initBottomRow();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
initBottomRow() {
|
|
31
|
+
const bottomY = this.height - 1;
|
|
32
|
+
const maxIntensity = COLORS.length - 1;
|
|
33
|
+
|
|
34
|
+
for (let x = 0; x < this.width; x++) {
|
|
35
|
+
this.firePixels[bottomY * this.width + x] = maxIntensity;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
update() {
|
|
40
|
+
for (let x = 0; x < this.width; x++) {
|
|
41
|
+
for (let y = 1; y < this.height; y++) {
|
|
42
|
+
const src = y * this.width + x;
|
|
43
|
+
|
|
44
|
+
// 3. Decoupled physics: Heat drops gently but consistently
|
|
45
|
+
// Drops by 1 about 60% of the time, resulting in shorter, smoother flames
|
|
46
|
+
const heatLoss = Math.random() > 0.4 ? 1 : 0;
|
|
47
|
+
|
|
48
|
+
// 4. Subtler wind: mostly straight up, occasional gentle sway
|
|
49
|
+
const windChance = Math.random();
|
|
50
|
+
let shiftX = 0;
|
|
51
|
+
if (windChance < 0.25) shiftX = -1; // Gentle drift left
|
|
52
|
+
else if (windChance > 0.75) shiftX = 1; // Gentle drift right
|
|
53
|
+
|
|
54
|
+
let destX = x + shiftX;
|
|
55
|
+
|
|
56
|
+
// Boundary wrapping/clamping
|
|
57
|
+
if (destX < 0) destX = 0;
|
|
58
|
+
if (destX >= this.width) destX = this.width - 1;
|
|
59
|
+
|
|
60
|
+
const dest = (y - 1) * this.width + destX;
|
|
61
|
+
let pixel = this.firePixels[src] - heatLoss;
|
|
62
|
+
|
|
63
|
+
if (pixel < 0) pixel = 0;
|
|
64
|
+
|
|
65
|
+
this.firePixels[dest] = pixel;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 5. Softer base generation
|
|
70
|
+
// Instead of a solid wall of max intensity, we poke "holes" in the bottom
|
|
71
|
+
// row to create the illusion of individual, distinct flames swaying up.
|
|
72
|
+
const bottomY = this.height - 1;
|
|
73
|
+
for (let x = 0; x < this.width; x++) {
|
|
74
|
+
if (Math.random() < 0.35) {
|
|
75
|
+
// Drop intensity by 0 to 3 levels to create gaps
|
|
76
|
+
const drop = Math.floor(Math.random() * 4);
|
|
77
|
+
this.firePixels[bottomY * this.width + x] = Math.max(0, (COLORS.length - 1) - drop);
|
|
78
|
+
} else {
|
|
79
|
+
this.firePixels[bottomY * this.width + x] = COLORS.length - 1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
draw(buffer) {
|
|
85
|
+
const maxIntensity = COLORS.length - 1;
|
|
86
|
+
for (let y = 0; y < this.height; y++) {
|
|
87
|
+
if (!buffer[y]) buffer[y] = new Array(this.width).fill(' ');
|
|
88
|
+
|
|
89
|
+
for (let x = 0; x < this.width; x++) {
|
|
90
|
+
let intensity = this.firePixels[y * this.width + x];
|
|
91
|
+
if (intensity < 0) intensity = 0;
|
|
92
|
+
if (intensity > maxIntensity) intensity = maxIntensity;
|
|
93
|
+
|
|
94
|
+
// Explicitly render empty space for 0 intensity to avoid artifacts
|
|
95
|
+
if (intensity === 0) {
|
|
96
|
+
buffer[y][x] = ' ';
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const charIndex = Math.floor((intensity / maxIntensity) * (FIRE_CHARS.length - 1));
|
|
101
|
+
const char = FIRE_CHARS[charIndex];
|
|
102
|
+
|
|
103
|
+
const colorHex = COLORS[intensity];
|
|
104
|
+
if (colorHex) {
|
|
105
|
+
buffer[y][x] = colorize(colorHex, char);
|
|
106
|
+
} else {
|
|
107
|
+
buffer[y][x] = char;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import cliCursor from "cli-cursor";
|
|
4
|
+
import { colorize } from "./colorUtils.js";
|
|
5
|
+
import readline from "readline";
|
|
6
|
+
import { dragonLines, dragonWidth, dragonHeight } from "./dragon.js";
|
|
7
|
+
import { FireSystem } from "./fire.js";
|
|
8
|
+
|
|
9
|
+
function exitGracefully() {
|
|
10
|
+
cliCursor.show();
|
|
11
|
+
process.stdout.write("\x1b[2J\x1b[3J\x1b[H"); // Clear full screen and history, move to top
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
process.on("SIGINT", exitGracefully);
|
|
16
|
+
process.on("SIGTERM", exitGracefully);
|
|
17
|
+
|
|
18
|
+
let width = process.stdout.columns || 80;
|
|
19
|
+
let height = process.stdout.rows || 24;
|
|
20
|
+
|
|
21
|
+
const fire = new FireSystem(width, height);
|
|
22
|
+
|
|
23
|
+
// Dragon starting position (bottom centered)
|
|
24
|
+
let dragonX = (width - dragonWidth) / 2;
|
|
25
|
+
let dragonY = height;
|
|
26
|
+
|
|
27
|
+
// Movement speeds (frames)
|
|
28
|
+
let dy = 0.5;
|
|
29
|
+
|
|
30
|
+
// Prepare color function for dragon
|
|
31
|
+
const colorDragon = (char) => colorize("#22c55e", char);
|
|
32
|
+
|
|
33
|
+
cliCursor.hide();
|
|
34
|
+
|
|
35
|
+
function render() {
|
|
36
|
+
// Update dimensions in case of resize
|
|
37
|
+
const newWidth = process.stdout.columns || 80;
|
|
38
|
+
const newHeight = process.stdout.rows || 24;
|
|
39
|
+
|
|
40
|
+
if (width !== newWidth || height !== newHeight) {
|
|
41
|
+
width = newWidth;
|
|
42
|
+
height = newHeight;
|
|
43
|
+
fire.resize(width, height);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Clear buffer (2D array of spaces)
|
|
47
|
+
const buffer = [];
|
|
48
|
+
for (let y = 0; y < height; y++) {
|
|
49
|
+
buffer.push(new Array(width).fill(" "));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Update logic
|
|
53
|
+
fire.update();
|
|
54
|
+
|
|
55
|
+
// Keep horizontally centered
|
|
56
|
+
dragonX = (width - dragonWidth) / 2;
|
|
57
|
+
|
|
58
|
+
// Move up until centered vertically
|
|
59
|
+
const targetY = (height - dragonHeight) / 2;
|
|
60
|
+
if (dragonY > targetY) {
|
|
61
|
+
dragonY -= dy;
|
|
62
|
+
if (dragonY < targetY) dragonY = targetY;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Draw fire
|
|
66
|
+
fire.draw(buffer);
|
|
67
|
+
|
|
68
|
+
// Draw dragon over rain
|
|
69
|
+
const drX = Math.floor(dragonX);
|
|
70
|
+
const drY = Math.floor(dragonY);
|
|
71
|
+
|
|
72
|
+
for (let r = 0; r < dragonHeight; r++) {
|
|
73
|
+
const screenY = drY + r;
|
|
74
|
+
if (screenY >= 0 && screenY < height) {
|
|
75
|
+
const line = dragonLines[r];
|
|
76
|
+
for (let c = 0; c < line.length; c++) {
|
|
77
|
+
const char = line[c];
|
|
78
|
+
// Treat both space and Braille blank pattern as transparent
|
|
79
|
+
if (char !== " " && char !== "⠀") {
|
|
80
|
+
const screenX = drX + c;
|
|
81
|
+
if (screenX >= 0 && screenX < width) {
|
|
82
|
+
buffer[screenY][screenX] = colorDragon(char);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Create frame string
|
|
90
|
+
let frame = "";
|
|
91
|
+
for (let y = 0; y < height; y++) {
|
|
92
|
+
frame += buffer[y].join("") + (y === height - 1 ? "" : "\n");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Render to screen by clearing and writing frame
|
|
96
|
+
// \x1b[H moves cursor to 0,0. It's faster and less flickery than clearing screen entirely.
|
|
97
|
+
process.stdout.write("\x1b[H" + frame);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Clear screen once before loop
|
|
101
|
+
process.stdout.write("\x1b[2J\x1b[3J\x1b[H");
|
|
102
|
+
|
|
103
|
+
setInterval(render, 53); // ~30 FPS
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mintikaryu",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A sacred CLI tool to summon the ancient fire dragon Mintikaryū (みんてぃかりゅう)",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"cli",
|
|
11
|
+
"terminal",
|
|
12
|
+
"ascii-art",
|
|
13
|
+
"animation",
|
|
14
|
+
"dragon",
|
|
15
|
+
"fire",
|
|
16
|
+
"ansi",
|
|
17
|
+
"true-color",
|
|
18
|
+
"japanese-dragon",
|
|
19
|
+
"fire-simulation",
|
|
20
|
+
"terminal-art",
|
|
21
|
+
"mythology"
|
|
22
|
+
],
|
|
23
|
+
"author": "Aayush Anand",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/aayushananda/Dragon_god.git"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"cli-cursor": "^5.0.0"
|
|
31
|
+
},
|
|
32
|
+
"type": "module",
|
|
33
|
+
"bin": {
|
|
34
|
+
"summon-dragon": "index.js"
|
|
35
|
+
}
|
|
36
|
+
}
|