@jjlmoya/utils-games-development 1.61.0 → 1.63.0

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 (72) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -1
  3. package/src/entries.ts +5 -1
  4. package/src/index.ts +2 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/tool_validation.test.ts +2 -2
  7. package/src/tool/gameUIAccessibilityTester/bibliography.astro +6 -0
  8. package/src/tool/gameUIAccessibilityTester/bibliography.ts +10 -0
  9. package/src/tool/gameUIAccessibilityTester/component.astro +210 -0
  10. package/src/tool/gameUIAccessibilityTester/controller-actions.ts +92 -0
  11. package/src/tool/gameUIAccessibilityTester/controller.ts +237 -0
  12. package/src/tool/gameUIAccessibilityTester/dom-views.ts +193 -0
  13. package/src/tool/gameUIAccessibilityTester/entry.ts +28 -0
  14. package/src/tool/gameUIAccessibilityTester/evaluator.ts +43 -0
  15. package/src/tool/gameUIAccessibilityTester/game-ui-accessibility-stress-tester.css +982 -0
  16. package/src/tool/gameUIAccessibilityTester/i18n/de.ts +203 -0
  17. package/src/tool/gameUIAccessibilityTester/i18n/en.ts +199 -0
  18. package/src/tool/gameUIAccessibilityTester/i18n/es.ts +203 -0
  19. package/src/tool/gameUIAccessibilityTester/i18n/fr.ts +203 -0
  20. package/src/tool/gameUIAccessibilityTester/i18n/id.ts +203 -0
  21. package/src/tool/gameUIAccessibilityTester/i18n/it.ts +203 -0
  22. package/src/tool/gameUIAccessibilityTester/i18n/ja.ts +203 -0
  23. package/src/tool/gameUIAccessibilityTester/i18n/ko.ts +203 -0
  24. package/src/tool/gameUIAccessibilityTester/i18n/nl.ts +203 -0
  25. package/src/tool/gameUIAccessibilityTester/i18n/pl.ts +203 -0
  26. package/src/tool/gameUIAccessibilityTester/i18n/pt.ts +203 -0
  27. package/src/tool/gameUIAccessibilityTester/i18n/ru.ts +203 -0
  28. package/src/tool/gameUIAccessibilityTester/i18n/sv.ts +203 -0
  29. package/src/tool/gameUIAccessibilityTester/i18n/tr.ts +203 -0
  30. package/src/tool/gameUIAccessibilityTester/i18n/zh.ts +203 -0
  31. package/src/tool/gameUIAccessibilityTester/index.ts +11 -0
  32. package/src/tool/gameUIAccessibilityTester/logic.test.ts +57 -0
  33. package/src/tool/gameUIAccessibilityTester/logic.ts +157 -0
  34. package/src/tool/gameUIAccessibilityTester/report.ts +59 -0
  35. package/src/tool/gameUIAccessibilityTester/seo.astro +15 -0
  36. package/src/tool/gameUIAccessibilityTester/storage.ts +34 -0
  37. package/src/tool/gameUIAccessibilityTester/ui.ts +80 -0
  38. package/src/tool/hitboxHurtboxAnimator/bibliography.astro +12 -0
  39. package/src/tool/hitboxHurtboxAnimator/bibliography.ts +10 -0
  40. package/src/tool/hitboxHurtboxAnimator/canvas-interactions.ts +59 -0
  41. package/src/tool/hitboxHurtboxAnimator/canvas-metrics.ts +8 -0
  42. package/src/tool/hitboxHurtboxAnimator/component.astro +148 -0
  43. package/src/tool/hitboxHurtboxAnimator/controller.ts +247 -0
  44. package/src/tool/hitboxHurtboxAnimator/dom-views.ts +194 -0
  45. package/src/tool/hitboxHurtboxAnimator/editor-state.ts +19 -0
  46. package/src/tool/hitboxHurtboxAnimator/entry.ts +28 -0
  47. package/src/tool/hitboxHurtboxAnimator/evaluator.ts +15 -0
  48. package/src/tool/hitboxHurtboxAnimator/file-io.ts +82 -0
  49. package/src/tool/hitboxHurtboxAnimator/hitbox-hurtbox-animator.css +614 -0
  50. package/src/tool/hitboxHurtboxAnimator/i18n/de.ts +195 -0
  51. package/src/tool/hitboxHurtboxAnimator/i18n/en.ts +191 -0
  52. package/src/tool/hitboxHurtboxAnimator/i18n/es.ts +195 -0
  53. package/src/tool/hitboxHurtboxAnimator/i18n/fr.ts +195 -0
  54. package/src/tool/hitboxHurtboxAnimator/i18n/id.ts +195 -0
  55. package/src/tool/hitboxHurtboxAnimator/i18n/it.ts +195 -0
  56. package/src/tool/hitboxHurtboxAnimator/i18n/ja.ts +195 -0
  57. package/src/tool/hitboxHurtboxAnimator/i18n/ko.ts +195 -0
  58. package/src/tool/hitboxHurtboxAnimator/i18n/nl.ts +195 -0
  59. package/src/tool/hitboxHurtboxAnimator/i18n/pl.ts +195 -0
  60. package/src/tool/hitboxHurtboxAnimator/i18n/pt.ts +195 -0
  61. package/src/tool/hitboxHurtboxAnimator/i18n/ru.ts +195 -0
  62. package/src/tool/hitboxHurtboxAnimator/i18n/sv.ts +195 -0
  63. package/src/tool/hitboxHurtboxAnimator/i18n/tr.ts +195 -0
  64. package/src/tool/hitboxHurtboxAnimator/i18n/zh.ts +195 -0
  65. package/src/tool/hitboxHurtboxAnimator/index.ts +11 -0
  66. package/src/tool/hitboxHurtboxAnimator/logic.test.ts +97 -0
  67. package/src/tool/hitboxHurtboxAnimator/logic.ts +173 -0
  68. package/src/tool/hitboxHurtboxAnimator/project-actions.ts +128 -0
  69. package/src/tool/hitboxHurtboxAnimator/seo.astro +13 -0
  70. package/src/tool/hitboxHurtboxAnimator/storage.ts +27 -0
  71. package/src/tool/hitboxHurtboxAnimator/ui.ts +70 -0
  72. package/src/tools.ts +4 -0
@@ -0,0 +1,195 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { HitboxHurtboxAnimatorUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const slug = 'animateur-hitbox-hurtbox-sprites';
7
+ const title = 'Animateur de Hitbox et Hurtbox pour Sprites';
8
+ const description = 'Dessinez des calques de collision sur chaque image de sprite, prévisualisez les mouvements avec la pelure d\'oignon et exportez un fichier JSON neutre.';
9
+
10
+ const faq = [
11
+ {
12
+ question: 'Quelle est la différence entre une hitbox et une hurtbox ?',
13
+ answer: 'Une hitbox définit la zone qui inflige une attaque, tandis qu\'une hurtbox définit la zone vulnérable qui la reçoit. Les pushboxes maintiennent les personnages à distance et les grabboxes définissent la portée des prises.',
14
+ },
15
+ {
16
+ question: 'Mes fichiers de sprites quittent-ils le navigateur ?',
17
+ answer: 'Non. Les images sont traitées et exportées entièrement dans votre navigateur. Seules les préférences d\'édition sont conservées localement.',
18
+ },
19
+ {
20
+ question: 'Quel système de coordonnées l\'export JSON utilise-t-il ?',
21
+ answer: 'Chaque image mesure ses coordonnées en pixels depuis le coin supérieur gauche du découpage. Les dimensions de largeur et hauteur stockent des valeurs positives avec leur propre pivot.',
22
+ },
23
+ {
24
+ question: 'Puis-je éditer une planche de sprites ou des images séparées ?',
25
+ answer: 'Oui. Vous pouvez charger une planche PNG ou WebP en indiquant les lignes et colonnes, ou sélectionner plusieurs images ordonnées.',
26
+ },
27
+ {
28
+ question: 'L\'export fonctionne-t-il directement dans tous les moteurs ?',
29
+ answer: 'Le format JSON est neutre. Il enregistre les rectangles d\'images, les pivots et les calques géométriques sans imposer un moteur spécifique.',
30
+ },
31
+ ];
32
+
33
+ const howTo = [
34
+ { name: 'Charger les sprites', text: 'Sélectionnez une planche de sprites PNG/WebP ou des images ordonnées. Le traitement reste local.' },
35
+ { name: 'Définir les images', text: 'Indiquez le nombre de lignes et colonnes pour une planche et vérifiez le découpage sur le film d\'animation.' },
36
+ { name: 'Dessiner les calques de collision', text: 'Choisissez un calque hitbox, hurtbox, pushbox ou sensor, puis tracez un rectangle ou un cercle.' },
37
+ { name: 'Ajuster le mouvement', text: 'Modifiez les coordonnées exactes, copiez les formes sur les images voisines et utilisez la pelure d\'oignon.' },
38
+ { name: 'Exporter le projet', text: 'Téléchargez le fichier JSON neutre et une planche de contact PNG. Conservez les images d\'origine.' },
39
+ ];
40
+
41
+ const softwareApplication: WithContext<SoftwareApplication> = {
42
+ '@context': 'https://schema.org',
43
+ '@type': 'SoftwareApplication',
44
+ name: title,
45
+ applicationCategory: 'DeveloperApplication',
46
+ operatingSystem: 'Any',
47
+ };
48
+
49
+ const faqPage: WithContext<FAQPage> = {
50
+ '@context': 'https://schema.org',
51
+ '@type': 'FAQPage',
52
+ mainEntity: faq.map((item) => ({
53
+ '@type': 'Question',
54
+ name: item.question,
55
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
56
+ })),
57
+ };
58
+
59
+ const howToSchema: WithContext<HowTo> = {
60
+ '@context': 'https://schema.org',
61
+ '@type': 'HowTo',
62
+ name: title,
63
+ step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })),
64
+ };
65
+
66
+ export const content: ToolLocaleContent<HitboxHurtboxAnimatorUI> = {
67
+ slug,
68
+ title,
69
+ description,
70
+ ui: {
71
+ onboarding: 'Chargez une animation, confirmez le découpage et dessinez les zones d\'attaque, de dégâts ou de collision.',
72
+ privacyNote: 'Table d\'animation locale. Les images ne sont pas envoyées sur un serveur.',
73
+ loadSprite: 'Placer l\'image sur la table d\'animation',
74
+ loadHint: 'Choisissez une planche de sprites ou des images PNG/WebP ordonnées.',
75
+ chooseImages: 'Choisir les images',
76
+ slicingTitle: 'Découpage des images',
77
+ rowsLabel: 'Lignes',
78
+ columnsLabel: 'Colonnes',
79
+ applySlicing: 'Découper',
80
+ playbackTitle: 'Aperçu du mouvement',
81
+ previousFrame: 'Image précédente',
82
+ play: 'Lecture',
83
+ pause: 'Pause',
84
+ nextFrame: 'Image suivante',
85
+ fpsLabel: 'Images par seconde',
86
+ onionPrevious: 'Calque précédent',
87
+ onionNext: 'Calque suivant',
88
+ layerTitle: 'Calques de collision',
89
+ typeHitbox: 'Hitbox',
90
+ typeHurtbox: 'Hurtbox',
91
+ typePushbox: 'Pushbox',
92
+ typeGrabbox: 'Grabbox',
93
+ typeSensor: 'Capteur',
94
+ typeCustom: 'Personnalisé',
95
+ shapeRectangle: 'Rectangle',
96
+ shapeCircle: 'Cercle',
97
+ drawShape: 'Dessiner',
98
+ selectShape: 'Sélectionner',
99
+ stageLabel: 'Zone de travail',
100
+ emptyStage: 'Chargez des images pour commencer à dessiner les calques de collision.',
101
+ frameReadout: 'Image {current} sur {total}',
102
+ timelineTitle: 'Bande d\'animation',
103
+ inspectorTitle: 'Inspecteur de forme',
104
+ noSelection: 'Sélectionnez une forme pour modifier ses coordonnées exactes.',
105
+ nameLabel: 'Nom du calque',
106
+ xLabel: 'X en pixels',
107
+ yLabel: 'Y en pixels',
108
+ widthLabel: 'Largeur en pixels',
109
+ heightLabel: 'Hauteur en pixels',
110
+ radiusLabel: 'Rayon en pixels',
111
+ duplicateShape: 'Dupliquer',
112
+ mirrorShape: 'Miroir horizontal',
113
+ deleteShape: 'Supprimer la forme',
114
+ copyPrevious: 'Copier l\'image précédente ici',
115
+ copyAll: 'Copier sur toutes les images',
116
+ pivotTitle: 'Pivot d\'image',
117
+ pivotXLabel: 'Pivot X',
118
+ pivotYLabel: 'Pivot Y',
119
+ exportTitle: 'Exporter le projet',
120
+ exportJson: 'Télécharger le JSON',
121
+ importJson: 'Importer un JSON',
122
+ exportContactSheet: 'Télécharger la planche de contact',
123
+ resetProject: 'Réinitialiser les calques',
124
+ undo: 'Annuler',
125
+ redo: 'Rétablir',
126
+ statusReady: 'La table d\'animation est prête.',
127
+ statusImageLoaded: '{count} fichiers d\'image chargés.',
128
+ statusShapeCreated: 'Forme de collision ajoutée.',
129
+ statusShapeUpdated: 'Forme mise à jour.',
130
+ statusImported: 'Projet importé.',
131
+ statusExported: 'Exportation prête.',
132
+ statusError: 'Impossible de lire le fichier sélectionné.',
133
+ framesBadge: '{count} images',
134
+ shapesBadge: '{count} formes',
135
+ coverageBadge: '{percent}% couvert',
136
+ coordinatesNote: 'Les coordonnées utilisent le coin supérieur gauche de chaque image comme origine (0,0).',
137
+ localOnlyDisclosure: 'Le fichier JSON stocke les noms d\'images, pivots et formes sans inclure les pixels.',
138
+ limitationDisclosure: 'Les calques définissent des zones géométriques. Testez-les directement dans votre moteur de jeu.',
139
+ },
140
+ seo: [
141
+ {
142
+ type: 'title',
143
+ level: 2,
144
+ text: 'Concevoir des hitboxes et hurtboxes adaptées au mouvement réel',
145
+ },
146
+ {
147
+ type: 'paragraph',
148
+ html: 'Régler les collisions devient complexe quand chaque image est analysée séparément. Cet éditeur rassemble l\'image du sprite, les calques de collision, la pelure d\'oignon et la chronologie pour garantir la continuité du mouvement.',
149
+ },
150
+ {
151
+ type: 'title',
152
+ level: 2,
153
+ text: 'Choisir chaque calque selon sa fonction dans le jeu',
154
+ },
155
+ {
156
+ type: 'table',
157
+ headers: ['Calque', 'Rôle principal', 'Question à vérifier'],
158
+ rows: [
159
+ ['Hitbox', 'Zone qui inflige une attaque ou un effet', 'Apparaît-elle uniquement pendant les images actives ?'],
160
+ ['Hurtbox', 'Zone qui reçoit une attaque', 'Suit-elle la silhouette sans écarts inutiles ?'],
161
+ ['Pushbox', 'Zone de collision physique entre personnages', 'Reste-t-elle stable pour éviter les secousses ?'],
162
+ ['Grabbox', 'Portée pour déclencher une prise', 'Le timing correspond-il à l\'animation visuelle ?'],
163
+ ['Sensor', 'Zone de détection pour les interactions', 'Le nom est-il suffisamment explicite ?'],
164
+ ],
165
+ },
166
+ {
167
+ type: 'title',
168
+ level: 2,
169
+ text: 'Comprendre et appliquer le système de coordonnées',
170
+ },
171
+ {
172
+ type: 'paragraph',
173
+ html: 'Le projet exporté mesure X et Y depuis le coin supérieur gauche de chaque image découpée. Les dimensions sont positives et exprimées en pixels, facilitant la réutilisation dans votre moteur.',
174
+ },
175
+ {
176
+ type: 'tip',
177
+ title: 'Vérifier l\'ensemble de la séquence d\'attaque',
178
+ html: 'Relancez l\'animation complète après chaque modification pour valider la fluidité du geste.',
179
+ },
180
+ {
181
+ type: 'title',
182
+ level: 2,
183
+ text: 'Utiliser la planche de contact pour les revues d\'équipe',
184
+ },
185
+ {
186
+ type: 'paragraph',
187
+ html: 'La planche de contact PNG affiche toutes les images et leurs calques sur un seul visuel, idéal pour échanger entre graphistes et développeurs.',
188
+ },
189
+ ],
190
+ faq,
191
+ bibliographyTitle: 'Références sur la gestion des collisions',
192
+ bibliography: bibliographyEntries,
193
+ howTo,
194
+ schemas: [softwareApplication, faqPage, howToSchema],
195
+ };
@@ -0,0 +1,195 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { HitboxHurtboxAnimatorUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const slug = 'animator-hitbox-hurtbox-sprite';
7
+ const title = 'Animator Hitbox dan Hurtbox Sprite';
8
+ const description = 'Buat lapisan tabrakan pada setiap bingkai sprite, pratinjau animasi dengan fitur onion skin, sesuaikan koordinat piksel, dan ekspor JSON terstruktur.';
9
+
10
+ const faq = [
11
+ {
12
+ question: 'Apa perbedaan antara hitbox dan hurtbox?',
13
+ answer: 'Hitbox menandai area serangan, sedangkan hurtbox menandai area yang dapat menerima serangan. Pushbox mengatur jarak antar karakter, grabbox menentukan jangkauan tangkapan, dan sensor berfungsi sebagai area deteksi.',
14
+ },
15
+ {
16
+ question: 'Apakah gambar sprite saya diunggah ke server?',
17
+ answer: 'Tidak. Seluruh pemrosesan gambar dilakukan di dalam peramban Anda. Alat ini hanya menyimpan pengaturan preferensi secara lokal.',
18
+ },
19
+ {
20
+ question: 'Sistem koordinat apa yang digunakan oleh ekspor JSON?',
21
+ answer: 'Setiap bingkai mengukur koordinat piksel dari sudut kiri atas. Nilai lebar, tinggi, dan posisi titik pivot disimpan dalam koordinat lokal.',
22
+ },
23
+ {
24
+ question: 'Bisakah saya mengedit lembaran sprite dan gambar bingkai terpisah?',
25
+ answer: 'Ya. Anda dapat memuat satu lembaran sprite PNG/WebP dengan mengatur jumlah baris dan kolom, atau memilih beberapa gambar berurutan.',
26
+ },
27
+ {
28
+ question: 'Apakah hasil ekspor dapat langsung digunakan di mesin game?',
29
+ answer: 'Format JSON bersifat netral dan dapat adaptasikan. Format ini menyimpan posisi kotak, titik pivot, dan bentuk geometri tanpa terikat pada mesin game tertentu.',
30
+ },
31
+ ];
32
+
33
+ const howTo = [
34
+ { name: 'Muat gambar animasi', text: 'Pilih lembaran sprite PNG/WebP atau urutan gambar bingkai. Pemrosesan dilakukan secara lokal di perangkat Anda.' },
35
+ { name: 'Atur potong bingkai', text: 'Tentukan jumlah baris dan kolom untuk lembaran sprite dan periksa setiap bingkai pada bilah waktu.' },
36
+ { name: 'Gambar lapisan tabrakan', text: 'Pilih jenis hitbox, hurtbox, pushbox, atau sensor, lalu buat bentuk persegi atau lingkaran.' },
37
+ { name: 'Adjust gerakan animasi', text: 'Edit koordinat secara presisi, salin bentuk ke bingkai lain, dan gunakan onion skin untuk melihat animasi sebelumnya.' },
38
+ { name: 'Ekspor proyek JSON', text: 'Unduh berkas JSON dan lembaran kontak PNG. Simpan gambar asli bersama berkas JSON.' },
39
+ ];
40
+
41
+ const softwareApplication: WithContext<SoftwareApplication> = {
42
+ '@context': 'https://schema.org',
43
+ '@type': 'SoftwareApplication',
44
+ name: title,
45
+ applicationCategory: 'DeveloperApplication',
46
+ operatingSystem: 'Any',
47
+ };
48
+
49
+ const faqPage: WithContext<FAQPage> = {
50
+ '@context': 'https://schema.org',
51
+ '@type': 'FAQPage',
52
+ mainEntity: faq.map((item) => ({
53
+ '@type': 'Question',
54
+ name: item.question,
55
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
56
+ })),
57
+ };
58
+
59
+ const howToSchema: WithContext<HowTo> = {
60
+ '@context': 'https://schema.org',
61
+ '@type': 'HowTo',
62
+ name: title,
63
+ step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })),
64
+ };
65
+
66
+ export const content: ToolLocaleContent<HitboxHurtboxAnimatorUI> = {
67
+ slug,
68
+ title,
69
+ description,
70
+ ui: {
71
+ onboarding: 'Muat animasi sprite, atur potongan bingkai, dan buat area serangan, area terkena dampak, atau area pergerakan fisika.',
72
+ privacyNote: 'Meja kerja lokal. Gambar tidak diunggah ke server.',
73
+ loadSprite: 'Muat gambar ke area kerja',
74
+ loadHint: 'Pilih satu lembaran sprite atau beberapa file PNG/WebP berurutan.',
75
+ chooseImages: 'Pilih gambar sprite',
76
+ slicingTitle: 'Pemotongan bingkai',
77
+ rowsLabel: 'Baris',
78
+ columnsLabel: 'Kolom',
79
+ applySlicing: 'Potong bingkai',
80
+ playbackTitle: 'Pratinjau gerakan',
81
+ previousFrame: 'Bingkai sebelumnya',
82
+ play: 'Putar',
83
+ pause: 'Jeda',
84
+ nextFrame: 'Bingkai berikutnya',
85
+ fpsLabel: 'Bingkai per detik',
86
+ onionPrevious: 'Lapisan sebelumnya',
87
+ onionNext: 'Lapisan berikutnya',
88
+ layerTitle: 'Lapisan tabrakan',
89
+ typeHitbox: 'Hitbox',
90
+ typeHurtbox: 'Hurtbox',
91
+ typePushbox: 'Pushbox',
92
+ typeGrabbox: 'Grabbox',
93
+ typeSensor: 'Sensor',
94
+ typeCustom: 'Kustom',
95
+ shapeRectangle: 'Persegi Panjang',
96
+ shapeCircle: 'Lingkaran',
97
+ drawShape: 'Gambar',
98
+ selectShape: 'Pilih',
99
+ stageLabel: 'Area animasi',
100
+ emptyStage: 'Muat gambar sprite untuk mulai membuat lapisan tabrakan.',
101
+ frameReadout: 'Bingkai {current} dari {total}',
102
+ timelineTitle: 'Bilah animasi',
103
+ inspectorTitle: 'Inspektur bentuk',
104
+ noSelection: 'Pilih bentuk untuk mengubah nilai koordinat secara presisi.',
105
+ nameLabel: 'Nama lapisan',
106
+ xLabel: 'X dalam piksel',
107
+ yLabel: 'Y dalam piksel',
108
+ widthLabel: 'Lebar dalam piksel',
109
+ heightLabel: 'Tinggi dalam piksel',
110
+ radiusLabel: 'Jari-jari dalam piksel',
111
+ duplicateShape: 'Duplikat',
112
+ mirrorShape: 'Cermin horizontal',
113
+ deleteShape: 'Hapus bentuk',
114
+ copyPrevious: 'Salin bingkai sebelumnya ke sini',
115
+ copyAll: 'Salin bingkai ini ke semua',
116
+ pivotTitle: 'Titik pivot',
117
+ pivotXLabel: 'Pivot X',
118
+ pivotYLabel: 'Pivot Y',
119
+ exportTitle: 'Ekspor proyek',
120
+ exportJson: 'Unduh JSON',
121
+ importJson: 'Impor JSON',
122
+ exportContactSheet: 'Unduh lembar kontak',
123
+ resetProject: 'Reset lapisan',
124
+ undo: 'Batal',
125
+ redo: 'Ulangi',
126
+ statusReady: 'Area kerja siap.',
127
+ statusImageLoaded: '{count} file gambar dimuat.',
128
+ statusShapeCreated: 'Bentuk tabrakan baru ditambahkan.',
129
+ statusShapeUpdated: 'Bentuk tabrakan diperbarui.',
130
+ statusImported: 'Proyek berhasil diimpor.',
131
+ statusExported: 'Berkas ekspor siap.',
132
+ statusError: 'File tidak dapat dibaca.',
133
+ framesBadge: '{count} bingkai',
134
+ shapesBadge: '{count} bentuk',
135
+ coverageBadge: '{percent}% cakupan',
136
+ coordinatesNote: 'Koordinat dihitung dari sudut kiri atas bingkai sebagai titik asal (0,0).',
137
+ localOnlyDisclosure: 'Berkas JSON menyimpan data bentuk dan titik pivot tanpa menyertakan data gambar.',
138
+ limitationDisclosure: 'Lapisan ini merupakan panduan geometri desain. Uji kembali di dalam mesin game Anda.',
139
+ },
140
+ seo: [
141
+ {
142
+ type: 'title',
143
+ level: 2,
144
+ text: 'Desain hitbox dan hurtbox sesuai dengan gerakan sprite',
145
+ },
146
+ {
147
+ type: 'paragraph',
148
+ html: 'Mengatur area tabrakan menjadi rumit jika setiap bingkai dianalisis secara terpisah. Alat ini menggabungkan tampilan sprite, lapisan tabrakan, dan alur animasi untuk memastikan konsistensi gerakan.',
149
+ },
150
+ {
151
+ type: 'title',
152
+ level: 2,
153
+ text: 'Pilih jenis lapisan sesuai dengan fungsi permainan',
154
+ },
155
+ {
156
+ type: 'table',
157
+ headers: ['Lapisan', 'Fungsi Utama', 'Hal yang Perlu Diperiksa'],
158
+ rows: [
159
+ ['Hitbox', 'Area yang menghasilkan serangan', 'Apakah hanya aktif pada bingkai yang tepat?'],
160
+ ['Hurtbox', 'Area yang menerima serangan', 'Apakah mengikuti bentuk karakter dengan pas?'],
161
+ ['Pushbox', 'Area tabrakan fisik antar karakter', 'Apakah ukurannya stabil agar tidak bergetar?'],
162
+ ['Grabbox', 'Jangkauan untuk tangkapan', 'Apakah waktunya sesuai dengan animasi visual?'],
163
+ ['Sensor', 'Area deteksi pemicu atau interaksi', 'Apakah namanya sudah cukup jelas?'],
164
+ ],
165
+ },
166
+ {
167
+ type: 'title',
168
+ level: 2,
169
+ text: 'Memahami sistem koordinat bingkai',
170
+ },
171
+ {
172
+ type: 'paragraph',
173
+ html: 'Proyek JSON yang diekspor mengukur posisi X dan Y dari sudut kiri atas setiap bingkai. Nilai lebar dan tinggi disimpan dalam ukuran piksel asli.',
174
+ },
175
+ {
176
+ type: 'tip',
177
+ title: 'Periksa seluruh urutan gerakan animasi',
178
+ html: 'Putar animasi secara penuh setelah mengubah satu bingkai untuk memastikan alur gerakan tetap halus.',
179
+ },
180
+ {
181
+ type: 'title',
182
+ level: 2,
183
+ text: 'Gunakan lembaran kontak untuk peninjauan tim',
184
+ },
185
+ {
186
+ type: 'paragraph',
187
+ html: 'Lembaran kontak PNG menampilkan semua bingkai dan lapisan tabrakan dalam satu gambar untuk mempermudah komunikasi tim.',
188
+ },
189
+ ],
190
+ faq,
191
+ bibliographyTitle: 'Referensi desain area tabrakan',
192
+ bibliography: bibliographyEntries,
193
+ howTo,
194
+ schemas: [softwareApplication, faqPage, howToSchema],
195
+ };
@@ -0,0 +1,195 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { HitboxHurtboxAnimatorUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const slug = 'animatore-hitbox-hurtbox-sprite';
7
+ const title = 'Animatore Hitbox e Hurtbox per Sprite';
8
+ const description = 'Disegna livelli di collisione su ogni fotogramma dello sprite, anteprima con carta cipolla, modifica coordinate in pixel ed esporta JSON neutro.';
9
+
10
+ const faq = [
11
+ {
12
+ question: 'Qual è la differenza tra hitbox e hurtbox?',
13
+ answer: 'Una hitbox definisce l area che infligge un attacco, mentre una hurtbox definisce l area vulnerabile che lo riceve. Le pushbox mantengono la distanza tra i personaggi e le grabbox regolano le prese.',
14
+ },
15
+ {
16
+ question: 'I miei file di immagini vengono caricati online?',
17
+ answer: 'No. Le immagini vengono elaborate ed esportate interamente nel tuo browser. Vengono salvate localmente solo le preferenze dell editor.',
18
+ },
19
+ {
20
+ question: 'Quale sistema di coordinate utilizza l esportazione JSON?',
21
+ answer: 'Ogni fotogramma misura le coordinate in pixel dall angolo in alto a sinistra. Le dimensioni di larghezza e altezza memorizzano valori positivi con il proprio perno.',
22
+ },
23
+ {
24
+ question: 'Posso modificare uno spritesheet o fotogrammi singoli?',
25
+ answer: 'Sì. Puoi caricare uno spritesheet PNG/WebP indicando righe e colonne, oppure selezionare più immagini ordinate.',
26
+ },
27
+ {
28
+ question: 'L esportazione funziona in tutti i motori di gioco?',
29
+ answer: 'Il formato JSON è neutro. Salva i rettangoli dei fotogrammi, i perni e i livelli geometrici senza imporre la struttura di un motore specifico.',
30
+ },
31
+ ];
32
+
33
+ const howTo = [
34
+ { name: 'Carica la grafica', text: 'Seleziona uno spritesheet PNG/WebP o immagini ordinate. L elaborazione rimane locale sul tuo dispositivo.' },
35
+ { name: 'Definisci i fotogrammi', text: 'Imposta righe e colonne per uno spritesheet e verifica il ritaglio dei fotogrammi sulla sequenza temporale.' },
36
+ { name: 'Disegna i livelli di collisione', text: 'Scegli un livello hitbox, hurtbox, pushbox o sensore, quindi traccia un rettangolo o un cerchio.' },
37
+ { name: 'Rifinisci il movimento', text: 'Modifica le coordinate esatte, copia le forme su fotogrammi vicini e usa la carta cipolla.' },
38
+ { name: 'Esporta il progetto', text: 'Scarica il file JSON neutro e una scheda di contatto PNG. Conserva le immagini originali.' },
39
+ ];
40
+
41
+ const softwareApplication: WithContext<SoftwareApplication> = {
42
+ '@context': 'https://schema.org',
43
+ '@type': 'SoftwareApplication',
44
+ name: title,
45
+ applicationCategory: 'DeveloperApplication',
46
+ operatingSystem: 'Any',
47
+ };
48
+
49
+ const faqPage: WithContext<FAQPage> = {
50
+ '@context': 'https://schema.org',
51
+ '@type': 'FAQPage',
52
+ mainEntity: faq.map((item) => ({
53
+ '@type': 'Question',
54
+ name: item.question,
55
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
56
+ })),
57
+ };
58
+
59
+ const howToSchema: WithContext<HowTo> = {
60
+ '@context': 'https://schema.org',
61
+ '@type': 'HowTo',
62
+ name: title,
63
+ step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })),
64
+ };
65
+
66
+ export const content: ToolLocaleContent<HitboxHurtboxAnimatorUI> = {
67
+ slug,
68
+ title,
69
+ description,
70
+ ui: {
71
+ onboarding: 'Carica un animazione, conferma i ritagli dei fotogrammi e disegna le aree di attacco, danno o collisione.',
72
+ privacyNote: 'Tavolo di animazione locale. Le immagini non vengono caricate online.',
73
+ loadSprite: 'Metti l immagine sul tavolo di lavoro',
74
+ loadHint: 'Scegli uno spritesheet o immagini PNG/WebP ordinate.',
75
+ chooseImages: 'Scegli immagini',
76
+ slicingTitle: 'Ritaglio fotogrammi',
77
+ rowsLabel: 'Righe',
78
+ columnsLabel: 'Colonne',
79
+ applySlicing: 'Ritaglia',
80
+ playbackTitle: 'Anteprima movimento',
81
+ previousFrame: 'Fotogramma precedente',
82
+ play: 'Riproduci',
83
+ pause: 'Pausa',
84
+ nextFrame: 'Fotogramma successivo',
85
+ fpsLabel: 'Fotogrammi al secondo',
86
+ onionPrevious: 'FOGLIO precedente',
87
+ onionNext: 'FOGLIO successivo',
88
+ layerTitle: 'Livelli di collisione',
89
+ typeHitbox: 'Hitbox',
90
+ typeHurtbox: 'Hurtbox',
91
+ typePushbox: 'Pushbox',
92
+ typeGrabbox: 'Grabbox',
93
+ typeSensor: 'Sensore',
94
+ typeCustom: 'Personalizzato',
95
+ shapeRectangle: 'Rettangolo',
96
+ shapeCircle: 'Cerchio',
97
+ drawShape: 'Disegna',
98
+ selectShape: 'Seleziona',
99
+ stageLabel: 'Area di lavoro',
100
+ emptyStage: 'Carica le immagini per iniziare a disegnare i livelli di collisione.',
101
+ frameReadout: 'Fotogramma {current} di {total}',
102
+ timelineTitle: 'Sequenza fotogrammi',
103
+ inspectorTitle: 'Ispettore forma',
104
+ noSelection: 'Seleziona una forma per modificarne le coordinate esatte.',
105
+ nameLabel: 'Nome livello',
106
+ xLabel: 'X in pixel',
107
+ yLabel: 'Y in pixel',
108
+ widthLabel: 'Larghezza in pixel',
109
+ heightLabel: 'Altezza in pixel',
110
+ radiusLabel: 'Raggio in pixel',
111
+ duplicateShape: 'Duplica',
112
+ mirrorShape: 'Rifletti orizzontalmente',
113
+ deleteShape: 'Elimina forma',
114
+ copyPrevious: 'Copia fotogramma precedente qui',
115
+ copyAll: 'Copia su tutti i fotogrammi',
116
+ pivotTitle: 'Perno fotogramma',
117
+ pivotXLabel: 'Perno X',
118
+ pivotYLabel: 'Perno Y',
119
+ exportTitle: 'Esporta progetto',
120
+ exportJson: 'Scarica JSON',
121
+ importJson: 'Importa JSON',
122
+ exportContactSheet: 'Scarica scheda di contatto',
123
+ resetProject: 'Ripristina livelli',
124
+ undo: 'Annulla',
125
+ redo: 'Ripristina',
126
+ statusReady: 'Il tavolo di lavoro è pronto.',
127
+ statusImageLoaded: '{count} file immagine caricati.',
128
+ statusShapeCreated: 'Forma di collisione aggiunta.',
129
+ statusShapeUpdated: 'Forma aggiornata.',
130
+ statusImported: 'Progetto importato.',
131
+ statusExported: 'Esportazione pronta.',
132
+ statusError: 'Impossibile leggere il file selezionato.',
133
+ framesBadge: '{count} fotogrammi',
134
+ shapesBadge: '{count} forme',
135
+ coverageBadge: '{percent}% coperto',
136
+ coordinatesNote: 'Le coordinate usano l angolo in alto a sinistra di ogni fotogramma come origine (0,0).',
137
+ localOnlyDisclosure: 'Il file JSON memorizza nomi delle immagini, perni e forme senza includere i pixel.',
138
+ limitationDisclosure: 'I livelli definiscono aree geometriche di design. Testali direttamente nel tuo motore di gioco.',
139
+ },
140
+ seo: [
141
+ {
142
+ type: 'title',
143
+ level: 2,
144
+ text: 'Progetta hitbox e hurtbox allineate al movimento reale dello sprite',
145
+ },
146
+ {
147
+ type: 'paragraph',
148
+ html: 'Configurare le collisioni risulta complesso quando ogni fotogramma viene analizzato singolarmente. Questo editor unisce l immagine dello sprite, i livelli di collisione, la carta cipolla e la sequenza temporale per garantire la fluidità del movimento.',
149
+ },
150
+ {
151
+ type: 'title',
152
+ level: 2,
153
+ text: 'Scegli ogni livello in base alla funzione di gioco',
154
+ },
155
+ {
156
+ type: 'table',
157
+ headers: ['Livello', 'Ruolo principale', 'Aspetto da verificare'],
158
+ rows: [
159
+ ['Hitbox', 'Area che infligge un attacco o effetto', 'Compare solo nei fotogrammi attivi previsti?'],
160
+ ['Hurtbox', 'Area che riceve attacchi o danni', 'Segue la silhouette senza spazi innaturali?'],
161
+ ['Pushbox', 'Area di collisione fisica tra personaggi', 'Rimani stabile per evitare scatti visibili?'],
162
+ ['Grabbox', 'Raggio d azione per avviare una presa', 'Il timing corrisponde all animazione visiva?'],
163
+ ['Sensor', 'Area di rilevamento per interazioni', 'Il nome è abbastanza chiaro per l implementazione?'],
164
+ ],
165
+ },
166
+ {
167
+ type: 'title',
168
+ level: 2,
169
+ text: 'Comprendere e applicare il sistema di coordinate',
170
+ },
171
+ {
172
+ type: 'paragraph',
173
+ html: 'Il progetto esportato misura X e Y dall angolo in alto a sinistra di ogni fotogramma ritagliato. Le dimensioni di larghezza e altezza sono valori positivi espressi in pixel.',
174
+ },
175
+ {
176
+ type: 'tip',
177
+ title: 'Verifica l intera sequenza di attacco',
178
+ html: 'Riproduci l animazione completa dopo aver modificato un fotogramma per confermare la continuità del movimento.',
179
+ },
180
+ {
181
+ type: 'title',
182
+ level: 2,
183
+ text: 'Utilizza la scheda di contatto per la revisione con il team',
184
+ },
185
+ {
186
+ type: 'paragraph',
187
+ html: 'La scheda di contatto PNG mostra tutti i fotogrammi e i loro livelli di colore su un unica immagine, ideale per la collaborazione tra artisti e programmatori.',
188
+ },
189
+ ],
190
+ faq,
191
+ bibliographyTitle: 'Riferimenti per lo sviluppo delle collisioni',
192
+ bibliography: bibliographyEntries,
193
+ howTo,
194
+ schemas: [softwareApplication, faqPage, howToSchema],
195
+ };