4
\$\begingroup\$

/UPDATE:
I took one of the suggested solutions and tried to implement them. I implemented a BaseGameWorld class that contains the basic tetris gameplay. Every game mode extends this base class. If any of the game modes differ from that classic gameplay they will simply override any methods needed or add new ones. My GameScreen class is now structured like this:

public class GameScreen  {
    private BaseGameWorld gWorld;
    private GameRenderer gRender;

    public GameScreen (int gameMode) {
         // PuzzleGameMode extends BaseGameWorld
         gWorld = new PuzzleGameMode();
         // Constructor of GameRenderer takes a BaseGameWorld object
         gRender = new GameRenderer(gWorld);
    }

    public void render() {
         // Update Game World
         gWorld.update();
         // Draw Game World
         gRender.draw();
    } 
}

This is ofcourse not the complete code, but it should show everything important. The idea behind the GameWorld and the GameRenderer classes is to reduce any clutter in the GameScreen class and seperate the game world and the drawing of the game world in two seperate steps with the goal to improve maintainability. So far this approach works quite well.
The type gWorld get's initiated with depends on the gameMode input variable and is handled through a switch-case in the actual code. Just as an example I used the class PuzzleGameMode.

Now my problem is that any new things added in the PuzzleGameMode class can't be drawn inside the GameRenderer class, since the GameRenderer constructor takes a BaseGameWorld object. It can only draw things that are in the BaseGameWorld.

Is there a way to resolve this situation that doesn't involve making a seperate GameRenderer for every game mode? My hope was to only have different classes for each game mode but to have one universal GameRenderer class.


I am currently making a tetris clone to get back into game programming using libGDX. The game is currently seperated in different screens. MenuScreen (includes Options, Highscore, Credits etc.) and the GameScreen itself. The GameScreen also has one member (named GameWorld) that manages all the calculations and game states, aswell as another one (named GameRenderer) that does all the drawing.

This works fine for the moment, however I plan on adding multiple game modes. I could probably add them to the GameWorld class, but it is already very full and managing multiple game modes inside a single class would end up very confusing and not very nice to maintain later down the line.

I could make a different class for every game mode and just use one of them depending on the selected game mode. This would be a solution, however this seems like a waste since I would just copy most of the original code for some of the game modes.
Alternativly I could make a Superclass that all game modes inherit from, however I am not sure how well it would work since game modes can differ quite a bit from each other. One mode might change the fundamentals like collision or intoduce new mechanics that need to be implemented on a deeper level, while others only differ a bit from the classic tetris mode and use most of the already implemented stuff.

What would be a good way to implement different game modes?
If more information is needed or if I should specify something better, just tell me and I will add the missing information. :)

\$\endgroup\$
6
  • 2
    \$\begingroup\$ Two solutions that came into my head: 1. Split your game to smaller blocks and build game modes picking specific set of blocks for each mode. 2. Can't you just inherit and, when one game mode isn't using common method, just override it? \$\endgroup\$
    – Mars
    Sep 13, 2016 at 13:13
  • \$\begingroup\$ @Mars I thought about it more and I think your second solution would indeed be a good way to do it. I implemented a BaseGameWorld class that contains the basic Tetris gameplay I had implemented and other game modes override methods from that class. However I ran into a bit of a problem trying to implement it. My GameRenderer class takes a BaseGameWorld object in the constructor. When I add something in one of the game modes I can't render the added things since the GameRenderer class can ofcourse only use things that are present in the BaseGameWorld. \$\endgroup\$
    – The_Blog
    Sep 13, 2016 at 20:23
  • \$\begingroup\$ Do you need whole BaseGameWorld to render its contents, or just a subset, list of objects/rendering requests? Perhaps you could make some GetContentToRender method and override it as well, or just have a list of game objects/prepared rendering information and pass it to GameRenderer instead of whole BaseGameWorld. \$\endgroup\$
    – Mars
    Sep 14, 2016 at 11:08
  • \$\begingroup\$ That's an interesting idea. Hadn't thought about it. The GameRenderer class needs an int[][] array of the grid that shows the position of all landed tetris blocks, aswell as the currently falling tetrimino object. Plus any new stuff from the custom gamemodes. I like the idea, but I am not exactly sure how you could pass over the custom stuff since it could be off different types or multiple objects or things like that. My current solution would have been to type sniff the BaseGameWorld object that goes into the GameRenderer class. However that is considered bad practice in most cases. \$\endgroup\$
    – The_Blog
    Sep 14, 2016 at 12:34
  • \$\begingroup\$ In the end, you need (in most cases) to have unified data for renerer. You can either somehow pass different types of objects to renderer and make your processing there (if object type equals...), or prepare data in each object and pass such data to renderer. Renderer then gets unified data and really doesn't care if its sheep at specific location, or our sneaky hero disguised as sheep - it only knows that sheep image (mesh/sprite) has to be placed at that location. So just pass array of pairs (location, image) to the renderer and let it do the job we expect from it - render. \$\endgroup\$
    – Mars
    Sep 14, 2016 at 15:08

