create-gamenative-app 0.1.5 → 0.1.6

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.
Files changed (50) hide show
  1. package/bin/create.js +145 -32
  2. package/dist/scripts/Game.d.ts +11 -0
  3. package/dist/scripts/Game.d.ts.map +1 -0
  4. package/dist/scripts/Game.js +83 -0
  5. package/dist/scripts/Game.js.map +1 -0
  6. package/dist/scripts/Graphics.d.ts +8 -0
  7. package/dist/scripts/Graphics.d.ts.map +1 -0
  8. package/dist/scripts/Graphics.js +78 -0
  9. package/dist/scripts/Graphics.js.map +1 -0
  10. package/dist/scripts/Input.d.ts +55 -0
  11. package/dist/scripts/Input.d.ts.map +1 -0
  12. package/dist/scripts/Input.js +69 -0
  13. package/dist/scripts/Input.js.map +1 -0
  14. package/dist/scripts/config.d.ts +12 -0
  15. package/dist/scripts/config.d.ts.map +1 -0
  16. package/dist/scripts/config.js +14 -0
  17. package/dist/scripts/config.js.map +1 -0
  18. package/dist/scripts/icon.d.ts +7 -0
  19. package/dist/scripts/icon.d.ts.map +1 -0
  20. package/dist/scripts/icon.js +16 -0
  21. package/dist/scripts/icon.js.map +1 -0
  22. package/dist/scripts/index.d.ts +7 -0
  23. package/dist/scripts/index.d.ts.map +1 -0
  24. package/dist/scripts/index.js +3 -0
  25. package/dist/scripts/index.js.map +1 -0
  26. package/dist/scripts/main.d.ts +2 -0
  27. package/dist/scripts/main.d.ts.map +1 -0
  28. package/dist/scripts/main.js +33 -0
  29. package/dist/scripts/main.js.map +1 -0
  30. package/dist/scripts/types.d.ts +33 -0
  31. package/dist/scripts/types.d.ts.map +1 -0
  32. package/dist/scripts/types.js +2 -0
  33. package/dist/scripts/types.js.map +1 -0
  34. package/dist/src/games/ExampleGame.d.ts +11 -0
  35. package/dist/src/games/ExampleGame.d.ts.map +1 -0
  36. package/dist/src/games/ExampleGame.js +36 -0
  37. package/dist/src/games/ExampleGame.js.map +1 -0
  38. package/package.json +7 -7
  39. package/{src → scripts}/config.ts +1 -1
  40. package/{src → scripts}/main.ts +1 -1
  41. package/src/assets/icon.png +0 -0
  42. package/src/games/ExampleGame.ts +2 -2
  43. package/tsconfig.json +1 -1
  44. /package/{src → scripts}/Game.ts +0 -0
  45. /package/{src → scripts}/Graphics.ts +0 -0
  46. /package/{src → scripts}/Input.ts +0 -0
  47. /package/{src → scripts}/icon.ts +0 -0
  48. /package/{src → scripts}/index.ts +0 -0
  49. /package/{src → scripts}/pngjs.d.ts +0 -0
  50. /package/{src → scripts}/types.ts +0 -0
package/bin/create.js CHANGED
@@ -45,15 +45,15 @@ async function scaffold(projectName, parentDir) {
45
45
  pngjsDts,
46
46
  copyConfigJs,
47
47
  ] = await Promise.all([
48
- copyFrameworkFile('src/main.ts'),
49
- copyFrameworkFile('src/config.ts'),
50
- copyFrameworkFile('src/Game.ts'),
51
- copyFrameworkFile('src/Input.ts'),
52
- copyFrameworkFile('src/Graphics.ts'),
53
- copyFrameworkFile('src/types.ts'),
54
- copyFrameworkFile('src/index.ts'),
55
- copyFrameworkFile('src/icon.ts'),
56
- copyFrameworkFile('src/pngjs.d.ts'),
48
+ copyFrameworkFile('scripts/main.ts'),
49
+ copyFrameworkFile('scripts/config.ts'),
50
+ copyFrameworkFile('scripts/Game.ts'),
51
+ copyFrameworkFile('scripts/Input.ts'),
52
+ copyFrameworkFile('scripts/Graphics.ts'),
53
+ copyFrameworkFile('scripts/types.ts'),
54
+ copyFrameworkFile('scripts/index.ts'),
55
+ copyFrameworkFile('scripts/icon.ts'),
56
+ copyFrameworkFile('scripts/pngjs.d.ts'),
57
57
  readFile(join(FRAMEWORK_ROOT, 'scripts/copy-config.js'), 'utf-8'),
58
58
  ])
59
59
 
