I sat down tonight and in about three hours or so cranked out the first vestiges of something that kind of maybe resembles Breakout, only using graphics that are possibly worse than anything ever shown on Atari 2600 because well, I made them.
I should also point out: I used some sounds from the Spacewar demo in XNA Game Studio 2.0. Those sound AWESOME.
This app is built with a model in a separate assembly; the model portion of the project contains the mathematics, collision detection, and all the game objects on the screen. We’ve got tiles, a ball, and a paddle. I should also point out that there’s a game board (that’s the big black empty space on the screen).
The XNA game application, then, instantiates a GameBoard (that’s the containing class that owns all of the rest of the objects) and then instantiates a GameBoardPresenter. GameBoardPresenter is part of the game application itself, and it owns a copy of the GameBoard because it’s intimately tied to its inner workings.
To keep things relatively efficient, the GameBoard class exposes all of its object lists as properties that return the lists. This way, object references aren’t duplicated (except for the references to the Lists), and we’re not wasting unnecessary memory and copy operations. (If you’re not clear what I mean, here are the properties:)
Since the balls are the only pieces of the game that move, each call to Update() on the GameBoard instance iterates through each Ball object, moving it accordingly and handling any collisions. When a collision is detected, it fires an event corresponding to the type of collision, which is consumed by the GameBoardPresenter.
One other advantage of separating out the presentation and the actual game logic is that I can scale the graphics size to anything I want; for instance, the video above was recorded and 960×720, but I was also able to run it at 1920×1200 without any apparent differences in visualization. The internal game units actually default to a game board size of 4800×4800, and scaling is simply done within the GameBoardPresenter’s Draw() method:
The scale is calculated when the backbuffer is sized.
Source code for this isn’t quite ready yet; there are some things that I want to refactor (for instance, I want the Model part to define input "actions" and that View/Presenter part to keymap inputs to actions).