Pacman game class design - model-view-controller

I have to write a multiplayer pacman game in Java for a university assignment and I'm after some feedback for my design so far.
So I'm trying to go down an MVC style and this is what I've sketched out.
I've never designed anything using MVC, so my knowledge is really only from the pragmatic programmer and a short lecture so it's quite possible I'll have misunderstood or misinterpreted it slightly.
Also, most of the tutorials I've seen for designing simple games don't mention MVC at all so is this a case where MVC is not a good pattern to use?
My idea so far is that the Game State class would be the main source of data storage as it were, and would use a 2d array to store the state of the game, where the ghosts are, where pacman is etc.
The Game class would be the main controller class that would contain the main game loop and control all the interactions between the data (game state) and the view (probably a GUI representation - I just added text based really as an example).
After I've got the game working I'm going to have to split it out into client/server. It seems to me, by using this model, that it wouldn't be too hard to keep most of the the data and processing on the server and have the clients interact with the controller and draw their own views. I have no idea (yet) how this may effect the performance of the game over a network so I'll have to research into that further once the single player version is done.
Any tips or advice, based on my design so far, would be greatly appreciated - also bearing in mind that it will eventually have to be a multiplayer game.
Cheers,
Adam

On the contrary: MVC is actually a very good thing to use for this type of problem and the Swing framework does a really nice job at supporting it.
You should probably first read up on MVC. Just as an overview, you will be trying to separate how the game is represented internally (the model), from how it is drawn (the view) and how that state is to change (the controller).
First think about everything you need to model the current state of the game. Having an Entity that defines some basic behavior and subclassing it for the PacMan and Ghost like you do is probably a good way to start, but you'll probably want to call your Map a GameBoard or the like (giving things the same name as library classes is generally a bad idea: you don't want to confuse it with java.util.Map). To wrap up the model section, you probably want to wrap them all up in one class who 'knows' the entire state of your game. Since this is your GameState class, you probably want to redraw your arrows.
Since determining the view is likely to be fairly easy, you can go there. You can give your GameState a draw(Graphics) method and invoke this from whatever your view is (which you'll decide later). This might in turn delegate do each of your Entities, who might in turn delegate it to a Sprite or Image object that they have. Now your view, who's likely to be a JPanel or the like, can just call draw() using its own Graphics object from within its paintComponent() method.
Now you still need a controller to actually make stuff happen. This is likely to be some object with a KeyListener hooked into the view as well as an InputStream and an OutputStream to handle communication with the other player (it probably also needs to be the one to worry about synchronizing the game state). It also needs to also have a timer so that it can tell the units to update periodically. You do need to decide who makes the decisions on whether the moves are legal: the controller could do it, the GameState could, or it could just give the Entities the information they need and let them do it themselves.
Once you have all of these parts, you can wrap them up in one final class who knows everything and gets it all set up and such. There's a lot more that I'm glossing over and several more decisions that you have to make, but it should get you going.

I agree with James entirely, and would like to add that you might also want to make sure that this 2d array of yours for the game state can handle some edge cases like multiple ghosts occupying a tile, a pacman and ghost in the same tile (depending on how you handle it in your code), the pacman's food dots, etc.
Good planning more often than not makes the best programs, I'm glad to see you have started off with a diagram.

Related

Nested MVC communication patterns

This is entirely a best practices type question, so the language is irrelevant. I understand the basic principles of MVC, and that there are different, subtle flavors of it (i.e. views having a direct reference to models vs. a data delegate off the controller).
My question is around cross MVC communication, when those MVCs are nested. An example of this would be a drawing program (like Paint or something). The Canvas itself could be an MVC, but so could each drawn entity (e.g. Shapes, Text). From a model perspective, it makes sense for the CanvasModel to have a collection of entities, but should the CanvasView and CanvasController have corresponding collections of entity views and controllers respectively?
Also, what's the best/cleanest way to add a new drawn entity? Say the user has the CircleTool active, they click in the Canvas view and start drawing the shape. The CanvasView could fire relevant mouse down/move/up events that the CanvasController could listen to. The controller could then basically proxy those events to the CircleTool (state pattern). On mouse down, the CircleTool would want to create a new Circle. Should the Tool create a new CircleEntityController outright and call something like canvasController.addEntity(circleController)? Where should the responsibility of creating the Circle's model and view then lie?
Sorry if these questions are somewhat nebulous :)
--EDIT--
Here's a pseudo-codish example of what I'm talking about:
CircleTool {
...
onCanvasMouseDown: function(x, y) {
// should this tool/service create the new entity's model, view, and controller?
var model = new CircleModel(x, y);
var view = new CircleView(model);
var controller = new CircleController(model, view);
// should the canvasController's add method take in all 3 components
// and then add them to their respective endpoints?
this.canvasController.addEntity(model, view, controller);
}
...
}
CanvasController {
...
addEntity: function(model, view, controller) {
// this doesn't really feel right...
this.entityControllers.add(controller);
this.model.addEntityModel(model);
this.view.addEntityView(view);
}
...
}
Wow, well I have perhaps a surprising answer to this question: I have a long-standing rant about how MVC is considered this beatific symbol of perfection in programming that no one sees any issues with. A favorite interview question is 'what are some problems, or challenges that you might encounter in MVC?' It's amazing how often the question is greeted with a puzzled, queasy look.
The answer is really quite simple: MVC relies on the notion of multiple consumers having their needs met from a single shared model object. Things really start to go to hell when the various views make different demands. There was an article a few years ago where the authors advanced the notion of Hierarchical MVC. Someone else came on in the comments and told them that what they thought they were inventing already existed: a pattern called Presentation-Abstraction-Controller (PAC). Probably the only place you see this in the pattern literature is in the Buschmann book, sometimes referred to as the Gang of Five, or POSA (Pattern-Oriented Software Architecture). Interestingly, whenever I explain PAC, I use a paint program as the perfect example.
The main difference is that in PAC, the presentation elements tend to have their own models, that's the A of the PAC: for each component, you don't have to, but can have an abstraction. Per some of the other responses here, then what happens is you have a coordinating controller, in this case, that would rule over the canvas. Let's say we want to add a small view to the side of the canvas that shows the count of various shapes (e.g. Squares 3, Circles 5, etc.). That controller would register with the coordinating controller to listen on a two events: elementAdded and elementRemoved. As it received each notification, it would simply update a map it had in its own Abstraction. Imagine how absurd it would be to alter a shared model that a bunch of components are using to add support for such a thing. Furthermore, the person who did the ShapesSummary component didn't have to learn about anything, but the event protocols, and of course all its interactions with collaborators are immutable.
The hierarchical part is that there can be layers of controllers in PAC: for instance, the coordinating one at the Canvas level would not know about any of the various components with specialized behaviors. We might make a shape that can contain other things, which would need logic for accepting drags, etc. That component would have its own Abstraction and Controller, and that Controller would coordinate its activities with the CanvasController, etc. It might even become necessary at some point for it to communicate with its contained components.
Here's the POSA Book.
There are many different ways to attack this. I don't disagree with the other answers posted here.
However, one way that I've done this is by using the observer pattern. And let me explain why.
The observer pattern is necessary here because these drawing tools are nothing without the canvas. So, if you have no canvas, you can't (or shouldn't) invoke the circle tool. So instead, my canvas has a host of observers on it.
Each tool that can be used on the canvas is added as an observable event. Then, when an event is fired - like "begin draw" - the tool is sent as the context (in this case 'circle'). From there, the actions of the circle tool execute.
Another way to imagine this is that each layer has its own service, model, and view. The controller really is at the exterior level and associated with the canvas. So, services are only called by other services or by a controller. There are no circle tool controllers - so only another service (in our case the observed event) can call it. That service is responsible for aggregating the data, building the model, and supplying a view.
The RenderingService (for lack of better name - the thing that manages the interaction of shapes) would instantiate new Circle domain object and informs about it (either directly or when view is requesting new data) the view.
It seems that you are still in a habit of dumping all your application logic (interaction between storage abstractions and domain objects) in the presentation layer (in your case - the controllers).
P.S. I am assuming that you are not talking about HMVC.
If I were you I would opt for Composite pattern when working with shapes. Regardless of whether you have circles, squares, rectangles, triangles, letters, etc, I would treat everything as a shape. Some shapes can be simple shapes like lines, other shapes can be more complex composite shapes like graphs, pie charts, etc. A good idea would be to define a base class that has a reference to basic shapes and to advanced (complex) shapes. Both basic shapes and advanced shapes are the same type of object, its just that advanced shapes can have children that help define this complex object.
By following this logic, you can use the logic where each shape draws itself and each shape knows its location, and based on that you would apply certain logic and algorithm to ask which shape was clicked and each shape could respond to your event.
According to the GoF book:
Intent
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
Motivation
Graphics applications like drawing editors and schematic capture systems let users build complex diagrams out of simple components. The user can group components to form larger components. [...]
The key to composite pattern is an abstract class that represents both primitives and their containers. For the graphics system, this class is Graphics. Graphic declares operations like Draw that are specific to graphical objects. It also declares operations that all composite objects share, such as operations for accessing and managing its children.
Now, back to your problem. One of the base functions, as previously mentioned, is a Draw method. This method could be implemented as an abstract method in the base class with a following signature:
public virtual void Draw(YourDrawingCanvas canvas);
Each shape would implement it's own version of Draw. The argument that you pass them is a reference to the drawing canvas where each shape will draw itself. Each shape could store a reference of itself in its internal structure and it can be used to compare mouse click location with these coordinates to inform you which shape was clicked.
From my point of view using nested MVC components is kind of an overkill here: At each point in time the model contains multiple elements (different circles, squares etc., which may be nested constructs using the Composite pattern, as mentioned in another answer). However, the canvas that displays the elements is just a single view!
(And corresponding to the single view there would only a single controller be needed.)
One case of having several views could be a list of elements (which is shown, e.g., next to the canvas) - then you could implement the canvas and the element list as two distinct views on one and the same model.
Regarding the question of how to "best" implement adding an element: I would consider the following sequence of events:
The view notifies its listeners that a new circle element has been drawn (with the middle point and an initial radius as parameters, for example).
The controller is registered as listener to the view, so the controller's "draw-circle(point, radius)" listener method is invoked.
The controller creates a new circle instance in the model (either directly, or via a factory class which is part of the model - I think there are lots of different ways of implementing the creation of new elements). The controller is "in control" (literally), so I believe that it's the controllers responsibility to instantiate a new element (or at least trigger the instantiation).
In the model, some kind of "add element" method is invoked by the previous step.
The model raises a "new element created" notification to all of its listeners (probably passing on a reference to the newly created element).
The canvas is registered as listener to the model, so the canvas' "new element created (element)" listener method is invoked.
As response to the latter notification, the canvas draws the circle (on itself).
This is just an idea, but consider if the mediator pattern is applicable.
From the gang of four:
Intent
Define an object that encapsulates how a set of objects interact.
Mediator promotes loose coupling by keeping objects from referring to
each other explicitly, and it lets you vary their interaction
independently.
Applicability
Use the Mediator pattern when
a set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to
understand.
reusing an object is difficult because it refers to and communicates with many other objects.
a behavior that's distributed between several classes should be customizable without a lot of subclassing.
Consequences
The Mediator pattern has the following benefits and drawbacks:
It limits subclassing. A mediator localizes behavior that otherwise would be distributed among several objects. Changing this
behavior requires subclassing Mediator only; Colleague classes can be
reused as is.
It decouples colleagues. A mediator promotes loose coupling between colleagues. You can vary and reuse Colleague and Mediator classes independently.
It simplifies object protocols. A mediator replaces many-to-many interactions with one-to-many interactions between the mediator and
its colleagues. One-to-many relationships are easier to understand,
maintain, and extend.
It abstracts how objects cooperate. Making mediation an independent concept and encapsulating it in an object lets you focus
on how objects interact apart from their individual behavior. That can
help clarify how objects interact in a system.
It centralizes control. The Mediator pattern trades complexity of interaction for complexity in the mediator. Because a mediator
encapsulates protocols, it can become more complex than any individual
colleague. This can make the mediator itself a monolith that's hard to
maintain.
I am assuming MSPaint-like behavior, where the active tool creates a vector graphic glyph that the user can manipulate until he's satisfied. When the user is satisfied, the glyph gets written to the image, which is a raster of pixels.
When the Circle Tool gets selected, I'd have the CanvasController deselect the previously active tool's MVC trio (if another tool was active) and create a new CircleToolController, CircleModel and CircleView. The previously active glyph becomes final and draws itself to the CanvasModel.
The CanvasView will need to be passed a reference to the CircleView so it can draw the CanvasModel's pixels to the screen before the Circle gets drawn. The actual drawing of the circle to the screen, I'd delegate to the CircleView.
The CircleView will therefore need to know and observe other, more general, model classes besides the CircleModel, I'm thinking of a color selection / palette model, and a model for fill style and line thickness, etc. These other models live as long as the application does and have their own View and Controller. They are quite separate of the rest of the application after all.
As a sidenote: You could actually split off the drawing of the CanvasModel (the raster of pixel colors) by the CanvasView from the coordination of the updating of the entire screen. Have a higher level PaintView which knows the CanvasView and the active GlyphView (for example the CircleView) coordinate the drawing between the CanvasView and the GlyphView.

