@nixia/2d 0.0.2 → 0.0.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Aedan
3
+ Copyright (c) 2026 nixia.org
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,6 +1,92 @@
1
- # Nixia 2D Game Engine
1
+ # 🎮 NIXIA 2D Game Engine
2
+ > A lightning-fast, lightweight 2D game engine written entirely in TypeScript, engineered from the ground up to run seamlessly on low-power machines and resource-constrained devices.
2
3
 
3
- ## Getting started
4
+ ---
5
+
6
+ ## 🚀 Getting Started
7
+
8
+ Getting your first Nixia project up and running takes less than a minute. Follow these simple steps:
9
+
10
+ ### 1. Initialize your workspace
11
+ Create a new directory for your game and step into it:
4
12
  ```bash
5
- npm i -D @aedanmaki/nixia-2d
6
- ```
13
+ mkdir my-game
14
+ cd my-game
15
+ ```
16
+
17
+ ### 2. Install the core package
18
+ Install the NIXIA package as a development dependency (this automatically pulls in Vite and all other required toolchain dependencies):
19
+ ```bash
20
+ npm install -D @nixia/2d
21
+ ```
22
+
23
+ ### 3. Initialize your project structure
24
+ Run the built-in CLI tool to scaffold your configuration files and entry point:
25
+ ```bash
26
+ nixia init
27
+ ```
28
+
29
+ Once initialization is complete, you are ready to write code! Your application's main entry point is located at `src/main.ts`
30
+
31
+ ## 🏗️ Creating Your First Level
32
+ Levels represent the scenes or stages of your game. To create a new level, generate a new TypeScript file inside `src/levels/MyLevel.ts`, extend the core `Nixia.Level` class, and configure it:
33
+
34
+ ```ts
35
+ // src/levels/MyLevel.ts
36
+ import * as Nixia from '@nixia/2d';
37
+
38
+ export class MyLevel extends Nixia.Level {
39
+ constructor() {
40
+ super("MyLevel");
41
+ }
42
+ }
43
+ ```
44
+
45
+ Then in your `src/main.ts`, you can make this your default level by using the following code:
46
+ ```ts
47
+ // src/main.ts
48
+ import * as Nixia from '@nixia/2d';
49
+ import { MyLevel } from './levels/MyLevel';
50
+
51
+ // Preload your level
52
+ const myLevel = new MyLevel();
53
+
54
+ // Create a new Application
55
+ const app = new Nixia.Application();
56
+
57
+ // Set the default level to our custom level
58
+ app.setDefaultLevel(myLevel);
59
+
60
+ // Start the application
61
+ app.start();
62
+ ```
63
+
64
+ ## 👾 Creating Your First Actor
65
+ Actors represent game objects—or more specifically, active entities living inside a level. They handle components, custom game logic, rendering, physics, and more. You can create one like this:
66
+
67
+ ```ts
68
+ // src/actors/MyActor.ts
69
+ import * as Nixia from '@nixia/2d';
70
+
71
+ export class MyActor extends Nixai.Actor {
72
+ constructor() {
73
+ super("MyActor");
74
+ }
75
+ }
76
+ ```
77
+
78
+ You can add your Actor to your Level like this:
79
+ ```ts
80
+ // src/levels/MyLevel.ts
81
+ import * as Nixia from '@nixia/2d';
82
+ import { MyActor } from './actors/MyActor';
83
+
84
+ export class MyLevel extends Nixia.Level {
85
+ constructor() {
86
+ super("MyLevel");
87
+
88
+ // This both adds the actor to the scene and registers it with
89
+ // the game lifecycle.
90
+ this.root.add(new MyActor(this, this.app));
91
+ }
92
+ }
package/cli.js CHANGED
@@ -2,31 +2,6 @@
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
4
 
