@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
|
@@ -41,7 +41,7 @@ const TUTORIAL_RPG = {
|
|
|
41
41
|
de: 'Baue dein eigenes RPG! ⚔️',
|
|
42
42
|
},
|
|
43
43
|
content: {
|
|
44
|
-
en:
|
|
44
|
+
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?",
|
|
45
45
|
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ę?',
|
|
46
46
|
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?',
|
|
47
47
|
},
|
|
@@ -58,7 +58,7 @@ const TUTORIAL_RPG = {
|
|
|
58
58
|
de: 'Charakterwerte & Leveling',
|
|
59
59
|
},
|
|
60
60
|
content: {
|
|
61
|
-
en:
|
|
61
|
+
en: "Define your hero's stats. Use the RPG template config for stat growth curves and XP requirements.",
|
|
62
62
|
pl: 'Zdefiniuj statystyki bohatera. Użyj konfiguracji szablonu RPG dla krzywych wzrostu statystyk i wymogów XP.',
|
|
63
63
|
de: 'Definiere die Werte deines Helden. Verwende die RPG-Template-Konfiguration für Wachstumskurven und XP-Anforderungen.',
|
|
64
64
|
},
|
|
@@ -112,7 +112,7 @@ const TUTORIAL_RPG = {
|
|
|
112
112
|
pl: 'Stwórz NPC z drzewami dialogów. Gracz może wybierać odpowiedzi, które rozgałęziają rozmowę.',
|
|
113
113
|
de: 'Erstelle NPCs mit Dialogbäumen. Spieler können Antworten wählen, die das Gespräch verzweigen.',
|
|
114
114
|
},
|
|
115
|
-
codeTemplate:
|
|
115
|
+
codeTemplate: '// Dialogue system\ninterface DialogNode {\n id: string;\n text: string;\n',
|
|
116
116
|
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];",
|
|
117
117
|
codeValidation: {
|
|
118
118
|
containsAll: ['DialogNode', 'speaker', 'choices', 'next'],
|
|
@@ -163,7 +163,7 @@ const TUTORIAL_RPG = {
|
|
|
163
163
|
de: 'Erstelle mehrere Räume verbunden durch Warps. Verwende Tilemaps für jeden Bereich (Stadt, Wald, Höhle, Burg).',
|
|
164
164
|
},
|
|
165
165
|
requiredAction: 'create-world-map',
|
|
166
|
-
codeTemplate:
|
|
166
|
+
codeTemplate: '// Define world areas\nconst areas = [\n',
|
|
167
167
|
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];",
|
|
168
168
|
codeValidation: {
|
|
169
169
|
containsAll: ['areas', 'warps', 'tilemap'],
|
|
@@ -201,7 +201,7 @@ const TUTORIAL_RPG = {
|
|
|
201
201
|
de: 'RPG fertig! 🏰',
|
|
202
202
|
},
|
|
203
203
|
content: {
|
|
204
|
-
en:
|
|
204
|
+
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!",
|
|
205
205
|
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!',
|
|
206
206
|
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!',
|
|
207
207
|
},
|
|
@@ -241,7 +241,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
241
241
|
de: 'Baue Tower Defense! 🗼',
|
|
242
242
|
},
|
|
243
243
|
content: {
|
|
244
|
-
en:
|
|
244
|
+
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!",
|
|
245
245
|
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!',
|
|
246
246
|
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!',
|
|
247
247
|
},
|
|
@@ -288,7 +288,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
288
288
|
de: 'Feinde folgen einem vordefinierten Pfad vom Start zum Ende. Definiere Wegpunkte, zwischen denen Feinde laufen.',
|
|
289
289
|
},
|
|
290
290
|
codeTemplate: '// Enemy path waypoints\nconst path = [\n',
|
|
291
|
-
codeSolution:
|
|
291
|
+
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}',
|
|
292
292
|
codeValidation: {
|
|
293
293
|
containsAll: ['path', 'waypointIndex', 'moveAlongPath'],
|
|
294
294
|
},
|
|
@@ -363,7 +363,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
363
363
|
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.',
|
|
364
364
|
},
|
|
365
365
|
codeTemplate: '// Upgrade system\nlet gold = 200;\n',
|
|
366
|
-
codeSolution:
|
|
366
|
+
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}',
|
|
367
367
|
codeValidation: {
|
|
368
368
|
containsAll: ['upgradeTower', 'sellTower', 'gold'],
|
|
369
369
|
},
|
|
@@ -383,7 +383,7 @@ const TUTORIAL_TOWER_DEFENSE = {
|
|
|
383
383
|
de: 'Tower Defense fertig! 🏆',
|
|
384
384
|
},
|
|
385
385
|
content: {
|
|
386
|
-
en:
|
|
386
|
+
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!",
|
|
387
387
|
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ę!',
|
|
388
388
|
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!',
|
|
389
389
|
},
|
|
@@ -423,7 +423,7 @@ const TUTORIAL_3D_GAME = {
|
|
|
423
423
|
de: 'Willkommen in 3D! 🎮',
|
|
424
424
|
},
|
|
425
425
|
content: {
|
|
426
|
-
en:
|
|
426
|
+
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!",
|
|
427
427
|
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!',
|
|
428
428
|
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!',
|
|
429
429
|
},
|
|
@@ -590,7 +590,7 @@ const TUTORIAL_3D_GAME = {
|
|
|
590
590
|
de: '3D-Spiel fertig! 🌟',
|
|
591
591
|
},
|
|
592
592
|
content: {
|
|
593
|
-
en:
|
|
593
|
+
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!",
|
|
594
594
|
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!',
|
|
595
595
|
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!',
|
|
596
596
|
},
|
|
@@ -630,9 +630,9 @@ const TUTORIAL_PUBLISHING = {
|
|
|
630
630
|
de: 'Veröffentliche dein Spiel! 🚀',
|
|
631
631
|
},
|
|
632
632
|
content: {
|
|
633
|
-
en:
|
|
633
|
+
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!",
|
|
634
634
|
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!',
|
|
635
|
-
de:
|
|
635
|
+
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!",
|
|
636
636
|
},
|
|
637
637
|
skippable: true,
|
|
638
638
|
tooltipPosition: 'center',
|
|
@@ -742,10 +742,38 @@ const TUTORIAL_PUBLISHING = {
|
|
|
742
742
|
de: 'Was ist eine PWA (Progressive Web App)?',
|
|
743
743
|
},
|
|
744
744
|
quizOptions: [
|
|
745
|
-
{
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
745
|
+
{
|
|
746
|
+
id: 'a',
|
|
747
|
+
text: {
|
|
748
|
+
en: 'A native mobile app',
|
|
749
|
+
pl: 'Natywna aplikacja mobilna',
|
|
750
|
+
de: 'Eine native mobile App',
|
|
751
|
+
},
|
|
752
|
+
},
|
|
753
|
+
{
|
|
754
|
+
id: 'b',
|
|
755
|
+
text: {
|
|
756
|
+
en: 'A web app that can be installed and works offline',
|
|
757
|
+
pl: 'Web app instalowalna i działająca offline',
|
|
758
|
+
de: 'Eine Web-App die installierbar ist und offline funktioniert',
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
{
|
|
762
|
+
id: 'c',
|
|
763
|
+
text: {
|
|
764
|
+
en: 'A special browser plugin',
|
|
765
|
+
pl: 'Specjalna wtyczka przeglądarki',
|
|
766
|
+
de: 'Ein spezielles Browser-Plugin',
|
|
767
|
+
},
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
id: 'd',
|
|
771
|
+
text: {
|
|
772
|
+
en: 'A server-side application',
|
|
773
|
+
pl: 'Aplikacja serwerowa',
|
|
774
|
+
de: 'Eine serverseitige Anwendung',
|
|
775
|
+
},
|
|
776
|
+
},
|
|
749
777
|
],
|
|
750
778
|
quizCorrectId: 'b',
|
|
751
779
|
},
|
|
@@ -770,12 +798,7 @@ const TUTORIAL_PUBLISHING = {
|
|
|
770
798
|
Convenience export
|
|
771
799
|
══════════════════════════════════════════════════════════════ */
|
|
772
800
|
function getTutorials_T12_T15() {
|
|
773
|
-
return [
|
|
774
|
-
TUTORIAL_RPG,
|
|
775
|
-
TUTORIAL_TOWER_DEFENSE,
|
|
776
|
-
TUTORIAL_3D_GAME,
|
|
777
|
-
TUTORIAL_PUBLISHING,
|
|
778
|
-
];
|
|
801
|
+
return [TUTORIAL_RPG, TUTORIAL_TOWER_DEFENSE, TUTORIAL_3D_GAME, TUTORIAL_PUBLISHING];
|
|
779
802
|
}
|
|
780
803
|
|
|
781
804
|
exports.TUTORIAL_3D_GAME = TUTORIAL_3D_GAME;
|
|
@@ -35,13 +35,27 @@ class GameConfig {
|
|
|
35
35
|
get settings() {
|
|
36
36
|
return this._settings;
|
|
37
37
|
}
|
|
38
|
-
get width() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
get
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
get
|
|
38
|
+
get width() {
|
|
39
|
+
return this._settings.width;
|
|
40
|
+
}
|
|
41
|
+
get height() {
|
|
42
|
+
return this._settings.height;
|
|
43
|
+
}
|
|
44
|
+
get targetFps() {
|
|
45
|
+
return this._settings.targetFps;
|
|
46
|
+
}
|
|
47
|
+
get maxPlayers() {
|
|
48
|
+
return this._settings.maxPlayers;
|
|
49
|
+
}
|
|
50
|
+
get physics() {
|
|
51
|
+
return this._settings.physics;
|
|
52
|
+
}
|
|
53
|
+
get audio() {
|
|
54
|
+
return this._settings.audio;
|
|
55
|
+
}
|
|
56
|
+
get rendering() {
|
|
57
|
+
return this._settings.rendering;
|
|
58
|
+
}
|
|
45
59
|
update(overrides) {
|
|
46
60
|
this._settings = mergeSettings(this._settings, overrides);
|
|
47
61
|
}
|
|
@@ -22,9 +22,24 @@ function generateServiceWorkerConfig(config) {
|
|
|
22
22
|
strategy: config.cacheStrategy,
|
|
23
23
|
precache: [config.startUrl, '/index.html', '/manifest.json'],
|
|
24
24
|
runtimeCaching: [
|
|
25
|
-
{
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
{
|
|
26
|
+
urlPattern: /\.(?:png|jpg|jpeg|webp|svg|gif)$/i,
|
|
27
|
+
handler: 'CacheFirst',
|
|
28
|
+
options: {
|
|
29
|
+
cacheName: 'images',
|
|
30
|
+
expiration: { maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
urlPattern: /\.(?:js|css)$/i,
|
|
35
|
+
handler: 'StaleWhileRevalidate',
|
|
36
|
+
options: { cacheName: 'static' },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
urlPattern: /\.(?:mp3|ogg|wav)$/i,
|
|
40
|
+
handler: 'CacheFirst',
|
|
41
|
+
options: { cacheName: 'audio', expiration: { maxEntries: 50 } },
|
|
42
|
+
},
|
|
28
43
|
],
|
|
29
44
|
offlineFallback: config.offlineSupport ? '/offline.html' : undefined,
|
|
30
45
|
};
|
|
@@ -122,19 +137,37 @@ function createDefaultMobileLayout() {
|
|
|
122
137
|
}
|
|
123
138
|
const MOBILE_PERF_PROFILES = {
|
|
124
139
|
low: {
|
|
125
|
-
tier: 'low',
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
tier: 'low',
|
|
141
|
+
maxFPS: 30,
|
|
142
|
+
renderScale: 0.5,
|
|
143
|
+
maxParticles: 100,
|
|
144
|
+
maxAudioSources: 8,
|
|
145
|
+
shadowQuality: 'off',
|
|
146
|
+
postProcessing: false,
|
|
147
|
+
textureQuality: 'low',
|
|
148
|
+
physicsBroadPhaseSize: 64,
|
|
128
149
|
},
|
|
129
150
|
medium: {
|
|
130
|
-
tier: 'medium',
|
|
131
|
-
|
|
132
|
-
|
|
151
|
+
tier: 'medium',
|
|
152
|
+
maxFPS: 60,
|
|
153
|
+
renderScale: 0.75,
|
|
154
|
+
maxParticles: 500,
|
|
155
|
+
maxAudioSources: 16,
|
|
156
|
+
shadowQuality: 'low',
|
|
157
|
+
postProcessing: true,
|
|
158
|
+
textureQuality: 'medium',
|
|
159
|
+
physicsBroadPhaseSize: 128,
|
|
133
160
|
},
|
|
134
161
|
high: {
|
|
135
|
-
tier: 'high',
|
|
136
|
-
|
|
137
|
-
|
|
162
|
+
tier: 'high',
|
|
163
|
+
maxFPS: 60,
|
|
164
|
+
renderScale: 1,
|
|
165
|
+
maxParticles: 2000,
|
|
166
|
+
maxAudioSources: 32,
|
|
167
|
+
shadowQuality: 'high',
|
|
168
|
+
postProcessing: true,
|
|
169
|
+
textureQuality: 'high',
|
|
170
|
+
physicsBroadPhaseSize: 256,
|
|
138
171
|
},
|
|
139
172
|
};
|
|
140
173
|
|
|
@@ -13,12 +13,12 @@ const TUTORIAL_ANIMATIONS = {
|
|
|
13
13
|
id: 'animations-sprites-tweens',
|
|
14
14
|
title: {
|
|
15
15
|
en: 'Animations: Sprites, Tweens & Easing',
|
|
16
|
-
pl:
|
|
16
|
+
pl: "Animacje: Sprite'y, Tweeny i Easing",
|
|
17
17
|
de: 'Animationen: Sprites, Tweens & Easing',
|
|
18
18
|
},
|
|
19
19
|
description: {
|
|
20
20
|
en: 'Learn to animate game objects using sprite sheets, tweens, easing functions, and state machines.',
|
|
21
|
-
pl:
|
|
21
|
+
pl: "Naucz się animować obiekty za pomocą sprite sheet'ów, tweenów, easing'ów i maszyn stanów.",
|
|
22
22
|
de: 'Lerne, Spielobjekte mit Spritesheets, Tweens, Easing und Zustandsmaschinen zu animieren.',
|
|
23
23
|
},
|
|
24
24
|
category: 'game-basics',
|
|
@@ -39,8 +39,8 @@ const TUTORIAL_ANIMATIONS = {
|
|
|
39
39
|
de: 'Willkommen bei Animationen! 🎬',
|
|
40
40
|
},
|
|
41
41
|
content: {
|
|
42
|
-
en:
|
|
43
|
-
pl:
|
|
42
|
+
en: "In this tutorial you will learn:\n• Creating animation clips from sprite sheets\n• Using tweens for smooth movement\n• Easing functions (bounce, elastic, cubic)\n• Animation state machines\n\nLet's bring your game to life!",
|
|
43
|
+
pl: "W tym tutorialu nauczysz się:\n• Tworzenia klipów animacji ze sprite sheet'ów\n• Używania tweenów do płynnego ruchu\n• Funkcji easing (bounce, elastic, cubic)\n• Maszyn stanów animacji\n\nOżywmy Twoją grę!",
|
|
44
44
|
de: 'In diesem Tutorial lernst du:\n• Animationsclips aus Spritesheets erstellen\n• Tweens für flüssige Bewegungen\n• Easing-Funktionen (Bounce, Elastic, Cubic)\n• Animations-Zustandsmaschinen\n\nLass uns dein Spiel zum Leben erwecken!',
|
|
45
45
|
},
|
|
46
46
|
skippable: true,
|
|
@@ -57,7 +57,7 @@ const TUTORIAL_ANIMATIONS = {
|
|
|
57
57
|
},
|
|
58
58
|
content: {
|
|
59
59
|
en: 'Use `createClipFromSheet` to define an animation clip from a sprite sheet.\nParameters: name, columns in the sheet, start index, frame count, frame size, and duration per frame.',
|
|
60
|
-
pl:
|
|
60
|
+
pl: "Użyj `createClipFromSheet` aby zdefiniować klip animacji ze sprite sheet'a.\nParametry: nazwa, kolumny w arkuszu, indeks startowy, ilość klatek, rozmiar klatki i czas trwania klatki.",
|
|
61
61
|
de: 'Verwende `createClipFromSheet` um einen Animationsclip aus einem Spritesheet zu erstellen.\nParameter: Name, Spalten im Sheet, Startindex, Framezahl, Framegröße und Dauer pro Frame.',
|
|
62
62
|
},
|
|
63
63
|
codeTemplate: '// Create a "walk" animation clip\nconst walkClip = ',
|
|
@@ -193,7 +193,7 @@ const TUTORIAL_ANIMATIONS = {
|
|
|
193
193
|
de: 'Animations-Checkpoint ✅',
|
|
194
194
|
},
|
|
195
195
|
content: {
|
|
196
|
-
en:
|
|
196
|
+
en: "Great progress! You've learned the core animation APIs. Your progress is saved.",
|
|
197
197
|
pl: 'Świetne postępy! Opanowałeś podstawowe API animacji. Twoje postępy zostały zapisane.',
|
|
198
198
|
de: 'Toller Fortschritt! Du hast die Kern-Animations-APIs gelernt. Dein Fortschritt wurde gespeichert.',
|
|
199
199
|
},
|
|
@@ -249,7 +249,7 @@ const TUTORIAL_TILEMAPS = {
|
|
|
249
249
|
de: 'Welten mit Kacheln bauen! 🗺️',
|
|
250
250
|
},
|
|
251
251
|
content: {
|
|
252
|
-
en:
|
|
252
|
+
en: "Tilemaps are the foundation of 2D game worlds — platformers, RPGs, strategy games.\n\nYou will learn:\n• Creating a tilemap with layers\n• Placing and filling tiles\n• Auto-tiling (smart borders)\n• Collision detection with tiles\n• Serializing tilemaps (save/load)\n\nLet's build a world! 🌍",
|
|
253
253
|
pl: 'Tilemapy to fundament świata gier 2D — platformówek, RPG, strategii.\n\nNauczysz się:\n• Tworzenia tilemapy z warstwami\n• Umieszczania i wypełniania kafelków\n• Auto-tilingu (inteligentne krawędzie)\n• Detekcji kolizji z kafelkami\n• Serializacji tilemap (zapis/odczyt)\n\nZbudujmy świat! 🌍',
|
|
254
254
|
de: 'Tilemaps sind das Fundament von 2D-Spielwelten — Platformer, RPGs, Strategiespiele.\n\nDu lernst:\n• Erstellen einer Tilemap mit Ebenen\n• Kacheln platzieren und füllen\n• Auto-Tiling (intelligente Ränder)\n• Kollisionserkennung mit Kacheln\n• Tilemaps serialisieren (Speichern/Laden)\n\nBauen wir eine Welt! 🌍',
|
|
255
255
|
},
|
|
@@ -495,7 +495,7 @@ const TUTORIAL_VISUAL_SCRIPTING = {
|
|
|
495
495
|
de: 'Baue einen Script-Graphen',
|
|
496
496
|
},
|
|
497
497
|
content: {
|
|
498
|
-
en:
|
|
498
|
+
en: "A `ScriptGraph` has nodes (instances) and connections between their ports.\nLet's create a simple graph that moves an entity when a key is pressed.",
|
|
499
499
|
pl: '`ScriptGraph` zawiera węzły (instancje) i połączenia między ich portami.\nUtwórzmy prosty graf, który przesuwa encję po naciśnięciu klawisza.',
|
|
500
500
|
de: 'Ein `ScriptGraph` hat Knoten (Instanzen) und Verbindungen zwischen Ports.\nErstellen wir einen einfachen Graphen, der eine Entity bewegt, wenn eine Taste gedrückt wird.',
|
|
501
501
|
},
|
|
@@ -525,9 +525,26 @@ const TUTORIAL_VISUAL_SCRIPTING = {
|
|
|
525
525
|
de: 'Was steuert ein "flow"-Port in Visual Scripting?',
|
|
526
526
|
},
|
|
527
527
|
quizOptions: [
|
|
528
|
-
{
|
|
529
|
-
|
|
530
|
-
|
|
528
|
+
{
|
|
529
|
+
id: 'a',
|
|
530
|
+
text: { en: 'The color of the node', pl: 'Kolor węzła', de: 'Die Farbe des Knotens' },
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
id: 'b',
|
|
534
|
+
text: {
|
|
535
|
+
en: 'The execution order (which node runs next)',
|
|
536
|
+
pl: 'Kolejność wykonania (który węzeł uruchomić dalej)',
|
|
537
|
+
de: 'Die Ausführungsreihenfolge (welcher Knoten als nächstes läuft)',
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
id: 'c',
|
|
542
|
+
text: {
|
|
543
|
+
en: 'The animation speed',
|
|
544
|
+
pl: 'Prędkość animacji',
|
|
545
|
+
de: 'Die Animationsgeschwindigkeit',
|
|
546
|
+
},
|
|
547
|
+
},
|
|
531
548
|
{ id: 'd', text: { en: 'The sound volume', pl: 'Głośność dźwięku', de: 'Die Lautstärke' } },
|
|
532
549
|
],
|
|
533
550
|
quizCorrectId: 'b',
|
|
@@ -542,7 +559,7 @@ const TUTORIAL_VISUAL_SCRIPTING = {
|
|
|
542
559
|
de: 'Starte den Graphen! 🚀',
|
|
543
560
|
},
|
|
544
561
|
content: {
|
|
545
|
-
en:
|
|
562
|
+
en: "The `GraphExecutor` takes a node library and a script graph, then executes it each frame.\nConnect it to the engine's update loop.",
|
|
546
563
|
pl: '`GraphExecutor` przyjmuje bibliotekę węzłów i graf, a następnie wykonuje go co klatkę.\nPodłącz go do pętli update silnika.',
|
|
547
564
|
de: 'Der `GraphExecutor` nimmt eine Knoten-Bibliothek und einen Graphen und führt ihn pro Frame aus.\nVerbinde ihn mit der Update-Schleife der Engine.',
|
|
548
565
|
},
|
|
@@ -567,7 +584,7 @@ const TUTORIAL_VISUAL_SCRIPTING = {
|
|
|
567
584
|
de: 'Probiere es! Verbinde Knoten',
|
|
568
585
|
},
|
|
569
586
|
content: {
|
|
570
|
-
en:
|
|
587
|
+
en: "In the editor, try dragging a connection from one node's output port to another node's input port.\nThe wire turns green when compatible ports are connected!",
|
|
571
588
|
pl: 'W edytorze spróbuj przeciągnąć połączenie z portu wyjściowego jednego węzła na port wejściowy drugiego.\nPrzewód zmienia kolor na zielony gdy porty są kompatybilne!',
|
|
572
589
|
de: 'Im Editor: Ziehe eine Verbindung vom Ausgang eines Knotens zum Eingang eines anderen.\nDie Leitung wird grün, wenn kompatible Ports verbunden sind!',
|
|
573
590
|
},
|
|
@@ -624,7 +641,7 @@ const TUTORIAL_LOCAL_MULTIPLAYER = {
|
|
|
624
641
|
de: 'Zusammen spielen! 🎮🎮',
|
|
625
642
|
},
|
|
626
643
|
content: {
|
|
627
|
-
en:
|
|
644
|
+
en: "Local multiplayer lets friends play together on the same screen!\n\nYou will learn:\n• `PlayerManager` — managing up to 12 players\n• Gamepad input for each player\n• Split-screen viewports\n• Drop-in / drop-out\n\nGrab some controllers and let's go! 🕹️",
|
|
628
645
|
pl: 'Multiplayer lokalny pozwala znajomym grać razem na jednym ekranie!\n\nNauczysz się:\n• `PlayerManager` — zarządzanie do 12 graczy\n• Wejście z gamepada dla każdego gracza\n• Podzielony ekran (split-screen)\n• Dynamiczne dołączanie/odłączanie graczy\n\nWeź kontrolery i zaczynamy! 🕹️',
|
|
629
646
|
de: 'Lokaler Multiplayer lässt Freunde zusammen auf einem Bildschirm spielen!\n\nDu lernst:\n• `PlayerManager` — bis zu 12 Spieler verwalten\n• Gamepad-Eingabe für jeden Spieler\n• Splitscreen-Ansichten\n• Drop-in / Drop-out\n\nSchnappt euch Controller und los! 🕹️',
|
|
630
647
|
},
|
|
@@ -767,8 +784,8 @@ const TUTORIAL_LOCAL_MULTIPLAYER = {
|
|
|
767
784
|
pl: 'Spraw, aby gamepady zaczęły wibrować przy zdarzeniach jak obrażenia czy eksplozje, używając metody `vibrate`.',
|
|
768
785
|
de: 'Lass Gamepads bei Events wie Schaden oder Explosionen vibrieren mit der `vibrate`-Methode.',
|
|
769
786
|
},
|
|
770
|
-
codeTemplate:
|
|
771
|
-
codeSolution:
|
|
787
|
+
codeTemplate: "// Vibrate a player's gamepad\n",
|
|
788
|
+
codeSolution: "// Vibrate player 1's gamepad for 200ms\nengine.input.vibrate(\n 1, // player index\n 200, // duration (ms)\n 0.5, // weak motor magnitude (0-1)\n 1.0 // strong motor magnitude (0-1)\n);",
|
|
772
789
|
codeValidation: {
|
|
773
790
|
containsAll: ['vibrate'],
|
|
774
791
|
},
|