Xcode app design - loop easier?

I'm pretty new to programming and want some advice on the basic app structure so forgive me if this is pretty obvious.
The main part of the app is a series of 20 pairs of views which the users moves through sequentially (1a,1b,2a,2b,3a etc). Each a view and b view have the same layout as other a/b's but have different image, audio and text.
I could set out all 40 views in storyboard in one long line but that seems like I'm duplicating a lot of work (as well as creating a larger size app) although it would be conceptually very simple (and more stable?)
Alternatively I could just have two views (a and b) with all the content and some sort of counter so that Xcode would know which content to serve up depending on where the user is in the sequence. What would be the easiest way to implement this? I'm afraid however that this could also get unwieldy and perhaps keeping it simple really is the way to go.
Any advice gratefully received.
Many thanks
Design is totally dependent on complexity of screens not on the number of screen. If Screen won't have much variation then you can go for second approach having only 2 views and conditionally loading the data.
Alternatively if you want to go with approach first you won't need to duplicate all the steps. You can programatically create two super class which contains all the functionalities, and the part which varries for that you can create separate class(Inheritance concept). This will make the thing easier, you can reuse the code as well as increase the maintainability of app.

Android Activity.setContentView(), smooth transition?

I'm developing my first Android game and I'm having a bit of difficulty making the UI as smooth as I would like. I've spent a couple of hours googling around with no luck, I'm probably just searching for the wrong thing.
I have two different XML layout resources where each layout contains just one SurfaceView subclass. When I call activity.setContentView(R.layout.second_layout) to transition from the first layout to the second layout there is a noticeable period of time where a black screen (with a small white bar along the top) is displayed in between the two views.
I've tried various things such as; constructing the second view manually at runtime (i.e not using a layout XML file), calling activity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out) after activity.setContentView(R.layout.second_layout) and attempting to render to the canvas before the view has loaded (turns out the canvas is unavailable).
I don't see other games (or apps) having this issue so I presume there is a reasonably simple solution.
If you need some more information about my particular situation in order to help out then please let me know what information is missing. Any help would be largely appreciated.
Update: My answer below was written in 2010. Since then Fragments have become the norm, particularly since Fragment nesting was made possible and the support library allows this functionality to be used in a backwards compatible fashion. As such, instead of transitioning to a new Activity to perform a new "user task", you can use the one Activity and push and pop fragments within that Activity's view hierarchy. Animations can also be performed as a part of a fragment transaction (e.g. Fragment transaction animation: slide in and slide out).
This became pretty apparent not long after posting this question, however I thought I should come back here and make it clear to everyone else.
Activities are positively the way to go when developing for Android. Don't be put off by the fact that a transition may seem too minor for a separate Activity, the very foundation of Android is built around the idea of an Activity.

