I keep hitting this problem when building game engines where my classes want to look like this:
interface Entity {
draw();
}
class World {
draw() {
for (e in entities)
e.draw();
}
}
That's just pseudo-code to show roughly how the drawing happens. Each entity subclass implements its own drawing. The world loops through all the entities in no particular order and tells them to draw themselves one by one.
But with shader based graphics, this tends to be horribly inefficient or even infeasible. Each entity type is probably going to have its own shader program. To minimize program changes, all entities of each particular type need to be drawn together. Simple types of entities, like particles, may also want to aggregate their drawing in other ways, like sharing one big vertex array. And it gets really hairy with blending and such where some entity types need to be rendered at certain times relative to others, or even at multiple times for different passes.
What I normally end up with is some sort of renderer singleton for each entity class that keeps a list of all instances and draws them all at once. That's not so bad since it separates the drawing from the game logic. But the renderer needs to figure out which subset of entities to draw and it needs access to multiple different parts of the graphics pipeline. This is where my object model tends to get messy, with lots of duplicate code, tight coupling, and other bad things.
So my question is: what is a good architecture for this kind of game drawing that is efficient, versatile, and modular?
Use a two stages approach: First loop through all entities, but instead of drawing let them insert references to themself into a (the) drawing batch list. Then sort the list by OpenGL state and shader use; after sorting insert state changer objects at every state transistion.
Finally iterate through the list executing the drawing routine of each object referenced in the list.
This is not an easy question to answer, since there are many ways to deal with the problem. A good idea is to look into some Game/Rendering engines and see how this is handled there. A good starting point would be Ogre, since its well documented and open source.
As far as I know, it separates the vertex data from the material components (shaders) through the built-in material scripts. The renderer itself knows what mesh is to be drawn in what order and with what shader (and its passes).
I know this answer is a bit vague, but I hope I could give you a useful hint.
Related
Currently I am trying my best programming a little video game in the style of the old Zelda games. However, I am having some trouble with the whole OOP style of thinking. To be more specific, I don't really know how to "design" the screens.
Let's say I have a class for my sprites and loaded a Wall-sprite to have a border for a certain area, should I make an extra "wall"-class, or is the wall being a "sprite" already enough? I thought it might be senseless to define an extra class since it would not have any different variables than the actual sprite class (as my wall IS only a sprite) so I didn't consider it to be a useful idea.
I am asking this because I have a little problem with the collision detection as well: What I currently do is loading a sprite for an object only once and rendering it multiple times at several locations. But the problem is that this causes the collision only to be detected at the last position the sprite was rendered at.
It gives me more problems when I render 2 cave-entrances somewhere but my game only checks for the 2nd entrance if I "entered" it.
So I thought making an extra "entrance"-class and creating 2 completely different objects of it that are treated separately might help, but should I then also create 30 objects for my wall-sprites?
Hmmm, there is really two questions, well three, but the OOP-thinking is too non-specific for a good question. So let's see if we can answer it by answering your valid ones.
Good OO Design is centered around "Patterns" (Common solutions to a variety of Problems) in the case of your sprite re-use in OO this would be known as a "Fly-weight" Pattern. Three important structural elements in good OO and understanding them is key to "getting it". They are:
Interfaces - They are free (relatively) of operational code, and provide only method and constructor signatures(generally) to allow for clean separation of coding concerns.
Classes - Only the reusable parts(ideally) of an object they are "the Mold or Pattern" that objects are instantiated (or patterned) from.
Objects - Instances (this chair or that chair as opposed, to Chair as an ideal) of the same form of Class (the ideal Chair). Objects (ideally) should keep as instance values only that which differentiates it from other instances of the same ideal.
However, because your original sprite is not an object you are having this collision problem, because it actually is the same instance rendered again and again, the graphics pipeline does not keep all of its previous locations as separate things it actual just stores pixels(usually), once they've been translated.
In this case if each instance is an object, each instance would have its location as a local instance variable(s), while its graphical representation and collision detection method would be common to all instances of the class.
Don't think of it as having 30 whole copies in memory at once, you only have thirty copies of the instance variables. This is true if you use OO or not; in a procedural solution to get proper collision detection you would have to maintain an array of all of the places you rendered that sprite and iterate through each time, further your code would be less cleanly separated and you would have to iterate through the array for every sprite interaction as well as for updating moving sprites. With OO you could handle this with one class method call that recurses it children.
A good class structure for this simple example might be:
An Abstract Sprite Class (abstract because you will never use a non-specific Sprite) containing only code common to all sprites
A Concrete Wall Sprite Class that extends Sprite, only the code for non-moving wall sprites.
A Concrete Trigger Sprite Class (whose graphic might be clear or null) for behaviors that need to be triggered in "open spaces"
A Concrete Agent Sprite Class for moving sprites (might implement a movable interface meaning all derivatives of the class have a move() method.
A Concrete Character class that extends agent for a movable sprite that is driven by user commands.
It may seem confusing at first, but it's actually cleaner, simpler, and more maintainable doing it the OO way.
:)
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.
I just resumed work on an old project and have been thinking about rewriting some parts of it.
My question relates to how to structure my program. I have been trying to follow the MVC paradigm. I'll start by explaining where things stand: the program manipulates 4 types of images: Bias, Darks, Flat Fields and Lights. I have a class called Image that can represent all of these. The Bias and Dark are subtracted from the Light and then the Light is divided by the Flat Field. Initially, I was going to use 2 classes for this, one called CalibrationImage and the other just Light. But the difference was only of one method which would be the dividing function I mentioned above. Otherwise, they are the same. So I decided against having two classes for this purpose.
The 2nd major class in the program concerns handling multiple Image objects -- this class is known as ImageStacker. As of right now, it holds Image objects in a mutable array. It can do various operations on this array, like stack all the images, calibrate them etc.
This class also acts as the datasource for the NSTableView object in the main window. I'm not thinking that instead of having a single mutable array, I should have 4 arrays each holding its designated for a type of image (like, an array for Lights, another for Darks etc.). Once the program begins its actual work, it will Darks, Flat Fields and Bias frames. It will then calibrate each object held in the Lights array and then stack them. I feel like this provides the program with logical progression. Its also a bit easy to visualize.
Is this a good program design? Does it follow MVC? As I see it, my view is NSTableView, controller is NSApplication and Model is ImageStacker. But then, Image feels like its not part of the MVC but I cant see how to write the program without it.
My 2-cents: MVC is a presentation design pattern. I will typically write my MVC apps with separate business and data layers apart from MVC portion. It is ok that Image is not apart of the MVC pattern, it would probably better fit into a group of classes that you would define as your business layer. There are a lot of good books, blogs and articles out there that talk about programming design patters so I will not reiterate what they have already done. Simply asking this question is a good start. I would suggest you follow through by looking at content that is already available.
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.
I'm starting a game project, my first, it'll be like a civilization clone, with a big focus in war. I always worked with C# but for business apps (mostly web apps) so I have a doubt about what would be a good design to build the map positioning system.
I would like to each unit know where it's positioned, and to the map to know all units at each point, a two-way relationship, but I can't see what would be the best way to model this! I'd like some ideas and pseudo-code, if you could!
Thankz.
Make your map a two-dimensional array. At each position, put an array of all objects at that position. In addition, add position attributes to each object.
Yes, this will duplicate the information! So on each move you'll have to change the object and update the map.
However, fast reading and fast finding of the objects is very important for that kind of game. In addition, this solution avoids any search routine (e.g. go through the map and look for a particular object), which is generally a good idea: Replace all search routines over large datasets with indexes. The map should be seen as some kind of index over the object's position attributes.
The map should have all knowledge of all object on it. Furthermore, only each object on the map should know its location. This way, the map can ask all objects where they are and place them in their correct locations. You should never have to store the positioning information twice.
Here's one approach that should avoid duplication
Have a class which holds all objects on the map, and within it collections of different types of object
public class MapObjects
{
private Collection<GamePiece> gamePieces;
}
Each item in the collections will hold its (current) map co-ordinates
public class GamePiece
{
private MapCoordinate mapCoordinate;
// Other items relevant to a GamePiece.. Health, ItemType, etc
}
To find where a particular selected item is on the map should be easy, you have a reference to the GamePiece which holds its coordinates. To find what items are in a particular coordinate you need a helper method, probably within the MapObjects class:
public class MapObjects
{
public Collection<GamePiece> GamePiecesAtLocation(MapCoordinate mapCoordinate)
{
// Iterate through gamePieces collection and build a result
// collection of items at specified coordinates.
}
}
Good luck, sounds like an interesting project with plenty of challenges.
I would make the map hexagonal instead of a grid, so you don't have the odd Civilization phenomenon where you can cover more ground diagonally. Beyond that, I would just have each unit store its own position, and when you need to know which units are in a particular hex just iterate through the whole collection. It's hard to imagine having so many units involved that this approach would be a performance problem.
NSPoint is extremely useful when it comes to things like this. Each gameobject should have it's own location. You could store these gameobjects in arrays, one for each player, one for the whole game, it's up to you.
I will warn you that this is a huge project, not only codewise, but content wise, and requires lots of back and forth work while balancing the game. You should really try a few smaller games before you go after this one. Nothing is stopping you from diving in, but you are going to hit a lot of walls and write some serious spaghetticode if your first game is something this large. I would suggest starting with something like checkers, to get the turn based side of things down.
This is all coming from the guy who is currently writing a roguelike as his first game project. In my defense it is relatively straightforward, but there are a lot of things I was not expecting, and something as simple as calculating the sight / fog of war taking obstructions into account uses complex algorithms. I don't regret picking a roguelike as my first game, but after seeing how complex even the most basic concepts can be to implement, something like a turn based strategy game is simply something I'll leave to the pros for now.
If you're currently having trouble thinking of a way to not only create the units, but represent the map and store the locations, what are you going to do when it comes time to code in research? cities? production? resource gathering? A random map generator? Trajectory calculation? Hit probability? Armor? Mobility? Line of sight? Random events? AI?
I'm not trying to crush your dreams by any means, it's just that the genre you picked is more complex than it seems. Your brain will overload and burst at the seams. (I could continue rhyming on topic, but I will refrain to remind you that you should really try something like checkers first.)
Good design = simple design.
Make the map a list of objects.
Object
int X { get; set; }
int Y { get; set; }
Map
List<Object> objects
Add(Object)
Remove(Object)
GetAt(X, Y)
GetInBox(X,Y,Width,Height)
GetInRadius(X,Y,Radius)
That should be all you need. If the Get(..) queries get too slow, add caching or divide the map into sectors and keep a list of objects for each sector and update it when they move. This helps dramatically if you have many static objects or objects that don't move too quickly from sector to sector. My guess is that in a turn-based game, you won't need to optimize at all.