Breakout began as an internship project to deepen my familiarity with the Godot engine. As development progressed, I expanded it with backend-focused features aligned with my web development experience, including JSON-based data management, a lightweight server, and client–server communication. This allowed me to prototype and evaluate backend workflows—such as request handling, data serialization, and state synchronization—within an interactive game environment
This project is an extended implementation of a classic Breakout game developed during my internship. A key gameplay mechanic involves color-based brick destruction: bricks can only be broken when their color matches that of the ball. This behavior is implemented by dynamically modifying the modulate property of both the ball and the bricks, while collision outcomes are handled through a signal-based event system. The game includes a designated death zone positioned below the paddle, which detects when the ball falls out of bounds and triggers a life-loss event. Player lives are managed centrally, and the game transitions to a game-over state after three lost lives. Both life management and scoring systems are implemented using custom signals, defined within the main game loop and emitted from relevant gameplay scripts to ensure loose coupling and modularity. An additional feature of the project is a dedicated score management system that supports both local and web-based persistence. Players can enter a username, and their name–score pair is stored either locally on the user’s machine or remotely when exported to the web. This approach ensures consistent functionality across platforms while demonstrating client–server interaction and persistent data handling.
I implemented a basic client-server setup where the backend was written in Rust and the client was built using Godot. The client communicates with the server through HTTP requests to send and retrieve the highscores and the name of the player, while the server handles these requests and return structured responses. This helped me understand how client-server communication works in practice and how backend services can be integrated with a frontend application.
The game uses an event-driven architecture where different parts of the system communicate through signals. For example, when the ball hits a brick, a signal is emitted to update the score or remove the brick, and when the player loses a life, a signal triggers the life count update and potentially the game-over state. This approach allowed me to keep the code modular and organized, making it easier to manage multiple systems that interact without being tightly connected.
In this project, I applied the principle of separation of concerns by keeping different parts of the game logic separate. For example, collision detection, score handling, life management, and UI updates were all managed in their own scripts, while the main game loop coordinated the overall flow. This made the code easier to read, maintain, and extend, and taught me how to structure applications in a modular way—an approach that directly applies to web development.
During this project, I learned how to design clear and maintainable communication between different parts of an application, focusing on modularity and readability through event-driven patterns. I also gained my first hands-on experience integrating a client application with a backend service, including sending and receiving data via HTTP, working with JSON serialization, and handling server responses. The backend component was implemented in Rust using the Actix-Web framework, which introduced me to core backend concepts such as API endpoints and data persistence. Although the project was game-oriented, it reinforced my strong interest in web development—particularly backend and full-stack engineering—and helped me understand how these principles apply across different types of software systems.