Separated GUI and game logic class hierarchy?

Im developing a game on Java, and wanted to keep my code separated in packages for the hud/gui and the game logic so that code can be reused in some other project, and where objects to be drawn call methods from another class or classes (maybe a "rendering context" like a group of classes just made for the drawing or something like that), the problem is that i can't find the best way to achieve this, because I've researched the web (also this forum) and the design patterns but despite some looked interesting (like Model-View-Controller), I couldn't find something that suits me, neither the common approach to solve this problem.
I've been told to make the objects to implement some drawable kind interface, and in another class called by this objects, some object which implements drawable and inherits from canvas, for example, so that if i would want later to change the objects drawing or displaying methods for another one better, for example from awt to swing, to be able just rewritting those classes and dont need to worry about my objects code,
any help would be greatly appreciated, thanks in advance!
What I do is typically along the lines of:
Create your game objects completely independent of all things visual. I'm going to use chess as an example. Each chess piece inherits a "GamePiece" interface and knows it's valid moves, what "color" it is (not visual color, but what "side" it's on), etc. But these pieces do not have any code related to drawing themselves. None. Basically pretend like you're playing a game inside the computer and never need to draw it. Design your whole game this way. You'd need a GameDirector that manages the various pieces, the GameBoard, and abstract Players. But still, no visual representation. There's a lot of leeway in exactly how you design your class hierarchy but leave the visuals out of it.
You communicate state changes by raising events, this is key. So when a player moves, an event is raised. When the GameDirector detects checkmate, an event is raised, etc.
Then you have a GameRender class that contains a GameDirector. It listens for these events and updates the visual scene accordingly (whether it's a simple 2D thing or complex 3D animation). This class can optionally have sub-components that are responsible for rendering sub-components of the game but that's not strictly necessary.

How are the classes in the Sketch example AppKit application separated into Models/Views/Controllers?

I am a little confused as to the definition of classes as Models or Views in the Sketch example AppKit application (found at /Developer/Examples/AppKit/Sketch). The classes SKTRectangle, SKTCircle etc. are considered Model classes but they have drawing code.
I am under the impression that Models should be free of any view/drawing code.
Can someone clarify this?
Thanks.
The developer of Sketch outlines his/her rationale a bit in the ReadMe file:
Model-View-Controller Design
The Model layer of Sketch is mainly the SKTGraphic class and its subclasses. A Sketch Document is made up of a list of SKTGraphics. SKTGraphics are mainly data-bearing classes. Each graphic keeps all the information required to represent whatever kind of graphic it is. The SKTGraphic class defines a set of primitive methods for modifying a graphic and some of the subclasses add new primitives of their own. The SKTGraphic class also defines some extended methods for modifying a graphic which are implemented in terms of the primitives.
The SKTGraphic class defines a set of methods that allow it to draw itself. While this may not strictly seem like it should be part of the model, keep in mind that what we are modelling is a collection of visual objects. Even though a SKTGraphic knows how to render itself within a view, it is not a view itself.
I don't know if that is a satisfying answer for you or not. My personal experience with MVC is that while separation of model, view and controller is a "good thing" oftentimes in practice the lines between layers become blurred. I think compromises of design are frequently made for convenience.
For Sketch in particular, it makes sense to me that the model knows how to draw itself inside a view. The alternative to having each SKTGraphic subclass knowing how to draw itself would be to have a view class with knowledge of each SKTGraphic subclass and how to render it. In this case, adding a new SKTGraphic subclass would require editing the view class (adding a new clause to an if/else or switch statement, likely). WIth the current design, an SKTGraphic subclass can be added with no changes required to the view classes to get things working.
I'm not aware of the particular example that you're refering to, but here's my guess on the reason for that design:
Perhaps the Models (the SKTRectangle, SKTCircle that you mention) know enough to draw themselves but not enough to actually perform the drawing to the screen. The drawing to the screen is handled by the View, where the View will call the Models to find out how to draw them on the screen.
By taking this approach, the View won't have to know how to draw every single Model that it may encounter -- the View only needs to know how to ask the Model to draw itself on the screen.
I'm thinking that it's a trade-off between the MVC model and the object-oriented programming model -- strictly separating along the line of MVC will mean that the View will become extremely large and not very flexible when it comes to adding support for other Models that need to be displayed. With object-orientated design, we'd want the Models themselves to be able to be able to draw themselves on the screen, and we'd want the View to be able to handle new types of Models through facilities such as interfaces.

Resources