Skip to content

Commit 8a997e3

Browse files
committed
New controls description dialog added
1 parent 281aa91 commit 8a997e3

27 files changed

+3654
-47
lines changed
Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
# Design Document
2+
3+
## Overview
4+
5+
The Controls Menu Dialog feature adds an in-game reference for all keyboard controls accessible from the main game menu. The implementation follows the established dialog pattern used by LanguageDialog and WorldSaveDialog, ensuring visual and architectural consistency. The dialog displays all control bindings organized into logical categories, supports multi-language localization, and integrates seamlessly with the existing menu system.
6+
7+
## Architecture
8+
9+
The feature consists of three main components:
10+
11+
1. **ControlsDialog Class**: A new dialog class that manages the display and interaction logic for the controls reference
12+
2. **GameMenu Integration**: Modifications to GameMenu to add the Controls menu item and handle dialog lifecycle
13+
3. **Localization Resources**: Translation keys added to all supported language files (en, de, nl, pl, pt)
14+
15+
The architecture follows the Model-View-Controller pattern where:
16+
- **Model**: Translation keys and control binding data
17+
- **View**: ControlsDialog rendering logic
18+
- **Controller**: GameMenu input handling and dialog state management
19+
20+
## Components and Interfaces
21+
22+
### ControlsDialog
23+
24+
**Location**: `src/main/java/wagemaker/uk/ui/ControlsDialog.java`
25+
26+
**Responsibilities**:
27+
- Render the controls reference dialog with wooden plank background
28+
- Display all control bindings organized by category
29+
- Handle ESC key input to close the dialog
30+
- Implement LanguageChangeListener for localization support
31+
- Manage dialog visibility state
32+
33+
**Key Methods**:
34+
```java
35+
public ControlsDialog() // Constructor
36+
public void show() // Display the dialog
37+
public void hide() // Hide the dialog
38+
public boolean isVisible() // Check visibility state
39+
public void handleInput() // Process keyboard input
40+
public void render(SpriteBatch, ShapeRenderer, float, float) // Render dialog
41+
public void onLanguageChanged(String) // Handle language changes
42+
public void dispose() // Clean up resources
43+
```
44+
45+
**Dependencies**:
46+
- LocalizationManager: For retrieving translated text
47+
- LibGDX Graphics: For texture and font rendering
48+
- LanguageChangeListener: Interface implementation
49+
50+
### GameMenu Modifications
51+
52+
**Location**: `src/main/java/wagemaker/uk/ui/GameMenu.java`
53+
54+
**Changes Required**:
55+
1. Add ControlsDialog field and initialization
56+
2. Add "Controls" to menu items arrays (singleplayer and multiplayer)
57+
3. Increase MENU_HEIGHT constant to accommodate new menu item
58+
4. Add dialog visibility check in update() method
59+
5. Add dialog rendering in render methods
60+
6. Add menu selection handler for Controls option
61+
7. Add dialog disposal in dispose() method
62+
63+
### Localization Resources
64+
65+
**Location**: `assets/localization/*.json`
66+
67+
**New Translation Keys**:
68+
```
69+
controls_dialog.title
70+
controls_dialog.movement_header
71+
controls_dialog.movement_up
72+
controls_dialog.movement_down
73+
controls_dialog.movement_left
74+
controls_dialog.movement_right
75+
controls_dialog.inventory_header
76+
controls_dialog.inventory_open
77+
controls_dialog.inventory_navigate_left
78+
controls_dialog.inventory_navigate_right
79+
controls_dialog.item_header
80+
controls_dialog.item_plant_p
81+
controls_dialog.item_plant_space
82+
controls_dialog.item_consume
83+
controls_dialog.targeting_header
84+
controls_dialog.targeting_up
85+
controls_dialog.targeting_down
86+
controls_dialog.targeting_left
87+
controls_dialog.targeting_right
88+
controls_dialog.combat_header
89+
controls_dialog.combat_attack
90+
controls_dialog.system_header
91+
controls_dialog.system_menu
92+
controls_dialog.system_delete_world
93+
controls_dialog.system_compass_target
94+
controls_dialog.close_instruction
95+
menu.controls
96+
```
97+
98+
## Data Models
99+
100+
### Control Binding Structure
101+
102+
Controls are organized into logical categories for display:
103+
104+
1. **Movement Controls**
105+
- UP Arrow: Move up
106+
- DOWN Arrow: Move down
107+
- LEFT Arrow: Move left
108+
- RIGHT Arrow: Move right
109+
110+
2. **Inventory Controls**
111+
- I: Open/close inventory
112+
- LEFT Arrow: Navigate inventory left
113+
- RIGHT Arrow: Navigate inventory right
114+
115+
3. **Item Controls**
116+
- P: Plant item
117+
- SPACE: Plant/consume item
118+
- SPACE: Consume item
119+
120+
4. **Targeting Controls**
121+
- W: Target up
122+
- A: Target left
123+
- S: Target down
124+
- D: Target right
125+
126+
5. **Combat Controls**
127+
- SPACE: Attack
128+
129+
6. **System Controls**
130+
- ESC: Open menu
131+
- X: Delete world
132+
- TAB: Set compass target
133+
134+
### Dialog Dimensions
135+
136+
```java
137+
private static final float DIALOG_WIDTH = 840; // Increased by 20% to prevent text overlap in wider languages
138+
private static final float DIALOG_HEIGHT = 480; // Reduced by 20% for better proportions
139+
```
140+
141+
### Menu Dimensions Update
142+
143+
```java
144+
// In GameMenu.java
145+
private static final float MENU_HEIGHT = 340; // Increased from 310 to fit Controls item
146+
```
147+
148+
## Correctness Properties
149+
150+
*A property is a characteristic or behavior that should hold true across all valid executions of a system-essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
151+
152+
### Property 1: Dialog visibility toggles correctly
153+
*For any* dialog state, when show() is called the dialog should become visible, and when hide() is called the dialog should become not visible
154+
**Validates: Requirements 1.2, 1.4**
155+
156+
### Property 2: ESC key closes dialog
157+
*For any* dialog state where isVisible() returns true, simulating ESC key input should result in isVisible() returning false
158+
**Validates: Requirements 1.4**
159+
160+
### Property 3: Dialog prevents game input
161+
*For any* game state where the Controls Dialog is visible, game input handlers should not process player movement or action inputs
162+
**Validates: Requirements 1.3**
163+
164+
### Property 4: All controls are displayed
165+
*For any* rendering of the Controls Dialog, the rendered text should contain descriptions for all defined control bindings (movement, inventory, items, targeting, combat, system)
166+
**Validates: Requirements 2.1-2.9**
167+
168+
### Property 5: Dialog centers on camera
169+
*For any* camera position (camX, camY), the dialog X position should equal camX - DIALOG_WIDTH/2 and dialog Y position should equal camY - DIALOG_HEIGHT/2
170+
**Validates: Requirements 3.4**
171+
172+
### Property 6: Language changes update text
173+
*For any* supported language, when setLanguage() is called on LocalizationManager, the Controls Dialog should retrieve and display text in the new language
174+
**Validates: Requirements 1.5, 4.5**
175+
176+
### Property 7: Translation keys exist in all languages
177+
*For any* translation key defined for the Controls Dialog, that key should exist in all supported language files (en.json, de.json, nl.json, pl.json, pt.json)
178+
**Validates: Requirements 5.1, 5.2-5.6**
179+
180+
### Property 8: No hardcoded strings in rendering
181+
*For any* text displayed in the Controls Dialog, that text should be retrieved from LocalizationManager using a translation key, not hardcoded as a string literal
182+
**Validates: Requirements 5.7**
183+
184+
### Property 9: Listener registration lifecycle
185+
*For any* ControlsDialog instance, after construction the dialog should be registered with LocalizationManager, and after dispose() the dialog should be unregistered
186+
**Validates: Requirements 4.3, 4.4**
187+
188+
## Error Handling
189+
190+
### Input Validation
191+
- No user input validation required (dialog is read-only)
192+
- ESC key handling is fail-safe (always closes dialog)
193+
194+
### Resource Loading
195+
- Font loading failure: Fall back to default LibGDX BitmapFont
196+
- Texture creation failure: Log error and use fallback solid color background
197+
- Translation key missing: LocalizationManager returns key wrapped in brackets [key]
198+
199+
### State Management
200+
- Dialog visibility state is boolean (no invalid states possible)
201+
- Multiple show() calls are idempotent (no side effects)
202+
- Multiple hide() calls are idempotent (no side effects)
203+
204+
### Disposal
205+
- Texture disposal is guarded by null checks
206+
- Font disposal is guarded by null checks
207+
- Listener unregistration is safe even if not registered
208+
209+
## Testing Strategy
210+
211+
### Unit Tests
212+
213+
Unit tests will verify specific examples and edge cases:
214+
215+
1. **Dialog Construction Test**
216+
- Verify dialog initializes with isVisible() = false
217+
- Verify wooden plank texture is created
218+
- Verify font is loaded or fallback is used
219+
220+
2. **Show/Hide Test**
221+
- Verify show() sets isVisible() to true
222+
- Verify hide() sets isVisible() to false
223+
- Verify multiple show() calls are idempotent
224+
225+
3. **Translation Key Existence Test**
226+
- Verify all required translation keys exist in en.json
227+
- Verify all required translation keys exist in all language files
228+
- Verify no translation keys are missing
229+
230+
4. **Menu Integration Test**
231+
- Verify "Controls" menu item is added to singleplayer menu
232+
- Verify "Controls" menu item is added to multiplayer menu
233+
- Verify MENU_HEIGHT is increased appropriately
234+
235+
### Property-Based Tests
236+
237+
Property-based tests will verify universal properties across all inputs:
238+
239+
**Testing Framework**: We will use [junit-quickcheck](https://github.com/pholser/junit-quickcheck) for Java property-based testing, which integrates with JUnit and provides generators for common types.
240+
241+
**Configuration**: Each property-based test will run a minimum of 100 iterations to ensure thorough coverage of the input space.
242+
243+
**Test Tagging**: Each property-based test will include a comment tag in the format:
244+
```java
245+
// Feature: controls-menu-dialog, Property N: [property description]
246+
```
247+
248+
1. **Property Test: Dialog Visibility Toggle**
249+
- Generate random sequences of show()/hide() calls
250+
- Verify isVisible() state matches expected state after each call
251+
- **Validates Property 1**
252+
253+
2. **Property Test: ESC Key Closes Dialog**
254+
- Generate random dialog states (visible/hidden)
255+
- When visible, simulate ESC input and verify dialog closes
256+
- **Validates Property 2**
257+
258+
3. **Property Test: Dialog Centering**
259+
- Generate random camera positions
260+
- Verify dialog X/Y coordinates are correctly centered
261+
- **Validates Property 5**
262+
263+
4. **Property Test: Language Change Updates**
264+
- Generate random language selections from supported languages
265+
- Verify dialog text changes when language changes
266+
- **Validates Property 6**
267+
268+
5. **Property Test: Translation Key Completeness**
269+
- For each required translation key
270+
- Verify key exists in all language files
271+
- **Validates Property 7**
272+
273+
6. **Property Test: No Hardcoded Strings**
274+
- Parse ControlsDialog source code
275+
- Verify all displayed text uses LocalizationManager.getText()
276+
- **Validates Property 8**
277+
278+
### Integration Tests
279+
280+
Integration tests will verify the feature works correctly with other system components:
281+
282+
1. **Menu Navigation Integration Test**
283+
- Open game menu
284+
- Navigate to Controls item
285+
- Press Enter and verify dialog opens
286+
- Press ESC and verify dialog closes
287+
288+
2. **Localization Integration Test**
289+
- Open Controls Dialog
290+
- Change language via Language Dialog
291+
- Verify Controls Dialog text updates automatically
292+
293+
3. **Multi-Dialog Integration Test**
294+
- Open Controls Dialog
295+
- Verify other dialogs cannot be opened simultaneously
296+
- Verify game menu remains accessible after closing dialog
297+
298+
## Implementation Notes
299+
300+
### Visual Consistency
301+
302+
The ControlsDialog must match the visual style of existing dialogs:
303+
- Use same wooden plank texture generation algorithm
304+
- Use same font (Sancreek-Regular.ttf) with size 16
305+
- Use same color scheme (white for labels, yellow for highlights, light gray for instructions)
306+
- Use same border styling (dark brown, 2px thick)
307+
308+
### Performance Considerations
309+
310+
- Texture and font are created once in constructor, not per-frame
311+
- Translation text is retrieved once per render, cached in local variables
312+
- No complex calculations in render loop
313+
- Dialog only renders when visible
314+
315+
### Accessibility
316+
317+
- All text uses high-contrast colors (white/yellow on dark brown)
318+
- Font size is 16pt for readability
319+
- Controls are organized into clear categories with headers
320+
- Simple keyboard navigation (only ESC key required)
321+
322+
### Future Extensibility
323+
324+
The design allows for future enhancements:
325+
- Adding rebindable controls (would require additional UI for key binding)
326+
- Adding controller support (would add new control categories)
327+
- Adding tooltips or help text for complex controls
328+
- Adding search/filter functionality for large control lists

0 commit comments

Comments
 (0)