zx-kit 0.1.0 → 0.1.1

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.
@@ -0,0 +1,6 @@
1
+ export declare function initAudio(volume?: number): void;
2
+ export declare function resumeAudio(): void;
3
+ export declare function getAudioContext(): AudioContext | null;
4
+ export declare function getMasterGain(): GainNode | null;
5
+ export declare function beep(freq: number, durationMs: number, startTime: number): void;
6
+ //# sourceMappingURL=audio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.d.ts","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"AAGA,wBAAgB,SAAS,CAAC,MAAM,SAAM,GAAG,IAAI,CAM5C;AAED,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAErD;AAED,wBAAgB,aAAa,IAAI,QAAQ,GAAG,IAAI,CAE/C;AAGD,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAc9E"}
package/dist/audio.js ADDED
@@ -0,0 +1,38 @@
1
+ let ctx = null;
2
+ let masterGain = null;
3
+ export function initAudio(volume = 0.3) {
4
+ if (ctx)
5
+ return;
6
+ ctx = new AudioContext();
7
+ masterGain = ctx.createGain();
8
+ masterGain.gain.value = volume;
9
+ masterGain.connect(ctx.destination);
10
+ }
11
+ export function resumeAudio() {
12
+ if (ctx && ctx.state === 'suspended')
13
+ void ctx.resume();
14
+ }
15
+ export function getAudioContext() {
16
+ return ctx;
17
+ }
18
+ export function getMasterGain() {
19
+ return masterGain;
20
+ }
21
+ // Core primitive — schedule a square-wave beep on the shared AudioContext
22
+ export function beep(freq, durationMs, startTime) {
23
+ if (!ctx || !masterGain)
24
+ return;
25
+ const osc = ctx.createOscillator();
26
+ const gain = ctx.createGain();
27
+ osc.type = 'square';
28
+ osc.frequency.value = freq;
29
+ gain.gain.setValueAtTime(0, startTime);
30
+ gain.gain.linearRampToValueAtTime(0.8, startTime + 0.005);
31
+ gain.gain.setValueAtTime(0.8, startTime + durationMs / 1000 - 0.005);
32
+ gain.gain.linearRampToValueAtTime(0, startTime + durationMs / 1000);
33
+ osc.connect(gain);
34
+ gain.connect(masterGain);
35
+ osc.start(startTime);
36
+ osc.stop(startTime + durationMs / 1000 + 0.01);
37
+ }
38
+ //# sourceMappingURL=audio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio.js","sourceRoot":"","sources":["../src/audio.ts"],"names":[],"mappings":"AAAA,IAAI,GAAG,GAAwB,IAAI,CAAA;AACnC,IAAI,UAAU,GAAoB,IAAI,CAAA;AAEtC,MAAM,UAAU,SAAS,CAAC,MAAM,GAAG,GAAG;IACpC,IAAI,GAAG;QAAE,OAAM;IACf,GAAG,GAAG,IAAI,YAAY,EAAE,CAAA;IACxB,UAAU,GAAG,GAAG,CAAC,UAAU,EAAE,CAAA;IAC7B,UAAU,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;IAC9B,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,KAAK,WAAW;QAAE,KAAK,GAAG,CAAC,MAAM,EAAE,CAAA;AACzD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,IAAI,CAAC,IAAY,EAAE,UAAkB,EAAE,SAAiB;IACtE,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU;QAAE,OAAM;IAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,EAAE,CAAA;IAClC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,EAAE,CAAA;IAC7B,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAA;IACnB,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,IAAI,CAAA;IAC1B,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;IACtC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,GAAG,EAAE,SAAS,GAAG,KAAK,CAAC,CAAA;IACzD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,SAAS,GAAG,UAAU,GAAG,IAAI,GAAG,KAAK,CAAC,CAAA;IACpE,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,CAAA;IACnE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACjB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IACxB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IACpB,GAAG,CAAC,IAAI,CAAC,SAAS,GAAG,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC,CAAA;AAChD,CAAC"}
package/dist/font.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare const FONT: Uint8Array<ArrayBuffer>;
2
+ export declare function getCharRow(charCode: number, row: number): number;
3
+ //# sourceMappingURL=font.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font.d.ts","sourceRoot":"","sources":["../src/font.ts"],"names":[],"mappings":"AAoMA,eAAO,MAAM,IAAI,yBAAsB,CAAA;AAEvC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAIhE"}
package/dist/font.js ADDED
@@ -0,0 +1,203 @@
1
+ // ZX Spectrum ROM font — characters 32–127, 8 bytes per char (row-major, bit7=leftmost pixel)
2
+ const RAW = [
3
+ // 32 space
4
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5
+ // 33 !
6
+ 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00,
7
+ // 34 "
8
+ 0x00, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
9
+ // 35 #
10
+ 0x00, 0x28, 0x7C, 0x28, 0x28, 0x7C, 0x28, 0x00,
11
+ // 36 $
12
+ 0x00, 0x10, 0x3C, 0x50, 0x3C, 0x14, 0x7C, 0x10,
13
+ // 37 %
14
+ 0x00, 0x62, 0x64, 0x08, 0x10, 0x26, 0x46, 0x00,
15
+ // 38 &
16
+ 0x00, 0x10, 0x28, 0x10, 0x2A, 0x44, 0x3A, 0x00,
17
+ // 39 '
18
+ 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
19
+ // 40 (
20
+ 0x00, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x00,
21
+ // 41 )
22
+ 0x00, 0x20, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00,
23
+ // 42 *
24
+ 0x00, 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, 0x00,
25
+ // 43 +
26
+ 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00,
27
+ // 44 ,
28
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10,
29
+ // 45 -
30
+ 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
31
+ // 46 .
32
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
33
+ // 47 /
34
+ 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00,
35
+ // 48 0
36
+ 0x00, 0x3C, 0x46, 0x4A, 0x52, 0x62, 0x3C, 0x00,
37
+ // 49 1
38
+ 0x00, 0x08, 0x18, 0x08, 0x08, 0x08, 0x1C, 0x00,
39
+ // 50 2
40
+ 0x00, 0x3C, 0x42, 0x04, 0x18, 0x20, 0x7E, 0x00,
41
+ // 51 3
42
+ 0x00, 0x3C, 0x42, 0x0C, 0x02, 0x42, 0x3C, 0x00,
43
+ // 52 4
44
+ 0x00, 0x08, 0x18, 0x28, 0x48, 0x7E, 0x08, 0x00,
45
+ // 53 5
46
+ 0x00, 0x7E, 0x40, 0x7C, 0x02, 0x42, 0x3C, 0x00,
47
+ // 54 6
48
+ 0x00, 0x3C, 0x40, 0x7C, 0x42, 0x42, 0x3C, 0x00,
49
+ // 55 7
50
+ 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10, 0x10, 0x00,
51
+ // 56 8
52
+ 0x00, 0x3C, 0x42, 0x3C, 0x42, 0x42, 0x3C, 0x00,
53
+ // 57 9
54
+ 0x00, 0x3C, 0x42, 0x42, 0x3E, 0x02, 0x3C, 0x00,
55
+ // 58 :
56
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00,
57
+ // 59 ;
58
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20,
59
+ // 60 <
60
+ 0x00, 0x04, 0x08, 0x10, 0x08, 0x04, 0x00, 0x00,
61
+ // 61 =
62
+ 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x00,
63
+ // 62 >
64
+ 0x00, 0x20, 0x10, 0x08, 0x10, 0x20, 0x00, 0x00,
65
+ // 63 ?
66
+ 0x00, 0x3C, 0x42, 0x04, 0x08, 0x00, 0x08, 0x00,
67
+ // 64 @
68
+ 0x00, 0x3C, 0x4A, 0x56, 0x5C, 0x40, 0x3C, 0x00,
69
+ // 65 A
70
+ 0x00, 0x18, 0x24, 0x42, 0x7E, 0x42, 0x42, 0x00,
71
+ // 66 B
72
+ 0x00, 0x7C, 0x42, 0x7C, 0x42, 0x42, 0x7C, 0x00,
73
+ // 67 C
74
+ 0x00, 0x3C, 0x42, 0x40, 0x40, 0x42, 0x3C, 0x00,
75
+ // 68 D
76
+ 0x00, 0x78, 0x44, 0x42, 0x42, 0x44, 0x78, 0x00,
77
+ // 69 E
78
+ 0x00, 0x7E, 0x40, 0x7C, 0x40, 0x40, 0x7E, 0x00,
79
+ // 70 F
80
+ 0x00, 0x7E, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x00,
81
+ // 71 G
82
+ 0x00, 0x3C, 0x42, 0x40, 0x4E, 0x42, 0x3C, 0x00,
83
+ // 72 H
84
+ 0x00, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00,
85
+ // 73 I
86
+ 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00,
87
+ // 74 J
88
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x42, 0x3C, 0x00,
89
+ // 75 K
90
+ 0x00, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00,
91
+ // 76 L
92
+ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00,
93
+ // 77 M
94
+ 0x00, 0x42, 0x66, 0x5A, 0x42, 0x42, 0x42, 0x00,
95
+ // 78 N
96
+ 0x00, 0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x00,
97
+ // 79 O
98
+ 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00,
99
+ // 80 P
100
+ 0x00, 0x7C, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x00,
101
+ // 81 Q
102
+ 0x00, 0x3C, 0x42, 0x42, 0x4A, 0x44, 0x3A, 0x00,
103
+ // 82 R
104
+ 0x00, 0x7C, 0x42, 0x42, 0x7C, 0x48, 0x44, 0x00,
105
+ // 83 S
106
+ 0x00, 0x3C, 0x40, 0x3C, 0x02, 0x42, 0x3C, 0x00,
107
+ // 84 T
108
+ 0x00, 0x7E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
109
+ // 85 U
110
+ 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00,
111
+ // 86 V
112
+ 0x00, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00,
113
+ // 87 W
114
+ 0x00, 0x42, 0x42, 0x42, 0x5A, 0x66, 0x42, 0x00,
115
+ // 88 X
116
+ 0x00, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x00,
117
+ // 89 Y
118
+ 0x00, 0x42, 0x42, 0x24, 0x18, 0x08, 0x08, 0x00,
119
+ // 90 Z
120
+ 0x00, 0x7E, 0x04, 0x08, 0x10, 0x20, 0x7E, 0x00,
121
+ // 91 [
122
+ 0x00, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x1C, 0x00,
123
+ // 92 backslash
124
+ 0x00, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00,
125
+ // 93 ]
126
+ 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00,
127
+ // 94 ^
128
+ 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00,
129
+ // 95 _
130
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E,
131
+ // 96 `
132
+ 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
133
+ // 97 a
134
+ 0x00, 0x00, 0x3C, 0x02, 0x3E, 0x42, 0x3E, 0x00,
135
+ // 98 b
136
+ 0x00, 0x20, 0x20, 0x3E, 0x22, 0x22, 0x3E, 0x00,
137
+ // 99 c
138
+ 0x00, 0x00, 0x1E, 0x20, 0x20, 0x20, 0x1E, 0x00,
139
+ // 100 d
140
+ 0x00, 0x02, 0x02, 0x3E, 0x42, 0x42, 0x3E, 0x00,
141
+ // 101 e
142
+ 0x00, 0x00, 0x3C, 0x42, 0x7E, 0x40, 0x3C, 0x00,
143
+ // 102 f
144
+ 0x00, 0x0C, 0x10, 0x3C, 0x10, 0x10, 0x10, 0x00,
145
+ // 103 g
146
+ 0x00, 0x00, 0x3E, 0x42, 0x42, 0x3E, 0x02, 0x3C,
147
+ // 104 h
148
+ 0x00, 0x20, 0x20, 0x2C, 0x32, 0x22, 0x22, 0x00,
149
+ // 105 i
150
+ 0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x1C, 0x00,
151
+ // 106 j
152
+ 0x00, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x44, 0x38,
153
+ // 107 k
154
+ 0x00, 0x20, 0x28, 0x30, 0x28, 0x24, 0x22, 0x00,
155
+ // 108 l
156
+ 0x00, 0x18, 0x08, 0x08, 0x08, 0x08, 0x1C, 0x00,
157
+ // 109 m
158
+ 0x00, 0x00, 0x76, 0x49, 0x49, 0x49, 0x49, 0x00,
159
+ // 110 n
160
+ 0x00, 0x00, 0x2C, 0x32, 0x22, 0x22, 0x22, 0x00,
161
+ // 111 o
162
+ 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x3C, 0x00,
163
+ // 112 p
164
+ 0x00, 0x00, 0x3C, 0x22, 0x22, 0x3C, 0x20, 0x20,
165
+ // 113 q
166
+ 0x00, 0x00, 0x1E, 0x22, 0x22, 0x1E, 0x02, 0x02,
167
+ // 114 r
168
+ 0x00, 0x00, 0x2C, 0x30, 0x20, 0x20, 0x20, 0x00,
169
+ // 115 s
170
+ 0x00, 0x00, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x00,
171
+ // 116 t
172
+ 0x00, 0x10, 0x7C, 0x10, 0x10, 0x12, 0x0C, 0x00,
173
+ // 117 u
174
+ 0x00, 0x00, 0x22, 0x22, 0x22, 0x26, 0x1A, 0x00,
175
+ // 118 v
176
+ 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00,
177
+ // 119 w
178
+ 0x00, 0x00, 0x42, 0x42, 0x49, 0x55, 0x22, 0x00,
179
+ // 120 x
180
+ 0x00, 0x00, 0x42, 0x24, 0x18, 0x24, 0x42, 0x00,
181
+ // 121 y
182
+ 0x00, 0x00, 0x44, 0x44, 0x44, 0x3C, 0x04, 0x38,
183
+ // 122 z
184
+ 0x00, 0x00, 0x7E, 0x04, 0x18, 0x20, 0x7E, 0x00,
185
+ // 123 {
186
+ 0x00, 0x0C, 0x10, 0x60, 0x10, 0x10, 0x0C, 0x00,
187
+ // 124 |
188
+ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
189
+ // 125 }
190
+ 0x00, 0x30, 0x08, 0x06, 0x08, 0x08, 0x30, 0x00,
191
+ // 126 ~
192
+ 0x00, 0x00, 0x32, 0x4C, 0x00, 0x00, 0x00, 0x00,
193
+ // 127 solid block (used for lives / filled blocks)
194
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
195
+ ];
196
+ export const FONT = new Uint8Array(RAW);
197
+ export function getCharRow(charCode, row) {
198
+ const idx = charCode - 32;
199
+ if (idx < 0 || idx >= 96)
200
+ return 0;
201
+ return FONT[idx * 8 + row];
202
+ }
203
+ //# sourceMappingURL=font.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"font.js","sourceRoot":"","sources":["../src/font.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,GAAG,GAAsB;IAC7B,WAAW;IACX,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,eAAe;IACf,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,OAAO;IACP,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,QAAQ;IACR,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;IACvC,mDAAmD;IACnD,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI,EAAC,IAAI;CACxC,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;AAEvC,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,GAAW;IACtD,MAAM,GAAG,GAAG,QAAQ,GAAG,EAAE,CAAA;IACzB,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,EAAE;QAAE,OAAO,CAAC,CAAA;IAClC,OAAO,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;AAC5B,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './palette.js';
2
+ export * from './font.js';
3
+ export * from './renderer.js';
4
+ export * from './audio.js';
5
+ export * from './input.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from './palette.js';
2
+ export * from './font.js';
3
+ export * from './renderer.js';
4
+ export * from './audio.js';
5
+ export * from './input.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA"}
@@ -0,0 +1,9 @@
1
+ export type Direction = 'up' | 'down' | 'left' | 'right';
2
+ export declare function initInput(repeatDelay?: number, repeatInterval?: number): void;
3
+ export declare function tickMovement(dtMs: number): Direction | null;
4
+ export declare function consumeFlag(): boolean;
5
+ export declare function consumeDebug(): boolean;
6
+ export declare function consumePause(): boolean;
7
+ export declare function consumeAnyKey(): boolean;
8
+ export declare function isHeld(key: string): boolean;
9
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAmBxD,wBAAgB,SAAS,CAAC,WAAW,SAAM,EAAE,cAAc,SAAK,GAAG,IAAI,CAkCtE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAe3D;AAED,wBAAgB,WAAW,IAAI,OAAO,CAA+D;AACrG,wBAAgB,YAAY,IAAI,OAAO,CAA8D;AACrG,wBAAgB,YAAY,IAAI,OAAO,CAA8D;AACrG,wBAAgB,aAAa,IAAI,OAAO,CAA6D;AACrG,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAyB"}
package/dist/input.js ADDED
@@ -0,0 +1,70 @@
1
+ const DIR_KEYS = {
2
+ ArrowUp: 'up', ArrowDown: 'down', ArrowLeft: 'left', ArrowRight: 'right',
3
+ };
4
+ const held = new Set();
5
+ let pendingFlag = false;
6
+ let pendingDebug = false;
7
+ let pendingPause = false;
8
+ let pendingAnyKey = false;
9
+ let repeatDir = null;
10
+ let repeatTimer = 0;
11
+ let repeatPhase = 'idle';
12
+ let pendingImmediate = null;
13
+ let _repeatDelay = 150;
14
+ let _repeatInterval = 80;
15
+ export function initInput(repeatDelay = 150, repeatInterval = 80) {
16
+ _repeatDelay = repeatDelay;
17
+ _repeatInterval = repeatInterval;
18
+ window.addEventListener('keydown', (e) => {
19
+ if (e.repeat)
20
+ return;
21
+ pendingAnyKey = true;
22
+ held.add(e.key);
23
+ const dir = DIR_KEYS[e.key];
24
+ if (dir) {
25
+ repeatDir = dir;
26
+ repeatPhase = 'delay';
27
+ repeatTimer = _repeatDelay;
28
+ pendingImmediate = dir;
29
+ }
30
+ if (e.key === 'f' || e.key === 'F')
31
+ pendingFlag = true;
32
+ if (e.key === 'p' || e.key === 'P')
33
+ pendingPause = true;
34
+ if (e.ctrlKey && e.shiftKey && (e.key === 'b' || e.key === 'B')) {
35
+ pendingDebug = true;
36
+ e.preventDefault();
37
+ }
38
+ });
39
+ window.addEventListener('keyup', (e) => {
40
+ held.delete(e.key);
41
+ const dir = DIR_KEYS[e.key];
42
+ if (dir && repeatDir === dir) {
43
+ repeatDir = null;
44
+ repeatPhase = 'idle';
45
+ }
46
+ });
47
+ }
48
+ export function tickMovement(dtMs) {
49
+ if (pendingImmediate !== null) {
50
+ const d = pendingImmediate;
51
+ pendingImmediate = null;
52
+ return d;
53
+ }
54
+ if (repeatDir !== null && repeatPhase !== 'idle') {
55
+ repeatTimer -= dtMs;
56
+ if (repeatTimer <= 0) {
57
+ repeatTimer += _repeatInterval;
58
+ if (repeatPhase === 'delay')
59
+ repeatPhase = 'repeat';
60
+ return repeatDir;
61
+ }
62
+ }
63
+ return null;
64
+ }
65
+ export function consumeFlag() { const v = pendingFlag; pendingFlag = false; return v; }
66
+ export function consumeDebug() { const v = pendingDebug; pendingDebug = false; return v; }
67
+ export function consumePause() { const v = pendingPause; pendingPause = false; return v; }
68
+ export function consumeAnyKey() { const v = pendingAnyKey; pendingAnyKey = false; return v; }
69
+ export function isHeld(key) { return held.has(key); }
70
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export declare const SCALE = 4;
2
+ export declare const CELL = 8;
3
+ export declare const C: {
4
+ readonly BLACK: "#000000";
5
+ readonly BLUE: "#0000CD";
6
+ readonly RED: "#CD0000";
7
+ readonly MAGENTA: "#CD00CD";
8
+ readonly GREEN: "#00CD00";
9
+ readonly CYAN: "#00CDCD";
10
+ readonly YELLOW: "#CDCD00";
11
+ readonly WHITE: "#CDCDCD";
12
+ readonly B_BLACK: "#000000";
13
+ readonly B_BLUE: "#0000FF";
14
+ readonly B_RED: "#FF0000";
15
+ readonly B_MAGENTA: "#FF00FF";
16
+ readonly B_GREEN: "#00FF00";
17
+ readonly B_CYAN: "#00FFFF";
18
+ readonly B_YELLOW: "#FFFF00";
19
+ readonly B_WHITE: "#FFFFFF";
20
+ };
21
+ export type SpectrumColor = typeof C[keyof typeof C];
22
+ //# sourceMappingURL=palette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.d.ts","sourceRoot":"","sources":["../src/palette.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,IAAI,CAAA;AACtB,eAAO,MAAM,IAAI,IAAI,CAAA;AAGrB,eAAO,MAAM,CAAC;;;;;;;;;;;;;;;;;CAiBJ,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,CAAA"}
@@ -0,0 +1,22 @@
1
+ export const SCALE = 4;
2
+ export const CELL = 8;
3
+ // ZX Spectrum palette — exactly 15 colours, EXCLUSIVELY these hex values
4
+ export const C = {
5
+ BLACK: '#000000',
6
+ BLUE: '#0000CD',
7
+ RED: '#CD0000',
8
+ MAGENTA: '#CD00CD',
9
+ GREEN: '#00CD00',
10
+ CYAN: '#00CDCD',
11
+ YELLOW: '#CDCD00',
12
+ WHITE: '#CDCDCD',
13
+ B_BLACK: '#000000',
14
+ B_BLUE: '#0000FF',
15
+ B_RED: '#FF0000',
16
+ B_MAGENTA: '#FF00FF',
17
+ B_GREEN: '#00FF00',
18
+ B_CYAN: '#00FFFF',
19
+ B_YELLOW: '#FFFF00',
20
+ B_WHITE: '#FFFFFF',
21
+ };
22
+ //# sourceMappingURL=palette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.js","sourceRoot":"","sources":["../src/palette.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAA;AACtB,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAA;AAErB,yEAAyE;AACzE,MAAM,CAAC,MAAM,CAAC,GAAG;IACf,KAAK,EAAM,SAAS;IACpB,IAAI,EAAO,SAAS;IACpB,GAAG,EAAQ,SAAS;IACpB,OAAO,EAAI,SAAS;IACpB,KAAK,EAAM,SAAS;IACpB,IAAI,EAAO,SAAS;IACpB,MAAM,EAAK,SAAS;IACpB,KAAK,EAAM,SAAS;IACpB,OAAO,EAAI,SAAS;IACpB,MAAM,EAAK,SAAS;IACpB,KAAK,EAAM,SAAS;IACpB,SAAS,EAAE,SAAS;IACpB,OAAO,EAAI,SAAS;IACpB,MAAM,EAAK,SAAS;IACpB,QAAQ,EAAG,SAAS;IACpB,OAAO,EAAI,SAAS;CACZ,CAAA"}
@@ -0,0 +1,6 @@
1
+ export declare function mirrorSprite(src: Uint8Array): Uint8Array;
2
+ export declare function drawSprite(ctx: CanvasRenderingContext2D, sprite: Uint8Array, x: number, y: number, ink: string, paper: string): void;
3
+ export declare function drawChar(ctx: CanvasRenderingContext2D, code: number, x: number, y: number, ink: string, paper?: string): void;
4
+ export declare function drawText(ctx: CanvasRenderingContext2D, text: string, x: number, y: number, ink: string, paper?: string): void;
5
+ export declare function drawTextCentered(ctx: CanvasRenderingContext2D, text: string, y: number, cols: number, ink: string, paper?: string): void;
6
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAUxD;AAED,wBAAgB,UAAU,CACxB,GAAG,EAAE,wBAAwB,EAC7B,MAAM,EAAE,UAAU,EAClB,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EACpB,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GACzB,IAAI,CAUN;AAED,wBAAgB,QAAQ,CACtB,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EACpB,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAC1B,IAAI,CAYN;AAED,wBAAgB,QAAQ,CACtB,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EACpB,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAC1B,IAAI,CAIN;AAGD,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAC1B,IAAI,CAGN"}
@@ -0,0 +1,52 @@
1
+ import { CELL } from './palette.js';
2
+ import { getCharRow } from './font.js';
3
+ // Flip an 8×8 sprite horizontally
4
+ export function mirrorSprite(src) {
5
+ const out = new Uint8Array(8);
6
+ for (let r = 0; r < 8; r++) {
7
+ let b = src[r], m = 0;
8
+ for (let i = 0; i < 8; i++) {
9
+ if (b & (1 << i))
10
+ m |= (1 << (7 - i));
11
+ }
12
+ out[r] = m;
13
+ }
14
+ return out;
15
+ }
16
+ export function drawSprite(ctx, sprite, x, y, ink, paper) {
17
+ ctx.fillStyle = paper;
18
+ ctx.fillRect(x, y, CELL, CELL);
19
+ ctx.fillStyle = ink;
20
+ for (let row = 0; row < 8; row++) {
21
+ const byte = sprite[row];
22
+ for (let bit = 0; bit < 8; bit++) {
23
+ if (byte & (0x80 >> bit))
24
+ ctx.fillRect(x + bit, y + row, 1, 1);
25
+ }
26
+ }
27
+ }
28
+ export function drawChar(ctx, code, x, y, ink, paper) {
29
+ if (paper !== undefined) {
30
+ ctx.fillStyle = paper;
31
+ ctx.fillRect(x, y, CELL, CELL);
32
+ }
33
+ ctx.fillStyle = ink;
34
+ for (let row = 0; row < 8; row++) {
35
+ const byte = getCharRow(code, row);
36
+ for (let bit = 0; bit < 8; bit++) {
37
+ if (byte & (0x80 >> bit))
38
+ ctx.fillRect(x + bit, y + row, 1, 1);
39
+ }
40
+ }
41
+ }
42
+ export function drawText(ctx, text, x, y, ink, paper) {
43
+ for (let i = 0; i < text.length; i++) {
44
+ drawChar(ctx, text.charCodeAt(i), x + i * CELL, y, ink, paper);
45
+ }
46
+ }
47
+ // cols = total character columns of the canvas (e.g. 32 for standard Spectrum)
48
+ export function drawTextCentered(ctx, text, y, cols, ink, paper) {
49
+ const x = Math.floor((cols - text.length) / 2) * CELL;
50
+ drawText(ctx, text, x, y, ink, paper);
51
+ }
52
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,31 @@
1
1
  {
2
2
  "name": "zx-kit",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Reusable ZX Spectrum primitives: font, palette, renderer, audio, input",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": "./src/index.ts"
7
+ ".": {
8
+ "import": "./dist/index.js",
9
+ "types": "./dist/index.d.ts"
10
+ }
8
11
  },
