For this project, I rebuilt Space Invaders entirely from scratch, using only the provided art assets. Every part of the game—from the game loop to collision handling and rendering—was developed by me, leveraging a range of object-oriented design patterns. The focus wasn’t just on creating a playable game but on designing a system that was clean, modular, and adaptable. This approach allowed me to deeply understand how different patterns can solve specific problems and improve overall architecture.
Proxy Pattern: Optimized memory by using lightweight proxies to manage position data while delegating heavy sprite logic to shared resources. This approach streamlined animations and reduced redundancy.
Factory Pattern: Centralized object creation to ensure consistency and flexibility when instantiating game elements like aliens and shield bricks.
Observer Pattern: Decoupled event handling from the game logic, enabling modular and extensible systems for events like collisions.
Command Pattern: Organized game actions—like animations, sound effects, and object destruction—into encapsulated commands for better timing and easier debugging.
Composite Pattern: Built hierarchical structures, such as the enemy grid, to enable unified updates and rendering while maintaining flexibility.
State and Strategy Patterns: Managed player behaviors and enemy bomb patterns through cleanly separated logic, avoiding bloated conditional code.
Rebuilding Space Invaders from the ground up was an interesting experience. This wasn’t just about implementing a game; it was about learning how to structure code in ways that are efficient, scalable, and maintainable. Before this project, I often approached programming as solving isolated problems. Now, I think about systems as interconnected pieces that need to work seamlessly together.
This project showed me the importance of thoughtful architecture. By applying design patterns, I could see how small, intentional design choices had far-reaching impacts on the system's flexibility and performance. It also taught me to think ahead—anticipating where the code might need to expand or adapt in the future,