@@ -72,11 +72,11 @@ async function scaffold(projectName, parentDir) {
72
72
  version: '0.1.0',
73
73
  description: `Game built with GameNative`,
74
74
  type: 'module',
75
- main: 'dist/main.js',
75
+ main: 'dist/scripts/main.js',
76
76
  scripts: {
77
- dev: 'cross-env NODE_ENV=development tsx src/main.ts',
77
+ dev: 'cross-env NODE_ENV=development tsx scripts/main.ts',
78
78
  build: 'tsc',
79
- start: 'node dist/main.js',
79
+ start: 'node dist/scripts/main.js',
80
80
  'build:exe': 'npm run build && node scripts/copy-config.js && pkg . --output release/' + name + '.exe',
81
81
  },
82
82
  dependencies: {
@@ -93,8 +93,8 @@ async function scaffold(projectName, parentDir) {
93
93
  },
94
94
  engines: { node: '>=18' },
95
95
  pkg: {
96
- scripts: 'dist/main.js',
97
- assets: ['node_modules/@kmamal/sdl/**', 'node_modules/@kmamal/gl/**', 'dist/games/**'],
96
+ scripts: 'dist/scripts/main.js',
97
+ assets: ['node_modules/@kmamal/sdl/**', 'node_modules/@kmamal/gl/**', 'dist/src/games/**'],
98
98
  targets: ['node18-win-x64'],
99
99
  },
100
100
  }
@@ -114,38 +114,151 @@ async function scaffold(projectName, parentDir) {
114
114
  esModuleInterop: true,
115
115
  forceConsistentCasingInFileNames: true,
116
116
  },
117
- include: ['src/**/*.ts'],
117
+ include: ['scripts/**/*.ts', 'src/**/*.ts'],
118
118
  exclude: ['node_modules', 'dist'],
119
119
  }
120
120
 
