My goal is to implement a (very simple) strategy game.
For the moment, I'll start with the map and two characters (I want the terrain to affect them differently) to experiment with pathfinding
The problem is that I have very little or no experience in object oriented design. I've used C++ classes before, but it was pretty straightforward: for instance, a class Graph implemented using an array of sets, with a method AStar. I didn't have in mind the concept of "several players".
I've thought of the following elements/classes: Game, Map and Character. Eventually a Pathfinder class.
First question: the position of a character is something the game should know? The map? or each character?
( I think the game should )
Second question: where would it be a good choice for a "findPath" method?
The Game?
Should a pathfinding algorithm be a method of Map? Something like map.findPath(character, srcpos, dstpos)
In the Character class? It makes more sense to do character1.findPath(map, srcpos, dstpos)
If I added a Pathfinder class, it would have to build its own representation of the map in order to determine the shortest path. And before doing that, it would have "to ask" the map how the terrain affects each player.
( I prefer the latter )
It seems the construction of an auxiliary structure (and asking the map) to apply, let's say, A* is something that I can't avoid.
Making things object-oriented is not a goal, it's a tool to be used when it makes sense. C++ is a language with lots of functionality that you can easily drown yourself with, so my advice is to keep things simple and easy.
This can mean keeping data and logic tightly together sometimes, or separating it completely other times.
First question: My initial reaction is that the character should know its position. But how you represent it with data depends on how you intend to use it, so both the game, the character and potentially also the map needs to know where the character is.
Second question: It depends on what the Map class is. Is it an object representing the map itself with necessary functionality exposed to the rest of your program, or is it a toolbox of functions that works on a simple data representation of the map?
If the Map class represents the map, it should have the necessary functionality exposed for a Pathfinder class to work on it (the pathfinding algorithm will need to have some additional data derived from the map, maybe temporary, maybe persistent).
If the Map class does not represent the map, you can put the pathfinding functionality in it. I think it would belong there in that case. If the pathfinding code causes the Map class to get too big, you should separate it into its own class anyway.
First Question: The position of the character should be a part of character itself (makes sense this way) for me.
Second Question: Finding a path logically cannot be a part of Map. Then you would be violating one of OOP principles i.e. Single Responsibility.
According to me you should create the PathFinder class. You can design it in this way
class PathFinder{
PathFinderAlgorithm algorithm;
//other required values according to your design
Path findPath(){
algorithm.apply();
}
//other required methods according to your design
}
PathFinderAlgorithm is an interface.
Using this you can also change the algorithm that you are using to find the path. Like if you in future need to find the longest path, all you have to do is create another class which will find the longest path and replace it in the PathFinder class.
Related
I'm currently in a project of making a video game, to be specific, a turn-based strategy in OCAML. It's a coursework about functional programming, so the more functional programming the better, but if I can't do it with functional programming, I can use OOP if REALLY needed.
Here's the model of my game at the basic level :
In the following, when I say type, I actually mean instance/type/module, i.e. I don't know how I should implement it, but I know that they should be at least packaged into different sections.
There will be a Main type. It's role is to switch between menus, settings, and the actual game.
The Game type will run the game. In context, it will iterate over each Faction of the game, and iterate, within the Faction, each Unit that the faction has. Each Unit will have a specific behaviour attached to it.
Every game object ( that can be rendered in a 2D screen ) will have the GameObject type. Ideally, I can attach a bunch of video/audio/etc. renderer and I will be able to know their position on the map.
Grid will be an array of array composed of Tile. Grid has a global view over the game, from Grid, I can, for example, know the location of every GameObject in the Game
Tile is a tile on the grid. Eventually, I would like them to have special features, for example, a terrain type.
Unit ( not to be confused with unit type from OCAML ) is an entity controlled by a Faction. It has many attributes, such as health, mana, strength etc... and can do certain actions depending on who they are.
Faction represents either the player or one of the opponents. Some bonus apply depending on the faction. e.g. a faction could have greater health, but lower strength and vice-versa.
Action is a type that represents an action. It has a source and a destination attributes. It can represent, any type of action, from self healing to an AOE spell. It has access to Game so that it can be free to do whatever it pleases within the Game.
My goal is to make a game model that I can improve on progressively. For instance, I would like to make subclasses of unit, those who can attack from afar, and those who can only attack in melee etc.
If this was a OOP project, it would be pretty straightforward, albeit inefficient if I understood the previous comments. As you can see, my way of thinking is biased towards OOP because I haven't done any project of this scale without OOP. My goal here is to make it in Functional Programming.
I require your advice on how to implement what I described, or part of it so I can figure out the rest on my own.
Thank you.
EDIT: Edited the whole question
EDIT2: Some spelling and backticks
Your question is filled with imperative and OOP idioms: iterate, array, object, subclasses, ... So your mind set seems to be already made up.
Not surprising as GUIs and games are the most obvious examples for OOP. They have state and mutate over time and thrive on inheritance. And while you can do all those things functionally, with functors or with with first class modules I don't think it is worth it.
Luckily ocaml lends itself well to this. Records and classes can have mutable fields and ocamls classes can model your objects and inheritance nicely. And you still can use all the functional concepts of ocaml alongside the classes. It mixes well.
For some homework, we have to devise an example (with classes) where both the Strategy and Template Method design patterns come together to complement each other and make them more customizable as a result. Or "use template method to provide more customizability to handle a variety of strategies" as it says.
After much reading and initial confusion, I came up with the idea of having two animals as classes, Dog and Snake and have them both use interfaces to implement a specific function, moving (so a dog might walk and a snake would slither). I thought this to be the Strategy pattern portion, as they're each separately implementing their own move functionality.
In order to incorporate the Template Method pattern into this, I thought I'd make it so the class it's implementing is then subclassed further for customizability, which seems to go with the question. So I thought I'd have Mover as the class and have it subclassed down into Walk and Slither. But this confused me as would each animal implement the superclass Mover, or one of the subclasses? And is the superclass Abstract, while the subclasses are Interfaces? Or are they all interfaces?
Does my example make sense?
As Per my Understanding your example does't fit into the Strategy and Template, the Scenario best fits into Abstract Factory and May be Prototype (Depends upon full requirement).
The basic difference between strategy and Template is Inheritance v/s Delegation.
If you are Searching for Strategy and template Example i would suggest you to go with some game application where the Full game can fit into template function like end of game, start the game,Winner of the game looser of the game and the Rules to play the can be fitted into Strategy like when to move, what to do with some moves.
No. The main reason is because Strategy applies when you need to have different ways to do the same thing, e.g. a Layout Manager. In your example, Snakes have one way of moving, likewise Dog.
Frankly, I don't see those patterns as going together so well, not sure what the assignment is after. Template Method is great when things are done in a particular way, and variants merely implement steps of the process differently.
Probably you should think of a process where one of the steps could have a Strategy plugged in.
Your example is OK if you would somehow manage to get appropriate names to BeginMove and EndMove methods in MoverStrategy.
Here:
GetMoveStrategy - FactoryMethod responsible for declaring interface for creation appropriate strategy
MoverStrategy - Strategy
Move - Template method with one placeholder DoMove which Concrete Strategy must define
C++ Should I make one abstract class with many derived classes or just one general class?
Classic example is the abstract Shape object with derived classes Square and Triangle that hold specific geometry and functions.
Why don't I just make one general class called Shape that includes a more general geometry data member to hold a dynamic amount of points that could either be a square or a triangle?
Functions could take some parameter indicating what type of shape it was e.g. Shape.process("square"); instead of something like Square.process();
Is my question clear? Is this purely a stylistic choice?
You should avoid creating "god" classes that do a bunch of stuff. What if you will have to implement a lot of shapes? A class should have only one responsibility, should be open for extension and closed for modifications. Check the class design principles or the SOLID principles of design. You should avoid complicated design and big classes that have multiple responsibilities just because at a moment it will become a pain to maintain them or add extra functionality. Unit testing will also be something more easy to do with a good design.
You cannot get an answer to this type of question in general. It is going to depend on the situation and requirements for whatever problem you are attempting to solve. In some cases, it will make sense to have an interface with derived classes. In others, it will make sense to have a generalized class. Without knowing the requirements for the problem, you will get no real answer.
It really depends on what you need the Shape for. For example if you are just drawing it, then yeah a general Shape class that just draws line from point to point would be perfect (for polygons anyway). But what if you wanted to calculate the area. It would probably be easier to have a Square and Triangle class where the getArea() function uses the appropriate area formula. There is no hard and fast rule it simply depends on what you need them for
I've been tasked with writing an essay extolling the virtues of object oriented programming and creating an accompanying game to demonstrate them.
My initial idea is to find a tutorial for a simple game written in a programming language which does not follow the OOP paradigm (or written in an OOP language but not in an OOP way) and recreate it in an OOP way using either C# or Java (haven't yet decided). This would then allow me to make concrete comparisons between the two.
The game doesn't have to be anything complex; Tetris, Pong, etc. that sort of thing. The problem I've had so far is finding a suitable tutorial, any suggestions?
Let's say that you found source code for a game not in OOP. There are some OOP virtues that you can point out in your essay:
Organization.
Since a game has many tasks, it is a good idea to assign a responsibility to one class. This means write one class that keeps score, one class that does file access (reading and writing game state, for example), classes to represent your characters, etc. Otherwise, you will have one huge text file with thousands of lines of code. It would be a nightmare to even look at it, let alone find what you need and fix it.
Encapsulation.
This is grouping together properties and functions for better organization. We used to have a different array to store each property - (example) one array for aircraft names, one array for firepower, another array for top speed, etc. That sucks because you need to make sure that the same index across all those arrays actually describes the correct aircraft. It's better to create an Aircraft object and give it those property names. You'll then have one array that holds aircraft - no need to keep track of too many arrays.
Reusability.
As you write more games (and even other apps), you will come across the need to reuse classes. For example, you would use the same Card class in your Solitaire game as any card game you'll write in the future.
Polymorphism/Inheritance.
Say that you want to display each character - both heroes and villains in some sort of a grid. You will want both Hero and Villain to inherit Character. Character will have common properties and even a[n abstract] Display() function. You would then write the custom Display() function for Character and Villain (that access class-specific data for drawing). You then create an array of Character objects, and you may store either a Villain or Hero in each slot. When the game goes through that list to display, each item.Display() call will automatically pick the correct Display() function based on the Character's actual type. Try to do this without OOP and you'll end up with a long if-else (and probably even nested) statement and all drawing routines in one place.
That's just from the type of my head from experience in general programming that you can definitely apply in game programming. There are probably more OOP aspects than mentioned, so you may want to research. Best of everything for your essay!
You can try grabbing a (simple) TI-Basic game from TICalc, Omnimaga, or most other calculator programming websites and try to understand its code.
Try a BASIC game from this site:
http://www.atariarchives.org/basicgames/
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
You are writing a Tetris program in Java. How would you set up your class design with regards to the following aspects?
Piece class: Have one Piece class, with an internal array which determines the shape of the piece, versus having seven Piece classes, one for each of the pieces. They are all subclasses of one generic Piece class.
Piece class representation: Have an array of 4 instances of Block, representing one square of a piece, and each Block contains its location on the Board (in graphical coordinates) vs. having a 4x4 array where null means there is no block there, and location is determined by the shape of the array.
Location: Each Block in the Piece array or on the Board array stores its location vs. the Piece and the Board know the locations of the Blocks that comprise them.
Generating a Piece: Have a static method of the Piece class getRandomPiece, or have a PieceFactory which you make one instance of that has the genRandomPiece method on the instance.
Manipulating the current piece: Use the Proxy pattern, so that everything that needs access to it just uses the proxy, or have a getCurrentPiece method on the Board class and call that any time you want to do something with the current piece.
This is not homework. I'm just at odds with what the intro CS course teaches at my college and I want to see what people in general believe. What would be thought of as "good" OOP design? Ignore the fact that it's for an intro course - how would you do it?
Firstly, I wouldn't subclass the Piece class because it's unnecessary. The Piece class should be capable of describing any shape without using inheritance. IMHO, this isn't what inheritance was made for and it just complicates things.
Secondly, I wouldn't store the x/y coordinates in the Block objects because it allows two blocks to exist in the same place. The Piece classes would keep a grid (i.e. 2D array) holding the block objects. The x/y coordinates would be the indexes of the 2D array.
As for the static method vs factory object for getting a random piece, I'd go with the factory object for the simple fact that the factory object can be mocked for testing.
I would treat the board as one large Piece object. The Board class would keep the large Piece object as a member variable, and might keep other Piece objects such as the current piece being played, and the next piece to be played. This is done using composition to avoid inheritance.
All these classes and stuff... it might be making the problem way too abstract for what it really is. Many different ways to represent tetris pieces (stackoverflow.com/questions/233850/…) and many different ways to manipulate them. If it's for an intro course I wouldn't worry about OOP. Just my opinion, not a real answer to your question.
Having said that, one could suffice with simply a Board and Piece class.
Board class: Encapsulates a simple 2d array of rectangles. Properties like currentpiece, nextpiece. Routines like draw(), fullrows(), drop(), etc.. which manipulate the current piece and the filled in board squares.
Piece class: Encapsulates an array of unsigned 16 bit numbers encoding the pieces in their various rotations. You would track color, current location, and rotation. Perhaps one routine, rotate() would be necessary.
The rest, would be, depending on the environment, handling keyboard events etc...
I've found that placing too much emphasis on design tends to make people forget that what they really need to do is to get something running. I'm not saying don't design, I'm saying that more often than not, there is more value in getting something going, giving you traction and motivation to keep going.
I would say, to the class, you have X hours to make a design for a tetris game. Then they would need to turn in that design. Then I would say, you have X days, to get something running based on the design you turned in or even not based on the design.
One Piece interface, with seven classes that implement that interface for the individual pieces (which would also enable the OOP course to discuss interfaces) (EDIT: One Piece class. See comments)
I would have a BlockGrid class that can be used for any map of blocks - both the board, and the individual pieces. BlockGrid should have methods to detect intersections - for example, boolean intersects(Block block2, Point location) - as well as to rotate a grid (interesting discussion point for the course: If the Board doesn't need to rotate, should a rotate() method be in BlockGrid?). For a Piece, BlockGrid would represent be a 4x4 grid.
I would create a PieceFactory with a method getRandomShape() to get an instance of one of the seven shapes
For manipulating the piece, I'd get into a Model-View-Controller architecture. The Model is the Piece. The Controller is perhaps a PieceController, and would also allow or disallow legal/illegal moves. The thing that would show the Piece on the screen is a PieceView (hrm, or is it a BlockGridView that can show Piece.getBlockGrid()? Another discussion point!)
There are multiple legitimate ways to architect this. It would benefit the course to have discussions on the pro's and con's of different OOP principles applied to the problem. In fact, it might be interesting to compare and contrast this with a non-OOP implementation that just uses arrays to represent the board and pieces.
EDIT: Claudiu helped me realize that the BlockGrid would sufficiently differentiate pieces, so there is no need for a Piece interface with multiple subclasses; rather, an instance of a Piece class could differ from other instances based on its BlockGrid.
Piece class: I think that a single class for all the pieces is sufficient. The class functions shoudl be general enough to work for any piece, so there is no need to subclass.
Piece Class Representation: I believe that a 4x4 array is probably a better way as you will then find it much easier to rotate the piece.
Location: Location should definitely be stored by the board, not the piece as otherwise you would have to go through the entire set of blocks to ensure that no two blocks are in the same position.
Generating a Piece: Honestly for this one I do not feel that it will make too much of a difference. Having said that, I would prefer a static function as there is really not so much to this function that it warrants its own class.
Manipulating the Current Piece: I would just implement a getCurrent function as I feel that there is no need to overcomplicate the problem by adding in an extra class to serve as a proxy.
This is how I would do it, but there are many different ways, and at the end of the day, the thing to focus on is simply getting the program running.