3 Answers 3

1
\$\begingroup\$

Take a look at GOF (Gang of four ) state machine , and Hierarchy State machines patterns state pattern State Pattern

In a Hierarchical state machines, A state can have a superstate (making itself a substate). When an event comes in, if the substate doesn’t handle it, it rolls up the chain of superstates. In other words, it works just like overriding inherited methods, So no code Duplication.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Could you expand on this? This is more a comment than an answer... \$\endgroup\$
    – Vaillancourt
    Sep 13, 2016 at 16:14
  • 1
    \$\begingroup\$ ...and how could be applied to the OP's issue? \$\endgroup\$
    – Vaillancourt
    Sep 13, 2016 at 16:28
  • \$\begingroup\$ That can be applied by making the SuperState class with virtual methods , so each SubState class can inherit it an override these methods , although the SubState class can invoke SuperState class to roll up the chain (walking up the hierarchy ) ,where some event need to be handled by the base class \$\endgroup\$
    – Dr.MSM
    Sep 13, 2016 at 16:36
  • \$\begingroup\$ Please edit your answer :) What would be in the superstate? what would be in the sudstate? The answer is very generic... how does it relate to the OP's question? \$\endgroup\$
    – Vaillancourt
    Sep 13, 2016 at 16:38
1
\$\begingroup\$

Consider the following UML diagram: UML

This is what is known as a finite state machine. In this way, an application, or game, can have several states, or behaviours. When certain conditions are met, such as a key being pressed, or a menu choice selected, a change in state is triggered, which changes how the application or game behaves.

Additionally, each state can have a set of sub-states themselves, which further granulates the behaviours.

\$\endgroup\$
0
\$\begingroup\$

I use what is essentially a simplified version of libgdx (no OpenGL, for example). It has a basic class called Screen. Of course there are other classes for saving the scores, etc., but the main classes in my game just extend this class: the opening screen, the menu screen, the setting screen, the game screen, the end of level screen, etc. Because the basic functionality I need is built into Screen -- recognising touch, drawing, updating, pausing, etc. -- it is relatively easy to build the different types of screen that I need and there is relatively little duplication of code.

In your case, I would build a basic game screen and then override the methods that need to change. I don't know libgdx well, but I would guess that you leave GameWorld alone and just focus on what you want on the screen. I could be wrong about that.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I am using Screens aswell so it's very similiar. However the Game Screen in my case "only" loads and unloads ressources, contains the game loop and assigns the InputProcessor. The rest of the actual game is handled inside the GameWorld class. So if I would carry over your suggestion into my case it would mean making a subclass of GameWorld for each game mode and overriding methods when needed. This is one of the solutions I considered in my main post, but the more I think about it I think I agree that it would be the best way. Unless ofcourse I got your answer the wrong way. :) \$\endgroup\$
    – The_Blog
    Sep 13, 2016 at 18:23
  • \$\begingroup\$ I am not very familiar with libgdx (I tried writing a game with it and eventually gave up) and from what you say Game Screen is the wrong class. I was just trying to give you a clue as to how to proceed. I have found that picking a class, extending it and overriding the methods works for me. \$\endgroup\$ Sep 13, 2016 at 18:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .