bmad-method 4.8.0 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/bmad-core/agents/dev.md +10 -22
- package/bmad-core/core-config.yml +2 -0
- package/bmad-core/tasks/shard-doc.md +1 -1
- package/bmad-core/templates/architecture-tmpl.md +2 -2
- package/bmad-core/templates/brownfield-architecture-tmpl.md +2 -2
- package/bmad-core/templates/front-end-spec-tmpl.md +1 -1
- package/bmad-core/utils/workflow-management.md +5 -5
- package/dist/agents/architect.txt +4 -4
- package/dist/agents/bmad-master.txt +11 -11
- package/dist/agents/bmad-orchestrator.txt +5 -5
- package/dist/agents/dev.txt +9 -17
- package/dist/agents/pm.txt +1 -1
- package/dist/agents/po.txt +1 -1
- package/dist/agents/ux-expert.txt +1 -1
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +144 -18
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +139 -95
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +39 -0
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +310 -118
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +16 -16
- package/dist/expansion-packs/expansion-creator/agents/bmad-the-creator.txt +25 -27
- package/dist/teams/team-all.txt +20 -28
- package/dist/teams/team-fullstack.txt +11 -11
- package/dist/teams/team-ide-minimal.txt +15 -23
- package/dist/teams/team-no-ui.txt +10 -10
- package/docs/core-architecture.md +5 -3
- package/docs/how-to-contribute-with-pull-requests.md +6 -6
- package/docs/user-guide.md +51 -66
- package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +107 -87
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.md +4 -4
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.md +21 -2
- package/expansion-packs/bmad-infrastructure-devops/README.md +5 -5
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
- package/expansion-packs/expansion-creator/tasks/create-agent.md +10 -10
- package/expansion-packs/expansion-creator/tasks/generate-expansion-pack.md +2 -4
- package/expansion-packs/expansion-creator/templates/agent-teams-tmpl.md +6 -6
- package/expansion-packs/expansion-creator/templates/agent-tmpl.md +15 -15
- package/expansion-packs/expansion-creator/utils/workflow-management.md +8 -8
- package/package.json +1 -1
- package/tools/installer/README.md +3 -3
- package/tools/installer/package.json +1 -1
|
@@ -290,7 +290,7 @@ This architecture is designed to support the gameplay mechanics defined in the G
|
|
|
290
290
|
│ ├── stories/ # Development stories
|
|
291
291
|
│ └── architecture/ # Technical docs
|
|
292
292
|
└── dist/ # Built game files
|
|
293
|
-
```
|
|
293
|
+
```
|
|
294
294
|
|
|
295
295
|
### Module Organization
|
|
296
296
|
|
|
@@ -575,7 +575,7 @@ const gameConfig: Phaser.Types.Core.GameConfig = {
|
|
|
575
575
|
},
|
|
576
576
|
// Additional configuration...
|
|
577
577
|
};
|
|
578
|
-
```
|
|
578
|
+
```
|
|
579
579
|
|
|
580
580
|
### Game Balance Configuration
|
|
581
581
|
|
|
@@ -776,6 +776,7 @@ export const GameBalance = {
|
|
|
776
776
|
## Story Completeness
|
|
777
777
|
|
|
778
778
|
### Basic Story Elements
|
|
779
|
+
|
|
779
780
|
- [ ] **Story Title** - Clear, descriptive title that identifies the feature
|
|
780
781
|
- [ ] **Epic Assignment** - Story is properly assigned to relevant epic
|
|
781
782
|
- [ ] **Priority Level** - Appropriate priority assigned (High/Medium/Low)
|
|
@@ -783,6 +784,7 @@ export const GameBalance = {
|
|
|
783
784
|
- [ ] **Description** - Clear, concise description of what needs to be implemented
|
|
784
785
|
|
|
785
786
|
### Game Design Alignment
|
|
787
|
+
|
|
786
788
|
- [ ] **GDD Reference** - Specific Game Design Document section referenced
|
|
787
789
|
- [ ] **Game Mechanic Context** - Clear connection to game mechanics defined in GDD
|
|
788
790
|
- [ ] **Player Experience Goal** - Describes the intended player experience
|
|
@@ -792,6 +794,7 @@ export const GameBalance = {
|
|
|
792
794
|
## Technical Specifications
|
|
793
795
|
|
|
794
796
|
### Architecture Compliance
|
|
797
|
+
|
|
795
798
|
- [ ] **File Organization** - Follows game architecture document structure
|
|
796
799
|
- [ ] **Class Definitions** - TypeScript interfaces and classes are properly defined
|
|
797
800
|
- [ ] **Integration Points** - Clear specification of how feature integrates with existing systems
|
|
@@ -799,6 +802,7 @@ export const GameBalance = {
|
|
|
799
802
|
- [ ] **Dependencies** - All system dependencies clearly identified
|
|
800
803
|
|
|
801
804
|
### Phaser 3 Requirements
|
|
805
|
+
|
|
802
806
|
- [ ] **Scene Integration** - Specifies which scenes are affected and how
|
|
803
807
|
- [ ] **Game Object Usage** - Proper use of Phaser 3 game objects and components
|
|
804
808
|
- [ ] **Physics Integration** - Physics requirements specified if applicable
|
|
@@ -806,6 +810,7 @@ export const GameBalance = {
|
|
|
806
810
|
- [ ] **Performance Considerations** - 60 FPS target and optimization requirements
|
|
807
811
|
|
|
808
812
|
### Code Quality Standards
|
|
813
|
+
|
|
809
814
|
- [ ] **TypeScript Strict Mode** - All code must comply with strict TypeScript
|
|
810
815
|
- [ ] **Error Handling** - Error scenarios and handling requirements specified
|
|
811
816
|
- [ ] **Memory Management** - Object pooling and cleanup requirements where needed
|
|
@@ -815,6 +820,7 @@ export const GameBalance = {
|
|
|
815
820
|
## Implementation Readiness
|
|
816
821
|
|
|
817
822
|
### Acceptance Criteria
|
|
823
|
+
|
|
818
824
|
- [ ] **Functional Requirements** - All functional acceptance criteria are specific and testable
|
|
819
825
|
- [ ] **Technical Requirements** - Technical acceptance criteria are complete and verifiable
|
|
820
826
|
- [ ] **Game Design Requirements** - Game-specific requirements match GDD specifications
|
|
@@ -822,6 +828,7 @@ export const GameBalance = {
|
|
|
822
828
|
- [ ] **Completeness** - No acceptance criteria are vague or unmeasurable
|
|
823
829
|
|
|
824
830
|
### Implementation Tasks
|
|
831
|
+
|
|
825
832
|
- [ ] **Task Breakdown** - Story broken into specific, ordered implementation tasks
|
|
826
833
|
- [ ] **Task Scope** - Each task is completable in 1-4 hours
|
|
827
834
|
- [ ] **Task Clarity** - Each task has clear, actionable instructions
|
|
@@ -829,6 +836,7 @@ export const GameBalance = {
|
|
|
829
836
|
- [ ] **Development Flow** - Tasks follow logical implementation order
|
|
830
837
|
|
|
831
838
|
### Dependencies
|
|
839
|
+
|
|
832
840
|
- [ ] **Story Dependencies** - All prerequisite stories identified with IDs
|
|
833
841
|
- [ ] **Technical Dependencies** - Required systems and files identified
|
|
834
842
|
- [ ] **Asset Dependencies** - All needed assets specified with locations
|
|
@@ -838,6 +846,7 @@ export const GameBalance = {
|
|
|
838
846
|
## Testing Requirements
|
|
839
847
|
|
|
840
848
|
### Test Coverage
|
|
849
|
+
|
|
841
850
|
- [ ] **Unit Test Requirements** - Specific unit test files and scenarios defined
|
|
842
851
|
- [ ] **Integration Test Cases** - Integration testing with other game systems specified
|
|
843
852
|
- [ ] **Manual Test Cases** - Game-specific manual testing procedures defined
|
|
@@ -845,6 +854,7 @@ export const GameBalance = {
|
|
|
845
854
|
- [ ] **Edge Case Testing** - Edge cases and error conditions covered
|
|
846
855
|
|
|
847
856
|
### Test Implementation
|
|
857
|
+
|
|
848
858
|
- [ ] **Test File Paths** - Exact test file locations specified
|
|
849
859
|
- [ ] **Test Scenarios** - All test scenarios are complete and executable
|
|
850
860
|
- [ ] **Expected Behaviors** - Clear expected outcomes for all tests defined
|
|
@@ -854,6 +864,7 @@ export const GameBalance = {
|
|
|
854
864
|
## Game-Specific Quality
|
|
855
865
|
|
|
856
866
|
### Gameplay Implementation
|
|
867
|
+
|
|
857
868
|
- [ ] **Mechanic Accuracy** - Implementation matches GDD mechanic specifications
|
|
858
869
|
- [ ] **Player Controls** - Input handling requirements are complete
|
|
859
870
|
- [ ] **Game Feel** - Requirements for juice, feedback, and responsiveness specified
|
|
@@ -861,6 +872,7 @@ export const GameBalance = {
|
|
|
861
872
|
- [ ] **State Management** - Game state changes and persistence requirements defined
|
|
862
873
|
|
|
863
874
|
### User Experience
|
|
875
|
+
|
|
864
876
|
- [ ] **UI Requirements** - User interface elements and behaviors specified
|
|
865
877
|
- [ ] **Audio Integration** - Sound effect and music requirements defined
|
|
866
878
|
- [ ] **Visual Feedback** - Animation and visual effect requirements specified
|
|
@@ -868,6 +880,7 @@ export const GameBalance = {
|
|
|
868
880
|
- [ ] **Error Recovery** - User-facing error handling and recovery specified
|
|
869
881
|
|
|
870
882
|
### Performance Optimization
|
|
883
|
+
|
|
871
884
|
- [ ] **Frame Rate Targets** - Specific FPS requirements for different platforms
|
|
872
885
|
- [ ] **Memory Usage** - Memory consumption limits and monitoring requirements
|
|
873
886
|
- [ ] **Asset Optimization** - Texture, audio, and data optimization requirements
|
|
@@ -877,6 +890,7 @@ export const GameBalance = {
|
|
|
877
890
|
## Documentation and Communication
|
|
878
891
|
|
|
879
892
|
### Story Documentation
|
|
893
|
+
|
|
880
894
|
- [ ] **Implementation Notes** - Additional context and implementation guidance provided
|
|
881
895
|
- [ ] **Design Decisions** - Key design choices documented with rationale
|
|
882
896
|
- [ ] **Future Considerations** - Potential future enhancements or modifications noted
|
|
@@ -884,6 +898,7 @@ export const GameBalance = {
|
|
|
884
898
|
- [ ] **Reference Materials** - Links to relevant GDD sections and architecture docs
|
|
885
899
|
|
|
886
900
|
### Developer Handoff
|
|
901
|
+
|
|
887
902
|
- [ ] **Immediate Actionability** - Developer can start implementation without additional questions
|
|
888
903
|
- [ ] **Complete Context** - All necessary context provided within the story
|
|
889
904
|
- [ ] **Clear Boundaries** - What is and isn't included in the story scope is clear
|
|
@@ -893,6 +908,7 @@ export const GameBalance = {
|
|
|
893
908
|
## Final Validation
|
|
894
909
|
|
|
895
910
|
### Story Readiness
|
|
911
|
+
|
|
896
912
|
- [ ] **No Ambiguity** - No sections require interpretation or additional design decisions
|
|
897
913
|
- [ ] **Technical Completeness** - All technical requirements are specified and actionable
|
|
898
914
|
- [ ] **Scope Appropriateness** - Story scope matches assigned story points
|
|
@@ -900,6 +916,7 @@ export const GameBalance = {
|
|
|
900
916
|
- [ ] **Review Completion** - Story has been reviewed for completeness and accuracy
|
|
901
917
|
|
|
902
918
|
### Implementation Preparedness
|
|
919
|
+
|
|
903
920
|
- [ ] **Environment Ready** - Development environment requirements specified
|
|
904
921
|
- [ ] **Resources Available** - All required resources (assets, docs, dependencies) accessible
|
|
905
922
|
- [ ] **Testing Prepared** - Testing environment and data requirements specified
|
|
@@ -928,6 +945,7 @@ This document establishes coding standards, architectural patterns, and developm
|
|
|
928
945
|
### Strict Mode Configuration
|
|
929
946
|
|
|
930
947
|
**Required tsconfig.json settings:**
|
|
948
|
+
|
|
931
949
|
```json
|
|
932
950
|
{
|
|
933
951
|
"compilerOptions": {
|
|
@@ -941,11 +959,12 @@ This document establishes coding standards, architectural patterns, and developm
|
|
|
941
959
|
"exactOptionalPropertyTypes": true
|
|
942
960
|
}
|
|
943
961
|
}
|
|
944
|
-
```
|
|
962
|
+
```
|
|
945
963
|
|
|
946
964
|
### Type Definitions
|
|
947
965
|
|
|
948
966
|
**Game Object Interfaces:**
|
|
967
|
+
|
|
949
968
|
```typescript
|
|
950
969
|
// Core game entity interface
|
|
951
970
|
interface GameEntity {
|
|
@@ -969,9 +988,10 @@ interface GameSystem {
|
|
|
969
988
|
update(delta: number): void;
|
|
970
989
|
shutdown(): void;
|
|
971
990
|
}
|
|
972
|
-
```
|
|
991
|
+
```
|
|
973
992
|
|
|
974
993
|
**Scene Data Interfaces:**
|
|
994
|
+
|
|
975
995
|
```typescript
|
|
976
996
|
// Scene transition data
|
|
977
997
|
interface SceneData {
|
|
@@ -989,28 +1009,32 @@ interface GameState {
|
|
|
989
1009
|
interface GameSettings {
|
|
990
1010
|
musicVolume: number;
|
|
991
1011
|
sfxVolume: number;
|
|
992
|
-
difficulty:
|
|
1012
|
+
difficulty: "easy" | "normal" | "hard";
|
|
993
1013
|
controls: ControlScheme;
|
|
994
1014
|
}
|
|
995
|
-
```
|
|
1015
|
+
```
|
|
996
1016
|
|
|
997
1017
|
### Naming Conventions
|
|
998
1018
|
|
|
999
1019
|
**Classes and Interfaces:**
|
|
1020
|
+
|
|
1000
1021
|
- PascalCase for classes: `PlayerSprite`, `GameManager`, `AudioSystem`
|
|
1001
1022
|
- PascalCase with 'I' prefix for interfaces: `IGameEntity`, `IPlayerController`
|
|
1002
1023
|
- Descriptive names that indicate purpose: `CollisionManager` not `CM`
|
|
1003
1024
|
|
|
1004
1025
|
**Methods and Variables:**
|
|
1026
|
+
|
|
1005
1027
|
- camelCase for methods and variables: `updatePosition()`, `playerSpeed`
|
|
1006
1028
|
- Descriptive names: `calculateDamage()` not `calcDmg()`
|
|
1007
1029
|
- Boolean variables with is/has/can prefix: `isActive`, `hasCollision`, `canMove`
|
|
1008
1030
|
|
|
1009
1031
|
**Constants:**
|
|
1032
|
+
|
|
1010
1033
|
- UPPER_SNAKE_CASE for constants: `MAX_PLAYER_SPEED`, `DEFAULT_VOLUME`
|
|
1011
1034
|
- Group related constants in enums or const objects
|
|
1012
1035
|
|
|
1013
1036
|
**Files and Directories:**
|
|
1037
|
+
|
|
1014
1038
|
- kebab-case for file names: `player-controller.ts`, `audio-manager.ts`
|
|
1015
1039
|
- PascalCase for scene files: `MenuScene.ts`, `GameScene.ts`
|
|
1016
1040
|
|
|
@@ -1019,88 +1043,91 @@ interface GameSettings {
|
|
|
1019
1043
|
### Scene Organization
|
|
1020
1044
|
|
|
1021
1045
|
**Scene Lifecycle Management:**
|
|
1046
|
+
|
|
1022
1047
|
```typescript
|
|
1023
1048
|
class GameScene extends Phaser.Scene {
|
|
1024
1049
|
private gameManager!: GameManager;
|
|
1025
1050
|
private inputManager!: InputManager;
|
|
1026
|
-
|
|
1051
|
+
|
|
1027
1052
|
constructor() {
|
|
1028
|
-
super({ key:
|
|
1053
|
+
super({ key: "GameScene" });
|
|
1029
1054
|
}
|
|
1030
|
-
|
|
1055
|
+
|
|
1031
1056
|
preload(): void {
|
|
1032
1057
|
// Load only scene-specific assets
|
|
1033
|
-
this.load.image(
|
|
1058
|
+
this.load.image("player", "assets/player.png");
|
|
1034
1059
|
}
|
|
1035
|
-
|
|
1060
|
+
|
|
1036
1061
|
create(data: SceneData): void {
|
|
1037
1062
|
// Initialize game systems
|
|
1038
1063
|
this.gameManager = new GameManager(this);
|
|
1039
1064
|
this.inputManager = new InputManager(this);
|
|
1040
|
-
|
|
1065
|
+
|
|
1041
1066
|
// Set up scene-specific logic
|
|
1042
1067
|
this.setupGameObjects();
|
|
1043
1068
|
this.setupEventListeners();
|
|
1044
1069
|
}
|
|
1045
|
-
|
|
1070
|
+
|
|
1046
1071
|
update(time: number, delta: number): void {
|
|
1047
1072
|
// Update all game systems
|
|
1048
1073
|
this.gameManager.update(delta);
|
|
1049
1074
|
this.inputManager.update(delta);
|
|
1050
1075
|
}
|
|
1051
|
-
|
|
1076
|
+
|
|
1052
1077
|
shutdown(): void {
|
|
1053
1078
|
// Clean up resources
|
|
1054
1079
|
this.gameManager.destroy();
|
|
1055
1080
|
this.inputManager.destroy();
|
|
1056
|
-
|
|
1081
|
+
|
|
1057
1082
|
// Remove event listeners
|
|
1058
|
-
this.events.off(
|
|
1083
|
+
this.events.off("*");
|
|
1059
1084
|
}
|
|
1060
1085
|
}
|
|
1061
1086
|
```
|
|
1062
1087
|
|
|
1063
1088
|
**Scene Transitions:**
|
|
1089
|
+
|
|
1064
1090
|
```typescript
|
|
1065
1091
|
// Proper scene transitions with data
|
|
1066
|
-
this.scene.start(
|
|
1092
|
+
this.scene.start("NextScene", {
|
|
1067
1093
|
playerScore: this.playerScore,
|
|
1068
|
-
currentLevel: this.currentLevel + 1
|
|
1094
|
+
currentLevel: this.currentLevel + 1,
|
|
1069
1095
|
});
|
|
1070
1096
|
|
|
1071
1097
|
// Scene overlays for UI
|
|
1072
|
-
this.scene.launch(
|
|
1098
|
+
this.scene.launch("PauseMenuScene");
|
|
1073
1099
|
this.scene.pause();
|
|
1074
|
-
```
|
|
1100
|
+
```
|
|
1075
1101
|
|
|
1076
1102
|
### Game Object Patterns
|
|
1077
1103
|
|
|
1078
1104
|
**Component-Based Architecture:**
|
|
1105
|
+
|
|
1079
1106
|
```typescript
|
|
1080
1107
|
// Base game entity
|
|
1081
1108
|
abstract class GameEntity extends Phaser.GameObjects.Sprite {
|
|
1082
1109
|
protected components: Map<string, GameComponent> = new Map();
|
|
1083
|
-
|
|
1110
|
+
|
|
1084
1111
|
constructor(scene: Phaser.Scene, x: number, y: number, texture: string) {
|
|
1085
1112
|
super(scene, x, y, texture);
|
|
1086
1113
|
scene.add.existing(this);
|
|
1087
1114
|
}
|
|
1088
|
-
|
|
1115
|
+
|
|
1089
1116
|
addComponent<T extends GameComponent>(component: T): T {
|
|
1090
1117
|
this.components.set(component.name, component);
|
|
1091
1118
|
return component;
|
|
1092
1119
|
}
|
|
1093
|
-
|
|
1120
|
+
|
|
1094
1121
|
getComponent<T extends GameComponent>(name: string): T | undefined {
|
|
1095
1122
|
return this.components.get(name) as T;
|
|
1096
1123
|
}
|
|
1097
|
-
|
|
1124
|
+
|
|
1098
1125
|
update(delta: number): void {
|
|
1099
|
-
this.components.forEach(component => component.update(delta));
|
|
1126
|
+
this.components.forEach((component) => component.update(delta));
|
|
1100
1127
|
}
|
|
1101
|
-
|
|
1128
|
+
|
|
1102
1129
|
destroy(): void {
|
|
1103
|
-
this.components.forEach(component => component.destroy());
|
|
1130
|
+
this.components.forEach((component) => component.destroy());
|
|
1104
1131
|
this.components.clear();
|
|
1105
1132
|
super.destroy();
|
|
1106
1133
|
}
|
|
@@ -1110,65 +1137,67 @@ abstract class GameEntity extends Phaser.GameObjects.Sprite {
|
|
|
1110
1137
|
class Player extends GameEntity {
|
|
1111
1138
|
private movement!: MovementComponent;
|
|
1112
1139
|
private health!: HealthComponent;
|
|
1113
|
-
|
|
1140
|
+
|
|
1114
1141
|
constructor(scene: Phaser.Scene, x: number, y: number) {
|
|
1115
|
-
super(scene, x, y,
|
|
1116
|
-
|
|
1142
|
+
super(scene, x, y, "player");
|
|
1143
|
+
|
|
1117
1144
|
this.movement = this.addComponent(new MovementComponent(this));
|
|
1118
1145
|
this.health = this.addComponent(new HealthComponent(this, 100));
|
|
1119
1146
|
}
|
|
1120
1147
|
}
|
|
1121
|
-
```
|
|
1148
|
+
```
|
|
1122
1149
|
|
|
1123
1150
|
### System Management
|
|
1124
1151
|
|
|
1125
1152
|
**Singleton Managers:**
|
|
1153
|
+
|
|
1126
1154
|
```typescript
|
|
1127
1155
|
class GameManager {
|
|
1128
1156
|
private static instance: GameManager;
|
|
1129
1157
|
private scene: Phaser.Scene;
|
|
1130
1158
|
private gameState: GameState;
|
|
1131
|
-
|
|
1159
|
+
|
|
1132
1160
|
constructor(scene: Phaser.Scene) {
|
|
1133
1161
|
if (GameManager.instance) {
|
|
1134
|
-
throw new Error(
|
|
1162
|
+
throw new Error("GameManager already exists!");
|
|
1135
1163
|
}
|
|
1136
|
-
|
|
1164
|
+
|
|
1137
1165
|
this.scene = scene;
|
|
1138
1166
|
this.gameState = this.loadGameState();
|
|
1139
1167
|
GameManager.instance = this;
|
|
1140
1168
|
}
|
|
1141
|
-
|
|
1169
|
+
|
|
1142
1170
|
static getInstance(): GameManager {
|
|
1143
1171
|
if (!GameManager.instance) {
|
|
1144
|
-
throw new Error(
|
|
1172
|
+
throw new Error("GameManager not initialized!");
|
|
1145
1173
|
}
|
|
1146
1174
|
return GameManager.instance;
|
|
1147
1175
|
}
|
|
1148
|
-
|
|
1176
|
+
|
|
1149
1177
|
update(delta: number): void {
|
|
1150
1178
|
// Update game logic
|
|
1151
1179
|
}
|
|
1152
|
-
|
|
1180
|
+
|
|
1153
1181
|
destroy(): void {
|
|
1154
1182
|
GameManager.instance = null!;
|
|
1155
1183
|
}
|
|
1156
1184
|
}
|
|
1157
|
-
```
|
|
1185
|
+
```
|
|
1158
1186
|
|
|
1159
1187
|
## Performance Optimization
|
|
1160
1188
|
|
|
1161
1189
|
### Object Pooling
|
|
1162
1190
|
|
|
1163
1191
|
**Required for High-Frequency Objects:**
|
|
1192
|
+
|
|
1164
1193
|
```typescript
|
|
1165
1194
|
class BulletPool {
|
|
1166
1195
|
private pool: Bullet[] = [];
|
|
1167
1196
|
private scene: Phaser.Scene;
|
|
1168
|
-
|
|
1197
|
+
|
|
1169
1198
|
constructor(scene: Phaser.Scene, initialSize: number = 50) {
|
|
1170
1199
|
this.scene = scene;
|
|
1171
|
-
|
|
1200
|
+
|
|
1172
1201
|
// Pre-create bullets
|
|
1173
1202
|
for (let i = 0; i < initialSize; i++) {
|
|
1174
1203
|
const bullet = new Bullet(scene, 0, 0);
|
|
@@ -1177,20 +1206,20 @@ class BulletPool {
|
|
|
1177
1206
|
this.pool.push(bullet);
|
|
1178
1207
|
}
|
|
1179
1208
|
}
|
|
1180
|
-
|
|
1209
|
+
|
|
1181
1210
|
getBullet(): Bullet | null {
|
|
1182
|
-
const bullet = this.pool.find(b => !b.active);
|
|
1211
|
+
const bullet = this.pool.find((b) => !b.active);
|
|
1183
1212
|
if (bullet) {
|
|
1184
1213
|
bullet.setActive(true);
|
|
1185
1214
|
bullet.setVisible(true);
|
|
1186
1215
|
return bullet;
|
|
1187
1216
|
}
|
|
1188
|
-
|
|
1217
|
+
|
|
1189
1218
|
// Pool exhausted - create new bullet
|
|
1190
|
-
console.warn(
|
|
1219
|
+
console.warn("Bullet pool exhausted, creating new bullet");
|
|
1191
1220
|
return new Bullet(this.scene, 0, 0);
|
|
1192
1221
|
}
|
|
1193
|
-
|
|
1222
|
+
|
|
1194
1223
|
releaseBullet(bullet: Bullet): void {
|
|
1195
1224
|
bullet.setActive(false);
|
|
1196
1225
|
bullet.setVisible(false);
|
|
@@ -1202,45 +1231,47 @@ class BulletPool {
|
|
|
1202
1231
|
### Frame Rate Optimization
|
|
1203
1232
|
|
|
1204
1233
|
**Performance Monitoring:**
|
|
1234
|
+
|
|
1205
1235
|
```typescript
|
|
1206
1236
|
class PerformanceMonitor {
|
|
1207
1237
|
private frameCount: number = 0;
|
|
1208
1238
|
private lastTime: number = 0;
|
|
1209
1239
|
private frameRate: number = 60;
|
|
1210
|
-
|
|
1240
|
+
|
|
1211
1241
|
update(time: number): void {
|
|
1212
1242
|
this.frameCount++;
|
|
1213
|
-
|
|
1243
|
+
|
|
1214
1244
|
if (time - this.lastTime >= 1000) {
|
|
1215
1245
|
this.frameRate = this.frameCount;
|
|
1216
1246
|
this.frameCount = 0;
|
|
1217
1247
|
this.lastTime = time;
|
|
1218
|
-
|
|
1248
|
+
|
|
1219
1249
|
if (this.frameRate < 55) {
|
|
1220
1250
|
console.warn(`Low frame rate detected: ${this.frameRate} FPS`);
|
|
1221
1251
|
this.optimizePerformance();
|
|
1222
1252
|
}
|
|
1223
1253
|
}
|
|
1224
1254
|
}
|
|
1225
|
-
|
|
1255
|
+
|
|
1226
1256
|
private optimizePerformance(): void {
|
|
1227
1257
|
// Reduce particle counts, disable effects, etc.
|
|
1228
1258
|
}
|
|
1229
1259
|
}
|
|
1230
|
-
```
|
|
1260
|
+
```
|
|
1231
1261
|
|
|
1232
1262
|
**Update Loop Optimization:**
|
|
1263
|
+
|
|
1233
1264
|
```typescript
|
|
1234
1265
|
// Avoid expensive operations in update loops
|
|
1235
1266
|
class GameScene extends Phaser.Scene {
|
|
1236
1267
|
private updateTimer: number = 0;
|
|
1237
1268
|
private readonly UPDATE_INTERVAL = 100; // ms
|
|
1238
|
-
|
|
1269
|
+
|
|
1239
1270
|
update(time: number, delta: number): void {
|
|
1240
1271
|
// High-frequency updates (every frame)
|
|
1241
1272
|
this.updatePlayer(delta);
|
|
1242
1273
|
this.updatePhysics(delta);
|
|
1243
|
-
|
|
1274
|
+
|
|
1244
1275
|
// Low-frequency updates (10 times per second)
|
|
1245
1276
|
this.updateTimer += delta;
|
|
1246
1277
|
if (this.updateTimer >= this.UPDATE_INTERVAL) {
|
|
@@ -1250,13 +1281,14 @@ class GameScene extends Phaser.Scene {
|
|
|
1250
1281
|
}
|
|
1251
1282
|
}
|
|
1252
1283
|
}
|
|
1253
|
-
```
|
|
1284
|
+
```
|
|
1254
1285
|
|
|
1255
1286
|
## Input Handling
|
|
1256
1287
|
|
|
1257
1288
|
### Cross-Platform Input
|
|
1258
1289
|
|
|
1259
1290
|
**Input Abstraction:**
|
|
1291
|
+
|
|
1260
1292
|
```typescript
|
|
1261
1293
|
interface InputState {
|
|
1262
1294
|
moveLeft: boolean;
|
|
@@ -1272,26 +1304,26 @@ class InputManager {
|
|
|
1272
1304
|
moveRight: false,
|
|
1273
1305
|
jump: false,
|
|
1274
1306
|
action: false,
|
|
1275
|
-
pause: false
|
|
1307
|
+
pause: false,
|
|
1276
1308
|
};
|
|
1277
|
-
|
|
1309
|
+
|
|
1278
1310
|
private keys!: { [key: string]: Phaser.Input.Keyboard.Key };
|
|
1279
1311
|
private pointer!: Phaser.Input.Pointer;
|
|
1280
|
-
|
|
1312
|
+
|
|
1281
1313
|
constructor(private scene: Phaser.Scene) {
|
|
1282
1314
|
this.setupKeyboard();
|
|
1283
1315
|
this.setupTouch();
|
|
1284
1316
|
}
|
|
1285
|
-
|
|
1317
|
+
|
|
1286
1318
|
private setupKeyboard(): void {
|
|
1287
|
-
this.keys = this.scene.input.keyboard.addKeys(
|
|
1319
|
+
this.keys = this.scene.input.keyboard.addKeys("W,A,S,D,SPACE,ESC,UP,DOWN,LEFT,RIGHT");
|
|
1288
1320
|
}
|
|
1289
|
-
|
|
1321
|
+
|
|
1290
1322
|
private setupTouch(): void {
|
|
1291
|
-
this.scene.input.on(
|
|
1292
|
-
this.scene.input.on(
|
|
1323
|
+
this.scene.input.on("pointerdown", this.handlePointerDown, this);
|
|
1324
|
+
this.scene.input.on("pointerup", this.handlePointerUp, this);
|
|
1293
1325
|
}
|
|
1294
|
-
|
|
1326
|
+
|
|
1295
1327
|
update(): void {
|
|
1296
1328
|
// Update input state from multiple sources
|
|
1297
1329
|
this.inputState.moveLeft = this.keys.A.isDown || this.keys.LEFT.isDown;
|
|
@@ -1299,42 +1331,43 @@ class InputManager {
|
|
|
1299
1331
|
this.inputState.jump = Phaser.Input.Keyboard.JustDown(this.keys.SPACE);
|
|
1300
1332
|
// ... handle touch input
|
|
1301
1333
|
}
|
|
1302
|
-
|
|
1334
|
+
|
|
1303
1335
|
getInputState(): InputState {
|
|
1304
1336
|
return { ...this.inputState };
|
|
1305
1337
|
}
|
|
1306
1338
|
}
|
|
1307
|
-
```
|
|
1339
|
+
```
|
|
1308
1340
|
|
|
1309
1341
|
## Error Handling
|
|
1310
1342
|
|
|
1311
1343
|
### Graceful Degradation
|
|
1312
1344
|
|
|
1313
1345
|
**Asset Loading Error Handling:**
|
|
1346
|
+
|
|
1314
1347
|
```typescript
|
|
1315
1348
|
class AssetManager {
|
|
1316
1349
|
loadAssets(): Promise<void> {
|
|
1317
1350
|
return new Promise((resolve, reject) => {
|
|
1318
|
-
this.scene.load.on(
|
|
1319
|
-
this.scene.load.on(
|
|
1320
|
-
this.scene.load.on(
|
|
1321
|
-
|
|
1351
|
+
this.scene.load.on("filecomplete", this.handleFileComplete, this);
|
|
1352
|
+
this.scene.load.on("loaderror", this.handleLoadError, this);
|
|
1353
|
+
this.scene.load.on("complete", () => resolve());
|
|
1354
|
+
|
|
1322
1355
|
this.scene.load.start();
|
|
1323
1356
|
});
|
|
1324
1357
|
}
|
|
1325
|
-
|
|
1358
|
+
|
|
1326
1359
|
private handleLoadError(file: Phaser.Loader.File): void {
|
|
1327
1360
|
console.error(`Failed to load asset: ${file.key}`);
|
|
1328
|
-
|
|
1361
|
+
|
|
1329
1362
|
// Use fallback assets
|
|
1330
1363
|
this.loadFallbackAsset(file.key);
|
|
1331
1364
|
}
|
|
1332
|
-
|
|
1365
|
+
|
|
1333
1366
|
private loadFallbackAsset(key: string): void {
|
|
1334
1367
|
// Load placeholder or default assets
|
|
1335
1368
|
switch (key) {
|
|
1336
|
-
case
|
|
1337
|
-
this.scene.load.image(
|
|
1369
|
+
case "player":
|
|
1370
|
+
this.scene.load.image("player", "assets/defaults/default-player.png");
|
|
1338
1371
|
break;
|
|
1339
1372
|
default:
|
|
1340
1373
|
console.warn(`No fallback for asset: ${key}`);
|
|
@@ -1346,25 +1379,26 @@ class AssetManager {
|
|
|
1346
1379
|
### Runtime Error Recovery
|
|
1347
1380
|
|
|
1348
1381
|
**System Error Handling:**
|
|
1382
|
+
|
|
1349
1383
|
```typescript
|
|
1350
1384
|
class GameSystem {
|
|
1351
1385
|
protected handleError(error: Error, context: string): void {
|
|
1352
1386
|
console.error(`Error in ${context}:`, error);
|
|
1353
|
-
|
|
1387
|
+
|
|
1354
1388
|
// Report to analytics/logging service
|
|
1355
1389
|
this.reportError(error, context);
|
|
1356
|
-
|
|
1390
|
+
|
|
1357
1391
|
// Attempt recovery
|
|
1358
1392
|
this.attemptRecovery(context);
|
|
1359
1393
|
}
|
|
1360
|
-
|
|
1394
|
+
|
|
1361
1395
|
private attemptRecovery(context: string): void {
|
|
1362
1396
|
switch (context) {
|
|
1363
|
-
case
|
|
1397
|
+
case "update":
|
|
1364
1398
|
// Reset system state
|
|
1365
1399
|
this.reset();
|
|
1366
1400
|
break;
|
|
1367
|
-
case
|
|
1401
|
+
case "render":
|
|
1368
1402
|
// Disable visual effects
|
|
1369
1403
|
this.disableEffects();
|
|
1370
1404
|
break;
|
|
@@ -1374,64 +1408,66 @@ class GameSystem {
|
|
|
1374
1408
|
}
|
|
1375
1409
|
}
|
|
1376
1410
|
}
|
|
1377
|
-
```
|
|
1411
|
+
```
|
|
1378
1412
|
|
|
1379
1413
|
## Testing Standards
|
|
1380
1414
|
|
|
1381
1415
|
### Unit Testing
|
|
1382
1416
|
|
|
1383
1417
|
**Game Logic Testing:**
|
|
1418
|
+
|
|
1384
1419
|
```typescript
|
|
1385
1420
|
// Example test for game mechanics
|
|
1386
|
-
describe(
|
|
1421
|
+
describe("HealthComponent", () => {
|
|
1387
1422
|
let healthComponent: HealthComponent;
|
|
1388
|
-
|
|
1423
|
+
|
|
1389
1424
|
beforeEach(() => {
|
|
1390
1425
|
const mockEntity = {} as GameEntity;
|
|
1391
1426
|
healthComponent = new HealthComponent(mockEntity, 100);
|
|
1392
1427
|
});
|
|
1393
|
-
|
|
1394
|
-
test(
|
|
1428
|
+
|
|
1429
|
+
test("should initialize with correct health", () => {
|
|
1395
1430
|
expect(healthComponent.currentHealth).toBe(100);
|
|
1396
1431
|
expect(healthComponent.maxHealth).toBe(100);
|
|
1397
1432
|
});
|
|
1398
|
-
|
|
1399
|
-
test(
|
|
1433
|
+
|
|
1434
|
+
test("should handle damage correctly", () => {
|
|
1400
1435
|
healthComponent.takeDamage(25);
|
|
1401
1436
|
expect(healthComponent.currentHealth).toBe(75);
|
|
1402
1437
|
expect(healthComponent.isAlive()).toBe(true);
|
|
1403
1438
|
});
|
|
1404
|
-
|
|
1405
|
-
test(
|
|
1439
|
+
|
|
1440
|
+
test("should handle death correctly", () => {
|
|
1406
1441
|
healthComponent.takeDamage(150);
|
|
1407
1442
|
expect(healthComponent.currentHealth).toBe(0);
|
|
1408
1443
|
expect(healthComponent.isAlive()).toBe(false);
|
|
1409
1444
|
});
|
|
1410
1445
|
});
|
|
1411
|
-
```
|
|
1446
|
+
```
|
|
1412
1447
|
|
|
1413
1448
|
### Integration Testing
|
|
1414
1449
|
|
|
1415
1450
|
**Scene Testing:**
|
|
1451
|
+
|
|
1416
1452
|
```typescript
|
|
1417
|
-
describe(
|
|
1453
|
+
describe("GameScene Integration", () => {
|
|
1418
1454
|
let scene: GameScene;
|
|
1419
1455
|
let mockGame: Phaser.Game;
|
|
1420
|
-
|
|
1456
|
+
|
|
1421
1457
|
beforeEach(() => {
|
|
1422
1458
|
// Mock Phaser game instance
|
|
1423
1459
|
mockGame = createMockGame();
|
|
1424
1460
|
scene = new GameScene();
|
|
1425
1461
|
});
|
|
1426
|
-
|
|
1427
|
-
test(
|
|
1462
|
+
|
|
1463
|
+
test("should initialize all systems", () => {
|
|
1428
1464
|
scene.create({});
|
|
1429
|
-
|
|
1465
|
+
|
|
1430
1466
|
expect(scene.gameManager).toBeDefined();
|
|
1431
1467
|
expect(scene.inputManager).toBeDefined();
|
|
1432
1468
|
});
|
|
1433
1469
|
});
|
|
1434
|
-
```
|
|
1470
|
+
```
|
|
1435
1471
|
|
|
1436
1472
|
## File Organization
|
|
1437
1473
|
|
|
@@ -1485,21 +1521,25 @@ src/
|
|
|
1485
1521
|
### Story Implementation Process
|
|
1486
1522
|
|
|
1487
1523
|
1. **Read Story Requirements:**
|
|
1524
|
+
|
|
1488
1525
|
- Understand acceptance criteria
|
|
1489
1526
|
- Identify technical requirements
|
|
1490
1527
|
- Review performance constraints
|
|
1491
1528
|
|
|
1492
1529
|
2. **Plan Implementation:**
|
|
1530
|
+
|
|
1493
1531
|
- Identify files to create/modify
|
|
1494
1532
|
- Consider component architecture
|
|
1495
1533
|
- Plan testing approach
|
|
1496
1534
|
|
|
1497
1535
|
3. **Implement Feature:**
|
|
1536
|
+
|
|
1498
1537
|
- Follow TypeScript strict mode
|
|
1499
1538
|
- Use established patterns
|
|
1500
1539
|
- Maintain 60 FPS performance
|
|
1501
1540
|
|
|
1502
1541
|
4. **Test Implementation:**
|
|
1542
|
+
|
|
1503
1543
|
- Write unit tests for game logic
|
|
1504
1544
|
- Test cross-platform functionality
|
|
1505
1545
|
- Validate performance targets
|
|
@@ -1512,6 +1552,7 @@ src/
|
|
|
1512
1552
|
### Code Review Checklist
|
|
1513
1553
|
|
|
1514
1554
|
**Before Committing:**
|
|
1555
|
+
|
|
1515
1556
|
- [ ] TypeScript compiles without errors
|
|
1516
1557
|
- [ ] All tests pass
|
|
1517
1558
|
- [ ] Performance targets met (60 FPS)
|
|
@@ -1525,17 +1566,20 @@ src/
|
|
|
1525
1566
|
## Performance Targets
|
|
1526
1567
|
|
|
1527
1568
|
### Frame Rate Requirements
|
|
1569
|
+
|
|
1528
1570
|
- **Desktop**: Maintain 60 FPS at 1080p
|
|
1529
1571
|
- **Mobile**: Maintain 60 FPS on mid-range devices, minimum 30 FPS on low-end
|
|
1530
1572
|
- **Optimization**: Implement dynamic quality scaling when performance drops
|
|
1531
1573
|
|
|
1532
1574
|
### Memory Management
|
|
1575
|
+
|
|
1533
1576
|
- **Total Memory**: Under 100MB for full game
|
|
1534
1577
|
- **Per Scene**: Under 50MB per gameplay scene
|
|
1535
1578
|
- **Asset Loading**: Progressive loading to stay under limits
|
|
1536
1579
|
- **Garbage Collection**: Minimize object creation in update loops
|
|
1537
1580
|
|
|
1538
1581
|
### Loading Performance
|
|
1582
|
+
|
|
1539
1583
|
- **Initial Load**: Under 5 seconds for game start
|
|
1540
1584
|
- **Scene Transitions**: Under 2 seconds between scenes
|
|
1541
1585
|
- **Asset Streaming**: Background loading for upcoming content
|