121
- const gameTemplate = `import { createDraw2D, SCANCODE } from '../index.js'
122
- import type { GameContext, IGame } from '../types.js'
121
+ const gameTemplate = `import { SCANCODE } from '../../scripts/index.js'
122
+ import type { GameContext, IGame } from '../../scripts/types.js'
123
+
124
+ const VERT = \`
125
+ attribute vec3 a_position;
126
+ uniform mat4 u_mvp;
127
+ void main() {
128
+ gl_Position = u_mvp * vec4(a_position, 1.0);
129
+ }
130
+ \`
131
+
132
+ const FRAG = \`
133
+ precision mediump float;
134
+ uniform vec3 u_color;
135
+ void main() {
136
+ gl_FragColor = vec4(u_color, 1.0);
137
+ }
138
+ \`
139
+
140
+ function mul4(a: number[], b: number[]): number[] {
141
+ const out: number[] = []
142
+ for (let col = 0; col < 4; col++) {
143
+ for (let row = 0; row < 4; row++) {
144
+ out[col * 4 + row] = a[0 * 4 + row] * b[col * 4 + 0] + a[1 * 4 + row] * b[col * 4 + 1] + a[2 * 4 + row] * b[col * 4 + 2] + a[3 * 4 + row] * b[col * 4 + 3]
145
+ }
146
+ }
147
+ return out
148
+ }
149
+
150
+ function perspective(fovY: number, aspect: number, near: number, far: number): number[] {
151
+ const f = 1 / Math.tan(fovY / 2)
152
+ const nf = 1 / (near - far)
153
+ return [f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (far + near) * nf, -1, 0, 0, 2 * far * near * nf, 0]
154
+ }
155
+
156
+ function rotateY(t: number): number[] {
157
+ const c = Math.cos(t), s = Math.sin(t)
158
+ return [c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1]
159
+ }
160
+
161
+ function rotateX(t: number): number[] {
162
+ const c = Math.cos(t), s = Math.sin(t)
163
+ return [1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1]
164
+ }
165
+
166
+ function translate(x: number, y: number, z: number): number[] {
167
+ return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1]
168
+ }
169
+
170
+ const CUBE_POSITIONS = new Float32Array([
171
+ -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
172
+ -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
173
+ -0.5, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5,
174
+ 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -0.5,
175
+ -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
176
+ -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5,
177
+ ])
123
178
 
124
179
  interface Game extends IGame {
125
180
  ctx: GameContext | null
126
- draw2d: ReturnType<typeof createDraw2D> | null
181
+ gl: WebGLRenderingContext | null
182
+ program: WebGLProgram | null
183
+ buf: WebGLBuffer | null
184
+ uMvp: WebGLUniformLocation | null
185
+ uColor: WebGLUniformLocation | null
186
+ time: number
127
187
  }
128
188
 
129
189
  const game: Game = {
130
190
  ctx: null,
131
- draw2d: null,
191
+ gl: null,
192
+ program: null,
193
+ buf: null,
194
+ uMvp: null,
195
+ uColor: null,
196
+ time: 0,
132
197
 
133
198
  async init(ctx: GameContext) {
134
199
  this.ctx = ctx
135
- this.draw2d = createDraw2D(ctx.gl)
200
+ const gl = ctx.gl
201
+ this.gl = gl
202
+ const vs = gl.createShader(gl.VERTEX_SHADER)!
203
+ gl.shaderSource(vs, VERT)
204
+ gl.compileShader(vs)
205
+ if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(vs) ?? 'vert')
206
+ const fs = gl.createShader(gl.FRAGMENT_SHADER)!
207
+ gl.shaderSource(fs, FRAG)
208
+ gl.compileShader(fs)
209
+ if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(fs) ?? 'frag')
210
+ const program = gl.createProgram()!
211
+ gl.attachShader(program, vs)
212
+ gl.attachShader(program, fs)
213
+ gl.linkProgram(program)
214
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) throw new Error(gl.getProgramInfoLog(program) ?? 'link')
215
+ this.program = program
216
+ const buf = gl.createBuffer()!
217
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf)
218
+ gl.bufferData(gl.ARRAY_BUFFER, CUBE_POSITIONS, gl.STATIC_DRAW)
219
+ this.buf = buf
220
+ this.uMvp = gl.getUniformLocation(program, 'u_mvp')!
221
+ this.uColor = gl.getUniformLocation(program, 'u_color')!
222
+ gl.enable(gl.DEPTH_TEST)
223
+ gl.depthFunc(gl.LEQUAL)
136
224
  },
137
225
 
138
226
  update(dt: number) {
227
+ this.time += dt
139
228
  if (this.ctx?.input.isKeyDown(SCANCODE.Escape)) process.exit(0)
140
229
  },
141
230
 
142
231
  draw() {
143
- this.draw2d?.clear(0.08, 0.08, 0.12, 1)
144
- this.draw2d?.fillRect(100, 100, 120, 80, 0.2, 0.5, 0.9, 1)
232
+ const gl = this.gl!
233
+ const w = this.ctx!.width
234
+ const h = this.ctx!.height
235
+ gl.viewport(0, 0, w, h)
236
+ gl.clearColor(0.06, 0.06, 0.1, 1)
237
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
238
+ const aspect = w / h
239
+ const proj = perspective(Math.PI / 4, aspect, 0.1, 10)
240
+ const view = translate(0, 0, -2.5)
241
+ const model = mul4(rotateY(this.time), rotateX(this.time * 0.7))
242
+ const mvp = mul4(mul4(proj, view), model)
243
+ gl.useProgram(this.program!)
244
+ gl.uniformMatrix4fv(this.uMvp!, false, new Float32Array(mvp))
245
+ gl.uniform3f(this.uColor!, 0.25, 0.5, 0.9)
246
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.buf!)
247
+ const loc = gl.getAttribLocation(this.program!, 'a_position')
248
+ gl.enableVertexAttribArray(loc)
249
+ gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0)
250
+ gl.drawArrays(gl.TRIANGLE_FAN, 0, 4)
251
+ gl.drawArrays(gl.TRIANGLE_FAN, 4, 4)
252
+ gl.drawArrays(gl.TRIANGLE_FAN, 8, 4)
253
+ gl.drawArrays(gl.TRIANGLE_FAN, 12, 4)
254
+ gl.drawArrays(gl.TRIANGLE_FAN, 16, 4)
255
+ gl.drawArrays(gl.TRIANGLE_FAN, 20, 4)
145
256
  },
146
257
 
147
258
  dispose() {
148
- this.draw2d?.dispose()
259
+ const gl = this.gl
260
+ if (gl && this.buf) gl.deleteBuffer(this.buf)
261
+ if (gl && this.program) gl.deleteProgram(this.program)
149
262
  },
150
263
  }
151
264
 
@@ -156,15 +269,15 @@ export default game
156
269
  writeFile(join(projectPath, 'package.json'), JSON.stringify(packageJson, null, 2)),
157
270
  writeFile(join(projectPath, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2)),
158
271
  writeFile(join(projectPath, 'game.config.json'), JSON.stringify(gameConfig, null, 2)),
159
- writeFile(join(src, 'main.ts'), mainTs),
160
- writeFile(join(src, 'config.ts'), configTs),
161
- writeFile(join(src, 'Game.ts'), gameTs),
162
- writeFile(join(src, 'Input.ts'), inputTs),
163
- writeFile(join(src, 'Graphics.ts'), graphicsTs),
164
- writeFile(join(src, 'types.ts'), typesTs),
165
- writeFile(join(src, 'index.ts'), indexTs),
166
- writeFile(join(src, 'icon.ts'), iconTs),
167
- writeFile(join(src, 'pngjs.d.ts'), pngjsDts),
272
+ writeFile(join(scripts, 'main.ts'), mainTs),
273
+ writeFile(join(scripts, 'config.ts'), configTs),
274
+ writeFile(join(scripts, 'Game.ts'), gameTs),
275
+ writeFile(join(scripts, 'Input.ts'), inputTs),
276
+ writeFile(join(scripts, 'Graphics.ts'), graphicsTs),
277
+ writeFile(join(scripts, 'types.ts'), typesTs),
278
+ writeFile(join(scripts, 'index.ts'), indexTs),
279
+ writeFile(join(scripts, 'icon.ts'), iconTs),
280
+ writeFile(join(scripts, 'pngjs.d.ts'), pngjsDts),
168
281
  writeFile(join(games, 'Game.ts'), gameTemplate),
169
282
  writeFile(join(scripts, 'copy-config.js'), copyConfigJs),
170
283
  ])
@@ -0,0 +1,11 @@
1
+ import sdl from '@kmamal/sdl';
2
+ import type { IGame, GameConfig } from './types.js';
3
+ import { createInput } from './Input.js';
4
+ /**
5
+ * Runs an IGame: creates SDL window + WebGL context, drives update/draw loop, handles resize and close.
6
+ */
7
+ export declare function run(game: IGame, config?: GameConfig): Promise<void>;
8
+ export type { IGame, GameConfig };
9
+ export { sdl, createInput };
10
+ export { SCANCODE } from './Input.js';
11
+ //# sourceMappingURL=Game.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Game.d.ts","sourceRoot":"","sources":["../../scripts/Game.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,aAAa,CAAA;AAG7B,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAe,MAAM,YAAY,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAaxC;;GAEG;AACH,wBAAsB,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAwE7E;AAED,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;AACjC,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAA;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,83 @@
1
+ import sdl from '@kmamal/sdl';
2
+ import glPkg from '@kmamal/gl';
3
+ import { createInput } from './Input.js';
4
+ const createGLContext = (typeof glPkg === 'function' ? glPkg : glPkg.default);
5
+ const DEFAULT_CONFIG = {
6
+ title: 'Game',
7
+ width: 800,
8
+ height: 600,
9
+ vsync: true,
10
+ resizable: true,
11
+ };
12
+ /**
13
+ * Runs an IGame: creates SDL window + WebGL context, drives update/draw loop, handles resize and close.
14
+ */
15
+ export async function run(game, config = {}) {
16
+ const opts = { ...DEFAULT_CONFIG, ...config };
17
+ const window = sdl.video.createWindow({
18
+ title: opts.title,
19
+ width: opts.width,
20
+ height: opts.height,
21
+ resizable: opts.resizable,
22
+ vsync: opts.vsync,
23
+ opengl: true,
24
+ });
25
+ if (opts.icon) {
26
+ try {
27
+ const { loadIcon } = await import('./icon.js');
28
+ await loadIcon(window, opts.icon);
29
+ }
30
+ catch {
31
+ // icon optional; ignore if loadIcon or file fails
32
+ }
33
+ }
34
+ let width = window.pixelWidth;
35
+ let height = window.pixelHeight;
36
+ const gl = createGLContext(width, height, { window: window.native });
37
+ const input = createInput(sdl);
38
+ const ctx = {
39
+ gl,
40
+ input,
41
+ get width() {
42
+ return width;
43
+ },
44
+ get height() {
45
+ return height;
46
+ },
47
+ };
48
+ if (game.init) {
49
+ await game.init(ctx, { ...opts, width, height });
50
+ }
51
+ window.on('resize', (e) => {
52
+ width = e.pixelWidth;
53
+ height = e.pixelHeight;
54
+ gl.viewport(0, 0, width, height);
55
+ });
56
+ let running = true;
57
+ window.on('close', () => {
58
+ running = false;
59
+ });
60
+ let lastTime = performance.now();
61
+ const maxDt = 0.1;
62
+ function loop() {
63
+ if (!running) {
64
+ if (game.dispose)
65
+ game.dispose();
66
+ window.destroy();
67
+ return;
68
+ }
69
+ const now = performance.now();
70
+ let dt = (now - lastTime) / 1000;
71
+ lastTime = now;
72
+ if (dt > maxDt)
73
+ dt = maxDt;
74
+ game.update(dt);
75
+ game.draw();
76
+ gl.swap();
77
+ setImmediate(loop);
78
+ }
79
+ setImmediate(loop);
80
+ }
81
+ export { sdl, createInput };
82
+ export { SCANCODE } from './Input.js';
83
+ //# sourceMappingURL=Game.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Game.js","sourceRoot":"","sources":["../../scripts/Game.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { WebGLRenderingContext as GLContext } from '@kmamal/gl';
2
+ export interface Draw2D {
3
+ clear(r: number, g: number, b: number, a?: number): void;
4
+ fillRect(x: number, y: number, w: number, h: number, r: number, g: number, b: number, a?: number): void;
5
+ dispose(): void;
6
+ }
7
+ export declare function createDraw2D(gl: GLContext): Draw2D;
8
+ //# sourceMappingURL=Graphics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Graphics.d.ts","sourceRoot":"","sources":["../../scripts/Graphics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAwBpE,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxD,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvG,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,MAAM,CA8DlD"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Minimal 2D helpers: clear, and draw solid-color quads with a simple shader.
3
+ * For anything else use the raw WebGL context.
4
+ */
5
+ const VERT = `
6
+ attribute vec2 a_position;
7
+ uniform vec2 u_resolution;
8
+ void main() {
9
+ vec2 clip = (a_position / u_resolution) * 2.0 - 1.0;
10
+ gl_Position = vec4(clip * vec2(1, -1), 0, 1);
11
+ }
12
+ `;
13
+ const FRAG = `
14
+ precision mediump float;
15
+ uniform vec4 u_color;
16
+ void main() {
17
+ gl_FragColor = u_color;
18
+ }
19
+ `;
20
+ export function createDraw2D(gl) {
21
+ const vs = gl.createShader(gl.VERTEX_SHADER);
22
+ gl.shaderSource(vs, VERT);
23
+ gl.compileShader(vs);
24
+ if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
25
+ throw new Error('vert: ' + gl.getShaderInfoLog(vs));
26
+ }
27
+ const fs = gl.createShader(gl.FRAGMENT_SHADER);
28
+ gl.shaderSource(fs, FRAG);
29
+ gl.compileShader(fs);
30
+ if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
31
+ throw new Error('frag: ' + gl.getShaderInfoLog(fs));
32
+ }
33
+ const program = gl.createProgram();
34
+ gl.attachShader(program, vs);
35
+ gl.attachShader(program, fs);
36
+ gl.linkProgram(program);
37
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
38
+ throw new Error('link: ' + gl.getProgramInfoLog(program));
39
+ }
40
+ const aPosition = gl.getAttribLocation(program, 'a_position');
41
+ const uResolution = gl.getUniformLocation(program, 'u_resolution');
42
+ const uColor = gl.getUniformLocation(program, 'u_color');
43
+ const buffer = gl.createBuffer();
44
+ const verts = new Float32Array(8);
45
+ return {
46
+ clear(r, g, b, a = 1) {
47
+ gl.clearColor(r, g, b, a);
48
+ gl.clear(gl.COLOR_BUFFER_BIT);
49
+ },
50
+ fillRect(x, y, w, h, r, g, b, a = 1) {
51
+ const x2 = x + w;
52
+ const y2 = y + h;
53
+ verts[0] = x;
54
+ verts[1] = y;
55
+ verts[2] = x2;
56
+ verts[3] = y;
57
+ verts[4] = x;
58
+ verts[5] = y2;
59
+ verts[6] = x2;
60
+ verts[7] = y2;
61
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
62
+ gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);
63
+ gl.useProgram(program);
64
+ gl.uniform2f(uResolution, gl.drawingBufferWidth, gl.drawingBufferHeight);
65
+ gl.uniform4f(uColor, r, g, b, a);
66
+ gl.enableVertexAttribArray(aPosition);
67
+ gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
68
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
69
+ },
70
+ dispose() {
71
+ gl.deleteProgram(program);
72
+ gl.deleteShader(vs);
73
+ gl.deleteShader(fs);
74
+ gl.deleteBuffer(buffer);
75
+ },
76
+ };
77
+ }
78
+ //# sourceMappingURL=Graphics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Graphics.js","sourceRoot":"","sources":["../../scripts/Graphics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Input state: keyboard and mouse. Read each frame in update().
3
+ * Keys use SDL scancode names; common ones: W, A, S, D, Up, Down, Left, Right, Space, Escape, etc.
4
+ */
5
+ type SDL = any;
6
+ export interface InputState {
7
+ readonly mouseX: number;
8
+ readonly mouseY: number;
9
+ readonly mouseLeft: boolean;
10
+ readonly mouseRight: boolean;
11
+ readonly mouseMiddle: boolean;
12
+ isKeyDown(scancode: number): boolean;
13
+ }
14
+ export declare function createInput(sdl: SDL): InputState;
15
+ /** SDL scancode constants for use with input.isKeyDown(sdl.SCANCODE.X). Use the sdl instance from run(). */
16
+ export declare const SCANCODE: {
17
+ readonly A: 4;
18
+ readonly B: 5;
19
+ readonly C: 6;
20
+ readonly D: 7;
21
+ readonly E: 8;
22
+ readonly F: 9;
23
+ readonly G: 10;
24
+ readonly H: 11;
25
+ readonly I: 12;
26
+ readonly J: 13;
27
+ readonly K: 14;
28
+ readonly L: 15;
29
+ readonly M: 16;
30
+ readonly N: 17;
31
+ readonly O: 18;
32
+ readonly P: 19;
33
+ readonly Q: 20;
34
+ readonly R: 21;
35
+ readonly S: 22;
36
+ readonly T: 23;
37
+ readonly U: 24;
38
+ readonly V: 25;
39
+ readonly W: 26;
40
+ readonly X: 27;
41
+ readonly Y: 28;
42
+ readonly Z: 29;
43
+ readonly Space: 44;
44
+ readonly Escape: 41;
45
+ readonly Up: 82;
46
+ readonly Down: 81;
47
+ readonly Left: 80;
48
+ readonly Right: 79;
49
+ readonly Enter: 40;
50
+ readonly Shift: 225;
51
+ readonly Ctrl: 224;
52
+ readonly Tab: 43;
53
+ };
54
+ export {};
55
+ //# sourceMappingURL=Input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../scripts/Input.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,KAAK,GAAG,GAAG,GAAG,CAAA;AAEd,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;CACrC;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,CAyBhD;AAED,4GAA4G;AAC5G,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCX,CAAA"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Input state: keyboard and mouse. Read each frame in update().
3
+ * Keys use SDL scancode names; common ones: W, A, S, D, Up, Down, Left, Right, Space, Escape, etc.
4
+ */
5
+ export function createInput(sdl) {
6
+ const keyboard = sdl.keyboard;
7
+ const mouse = sdl.mouse;
8
+ return {
9
+ get mouseX() {
10
+ return mouse.position.x;
11
+ },
12
+ get mouseY() {
13
+ return mouse.position.y;
14
+ },
15
+ get mouseLeft() {
16
+ return mouse.getButton(1);
17
+ },
18
+ get mouseRight() {
19
+ return mouse.getButton(3);
20
+ },
21
+ get mouseMiddle() {
22
+ return mouse.getButton(2);
23
+ },
24
+ isKeyDown(scancode) {
25
+ const state = keyboard.getState();
26
+ return !!(Array.isArray(state) ? state[scancode] : state[scancode]);
27
+ },
28
+ };
29
+ }
30
+ /** SDL scancode constants for use with input.isKeyDown(sdl.SCANCODE.X). Use the sdl instance from run(). */
31
+ export const SCANCODE = {
32
+ A: 4,
33
+ B: 5,
34
+ C: 6,
35
+ D: 7,
36
+ E: 8,
37
+ F: 9,
38
+ G: 10,
39
+ H: 11,
40
+ I: 12,
41
+ J: 13,
42
+ K: 14,
43
+ L: 15,
44
+ M: 16,
45
+ N: 17,
46
+ O: 18,
47
+ P: 19,
48
+ Q: 20,
49
+ R: 21,
50
+ S: 22,
51
+ T: 23,
52
+ U: 24,
53
+ V: 25,
54
+ W: 26,
55
+ X: 27,
56
+ Y: 28,
57
+ Z: 29,
58
+ Space: 44,
59
+ Escape: 41,
60
+ Up: 82,
61
+ Down: 81,
62
+ Left: 80,
63
+ Right: 79,
64
+ Enter: 40,
65
+ Shift: 225,
66
+ Ctrl: 224,
67
+ Tab: 43,
68
+ };
69
+ //# sourceMappingURL=Input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../scripts/Input.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,MAAM,UAAU,WAAW,CAAC,GAAQ;IAClC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAA;IAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAA;IAEvB,OAAO;QACL,IAAI,MAAM;YACR,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QACzB,CAAC;QACD,IAAI,MAAM;YACR,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;QACzB,CAAC;QACD,IAAI,SAAS;YACX,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;QAC3B,CAAC;QACD,IAAI,UAAU;YACZ,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;QAC3B,CAAC;QACD,IAAI,WAAW;YACb,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;QAC3B,CAAC;QACD,SAAS,CAAC,QAAgB;YACxB,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAA;YACjC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,KAAkC,CAAC,QAAQ,CAAC,CAAC,CAAA;QACnG,CAAC;KACF,CAAA;AACH,CAAC;AAED,4GAA4G;AAC5G,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,CAAC,EAAE,EAAE;IACL,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,EAAE;IACV,EAAE,EAAE,EAAE;IACN,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,GAAG;IACT,GAAG,EAAE,EAAE;CACC,CAAA"}
@@ -0,0 +1,12 @@
1
+ export interface AppConfig {
2
+ window?: {
3
+ title?: string;
4
+ width?: number;
5
+ height?: number;
6
+ icon?: string;
7
+ };
8
+ /** Game name (no extension). Resolved to src/games/<game>.ts in dev, dist/src/games/<game>.js in prod. */
9
+ game?: string;
10
+ }
11
+ export declare function loadAppConfig(): Promise<AppConfig>;
12
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../scripts/config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;IACD,0GAA0G;IAC1G,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAID,wBAAsB,aAAa,IAAI,OAAO,CAAC,SAAS,CAAC,CAQxD"}
@@ -0,0 +1,14 @@
1
+ import { readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ const CONFIG_FILENAME = 'game.config.json';
4
+ export async function loadAppConfig() {
5
+ const path = join(process.cwd(), CONFIG_FILENAME);
6
+ try {
7
+ const raw = await readFile(path, 'utf-8');
8
+ return JSON.parse(raw);
9
+ }
10
+ catch {
11
+ return {};
12
+ }
13
+ }
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../scripts/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAa3B,MAAM,eAAe,GAAG,kBAAkB,CAAA;AAE1C,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAA;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAc,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Load a PNG from path and set it as the window icon. Path can be absolute or relative to cwd.
3
+ */
4
+ export declare function loadIcon(window: {
5
+ setIcon: (w: number, h: number, stride: number, format: string, buffer: Buffer) => void;
6
+ }, iconPath: string): Promise<void>;
7
+ //# sourceMappingURL=icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../scripts/icon.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE;IAAE,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,EACnG,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -0,0 +1,16 @@
1
+ import { readFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ /**
4
+ * Load a PNG from path and set it as the window icon. Path can be absolute or relative to cwd.
5
+ */
6
+ export async function loadIcon(window, iconPath) {
7
+ const pngjs = await import('pngjs');
8
+ const PNG = pngjs.default?.PNG ?? pngjs.PNG;
9
+ const abs = join(process.cwd(), iconPath);
10
+ const buf = await readFile(abs);
11
+ const png = PNG.sync.read(buf);
12
+ const stride = png.width * 4;
13
+ const buffer = Buffer.from(png.data);
14
+ window.setIcon(png.width, png.height, stride, 'rgba32', buffer);
15
+ }
16
+ //# sourceMappingURL=icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.js","sourceRoot":"","sources":["../../scripts/icon.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,MAAmG,EACnG,QAAgB;IAEhB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAA;IACnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC,GAAG,CAAA;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAA;IACzC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;IAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,CAAA;IAC5B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACpC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;AACjE,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { run, sdl, createInput, SCANCODE } from './Game.js';
2
+ export type { IGame, GameConfig } from './Game.js';
3
+ export type { GameContext } from './types.js';
4
+ export type { InputState } from './Input.js';
5
+ export { createDraw2D } from './Graphics.js';
6
+ export type { Draw2D } from './Graphics.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../scripts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAC3D,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAClD,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,YAAY,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { run, sdl, createInput, SCANCODE } from './Game.js';
2
+ export { createDraw2D } from './Graphics.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../scripts/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAI3D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../scripts/main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ import { pathToFileURL } from 'url';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { run } from './Game.js';
5
+ import { loadAppConfig } from './config.js';
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ async function main() {
8
+ const appConfig = await loadAppConfig();
9
+ const gameName = appConfig.game ?? 'ExampleGame';
10
+ const isDev = process.env.NODE_ENV === 'development';
11
+ const isPkg = typeof process.pkg !== 'undefined';
12
+ const gamePath = isPkg || !isDev
13
+ ? join(__dirname, '..', 'src', 'games', `${gameName}.js`)
14
+ : join(process.cwd(), 'src', 'games', `${gameName}.ts`);
15
+ const href = pathToFileURL(gamePath).href;
16
+ const mod = await import(/* @vite-ignore */ href);
17
+ const game = mod.default;
18
+ if (!game || typeof game.update !== 'function' || typeof game.draw !== 'function') {
19
+ throw new Error(`Game "${gameName}" must export a default IGame (update/draw)`);
20
+ }
21
+ const windowOpts = appConfig.window ?? {};
22
+ await run(game, {
23
+ title: windowOpts.title ?? 'Game',
24
+ width: windowOpts.width ?? 800,
25
+ height: windowOpts.height ?? 600,
26
+ icon: windowOpts.icon,
27
+ });
28
+ }
29
+ main().catch((err) => {
30
+ console.error(err);
31
+ process.exit(1);
32
+ });
33
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../scripts/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzD,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,MAAM,aAAa,EAAE,CAAA;IACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,IAAI,aAAa,CAAA;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAA;IACpD,MAAM,KAAK,GAAG,OAAQ,OAA6B,CAAC,GAAG,KAAK,WAAW,CAAA;IACvE,MAAM,QAAQ,GACZ,KAAK,IAAI,CAAC,KAAK;QACb,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,KAAK,CAAC;QACzD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,KAAK,CAAC,CAAA;IAC3D,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAA;IAEzC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAA;IACjD,MAAM,IAAI,GAAU,GAAG,CAAC,OAAO,CAAA;IAC/B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,UAAU,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAClF,MAAM,IAAI,KAAK,CAAC,SAAS,QAAQ,6CAA6C,CAAC,CAAA;IACjF,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,IAAI,EAAE,CAAA;IACzC,MAAM,GAAG,CAAC,IAAI,EAAE;QACd,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,MAAM;QACjC,KAAK,EAAE,UAAU,CAAC,KAAK,IAAI,GAAG;QAC9B,MAAM,EAAE,UAAU,CAAC,MAAM,IAAI,GAAG;QAChC,IAAI,EAAE,UAAU,CAAC,IAAI;KACtB,CAAC,CAAA;AACJ,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,33 @@
1
+ import type { InputState } from './Input.js';
2
+ import type { WebGLRenderingContext as GLContext } from '@kmamal/gl';
3
+ /**
4
+ * Config passed when creating the game window.
5
+ */
6
+ export interface GameConfig {
7
+ title?: string;
8
+ width?: number;
9
+ height?: number;
10
+ vsync?: boolean;
11
+ resizable?: boolean;
12
+ /** Path to PNG for window/taskbar icon */
13
+ icon?: string;
14
+ }
15
+ /**
16
+ * Context passed to init and available each frame. width/height update on resize.
17
+ */
18
+ export interface GameContext {
19
+ gl: GLContext;
20
+ input: InputState;
21
+ width: number;
22
+ height: number;
23
+ }
24
+ /**
25
+ * Your game implements this. Framework calls init once, then update(dt) and draw() each frame.
26
+ */
27
+ export interface IGame {
28
+ init?(ctx: GameContext, config: GameConfig): void | Promise<void>;
29
+ update(dt: number): void;
30
+ draw(): void;
31
+ dispose?(): void;
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../scripts/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,KAAK,EAAE,qBAAqB,IAAI,SAAS,EAAE,MAAM,YAAY,CAAA;AAEpE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,SAAS,CAAA;IACb,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,CAAC,IAAI,IAAI,CAAA;CACjB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../scripts/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import { createDraw2D } from '../../scripts/index.js';
2
+ import type { GameContext, IGame } from '../../scripts/types.js';
3
+ interface ExampleGame extends IGame {
4
+ ctx: GameContext | null;
5
+ draw2d: ReturnType<typeof createDraw2D> | null;
6
+ x: number;
7
+ vx: number;
8
+ }
9
+ declare const game: ExampleGame;
10
+ export default game;
11
+ //# sourceMappingURL=ExampleGame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExampleGame.d.ts","sourceRoot":"","sources":["../../../src/games/ExampleGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAY,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAEhE,UAAU,WAAY,SAAQ,KAAK;IACjC,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,GAAG,IAAI,CAAA;IAC9C,CAAC,EAAE,MAAM,CAAA;IACT,EAAE,EAAE,MAAM,CAAA;CACX;AAED,QAAA,MAAM,IAAI,EAAE,WAoCX,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,36 @@
1
+ import { createDraw2D, SCANCODE } from '../../scripts/index.js';
2
+ const game = {
3
+ ctx: null,
4
+ draw2d: null,
5
+ x: 100,
6
+ vx: 120,
7
+ async init(ctx) {
8
+ this.ctx = ctx;
9
+ this.draw2d = createDraw2D(ctx.gl);
10
+ },
11
+ update(dt) {
12
+ const c = this.ctx;
13
+ this.x += this.vx * dt;
14
+ if (this.x < 0) {
15
+ this.x = 0;
16
+ this.vx = -this.vx;
17
+ }
18
+ if (this.x > c.width - 80) {
19
+ this.x = c.width - 80;
20
+ this.vx = -this.vx;
21
+ }
22
+ if (c.input.isKeyDown(SCANCODE.Escape)) {
23
+ process.exit(0);
24
+ }
25
+ },
26
+ draw() {
27
+ const d = this.draw2d;
28
+ d.clear(0.1, 0.1, 0.15, 1);
29
+ d.fillRect(this.x, 200, 80, 60, 0.2, 0.6, 0.9, 1);
30
+ },
31
+ dispose() {
32
+ this.draw2d?.dispose();
33
+ },
34
+ };
35
+ export default game;
36
+ //# sourceMappingURL=ExampleGame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExampleGame.js","sourceRoot":"","sources":["../../../src/games/ExampleGame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAU/D,MAAM,IAAI,GAAgB;IACxB,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,IAAI;IACZ,CAAC,EAAE,GAAG;IACN,EAAE,EAAE,GAAG;IAEP,KAAK,CAAC,IAAI,CAAC,GAAgB;QACzB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACpC,CAAC;IAED,MAAM,CAAC,EAAU;QACf,MAAM,CAAC,GAAG,IAAI,CAAC,GAAI,CAAA;QACnB,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;QACtB,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YACV,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAA;QACpB,CAAC;QACD,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAA;YACrB,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAA;QACpB,CAAC;QACD,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IAED,IAAI;QACF,MAAM,CAAC,GAAG,IAAI,CAAC,MAAO,CAAA;QACtB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QAC1B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IACnD,CAAC;IAED,OAAO;QACL,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAA;IACxB,CAAC;CACF,CAAA;AAED,eAAe,IAAI,CAAA"}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "create-gamenative-app",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Native TypeScript framework for desktop games — no game engine, just SDL + WebGL.",
5
5
  "type": "module",
6
- "main": "dist/main.js",
7
- "types": "dist/index.d.ts",
6
+ "main": "dist/scripts/main.js",
7
+ "types": "dist/scripts/index.d.ts",
8
8
  "scripts": {
9
- "dev": "cross-env NODE_ENV=development tsx src/main.ts",
9
+ "dev": "cross-env NODE_ENV=development tsx scripts/main.ts",
10
10
  "build": "tsc",
11
- "start": "node dist/main.js",
11
+ "start": "node dist/scripts/main.js",
12
12
  "build:exe": "npm run build && node scripts/copy-config.js && pkg . --output release/GameNative.exe",
13
13
  "example": "npm run build && npm start",
14
14
  "create": "node bin/create.js",
@@ -34,11 +34,11 @@
34
34
  "node": ">=18"
35
35
  },
36
36
  "pkg": {
37
- "scripts": "dist/main.js",
37
+ "scripts": "dist/scripts/main.js",
38
38
  "assets": [
39
39
  "node_modules/@kmamal/sdl/**",
40
40
  "node_modules/@kmamal/gl/**",
41
- "dist/games/**"
41
+ "dist/src/games/**"
42
42
  ],
43
43
  "targets": [
44
44
  "node18-win-x64"
@@ -8,7 +8,7 @@ export interface AppConfig {
8
8
  height?: number
9
9
  icon?: string
10
10
  }
11
- /** Game name (no extension). Resolved to src/games/<game>.ts in dev, dist/games/<game>.js in prod. */
11
+ /** Game name (no extension). Resolved to src/games/<game>.ts in dev, dist/src/games/<game>.js in prod. */
12
12
  game?: string
13
13
  }
14
14
 
@@ -14,7 +14,7 @@ async function main() {
14
14
  const isPkg = typeof (process as { pkg?: unknown }).pkg !== 'undefined'
15
15
  const gamePath =
16
16
  isPkg || !isDev
17
- ? join(__dirname, 'games', `${gameName}.js`)
17
+ ? join(__dirname, '..', 'src', 'games', `${gameName}.js`)
18
18
  : join(process.cwd(), 'src', 'games', `${gameName}.ts`)
19
19
  const href = pathToFileURL(gamePath).href
20
20
 
Binary file
@@ -1,5 +1,5 @@
1
- import { createDraw2D, SCANCODE } from '../index.js'
2
- import type { GameContext, IGame } from '../types.js'
1
+ import { createDraw2D, SCANCODE } from '../../scripts/index.js'
2
+ import type { GameContext, IGame } from '../../scripts/types.js'
3
3
 
4
4
  interface ExampleGame extends IGame {
5
5
  ctx: GameContext | null
package/tsconfig.json CHANGED
@@ -13,6 +13,6 @@
13
13
  "esModuleInterop": true,
14
14
  "forceConsistentCasingInFileNames": true
15
15
  },
16
- "include": ["src/**/*.ts"],
16
+ "include": ["scripts/**/*.ts","src/**/*.ts"],
17
17
  "exclude": ["node_modules", "dist"]
18
18
  }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes