@jjlmoya/utils-games-development 1.62.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.
- package/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +4 -1
- package/src/index.ts +1 -0
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/hitboxHurtboxAnimator/bibliography.astro +12 -0
- package/src/tool/hitboxHurtboxAnimator/bibliography.ts +10 -0
- package/src/tool/hitboxHurtboxAnimator/canvas-interactions.ts +59 -0
- package/src/tool/hitboxHurtboxAnimator/canvas-metrics.ts +8 -0
- package/src/tool/hitboxHurtboxAnimator/component.astro +148 -0
- package/src/tool/hitboxHurtboxAnimator/controller.ts +247 -0
- package/src/tool/hitboxHurtboxAnimator/dom-views.ts +194 -0
- package/src/tool/hitboxHurtboxAnimator/editor-state.ts +19 -0
- package/src/tool/hitboxHurtboxAnimator/entry.ts +28 -0
- package/src/tool/hitboxHurtboxAnimator/evaluator.ts +15 -0
- package/src/tool/hitboxHurtboxAnimator/file-io.ts +82 -0
- package/src/tool/hitboxHurtboxAnimator/hitbox-hurtbox-animator.css +614 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/de.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/en.ts +191 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/es.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/fr.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/id.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/it.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/ja.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/ko.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/nl.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/pl.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/pt.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/ru.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/sv.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/tr.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/i18n/zh.ts +195 -0
- package/src/tool/hitboxHurtboxAnimator/index.ts +11 -0
- package/src/tool/hitboxHurtboxAnimator/logic.test.ts +97 -0
- package/src/tool/hitboxHurtboxAnimator/logic.ts +173 -0
- package/src/tool/hitboxHurtboxAnimator/project-actions.ts +128 -0
- package/src/tool/hitboxHurtboxAnimator/seo.astro +13 -0
- package/src/tool/hitboxHurtboxAnimator/storage.ts +27 -0
- package/src/tool/hitboxHurtboxAnimator/ui.ts +70 -0
- package/src/tools.ts +2 -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 = 'animator-hitbox-hurtbox-sprites';
|
|
7
|
+
const title = 'Animator Hitbox i Hurtbox dla Spritów';
|
|
8
|
+
const description = 'Rysuj warstwy kolizji na klatkach spritów, podglądaj ruch za pomocą cebulki (onion skin), edytuj dokładne współrzędne w pikselach i eksportuj neutralny plik JSON.';
|
|
9
|
+
|
|
10
|
+
const faq = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Jaka jest różnica między hitboxem a hurtboxem?',
|
|
13
|
+
answer: 'Hitbox określa obszar zadający atak, natomiast hurtbox definiuje obszar wrażliwy na trafienie. Pushboxy utrzymują dystans między postaciami, a grabboxy określają zasięg rzutów.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
question: 'Czy moje pliki graficzne opuszczają przeglądarkę?',
|
|
17
|
+
answer: 'Nie. Obrazy są przetwarzane i eksportowane w 100% w Twojej przeglądarce. W pamięci lokalnej zapisywane są jedynie preferencje edytora.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
question: 'Jaki układ współrzędnych wykorzystuje eksport JSON?',
|
|
21
|
+
answer: 'Każda klatka mierzy piksele od lewego górnego rogu wycięcia. Wymiary szerokości i wysokości są zapisywane jako wartości dodatnie z własnym punktem kotwiczenia (pivot).',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
question: 'Czy mogę edytować arkusze spritów i pojedyncze pliki klatek?',
|
|
25
|
+
answer: 'Tak. Możesz załadować arkusz PNG/WebP podając liczbę wierszy i kolumn lub wybrać sekwencję uporządkowanych plików.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
question: 'Czy eksport działa bezpośrednio w każdym silniku gry?',
|
|
29
|
+
answer: 'Format JSON jest neutralny dla silników. Zapisuje wycięcia klatek, punkty kotwiczenia i geometrie bez narzucania konkretnej struktury silnika.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howTo = [
|
|
34
|
+
{ name: 'Załaduj grafikę', text: 'Wybierz arkusz spritów PNG/WebP lub sekwencję plików. Przetwarzanie odbywa się lokalnie.' },
|
|
35
|
+
{ name: 'Zdefiniuj klatki', text: 'Podaj liczbę wierszy i kolumn i sprawdź wycięcia klatek na taśmie animacji.' },
|
|
36
|
+
{ name: 'Rysuj warstwy kolizji', text: 'Wybierz warstwę hitbox, hurtbox, pushbox lub sensor i narysuj prostokąt lub koło.' },
|
|
37
|
+
{ name: 'Dopasuj ruch w czasie', text: 'Edytuj dokładne współrzędne, kopiuj kształty na sąsiednie klatki i używaj podglądu cebulki.' },
|
|
38
|
+
{ name: 'Eksportuj projekt', text: 'Pobierz neutralny plik JSON i arkusz styków PNG. Przechowuj oryginalne pliki graficzne razem z 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: 'Załaduj animację, potwierdź podział klatek i narysuj obszary ataku, trafienia, kolizji fizycznej lub detekcji.',
|
|
72
|
+
privacyNote: 'Stół animacyjny lokalny. Pliki graficzne nie są wysyłane na serwer.',
|
|
73
|
+
loadSprite: 'Umieść grafikę na stole montażowym',
|
|
74
|
+
loadHint: 'Wybierz arkusz spritów lub sekwencję uporządkowanych plików PNG/WebP.',
|
|
75
|
+
chooseImages: 'Wybierz pliki graficzne',
|
|
76
|
+
slicingTitle: 'Podział klatek',
|
|
77
|
+
rowsLabel: 'Wiersze',
|
|
78
|
+
columnsLabel: 'Kolumny',
|
|
79
|
+
applySlicing: 'Tnij klatki',
|
|
80
|
+
playbackTitle: 'Podgląd ruchu',
|
|
81
|
+
previousFrame: 'Poprzednia klatka',
|
|
82
|
+
play: 'Odtwarzaj',
|
|
83
|
+
pause: 'Pauza',
|
|
84
|
+
nextFrame: 'Następna klatka',
|
|
85
|
+
fpsLabel: 'Klatki na sekundę',
|
|
86
|
+
onionPrevious: 'Cebulka poprzednia',
|
|
87
|
+
onionNext: 'Cebulka następna',
|
|
88
|
+
layerTitle: 'Warstwy kolizji',
|
|
89
|
+
typeHitbox: 'Hitbox',
|
|
90
|
+
typeHurtbox: 'Hurtbox',
|
|
91
|
+
typePushbox: 'Pushbox',
|
|
92
|
+
typeGrabbox: 'Grabbox',
|
|
93
|
+
typeSensor: 'Czujnik',
|
|
94
|
+
typeCustom: 'Własny',
|
|
95
|
+
shapeRectangle: 'Prostokąt',
|
|
96
|
+
shapeCircle: 'Koło',
|
|
97
|
+
drawShape: 'Rysuj',
|
|
98
|
+
selectShape: 'Zaznacz',
|
|
99
|
+
stageLabel: 'Obszar roboczy',
|
|
100
|
+
emptyStage: 'Załaduj grafikę, aby rozpocząć rysowanie warstw kolizji.',
|
|
101
|
+
frameReadout: 'Klatka {current} z {total}',
|
|
102
|
+
timelineTitle: 'Taśma klatek',
|
|
103
|
+
inspectorTitle: 'Inspektor kształtu',
|
|
104
|
+
noSelection: 'Zaznacz kształt, aby edytować jego dokładne wartości.',
|
|
105
|
+
nameLabel: 'Nazwa warstwy',
|
|
106
|
+
xLabel: 'X w pikselach',
|
|
107
|
+
yLabel: 'Y w pikselach',
|
|
108
|
+
widthLabel: 'Szerokość w pikselach',
|
|
109
|
+
heightLabel: 'Wysokość w pikselach',
|
|
110
|
+
radiusLabel: 'Promień w pikselach',
|
|
111
|
+
duplicateShape: 'Duplikuj',
|
|
112
|
+
mirrorShape: 'Odbij w poziomie',
|
|
113
|
+
deleteShape: 'Usuń kształt',
|
|
114
|
+
copyPrevious: 'Kopiuj poprzednią klatkę tutaj',
|
|
115
|
+
copyAll: 'Kopiuj tę klatkę do wszystkich',
|
|
116
|
+
pivotTitle: 'Punkt kotwiczenia (Pivot)',
|
|
117
|
+
pivotXLabel: 'Pivot X',
|
|
118
|
+
pivotYLabel: 'Pivot Y',
|
|
119
|
+
exportTitle: 'Eksportuj projekt',
|
|
120
|
+
exportJson: 'Pobierz JSON',
|
|
121
|
+
importJson: 'Importuj JSON',
|
|
122
|
+
exportContactSheet: 'Pobierz arkusz styków',
|
|
123
|
+
resetProject: 'Zresetuj warstwy',
|
|
124
|
+
undo: 'Cofnij',
|
|
125
|
+
redo: 'Ponów',
|
|
126
|
+
statusReady: 'Stół montażowy jest gotowy.',
|
|
127
|
+
statusImageLoaded: 'Załadowano {count} plików graficznych.',
|
|
128
|
+
statusShapeCreated: 'Dodano nowy kształt kolizji.',
|
|
129
|
+
statusShapeUpdated: 'Zaktualizowano kształt.',
|
|
130
|
+
statusImported: 'Zaiportowano projekt.',
|
|
131
|
+
statusExported: 'Przygotowano eksport.',
|
|
132
|
+
statusError: 'Nie można odczytać wybranego pliku.',
|
|
133
|
+
framesBadge: '{count} klatek',
|
|
134
|
+
shapesBadge: '{count} kształtów',
|
|
135
|
+
coverageBadge: '{percent}% pokrycia',
|
|
136
|
+
coordinatesNote: 'Współrzędne używają lewego górnego rogu każdej klatki jako punktu (0,0).',
|
|
137
|
+
localOnlyDisclosure: 'Plik JSON zapisuje nazwy plików, punkty kotwiczenia i geometrie bez treści obrazu.',
|
|
138
|
+
limitationDisclosure: 'Warstwy definiują obszary projektowe. Przetestuj ich działanie w swoim silniku gry.',
|
|
139
|
+
},
|
|
140
|
+
seo: [
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
level: 2,
|
|
144
|
+
text: 'Projektuj hitboxy i hurtboxy dopasowane do ruchu sprita',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'paragraph',
|
|
148
|
+
html: 'Ustawianie kolizji staje się trudne, gdy każda klatka jest analizowana osobno. Ten edytor łączy podgląd sprita, warstwy kolizji, podgląd cebulki i linię czasu.',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: 'title',
|
|
152
|
+
level: 2,
|
|
153
|
+
text: 'Wybieraj warstwy kolizji według ich roli w grze',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'table',
|
|
157
|
+
headers: ['Warstwa', 'Rola główna', 'Punkt kontrolny'],
|
|
158
|
+
rows: [
|
|
159
|
+
['Hitbox', 'Obszar zadający atak', 'Czy pojawia się tylko w aktywnych klatkach?'],
|
|
160
|
+
['Hurtbox', 'Obszar otrzymujący obrażenia', 'Czy przylega do sylwetki postaci bez luk?'],
|
|
161
|
+
['Pushbox', 'Fizyczna kolizja między postaciami', 'Czy jest stabilna, aby uniknąć drgań?'],
|
|
162
|
+
['Grabbox', 'Zasięg wykonania rzutu', 'Czy czas zgadza się z animacją?'],
|
|
163
|
+
['Sensor', 'Strefa detekcji zdarzeń', 'Czy nazwa jest jednoznaczna?'],
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'title',
|
|
168
|
+
level: 2,
|
|
169
|
+
text: 'Zrozumienie układu współrzędnych',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: 'paragraph',
|
|
173
|
+
html: 'Wyeksportowany projekt mierzy współrzędne X i Y od lewego górnego rogu każdej klatki. Wymiary są podawane w dodatnich pikselach.',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'tip',
|
|
177
|
+
title: 'Sprawdzaj pełną sekwencję animacji',
|
|
178
|
+
html: 'Odtwórz pełną animację po edycji klatki, aby upewnić się, że ruch jest płynny.',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'title',
|
|
182
|
+
level: 2,
|
|
183
|
+
text: 'Wykorzystaj arkusz styków w pracy zespołowej',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
type: 'paragraph',
|
|
187
|
+
html: 'Arkusz styków PNG pokazuje wszystkie klatki i ich warstwy na jednym obrazie, co ułatwia komunikację z zespołem.',
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
faq,
|
|
191
|
+
bibliographyTitle: 'Referencje dotyczące projektowania kolizji',
|
|
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 = 'animador-hitboxes-hurtboxes-sprites';
|
|
7
|
+
const title = 'Animador de Hitbox e Hurtbox para Sprites';
|
|
8
|
+
const description = 'Desenhe camadas de colisão em cada quadro do seu sprite, pré-visualize sequências com papel vegetal, ajuste coordenadas exatas em pixels e exporte JSON neutro.';
|
|
9
|
+
|
|
10
|
+
const faq = [
|
|
11
|
+
{
|
|
12
|
+
question: 'Qual é a diferença entre uma hitbox e uma hurtbox?',
|
|
13
|
+
answer: 'Uma hitbox define a área que aplica um ataque, enquanto uma hurtbox delimita a área vulnerável que recebe o dano. As pushboxes mantêm o afastamento entre personagens e as grabboxes definem o alcance de agarres.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
question: 'Os meus arquivos de sprites saem do navegador?',
|
|
17
|
+
answer: 'Não. As imagens são processadas e exportadas inteiramente no seu navegador. A ferramenta salva apenas preferências de edição no armazenamento local.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
question: 'Qual sistema de coordenadas o arquivo JSON exportado utiliza?',
|
|
21
|
+
answer: 'Cada quadro mede suas coordenadas em pixels tomando o canto superior esquerdo como origem (0,0). As dimensões armazenam valores positivos de x, y, largura e altura com seu próprio ponto pivô.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
question: 'Posso editar folhas de sprites completas e quadros avulsos?',
|
|
25
|
+
answer: 'Sim. Você pode carregar uma folha PNG ou WebP informando linhas e colunas, ou selecionar várias imagens ordenadas para criar a sequência.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
question: 'O arquivo exportado funciona diretamente em qualquer motor de jogo?',
|
|
29
|
+
answer: 'O formato JSON é neutro. Ele registra recortes de quadros, pontos pivô e camadas geométricas sem impor uma estrutura rígida de um motor específico.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howTo = [
|
|
34
|
+
{ name: 'Carregar arte de animação', text: 'Selecione uma folha de sprites PNG/WebP ou imagens ordenadas. O processamento é realizado localmente no seu dispositivo.' },
|
|
35
|
+
{ name: 'Definir os quadros', text: 'Informe o número de linhas e colunas para folhas de sprites e confira a tira de quadros.' },
|
|
36
|
+
{ name: 'Desenhar camadas de colisão', text: 'Escolha uma camada de hitbox, hurtbox, pushbox ou sensor e desenhe retângulos ou círculos sobre o quadro.' },
|
|
37
|
+
{ name: 'Refinar movimento no tempo', text: 'Ajuste coordenadas numéricas, copie formas para quadros vizinhos e use o papel vegetal para comparar o movimento.' },
|
|
38
|
+
{ name: 'Exportar projeto', text: 'Baixe o arquivo JSON neutro e uma folha de contatos PNG. Mantenha as imagens originais junto ao arquivo 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: 'Carregue uma animação, confirme o recorte dos quadros e desenhe as áreas de ataque, dano ou colisão física.',
|
|
72
|
+
privacyNote: 'Mesa de animação local. As imagens não são enviadas para servidores.',
|
|
73
|
+
loadSprite: 'Colocar arte na mesa de trabalho',
|
|
74
|
+
loadHint: 'Escolha uma folha de sprites ou várias imagens PNG/WebP ordenadas.',
|
|
75
|
+
chooseImages: 'Escolher imagens de sprite',
|
|
76
|
+
slicingTitle: 'Divisão de quadros',
|
|
77
|
+
rowsLabel: 'Linhas',
|
|
78
|
+
columnsLabel: 'Colunas',
|
|
79
|
+
applySlicing: 'Recortar quadros',
|
|
80
|
+
playbackTitle: 'Prévia do movimento',
|
|
81
|
+
previousFrame: 'Quadro anterior',
|
|
82
|
+
play: 'Reproduzir',
|
|
83
|
+
pause: 'Pausar',
|
|
84
|
+
nextFrame: 'Próximo quadro',
|
|
85
|
+
fpsLabel: 'Quadros por segundo',
|
|
86
|
+
onionPrevious: 'Vegetal anterior',
|
|
87
|
+
onionNext: 'Vegetal seguinte',
|
|
88
|
+
layerTitle: 'Camadas de colisão',
|
|
89
|
+
typeHitbox: 'Hitbox',
|
|
90
|
+
typeHurtbox: 'Hurtbox',
|
|
91
|
+
typePushbox: 'Pushbox',
|
|
92
|
+
typeGrabbox: 'Grabbox',
|
|
93
|
+
typeSensor: 'Sensor',
|
|
94
|
+
typeCustom: 'Personalizado',
|
|
95
|
+
shapeRectangle: 'Retângulo',
|
|
96
|
+
shapeCircle: 'Círculo',
|
|
97
|
+
drawShape: 'Desenhar',
|
|
98
|
+
selectShape: 'Selecionar',
|
|
99
|
+
stageLabel: 'Mesa de trabalho',
|
|
100
|
+
emptyStage: 'Carregue imagens para começar a desenhar camadas de colisão.',
|
|
101
|
+
frameReadout: 'Quadro {current} de {total}',
|
|
102
|
+
timelineTitle: 'Tira de quadros',
|
|
103
|
+
inspectorTitle: 'Inspetor de forma',
|
|
104
|
+
noSelection: 'Selecione uma forma para editar suas dimensões exatas.',
|
|
105
|
+
nameLabel: 'Nome da camada',
|
|
106
|
+
xLabel: 'X em pixels',
|
|
107
|
+
yLabel: 'Y em pixels',
|
|
108
|
+
widthLabel: 'Largura em pixels',
|
|
109
|
+
heightLabel: 'Altura em pixels',
|
|
110
|
+
radiusLabel: 'Raio em pixels',
|
|
111
|
+
duplicateShape: 'Duplicar',
|
|
112
|
+
mirrorShape: 'Espelhar horizontalmente',
|
|
113
|
+
deleteShape: 'Excluir forma',
|
|
114
|
+
copyPrevious: 'Copiar quadro anterior aqui',
|
|
115
|
+
copyAll: 'Copiar este quadro para todos',
|
|
116
|
+
pivotTitle: 'Pivô do quadro',
|
|
117
|
+
pivotXLabel: 'Pivô X',
|
|
118
|
+
pivotYLabel: 'Pivô Y',
|
|
119
|
+
exportTitle: 'Exportar projeto',
|
|
120
|
+
exportJson: 'Baixar JSON',
|
|
121
|
+
importJson: 'Importar JSON',
|
|
122
|
+
exportContactSheet: 'Baixar folha de contatos',
|
|
123
|
+
resetProject: 'Limpar camadas',
|
|
124
|
+
undo: 'Desfazer',
|
|
125
|
+
redo: 'Refazer',
|
|
126
|
+
statusReady: 'A mesa de trabalho está pronta.',
|
|
127
|
+
statusImageLoaded: '{count} arquivos de imagem carregados.',
|
|
128
|
+
statusShapeCreated: 'Forma de colisão adicionada.',
|
|
129
|
+
statusShapeUpdated: 'Forma atualizada.',
|
|
130
|
+
statusImported: 'Projeto importado.',
|
|
131
|
+
statusExported: 'Exportação pronta.',
|
|
132
|
+
statusError: 'Não foi possível ler o arquivo.',
|
|
133
|
+
framesBadge: '{count} quadros',
|
|
134
|
+
shapesBadge: '{count} formas',
|
|
135
|
+
coverageBadge: '{percent}% coberto',
|
|
136
|
+
coordinatesNote: 'As coordenadas usam o canto superior esquerdo de cada quadro como origem (0,0).',
|
|
137
|
+
localOnlyDisclosure: 'O JSON salva nomes de imagem, recortes, pivôs e geometrias sem conter dados de pixels.',
|
|
138
|
+
limitationDisclosure: 'As camadas definem regiões geométricas de design. Teste o comportamento no seu motor de jogo.',
|
|
139
|
+
},
|
|
140
|
+
seo: [
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
level: 2,
|
|
144
|
+
text: 'Projete hitboxes e hurtboxes alinhadas ao movimento do sprite',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'paragraph',
|
|
148
|
+
html: 'Configurar colisões torna-se complexo quando cada quadro é analisado isoladamente. Este editor reúne a imagem do sprite, camadas de colisão, papel vegetal e a linha do tempo para garantir a fluidez do movimento.',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: 'title',
|
|
152
|
+
level: 2,
|
|
153
|
+
text: 'Escolha cada camada segundo a lógica do jogo',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'table',
|
|
157
|
+
headers: ['Camada', 'Função principal', 'Ponto a verificar'],
|
|
158
|
+
rows: [
|
|
159
|
+
['Hitbox', 'Área que aplica um ataque ou efeito', 'Aparece apenas nos quadros ativos previstos?'],
|
|
160
|
+
['Hurtbox', 'Área que recebe dano ou ataques', 'Acompanha o corpo do personagem sem lacunas?'],
|
|
161
|
+
['Pushbox', 'Área de colisão física entre personagens', 'Permanece estável para evitar solavancos?'],
|
|
162
|
+
['Grabbox', 'Alcance para iniciar um agarre', 'O tempo coincide com a animação visual?'],
|
|
163
|
+
['Sensor', 'Área de detecção de interações', 'O nome está suficientemente claro?'],
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'title',
|
|
168
|
+
level: 2,
|
|
169
|
+
text: 'Compreender e aplicar o sistema de coordenadas',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: 'paragraph',
|
|
173
|
+
html: 'O projeto exportado mede X e Y a partir do canto superior esquerdo de cada quadro recortado. As dimensões são valores positivos em pixels.',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'tip',
|
|
177
|
+
title: 'Verifique a sequência completa da animação',
|
|
178
|
+
html: 'Reproduza a animação completa após alterar um quadro para garantir transições suaves.',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'title',
|
|
182
|
+
level: 2,
|
|
183
|
+
text: 'Use a folha de contatos no trabalho em equipe',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
type: 'paragraph',
|
|
187
|
+
html: 'A folha de contatos PNG exibe todos os quadros e suas camadas de cor em uma só imagem, facilitando a comunicação no time.',
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
faq,
|
|
191
|
+
bibliographyTitle: 'Referências para desenvolvimento de colisões',
|
|
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-i-hurtbox-dlya-spraitov';
|
|
7
|
+
const title = 'Аниматор Hitbox и Hurtbox для Спрайтов';
|
|
8
|
+
const description = 'Рисуйте слои коллизий на каждом кадре спрайта, просматривайте анимацию с калькой (onion skin), редактируйте координаты в пикселях и экспортируйте JSON.';
|
|
9
|
+
|
|
10
|
+
const faq = [
|
|
11
|
+
{
|
|
12
|
+
question: 'В чем разница между хитбоксом (hitbox) и хертбоксом (hurtbox)?',
|
|
13
|
+
answer: 'Хитбокс определяет область, наносящую удар, а хертбокс - область персонажа, получающую урон. Пушбоксы (pushbox) удерживают персонажей на расстоянии, а граббоксы (grabbox) задают радиус захватов.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
question: 'Покидают ли мои файлы спрайтов браузер?',
|
|
17
|
+
answer: 'Нет. Обработка и экспорт выполняются полностью в вашем браузере. Локально сохраняются только настройки редактора.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
question: 'Какую систему координат использует экспорт в JSON?',
|
|
21
|
+
answer: 'Каждый кадр измеряет координаты в пикселях от верхнего левого угла. Размеры ширины и высоты сохраняются как положительные числа с собственным опорным центром (pivot).',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
question: 'Можно ли редактировать спрайтшиты и отдельные кадры?',
|
|
25
|
+
answer: 'Да. Вы можете загрузить спрайтшит PNG/WebP с указанием строк и столбцов или выбрать последовательность отдельных файлов.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
question: 'Работает ли экспорт во всех игровых движках?',
|
|
29
|
+
answer: 'Формат JSON является нейтральным. Он сохраняет прямоугольники кадров, точки опорного центра и геометрические слои без привязки к конкретному движку.',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const howTo = [
|
|
34
|
+
{ name: 'Загрузите графику', text: 'Выберите спрайтшит PNG/WebP или последовательность файлов. Обработка выполняется локально.' },
|
|
35
|
+
{ name: 'Настройте кадры', text: 'Укажите число строк и столбцов и проверьте нарезку на временной ленте.' },
|
|
36
|
+
{ name: 'Нарисуйте слои коллизий', text: 'Выберите слой hitbox, hurtbox, pushbox или sensor и нарисуйте прямоугольник или круг.' },
|
|
37
|
+
{ name: 'Настройте движение', text: 'Редактируйте точные координаты, копируйте фигуры на соседние кадры и используйте кальку.' },
|
|
38
|
+
{ name: 'Экспортируйте проект', text: 'Скачайте нейтральный файл JSON и сравнительный PNG. Сохраняйте исходные файлы вместе с 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: 'Загрузите анимацию, подтвердите нарезку кадров и нарисуйте зоны атаки, урона, физики или детекторов.',
|
|
72
|
+
privacyNote: 'Локальный монтажный стол. Изображения не отправляются на сервер.',
|
|
73
|
+
loadSprite: 'Поместить графику на монтажный стол',
|
|
74
|
+
loadHint: 'Выберите спрайтшит или набор упорядоченных файлов PNG/WebP.',
|
|
75
|
+
chooseImages: 'Выбрать файлы',
|
|
76
|
+
slicingTitle: 'Нарезка кадров',
|
|
77
|
+
rowsLabel: 'Строки',
|
|
78
|
+
columnsLabel: 'Столбцы',
|
|
79
|
+
applySlicing: 'Нарезать',
|
|
80
|
+
playbackTitle: 'Просмотр движения',
|
|
81
|
+
previousFrame: 'Предыдущий кадр',
|
|
82
|
+
play: 'Воспроизвести',
|
|
83
|
+
pause: 'Пауза',
|
|
84
|
+
nextFrame: 'Следующий кадр',
|
|
85
|
+
fpsLabel: 'Кадров в секунду',
|
|
86
|
+
onionPrevious: 'Калька пред.',
|
|
87
|
+
onionNext: 'Калька след.',
|
|
88
|
+
layerTitle: 'Слои коллизий',
|
|
89
|
+
typeHitbox: 'Hitbox',
|
|
90
|
+
typeHurtbox: 'Hurtbox',
|
|
91
|
+
typePushbox: 'Pushbox',
|
|
92
|
+
typeGrabbox: 'Grabbox',
|
|
93
|
+
typeSensor: 'Датчик',
|
|
94
|
+
typeCustom: 'Свой слой',
|
|
95
|
+
shapeRectangle: 'Прямоугольник',
|
|
96
|
+
shapeCircle: 'Круг',
|
|
97
|
+
drawShape: 'Рисовать',
|
|
98
|
+
selectShape: 'Выбрать',
|
|
99
|
+
stageLabel: 'Рабочая область',
|
|
100
|
+
emptyStage: 'Загрузите графику, чтобы начать рисовать слои коллизий.',
|
|
101
|
+
frameReadout: 'Кадр {current} из {total}',
|
|
102
|
+
timelineTitle: 'Лента кадров',
|
|
103
|
+
inspectorTitle: 'Инспектор формы',
|
|
104
|
+
noSelection: 'Выберите фигуру для редактирования точных координат.',
|
|
105
|
+
nameLabel: 'Имя слоя',
|
|
106
|
+
xLabel: 'X в пикселях',
|
|
107
|
+
yLabel: 'Y в пикселях',
|
|
108
|
+
widthLabel: 'Ширина в пикселях',
|
|
109
|
+
heightLabel: 'Высота в пикселях',
|
|
110
|
+
radiusLabel: 'Радиус в пикселях',
|
|
111
|
+
duplicateShape: 'Дублировать',
|
|
112
|
+
mirrorShape: 'Отразить по горизонтали',
|
|
113
|
+
deleteShape: 'Удалить фигуру',
|
|
114
|
+
copyPrevious: 'Скопировать пред. кадр сюда',
|
|
115
|
+
copyAll: 'Скопировать этот кадр во все',
|
|
116
|
+
pivotTitle: 'Опорный центр (Pivot)',
|
|
117
|
+
pivotXLabel: 'Центр X',
|
|
118
|
+
pivotYLabel: 'Центр Y',
|
|
119
|
+
exportTitle: 'Экспорт проекта',
|
|
120
|
+
exportJson: 'Скачать JSON',
|
|
121
|
+
importJson: 'Импортировать JSON',
|
|
122
|
+
exportContactSheet: 'Скачать сравнительный лист',
|
|
123
|
+
resetProject: 'Сбросить слои',
|
|
124
|
+
undo: 'Отменить',
|
|
125
|
+
redo: 'Повторить',
|
|
126
|
+
statusReady: 'Монтажный стол готов.',
|
|
127
|
+
statusImageLoaded: 'Загружено {count} файлов.',
|
|
128
|
+
statusShapeCreated: 'Добавлена форма коллизии.',
|
|
129
|
+
statusShapeUpdated: 'Форма обновлена.',
|
|
130
|
+
statusImported: 'Проект импортирован.',
|
|
131
|
+
statusExported: 'Экспорт подготовлен.',
|
|
132
|
+
statusError: 'Не удалось прочитать файл.',
|
|
133
|
+
framesBadge: '{count} кадров',
|
|
134
|
+
shapesBadge: '{count} фигур',
|
|
135
|
+
coverageBadge: '{percent}% покрытия',
|
|
136
|
+
coordinatesNote: 'Координаты отсчитываются от верхнего левого угла каждого кадра (0,0).',
|
|
137
|
+
localOnlyDisclosure: 'Файл JSON содержит имена файлов, точки центов и формы без графических пикселей.',
|
|
138
|
+
limitationDisclosure: 'Слои задают геометрические зоны. Проверяйте их поведение в вашем игровом движке.',
|
|
139
|
+
},
|
|
140
|
+
seo: [
|
|
141
|
+
{
|
|
142
|
+
type: 'title',
|
|
143
|
+
level: 2,
|
|
144
|
+
text: 'Проектирование хитбоксов в согласовании с движением спрайта',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: 'paragraph',
|
|
148
|
+
html: 'Настройка хитбоксов становится сложной, если каждый кадр рассматривается отдельно. Этот редактор объединяет просмотр спрайта, слои коллизий, кальку и временную ленту.',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
type: 'title',
|
|
152
|
+
level: 2,
|
|
153
|
+
text: 'Выбор слоев коллизий по их игровой роли',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'table',
|
|
157
|
+
headers: ['Слой', 'Основная роль', 'Контрольный вопрос'],
|
|
158
|
+
rows: [
|
|
159
|
+
['Hitbox', 'Зона, наносящая урон или эффект', 'Появляется ли она только в активных кадрах?'],
|
|
160
|
+
['Hurtbox', 'Зона, получающая урон', 'Прилегает ли она к контуру тела без зазоров?'],
|
|
161
|
+
['Pushbox', 'Физическая коллизия между персонажами', 'Сохраняет ли она стабильность во избежание тряски?'],
|
|
162
|
+
['Grabbox', 'Радиус для выполнения захвата', 'Совпадает ли тайминг с визуальной анимацией?'],
|
|
163
|
+
['Sensor', 'Зона детекции событий', 'Понятно ли написано название слоя?'],
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
type: 'title',
|
|
168
|
+
level: 2,
|
|
169
|
+
text: 'Понимание системы координат кадров',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: 'paragraph',
|
|
173
|
+
html: 'Экспортируемый проект измеряет X и Y от верхнего левого угла каждого кадра. Размеры задаются в положительных пикселях.',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'tip',
|
|
177
|
+
title: 'Проверяйте полную последовательность анимации',
|
|
178
|
+
html: 'Проигрывайте анимацию полностью после редактирования кадра, чтобы убедиться в плавности движения.',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
type: 'title',
|
|
182
|
+
level: 2,
|
|
183
|
+
text: 'Используйте сравнительный лист в командной работе',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
type: 'paragraph',
|
|
187
|
+
html: 'Сравнительный PNG-лист отображает все кадры и слои на одном изображении, что упрощает обсуждение разработчиками и художниками.',
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
faq,
|
|
191
|
+
bibliographyTitle: 'Ссылки по проектированию коллизий в играх',
|
|
192
|
+
bibliography: bibliographyEntries,
|
|
193
|
+
howTo,
|
|
194
|
+
schemas: [softwareApplication, faqPage, howToSchema],
|
|
195
|
+
};
|