@jjlmoya/utils-games-development 1.64.0 → 1.65.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 (161) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +4 -1
  4. package/src/tests/locale_completeness.test.ts +2 -2
  5. package/src/tests/seo_parity.test.ts +2 -2
  6. package/src/tests/seo_translation_completeness.test.ts +69 -0
  7. package/src/tests/tool_validation.test.ts +2 -2
  8. package/src/tests/translation_copy.test.ts +21 -18
  9. package/src/tool/audioLoopPointFinder/i18n/de.ts +13 -0
  10. package/src/tool/audioLoopPointFinder/i18n/fr.ts +26 -0
  11. package/src/tool/audioLoopPointFinder/i18n/id.ts +4 -0
  12. package/src/tool/audioLoopPointFinder/i18n/it.ts +3 -0
  13. package/src/tool/audioLoopPointFinder/i18n/nl.ts +4 -0
  14. package/src/tool/audioLoopPointFinder/i18n/pl.ts +4 -0
  15. package/src/tool/audioLoopPointFinder/i18n/pt.ts +3 -0
  16. package/src/tool/audioLoopPointFinder/i18n/ru.ts +4 -0
  17. package/src/tool/audioLoopPointFinder/i18n/sv.ts +4 -0
  18. package/src/tool/audioLoopPointFinder/i18n/tr.ts +4 -0
  19. package/src/tool/audioLoopPointFinder/i18n/zh.ts +4 -0
  20. package/src/tool/damageFormulaLab/i18n/de.ts +13 -0
  21. package/src/tool/damageFormulaLab/i18n/fr.ts +13 -0
  22. package/src/tool/damageFormulaLab/i18n/id.ts +13 -0
  23. package/src/tool/damageFormulaLab/i18n/it.ts +1 -0
  24. package/src/tool/damageFormulaLab/i18n/ja.ts +1 -0
  25. package/src/tool/damageFormulaLab/i18n/ko.ts +1 -0
  26. package/src/tool/damageFormulaLab/i18n/nl.ts +1 -0
  27. package/src/tool/damageFormulaLab/i18n/pl.ts +1 -0
  28. package/src/tool/damageFormulaLab/i18n/pt.ts +1 -0
  29. package/src/tool/damageFormulaLab/i18n/ru.ts +2 -0
  30. package/src/tool/damageFormulaLab/i18n/sv.ts +2 -0
  31. package/src/tool/damageFormulaLab/i18n/tr.ts +2 -0
  32. package/src/tool/damageFormulaLab/i18n/zh.ts +2 -0
  33. package/src/tool/gameDeltaTimeFixedTimestepLab/bibliography.astro +22 -0
  34. package/src/tool/gameDeltaTimeFixedTimestepLab/bibliography.ts +10 -0
  35. package/src/tool/gameDeltaTimeFixedTimestepLab/component.astro +51 -0
  36. package/src/tool/gameDeltaTimeFixedTimestepLab/controller.ts +79 -0
  37. package/src/tool/gameDeltaTimeFixedTimestepLab/dom-views.ts +88 -0
  38. package/src/tool/gameDeltaTimeFixedTimestepLab/entry.ts +27 -0
  39. package/src/tool/gameDeltaTimeFixedTimestepLab/evaluator.ts +21 -0
  40. package/src/tool/gameDeltaTimeFixedTimestepLab/game-delta-time-fixed-timestep-lab.css +491 -0
  41. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/de.ts +56 -0
  42. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/en.ts +180 -0
  43. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/es.ts +56 -0
  44. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/fr.ts +46 -0
  45. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/id.ts +46 -0
  46. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/it.ts +46 -0
  47. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/ja.ts +46 -0
  48. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/ko.ts +46 -0
  49. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/nl.ts +46 -0
  50. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/pl.ts +46 -0
  51. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/pt.ts +46 -0
  52. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/ru.ts +46 -0
  53. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/sv.ts +46 -0
  54. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/tr.ts +46 -0
  55. package/src/tool/gameDeltaTimeFixedTimestepLab/i18n/zh.ts +46 -0
  56. package/src/tool/gameDeltaTimeFixedTimestepLab/index.ts +11 -0
  57. package/src/tool/gameDeltaTimeFixedTimestepLab/logic.test.ts +35 -0
  58. package/src/tool/gameDeltaTimeFixedTimestepLab/logic.ts +140 -0
  59. package/src/tool/gameDeltaTimeFixedTimestepLab/seo.astro +15 -0
  60. package/src/tool/gameDeltaTimeFixedTimestepLab/seo_contract.test.ts +25 -0
  61. package/src/tool/gameDeltaTimeFixedTimestepLab/storage.ts +23 -0
  62. package/src/tool/gameDeltaTimeFixedTimestepLab/ui.ts +54 -0
  63. package/src/tool/gameUIAccessibilityTester/i18n/de.ts +13 -0
  64. package/src/tool/gameUIAccessibilityTester/i18n/fr.ts +13 -0
  65. package/src/tool/gameUIAccessibilityTester/i18n/id.ts +13 -0
  66. package/src/tool/gameUIAccessibilityTester/i18n/it.ts +1 -0
  67. package/src/tool/gameUIAccessibilityTester/i18n/nl.ts +5 -0
  68. package/src/tool/gameUIAccessibilityTester/i18n/pl.ts +5 -0
  69. package/src/tool/gameUIAccessibilityTester/i18n/pt.ts +2 -0
  70. package/src/tool/gameUIAccessibilityTester/i18n/ru.ts +1 -0
  71. package/src/tool/gameUIAccessibilityTester/i18n/sv.ts +1 -0
  72. package/src/tool/gameUIAccessibilityTester/i18n/tr.ts +2 -0
  73. package/src/tool/gameUIAccessibilityTester/i18n/zh.ts +1 -0
  74. package/src/tool/hitboxHurtboxAnimator/i18n/de.ts +14 -0
  75. package/src/tool/hitboxHurtboxAnimator/i18n/fr.ts +13 -0
  76. package/src/tool/hitboxHurtboxAnimator/i18n/id.ts +13 -0
  77. package/src/tool/hitboxHurtboxAnimator/i18n/it.ts +1 -0
  78. package/src/tool/hitboxHurtboxAnimator/i18n/nl.ts +1 -0
  79. package/src/tool/hitboxHurtboxAnimator/i18n/pl.ts +2 -0
  80. package/src/tool/hitboxHurtboxAnimator/i18n/pt.ts +2 -0
  81. package/src/tool/hitboxHurtboxAnimator/i18n/ru.ts +2 -0
  82. package/src/tool/hitboxHurtboxAnimator/i18n/sv.ts +1 -0
  83. package/src/tool/hitboxHurtboxAnimator/i18n/tr.ts +2 -0
  84. package/src/tool/itchioGameTester/i18n/de.ts +13 -0
  85. package/src/tool/itchioGameTester/i18n/es.ts +2 -2
  86. package/src/tool/itchioGameTester/i18n/fr.ts +26 -0
  87. package/src/tool/itchioGameTester/i18n/id.ts +3 -0
  88. package/src/tool/itchioGameTester/i18n/it.ts +3 -0
  89. package/src/tool/itchioGameTester/i18n/ja.ts +3 -0
  90. package/src/tool/itchioGameTester/i18n/ko.ts +3 -0
  91. package/src/tool/itchioGameTester/i18n/nl.ts +3 -0
  92. package/src/tool/itchioGameTester/i18n/pl.ts +3 -0
  93. package/src/tool/itchioGameTester/i18n/pt.ts +3 -0
  94. package/src/tool/itchioGameTester/i18n/ru.ts +3 -0
  95. package/src/tool/itchioGameTester/i18n/sv.ts +3 -0
  96. package/src/tool/itchioGameTester/i18n/tr.ts +3 -0
  97. package/src/tool/itchioGameTester/i18n/zh.ts +3 -0
  98. package/src/tool/localizationSanitizer/i18n/de.ts +13 -0
  99. package/src/tool/localizationSanitizer/i18n/es.ts +26 -0
  100. package/src/tool/localizationSanitizer/i18n/fr.ts +4 -0
  101. package/src/tool/localizationSanitizer/i18n/id.ts +4 -0
  102. package/src/tool/localizationSanitizer/i18n/it.ts +4 -0
  103. package/src/tool/localizationSanitizer/i18n/ja.ts +4 -0
  104. package/src/tool/localizationSanitizer/i18n/ko.ts +4 -0
  105. package/src/tool/localizationSanitizer/i18n/nl.ts +5 -0
  106. package/src/tool/localizationSanitizer/i18n/pl.ts +5 -0
  107. package/src/tool/localizationSanitizer/i18n/pt.ts +5 -0
  108. package/src/tool/localizationSanitizer/i18n/ru.ts +5 -0
  109. package/src/tool/localizationSanitizer/i18n/sv.ts +5 -0
  110. package/src/tool/localizationSanitizer/i18n/tr.ts +5 -0
  111. package/src/tool/localizationSanitizer/i18n/zh.ts +6 -0
  112. package/src/tool/pixelArtPaletteSwapper/i18n/ja.ts +13 -0
  113. package/src/tool/pixelArtPaletteSwapper/i18n/ko.ts +13 -0
  114. package/src/tool/pixelArtPaletteSwapper/i18n/zh.ts +18 -0
  115. package/src/tool/retroSfxGenerator/i18n/de.ts +13 -0
  116. package/src/tool/retroSfxGenerator/i18n/fr.ts +13 -0
  117. package/src/tool/retroSfxGenerator/i18n/id.ts +13 -0
  118. package/src/tool/retroSfxGenerator/i18n/it.ts +1 -0
  119. package/src/tool/retroSfxGenerator/i18n/nl.ts +1 -0
  120. package/src/tool/retroSfxGenerator/i18n/pl.ts +1 -0
  121. package/src/tool/retroSfxGenerator/i18n/pt.ts +1 -0
  122. package/src/tool/retroSfxGenerator/i18n/ru.ts +1 -0
  123. package/src/tool/retroSfxGenerator/i18n/sv.ts +2 -0
  124. package/src/tool/retroSfxGenerator/i18n/tr.ts +1 -0
  125. package/src/tool/retroSfxGenerator/i18n/zh.ts +1 -0
  126. package/src/tool/spriteSheetPacker/i18n/de.ts +13 -0
  127. package/src/tool/spriteSheetPacker/i18n/es.ts +2 -2
  128. package/src/tool/spriteSheetPacker/i18n/fr.ts +26 -0
  129. package/src/tool/spriteSheetPacker/i18n/id.ts +4 -0
  130. package/src/tool/spriteSheetPacker/i18n/it.ts +4 -0
  131. package/src/tool/spriteSheetPacker/i18n/ja.ts +3 -0
  132. package/src/tool/spriteSheetPacker/i18n/ko.ts +3 -0
  133. package/src/tool/spriteSheetPacker/i18n/nl.ts +4 -0
  134. package/src/tool/spriteSheetPacker/i18n/pl.ts +4 -0
  135. package/src/tool/spriteSheetPacker/i18n/pt.ts +4 -0
  136. package/src/tool/spriteSheetPacker/i18n/ru.ts +4 -0
  137. package/src/tool/spriteSheetPacker/i18n/sv.ts +4 -0
  138. package/src/tool/spriteSheetPacker/i18n/tr.ts +4 -0
  139. package/src/tool/spriteSheetPacker/i18n/zh.ts +4 -0
  140. package/src/tool/steamBbcodeTranslator/i18n/de.ts +22 -0
  141. package/src/tool/steamBbcodeTranslator/i18n/es.ts +23 -1
  142. package/src/tool/steamBbcodeTranslator/i18n/fr.ts +6 -1
  143. package/src/tool/steamBbcodeTranslator/i18n/id.ts +7 -1
  144. package/src/tool/steamBbcodeTranslator/i18n/it.ts +6 -1
  145. package/src/tool/steamBbcodeTranslator/i18n/ja.ts +5 -1
  146. package/src/tool/steamBbcodeTranslator/i18n/ko.ts +5 -1
  147. package/src/tool/steamBbcodeTranslator/i18n/nl.ts +7 -1
  148. package/src/tool/steamBbcodeTranslator/i18n/pl.ts +7 -1
  149. package/src/tool/steamBbcodeTranslator/i18n/pt.ts +7 -1
  150. package/src/tool/steamBbcodeTranslator/i18n/ru.ts +7 -1
  151. package/src/tool/steamBbcodeTranslator/i18n/sv.ts +7 -1
  152. package/src/tool/steamBbcodeTranslator/i18n/tr.ts +7 -1
  153. package/src/tool/steamBbcodeTranslator/i18n/zh.ts +5 -1
  154. package/src/tool/steamCapsuleGenerator/i18n/de.ts +2 -2
  155. package/src/tool/steamCapsuleGenerator/i18n/es.ts +2 -2
  156. package/src/tool/steamCapsuleGenerator/i18n/fr.ts +2 -2
  157. package/src/tool/steamCapsuleGenerator/i18n/pl.ts +13 -0
  158. package/src/tool/steamCapsuleGenerator/i18n/ru.ts +26 -0
  159. package/src/tool/steamCapsuleGenerator/i18n/sv.ts +1 -0
  160. package/src/tool/steamCapsuleGenerator/i18n/tr.ts +1 -0
  161. package/src/tools.ts +2 -0
@@ -0,0 +1,180 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { GameDeltaTimeFixedTimestepLabUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const faq = [
7
+ {
8
+ question: 'What does this fixed timestep lab demonstrate?',
9
+ answer: 'It runs the same moving object through a variable delta time loop and a fixed timestep accumulator. Frame spikes make the difference visible so you can inspect simulated time, position drift, and catch up steps without running a game engine.',
10
+ },
11
+ {
12
+ question: 'What is the difference between variable and fixed delta time?',
13
+ answer: 'The variable model advances once per rendered frame using that frame duration. The fixed model advances in equal simulation steps and uses an accumulator to process as many steps as the elapsed wall time requires. Fixed steps make simulation behavior less dependent on render rate, while a long frame may require catch up work.',
14
+ },
15
+ {
16
+ question: 'What does the frame spike input represent?',
17
+ answer: 'It adds extra milliseconds to every selected spike frame. The cadence field controls how often a spike appears, which lets you create a repeatable hitch pattern instead of relying on a random performance trace.',
18
+ },
19
+ {
20
+ question: 'What does delta clamping change?',
21
+ answer: 'Clamping limits the delta used by the variable model when a frame is longer than the chosen ceiling. This can prevent a single hitch from moving the object too far, but it also makes simulated time fall behind wall time. The fixed accumulator continues to account for the full elapsed frame.',
22
+ },
23
+ {
24
+ question: 'Is this a profiler or a replacement for playtesting?',
25
+ answer: 'No. It is a deterministic teaching and design lab using declared numbers. It does not measure your device, diagnose an engine, model rendering cost, or prove that one loop is correct for every game.',
26
+ },
27
+ ];
28
+
29
+ const howTo = [
30
+ {
31
+ name: 'Choose the frame rhythm',
32
+ text: 'Set a target frames per second and add a repeatable spike in milliseconds. Use the cadence field to place that spike every chosen number of frames.',
33
+ },
34
+ {
35
+ name: 'Set the simulation step',
36
+ text: 'Choose the fixed timestep in milliseconds. A value near 16.667 milliseconds represents a 60 updates per second simulation.',
37
+ },
38
+ {
39
+ name: 'Give both worlds a motion rule',
40
+ text: 'Set velocity and duration. Both models move the same object, so the position difference comes from how each loop consumes elapsed time.',
41
+ },
42
+ {
43
+ name: 'Test a clamp deliberately',
44
+ text: 'Enable the delta clamp to cap the variable model, then compare its simulated time with the fixed accumulator. A clamp is a policy choice with a visible cost, not a free correction.',
45
+ },
46
+ {
47
+ name: 'Read the evidence',
48
+ text: 'Inspect the two tracks, divergence summary, timeline, catch up behavior, and accessible frame table. Change one input at a time when teaching or debugging a loop design.',
49
+ },
50
+ ];
51
+
52
+ const softwareApplication: WithContext<SoftwareApplication> = {
53
+ '@context': 'https://schema.org',
54
+ '@type': 'SoftwareApplication',
55
+ name: 'Game Delta Time and Fixed Timestep Lab',
56
+ applicationCategory: 'DeveloperApplication',
57
+ operatingSystem: 'Any',
58
+ };
59
+
60
+ const faqPage: WithContext<FAQPage> = {
61
+ '@context': 'https://schema.org',
62
+ '@type': 'FAQPage',
63
+ mainEntity: faq.map((item) => ({
64
+ '@type': 'Question',
65
+ name: item.question,
66
+ acceptedAnswer: { '@type': 'Answer', text: item.answer },
67
+ })),
68
+ };
69
+
70
+ const howToSchema: WithContext<HowTo> = {
71
+ '@context': 'https://schema.org',
72
+ '@type': 'HowTo',
73
+ name: 'How to compare variable delta time with a fixed timestep',
74
+ step: howTo.map((step) => ({
75
+ '@type': 'HowToStep',
76
+ name: step.name,
77
+ text: step.text,
78
+ })),
79
+ };
80
+
81
+ export const content: ToolLocaleContent<GameDeltaTimeFixedTimestepLabUI> = {
82
+ slug: 'game-delta-time-fixed-timestep-lab',
83
+ title: 'Game Delta Time and Fixed Timestep Lab',
84
+ description: 'Compare variable and fixed timestep game loops with repeatable frame spikes, simulated motion, catch up steps, and visible time drift.',
85
+ ui: {
86
+ controlsTitle: 'Build the frame pattern',
87
+ fpsLabel: 'Target frame rate',
88
+ fpsHint: 'Rendered frames per second',
89
+ spikeLabel: 'Frame spike',
90
+ spikeHint: 'Extra time added to spike frames',
91
+ spikeEveryLabel: 'Spike every frames',
92
+ fixedDtLabel: 'Fixed timestep',
93
+ fixedDtHint: 'Equal simulation step size',
94
+ velocityLabel: 'Object velocity',
95
+ durationLabel: 'Run duration',
96
+ clampLabel: 'Delta ceiling',
97
+ clampToggle: 'Clamp variable delta time',
98
+ runLabel: 'Run experiment',
99
+ resetLabel: 'Reset values',
100
+ stageKicker: 'The proving ground',
101
+ stageTitle: 'Two clocks, one moving object',
102
+ stageCaption: 'Bars expose the hitches, lines trace both positions, and the lower trace isolates the drift that the final values can hide.',
103
+ frameTraceLabel: 'Frame durations',
104
+ positionPlotLabel: 'Object position',
105
+ differencePlotLabel: 'Position difference from fixed path',
106
+ variableLane: 'Variable delta',
107
+ fixedLane: 'Fixed accumulator',
108
+ frameCountLabel: 'Rendered frames',
109
+ wallTimeLabel: 'Wall time',
110
+ variableTimeLabel: 'Variable simulated time',
111
+ fixedTimeLabel: 'Fixed simulated time',
112
+ divergenceLabel: 'Position difference',
113
+ stepsLabel: 'Fixed simulation steps',
114
+ diagnosticsTitle: 'Frame reading',
115
+ stableStatus: 'The two paths stay aligned for this pattern.',
116
+ variableStatus: 'The variable path runs ahead because its frame durations include the spikes.',
117
+ fixedStatus: 'The fixed path is catching up in multiple simulation steps after a long frame.',
118
+ clampStatus: 'The clamp limits the variable jump and leaves that model behind elapsed wall time.',
119
+ timelineTitle: 'The motion ledger',
120
+ timelineCaption: 'Position over elapsed wall time. A dashed line marks equal fixed steps.',
121
+ frameAxis: 'Elapsed wall time',
122
+ positionAxis: 'Object position',
123
+ legendVariable: 'Variable delta path',
124
+ legendFixed: 'Fixed timestep path',
125
+ legendSpike: 'Frame spike',
126
+ tableTitle: 'Accessible frame ledger',
127
+ tableFrame: 'Frame',
128
+ tableWall: 'Wall time',
129
+ tableVariable: 'Variable position',
130
+ tableFixed: 'Fixed position',
131
+ tableDelta: 'Difference',
132
+ modelNote: 'The variable model applies velocity once with the current frame duration. The fixed model accumulates full wall time and advances in equal steps. Neither path is a performance measurement.',
133
+ privacyDisclosure: 'Your values are saved only in this browser so the experiment is ready when you return. No game data or telemetry is sent anywhere.',
134
+ unitMs: 'ms',
135
+ unitSeconds: 's',
136
+ unitPixels: 'units',
137
+ statusReady: 'Experiment updated',
138
+ },
139
+ seo: [
140
+ { type: 'title', level: 2, text: 'Understand the clock inside a game loop' },
141
+ { type: 'paragraph', html: 'Every rendered frame gives the game a new elapsed time. In a variable delta loop, motion is commonly updated as <code>position += velocity × frameTime</code>. That keeps average speed close to the intended value when frames are steady, but it also makes one simulation update as large as the frame that produced it. A hitch is therefore not just a visual pause: it changes the amount of game time consumed by that update.' },
142
+ { type: 'title', level: 2, text: 'Compare variable integration with a fixed accumulator' },
143
+ { type: 'paragraph', html: 'A fixed timestep loop adds each frame duration to an accumulator, then repeatedly consumes a chosen step such as <code>16.667 ms</code>. The simulation sees equal-sized updates, while the renderer can still present frames at a different rhythm. The leftover fraction stays in the accumulator for the next frame. When a long frame arrives, the fixed loop performs several small updates to account for elapsed time, which preserves the step size but can create a catch up burst.' },
144
+ {
145
+ type: 'table',
146
+ headers: ['Situation', 'Variable delta path', 'Fixed timestep path', 'Decision to consider'],
147
+ rows: [
148
+ ['Steady rendering', 'One update uses each regular frame duration', 'One or more equal steps consume the accumulated time', 'Both should follow the same motion closely.'],
149
+ ['Long frame', 'One large update can move an object too far', 'Several fixed updates catch up to elapsed time', 'Inspect drift and the catch up count together.'],
150
+ ['Different render rate', 'The update size changes with the frame rate', 'The simulation step stays the same', 'Fixed steps reduce render-rate dependence.'],
151
+ ['Delta ceiling', 'The variable update ignores time above the cap', 'The accumulator still receives the full frame duration', 'Use a clamp only when losing time is acceptable.'],
152
+ ],
153
+ },
154
+ { type: 'title', level: 2, text: 'See what a frame spike actually does' },
155
+ { type: 'paragraph', html: 'At 60 frames per second, a regular frame is about <code>16.667 ms</code>. With an extra <code>80 ms</code> spike, one frame becomes about <code>96.667 ms</code>. The variable model consumes that whole duration in one update. The fixed model consumes roughly six <code>16.667 ms</code> steps instead. The total elapsed time can match, while the path taken through the simulation is different.' },
156
+ { type: 'title', level: 2, text: 'Read position drift and catch up together' },
157
+ { type: 'paragraph', html: 'Position difference is the variable path minus the fixed path. It tells you how far the two integration policies have separated, not which one is automatically correct. The catch up count tells you how much fixed work was required in a single rendered frame. A large difference points to visible motion divergence; a large catch up count points to a possible CPU budget problem. These are related, but they are not the same diagnosis.' },
158
+ { type: 'title', level: 2, text: 'Treat delta clamping as a policy' },
159
+ { type: 'paragraph', html: 'A clamp can stop a paused tab, breakpoint, or severe hitch from teleporting a character or sending a physics body through geometry. The tradeoff is that the variable clock then falls behind real elapsed time. If the game must preserve timing, use a fixed accumulator or another recovery policy. If the game must remain bounded and responsive, a clamp may be acceptable, but the lost time should be intentional.' },
160
+ { type: 'title', level: 2, text: 'Choose the loop for the job it protects' },
161
+ {
162
+ type: 'table',
163
+ headers: ['Game-loop job', 'Useful default', 'Reason'],
164
+ rows: [
165
+ ['Physics, collisions, or deterministic gameplay', 'Fixed timestep', 'Equal steps make the simulation less sensitive to render cadence.'],
166
+ ['Simple visual motion with no accumulated state', 'Variable delta', 'The update is small and usually does not need a catch up queue.'],
167
+ ['Gameplay simulation plus smooth rendering', 'Fixed update with interpolation', 'The simulation keeps its step while presentation hides fractional progress.'],
168
+ ['Recovery after a severe stall', 'A bounded catch up policy', 'Avoid turning one bad frame into unbounded simulation work.'],
169
+ ],
170
+ },
171
+ { type: 'title', level: 2, text: 'Use a repeatable tuning workflow' },
172
+ { type: 'paragraph', html: 'Begin with no spikes and confirm that both paths agree. Add one repeatable hitch, then change its cadence to see whether the visible error accumulates or settles. Adjust the fixed step and inspect the catch up count before changing velocity. Finally enable the clamp and compare variable simulated time with wall time. This sequence separates the cause of a divergence from the policy used to contain it.' },
173
+ { type: 'tip', title: 'What this experiment cannot prove', html: 'The lab uses declared frame durations and a constant velocity, so it explains timing behavior rather than measuring a device or validating an engine. Real physics, input sampling, networking, interpolation, and a frame budget can change the best design. Use the result to form a hypothesis, then verify that hypothesis in the actual game.' },
174
+ ],
175
+ faq,
176
+ bibliographyTitle: 'Game loop references',
177
+ bibliography: bibliographyEntries,
178
+ howTo,
179
+ schemas: [softwareApplication, faqPage, howToSchema],
180
+ };
@@ -0,0 +1,56 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { GameDeltaTimeFixedTimestepLabUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const faq = [
7
+ { question: '¿Qué demuestra este laboratorio de timestep fijo?', answer: 'Ejecuta el mismo objeto en movimiento con un bucle de delta variable y con un acumulador de timestep fijo. Los picos de frame hacen visible la diferencia para inspeccionar tiempo simulado, deriva de posición y pasos de recuperación sin ejecutar un motor de juego.' },
8
+ { question: '¿Cuál es la diferencia entre delta variable y timestep fijo?', answer: 'El modelo variable avanza una vez por frame renderizado usando su duración. El modelo fijo avanza en pasos de simulación iguales y usa un acumulador para procesar los pasos que exige el tiempo real transcurrido. Los pasos fijos reducen la dependencia de la tasa de renderizado, aunque un frame largo puede exigir trabajo adicional.' },
9
+ { question: '¿Qué representa la entrada de pico de frame?', answer: 'Añade milisegundos extra a cada frame marcado como pico. El campo de frecuencia decide cada cuántos frames aparece, para crear un patrón de hitch repetible en lugar de depender de una traza de rendimiento aleatoria.' },
10
+ { question: '¿Qué cambia al limitar el delta?', answer: 'El límite reduce el delta que usa el modelo variable cuando un frame supera el techo elegido. Puede evitar que un hitch desplace demasiado un objeto, pero también hace que ese reloj simulado se quede atrás respecto al tiempo real. El acumulador fijo sigue contabilizando toda la duración del frame.' },
11
+ { question: '¿Es un profiler o sustituye a las pruebas del juego?', answer: 'No. Es un laboratorio determinista de aprendizaje y diseño con números declarados. No mide tu dispositivo, diagnostica un motor, modela el coste de renderizado ni demuestra que un bucle sea correcto para cualquier juego.' },
12
+ ];
13
+
14
+ const howTo = [
15
+ { name: 'Elegir el ritmo de frames', text: 'Define los frames por segundo objetivo y añade un pico repetible en milisegundos. Usa la frecuencia para colocar el pico cada cierto número de frames.' },
16
+ { name: 'Definir el paso de simulación', text: 'Elige el timestep fijo en milisegundos. Un valor cercano a 16,667 milisegundos representa una simulación de aproximadamente 60 actualizaciones por segundo.' },
17
+ { name: 'Dar la misma regla de movimiento', text: 'Configura velocidad y duración. Ambos modelos mueven el mismo objeto, así que la diferencia de posición nace de cómo consumen el tiempo transcurrido.' },
18
+ { name: 'Probar un límite de forma deliberada', text: 'Activa el límite de delta y compara el tiempo simulado del modelo variable con el acumulador fijo. Un límite es una decisión con un coste visible, no una corrección gratuita.' },
19
+ { name: 'Leer las evidencias', text: 'Observa las dos pistas, el resumen de divergencia, la línea temporal, la recuperación y la tabla accesible de frames. Cambia una entrada cada vez al enseñar o depurar el diseño.' },
20
+ ];
21
+
22
+ const softwareApplication: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'Laboratorio de delta time y timestep fijo para juegos', applicationCategory: 'DeveloperApplication', operatingSystem: 'Any' };
23
+ const faqPage: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
24
+ const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'Comparar delta time variable con timestep fijo', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
25
+
26
+ export const content: ToolLocaleContent<GameDeltaTimeFixedTimestepLabUI> = {
27
+ slug: 'laboratorio-delta-time-y-timestep-fijo-para-juegos',
28
+ title: 'Laboratorio de Delta Time y Timestep Fijo para Juegos',
29
+ description: 'Compara bucles de juego con delta variable y timestep fijo mediante picos de frame repetibles, movimiento simulado, recuperación y deriva temporal visible.',
30
+ ui: {
31
+ controlsTitle: 'Construye el patrón de frames', fpsLabel: 'Tasa de frames objetivo', fpsHint: 'Frames renderizados por segundo', spikeLabel: 'Pico de frame', spikeHint: 'Tiempo extra añadido a los frames con pico', spikeEveryLabel: 'Pico cada cuántos frames', fixedDtLabel: 'Timestep fijo', fixedDtHint: 'Tamaño del paso de simulación', velocityLabel: 'Velocidad del objeto', durationLabel: 'Duración de la prueba', clampLabel: 'Techo del delta', clampToggle: 'Limitar el delta variable', runLabel: 'Ejecutar experimento', resetLabel: 'Restablecer valores', stageKicker: 'El campo de pruebas', stageTitle: 'Dos relojes, un objeto en movimiento', stageCaption: 'Las barras muestran los hitches, las líneas siguen ambas posiciones y la pista inferior aísla la deriva que pueden ocultar los valores finales.', frameTraceLabel: 'Duraciones de frame', positionPlotLabel: 'Posición del objeto', differencePlotLabel: 'Diferencia de posición frente al recorrido fijo', variableLane: 'Delta variable', fixedLane: 'Acumulador fijo', frameCountLabel: 'Frames renderizados', wallTimeLabel: 'Tiempo real', variableTimeLabel: 'Tiempo simulado variable', fixedTimeLabel: 'Tiempo simulado fijo', divergenceLabel: 'Diferencia de posición', stepsLabel: 'Pasos de simulación fijos', diagnosticsTitle: 'Lectura de frames', stableStatus: 'Las dos rutas permanecen alineadas con este patrón.', variableStatus: 'La ruta variable se adelanta porque sus duraciones incluyen los picos.', fixedStatus: 'La ruta fija recupera el tiempo con varios pasos de simulación después de un frame largo.', clampStatus: 'El límite reduce el salto variable y deja ese modelo por detrás del tiempo real transcurrido.', timelineTitle: 'El registro del movimiento', timelineCaption: 'Posición a lo largo del tiempo real transcurrido. La línea discontinua marca pasos fijos iguales.', frameAxis: 'Tiempo real transcurrido', positionAxis: 'Posición del objeto', legendVariable: 'Ruta de delta variable', legendFixed: 'Ruta de timestep fijo', legendSpike: 'Pico de frame', tableTitle: 'Registro de frames accesible', tableFrame: 'Frame', tableWall: 'Tiempo real', tableVariable: 'Posición variable', tableFixed: 'Posición fija', tableDelta: 'Diferencia', modelNote: 'El modelo variable aplica la velocidad una vez con la duración del frame actual. El modelo fijo acumula todo el tiempo real y avanza en pasos iguales. Ninguna ruta es una medición de rendimiento.', privacyDisclosure: 'Tus valores se guardan solo en este navegador para que el experimento esté listo cuando vuelvas. No se envían datos del juego ni telemetría.', unitMs: 'ms', unitSeconds: 's', unitPixels: 'unidades', statusReady: 'Experimento actualizado',
32
+ },
33
+ seo: [
34
+ { type: 'title', level: 2, text: 'Entiende el reloj dentro de un bucle de juego' },
35
+ { type: 'paragraph', html: 'Cada frame renderizado entrega al juego un nuevo tiempo transcurrido. En un bucle de delta variable, el movimiento suele actualizarse como <code>position += velocity × frameTime</code>. Con frames estables, la velocidad media se acerca a la prevista, pero cada actualización puede ser tan grande como el frame que la produjo. Por eso un hitch no es solo una pausa visual: cambia la cantidad de tiempo de juego consumida por esa actualización.' },
36
+ { type: 'title', level: 2, text: 'Compara la integración variable con un acumulador fijo' },
37
+ { type: 'paragraph', html: 'Un bucle de timestep fijo suma la duración de cada frame a un acumulador y consume repetidamente un paso elegido, como <code>16,667 ms</code>. La simulación recibe actualizaciones iguales mientras el render puede mantener otro ritmo. La fracción sobrante queda en el acumulador para el siguiente frame. Cuando llega un frame largo, el bucle fijo ejecuta varias actualizaciones pequeñas para contabilizar el tiempo transcurrido. Conserva el tamaño del paso, pero puede crear un pico de trabajo de recuperación.' },
38
+ { type: 'table', headers: ['Situación', 'Ruta de delta variable', 'Ruta de timestep fijo', 'Decisión que ayuda a tomar'], rows: [['Renderizado estable', 'Una actualización usa cada duración normal', 'Pasos iguales consumen el tiempo acumulado', 'Ambas rutas deberían seguir la misma trayectoria.'], ['Frame largo', 'Una actualización grande puede mover demasiado el objeto', 'Varias actualizaciones fijas recuperan el tiempo', 'Mira la deriva junto al número de pasos de recuperación.'], ['Otra tasa de renderizado', 'El tamaño de actualización cambia con los frames', 'El paso de simulación se mantiene', 'Los pasos fijos reducen la dependencia del render.'], ['Techo del delta', 'Se ignora el tiempo que supera el límite', 'El acumulador recibe la duración completa', 'Limita solo cuando perder tiempo sea aceptable.']] },
39
+ { type: 'title', level: 2, text: 'Observa qué hace realmente un pico de frame' },
40
+ { type: 'paragraph', html: 'A 60 frames por segundo, un frame normal dura aproximadamente <code>16,667 ms</code>. Con un pico adicional de <code>80 ms</code>, un frame pasa a durar unos <code>96,667 ms</code>. El modelo variable consume toda esa duración en una actualización. El modelo fijo consume en cambio unos seis pasos de <code>16,667 ms</code>. El tiempo total transcurrido puede coincidir, aunque el recorrido por la simulación sea diferente.' },
41
+ { type: 'title', level: 2, text: 'Lee juntos la deriva de posición y la recuperación' },
42
+ { type: 'paragraph', html: 'La diferencia de posición es la ruta variable menos la ruta fija. Indica cuánto se han separado las dos políticas de integración, no cuál es automáticamente correcta. El número de recuperación indica cuánto trabajo fijo hizo falta dentro de un único frame renderizado. Una diferencia grande apunta a una divergencia de movimiento visible; muchos pasos de recuperación apuntan a un posible problema de presupuesto de CPU. Están relacionados, pero no son el mismo diagnóstico.' },
43
+ { type: 'title', level: 2, text: 'Trata el límite del delta como una política' },
44
+ { type: 'paragraph', html: 'Un límite puede evitar que una pestaña en pausa, un breakpoint o un hitch grave teletransporte a un personaje o envíe un cuerpo físico a través de la geometría. El coste es que el reloj variable se queda por detrás del tiempo real transcurrido. Si el juego debe conservar el tiempo, usa un acumulador fijo u otra política de recuperación. Si debe mantener los saltos acotados y responder bien, el límite puede ser válido, pero el tiempo perdido debe ser intencionado.' },
45
+ { type: 'title', level: 2, text: 'Elige el bucle según lo que deba proteger' },
46
+ { type: 'table', headers: ['Trabajo del bucle', 'Valor predeterminado útil', 'Motivo'], rows: [['Física, colisiones o gameplay determinista', 'Timestep fijo', 'Los pasos iguales hacen que la simulación dependa menos del ritmo de renderizado.'], ['Movimiento visual simple sin estado acumulado', 'Delta variable', 'La actualización es pequeña y normalmente no necesita una cola de recuperación.'], ['Simulación de gameplay con render suave', 'Actualización fija con interpolación', 'La simulación conserva su paso mientras la presentación oculta el progreso fraccionario.'], ['Recuperación tras un bloqueo grave', 'Política de recuperación acotada', 'Evita convertir un frame malo en trabajo de simulación ilimitado.']] },
47
+ { type: 'title', level: 2, text: 'Usa un flujo de ajuste repetible' },
48
+ { type: 'paragraph', html: 'Empieza sin picos y confirma que ambas rutas coinciden. Añade un hitch repetible y cambia su frecuencia para ver si el error visible se acumula o se estabiliza. Ajusta el paso fijo y observa la cantidad de recuperación antes de cambiar la velocidad. Por último, activa el límite y compara el tiempo simulado variable con el tiempo real. Esta secuencia separa la causa de una divergencia de la política que se usa para contenerla.' },
49
+ { type: 'tip', title: 'Qué no puede demostrar este experimento', html: 'El laboratorio usa duraciones de frame declaradas y velocidad constante, así que explica el comportamiento temporal, pero no mide un dispositivo ni valida un motor. La física real, el muestreo de entrada, la red, la interpolación y el presupuesto de frame pueden cambiar el mejor diseño. Usa el resultado para formular una hipótesis y compruébala en el juego real.' },
50
+ ],
51
+ faq,
52
+ bibliographyTitle: 'Referencias sobre bucles de juego',
53
+ bibliography: bibliographyEntries,
54
+ howTo,
55
+ schemas: [softwareApplication, faqPage, howToSchema],
56
+ };
@@ -0,0 +1,46 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { GameDeltaTimeFixedTimestepLabUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const faq = [
7
+ { question: 'Que montre ce laboratoire de timestep fixe ?', answer: 'Il fait passer le même objet en mouvement dans une boucle à delta variable et dans un accumulateur à pas fixe. Des pics de frame répétables rendent visibles le temps simulé, la dérive de position et les pas de rattrapage, sans lancer de moteur de jeu.' },
8
+ { question: 'Quelle est la différence entre delta variable et timestep fixe ?', answer: 'Le modèle variable avance une fois par frame rendu avec sa durée. Le modèle fixe avance par pas de simulation égaux et utilise un accumulateur pour traiter autant de pas que le temps réel écoulé l exige. Les pas fixes réduisent la dépendance au rythme de rendu, mais une longue frame peut demander davantage de calcul.' },
9
+ { question: 'Que représente l entrée de pic de frame ?', answer: 'Elle ajoute des millisecondes à chaque frame choisie comme pic. Le champ de cadence indique tous les combien de frames le pic apparaît, afin de créer un hitch reproductible plutôt qu une trace aléatoire.' },
10
+ { question: 'Que change le plafonnement du delta ?', answer: 'Le plafond limite le delta utilisé par le modèle variable lorsqu une frame dépasse la valeur choisie. Cela peut empêcher un saut trop grand, mais l horloge simulée de ce modèle prend alors du retard sur le temps réel. L accumulateur fixe comptabilise toujours toute la durée de la frame.' },
11
+ { question: 'Est ce un profiler ou un remplacement des tests de jeu ?', answer: 'Non. C est un laboratoire déterministe d apprentissage et de conception fondé sur des valeurs déclarées. Il ne mesure pas votre appareil, ne diagnostique pas un moteur, ne modélise pas le coût du rendu et ne prouve pas qu une boucle convient à tous les jeux.' },
12
+ ];
13
+ const howTo = [
14
+ { name: 'Choisir le rythme des frames', text: 'Définissez les frames par seconde visées et ajoutez un pic répétable en millisecondes. La cadence place ce pic tous les quelques frames.' },
15
+ { name: 'Définir le pas de simulation', text: 'Choisissez le timestep fixe en millisecondes. Une valeur proche de 16,667 millisecondes représente environ 60 mises à jour par seconde.' },
16
+ { name: 'Donner la même règle de mouvement', text: 'Définissez la vitesse et la durée. Les deux modèles déplacent le même objet, donc la différence vient de leur manière de consommer le temps écoulé.' },
17
+ { name: 'Tester un plafond consciemment', text: 'Activez le plafond du delta et comparez le temps simulé du modèle variable avec l accumulateur fixe. Un plafond est un choix avec un coût visible, pas une correction gratuite.' },
18
+ { name: 'Lire les indices', text: 'Examinez les deux trajectoires, le résumé de divergence, la chronologie, le rattrapage et le tableau de frames accessible. Changez une seule entrée à la fois pour expliquer ou déboguer la boucle.' },
19
+ ];
20
+ const softwareApplication: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'Laboratoire du delta time et du timestep fixe pour jeux', applicationCategory: 'DeveloperApplication', operatingSystem: 'Any' };
21
+ const faqPage: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
22
+ const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'Comparer un delta time variable à un timestep fixe', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
23
+
24
+ export const content: ToolLocaleContent<GameDeltaTimeFixedTimestepLabUI> = {
25
+ slug: 'laboratoire-delta-time-et-timestep-fixe-jeu', title: 'Laboratoire de Delta Time et Timestep Fixe pour Jeux', description: 'Comparez les boucles de jeu à delta variable et à timestep fixe avec des pics de frame répétables, du mouvement simulé, du rattrapage et une dérive temporelle visible.',
26
+ ui: { controlsTitle: 'Construire le rythme des frames', fpsLabel: 'Cadence cible', fpsHint: 'Frames rendues par seconde', spikeLabel: 'Pic de frame', spikeHint: 'Temps ajouté aux frames en pic', spikeEveryLabel: 'Pic tous les frames', fixedDtLabel: 'Timestep fixe', fixedDtHint: 'Taille égale du pas de simulation', velocityLabel: 'Vitesse de l objet', durationLabel: 'Durée de l expérience', clampLabel: 'Plafond du delta', clampToggle: 'Plafonner le delta variable', runLabel: 'Lancer l expérience', resetLabel: 'Réinitialiser les valeurs', stageKicker: 'Le terrain d essai', stageTitle: 'Deux horloges, un objet en mouvement', stageCaption: 'Les barres montrent les hitches, les lignes suivent les deux positions et la trace basse isole la dérive que les valeurs finales peuvent cacher.', frameTraceLabel: 'Durées de frame', positionPlotLabel: 'Position de l objet', differencePlotLabel: 'Différence de position avec le chemin fixe', variableLane: 'Delta variable', fixedLane: 'Accumulateur fixe', frameCountLabel: 'Frames rendues', wallTimeLabel: 'Temps réel', variableTimeLabel: 'Temps simulé variable', fixedTimeLabel: 'Temps simulé fixe', divergenceLabel: 'Différence de position', stepsLabel: 'Pas de simulation fixes', diagnosticsTitle: 'Lecture des frames', stableStatus: 'Les deux chemins restent alignés pour ce motif.', variableStatus: 'Le chemin variable prend de l avance car ses durées incluent les pics.', fixedStatus: 'Le chemin fixe rattrape son retard en plusieurs pas après une longue frame.', clampStatus: 'Le plafond réduit le saut variable et laisse ce modèle derrière le temps réel écoulé.', timelineTitle: 'Le registre du mouvement', timelineCaption: 'Position selon le temps réel écoulé. Une ligne en pointillé marque les pas fixes égaux.', frameAxis: 'Temps réel écoulé', positionAxis: 'Position de l objet', legendVariable: 'Chemin à delta variable', legendFixed: 'Chemin à timestep fixe', legendSpike: 'Pic de frame', tableTitle: 'Registre des frames accessible', tableFrame: 'Frame', tableWall: 'Temps réel', tableVariable: 'Position variable', tableFixed: 'Position fixe', tableDelta: 'Différence', modelNote: 'Le modèle variable applique la vitesse une fois avec la durée de la frame actuelle. Le modèle fixe accumule tout le temps réel et avance par pas égaux. Aucun chemin ne mesure les performances.', privacyDisclosure: 'Vos valeurs sont enregistrées uniquement dans ce navigateur pour retrouver l expérience prête à votre retour. Aucune donnée de jeu ni télémétrie n est envoyée.', unitMs: 'ms', unitSeconds: 's', unitPixels: 'unités', statusReady: 'Expérience mise à jour' },
27
+ seo: [
28
+ { type: 'title', level: 2, text: 'Comprendre l horloge d une boucle de jeu' },
29
+ { type: 'paragraph', html: 'Chaque frame rendue fournit au jeu un nouveau temps écoulé. Dans une boucle à delta variable, le mouvement est souvent mis à jour avec <code>position += velocity × frameTime</code>. Quand les frames sont régulières, la vitesse moyenne reste proche de la valeur voulue, mais une mise à jour peut devenir aussi grande que la frame qui l a produite. Un hitch n est donc pas seulement une pause visuelle: il change la quantité de temps de jeu consommée par cette mise à jour.' },
30
+ { type: 'title', level: 2, text: 'Comparer l intégration variable à un accumulateur fixe' },
31
+ { type: 'paragraph', html: 'Une boucle à timestep fixe ajoute la durée de chaque frame à un accumulateur, puis consomme plusieurs fois un pas choisi comme <code>16,667 ms</code>. La simulation reçoit des mises à jour égales tandis que le rendu peut garder un autre rythme. La fraction restante reste dans l accumulateur pour la frame suivante. Lorsqu une longue frame arrive, la boucle fixe exécute plusieurs petites mises à jour pour couvrir le temps écoulé. La taille du pas reste stable, mais un rattrapage peut créer une pointe de travail.' },
32
+ { type: 'table', headers: ['Situation', 'Chemin à delta variable', 'Chemin à timestep fixe', 'Décision à envisager'], rows: [['Rendu régulier', 'Une mise à jour utilise chaque durée normale', 'Des pas égaux consomment le temps accumulé', 'Les deux chemins devraient rester proches.'], ['Longue frame', 'Une grande mise à jour peut déplacer trop loin un objet', 'Plusieurs mises à jour fixes rattrapent le temps écoulé', 'Lire la dérive avec le nombre de pas de rattrapage.'], ['Cadence de rendu différente', 'La taille de mise à jour change avec la cadence', 'Le pas de simulation reste identique', 'Les pas fixes réduisent la dépendance au rendu.'], ['Plafond du delta', 'Le temps au-dessus du plafond est ignoré', 'L accumulateur reçoit toute la durée de la frame', 'Ne plafonner que si perdre du temps est acceptable.']] },
33
+ { type: 'title', level: 2, text: 'Voir l effet réel d un pic de frame' },
34
+ { type: 'paragraph', html: 'À 60 frames par seconde, une frame normale dure environ <code>16,667 ms</code>. Avec un pic supplémentaire de <code>80 ms</code>, une frame dure environ <code>96,667 ms</code>. Le modèle variable consomme toute cette durée en une mise à jour. Le modèle fixe consomme plutôt environ six pas de <code>16,667 ms</code>. Le temps écoulé total peut correspondre alors que le parcours dans la simulation est différent.' },
35
+ { type: 'title', level: 2, text: 'Lire ensemble dérive de position et rattrapage' },
36
+ { type: 'paragraph', html: 'La différence de position est le chemin variable moins le chemin fixe. Elle montre la séparation entre les deux politiques d intégration, sans dire automatiquement laquelle est correcte. Le nombre de rattrapage indique le travail fixe nécessaire dans une seule frame rendue. Une grande différence suggère une divergence de mouvement visible ; un grand nombre de pas suggère un risque pour le budget CPU. Ces signaux sont liés, mais ne donnent pas le même diagnostic.' },
37
+ { type: 'title', level: 2, text: 'Traiter le plafonnement du delta comme une politique' },
38
+ { type: 'paragraph', html: 'Un plafond peut empêcher qu un onglet en pause, un breakpoint ou un hitch sévère téléporte un personnage ou fasse traverser la géométrie à un corps physique. En contrepartie, l horloge variable prend du retard sur le temps réel écoulé. Si le jeu doit préserver le timing, préférez un accumulateur fixe ou une autre politique de récupération. Si le jeu doit rester borné et réactif, un plafond peut convenir, mais le temps perdu doit être voulu.' },
39
+ { type: 'title', level: 2, text: 'Choisir la boucle selon ce qu elle protège' },
40
+ { type: 'table', headers: ['Travail de la boucle', 'Choix utile par défaut', 'Pourquoi'], rows: [['Physique, collisions ou gameplay déterministe', 'Timestep fixe', 'Des pas égaux rendent la simulation moins dépendante du rythme de rendu.'], ['Mouvement visuel simple sans état accumulé', 'Delta variable', 'La mise à jour est petite et ne demande généralement pas de file de rattrapage.'], ['Simulation de gameplay avec rendu fluide', 'Mise à jour fixe et interpolation', 'La simulation garde son pas pendant que la présentation masque la fraction restante.'], ['Récupération après un arrêt sévère', 'Politique de rattrapage bornée', 'Un mauvais frame ne doit pas créer un travail de simulation sans limite.']] },
41
+ { type: 'title', level: 2, text: 'Suivre une méthode de réglage reproductible' },
42
+ { type: 'paragraph', html: 'Commencez sans pics et vérifiez que les deux chemins correspondent. Ajoutez un hitch reproductible, puis changez sa cadence pour voir si l erreur visible s accumule ou se stabilise. Ajustez le pas fixe et observez le rattrapage avant de modifier la vitesse. Activez enfin le plafond et comparez le temps simulé variable au temps réel. Cette séquence sépare la cause d une divergence de la politique qui cherche à la contenir.' },
43
+ { type: 'tip', title: 'Ce que cette expérience ne peut pas prouver', html: 'Le laboratoire utilise des durées de frame déclarées et une vitesse constante. Il explique donc le comportement temporel, mais ne mesure pas un appareil et ne valide pas un moteur. La physique réelle, l échantillonnage des entrées, le réseau, l interpolation et le budget de frame peuvent changer le meilleur choix. Utilisez le résultat pour former une hypothèse, puis vérifiez-la dans le jeu réel.' },
44
+ ],
45
+ faq, bibliographyTitle: 'Références sur les boucles de jeu', bibliography: bibliographyEntries, howTo, schemas: [softwareApplication, faqPage, howToSchema],
46
+ };
@@ -0,0 +1,46 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { GameDeltaTimeFixedTimestepLabUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const faq = [
7
+ { question: 'Apa yang ditunjukkan laboratorium timestep tetap ini?', answer: 'Laboratorium ini menjalankan objek bergerak yang sama melalui loop delta variabel dan akumulator timestep tetap. Spike frame yang berulang membuat waktu simulasi, selisih posisi, dan langkah pengejaran dapat dilihat tanpa menjalankan game engine.' },
8
+ { question: 'Apa perbedaan delta variabel dan timestep tetap?', answer: 'Model variabel maju sekali pada setiap frame yang dirender menggunakan durasi frame tersebut. Model tetap maju dalam langkah simulasi yang sama besar dan memakai akumulator untuk memproses langkah sesuai waktu nyata yang berlalu. Langkah tetap mengurangi ketergantungan simulasi pada frame rate, tetapi frame panjang dapat menambah pekerjaan pengejaran.' },
9
+ { question: 'Apa arti input spike frame?', answer: 'Input itu menambahkan milidetik ekstra ke setiap frame yang dipilih sebagai spike. Kolom frekuensi menentukan setiap berapa frame spike muncul, sehingga kamu dapat membuat pola hitch yang berulang dan dapat dibandingkan.' },
10
+ { question: 'Apa yang berubah saat delta dibatasi?', answer: 'Batas mengurangi delta yang dipakai model variabel ketika frame melebihi nilai maksimum. Ini dapat mencegah lompatan yang terlalu besar, tetapi waktu simulasi model itu tertinggal dari waktu nyata. Akumulator tetap tetap menghitung seluruh durasi frame.' },
11
+ { question: 'Apakah ini profiler atau pengganti playtest?', answer: 'Bukan. Ini laboratorium pembelajaran dan desain deterministik dengan angka yang ditentukan. Laboratorium ini tidak mengukur perangkat, mendiagnosis engine, memodelkan biaya render, atau membuktikan bahwa satu loop cocok untuk semua game.' },
12
+ ];
13
+ const howTo = [
14
+ { name: 'Pilih ritme frame', text: 'Atur frame per detik target dan tambahkan spike berulang dalam milidetik. Gunakan frekuensi untuk menempatkan spike setiap sejumlah frame.' },
15
+ { name: 'Atur langkah simulasi', text: 'Pilih timestep tetap dalam milidetik. Nilai sekitar 16,667 milidetik mewakili sekitar 60 pembaruan simulasi per detik.' },
16
+ { name: 'Gunakan aturan gerak yang sama', text: 'Atur kecepatan dan durasi. Kedua model menggerakkan objek yang sama, jadi selisih posisi berasal dari cara masing-masing mengonsumsi waktu.' },
17
+ { name: 'Uji batas dengan sengaja', text: 'Aktifkan batas delta lalu bandingkan waktu simulasi variabel dengan akumulator tetap. Batas adalah keputusan dengan biaya yang terlihat, bukan perbaikan gratis.' },
18
+ { name: 'Baca buktinya', text: 'Periksa kedua jalur, ringkasan selisih, garis waktu, perilaku pengejaran, dan tabel frame yang mudah diakses. Ubah satu input saja setiap kali saat mengajar atau men-debug loop.' },
19
+ ];
20
+ const softwareApplication: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'Laboratorium game delta time dan timestep tetap', applicationCategory: 'DeveloperApplication', operatingSystem: 'Any' };
21
+ const faqPage: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
22
+ const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'Membandingkan delta time variabel dengan timestep tetap', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
23
+
24
+ export const content: ToolLocaleContent<GameDeltaTimeFixedTimestepLabUI> = {
25
+ slug: 'laboratorium-delta-time-dan-timestep-tetap-game', title: 'Laboratorium Delta Time dan Timestep Tetap Game', description: 'Bandingkan loop game delta variabel dan timestep tetap dengan spike frame berulang, gerakan simulasi, langkah pengejaran, dan selisih waktu yang terlihat.',
26
+ ui: { controlsTitle: 'Buat pola frame', fpsLabel: 'Frame rate target', fpsHint: 'Frame yang dirender per detik', spikeLabel: 'Spike frame', spikeHint: 'Waktu tambahan pada frame spike', spikeEveryLabel: 'Spike setiap frame', fixedDtLabel: 'Timestep tetap', fixedDtHint: 'Ukuran langkah simulasi yang sama', velocityLabel: 'Kecepatan objek', durationLabel: 'Durasi percobaan', clampLabel: 'Batas delta', clampToggle: 'Batasi delta variabel', runLabel: 'Jalankan percobaan', resetLabel: 'Atur ulang nilai', stageKicker: 'Arena pengujian', stageTitle: 'Dua jam, satu objek bergerak', stageCaption: 'Batang menunjukkan hitch, garis mengikuti kedua posisi, dan jejak bawah mengisolasi selisih yang dapat disembunyikan nilai akhir.', frameTraceLabel: 'Durasi frame', positionPlotLabel: 'Posisi objek', differencePlotLabel: 'Selisih posisi dari jalur tetap', variableLane: 'Delta variabel', fixedLane: 'Akumulator tetap', frameCountLabel: 'Frame yang dirender', wallTimeLabel: 'Waktu nyata', variableTimeLabel: 'Waktu simulasi variabel', fixedTimeLabel: 'Waktu simulasi tetap', divergenceLabel: 'Selisih posisi', stepsLabel: 'Langkah simulasi tetap', diagnosticsTitle: 'Pembacaan frame', stableStatus: 'Kedua jalur tetap sejajar untuk pola ini.', variableStatus: 'Jalur variabel bergerak lebih cepat karena durasi frame mencakup spike.', fixedStatus: 'Jalur tetap mengejar dengan beberapa langkah simulasi setelah frame panjang.', clampStatus: 'Batas mengurangi lompatan variabel dan membuat model itu tertinggal dari waktu nyata yang berlalu.', timelineTitle: 'Buku gerak', timelineCaption: 'Posisi terhadap waktu nyata yang berlalu. Garis putus-putus menandai langkah tetap yang sama.', frameAxis: 'Waktu nyata yang berlalu', positionAxis: 'Posisi objek', legendVariable: 'Jalur delta variabel', legendFixed: 'Jalur timestep tetap', legendSpike: 'Spike frame', tableTitle: 'Buku frame yang mudah diakses', tableFrame: 'Frame', tableWall: 'Waktu nyata', tableVariable: 'Posisi variabel', tableFixed: 'Posisi tetap', tableDelta: 'Selisih', modelNote: 'Model variabel menerapkan kecepatan sekali dengan durasi frame saat ini. Model tetap mengakumulasi seluruh waktu nyata dan maju dalam langkah yang sama. Tidak ada jalur yang merupakan pengukuran performa.', privacyDisclosure: 'Nilai kamu disimpan hanya di browser ini agar percobaan siap saat kamu kembali. Tidak ada data game atau telemetri yang dikirim.', unitMs: 'ms', unitSeconds: 'dtk', unitPixels: 'unit', statusReady: 'Percobaan diperbarui' },
27
+ seo: [
28
+ { type: 'title', level: 2, text: 'Pahami jam di dalam loop game' },
29
+ { type: 'paragraph', html: 'Setiap frame yang dirender memberikan waktu berlalu yang baru kepada game. Dalam loop delta variabel, gerakan biasanya diperbarui sebagai <code>position += velocity × frameTime</code>. Saat frame stabil, kecepatan rata-rata mendekati nilai yang diinginkan, tetapi satu pembaruan bisa sebesar frame yang memicunya. Hitch bukan sekadar jeda visual: hitch mengubah jumlah waktu game yang dikonsumsi oleh pembaruan itu.' },
30
+ { type: 'title', level: 2, text: 'Bandingkan integrasi variabel dengan akumulator tetap' },
31
+ { type: 'paragraph', html: 'Loop timestep tetap menambahkan durasi setiap frame ke akumulator, lalu berulang kali memakai langkah seperti <code>16,667 ms</code>. Simulasi menerima pembaruan yang sama besar, sementara renderer dapat berjalan dengan ritme berbeda. Sisa pecahan disimpan untuk frame berikutnya. Saat frame panjang muncul, loop tetap menjalankan beberapa pembaruan kecil untuk menghitung waktu yang berlalu. Ukuran langkah tetap stabil, tetapi dapat muncul lonjakan kerja pengejaran.' },
32
+ { type: 'table', headers: ['Situasi', 'Jalur delta variabel', 'Jalur timestep tetap', 'Keputusan yang dipertimbangkan'], rows: [['Render stabil', 'Satu pembaruan memakai setiap durasi normal', 'Langkah yang sama memakai waktu terakumulasi', 'Kedua jalur seharusnya mengikuti gerakan yang sama.'], ['Frame panjang', 'Satu pembaruan besar dapat menggerakkan objek terlalu jauh', 'Beberapa pembaruan tetap mengejar waktu', 'Baca selisih bersama jumlah langkah pengejaran.'], ['Frame rate berbeda', 'Ukuran pembaruan berubah mengikuti frame rate', 'Langkah simulasi tetap sama', 'Langkah tetap mengurangi ketergantungan pada render.'], ['Batas delta', 'Waktu di atas batas diabaikan', 'Akumulator menerima seluruh durasi frame', 'Batasi hanya jika kehilangan waktu dapat diterima.']] },
33
+ { type: 'title', level: 2, text: 'Lihat dampak sebenarnya dari spike frame' },
34
+ { type: 'paragraph', html: 'Pada 60 frame per detik, frame normal berdurasi sekitar <code>16,667 ms</code>. Dengan spike tambahan <code>80 ms</code>, satu frame menjadi sekitar <code>96,667 ms</code>. Model variabel memakai seluruh durasi itu dalam satu pembaruan. Model tetap memakai kira-kira enam langkah <code>16,667 ms</code>. Total waktu berlalu bisa sama, tetapi jalur yang ditempuh simulasi berbeda.' },
35
+ { type: 'title', level: 2, text: 'Baca selisih posisi bersama pengejaran' },
36
+ { type: 'paragraph', html: 'Selisih posisi adalah jalur variabel dikurangi jalur tetap. Ini menunjukkan seberapa jauh kebijakan integrasi terpisah, bukan model mana yang otomatis benar. Jumlah pengejaran menunjukkan pekerjaan tetap yang diperlukan dalam satu frame render. Selisih besar mengarah pada perbedaan gerak yang terlihat; banyak langkah mengarah pada kemungkinan masalah anggaran CPU. Keduanya terkait, tetapi bukan diagnosis yang sama.' },
37
+ { type: 'title', level: 2, text: 'Perlakukan pembatasan delta sebagai kebijakan' },
38
+ { type: 'paragraph', html: 'Batas dapat mencegah tab yang dijeda, breakpoint, atau hitch berat membuat karakter berpindah jauh atau tubuh fisik menembus geometri. Konsekuensinya, jam variabel tertinggal dari waktu nyata. Jika game harus mempertahankan waktu, gunakan akumulator tetap atau kebijakan pemulihan lain. Jika game harus membatasi lompatan dan tetap responsif, batas mungkin sesuai, tetapi waktu yang hilang harus disengaja.' },
39
+ { type: 'title', level: 2, text: 'Pilih loop berdasarkan tugas yang dilindunginya' },
40
+ { type: 'table', headers: ['Tugas loop game', 'Pilihan awal yang berguna', 'Alasan'], rows: [['Fisika, tabrakan, atau gameplay deterministik', 'Timestep tetap', 'Langkah yang sama membuat simulasi kurang bergantung pada ritme render.'], ['Gerakan visual sederhana tanpa state terakumulasi', 'Delta variabel', 'Pembaruan kecil dan biasanya tidak memerlukan antrean pengejaran.'], ['Simulasi gameplay dengan render halus', 'Update tetap dengan interpolasi', 'Simulasi mempertahankan langkah sementara tampilan menyembunyikan pecahan gerak.'], ['Pemulihan setelah berhenti berat', 'Kebijakan pengejaran terbatas', 'Cegah satu frame buruk menjadi pekerjaan simulasi tanpa batas.']] },
41
+ { type: 'title', level: 2, text: 'Gunakan alur penyetelan yang dapat diulang' },
42
+ { type: 'paragraph', html: 'Mulai tanpa spike dan pastikan kedua jalur cocok. Tambahkan hitch berulang, lalu ubah frekuensinya untuk melihat apakah kesalahan visual bertambah atau stabil. Sesuaikan langkah tetap dan perhatikan jumlah pengejaran sebelum mengubah kecepatan. Terakhir, aktifkan batas dan bandingkan waktu simulasi variabel dengan waktu nyata. Urutan ini memisahkan penyebab selisih dari kebijakan yang digunakan untuk menahannya.' },
43
+ { type: 'tip', title: 'Hal yang tidak dapat dibuktikan percobaan ini', html: 'Laboratorium memakai durasi frame yang ditentukan dan kecepatan konstan, jadi ia menjelaskan perilaku waktu, bukan mengukur perangkat atau memvalidasi engine. Fisika nyata, pengambilan input, jaringan, interpolasi, dan anggaran frame dapat mengubah desain terbaik. Gunakan hasilnya sebagai hipotesis lalu periksa hipotesis itu di game yang sebenarnya.' },
44
+ ],
45
+ faq, bibliographyTitle: 'Referensi loop game', bibliography: bibliographyEntries, howTo, schemas: [softwareApplication, faqPage, howToSchema],
46
+ };
@@ -0,0 +1,46 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { GameDeltaTimeFixedTimestepLabUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const faq = [
7
+ { question: 'Che cosa dimostra questo laboratorio sul timestep fisso?', answer: 'Esegue lo stesso oggetto in movimento con un ciclo a delta variabile e con un accumulatore a timestep fisso. I picchi di frame ripetibili rendono visibili tempo simulato, deriva della posizione e passi di recupero senza avviare un motore di gioco.' },
8
+ { question: 'Qual è la differenza tra delta variabile e timestep fisso?', answer: 'Il modello variabile avanza una volta per ogni frame renderizzato usando la sua durata. Il modello fisso avanza con passi di simulazione uguali e usa un accumulatore per elaborare i passi richiesti dal tempo reale trascorso. I passi fissi riducono la dipendenza dal frame rate, ma un frame lungo può richiedere lavoro di recupero.' },
9
+ { question: 'Che cosa rappresenta l input del picco di frame?', answer: 'Aggiunge millisecondi extra a ogni frame scelto come picco. Il campo della frequenza decide ogni quanti frame compare, così puoi creare un hitch ripetibile invece di usare una traccia casuale.' },
10
+ { question: 'Che cosa cambia il limite del delta?', answer: 'Il limite restringe il delta usato dal modello variabile quando un frame supera il tetto scelto. Può evitare uno spostamento enorme, ma fa restare quell orologio simulato indietro rispetto al tempo reale. L accumulatore fisso continua a considerare tutta la durata del frame.' },
11
+ { question: 'È un profiler o sostituisce i test del gioco?', answer: 'No. È un laboratorio deterministico per imparare e progettare usando numeri dichiarati. Non misura il tuo dispositivo, non diagnostica un motore, non simula il costo del rendering e non dimostra che un ciclo sia corretto per ogni gioco.' },
12
+ ];
13
+ const howTo = [
14
+ { name: 'Scegliere il ritmo dei frame', text: 'Imposta i frame al secondo obiettivo e aggiungi un picco ripetibile in millisecondi. Usa la frequenza per collocarlo ogni determinato numero di frame.' },
15
+ { name: 'Impostare il passo di simulazione', text: 'Scegli il timestep fisso in millisecondi. Un valore vicino a 16,667 millisecondi rappresenta circa 60 aggiornamenti di simulazione al secondo.' },
16
+ { name: 'Dare la stessa regola di movimento', text: 'Imposta velocità e durata. I due modelli muovono lo stesso oggetto, quindi la differenza di posizione nasce da come consumano il tempo trascorso.' },
17
+ { name: 'Provare un limite in modo consapevole', text: 'Attiva il limite del delta e confronta il tempo simulato variabile con l accumulatore fisso. Un limite è una scelta con un costo visibile, non una correzione gratuita.' },
18
+ { name: 'Leggere le prove', text: 'Controlla i due percorsi, il riepilogo della divergenza, la sequenza temporale, il recupero e la tabella accessibile dei frame. Cambia un solo input alla volta per spiegare o correggere il ciclo.' },
19
+ ];
20
+ const softwareApplication: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'Laboratorio game delta time e timestep fisso', applicationCategory: 'DeveloperApplication', operatingSystem: 'Any' };
21
+ const faqPage: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
22
+ const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: 'Confrontare delta time variabile e timestep fisso', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
23
+
24
+ export const content: ToolLocaleContent<GameDeltaTimeFixedTimestepLabUI> = {
25
+ slug: 'laboratorio-delta-time-e-timestep-fisso-giochi', title: 'Laboratorio Delta Time e Timestep Fisso per Giochi', description: 'Confronta i cicli di gioco a delta variabile e timestep fisso con picchi di frame ripetibili, movimento simulato, passi di recupero e deriva temporale visibile.',
26
+ ui: { controlsTitle: 'Costruisci il ritmo dei frame', fpsLabel: 'Frame rate obiettivo', fpsHint: 'Frame renderizzati al secondo', spikeLabel: 'Picco di frame', spikeHint: 'Tempo extra aggiunto ai frame di picco', spikeEveryLabel: 'Picco ogni frame', fixedDtLabel: 'Timestep fisso', fixedDtHint: 'Dimensione del passo di simulazione', velocityLabel: 'Velocità dell oggetto', durationLabel: 'Durata dell esperimento', clampLabel: 'Tetto del delta', clampToggle: 'Limita il delta variabile', runLabel: 'Esegui esperimento', resetLabel: 'Ripristina valori', stageKicker: 'Il campo di prova', stageTitle: 'Due orologi, un oggetto in movimento', stageCaption: 'Le barre mostrano gli hitch, le linee seguono le due posizioni e la traccia inferiore isola la deriva che i valori finali possono nascondere.', frameTraceLabel: 'Durate dei frame', positionPlotLabel: 'Posizione dell oggetto', differencePlotLabel: 'Differenza di posizione rispetto al percorso fisso', variableLane: 'Delta variabile', fixedLane: 'Accumulatore fisso', frameCountLabel: 'Frame renderizzati', wallTimeLabel: 'Tempo reale', variableTimeLabel: 'Tempo simulato variabile', fixedTimeLabel: 'Tempo simulato fisso', divergenceLabel: 'Differenza di posizione', stepsLabel: 'Passi di simulazione fissi', diagnosticsTitle: 'Lettura dei frame', stableStatus: 'I due percorsi restano allineati con questo schema.', variableStatus: 'Il percorso variabile va avanti perché le sue durate includono i picchi.', fixedStatus: 'Il percorso fisso recupera con più passi dopo un frame lungo.', clampStatus: 'Il limite riduce il salto variabile e lascia quel modello indietro rispetto al tempo reale trascorso.', timelineTitle: 'Il registro del movimento', timelineCaption: 'Posizione rispetto al tempo reale trascorso. Una linea tratteggiata indica passi fissi uguali.', frameAxis: 'Tempo reale trascorso', positionAxis: 'Posizione dell oggetto', legendVariable: 'Percorso a delta variabile', legendFixed: 'Percorso a timestep fisso', legendSpike: 'Picco di frame', tableTitle: 'Registro accessibile dei frame', tableFrame: 'Frame', tableWall: 'Tempo reale', tableVariable: 'Posizione variabile', tableFixed: 'Posizione fissa', tableDelta: 'Differenza', modelNote: 'Il modello variabile applica la velocità una volta usando la durata del frame attuale. Il modello fisso accumula tutto il tempo reale e avanza a passi uguali. Nessun percorso è una misura delle prestazioni.', privacyDisclosure: 'I tuoi valori vengono salvati solo in questo browser, così l esperimento è pronto quando ritorni. Nessun dato di gioco o telemetria viene inviato.', unitMs: 'ms', unitSeconds: 's', unitPixels: 'unità', statusReady: 'Esperimento aggiornato' },
27
+ seo: [
28
+ { type: 'title', level: 2, text: 'Capire l orologio dentro un ciclo di gioco' },
29
+ { type: 'paragraph', html: 'Ogni frame renderizzato fornisce al gioco un nuovo tempo trascorso. In un ciclo a delta variabile, il movimento viene spesso aggiornato come <code>position += velocity × frameTime</code>. Quando i frame sono regolari, la velocità media resta vicina a quella desiderata, ma un singolo aggiornamento diventa grande quanto il frame che lo ha prodotto. Un hitch quindi non è solo una pausa visiva: cambia la quantità di tempo di gioco consumata da quell aggiornamento.' },
30
+ { type: 'title', level: 2, text: 'Confrontare l integrazione variabile con un accumulatore fisso' },
31
+ { type: 'paragraph', html: 'Un ciclo a timestep fisso somma ogni durata di frame a un accumulatore, poi consuma ripetutamente un passo scelto come <code>16,667 ms</code>. La simulazione riceve aggiornamenti uguali mentre il rendering può mantenere un ritmo diverso. La frazione residua resta nell accumulatore per il frame successivo. Quando arriva un frame lungo, il ciclo fisso esegue più aggiornamenti piccoli per coprire il tempo trascorso. Il passo resta stabile, ma può comparire un picco di lavoro di recupero.' },
32
+ { type: 'table', headers: ['Situazione', 'Percorso a delta variabile', 'Percorso a timestep fisso', 'Decisione da valutare'], rows: [['Rendering regolare', 'Un aggiornamento usa ogni durata normale', 'Passi uguali consumano il tempo accumulato', 'I due percorsi dovrebbero restare vicini.'], ['Frame lungo', 'Un aggiornamento grande può spostare troppo un oggetto', 'Più aggiornamenti fissi recuperano il tempo', 'Osserva deriva e numero di passi insieme.'], ['Frame rate diverso', 'La dimensione dell aggiornamento cambia', 'Il passo di simulazione resta uguale', 'I passi fissi riducono la dipendenza dal rendering.'], ['Tetto del delta', 'Il tempo oltre il limite viene ignorato', 'L accumulatore riceve la durata completa', 'Limita solo se perdere tempo è accettabile.']] },
33
+ { type: 'title', level: 2, text: 'Vedere l effetto reale di un picco di frame' },
34
+ { type: 'paragraph', html: 'A 60 frame al secondo, un frame regolare dura circa <code>16,667 ms</code>. Con un picco aggiuntivo di <code>80 ms</code>, un frame dura circa <code>96,667 ms</code>. Il modello variabile consuma tutta questa durata in un aggiornamento. Il modello fisso consuma invece circa sei passi da <code>16,667 ms</code>. Il tempo totale trascorso può coincidere, anche se il percorso nella simulazione è diverso.' },
35
+ { type: 'title', level: 2, text: 'Leggere insieme deriva della posizione e recupero' },
36
+ { type: 'paragraph', html: 'La differenza di posizione è il percorso variabile meno quello fisso. Mostra quanto si sono separate le due politiche di integrazione, non quale sia automaticamente corretta. Il conteggio del recupero mostra quanto lavoro fisso è servito in un solo frame renderizzato. Una differenza grande indica una divergenza di movimento visibile; molti passi indicano un possibile problema di budget CPU. Sono segnali collegati, ma non la stessa diagnosi.' },
37
+ { type: 'title', level: 2, text: 'Trattare il limite del delta come una politica' },
38
+ { type: 'paragraph', html: 'Un limite può impedire che una scheda in pausa, un breakpoint o un hitch grave teletrasporti un personaggio o faccia attraversare la geometria a un corpo fisico. Il costo è che l orologio variabile resta indietro rispetto al tempo reale. Se il gioco deve conservare i tempi, usa un accumulatore fisso o un altra politica di recupero. Se deve mantenere salti limitati e restare reattivo, il limite può essere valido, ma il tempo perso deve essere intenzionale.' },
39
+ { type: 'title', level: 2, text: 'Scegliere il ciclo in base a ciò che protegge' },
40
+ { type: 'table', headers: ['Lavoro del ciclo', 'Scelta utile di base', 'Motivo'], rows: [['Fisica, collisioni o gameplay deterministico', 'Timestep fisso', 'I passi uguali rendono la simulazione meno dipendente dal ritmo di rendering.'], ['Movimento visivo semplice senza stato accumulato', 'Delta variabile', 'L aggiornamento è piccolo e di solito non richiede una coda di recupero.'], ['Simulazione di gameplay con rendering fluido', 'Update fisso con interpolazione', 'La simulazione conserva il passo mentre la presentazione nasconde la frazione restante.'], ['Recupero dopo un blocco grave', 'Politica di recupero limitata', 'Evita di trasformare un frame cattivo in lavoro di simulazione illimitato.']] },
41
+ { type: 'title', level: 2, text: 'Usare un flusso di regolazione ripetibile' },
42
+ { type: 'paragraph', html: 'Inizia senza picchi e verifica che i due percorsi coincidano. Aggiungi un hitch ripetibile e cambia la sua frequenza per vedere se l errore visibile cresce o si stabilizza. Regola il passo fisso e osserva il recupero prima di cambiare la velocità. Infine attiva il limite e confronta il tempo simulato variabile con il tempo reale. Questa sequenza separa la causa di una divergenza dalla politica usata per contenerla.' },
43
+ { type: 'tip', title: 'Che cosa non può dimostrare questo esperimento', html: 'Il laboratorio usa durate di frame dichiarate e velocità costante, quindi spiega il comportamento temporale ma non misura un dispositivo né valida un motore. Fisica reale, campionamento degli input, rete, interpolazione e budget di frame possono cambiare la scelta migliore. Usa il risultato per formulare un ipotesi e poi verificala nel gioco reale.' },
44
+ ],
45
+ faq, bibliographyTitle: 'Riferimenti sui cicli di gioco', bibliography: bibliographyEntries, howTo, schemas: [softwareApplication, faqPage, howToSchema],
46
+ };
@@ -0,0 +1,46 @@
1
+ import type { FAQPage, HowTo, SoftwareApplication, WithContext } from 'schema-dts';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+ import type { GameDeltaTimeFixedTimestepLabUI } from '../ui';
4
+ import { bibliographyEntries } from '../bibliography';
5
+
6
+ const faq = [
7
+ { question: 'この固定タイムステップのラボでは何が分かりますか?', answer: '同じ動くオブジェクトを、可変デルタ時間のループと固定タイムステップのアキュムレーターで実行します。繰り返し発生するフレームスパイクによって、シミュレーション時間、位置のずれ、追いつきステップをゲームエンジンなしで確認できます。' },
8
+ { question: '可変デルタと固定タイムステップの違いは何ですか?', answer: '可変モデルはレンダリングされた各フレームの長さを使って一度更新します。固定モデルは同じ大きさのステップで進み、経過した実時間に必要な数だけアキュムレーターから処理します。固定ステップは描画速度への依存を減らしますが、長いフレームでは追加の追いつき処理が発生します。' },
9
+ { question: 'フレームスパイクの入力値は何を表しますか?', answer: '指定したスパイクフレームに追加するミリ秒数です。頻度で何フレームごとにスパイクを入れるかを決められるため、ランダムな計測ではなく再現可能なヒッチを作れます。' },
10
+ { question: 'デルタの上限を設定すると何が変わりますか?', answer: '長いフレームで可変モデルが使うデルタを上限までに制限します。大きなジャンプは抑えられますが、そのモデルのシミュレーション時計は実時間より遅れます。固定アキュムレーターはフレーム全体の時間を引き続き計上します。' },
11
+ { question: 'これはプロファイラーやプレイテストの代わりですか?', answer: 'いいえ。指定した数値を使う決定論的な学習と設計のラボです。端末の性能を測定したり、エンジンを診断したり、描画コストをモデル化したり、すべてのゲームに正しいループを証明したりするものではありません。' },
12
+ ];
13
+ const howTo = [
14
+ { name: 'フレームのリズムを選ぶ', text: '目標フレームレートを設定し、ミリ秒単位の再現可能なスパイクを追加します。頻度で何フレームごとに入れるかを指定します。' },
15
+ { name: 'シミュレーションのステップを設定する', text: '固定タイムステップをミリ秒で選びます。16.667ミリ秒前後なら、毎秒約60回のシミュレーション更新になります。' },
16
+ { name: '両方に同じ動きのルールを与える', text: '速度と実行時間を設定します。同じオブジェクトを動かすため、位置の差は経過時間の消費方法から生まれます。' },
17
+ { name: '上限を意図的に試す', text: 'デルタ上限を有効にし、可変モデルのシミュレーション時間を固定アキュムレーターと比較します。上限はコストを伴う方針であり、無料の修正ではありません。' },
18
+ { name: '結果を読む', text: '2本の軌跡、ずれの概要、タイムライン、追いつき動作、アクセシブルなフレーム表を確認します。説明やデバッグでは一度に1つの入力だけを変更します。' },
19
+ ];
20
+ const softwareApplication: WithContext<SoftwareApplication> = { '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: 'ゲームのデルタ時間と固定タイムステップのラボ', applicationCategory: 'DeveloperApplication', operatingSystem: 'Any' };
21
+ const faqPage: WithContext<FAQPage> = { '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) };
22
+ const howToSchema: WithContext<HowTo> = { '@context': 'https://schema.org', '@type': 'HowTo', name: '可変デルタ時間と固定タイムステップを比較する方法', step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) };
23
+
24
+ export const content: ToolLocaleContent<GameDeltaTimeFixedTimestepLabUI> = {
25
+ slug: 'game-delta-time-fixed-timestep-lab', title: 'ゲームのデルタ時間と固定タイムステップのラボ', description: '再現可能なフレームスパイク、動きのシミュレーション、追いつきステップ、見える時間差で可変と固定のゲームループを比較します。',
26
+ ui: { controlsTitle: 'フレームパターンを作る', fpsLabel: '目標フレームレート', fpsHint: '1秒あたりのレンダリングフレーム', spikeLabel: 'フレームスパイク', spikeHint: 'スパイクフレームに追加する時間', spikeEveryLabel: 'スパイクの間隔', fixedDtLabel: '固定タイムステップ', fixedDtHint: '均一なシミュレーションステップ', velocityLabel: 'オブジェクトの速度', durationLabel: '実行時間', clampLabel: 'デルタの上限', clampToggle: '可変デルタを制限', runLabel: '実験を実行', resetLabel: '値をリセット', stageKicker: '実験フィールド', stageTitle: '2つの時計、1つの動くオブジェクト', stageCaption: '棒グラフはヒッチを示し、線は両方の位置を追跡します。下の線は最終値では隠れるずれを分離します。', frameTraceLabel: 'フレーム時間', positionPlotLabel: 'オブジェクトの位置', differencePlotLabel: '固定経路からの位置差', variableLane: '可変デルタ', fixedLane: '固定アキュムレーター', frameCountLabel: 'レンダリングフレーム', wallTimeLabel: '実時間', variableTimeLabel: '可変シミュレーション時間', fixedTimeLabel: '固定シミュレーション時間', divergenceLabel: '位置差', stepsLabel: '固定シミュレーションステップ', diagnosticsTitle: 'フレームの読み方', stableStatus: 'このパターンでは2つの経路が揃っています。', variableStatus: 'フレーム時間にスパイクが含まれるため、可変経路が先行します。', fixedStatus: '長いフレームの後、固定経路は複数のシミュレーションステップで追いつきます。', clampStatus: '上限が可変のジャンプを抑え、そのモデルを経過した実時間より遅らせます。', timelineTitle: '動きの記録', timelineCaption: '経過した実時間に対する位置です。破線は均一な固定ステップを示します。', frameAxis: '経過した実時間', positionAxis: 'オブジェクトの位置', legendVariable: '可変デルタの経路', legendFixed: '固定タイムステップの経路', legendSpike: 'フレームスパイク', tableTitle: 'アクセシブルなフレーム記録', tableFrame: 'フレーム', tableWall: '実時間', tableVariable: '可変位置', tableFixed: '固定位置', tableDelta: '差分', modelNote: '可変モデルは現在のフレーム時間で速度を1回適用します。固定モデルは実時間全体を蓄積し、均一なステップで進みます。どちらも性能測定ではありません。', privacyDisclosure: '値はこのブラウザーだけに保存され、次回も実験を続けられます。ゲームデータやテレメトリは送信されません。', unitMs: 'ms', unitSeconds: '秒', unitPixels: '単位', statusReady: '実験を更新しました' },
27
+ seo: [
28
+ { type: 'title', level: 2, text: 'ゲームループの中にある時計を理解する' },
29
+ { type: 'paragraph', html: 'レンダリングされた各フレームは、ゲームに新しい経過時間を渡します。可変デルタのループでは、動きを <code>position += velocity × frameTime</code> のように更新します。フレームが安定していれば平均速度は意図した値に近づきますが、1回の更新はそれを発生させたフレームと同じ大きさになります。ヒッチは単なる映像の停止ではなく、その更新が消費するゲーム時間を変えます。' },
30
+ { type: 'title', level: 2, text: '可変積分と固定アキュムレーターを比較する' },
31
+ { type: 'paragraph', html: '固定タイムステップのループは各フレームの時間をアキュムレーターに加え、<code>16.667 ms</code> のような選択したステップを繰り返し消費します。シミュレーションには同じ大きさの更新が届き、レンダリングは別のリズムで動けます。余った端数は次のフレームまで残ります。長いフレームでは、経過時間を処理するために複数の小さな更新を実行します。ステップは安定しますが、追いつき処理の負荷が跳ね上がることがあります。' },
32
+ { type: 'table', headers: ['状況', '可変デルタの経路', '固定タイムステップの経路', '検討する判断'], rows: [['安定した描画', '通常のフレーム時間で1回更新', '均一なステップで蓄積時間を消費', '両方が同じ動きに近づくか確認します。'], ['長いフレーム', '大きな更新でオブジェクトが進みすぎる', '複数の固定更新で時間に追いつく', '位置差と追いつき数を一緒に読みます。'], ['異なる描画速度', '更新サイズがフレームレートで変化', 'シミュレーションステップは一定', '固定ステップは描画速度への依存を減らします。'], ['デルタ上限', '上限を超えた時間を無視', 'アキュムレーターは全時間を受け取る', '時間を失ってもよい場合だけ制限します。']] },
33
+ { type: 'title', level: 2, text: 'フレームスパイクの実際の影響を見る' },
34
+ { type: 'paragraph', html: '毎秒60フレームでは、通常のフレームは約 <code>16.667 ms</code> です。追加の <code>80 ms</code> スパイクがあると、1フレームは約 <code>96.667 ms</code> になります。可変モデルはこの時間を1回の更新で消費します。固定モデルは代わりに約6回の <code>16.667 ms</code> ステップを消費します。経過時間の合計は同じでも、シミュレーション内の経路は異なる場合があります。' },
35
+ { type: 'title', level: 2, text: '位置のずれと追いつき処理を一緒に読む' },
36
+ { type: 'paragraph', html: '位置差は可変経路から固定経路を引いた値です。2つの積分方針がどれだけ離れたかを示しますが、どちらが自動的に正しいかは決めません。追いつき数は、1つの描画フレーム内で必要だった固定処理の量を示します。大きな位置差は見える動きの違いを示し、多い追いつきステップはCPU予算の問題を示す可能性があります。関連していますが、同じ診断ではありません。' },
37
+ { type: 'title', level: 2, text: 'デルタ上限を方針として扱う' },
38
+ { type: 'paragraph', html: '上限は、停止中のタブ、ブレークポイント、深刻なヒッチによってキャラクターが瞬間移動したり、物理ボディがジオメトリを通り抜けたりするのを防げます。その代わり可変時計は実際に経過した時間より遅れます。時間を保つ必要があるゲームでは、固定アキュムレーターなど別の回復方針を使います。ジャンプを抑えて応答性を保ちたい場合は上限が役立ちますが、失う時間を意図して選ぶ必要があります。' },
39
+ { type: 'title', level: 2, text: '守るべき仕事に合わせてループを選ぶ' },
40
+ { type: 'table', headers: ['ゲームループの仕事', '役立つ初期設定', '理由'], rows: [['物理、衝突、決定論的なゲームプレイ', '固定タイムステップ', '均一なステップで描画リズムへの依存を減らします。'], ['状態を蓄積しない単純な視覚運動', '可変デルタ', '更新が小さく、通常は追いつきキューが不要です。'], ['滑らかな表示を伴うゲームプレイシミュレーション', '補間付き固定更新', 'シミュレーションのステップを保ち、表示側で端数を隠せます。'], ['深刻な停止からの回復', '上限付きの追いつき方針', '1回の悪いフレームが無制限の計算を生まないようにします。']] },
41
+ { type: 'title', level: 2, text: '繰り返し可能な調整手順を使う' },
42
+ { type: 'paragraph', html: 'まずスパイクなしで2つの経路が一致することを確認します。再現可能なヒッチを追加し、頻度を変えて見える誤差が蓄積するか安定するかを見ます。速度を変える前に固定ステップを調整し、追いつき数を確認します。最後に上限を有効にし、可変のシミュレーション時間と実時間を比較します。この順序で、ずれの原因と、それを抑える方針を切り分けられます。' },
43
+ { type: 'tip', title: 'この実験で証明できないこと', html: 'このラボは指定したフレーム時間と一定の速度を使うため、時間処理を説明するものであり、端末を測定したりエンジンを検証したりするものではありません。実際の物理、入力のサンプリング、ネットワーク、補間、フレーム予算によって最適な設計は変わります。結果を仮説として使い、実際のゲームで確認してください。' },
44
+ ],
45
+ faq, bibliographyTitle: 'ゲームループの参考資料', bibliography: bibliographyEntries, howTo, schemas: [softwareApplication, faqPage, howToSchema],
46
+ };