@nice2dev/game-engine 1.1.6 → 1.1.7
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/CHANGELOG.md +48 -0
- package/dist/cjs/core/GameConfig.js +21 -7
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/release/MobileExport.js +45 -12
- package/dist/cjs/tutorials/content/Tutorials_T05_T08.js +33 -16
- package/dist/cjs/tutorials/content/Tutorials_T09_T11.js +79 -31
- package/dist/cjs/tutorials/content/Tutorials_T12_T15.js +46 -23
- package/dist/esm/core/GameConfig.js +21 -7
- package/dist/esm/release/MobileExport.js +45 -12
- package/dist/esm/tutorials/content/Tutorials_T05_T08.js +33 -16
- package/dist/esm/tutorials/content/Tutorials_T09_T11.js +79 -31
- package/dist/esm/tutorials/content/Tutorials_T12_T15.js +46 -23
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/input/index.d.ts +1 -1
- package/dist/types/legendary/index.d.ts +7 -7
- package/dist/types/procedural/index.d.ts +1 -1
- package/package.json +2 -2
|
@@ -160,7 +160,7 @@ const TUTORIAL_MULTIPLAYER_ONLINE = {
|
|
|
160
160
|
de: 'Verwende `SnapshotBuffer` zum Speichern von Spielzustand-Snapshots für Interpolation. Der Host sendet Snapshots, Clients interpolieren dazwischen.',
|
|
161
161
|
},
|
|
162
162
|
codeTemplate: '// Create snapshot buffer\nconst snapshots = ',
|
|
163
|
-
codeSolution:
|
|
163
|
+
codeSolution: 'const snapshots = new SnapshotBuffer(60);\n\n// Host creates and broadcasts snapshots\nconst snapshot = {\n tick: net.tick,\n timestamp: performance.now(),\n states: new Map(),\n};\nsnapshots.push(snapshot);\n\n// Client interpolates\nconst pair = snapshots.getInterpolationPair(serverTime);\nif (pair) {\n const [a, b] = pair;\n const t = (serverTime - a.timestamp) / (b.timestamp - a.timestamp);\n // interpolateState(stateA, stateB, t)\n}',
|
|
164
164
|
codeValidation: {
|
|
165
165
|
containsAll: ['SnapshotBuffer', 'push', 'getInterpolationPair'],
|
|
166
166
|
},
|
|
@@ -185,7 +185,7 @@ const TUTORIAL_MULTIPLAYER_ONLINE = {
|
|
|
185
185
|
de: 'Verwende `ClientPrediction` zum Speichern lokaler Eingaben und Abgleich nach Server-Bestätigung. Dies eliminiert Input-Lag für den lokalen Spieler.',
|
|
186
186
|
},
|
|
187
187
|
codeTemplate: '// Set up prediction\nconst prediction = ',
|
|
188
|
-
codeSolution:
|
|
188
|
+
codeSolution: 'const prediction = new ClientPrediction();\n\n// Every frame: record local input + simulated result\nprediction.addInput({\n tick: net.tick,\n inputActions: { moveRight: true, jump: false },\n resultPosition: { x: player.x + 5, y: player.y },\n});\n\n// When server confirms a tick:\nprediction.acknowledge(serverTick);\n\n// Replay unconfirmed inputs after correction\nconst pending = prediction.getPendingInputs();',
|
|
189
189
|
codeValidation: {
|
|
190
190
|
containsAll: ['ClientPrediction', 'addInput', 'acknowledge'],
|
|
191
191
|
},
|
|
@@ -210,10 +210,38 @@ const TUTORIAL_MULTIPLAYER_ONLINE = {
|
|
|
210
210
|
de: 'Warum ist clientseitige Vorhersage in Online-Spielen wichtig?',
|
|
211
211
|
},
|
|
212
212
|
quizOptions: [
|
|
213
|
-
{
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
{
|
|
214
|
+
id: 'a',
|
|
215
|
+
text: {
|
|
216
|
+
en: 'To reduce server load',
|
|
217
|
+
pl: 'Aby zmniejszyć obciążenie serwera',
|
|
218
|
+
de: 'Um die Serverlast zu reduzieren',
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: 'b',
|
|
223
|
+
text: {
|
|
224
|
+
en: 'To eliminate perceived input lag',
|
|
225
|
+
pl: 'Aby wyeliminować odczuwane opóźnienie inputu',
|
|
226
|
+
de: 'Um wahrgenommene Eingabeverzögerung zu eliminieren',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
id: 'c',
|
|
231
|
+
text: {
|
|
232
|
+
en: 'To improve graphics',
|
|
233
|
+
pl: 'Aby poprawić grafikę',
|
|
234
|
+
de: 'Um die Grafik zu verbessern',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: 'd',
|
|
239
|
+
text: {
|
|
240
|
+
en: 'To save bandwidth',
|
|
241
|
+
pl: 'Aby oszczędzić transfer',
|
|
242
|
+
de: 'Um Bandbreite zu sparen',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
217
245
|
],
|
|
218
246
|
quizCorrectId: 'b',
|
|
219
247
|
},
|
|
@@ -252,7 +280,7 @@ const TUTORIAL_MULTIPLAYER_ONLINE = {
|
|
|
252
280
|
de: 'Online-Mehrspieler fertig! 🎉',
|
|
253
281
|
},
|
|
254
282
|
content: {
|
|
255
|
-
en:
|
|
283
|
+
en: "You've learned how to build networked multiplayer games! You can now:\n• Connect peers via WebRTC\n• Create and manage lobby rooms\n• Synchronize game state with snapshots\n• Implement client-side prediction\n• Spawn/destroy entities across the network",
|
|
256
284
|
pl: 'Nauczyłeś się budować gry multiplayer online! Teraz potrafisz:\n• Łączyć peerów przez WebRTC\n• Tworzyć i zarządzać pokojami lobby\n• Synchronizować stan gry snapshotami\n• Implementować predykcję po stronie klienta\n• Tworzyć/niszczyć encje w sieci',
|
|
257
285
|
de: 'Du hast gelernt, vernetzte Multiplayer-Spiele zu bauen! Du kannst jetzt:\n• Peers über WebRTC verbinden\n• Lobby-Räume erstellen und verwalten\n• Spielzustand mit Snapshots synchronisieren\n• Clientseitige Vorhersage implementieren\n• Entities über das Netzwerk spawnen/zerstören',
|
|
258
286
|
},
|
|
@@ -293,7 +321,7 @@ const TUTORIAL_PROCEDURAL_WORLD = {
|
|
|
293
321
|
},
|
|
294
322
|
content: {
|
|
295
323
|
en: 'Procedural generation creates content using algorithms instead of manual design.\n\nYou will learn:\n• Seeded random numbers (reproducible worlds)\n• Perlin noise (natural-looking terrain)\n• Enemy wave scaling\n• Loot tables with weighted drops\n• Procedural pixel art sprites',
|
|
296
|
-
pl:
|
|
324
|
+
pl: "Generowanie proceduralne tworzy zawartość za pomocą algorytmów zamiast ręcznego projektowania.\n\nNauczysz się:\n• Losowość z seedem (odtwarzalne światy)\n• Szum Perlina (naturalnie wyglądający teren)\n• Skalowanie fal wrogów\n• Tabele łupów z ważonymi dropami\n• Proceduralne pikselo-artowe sprite'y",
|
|
297
325
|
de: 'Prozedurale Generierung erstellt Inhalte mit Algorithmen statt manueller Gestaltung.\n\nDu lernst:\n• Zufallszahlen mit Seed (reproduzierbare Welten)\n• Perlin-Noise (natürlich aussehende Landschaft)\n• Feindwellen-Skalierung\n• Loot-Tabellen mit gewichteten Drops\n• Prozedurale Pixel-Art-Sprites',
|
|
298
326
|
},
|
|
299
327
|
skippable: true,
|
|
@@ -339,7 +367,7 @@ const TUTORIAL_PROCEDURAL_WORLD = {
|
|
|
339
367
|
de: '`PerlinNoise` erzeugt glatte, natürlich aussehende Werte. Verwende `noise2D(x, y)` für Heightmaps und `fbm()` für detaillierte Landschaften.',
|
|
340
368
|
},
|
|
341
369
|
codeTemplate: '// Generate a height map\nconst noise = ',
|
|
342
|
-
codeSolution:
|
|
370
|
+
codeSolution: 'const noise = new PerlinNoise(42);\n\n// Generate a 64x64 terrain\nfor (let y = 0; y < 64; y++) {\n for (let x = 0; x < 64; x++) {\n // noise2D returns -1 to 1 — scale to 0-1\n const height = (noise.noise2D(x * 0.05, y * 0.05) + 1) * 0.5;\n\n // Use fbm for more detail (4 octaves)\n const detail = noise.fbm(x * 0.1, y * 0.1, 4);\n\n // Map to tile type\n if (height < 0.3) { /* water */ }\n else if (height < 0.6) { /* grass */ }\n else { /* mountain */ }\n }\n}',
|
|
343
371
|
codeValidation: {
|
|
344
372
|
containsAll: ['PerlinNoise', 'noise2D'],
|
|
345
373
|
},
|
|
@@ -405,7 +433,7 @@ const TUTORIAL_PROCEDURAL_WORLD = {
|
|
|
405
433
|
type: 'code',
|
|
406
434
|
title: {
|
|
407
435
|
en: 'Generate Pixel Art Sprites',
|
|
408
|
-
pl:
|
|
436
|
+
pl: "Generuj pikselo-artowe sprite'y",
|
|
409
437
|
de: 'Pixel-Art-Sprites generieren',
|
|
410
438
|
},
|
|
411
439
|
content: {
|
|
@@ -414,7 +442,7 @@ const TUTORIAL_PROCEDURAL_WORLD = {
|
|
|
414
442
|
de: '`ProceduralSprite` generiert symmetrische Pixel-Art aus einer Palette. Jeder Seed ergibt einen einzigartigen Charakter!',
|
|
415
443
|
},
|
|
416
444
|
codeTemplate: '// Generate a procedural sprite\nconst sprite = ',
|
|
417
|
-
codeSolution:
|
|
445
|
+
codeSolution: 'const sprite = new ProceduralSprite(8, 8, [\n { r: 0.2, g: 0.5, b: 1, a: 1 }, // blue\n { r: 0.8, g: 0.2, b: 0.3, a: 1 }, // red\n { r: 0.9, g: 0.9, b: 0.1, a: 1 }, // yellow\n]);\n\n// Generate with seed\nconst pixels = sprite.generate(42);\n// Each seed = unique character sprite!',
|
|
418
446
|
codeValidation: {
|
|
419
447
|
containsAll: ['ProceduralSprite', 'generate'],
|
|
420
448
|
},
|
|
@@ -439,10 +467,34 @@ const TUTORIAL_PROCEDURAL_WORLD = {
|
|
|
439
467
|
de: 'Was macht Perlin-Noise besser als rein zufällige Werte für Terrain?',
|
|
440
468
|
},
|
|
441
469
|
quizOptions: [
|
|
442
|
-
{
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
470
|
+
{
|
|
471
|
+
id: 'a',
|
|
472
|
+
text: {
|
|
473
|
+
en: "It's faster to compute",
|
|
474
|
+
pl: 'Jest szybszy do obliczenia',
|
|
475
|
+
de: 'Es ist schneller zu berechnen',
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
id: 'b',
|
|
480
|
+
text: {
|
|
481
|
+
en: 'It produces smooth, continuous gradients',
|
|
482
|
+
pl: 'Produkuje gładkie, ciągłe gradienty',
|
|
483
|
+
de: 'Es erzeugt glatte, kontinuierliche Gradienten',
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
id: 'c',
|
|
488
|
+
text: {
|
|
489
|
+
en: 'It uses less memory',
|
|
490
|
+
pl: 'Zużywa mniej pamięci',
|
|
491
|
+
de: 'Es verbraucht weniger Speicher',
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
id: 'd',
|
|
496
|
+
text: { en: "It's more random", pl: 'Jest bardziej losowy', de: 'Es ist zufälliger' },
|
|
497
|
+
},
|
|
446
498
|
],
|
|
447
499
|
quizCorrectId: 'b',
|
|
448
500
|
},
|
|
@@ -457,7 +509,7 @@ const TUTORIAL_PROCEDURAL_WORLD = {
|
|
|
457
509
|
},
|
|
458
510
|
content: {
|
|
459
511
|
en: 'You can now generate infinite, unique games! Skills learned:\n• Seeded random for reproducible worlds\n• Perlin noise for natural terrain\n• Wave scaling for enemy difficulty\n• Loot tables for balanced drops\n• Procedural pixel art sprites',
|
|
460
|
-
pl:
|
|
512
|
+
pl: "Teraz możesz generować nieskończone, unikalne gry! Umiejętności:\n• Losowość z seedem dla odtwarzalnych światów\n• Szum Perlina dla naturalnego terenu\n• Skalowanie fal dla trudności wrogów\n• Tabele łupów dla zbalansowanych dropów\n• Proceduralne pikselo-artowe sprite'y",
|
|
461
513
|
de: 'Du kannst jetzt unendliche, einzigartige Spiele generieren! Gelernte Fähigkeiten:\n• Seed-Zufall für reproduzierbare Welten\n• Perlin-Noise für natürliches Terrain\n• Wellen-Skalierung für Feind-Schwierigkeit\n• Loot-Tabellen für ausgewogene Drops\n• Prozedurale Pixel-Art-Sprites',
|
|
462
514
|
},
|
|
463
515
|
},
|
|
@@ -496,7 +548,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
496
548
|
de: 'Baue einen Platformer! 🏃',
|
|
497
549
|
},
|
|
498
550
|
content: {
|
|
499
|
-
en:
|
|
551
|
+
en: "In this tutorial you'll build a complete platformer game!\n\n• Player movement & acceleration\n• Jumping with coyote time\n• Double-jump & wall-slide\n• Dash mechanic\n• Enemy AI (patrol + chase)\n• Coins & collectibles\n• Level with tilemap\n\nLet's make Mario-like magic!",
|
|
500
552
|
pl: 'W tym tutorialu zbudujesz kompletną grę platformową!\n\n• Ruch gracza i przyspieszenie\n• Skakanie z coyote time\n• Podwójny skok i wall-slide\n• Mechanika dashu\n• AI wrogów (patrol + pościg)\n• Monety i zbieranie\n• Poziom z tilemapy\n\nZróbmy magię jak Mario!',
|
|
501
553
|
de: 'In diesem Tutorial baust du ein komplettes Plattformspiel!\n\n• Spielerbewegung & Beschleunigung\n• Springen mit Coyote-Time\n• Doppelsprung & Wall-Slide\n• Dash-Mechanik\n• Feind-KI (Patrouille + Verfolgung)\n• Münzen & Sammelobjekte\n• Level mit Tilemap\n\nLass uns Mario-Magie machen!',
|
|
502
554
|
},
|
|
@@ -517,7 +569,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
517
569
|
pl: 'Skonfiguruj encję gracza z komponentami Transform, Sprite, Collider2D i RigidBody2D.',
|
|
518
570
|
de: 'Erstelle die Spieler-Entity mit Transform, Sprite, Collider2D und RigidBody2D Komponenten.',
|
|
519
571
|
},
|
|
520
|
-
codeTemplate:
|
|
572
|
+
codeTemplate: '// Create the player\nconst player = world.createEntity();\n',
|
|
521
573
|
codeSolution: "const player = world.createEntity();\nworld.addComponent(player, 'Transform', { x: 100, y: 300, scaleX: 1, scaleY: 1, rotation: 0 });\nworld.addComponent(player, 'Sprite', { textureId: 'player', width: 32, height: 32 });\nworld.addComponent(player, 'Collider2D', { type: 'aabb', width: 28, height: 30, offsetX: 2, offsetY: 2, isTrigger: false });\nworld.addComponent(player, 'RigidBody2D', {\n velocityX: 0, velocityY: 0,\n mass: 1, gravityScale: 1,\n isKinematic: false, restitution: 0,\n});",
|
|
522
574
|
codeValidation: {
|
|
523
575
|
containsAll: ['createEntity', 'Transform', 'Collider2D', 'RigidBody2D'],
|
|
@@ -542,7 +594,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
542
594
|
pl: 'Ruch w platformerze używa przyspieszenia i hamowania dla płynnego wrażenia. Sprawdź akcje `moveRight` i `moveLeft` i przyłóż prędkość.',
|
|
543
595
|
de: 'Platformer-Bewegung nutzt Beschleunigung und Verzögerung für ein flüssiges Gefühl. Prüfe `moveRight` und `moveLeft` Aktionen und wende Geschwindigkeit an.',
|
|
544
596
|
},
|
|
545
|
-
codeTemplate:
|
|
597
|
+
codeTemplate: '// Movement system\nconst MOVE_SPEED = 200;\nconst ACCEL = 800;\nconst FRICTION = 600;\n',
|
|
546
598
|
codeSolution: "const MOVE_SPEED = 200;\nconst ACCEL = 800;\nconst FRICTION = 600;\n\nfunction updateMovement(input: InputManager, rb: any, dt: number) {\n let moveDir = 0;\n if (input.getAction('moveRight')) moveDir += 1;\n if (input.getAction('moveLeft')) moveDir -= 1;\n\n if (moveDir !== 0) {\n // Accelerate toward target speed\n rb.velocityX += moveDir * ACCEL * dt;\n // Clamp to max speed\n if (Math.abs(rb.velocityX) > MOVE_SPEED) {\n rb.velocityX = Math.sign(rb.velocityX) * MOVE_SPEED;\n }\n } else {\n // Apply friction\n if (Math.abs(rb.velocityX) > FRICTION * dt) {\n rb.velocityX -= Math.sign(rb.velocityX) * FRICTION * dt;\n } else {\n rb.velocityX = 0;\n }\n }\n}",
|
|
547
599
|
codeValidation: {
|
|
548
600
|
containsAll: ['ACCEL', 'FRICTION', 'velocityX', 'getAction'],
|
|
@@ -567,7 +619,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
567
619
|
pl: 'Coyote time pozwala graczowi skoczyć chwilę po opuszczeniu platformy — co sprawia, że gra jest bardziej wybaczalna. Śledź czas ostatniego kontaktu z podłożem.',
|
|
568
620
|
de: 'Coyote-Time erlaubt dem Spieler kurz nach Verlassen einer Plattform zu springen — das Spiel fühlt sich nachsichtiger an. Verfolge die letzte Bodenberührungs-Zeit.',
|
|
569
621
|
},
|
|
570
|
-
codeTemplate:
|
|
622
|
+
codeTemplate: '// Jump system with coyote time\nconst JUMP_FORCE = -350;\nconst COYOTE_TIME = 0.1; // 100ms grace period\n',
|
|
571
623
|
codeSolution: "const JUMP_FORCE = -350;\nconst COYOTE_TIME = 0.1; // 100ms grace period\nlet lastGroundedTime = 0;\nlet hasJumped = false;\n\nfunction updateJump(input: InputManager, rb: any, isGrounded: boolean, time: number) {\n if (isGrounded) {\n lastGroundedTime = time;\n hasJumped = false;\n }\n\n const canJump = !hasJumped && (time - lastGroundedTime) < COYOTE_TIME;\n\n if (input.getAction('jump') && canJump) {\n rb.velocityY = JUMP_FORCE;\n hasJumped = true;\n }\n\n // Variable jump height — release early = lower jump\n if (!input.getAction('jump') && rb.velocityY < 0) {\n rb.velocityY *= 0.5;\n }\n}",
|
|
572
624
|
codeValidation: {
|
|
573
625
|
containsAll: ['COYOTE_TIME', 'JUMP_FORCE', 'lastGroundedTime', 'canJump'],
|
|
@@ -592,7 +644,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
592
644
|
pl: 'Dodaj dodatkowy skok w powietrzu (podwójny skok) i pozwól graczowi powoli zsuwać się po ścianach gdy ich dotyka.',
|
|
593
645
|
de: 'Füge einen zusätzlichen Sprung in der Luft (Doppelsprung) hinzu und lass den Spieler langsam an Wänden herunterrutschen.',
|
|
594
646
|
},
|
|
595
|
-
codeTemplate:
|
|
647
|
+
codeTemplate: '// Double jump + wall slide\nconst MAX_AIR_JUMPS = 1;\nconst WALL_SLIDE_SPEED = 50;\n',
|
|
596
648
|
codeSolution: "const MAX_AIR_JUMPS = 1;\nconst WALL_SLIDE_SPEED = 50;\nlet airJumpsLeft = MAX_AIR_JUMPS;\n\nfunction updateAirMoves(input: InputManager, rb: any, isGrounded: boolean, isTouchingWall: boolean) {\n if (isGrounded) {\n airJumpsLeft = MAX_AIR_JUMPS;\n }\n\n // Double jump (only when not grounded)\n if (input.getAction('jump') && !isGrounded && airJumpsLeft > 0) {\n rb.velocityY = JUMP_FORCE;\n airJumpsLeft--;\n }\n\n // Wall slide — slow down fall when touching wall\n if (isTouchingWall && !isGrounded && rb.velocityY > 0) {\n rb.velocityY = Math.min(rb.velocityY, WALL_SLIDE_SPEED);\n }\n}",
|
|
597
649
|
codeValidation: {
|
|
598
650
|
containsAll: ['MAX_AIR_JUMPS', 'WALL_SLIDE_SPEED', 'airJumpsLeft'],
|
|
@@ -617,7 +669,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
617
669
|
pl: 'Dash daje graczowi nagły przypływ prędkości w aktualnym kierunku. Dodaj cooldown, żeby nie spamować.',
|
|
618
670
|
de: 'Ein Dash gibt dem Spieler einen Geschwindigkeitsschub in die aktuelle Richtung. Füge einen Cooldown hinzu.',
|
|
619
671
|
},
|
|
620
|
-
codeTemplate:
|
|
672
|
+
codeTemplate: '// Dash system\nconst DASH_SPEED = 500;\nconst DASH_DURATION = 0.15;\nconst DASH_COOLDOWN = 0.5;\n',
|
|
621
673
|
codeSolution: "const DASH_SPEED = 500;\nconst DASH_DURATION = 0.15;\nconst DASH_COOLDOWN = 0.5;\nlet dashTimer = 0;\nlet dashCooldown = 0;\nlet dashDir = 1;\n\nfunction updateDash(input: InputManager, rb: any, dt: number, facingRight: boolean) {\n dashCooldown = Math.max(0, dashCooldown - dt);\n\n if (input.getAction('dash') && dashCooldown <= 0 && dashTimer <= 0) {\n dashTimer = DASH_DURATION;\n dashCooldown = DASH_COOLDOWN;\n dashDir = facingRight ? 1 : -1;\n }\n\n if (dashTimer > 0) {\n dashTimer -= dt;\n rb.velocityX = DASH_SPEED * dashDir;\n rb.velocityY = 0; // freeze vertical during dash\n }\n}",
|
|
622
674
|
codeValidation: {
|
|
623
675
|
containsAll: ['DASH_SPEED', 'DASH_COOLDOWN', 'dashTimer'],
|
|
@@ -642,7 +694,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
642
694
|
pl: 'Utwórz wrogów patrolujących między dwoma punktami. Gdy gracz się zbliży, przechodzą w tryb pościgu!',
|
|
643
695
|
de: 'Erstelle Feinde, die zwischen zwei Punkten patrouillieren. Wenn der Spieler nah kommt, wechseln sie in den Verfolgungsmodus!',
|
|
644
696
|
},
|
|
645
|
-
codeTemplate:
|
|
697
|
+
codeTemplate: '// Enemy patrol + chase AI\nconst PATROL_SPEED = 60;\nconst CHASE_SPEED = 120;\nconst DETECT_RANGE = 150;\n',
|
|
646
698
|
codeSolution: "const PATROL_SPEED = 60;\nconst CHASE_SPEED = 120;\nconst DETECT_RANGE = 150;\n\nfunction updateEnemy(enemy: any, playerPos: any, dt: number) {\n const dx = playerPos.x - enemy.x;\n const dy = playerPos.y - enemy.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < DETECT_RANGE) {\n // Chase mode — move toward player\n const dir = dx > 0 ? 1 : -1;\n enemy.velocityX = CHASE_SPEED * dir;\n enemy.state = 'chase';\n } else {\n // Patrol mode — walk between patrolLeft and patrolRight\n if (enemy.x <= enemy.patrolLeft) enemy.patrolDir = 1;\n if (enemy.x >= enemy.patrolRight) enemy.patrolDir = -1;\n enemy.velocityX = PATROL_SPEED * enemy.patrolDir;\n enemy.state = 'patrol';\n }\n}",
|
|
647
699
|
codeValidation: {
|
|
648
700
|
containsAll: ['PATROL_SPEED', 'CHASE_SPEED', 'DETECT_RANGE'],
|
|
@@ -674,7 +726,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
674
726
|
containsAll: ['createEntity', 'isTrigger', 'destroyEntity'],
|
|
675
727
|
},
|
|
676
728
|
hint: {
|
|
677
|
-
en:
|
|
729
|
+
en: "Set isTrigger: true on coins so they don't push the player",
|
|
678
730
|
pl: 'Ustaw isTrigger: true na monetach, aby nie odpychały gracza',
|
|
679
731
|
de: 'Setze isTrigger: true auf Münzen, damit sie den Spieler nicht wegstoßen',
|
|
680
732
|
},
|
|
@@ -693,7 +745,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
693
745
|
pl: 'Użyj `Tilemap` do zbudowania poziomu. Zdefiniuj podłoże, platformy i ściany z kafelków.',
|
|
694
746
|
de: 'Verwende eine `Tilemap` um das Level zu bauen. Definiere Boden, Plattformen und Wände mit Kacheln.',
|
|
695
747
|
},
|
|
696
|
-
codeTemplate:
|
|
748
|
+
codeTemplate: '// Create the level tilemap\nconst level = new Tilemap(20, 15, 32);\n',
|
|
697
749
|
codeSolution: "const level = new Tilemap(20, 15, 32);\n\n// Add a ground layer\nlevel.addLayer('ground', 20, 15);\n\n// Fill the ground row\nlevel.fillRect('ground', 0, 14, 20, 1, 1); // bottom row = solid\n\n// Add some platforms\nlevel.setTile('ground', 5, 10, 1); // floating block\nlevel.setTile('ground', 6, 10, 1);\nlevel.setTile('ground', 7, 10, 1);\n\nlevel.fillRect('ground', 12, 8, 4, 1, 1); // higher platform\n\n// Check collisions with tilemap\nconst isSolid = level.isSolid(5, 14); // true — ground!",
|
|
698
750
|
codeValidation: {
|
|
699
751
|
containsAll: ['Tilemap', 'addLayer', 'fillRect'],
|
|
@@ -714,7 +766,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
714
766
|
de: 'Platformer fertig! 🎮',
|
|
715
767
|
},
|
|
716
768
|
content: {
|
|
717
|
-
en:
|
|
769
|
+
en: "Congratulations! You've built a complete platformer with:\n• Smooth acceleration-based movement\n• Jumping with coyote time\n• Double jump & wall slide\n• Dash mechanic\n• Enemy AI (patrol & chase)\n• Coins with trigger colliders\n• Tilemap level design\n\nChallenge: Add moving platforms and a boss fight!",
|
|
718
770
|
pl: 'Gratulacje! Zbudowałeś kompletnego platformera z:\n• Płynny ruch z przyspieszeniem\n• Skakanie z coyote time\n• Podwójny skok i wall-slide\n• Mechanika dashu\n• AI wrogów (patrol i pościg)\n• Monety z trigger koliderami\n• Design poziomu z tilemapy\n\nWyzwanie: Dodaj ruchome platformy i walkę z bossem!',
|
|
719
771
|
de: 'Herzlichen Glückwunsch! Du hast einen kompletten Platformer gebaut mit:\n• Flüssige beschleunigungsbasierte Bewegung\n• Springen mit Coyote-Time\n• Doppelsprung & Wall-Slide\n• Dash-Mechanik\n• Feind-KI (Patrouille & Verfolgung)\n• Münzen mit Trigger-Kollidern\n• Tilemap Level-Design\n\nHerausforderung: Füge bewegliche Plattformen und einen Bosskampf hinzu!',
|
|
720
772
|
},
|
|
@@ -725,11 +777,7 @@ const TUTORIAL_PLATFORMER = {
|
|
|
725
777
|
Convenience export
|
|
726
778
|
══════════════════════════════════════════════════════════════ */
|
|
727
779
|
function getTutorials_T09_T11() {
|
|
728
|
-
return [
|
|
729
|
-
TUTORIAL_MULTIPLAYER_ONLINE,
|
|
730
|
-
TUTORIAL_PROCEDURAL_WORLD,
|
|
731
|
-
TUTORIAL_PLATFORMER,
|
|
732
|
-
];
|
|
780
|
+
return [TUTORIAL_MULTIPLAYER_ONLINE, TUTORIAL_PROCEDURAL_WORLD, TUTORIAL_PLATFORMER];
|
|
733
781
|
}
|
|
734
782
|
|
|
735
783
|
export { TUTORIAL_MULTIPLAYER_ONLINE, TUTORIAL_PLATFORMER, TUTORIAL_PROCEDURAL_WORLD, getTutorials_T09_T11 };
|
|
@@ -39,7 +39,7 @@ const TUTORIAL_RPG = {
|
|
|
39
39
|
de: 'Baue dein eigenes RPG! ⚔️',
|
|
40
40
|
},
|
|
41
41
|
content: {
|
|
42
|
-
en:
|
|
42
|
+
en: "In this tutorial you'll build a classic top-down RPG!\n\n• Character stats (HP, MP, ATK, DEF, SPD)\n• XP and leveling system\n• Inventory and items\n• NPCs with dialogue\n• Turn-based battle system\n• Tilemap world with warps\n\nReady for an adventure?",
|
|
43
43
|
pl: 'W tym tutorialu zbudujesz klasyczne RPG z widokiem z góry!\n\n• Statystyki postaci (HP, MP, ATK, DEF, SPD)\n• System XP i poziomów\n• Ekwipunek i przedmioty\n• NPC z dialogami\n• System walki turowej\n• Świat z tilemapy z przejściami\n\nGotowy na przygodę?',
|
|
44
44
|
de: 'In diesem Tutorial baust du ein klassisches Top-Down-RPG!\n\n• Charakterwerte (HP, MP, ATK, DEF, SPD)\n• XP- und Levelsystem\n• Inventar und Items\n• NPCs mit Dialogen\n• Rundenbasiertes Kampfsystem\n• Tilemap-Welt mit Warps\n\nBereit für ein Abenteuer?',
|
|
45
45
|
},
|
|
@@ -56,7 +56,7 @@ const TUTORIAL_RPG = {
|
|
|
56
56
|
de: 'Charakterwerte & Leveling',
|
|
57
57
|
},
|
|
58
58
|
content: {
|
|
59
|
-
en:
|
|
59
|
+
en: "Define your hero's stats. Use the RPG template config for stat growth curves and XP requirements.",
|
|
60
60
|
pl: 'Zdefiniuj statystyki bohatera. Użyj konfiguracji szablonu RPG dla krzywych wzrostu statystyk i wymogów XP.',
|
|
61
61
|
de: 'Definiere die Werte deines Helden. Verwende die RPG-Template-Konfiguration für Wachstumskurven und XP-Anforderungen.',
|
|
62
62
|
},
|
|
@@ -110,7 +110,7 @@ const TUTORIAL_RPG = {
|
|
|
110
110
|
pl: 'Stwórz NPC z drzewami dialogów. Gracz może wybierać odpowiedzi, które rozgałęziają rozmowę.',
|
|
111
111
|
de: 'Erstelle NPCs mit Dialogbäumen. Spieler können Antworten wählen, die das Gespräch verzweigen.',
|
|
112
112
|
},
|
|
113
|
-
codeTemplate:
|
|
113
|
+
codeTemplate: '// Dialogue system\ninterface DialogNode {\n id: string;\n text: string;\n',
|
|
114
114
|
codeSolution: "interface DialogNode {\n id: string;\n text: string;\n speaker: string;\n choices?: { text: string; next: string; condition?: string }[];\n next?: string; // auto-advance to next node\n}\n\nconst innkeeperDialog: DialogNode[] = [\n {\n id: 'greet',\n speaker: 'Innkeeper',\n text: 'Welcome, traveler! Would you like to rest?',\n choices: [\n { text: 'Yes, I need rest. (10 gold)', next: 'rest' },\n { text: 'No thanks.', next: 'bye' },\n { text: 'Any rumors?', next: 'rumors' },\n ],\n },\n {\n id: 'rest',\n speaker: 'Innkeeper',\n text: 'Sleep well! *HP and MP fully restored*',\n next: 'greet',\n },\n {\n id: 'rumors',\n speaker: 'Innkeeper',\n text: 'I heard monsters in the eastern cave grew stronger...',\n next: 'greet',\n },\n {\n id: 'bye',\n speaker: 'Innkeeper',\n text: 'Safe travels!',\n },\n];",
|
|
115
115
|
codeValidation: {
|
|
116
116
|
containsAll: ['DialogNode', 'speaker', 'choices', 'next'],
|
|
@@ -161,7 +161,7 @@ const TUTORIAL_RPG = {
|
|
|
161
161
|
de: 'Erstelle mehrere Räume verbunden durch Warps. Verwende Tilemaps für jeden Bereich (Stadt, Wald, Höhle, Burg).',
|
|
162
162
|
},
|
|
163
163
|
requiredAction: 'create-world-map',
|
|
164
|
-
codeTemplate:
|
|
164
|
+
codeTemplate: '// Define world areas\nconst areas = [\n',
|
|
165
165
|
codeSolution: "const areas = [\n { id: 'town', name: 'Starter Town', tilemap: 'town-map', npcs: ['innkeeper', 'shopkeeper'] },\n { id: 'forest', name: 'Dark Forest', tilemap: 'forest-map', enemies: ['wolf', 'slime'] },\n { id: 'cave', name: 'Crystal Cave', tilemap: 'cave-map', enemies: ['bat', 'golem'] },\n { id: 'castle', name: 'Demon Castle', tilemap: 'castle-map', enemies: ['skeleton', 'demon-lord'] },\n];\n\nconst warps = [\n { from: 'town', to: 'forest', x: 19, y: 7 },\n { from: 'forest', to: 'cave', x: 15, y: 2 },\n { from: 'forest', to: 'town', x: 0, y: 7 },\n { from: 'cave', to: 'castle', x: 10, y: 0 },\n];",
|
|
166
166
|
codeValidation: {
|
|
167
167
|
containsAll: ['areas', 'warps', 'tilemap'],
|
|
@@ -199,7 +199,7 @@ const TUTORIAL_RPG = {
|
|
|
199
199
|
de: 'RPG fertig! 🏰',
|
|
200
200
|
},
|
|
201
201
|
content: {
|
|
202
|
-
en:
|
|
202
|
+
en: "Amazing! You've built a full RPG with:\n• Character stats & leveling\n• Inventory with rarity system\n• NPCs with branching dialogue\n• Turn-based combat\n• Multi-area world map with warps\n\nChallenge: Add a party system with 4 heroes!",
|
|
203
203
|
pl: 'Niesamowite! Zbudowałeś pełne RPG z:\n• Statystyki i poziomy postaci\n• Ekwipunek z systemem rzadkości\n• NPC z rozgałęzionymi dialogami\n• Walki turowe\n• Mapa świata z wieloma obszarami\n\nWyzwanie: Dodaj system drużyny z 4 bohaterami!',
|
|
204
204
|
de: 'Fantastisch! Du hast ein vollständiges RPG gebaut mit:\n• Charakterwerte & Leveling\n• Inventar mit Seltenheitssystem\n• NPCs mit verzweigten Dialogen\n• Rundenbasierter Kampf\n• Weltkarte mit mehreren Bereichen\n\nHerausforderung: Füge ein Gruppensystem mit 4 Helden hinzu!',
|
|
205
205
|
},
|
|
@@ -239,7 +239,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
239
239
|
de: 'Baue Tower Defense! 🗼',
|
|
240
240
|
},
|
|
241
241
|
content: {
|
|
242
|
-
en:
|
|
242
|
+
en: "In this tutorial you'll build a tower defense game!\n\n• Map with path for enemies\n• Tower types (arrow, cannon, ice, laser)\n• Enemy waves with scaling difficulty\n• Tower targeting modes\n• Upgrade system\n• Gold & economy\n\nDefend your base!",
|
|
243
243
|
pl: 'W tym tutorialu zbudujesz grę tower defense!\n\n• Mapa ze ścieżką dla wrogów\n• Typy wież (strzały, armata, lód, laser)\n• Fale wrogów ze skalującą się trudnością\n• Tryby celowania wież\n• System ulepszeń\n• Złoto i ekonomia\n\nBroń swojej bazy!',
|
|
244
244
|
de: 'In diesem Tutorial baust du ein Tower-Defense-Spiel!\n\n• Karte mit Feindpfad\n• Turmtypen (Pfeil, Kanone, Eis, Laser)\n• Feindwellen mit steigender Schwierigkeit\n• Turm-Zielmodi\n• Upgrade-System\n• Gold & Wirtschaft\n\nVerteidige deine Basis!',
|
|
245
245
|
},
|
|
@@ -286,7 +286,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
286
286
|
de: 'Feinde folgen einem vordefinierten Pfad vom Start zum Ende. Definiere Wegpunkte, zwischen denen Feinde laufen.',
|
|
287
287
|
},
|
|
288
288
|
codeTemplate: '// Enemy path waypoints\nconst path = [\n',
|
|
289
|
-
codeSolution:
|
|
289
|
+
codeSolution: 'const path = [\n { x: 0, y: 200 }, // start (left edge)\n { x: 200, y: 200 }, // turn down\n { x: 200, y: 400 },\n { x: 400, y: 400 }, // turn up\n { x: 400, y: 100 },\n { x: 600, y: 100 }, // final stretch\n { x: 600, y: 300 },\n { x: 800, y: 300 }, // end (base)\n];\n\nfunction moveAlongPath(enemy: any, dt: number) {\n const target = path[enemy.waypointIndex];\n const dx = target.x - enemy.x;\n const dy = target.y - enemy.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist < 5) {\n enemy.waypointIndex++;\n if (enemy.waypointIndex >= path.length) {\n // Enemy reached the base!\n enemy.reachedEnd = true;\n }\n } else {\n enemy.x += (dx / dist) * enemy.speed * dt;\n enemy.y += (dy / dist) * enemy.speed * dt;\n }\n}',
|
|
290
290
|
codeValidation: {
|
|
291
291
|
containsAll: ['path', 'waypointIndex', 'moveAlongPath'],
|
|
292
292
|
},
|
|
@@ -361,7 +361,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
361
361
|
de: 'Türme können aufgewertet werden für mehr Schaden und Reichweite. Verdiene Gold durch Feind-Kills. Verkaufe Türme für Rückerstattung.',
|
|
362
362
|
},
|
|
363
363
|
codeTemplate: '// Upgrade system\nlet gold = 200;\n',
|
|
364
|
-
codeSolution:
|
|
364
|
+
codeSolution: 'let gold = 200;\n\nfunction upgradeTower(tower: any): boolean {\n const upgradeCost = Math.floor(tower.cost * 0.75 * tower.level);\n if (gold < upgradeCost) return false;\n\n gold -= upgradeCost;\n tower.level++;\n tower.damage = Math.floor(tower.damage * 1.3);\n tower.range += 10;\n tower.fireRate *= 1.1;\n return true;\n}\n\nfunction sellTower(tower: any): number {\n const refund = Math.floor(tower.cost * 0.6);\n gold += refund;\n return refund;\n}\n\nfunction onEnemyKilled(enemy: any) {\n gold += enemy.goldReward;\n}',
|
|
365
365
|
codeValidation: {
|
|
366
366
|
containsAll: ['upgradeTower', 'sellTower', 'gold'],
|
|
367
367
|
},
|
|
@@ -381,7 +381,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
381
381
|
de: 'Tower Defense fertig! 🏆',
|
|
382
382
|
},
|
|
383
383
|
content: {
|
|
384
|
-
en:
|
|
384
|
+
en: "You've built a full tower defense game!\n• 4 tower types with different targeting\n• Enemy pathfinding along waypoints\n• Escalating wave system\n• Upgrade & sell mechanics\n• Gold economy\n\nChallenge: Add flying enemies that ignore the path!",
|
|
385
385
|
pl: 'Zbudowałeś kompletną grę tower defense!\n• 4 typy wież z różnym celowaniem\n• Pathfinding wrogów po waypointach\n• Eskalujący system fal\n• Mechaniki ulepszania i sprzedaży\n• Ekonomia złota\n\nWyzwanie: Dodaj latających wrogów ignorujących ścieżkę!',
|
|
386
386
|
de: 'Du hast ein komplettes Tower-Defense-Spiel gebaut!\n• 4 Turmtypen mit verschiedenem Zielen\n• Feind-Pathfinding entlang Wegpunkten\n• Eskalierendes Wellensystem\n• Upgrade- & Verkaufsmechaniken\n• Gold-Wirtschaft\n\nHerausforderung: Füge fliegende Feinde hinzu, die den Pfad ignorieren!',
|
|
387
387
|
},
|
|
@@ -421,7 +421,7 @@ const TUTORIAL_3D_GAME = {
|
|
|
421
421
|
de: 'Willkommen in 3D! 🎮',
|
|
422
422
|
},
|
|
423
423
|
content: {
|
|
424
|
-
en:
|
|
424
|
+
en: "In this tutorial you'll enter the third dimension!\n\n• Set up a 3D world (World3D)\n• Add meshes (cube, sphere, plane)\n• Lighting (directional, point, spot)\n• Camera controllers (FPS, orbit)\n• 3D physics (rigid bodies, colliders)\n• Character controller (walking, jumping)\n\nLet's go 3D!",
|
|
425
425
|
pl: 'W tym tutorialu wejdziesz w trzeci wymiar!\n\n• Skonfiguruj świat 3D (World3D)\n• Dodaj meshe (sześcian, sfera, płaszczyzna)\n• Oświetlenie (kierunkowe, punktowe, spot)\n• Kontrolery kamery (FPS, orbita)\n• Fizyka 3D (rigid body, kolidery)\n• Kontroler postaci (chodzenie, skakanie)\n\nWejdźmy w 3D!',
|
|
426
426
|
de: 'In diesem Tutorial betrittst du die dritte Dimension!\n\n• 3D-Welt einrichten (World3D)\n• Meshes hinzufügen (Würfel, Kugel, Ebene)\n• Beleuchtung (Richtung, Punkt, Spot)\n• Kamera-Controller (FPS, Orbit)\n• 3D-Physik (Starrkörper, Kollider)\n• Character-Controller (Laufen, Springen)\n\nAb in die 3. Dimension!',
|
|
427
427
|
},
|
|
@@ -588,7 +588,7 @@ const TUTORIAL_3D_GAME = {
|
|
|
588
588
|
de: '3D-Spiel fertig! 🌟',
|
|
589
589
|
},
|
|
590
590
|
content: {
|
|
591
|
-
en:
|
|
591
|
+
en: "You've built your first 3D game!\n• World3D scene with multiple objects\n• Primitive meshes (cube, sphere, plane)\n• Directional and point lighting\n• Orbit camera controller\n• 3D physics with rigid bodies\n• Character controller with jumping\n\nChallenge: Add a skybox and third-person camera!",
|
|
592
592
|
pl: 'Zbudowałeś swoją pierwszą grę 3D!\n• Scena World3D z wieloma obiektami\n• Prymitywne meshe (sześcian, sfera, płaszczyzna)\n• Oświetlenie kierunkowe i punktowe\n• Kontroler kamery orbitalnej\n• Fizyka 3D z ciałami sztywnymi\n• Kontroler postaci ze skakaniem\n\nWyzwanie: Dodaj skybox i kamerę trzeciej osoby!',
|
|
593
593
|
de: 'Du hast dein erstes 3D-Spiel gebaut!\n• World3D-Szene mit mehreren Objekten\n• Primitive Meshes (Würfel, Kugel, Ebene)\n• Richtungs- und Punktbeleuchtung\n• Orbit-Kamera-Controller\n• 3D-Physik mit Starrkörpern\n• Character-Controller mit Springen\n\nHerausforderung: Füge eine Skybox und Third-Person-Kamera hinzu!',
|
|
594
594
|
},
|
|
@@ -628,9 +628,9 @@ const TUTORIAL_PUBLISHING = {
|
|
|
628
628
|
de: 'Veröffentliche dein Spiel! 🚀',
|
|
629
629
|
},
|
|
630
630
|
content: {
|
|
631
|
-
en:
|
|
631
|
+
en: "Your game is ready — now let's share it with the world!\n\n• Feature detection (check browser support)\n• Build optimization (minify, tree-shake)\n• PWA export (installable web app)\n• Electron export (Windows/Mac/Linux)\n• Capacitor export (iOS/Android)\n• Performance benchmarking\n\nLet's deploy!",
|
|
632
632
|
pl: 'Twoja gra jest gotowa — czas podzielić się nią ze światem!\n\n• Wykrywanie funkcji (sprawdź wsparcie przeglądarki)\n• Optymalizacja buildu (minifikacja, tree-shaking)\n• Eksport PWA (instalowalna web app)\n• Eksport Electron (Windows/Mac/Linux)\n• Eksport Capacitor (iOS/Android)\n• Benchmarkowanie wydajności\n\nWdrażamy!',
|
|
633
|
-
de:
|
|
633
|
+
de: "Dein Spiel ist bereit — teile es mit der Welt!\n\n• Feature-Erkennung (Browser-Support)\n• Build-Optimierung (Minifizierung, Tree-Shaking)\n• PWA-Export (installierbare Web-App)\n• Electron-Export (Windows/Mac/Linux)\n• Capacitor-Export (iOS/Android)\n• Performance-Benchmarking\n\nLos geht's!",
|
|
634
634
|
},
|
|
635
635
|
skippable: true,
|
|
636
636
|
tooltipPosition: 'center',
|
|
@@ -740,10 +740,38 @@ const TUTORIAL_PUBLISHING = {
|
|
|
740
740
|
de: 'Was ist eine PWA (Progressive Web App)?',
|
|
741
741
|
},
|
|
742
742
|
quizOptions: [
|
|
743
|
-
{
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
743
|
+
{
|
|
744
|
+
id: 'a',
|
|
745
|
+
text: {
|
|
746
|
+
en: 'A native mobile app',
|
|
747
|
+
pl: 'Natywna aplikacja mobilna',
|
|
748
|
+
de: 'Eine native mobile App',
|
|
749
|
+
},
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
id: 'b',
|
|
753
|
+
text: {
|
|
754
|
+
en: 'A web app that can be installed and works offline',
|
|
755
|
+
pl: 'Web app instalowalna i działająca offline',
|
|
756
|
+
de: 'Eine Web-App die installierbar ist und offline funktioniert',
|
|
757
|
+
},
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
id: 'c',
|
|
761
|
+
text: {
|
|
762
|
+
en: 'A special browser plugin',
|
|
763
|
+
pl: 'Specjalna wtyczka przeglądarki',
|
|
764
|
+
de: 'Ein spezielles Browser-Plugin',
|
|
765
|
+
},
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
id: 'd',
|
|
769
|
+
text: {
|
|
770
|
+
en: 'A server-side application',
|
|
771
|
+
pl: 'Aplikacja serwerowa',
|
|
772
|
+
de: 'Eine serverseitige Anwendung',
|
|
773
|
+
},
|
|
774
|
+
},
|
|
747
775
|
],
|
|
748
776
|
quizCorrectId: 'b',
|
|
749
777
|
},
|
|
@@ -768,12 +796,7 @@ const TUTORIAL_PUBLISHING = {
|
|
|
768
796
|
Convenience export
|
|
769
797
|
══════════════════════════════════════════════════════════════ */
|
|
770
798
|
function getTutorials_T12_T15() {
|
|
771
|
-
return [
|
|
772
|
-
TUTORIAL_RPG,
|
|
773
|
-
TUTORIAL_TOWER_DEFENSE,
|
|
774
|
-
TUTORIAL_3D_GAME,
|
|
775
|
-
TUTORIAL_PUBLISHING,
|
|
776
|
-
];
|
|
799
|
+
return [TUTORIAL_RPG, TUTORIAL_TOWER_DEFENSE, TUTORIAL_3D_GAME, TUTORIAL_PUBLISHING];
|
|
777
800
|
}
|
|
778
801
|
|
|
779
802
|
export { TUTORIAL_3D_GAME, TUTORIAL_PUBLISHING, TUTORIAL_RPG, TUTORIAL_TOWER_DEFENSE, getTutorials_T12_T15 };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './types';
|
|
2
2
|
export { GameLoop, type GameLoopCallbacks } from './GameLoop';
|
|
3
3
|
export { GameClock } from './GameClock';
|
|
4
|
-
export { GameConfig, DEFAULT_SETTINGS, DEFAULT_PHYSICS, DEFAULT_AUDIO, DEFAULT_RENDERING } from './GameConfig';
|
|
4
|
+
export { GameConfig, DEFAULT_SETTINGS, DEFAULT_PHYSICS, DEFAULT_AUDIO, DEFAULT_RENDERING, } from './GameConfig';
|
|
5
5
|
export { EventBus, type EventHandler } from './EventBus';
|
|
6
6
|
export { ServiceLocator, SERVICE_KEYS } from './ServiceLocator';
|
|
7
7
|
export { v2 } from './math';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { InputManager, PRESET_PLATFORMER, PRESET_TOPDOWN, PRESET_TWIN_STICK, type GamepadButton, type GamepadAxis, type ActionState, type ActionBinding, type InputPreset, } from './InputManager';
|
|
2
2
|
export { GamepadNavigationProvider, useGamepadNavigation, type FocusableMeta, type GamepadNavigationContextType, } from './GamepadNavigation';
|
|
3
|
-
export { useGamepads, useGamepadEdges, type GamepadSnapshot
|
|
3
|
+
export { useGamepads, useGamepadEdges, type GamepadSnapshot } from './useGamepads';
|
|
@@ -2,7 +2,7 @@ export { I18nManager, getI18n, initI18n, t, registerEngineTranslations, ENGINE_T
|
|
|
2
2
|
export type { Locale, TranslationDict, TranslationNamespace, InterpolationValues, PluralCategory, PluralRule, I18nConfig, } from '../i18n/I18n';
|
|
3
3
|
export { TutorialEngine, getBuiltInTutorials, TUTORIAL_FIRST_GAME, TUTORIAL_SPACE_SHOOTER, TUTORIAL_DATAGRID_BASICS, } from '../tutorials/TutorialEngine';
|
|
4
4
|
export type { TutorialStepType, TutorialDifficulty, TutorialCategory, QuizOption, CodeValidation, TutorialStep, TutorialDefinition, TutorialProgress, TutorialEvents, CodeValidatorFn, } from '../tutorials/TutorialEngine';
|
|
5
|
-
export { useTranslation, I18nProvider, TranslatedText, LocaleSelect
|
|
5
|
+
export { useTranslation, I18nProvider, TranslatedText, LocaleSelect } from '../i18n/useTranslation';
|
|
6
6
|
export type { UseTranslationResult } from '../i18n/useTranslation';
|
|
7
7
|
export { KidModeManager, DEFAULT_KID_MODE_CONFIG, KID_DIFFICULTY_PRESETS, VISUAL_BLOCKS, KID_BADGES, KID_SPRITES, } from '../kids/KidMode';
|
|
8
8
|
export type { AgeGroup, KidDifficulty, BlockCategory, VisualBlock, BlockParam, KidSprite, KidBadge, BadgeCondition, KidProfile, ParentConfig, ClassroomConfig, KidModeConfig, KidDifficultySettings, } from '../kids/KidMode';
|
|
@@ -11,7 +11,7 @@ export type { EngineError, APIHint, PerfSnapshot, PerfDashboard, HealthCheckResu
|
|
|
11
11
|
export { TUTORIAL_ANIMATIONS, TUTORIAL_TILEMAPS, TUTORIAL_VISUAL_SCRIPTING, TUTORIAL_LOCAL_MULTIPLAYER, getTutorials_T05_T08, } from '../tutorials/content/Tutorials_T05_T08';
|
|
12
12
|
export { clamp, clampPositive, assertFinite, assertPositive, assertNonNegative, assertInRange, assertNonEmpty, assertCanvasElement, validateGameSettings, validatePhysicsSettings, } from '../core/Validation';
|
|
13
13
|
export type { ValidationResult } from '../core/Validation';
|
|
14
|
-
export { PluginManager, PluginMarketplace, PLUGIN_TEMPLATES
|
|
14
|
+
export { PluginManager, PluginMarketplace, PLUGIN_TEMPLATES } from '../plugins/PluginSDK';
|
|
15
15
|
export type { PluginState, PluginType, PluginManifest, PluginContext, PluginDefinition, ExtensionPoint, PluginStorage, PluginInstance, PluginTemplate, MarketplaceEntry, MarketplaceSearchResult, } from '../plugins/PluginSDK';
|
|
16
16
|
export { TestPluginStorage, TestPluginContext, PluginAssertionError, pluginAssert, PluginTestRunner, createTestManifest, testPluginLifecycle, formatTestResults, } from '../plugins/PluginTestKit';
|
|
17
17
|
export type { TestStatus, TestResult, TestSuiteResult, PluginTestCase, } from '../plugins/PluginTestKit';
|
|
@@ -20,16 +20,16 @@ export { TUTORIAL_RPG, TUTORIAL_TOWER_DEFENSE, TUTORIAL_3D_GAME, TUTORIAL_PUBLIS
|
|
|
20
20
|
export { FrameBudgetManager, MemoryLeakDetector, AutoLODManager, WorkerPool, PerfTimer, ObjectPool, QUALITY_PRESETS, } from '../performance/PerformanceAdvanced';
|
|
21
21
|
export type { FrameBudgetConfig, BudgetReport, FrameBudgetSnapshot, MemoryTracker, MemorySnapshot, LeakSuspect, QualityLevel, AutoLODConfig, QualitySettings, WorkerTaskStatus, WorkerTask, WorkerPoolConfig, } from '../performance/PerformanceAdvanced';
|
|
22
22
|
export { TutorialOverlay } from '../tutorials/TutorialOverlay';
|
|
23
|
-
export type { OverlayConfig, TooltipPosition, OverlayAction
|
|
24
|
-
export { DocRegistry, DOCS_ECS, DOCS_RENDERING
|
|
23
|
+
export type { OverlayConfig, TooltipPosition, OverlayAction } from '../tutorials/TutorialOverlay';
|
|
24
|
+
export { DocRegistry, DOCS_ECS, DOCS_RENDERING } from '../docs/DocGenerator';
|
|
25
25
|
export type { DocCategory, DocMemberKind, DocParam, DocMember, DocModule, DocSearchResult, } from '../docs/DocGenerator';
|
|
26
26
|
export { BranchingEngine, AchievementEngine, BUILT_IN_ACHIEVEMENTS, } from '../tutorials/TutorialBranching';
|
|
27
27
|
export type { BranchConditionType, BranchCondition, BranchRule, BranchingStep, BranchingConfig, BranchContext, AchievementTier, AchievementCondition, AchievementDefinition, AchievementProgress, } from '../tutorials/TutorialBranching';
|
|
28
28
|
export { HotModuleReplacer, AssetPipeline, DeployManager, CollaborationManager, } from '../devtools/DevTools';
|
|
29
29
|
export type { HMRModule, HMRUpdate, AssetType, AssetMeta, AssetProcessorOptions, DeployTarget, DeployConfig, DeployResult, CollaboratorCursor, } from '../devtools/DevTools';
|
|
30
|
-
export { GuidedWizard, BlockEditor, KID_BLOCK_PALETTES
|
|
30
|
+
export { GuidedWizard, BlockEditor, KID_BLOCK_PALETTES } from '../kids/KidTools';
|
|
31
31
|
export type { WizardChoice, WizardStep, WizardResult, BlockShape, DragBlock, BlockPalette, DragDropState, } from '../kids/KidTools';
|
|
32
|
-
export { BenchmarkRunner, BUILTIN_BENCHMARKS
|
|
32
|
+
export { BenchmarkRunner, BUILTIN_BENCHMARKS } from '../performance/BenchmarkSuite';
|
|
33
33
|
export type { BenchmarkScenario, BenchmarkTimings, BenchmarkMemory, BenchmarkResult, BenchmarkReport, RegressionResult, } from '../performance/BenchmarkSuite';
|
|
34
34
|
export type { BuiltInComponentType, ComponentTypeMap, AnyBuiltInComponent, EngineEventName, EngineEventMap, TimeDelta, StrictRecord, JsonValue, EventCallback, StrictPartial, AtLeastOne, } from '../core/TypeSafety';
|
|
35
35
|
export { isVec2, isVec3, isRect, isColor, isComponent, isEntityId, isComponentOfType, getTypedComponent, requireComponent, assertNever, } from '../core/TypeSafety';
|
|
@@ -49,7 +49,7 @@ export { GUIDE_ARCHITECTURE, GUIDE_MIGRATION, GUIDE_PERFORMANCE, GUIDE_TROUBLESH
|
|
|
49
49
|
export type { Guide, GuideSection } from '../docs/Guides';
|
|
50
50
|
export { WebGPUContext, GPUPhysicsBroadphase, GPUParticleSystem, GPUPathfinder, isWebGPUAvailable, getWebGPUShaders, } from '../performance/WebGPUCompute';
|
|
51
51
|
export type { WebGPUConfig, ComputeBuffer, ComputePipeline, PhysicsBroadphaseResult, } from '../performance/WebGPUCompute';
|
|
52
|
-
export { WASMAccelerator, benchmarkWASMvsJS
|
|
52
|
+
export { WASMAccelerator, benchmarkWASMvsJS } from '../performance/WASMModules';
|
|
53
53
|
export type { WASMModuleConfig, WASMExports, CollisionResult, PathResult, } from '../performance/WASMModules';
|
|
54
54
|
export { TextureCompressor, AudioCompressor, MeshCompressor, AssetStreamer, AssetPipeline as CompressionPipeline, } from '../performance/AssetCompression';
|
|
55
55
|
export type { TextureCompressionConfig, AudioCompressionConfig, MeshCompressionConfig, StreamingConfig, AssetManifest, AssetEntry, CompressionStats, } from '../performance/AssetCompression';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { SeededRandom, PerlinNoise, WaveGenerator, LootTable, ProceduralSprite } from './Procedural';
|
|
1
|
+
export { SeededRandom, PerlinNoise, WaveGenerator, LootTable, ProceduralSprite, } from './Procedural';
|
|
2
2
|
export type { WaveEntry, WaveConfig, LootDrop } from './Procedural';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nice2dev/game-engine",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "Nice2Dev Game Engine — No-code game engine and editor for React",
|
|
5
5
|
"author": "NiceToDev <contact@nicetodev.com>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@microsoft/signalr": "^10.0.11",
|
|
75
|
-
"@nice2dev/ui": "^1.1.
|
|
75
|
+
"@nice2dev/ui": "^1.1.7",
|
|
76
76
|
"@rollup/plugin-commonjs": "^29.0.3",
|
|
77
77
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
78
78
|
"@rollup/plugin-typescript": "^12.3.0",
|