I'm making a game with different types of mobs in it. There is also a list of interfaces, each representing an ability that a mob can have. Let's say I have 100 objects extending the mob class, each one containing a different list of mob-applicable abilities (swing, explode, jump, etc.). All implementing these interfaces would do is to add blank methods to the class. If the usage of the ability is constant between all mobs, how would I make it so the ability is
pre-written so that I wouldn't need to write it again for every mob that implements it?
I do know of default methods, but they are static and don't have access to any of the mob's variables unless I pass "this" as a parameter which is something I don't want to do.
I am also aware that were there to be a solution to the problem using interfaces, those interfaces could only ever be implemented by a mob.
Thanks.
If I understand it correctly, a possible solution is to compose abilities instead of inheriting them.
interface Ability {
void doAbility();
}
class Firebending implements Ability {
private Mob mob;
public Firebending(Mob mob) {
this.mob = mob;
}
void doAbility() {
// mutate mob's state to spit fire, and attack the world
}
} // repeat this for each ability you have, flying, x-ray vision, doing taxes etc
class Mob {
private Ability[] abilities;
public Mob(Ability[] abilities) {
this.abilities = abilities;
}
}
With something like this, you can build different mobs on the fly each with a different set of abilities, suitable for when the mob varieties outnumber the number of abilities. And yes, this would involve designing your Mob class(es) to be flexible to be mutated this way.
Cool question and one I fought back and forth with. It turns out that you probably will end up in a code trap , mostly due to a strictly object oriented design approach. Having written a number of game engines I might propose an alternative thought process.
Image if you had a skeleton that needs a shield and a sword, but can at any time not have a shield, maybe you drop it, or conversely drop the sword (or both). To code this using Object Oriented design only, we would attempt to subclass from the skeleton and extend the class to have the skeleton with sword instance, but what about with shield, or with sword and shield, or both, or neither. To accomplish you could bang on it and force OOP design but as with all things, eventually the game designer will ask you to change the skeleton in some way that will cause a significant code change and you can forget about loosely coupled object sharing (say the skeleton drops the sword and the knight picks it up).
Having dealt with this and understating where you are right now, I'd suggest researching an Entity Component System.
Here the Game assets are split into Entities, Components, and Systems.
Entities: Is a simple list of integers where each integer is a component id. This allows components such as the SwordComponent to be shared across any other component. Think of an entity as a collection of components that a system can use to do some game action.
Components: A component is a simple class that ONLY contains data fields, never implementation. Each component gets a unique ID and the specific fields needed to define the component. Here I find it okay to use OOP to subclass the Component class so I really use a mix of both worlds.
System: Systems are where things get interesting. While entities are just list that combine components, and components are just data and state info, systems act on the component data to make entities work. Here you may pass in an entity and have some game logic act on the data. Systems are where you would put the code that makes each entity tick.
Here is an outline of our skeleton example:
Component[0]: Skeleton Mesh
Component[1]: Idle Animation
Component[2]: Walk Animation
Component[3]: Run Animation
Component[4]: Collision
Component[5]: Sound
Component[6]: Sword
Component[7]: Shield
Component[8]: Clown Suit
Skeleton Entity:
Entity[0] = new int {0,1,2,3,4,5,6,7,8} // Defines all the components above into one character
Possible Systems:
System[0] = Collision system handles polygon collisions, using all entities collision components.
System[1] = Animation system uses idle, walk, and run animation components and can be shared across entities.
System[2] = Render system is used to render the mesh using your render engine.
System[3] = Sound system is used to handle sound start, end, tween...
System[4] = ...
Now if the designer wants the skeleton to be able to sprout wings and fly, I don't worry about changing any previous code, I just create a new WingsComponent, add it to my entities component list, and code the new system to make the skeleton fly. Now I can freely extend my component and system pool without worrying about breaking changes.
Related
I'm trying to create a Entity for a game that uses both the Component and State design patterns. Let me explain.
The Components that make up an Entity will consist of an InputComponent, PhysicsComponent, and a GraphicsComponent (for now). Each Component will their own class to keep the clean nice and decoupled. This way you can implement your own components like for example a PlayerInputComponent to represent player input, and then create an Entity like this -> Entity player = new Entity(input, physics, graphics).
This system alone works really well for decoupling the code that makes up an Entity. It makes the Entity class flexible enough to accept all different types of components allowing for many variations. However, as stated in the question, I also want to use a State design pattern and I can't think of a way to make them coexist nicely.
The State design pattern is going to be used to represent a finite set of states that an Entity can be in. For example, there would be a RunningState, IdleState, JumpingState, etc... These states would be able to process input and update, deciding when to change states, and what state to change to. For example, if the movement keys are pressed in the IdleState, the IdleState would process this and decide to switch to a RunningState. This makes keeping track of animations easy and separates out the logic for changing states into their own class avoiding complex logic statements.
My question is how can I mix both of these patterns so they work well together? I need all Components to be able to access these States because state transitions may occur in the InputComponent or the PhysicsComponent (for right now), and the states also have to be accessible in the GraphicsComponent so I can draw the right frame for the current animation.
What's the best way to setup my Entity class so it can implement both patterns and have them interact with each other without creating a mess in the Entity class. Thanks!
I'm making a 2D game in java using the MVC pattern and after reading and searching my ass off I still haven't found a satisfying answear to how I'm supposed to handle the graphical representation of objects.
Should I divide every object, for example Player into PlayerModel (stored in Model) and PlayerView (stored in View)?
That seems kinda messy becuase then I would have to keep track of which grapical-representation-object, i.e. "ScaryMonsterEnemyView" is connected to which logical-representation-object, "ScaryMonsterEnemyModel". Is this really how I'm supposed to do it according to MVC? If so, where should this connection be stored? In the view?
I know this might be a silly problem to get stuck on, but I want to get as much as possible right from the start. Thanks for helping out :)
If I am not mistaken, you are basically asking how to split up a game into the Model-View-Controller paradigm.
Simply put, the Model is the state of your game. In O-O terms, you can think of the Model as all of the objects in your game.
The Controller is the set of rules that are applied to your game's state (in this case, all of your game objects) in every update cycle. This can be implemented as a method called update() in all of your objects, or it can be a function called in your game loop that systematically goes through all the objects that need updated and, well, updates them. You can also think of the Controller as the game loop itself. It calls everything to update, and then draws it on the screen and repeats, unless some conditions are met, then it tells the program to do something else. In this way, you almost have two nested MVC structures. One controlling the flow of the program through menus and such, and one dedicated to the game itself.
The View is just the graphical representation of your game. This can be as simple as text on a screen, but in your case it is 2D graphics. To implement this, you could have each object also contain their graphical state, either directly, or by encapsulation. The View would do little more than query all of the objects for their graphical state, and then shunt it to the screen. Again, this can be implemented on a per-object basis, such as a method called draw(), or another systematic function to be called directly from the game loop. A common practice is to create an object called 'Sptite' or something similar to hold the graphical information, and have every game object that is drawn have a personal instance. Also note that the View need not be an object unto itself. A mere function called in a game loop will suffice, although it is sometimes necessary to store information that directly effects the View's operation (like window size), in which case the View can be an object. The same goes for the Controller.
Also keep in mind that these divisions can be sectioned up even further to make life simpler. For example: The Controller can be divided up into AI processing, movements updating, and collision checking. The View could be separated into the game object display and the HUD, and the Model can be all the objects + all the state independent of the game objects (like the games settings for resolution, window size, key config and such).
I know this might be a little overkill, and it probably has extra information, but hopefully it answers your question and gives you ideas on where to start.
The Model and View are two collections/categories/domains of objects.
The controller provides a set of interfaces to perform some functions on the model objects. And if required, the view can talk directly to model objects regarding their state information.
Traditionally, The View domain corresponds to GUIs, with concepts such as Buttons, Forms, Windows etc. In a desktop environment.
Your View domain (Or one of them) will correspond to a 3D environment that you will build. (Trees, Houses, Person etc). This includes collision details, and your physics. Both of which require the geometry relating to your 3D environment.
It may be very rare in a game for any of these objects to have to collaborate with an object in another domain. But an example, consider a telephone. The object will exist in your 3D environment, but will also collaborate with another domain which describes "half-calls", "channels", "switches" etc. These objects do not belong in your View domain but in a separate Model domain.
A more relevant example maybe some sort of scoring system, such as RPG stats, which would belong in a Model domain.
I am trying to design the GUI front end of a robot simulator (effectively a simple game). However, I don't know the best way of passing the simulator components (such as Robots and Walls) to the display. I want to hide the non-display oriented information of the components (such as the Robots mass), yet still be able to recognise each component im printing, i.e. when I'm drawing components I want to draw Robots differently that I do Walls (maybe the robot will have a name tag or something).
Here is a picture that will hopefully explain the design:
Maybe there is a useful design pattern that I haven't come across yet...
I think you should design this by interface contract.
I would make your walls, robots and sensors be implementations of various 'things' the UI needs to know about. Only those interfaces should be shared between the UI and your Model.
For example, Robot, Sensor should implement an interface called Printable:
public interface Printable {
Shap getShape();
}
Wall should implement an extended interface PrintableTexture
public interface PrintableTexture extends Printable {
Texture getTexture();
}
You could also create and implement data provider type interfaces for angle, direction, etc.
For example:
public interface RangeProvider {
Range getRange();
}
public interface DirectionProvider {
Direction getDirection();
}
public interface SensorProvider {
Sensor[] getSensors();
}
The main point is that the 'printing' code would then check for what interfaces are implemented by the Printable object (or list of Printable objects) that has been passed to the it and react appropriately.
Looking at your comments, I think that PrintableRobot, PrintableWall, etc is a misunderstanding of the fundamental concept of what an interface is. An interface should be more about 'what something provides or how you can use it' versus a concrete implementation of how this is achieved. By putting Robot, Wall, etc in Printable you are giving an indication of implementation.
This aside, have you considered the Visitor Pattern?? You could have each entity implement the accept part of the visitor pattern and have your printing code be a special implementation that only takes what it needs out of a deeper knowledge of what each entity does.... It's not what I would do, but it may suit you...
Checkout the model-view-controller design pattern. It separates data (robot's speed, size,...), presentation (robot's shape and its paint method) and behavior (increase robot speed).
To answer your question - the simplest way to hide parts of a class's API is to split this class into multiple pieces (model, view, controller) and connect them according to some pattern (MVC, or model-view-presenter, they are many of them).
EDIT: Sorry for that I didn't provide any example. My suggestion is just to split Robot into two classes:
RobotData (contains speed, size,... provides getters/setters, simple java bean object)
RobotUi (provides shape method (using private reference of RobotData) )
The Simulator then contains collection of RobotUi (Simulator is a model) and SimulatorDisplay (=view) iterates through the UI objects when performing paint method. The RobotData will be hidden inside RobotUi.
As a project over summer while I have some downtime from Uni I am going to build a monopoly game. This question is more about the general idea of the problem however, rather than the specific task I'm trying to carry out.
I decided to build this with a bottom up approach, creating just movement around a forty space board and then moving on to interaction with spaces. I realised that I was quite unsure of the best way of proceeding with this and I am torn between two design ideas:
Giving every space its own object, all sub-classes of a Space object so the interaction can be defined by the space object itself. I could do this by implementing different land() methods for each type of space.
Only giving the Properties and Utilities (as each property has unique features) objects and creating methods for dealing with the buying/renting etc in the main class of the program (or Board as I'm calling it). Spaces like go and super tax could be implemented by a small set of conditionals checking to see if player is on a special space.
Option 1 is obviously the OO (and I feel the correct) way of doing things but I'd like to only have to handle user interaction from the programs main class. In other words, I don't want the space objects to be interacting with the player.
Why? Errr. A lot of the coding I've done thus far has had this simplicity but I'm not sure if this is a pipe dream or not for larger projects. Should I really be handling user interaction in an entirely separate class?
As you can see I am quite confused about this situation. Is there some way round this? And, does anyone have any advice on practical OO design that could help in general?
EDIT: Just like to note that I feel I lost a little focus on this question. I am interested in the general methodology of combining OO and any external action(command line, networking, GUI, file management etc) really.
In the end, it is up to you. That is the beauty of OO, in that it is subject to interpretation. There are some patterns that should usually be adhered to, but in general it is your decision how to approach it.
However, you should carefully consider what each actor in the system should know about the rest of it. Should a property really know about the player, his account balance, and the other players? Probably not. A property should know what it costs, how much its rent is, etc.
On the other hand, should the main playing thread be concerned about trivial matters such as paying rent? Probably not. Its main concern should be the state of the game itself, such as dice rolling, whether each player wants to trade or buy or unmortgage/mortgage, things like that.
Think for a moment about the action of landing on a square. Once landed, the player has 3 options:
Buy the property
Ignore the property
Pay rent
Now, which actor in the system knows all the information required to complete that. We have the Game class, which isn't concerned with such tedium. We have the Property, which doesn't really care about the players. But the Player object knows all this information. It keeps a record of what each player owns, and can easily access the proper data.
So, if it were me, I would make a Player.performMove(Die d) method. It has easy access to the accounts. This also allows for the least coupling among classes.
But in the end, it's up to you. I'm sure people have created Monopoly clones in perfect OO, as well as Functional or Procedural languages too. In the end, use what you know and keep refactoring until you're happy with the end design.
I agree option #1 seems better.
As for "user interaction" - it all depends. You could leave some of your code in another class. For example,
// in main class
user.landOn(space);
if (space.containsProperties()) doSomething(); // Option #1 for some user-interaction code
// in User.java
public void landOn(Space s) {
// do some checks
s.land(this);
if (s.containsProperties()) {...} // Option #2
// something else?
}
// in GetMoneySpace.java
#Override
public void land(User u) {
u.awardCash(200);
// Option #3 - no properties so nothing here
}
This is far more OOP-y (and better, in my opinion) than something like
if (space.isCashAwardSpace()) {
user.awardCash(space.getAward());
}
if (user.something()) doSomething(); // Some user-interaction code
I am not entirely sure if I understand it correctly. You have always such choice when designing software. I would personally go for the first choice. One argument is personal experience with small games (Scrabble), which prooved to me that good design matters for smaller projects as well. The point of OOP is that you can think differently about your design and you get some design benefits. For example imagine how hard it will be to add new field, change existing one, reuse behaviour of one field in multiple fields.
Your first approach is the one I'd go for. It encapsulates the behaviour where it's needed. So, you'd have Space subclasses for Utilities, Properties, GotoJail, FreeParking - basically all the different cateogires of spaces. What groups a category is it's common behaviour.
Your properties spaces may themselves have a group object as a member, e.g. to group all the dark blue properties together.
As to interaction with the user, you pass a Board (or better a GameController) instance to each space, so it knows which Game it is part of and can influence the game. The Space can then invoke specific actions on the board, such as, moving a piece, asking the user a question etc. The main point is that there is separation - the user interaction is not happening inside each Space - but the space is allowed to request that some interaction happens, or that a piece is moved. It's up to your GameController to actually do the interaction or move pieces etc. This separation makes it easy to test, and also provide alternative implementations as the need may arise (E.g. different game rules in different editions/countries?)
Go with the first design. You'd have a Property class, and subclass the special properties, overriding the default behavior.
As far as interaction, you could have a Token class, and move an instance of that around the board. You have to give the user some options, but yes, from the responses, you should be calling methods on objects, not putting complex logic in the user events.
Sample classes:
Property
name
price
baseRent
houseCount
hotelCount
mortgaged
getCurrentRent()
RailRoad extends Property
Utility extends Property
Board
properties
User
token
playerName
currentProperty
ownedProperties
buyProperty()
payRentOnProperty()
mortgageProperty()
move()
Option 2 doesn't make much sense, or at least it's not as clear to me as option 1. With option 1 you don't need to handle user interaction inside your space object. You could have in your main class or a separate class dedicated to handle user interaction:
public void move(Player p, int spaces){
Space landingSpace = board.getLandingSpace(p,spaces);
landingSpace.land(p); //apply your logic here
}
As you can see, the Space class is responsible for checking the Player p that intends to land on that space. It applies any custom logic, checks if it has enough money, if it's something that the player owns, etc. Each subclass of Space will have its own set of rules, as you described in option 1.
Part of the point of object-oriented design is to simplify the representation of the problem within the solution space (i.e., modeling the system in the computer). In this case, consider the relationships between objects. Is there enough functionality in a Space to warrant abstracting that into a class, or does it make more sense for there to be discrete Property and Utility classes unrelated to Space because of the unique features of both? Is a Property a special kind of Space, or merely a field within Space? These are the kinds of problems you probably will need to grapple with in designing the game.
As far as interaction, it's generally bad news for a design when you have a 'god class' that does all the work and merely asks the other classes for information. There are plenty of ways to fall into this trap; one way to determine whether you are dealing with a god class is to look for a class name including Manager or System. Thus, it's probably not the best idea to have some sort of "game manager" that asks all the other objects for data, makes all the changes, and keeps track of everything. Eliminate these as much as possible.
God classes violate the concept of encapsulation, which involves more than data hiding (though that's certainly a big part of it). Good encapsulation means that related methods and data are part of a single object. For example, a Property doesn't need to make requests of its owner, so a field containing a reference to the Player could violate encapsulation. Some of these encapsulation violations aren't obvious at all, and can be hard to spot. When designing the object, try to determine the smallest amount of information about the object that needs to be shared with external objects. Trim out anything unnecessary.
You can obviously go about this in a lot of ways, but my design would be something like this (iteration could certainly prove it wrong):
Space class that contains basic data and methods that are common to all spaces (such as their position on the board, occupied or not, etc.).
Subclasses moving from most common (Property and Utility) to most unique (Go, Jail, FreeParking, and so on; probably singletons) with fields and methods related to each.
Player class to contain player information.
GameState class that is concerned with game state; whose turn it is, how many houses are left in the bank, and so on.
Good luck with the game and your continued studies.
Naturally, Google is your friend, but here's a sampling of things I would recommend reading:
ATM simulation (this idea is
also discussed in Rebecca
Wirfs-Brock's book below)
Object-Oriented Design Heuristics - Arthur Riel
How Designs Differ (PDF), Designing Object-Oriented Software - Rebecca Wirfs-Brock
Whenever I try to write graphical programs (whether a game or really any GUI app) I always wind up with one or two god classes with way too many methods (and long methods, too), and each class having far too many responsibilities. I have graphics being done at the same time as calculations and logic, and I feel like this is a really bad way to go about organizing my code. I want to get better at organizing my code and abstracting out responsibilities to different classes. Here's an example of where I'd like to start - I want to write a Minesweeper clone, just sort of as practice and to try to improve my software engineering skills. How would I go about making this nice and object-oriented? For the sake of discussion, let's just say I'm using Java (because I probably will, either that or C#). Here's some things I would think about:
should each tile inherit from JButton or JComponent and handle drawing itself?
or should the tiles just be stored as some non-graphical MinesweeperTile object and some other class handles drawing them?
is the 8-segment display countdown timer (pre-Vista, at least) a separate class that handles drawing itself?
when the user clicks, do the tiles have mouse event listeners or does some other collision detection method loop through the tiles and check each one to see if it's been hit?
I realize that there's not just one way to write a GUI application, but what are some pretty basic things I can start doing to make my code more organized, manageable, object-oriented, and just over all write better programs?
edit: I guess I should add that I'm familiar with MVC, and I was originally going to incorporate that into my question, but I guess I didn't want to shoehorn myself into MVC if that's not necessarily what I need. I did searched for topics on MVC with GUI apps but didn't really find anything that answers my specific question.
edit2: Thanks to everyone who answered. I wish I could accept more than one answer..
Here is a simple (but effective) OO design to get you started:
First create a Game object that is pure Java/C# code. With no UI or anything else platform specific. The Game object handles a Board object and a Player object. The Board object manages a number of Tile objects (where the mines are). The Player object keeps track of "Number of turns", "Score" etc. You will also need a Timer object to keep track of the game time.
Then create a separate UI object that doesn't know anything about the Game object. It is completely stand alone and completely platform dependent. It has its own UIBoard, UITile, UITimer etc. and can be told how to change its states. The UI object is responsible for the User Interface (output to the screen/sound and input from the user).
And finally, add the top level Application object that reads input from the UI object, tells the Game what to do based on the input, is notified by the Game about state changes and then turns around and tells the UI how to update itself.
This is (by the way) an adaption of the MVP (Model, View, Presenter) pattern. And (oh by the way) the MVP pattern is really just a specialization of the Mediator pattern. And (another oh by the way) the MVP pattern is basically the MVC (Model, View, Control) pattern where the View does NOT have access to the model. Which is a big improvement IMHO.
Have fun!
use a MVC framework that handles all the hard organization work for you. there's a ton of MVC framework topics on SO.
using high quality stuff written by others will probably teach you faster - you will get further and see more patterns with less headache.
I'm not suggesting this is the only way to do it, but what I would suggest is something like the following. Other people, please feel free to comment on this and make corrections.
Each tile should inherit from something and handle drawing itself. A button seems like the best solution because it already has the button drawing functionality (pressed, unpressed, etc) built in.
Each tile should also be aware of its neighbors. You would have eight pointers to each of its eight neighbors, setting them to null of course if there is no neighbor. When it goes to draw, it would query each neighbor's IsMine() function and display the count.
If none of its neighbors are a mine, it would then recurse into each neighbor's Reveal() method.
For the 7-segment display, each digit is its own class that handles drawing. Then I would make a CountdownSegmentDigit class that inherits from this class, but has additional functionality, namely CountDown(), Set(), and Reset() methods, as well as a HitZero event. Then the display timer itself is a collection of these digits, wired up to propagate zeroes left. Then have a Timer within the timer class which ticks every second and counts down the rightmost digit.
When the user clicks, see above. The tile itself will handle the mouse click (it is a button after all) and call its Reveal() method. If it is a mine, it will fire the MineExploded event, which your main form will be listening to.
For me, when I think of how to encapsulate objects, it helps to imagine it as a manufacturing process for physical parts. Ask yourself, "How can I design this system so it can be most efficiently built and reused?" Think about future reuse possibilities too. Remember the assembly process takes small pieces and builds them up into larger and larger pieces until the entire object is built. Each bit should be as independent as possible and handle its own logic, but be able to talk to the outside world when necessary.
Take the 7-segment display bit, you could have another use for it later that does not count down. Say you want a speedometer in a car or something. You will already have the digits that you can wire up together. (Think hardware: stock 7-segment displays that do nothing but light up. Then you attach a controller to them and they get functionality.)
In fact if you think hard enough, you might find you want CountUp() functionality too. And an event argument in HitZero to tell whether it was by counting up or down. But you can wait until later to add this functionality when you need it. This is where inheritance shines: inherit for your CountDownDigit and make a CountUpOrDownDigit.
Thinking about how I might design it in hardware, you might want to design each digit so it knows about its neighbors and count them up or down when appropriate. Have them remember a max value (remember, 60 seconds to a minute, not 100) so when they roll over 0, they reset appropriately. There's a world of possibilites.
The central concern of a Graphic User Interface is handling events. The user does X and you need to response or not respond to it. The games have the added complexity in that it needs to change state in real time. In a lot of cases it does this by transforming the current state into a new state and telling the UI to display the results. It does this in a very short amount of time.
You start off with a model. A collection of classes that represents the data the user wants to manipulate. This could represent the accounts of a business or vast frontiers of an unknown world.
The UI starts with defining a series of forms or screens. The idea is that is for each form or screen you create a interface that defines how the UI Controller will interact with it. In general there is one UI Controller classes for each form or screen.
The form passes the event to the UI Controller. The UI Controller then decides which command to execute. This is best done through the Command design pattern where each command is it own class.
The Command then is executed and manipulate the model. The Command then tells the UI Controller that a screen or a portion of a screen needs to be redraw. The UI Control then looks at the data in the model and uses the Screen Interface to redraw the screen.
By putting all the forms and screen behind a interface you can rip out what you have and put something different in. This includes even not having any forms at all but rather mock objects. This is good for automated testing. As long as something implements the Screen Interface properly the rest of the software will be happy.
Finally a game that has to operate in real time will have a loop (or loops) running that will be continually transforming the state of the game. It will use the UI Controller to redraw what it updated. Commands will insert or change information in the model. The next time the loop comes around the new information will be used. For example altering a vector of a object traveling through the air.
I don't like the MVC architecture as I feel it doesn't handle the issues of GUIs well. I prefer the use of a Supervising Controller which you can read about here. The reason for this is that I believe automated tests are one of the most important tools you have. The more you can automate the better off you are. The supervising presenter pattern makes the forms a thin shell so there is very little that can't be tested automatically.
Sorry to say it, but it seems you have mess in your head trying to improve your coding too much in one step.
There is no way to answer your question as such, but here we go.
First start with OOP, think about what objects are required for your game/GUI and start implementing them a little at a time, see if there are chances to break up these objects further, or perhaps reunite some objects that make no sense on their own, then try to figure out if you have repeated functionality among your objects, if you do, figure out if this repeated functionality is a (or many) base class or not.
Now this will take you a few days, or weeks to really grok it well, then worry about dividing your logic and rendering.
I have some tutorials that are written in C#. It discusses this very same topic. It is a starting point for a RogueLike game.
Object Oriented Design in C# Converting Legacy Game
Object Oriented Design: Domain Type Objects
Object Oriented Design: Rethinking Design Issues
BROKEN LINK - Object Oriented Design: Baby Steps in Acceptance Testing