5
- const BASE_URL = "https://nixia-2d-cli.nakoyasoftware.com/components/";
6
-
7
- // Define all components in a single configuration array to maintain DRY principles
8
- const COMPONENTS = [
9
- { name: "index.html", dest: "index.html" },
10
- { name: "vite.config.ts", dest: "vite.config.ts" },
11
- { name: "tsconfig.json", dest: "tsconfig.json" },
12
- { name: "main.ts", dest: path.join("src", "main.ts") }
13
- ];
14
-
15
- /**
16
- * Generic helper function to download any file from the remote components repository.
17
- */
18
- async function downloadFile(filename) {
19
- try {
20
- const response = await fetch(`${BASE_URL}${filename}`);
21
- if (!response.ok) {
22
- throw new Error(`HTTP Error: ${response.status} ${response.statusText}`);
23
- }
24
- return await response.text();
25
- } catch (e) {
26
- throw new Error(`Failed to download '${filename}': ${e.message}`);
27
- }
28
- }
29
-
30
5
  async function runCli() {
31
6
  console.log('🔍 Running pre-flight environment checks...');
32
7
 
@@ -44,38 +19,79 @@ async function runCli() {
44
19
  }
45
20
  console.log('✅ Pre-flight checks passed successfully!');
46
21
 
47
- console.log('🚀 Downloading project components from remote server...');
48
- const downloadedContent = {};
49
-
50
- // Loop through our configuration array instead of writing duplicate functions
51
- for (let i = 0; i < COMPONENTS.length; i++) {
52
- const component = COMPONENTS[i];
53
- console.log(`📥 Downloading component ${i + 1} of ${COMPONENTS.length}: ${component.name}...`);
54
- downloadedContent[component.name] = await downloadFile(component.name);
55
- }
56
-
57
- console.log('💾 Writing files to disk...');
22
+ console.log('💾 Creating project structure and writing files locally...');
58
23
 
59
24
  // Ensure the src directory exists before writing nested files
60
25
  fs.mkdirSync("src", { recursive: true });
61
26
 
62
- // Write all downloaded files to their respective destinations
63
- for (const component of COMPONENTS) {
64
- let content = downloadedContent[component.name];
65
-
66
- // Pretty-print tsconfig.json so it looks clean and readable for humans
67
- if (component.name === "tsconfig.json") {
68
- try {
69
- const parsedJson = JSON.parse(content);
70
- content = JSON.stringify(parsedJson, null, 2);
71
- } catch (jsonError) {
72
- console.warn(`⚠️ Warning: Could not parse downloaded tsconfig.json as JSON. Writing raw text.`);
73
- }
74
- }
75
-
76
- fs.writeFileSync(component.dest, content);
77
- }
78
- console.log('✅ All components written to disk successfully!');
27
+ // 1. Write index.html
28
+ const indexHtmlContent = `<!DOCTYPE html>
29
+ <html lang="en">
30
+ <head>
31
+ <meta charset="utf-8">
32
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
33
+ <title>Nixia Engine Default Game</title>
34
+ </head>
35
+ <body>
36
+ <script type="module" src="./src/main.ts"></script>
37
+ </body>
38
+ </html>`;
39
+ fs.writeFileSync("index.html", indexHtmlContent);
40
+ console.log('📄 Created index.html successfully!');
41
+
42
+ // 2. Write tsconfig.json (Fixed the missing filename bug!)
43
+ const tsConfigData = {
44
+ "compilerOptions": {
45
+ "target": "ESNext",
46
+ "useDefineForClassFields": true,
47
+ "module": "ESNext",
48
+ "moduleResolution": "bundler",
49
+ "isolatedModules": true,
50
+ "strict": true,
51
+ "noUnusedLocals": true,
52
+ "noUnusedParameters": true,
53
+ "noImplicitReturns": true,
54
+ "skipLibCheck": true,
55
+ "resolveJsonModule": true,
56
+ "esModuleInterop": true,
57
+ "allowSyntheticDefaultImports": true,
58
+ "types": ["vite/client"]
59
+ },
60
+ "include": ["src/**/*", "vite.config.ts"]
61
+ };
62
+ fs.writeFileSync("tsconfig.json", JSON.stringify(tsConfigData, null, 2));
63
+ console.log('📄 Created tsconfig.json successfully!');
64
+
65
+ // 3. Write vite.config.ts
66
+ const viteConfigContent = `import { defineConfig } from 'vite';
67
+ import { viteSingleFile } from 'vite-plugin-singlefile';
68
+
69
+ export default defineConfig({
70
+ plugins: [viteSingleFile()],
71
+ build: {
72
+ target: 'esnext',
73
+ assetsInlineLimit: 100000000,
74
+ chunkSizeWarningLimit: 100000000,
75
+ cssCodeSplit: false,
76
+ rollupOptions: {
77
+ output: {
78
+ inlineDynamicImports: true,
79
+ },
80
+ },
81
+ },
82
+ });`;
83
+ fs.writeFileSync("vite.config.ts", viteConfigContent);
84
+ console.log('📄 Created vite.config.ts successfully!');
85
+
86
+ // 4. Write src/main.ts
87
+ const mainTsContent = `// This is the entry point for your game.
88
+ import * as Nixia from '@nixia/2d';
89
+
90
+ // Hello, world!`;
91
+ fs.writeFileSync(path.join("src", "main.ts"), mainTsContent);
92
+ console.log('📄 Created src/main.ts successfully!');
93
+
94
+ console.log('✅ All project components written to disk successfully!');
79
95
 
80
96
  console.log('📦 Updating package.json configuration...');
81
97
  const packageJsonPath = path.join("package.json");
package/index.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Nixia Engine</title>
6
+ <title>Nixia Engine Default Game</title>
7
7
  </head>
8
8
  <body>
9
9
  <script type="module" src="./src/main.ts"></script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nixia/2d",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "author": {
5
5
  "name": "Aedan Maki",
6
6
  "email": "aedanmaki@gmail.com"
@@ -10,6 +10,7 @@
10
10
  "type": "module",
11
11
  "main": "./src/index.ts",
12
12
  "module": "./src/index.ts",
13
+ "keywords": ["game-engine", "2d"],
13
14
  "exports": {
14
15
  ".": {
15
16
  "import": "./src/index.ts",
@@ -19,11 +20,14 @@
19
20
  "scripts": {
20
21
  "dev": "vite",
21
22
  "build": "vite build",
22
- "preview": "vite preview"
23
+ "preview": "vite preview",
24
+ "publish": "nixia publish"
23
25
  },
24
- "dependencies": {
26
+ "devDependencies": {
25
27
  "fs": "^0.0.1-security",
26
- "path": "^0.12.7",
28
+ "path": "^0.12.7"
29
+ },
30
+ "dependencies": {
27
31
  "typescript": "^7.0.2",
28
32
  "vite": "^8.3.5",
29
33
  "vite-plugin-singlefile": "^2.3.4"
package/publish.js ADDED
File without changes
package/src/core/Actor.ts CHANGED
@@ -1,14 +1,20 @@
1
1
  // src/core/Actor.ts
2
2
  import { Base } from "./Base";
3
+ import { ITickable } from "./ITickable";
3
4
 
4
5
  /**
5
6
  * Represents an Actor.
6
7
  */
7
- export class Actor extends Base {
8
+ export class Actor extends Base implements ITickable {
8
9
  /**
9
10
  * Creates a new Actor.
10
11
  */
11
12
  constructor() {
12
13
  super();
13
14
  }
15
+
16
+ /**
17
+ * Called on tick.
18
+ */
19
+ tick(dt: number): void {}
14
20
  }
@@ -1,5 +1,8 @@
1
1
  // src/core/Application.ts
2
2
  import { Base } from "./Base";
3
+ import { ITickable } from "./ITickable";
4
+ import { Renderer } from "./Renderer";
5
+ import { Level } from "./Level";
3
6
 
4
7
  /**
5
8
  * Represents an Application.
@@ -10,17 +13,44 @@ export class Application extends Base {
10
13
  */
11
14
  private wasInitialized: boolean = false;
12
15
 
16
+ /**
17
+ * If the game is ready.
18
+ */
19
+ private isReady: boolean = false;
20
+
21
+ /**
22
+ * Previous tick time.
23
+ */
24
+ private previousTickTime: number = Date.now();
25
+
26
+ /**
27
+ * An array of every tickable instance.
28
+ */
29
+ private tickableInstances: ITickable[] = [];
30
+
31
+ /**
32
+ * The renderer instance.
33
+ */
34
+ private renderer: Renderer;
35
+
36
+ /**
37
+ * The default level.
38
+ */
39
+ private defaultLevel!: Level;
40
+
13
41
  /**
14
42
  * Creates a new Application.
15
43
  */
16
44
  constructor() {
17
45
  super();
46
+
47
+ this.renderer = new Renderer();
18
48
  }
19
49
 
20
50
  /**
21
- * Initialize the Application.
51
+ * Starts the Application.
22
52
  */
23
- init() {
53
+ start() {
24
54
  if (this.wasInitialized) throw new Error('Application is already initialized.');
25
55
  this.wasInitialized = true;
26
56
 
@@ -37,6 +67,8 @@ export class Application extends Base {
37
67
  * Called when the game is ready.
38
68
  */
39
69
  private _ready() {
70
+ this.isReady = true;
71
+ if (!this.defaultLevel) throw new Error("No default level was assigned, cannot create game.");
40
72
  this.fire('ready');
41
73
 
42
74
  requestAnimationFrame(this._tick);
@@ -46,6 +78,28 @@ export class Application extends Base {
46
78
  * Called on tick.
47
79
  */
48
80
  private _tick = () => {
81
+ const now = Date.now();
82
+ const delta = now - this.previousTickTime;
83
+
84
+ const len = this.tickableInstances.length;
85
+ for (let i = 0; i < len; i++) {
86
+ const inst = this.tickableInstances[i];
87
+ inst.tick(delta);
88
+ }
89
+
90
+ this.renderer.clear();
91
+ this.renderer.draw();
92
+
93
+ this.previousTickTime = now;
94
+
49
95
  requestAnimationFrame(this._tick);
50
96
  }
97
+
98
+ /**
99
+ * Sets the default level.
100
+ */
101
+ setDefaultLevel(defaultLevel: Level) {
102
+ if (this.isReady) throw new Error("Cannot assign a default level when the game is already running.");
103
+ this.defaultLevel = defaultLevel;
104
+ }
51
105
  }
@@ -0,0 +1,5 @@
1
+ // src/core/ITickable.ts
2
+
3
+ export interface ITickable {
4
+ tick(dt: number): void;
5
+ }
package/src/core/Level.ts CHANGED
@@ -1,14 +1,27 @@
1
1
  // src/core/Level.ts
2
2
  import { Base } from "./Base";
3
+ import { ITickable } from "./ITickable";
3
4
 
4
5
  /**
5
6
  * Represents a Level.
6
7
  */
7
- export class Level extends Base {
8
+ export class Level extends Base implements ITickable {
9
+ /**
10
+ * The level name.
11
+ */
12
+ private name: string;
13
+
8
14
  /**
9
15
  * Creates a new Level.
10
16
  */
11
- constructor() {
17
+ constructor(name: string) {
12
18
  super();
19
+
20
+ this.name = name;
13
21
  }
22
+
23
+ /**
24
+ * Called on tick.
25
+ */
26
+ tick(dt: number): void {}
14
27
  }
@@ -0,0 +1,13 @@
1
+ // src/core/RenderBuffer.ts
2
+
3
+ /**
4
+ * Represents a Render Buffer.
5
+ */
6
+ export class RenderBuffer {
7
+ /**
8
+ * Creates a new Render Buffer.
9
+ */
10
+ constructor() {
11
+
12
+ }
13
+ }
@@ -5,10 +5,36 @@ import { Base } from "./Base";
5
5
  * Represents a Renderer.
6
6
  */
7
7
  export class Renderer extends Base {
8
+ /**
9
+ * The canvas element.
10
+ */
11
+ private canvas: HTMLCanvasElement;
12
+
8
13
  /**
9
14
  * Creates a new Renderer.
10
15
  */
11
16
  constructor() {
12
17
  super();
18
+
19
+ const canvas = document.createElement("canvas") as HTMLCanvasElement;
20
+ this.canvas = canvas;
21
+ this.canvas.width = 600;
22
+ this.canvas.height = 400;
23
+ this.canvas.style.border = "1px solid black";
24
+ document.body.appendChild(this.canvas);
25
+ }
26
+
27
+ /**
28
+ * Completely clears the canvas.
29
+ */
30
+ clear() {
31
+
32
+ }
33
+
34
+ /**
35
+ * Draws the buffers onto the canvas.
36
+ */
37
+ draw() {
38
+
13
39
  }
14
40
  }
package/src/index.ts CHANGED
@@ -3,5 +3,7 @@
3
3
  export * from './core/Actor';
4
4
  export * from './core/Application';
5
5
  export * from './core/Base';
6
+ export * from './core/ITickable';
6
7
  export * from './core/Level';
8
+ export * from './core/RenderBuffer';
7
9
  export * from './core/Renderer';
package/src/main.ts CHANGED
@@ -1,4 +1,8 @@
1
- import * as NIXIA from './index';
1
+ import * as Nixia from './index';
2
+ import { MyLevel } from './test/MyLevel';
2
3
 
3
- const app = new NIXIA.Application();
4
- app.init();
4
+ const app = new Nixia.Application();
5
+
6
+ app.setDefaultLevel(new MyLevel());
7
+
8
+ app.start();
package/cli.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "url": "https://nixia-2d-cli.nakoyasoftware.com/"
3
- }