9
- "keywords": ["zx-spectrum", "retro", "game", "canvas"],
10
- "license": "MIT"
12
+ "main": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "prepublishOnly": "npm run build"
20
+ },
21
+ "keywords": [
22
+ "zx-spectrum",
23
+ "retro",
24
+ "game",
25
+ "canvas"
26
+ ],
27
+ "license": "MIT",
28
+ "devDependencies": {
29
+ "typescript": "^6.0.3"
30
+ }
11
31
  }
package/src/audio.ts DELETED
@@ -1,39 +0,0 @@
1
- let ctx: AudioContext | null = null
2
- let masterGain: GainNode | null = null
3
-
4
- export function initAudio(volume = 0.3): void {
5
- if (ctx) return
6
- ctx = new AudioContext()
7
- masterGain = ctx.createGain()
8
- masterGain.gain.value = volume
9
- masterGain.connect(ctx.destination)
10
- }
11
-
12
- export function resumeAudio(): void {
13
- if (ctx && ctx.state === 'suspended') void ctx.resume()
14
- }
15
-
16
- export function getAudioContext(): AudioContext | null {
17
- return ctx
18
- }
19
-
20
- export function getMasterGain(): GainNode | null {
21
- return masterGain
22
- }
23
-
24
- // Core primitive — schedule a square-wave beep on the shared AudioContext
25
- export function beep(freq: number, durationMs: number, startTime: number): void {
26
- if (!ctx || !masterGain) return
27
- const osc = ctx.createOscillator()
28
- const gain = ctx.createGain()
29
- osc.type = 'square'
30
- osc.frequency.value = freq
31
- gain.gain.setValueAtTime(0, startTime)
32
- gain.gain.linearRampToValueAtTime(0.8, startTime + 0.005)
33
- gain.gain.setValueAtTime(0.8, startTime + durationMs / 1000 - 0.005)
34
- gain.gain.linearRampToValueAtTime(0, startTime + durationMs / 1000)
35
- osc.connect(gain)
36
- gain.connect(masterGain)
37
- osc.start(startTime)
38
- osc.stop(startTime + durationMs / 1000 + 0.01)
39
- }
package/src/font.ts DELETED
@@ -1,203 +0,0 @@
1
- // ZX Spectrum ROM font — characters 32–127, 8 bytes per char (row-major, bit7=leftmost pixel)
2
- const RAW: readonly number[] = [
3
- // 32 space
4
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
5
- // 33 !
6
- 0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x00,
7
- // 34 "
8
- 0x00,0x28,0x28,0x00,0x00,0x00,0x00,0x00,
9
- // 35 #
10
- 0x00,0x28,0x7C,0x28,0x28,0x7C,0x28,0x00,
11
- // 36 $
12
- 0x00,0x10,0x3C,0x50,0x3C,0x14,0x7C,0x10,
13
- // 37 %
14
- 0x00,0x62,0x64,0x08,0x10,0x26,0x46,0x00,
15
- // 38 &
16
- 0x00,0x10,0x28,0x10,0x2A,0x44,0x3A,0x00,
17
- // 39 '
18
- 0x00,0x08,0x08,0x00,0x00,0x00,0x00,0x00,
19
- // 40 (
20
- 0x00,0x04,0x08,0x08,0x08,0x08,0x04,0x00,
21
- // 41 )
22
- 0x00,0x20,0x10,0x10,0x10,0x10,0x20,0x00,
23
- // 42 *
24
- 0x00,0x00,0x14,0x08,0x3E,0x08,0x14,0x00,
25
- // 43 +
26
- 0x00,0x00,0x08,0x08,0x3E,0x08,0x08,0x00,
27
- // 44 ,
28
- 0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x10,
29
- // 45 -
30
- 0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,
31
- // 46 .
32
- 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
33
- // 47 /
34
- 0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x00,
35
- // 48 0
36
- 0x00,0x3C,0x46,0x4A,0x52,0x62,0x3C,0x00,
37
- // 49 1
38
- 0x00,0x08,0x18,0x08,0x08,0x08,0x1C,0x00,
39
- // 50 2
40
- 0x00,0x3C,0x42,0x04,0x18,0x20,0x7E,0x00,
41
- // 51 3
42
- 0x00,0x3C,0x42,0x0C,0x02,0x42,0x3C,0x00,
43
- // 52 4
44
- 0x00,0x08,0x18,0x28,0x48,0x7E,0x08,0x00,
45
- // 53 5
46
- 0x00,0x7E,0x40,0x7C,0x02,0x42,0x3C,0x00,
47
- // 54 6
48
- 0x00,0x3C,0x40,0x7C,0x42,0x42,0x3C,0x00,
49
- // 55 7
50
- 0x00,0x7E,0x02,0x04,0x08,0x10,0x10,0x00,
51
- // 56 8
52
- 0x00,0x3C,0x42,0x3C,0x42,0x42,0x3C,0x00,
53
- // 57 9
54
- 0x00,0x3C,0x42,0x42,0x3E,0x02,0x3C,0x00,
55
- // 58 :
56
- 0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,
57
- // 59 ;
58
- 0x00,0x00,0x10,0x00,0x00,0x10,0x10,0x20,
59
- // 60 <
60
- 0x00,0x04,0x08,0x10,0x08,0x04,0x00,0x00,
61
- // 61 =
62
- 0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,
63
- // 62 >
64
- 0x00,0x20,0x10,0x08,0x10,0x20,0x00,0x00,
65
- // 63 ?
66
- 0x00,0x3C,0x42,0x04,0x08,0x00,0x08,0x00,
67
- // 64 @
68
- 0x00,0x3C,0x4A,0x56,0x5C,0x40,0x3C,0x00,
69
- // 65 A
70
- 0x00,0x18,0x24,0x42,0x7E,0x42,0x42,0x00,
71
- // 66 B
72
- 0x00,0x7C,0x42,0x7C,0x42,0x42,0x7C,0x00,
73
- // 67 C
74
- 0x00,0x3C,0x42,0x40,0x40,0x42,0x3C,0x00,
75
- // 68 D
76
- 0x00,0x78,0x44,0x42,0x42,0x44,0x78,0x00,
77
- // 69 E
78
- 0x00,0x7E,0x40,0x7C,0x40,0x40,0x7E,0x00,
79
- // 70 F
80
- 0x00,0x7E,0x40,0x7C,0x40,0x40,0x40,0x00,
81
- // 71 G
82
- 0x00,0x3C,0x42,0x40,0x4E,0x42,0x3C,0x00,
83
- // 72 H
84
- 0x00,0x42,0x42,0x7E,0x42,0x42,0x42,0x00,
85
- // 73 I
86
- 0x00,0x3E,0x08,0x08,0x08,0x08,0x3E,0x00,
87
- // 74 J
88
- 0x00,0x02,0x02,0x02,0x02,0x42,0x3C,0x00,
89
- // 75 K
90
- 0x00,0x44,0x48,0x70,0x48,0x44,0x42,0x00,
91
- // 76 L
92
- 0x00,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,
93
- // 77 M
94
- 0x00,0x42,0x66,0x5A,0x42,0x42,0x42,0x00,
95
- // 78 N
96
- 0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x00,
97
- // 79 O
98
- 0x00,0x3C,0x42,0x42,0x42,0x42,0x3C,0x00,
99
- // 80 P
100
- 0x00,0x7C,0x42,0x42,0x7C,0x40,0x40,0x00,
101
- // 81 Q
102
- 0x00,0x3C,0x42,0x42,0x4A,0x44,0x3A,0x00,
103
- // 82 R
104
- 0x00,0x7C,0x42,0x42,0x7C,0x48,0x44,0x00,
105
- // 83 S
106
- 0x00,0x3C,0x40,0x3C,0x02,0x42,0x3C,0x00,
107
- // 84 T
108
- 0x00,0x7E,0x08,0x08,0x08,0x08,0x08,0x00,
109
- // 85 U
110
- 0x00,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,
111
- // 86 V
112
- 0x00,0x42,0x42,0x42,0x42,0x24,0x18,0x00,
113
- // 87 W
114
- 0x00,0x42,0x42,0x42,0x5A,0x66,0x42,0x00,
115
- // 88 X
116
- 0x00,0x42,0x24,0x18,0x18,0x24,0x42,0x00,
117
- // 89 Y
118
- 0x00,0x42,0x42,0x24,0x18,0x08,0x08,0x00,
119
- // 90 Z
120
- 0x00,0x7E,0x04,0x08,0x10,0x20,0x7E,0x00,
121
- // 91 [
122
- 0x00,0x1C,0x10,0x10,0x10,0x10,0x1C,0x00,
123
- // 92 backslash
124
- 0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x00,
125
- // 93 ]
126
- 0x00,0x38,0x08,0x08,0x08,0x08,0x38,0x00,
127
- // 94 ^
128
- 0x00,0x08,0x14,0x22,0x00,0x00,0x00,0x00,
129
- // 95 _
130
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,
131
- // 96 `
132
- 0x00,0x10,0x08,0x00,0x00,0x00,0x00,0x00,
133
- // 97 a
134
- 0x00,0x00,0x3C,0x02,0x3E,0x42,0x3E,0x00,
135
- // 98 b
136
- 0x00,0x20,0x20,0x3E,0x22,0x22,0x3E,0x00,
137
- // 99 c
138
- 0x00,0x00,0x1E,0x20,0x20,0x20,0x1E,0x00,
139
- // 100 d
140
- 0x00,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,
141
- // 101 e
142
- 0x00,0x00,0x3C,0x42,0x7E,0x40,0x3C,0x00,
143
- // 102 f
144
- 0x00,0x0C,0x10,0x3C,0x10,0x10,0x10,0x00,
145
- // 103 g
146
- 0x00,0x00,0x3E,0x42,0x42,0x3E,0x02,0x3C,
147
- // 104 h
148
- 0x00,0x20,0x20,0x2C,0x32,0x22,0x22,0x00,
149
- // 105 i
150
- 0x00,0x08,0x00,0x18,0x08,0x08,0x1C,0x00,
151
- // 106 j
152
- 0x00,0x04,0x00,0x0C,0x04,0x04,0x44,0x38,
153
- // 107 k
154
- 0x00,0x20,0x28,0x30,0x28,0x24,0x22,0x00,
155
- // 108 l
156
- 0x00,0x18,0x08,0x08,0x08,0x08,0x1C,0x00,
157
- // 109 m
158
- 0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x00,
159
- // 110 n
160
- 0x00,0x00,0x2C,0x32,0x22,0x22,0x22,0x00,
161
- // 111 o
162
- 0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x00,
163
- // 112 p
164
- 0x00,0x00,0x3C,0x22,0x22,0x3C,0x20,0x20,
165
- // 113 q
166
- 0x00,0x00,0x1E,0x22,0x22,0x1E,0x02,0x02,
167
- // 114 r
168
- 0x00,0x00,0x2C,0x30,0x20,0x20,0x20,0x00,
169
- // 115 s
170
- 0x00,0x00,0x1E,0x20,0x1C,0x02,0x3C,0x00,
171
- // 116 t
172
- 0x00,0x10,0x7C,0x10,0x10,0x12,0x0C,0x00,
173
- // 117 u
174
- 0x00,0x00,0x22,0x22,0x22,0x26,0x1A,0x00,
175
- // 118 v
176
- 0x00,0x00,0x42,0x42,0x42,0x24,0x18,0x00,
177
- // 119 w
178
- 0x00,0x00,0x42,0x42,0x49,0x55,0x22,0x00,
179
- // 120 x
180
- 0x00,0x00,0x42,0x24,0x18,0x24,0x42,0x00,
181
- // 121 y
182
- 0x00,0x00,0x44,0x44,0x44,0x3C,0x04,0x38,
183
- // 122 z
184
- 0x00,0x00,0x7E,0x04,0x18,0x20,0x7E,0x00,
185
- // 123 {
186
- 0x00,0x0C,0x10,0x60,0x10,0x10,0x0C,0x00,
187
- // 124 |
188
- 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00,
189
- // 125 }
190
- 0x00,0x30,0x08,0x06,0x08,0x08,0x30,0x00,
191
- // 126 ~
192
- 0x00,0x00,0x32,0x4C,0x00,0x00,0x00,0x00,
193
- // 127 solid block (used for lives / filled blocks)
194
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
195
- ]
196
-
197
- export const FONT = new Uint8Array(RAW)
198
-
199
- export function getCharRow(charCode: number, row: number): number {
200
- const idx = charCode - 32
201
- if (idx < 0 || idx >= 96) return 0
202
- return FONT[idx * 8 + row]
203
- }
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from './palette.ts'
2
- export * from './font.ts'
3
- export * from './renderer.ts'
4
- export * from './audio.ts'
5
- export * from './input.ts'
package/src/input.ts DELETED
@@ -1,77 +0,0 @@
1
- export type Direction = 'up' | 'down' | 'left' | 'right'
2
-
3
- const DIR_KEYS: Record<string, Direction> = {
4
- ArrowUp: 'up', ArrowDown: 'down', ArrowLeft: 'left', ArrowRight: 'right',
5
- }
6
-
7
- const held = new Set<string>()
8
- let pendingFlag = false
9
- let pendingDebug = false
10
- let pendingPause = false
11
- let pendingAnyKey = false
12
-
13
- let repeatDir: Direction | null = null
14
- let repeatTimer = 0
15
- let repeatPhase: 'delay' | 'repeat' | 'idle' = 'idle'
16
- let pendingImmediate: Direction | null = null
17
- let _repeatDelay = 150
18
- let _repeatInterval = 80
19
-
20
- export function initInput(repeatDelay = 150, repeatInterval = 80): void {
21
- _repeatDelay = repeatDelay
22
- _repeatInterval = repeatInterval
23
-
24
- window.addEventListener('keydown', (e: KeyboardEvent) => {
25
- if (e.repeat) return
26
- pendingAnyKey = true
27
- held.add(e.key)
28
-
29
- const dir = DIR_KEYS[e.key]
30
- if (dir) {
31
- repeatDir = dir
32
- repeatPhase = 'delay'
33
- repeatTimer = _repeatDelay
34
- pendingImmediate = dir
35
- }
36
-
37
- if (e.key === 'f' || e.key === 'F') pendingFlag = true
38
- if (e.key === 'p' || e.key === 'P') pendingPause = true
39
-
40
- if (e.ctrlKey && e.shiftKey && (e.key === 'b' || e.key === 'B')) {
41
- pendingDebug = true
42
- e.preventDefault()
43
- }
44
- })
45
-
46
- window.addEventListener('keyup', (e: KeyboardEvent) => {
47
- held.delete(e.key)
48
- const dir = DIR_KEYS[e.key]
49
- if (dir && repeatDir === dir) {
50
- repeatDir = null
51
- repeatPhase = 'idle'
52
- }
53
- })
54
- }
55
-
56
- export function tickMovement(dtMs: number): Direction | null {
57
- if (pendingImmediate !== null) {
58
- const d = pendingImmediate
59
- pendingImmediate = null
60
- return d
61
- }
62
- if (repeatDir !== null && repeatPhase !== 'idle') {
63
- repeatTimer -= dtMs
64
- if (repeatTimer <= 0) {
65
- repeatTimer += _repeatInterval
66
- if (repeatPhase === 'delay') repeatPhase = 'repeat'
67
- return repeatDir
68
- }
69
- }
70
- return null
71
- }
72
-
73
- export function consumeFlag(): boolean { const v = pendingFlag; pendingFlag = false; return v }
74
- export function consumeDebug(): boolean { const v = pendingDebug; pendingDebug = false; return v }
75
- export function consumePause(): boolean { const v = pendingPause; pendingPause = false; return v }
76
- export function consumeAnyKey(): boolean { const v = pendingAnyKey; pendingAnyKey = false; return v }
77
- export function isHeld(key: string): boolean { return held.has(key) }
package/src/palette.ts DELETED
@@ -1,24 +0,0 @@
1
- export const SCALE = 4
2
- export const CELL = 8
3
-
4
- // ZX Spectrum palette — exactly 15 colours, EXCLUSIVELY these hex values
5
- export const C = {
6
- BLACK: '#000000',
7
- BLUE: '#0000CD',
8
- RED: '#CD0000',
9
- MAGENTA: '#CD00CD',
10
- GREEN: '#00CD00',
11
- CYAN: '#00CDCD',
12
- YELLOW: '#CDCD00',
13
- WHITE: '#CDCDCD',
14
- B_BLACK: '#000000',
15
- B_BLUE: '#0000FF',
16
- B_RED: '#FF0000',
17
- B_MAGENTA: '#FF00FF',
18
- B_GREEN: '#00FF00',
19
- B_CYAN: '#00FFFF',
20
- B_YELLOW: '#FFFF00',
21
- B_WHITE: '#FFFFFF',
22
- } as const
23
-
24
- export type SpectrumColor = typeof C[keyof typeof C]
package/src/renderer.ts DELETED
@@ -1,74 +0,0 @@
1
- import { CELL } from './palette.ts'
2
- import { getCharRow } from './font.ts'
3
-
4
- // Flip an 8×8 sprite horizontally
5
- export function mirrorSprite(src: Uint8Array): Uint8Array {
6
- const out = new Uint8Array(8)
7
- for (let r = 0; r < 8; r++) {
8
- let b = src[r], m = 0
9
- for (let i = 0; i < 8; i++) {
10
- if (b & (1 << i)) m |= (1 << (7 - i))
11
- }
12
- out[r] = m
13
- }
14
- return out
15
- }
16
-
17
- export function drawSprite(
18
- ctx: CanvasRenderingContext2D,
19
- sprite: Uint8Array,
20
- x: number, y: number,
21
- ink: string, paper: string,
22
- ): void {
23
- ctx.fillStyle = paper
24
- ctx.fillRect(x, y, CELL, CELL)
25
- ctx.fillStyle = ink
26
- for (let row = 0; row < 8; row++) {
27
- const byte = sprite[row]
28
- for (let bit = 0; bit < 8; bit++) {
29
- if (byte & (0x80 >> bit)) ctx.fillRect(x + bit, y + row, 1, 1)
30
- }
31
- }
32
- }
33
-
34
- export function drawChar(
35
- ctx: CanvasRenderingContext2D,
36
- code: number,
37
- x: number, y: number,
38
- ink: string, paper?: string,
39
- ): void {
40
- if (paper !== undefined) {
41
- ctx.fillStyle = paper
42
- ctx.fillRect(x, y, CELL, CELL)
43
- }
44
- ctx.fillStyle = ink
45
- for (let row = 0; row < 8; row++) {
46
- const byte = getCharRow(code, row)
47
- for (let bit = 0; bit < 8; bit++) {
48
- if (byte & (0x80 >> bit)) ctx.fillRect(x + bit, y + row, 1, 1)
49
- }
50
- }
51
- }
52
-
53
- export function drawText(
54
- ctx: CanvasRenderingContext2D,
55
- text: string,
56
- x: number, y: number,
57
- ink: string, paper?: string,
58
- ): void {
59
- for (let i = 0; i < text.length; i++) {
60
- drawChar(ctx, text.charCodeAt(i), x + i * CELL, y, ink, paper)
61
- }
62
- }
63
-
64
- // cols = total character columns of the canvas (e.g. 32 for standard Spectrum)
65
- export function drawTextCentered(
66
- ctx: CanvasRenderingContext2D,
67
- text: string,
68
- y: number,
69
- cols: number,
70
- ink: string, paper?: string,
71
- ): void {
72
- const x = Math.floor((cols - text.length) / 2) * CELL
73
- drawText(ctx, text, x, y, ink, paper)
74
- }
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2023",
4
- "module": "esnext",
5
- "lib": ["ES2023", "DOM"],
6
- "moduleResolution": "bundler",
7
- "allowImportingTsExtensions": true,
8
- "verbatimModuleSyntax": true,
9
- "moduleDetection": "force",
10
- "noEmit": true,
11
- "strict": true,
12
- "noUnusedLocals": true,
13
- "noUnusedParameters": true
14
- },
15
- "include": ["src"]
16
- }