At this point, I would say archive your game, start fresh using the things you have learnt, develop significantly faster than you were before.
Now, part 3 is all about structure, and making sure your game stays neat, instead of becoming a mess of code. To start with, this is an object oriented language, so let's move this code over to a new class called 'Game', and take out some of that static!
class Game
{
private bool quitting;
public void Quit()
{
quitting = true;
}
public void Run()
{
TCODConsole.initRoot(80, 40, "Name of your game", false);
quitting = false;
while (!quitting && !TCODConsole.isWindowClosed())
{
TCODConsole.checkForKeypress();
TCODConsole.root.print(4, 5, "Morning sunshine!");
TCODConsole.flush();
}
}
}
We can refine this a little more through use of constructors.
class Game
{
private bool quitting;
public Game()
{
TCODConsole.initRoot(80, 40, "Name of your game", false);
quitting = false;
}
public void Quit()
{
quitting = true;
}
public void Run()
{
while (!quitting && !TCODConsole.isWindowClosed())
{
TCODConsole.checkForKeypress();
TCODConsole.root.print(4, 5, "Morning sunshine!");
TCODConsole.flush();
}
}
}
Back in our main, and we can change it to this.
static class Program
{
static void Main()
{
Game game = new Game();
game.Run();
}
}
There is a good chance that is all our main will ever be... Kind of sad, to think that the entry point to the entire program is nothing more than making a new game, a lonely gate keeper, so to speak. Until you realise it is just code and doesn't have the capacity to feel lonely.
Anyhoo! There will come a point when you want different states for your game, such as when you are in the main menu, when you are in character creation and when you are playing a level. To make the switch between states, it may seem tempting to do something like this.
enum GameState
{
MainMenu,
CharacterCreation,
PlayingLevel
}
And then have a massive switch statement to handle the flow of the program. Trust me, I have a
much better way that isn't going to do your head in later on.
To start with, add a new class, and call it 'GameState', now make it abstract, make a protected constructor, and give it a protected variable for a Game. You should hopefully end up with this.
abstract class GameState
{
protected Game game;
protected GameState(Game game)
{
this.game = game;
}
}
Now for a little bit of separation of logic. Updating a game, and drawing a game and different things, so let's have different methods for them.
abstract class GameState
{
protected Game game;
protected GameState(Game game)
{
this.game = game;
}
public abstract void Update();
public abstract void Draw(TCODConsole console);
}
Now you might have noticed we are taking a console as a parameter. I might have forgotten to mention, but in libtcod consoles are not static. You can make new ones, and pass them around. The point of this is so that you can 'blit' one on top of another, and have a console for each screen currently being shown.
Anyway, the point of having two separate methods is that later on, when we have a few more tricks under our belt, we can upgrade our game so that if the FPS is running low we can skip drawing a few frames to catch up, making the game move a lot less lagy.
Back in our game class, it needs a bit of up upgrade to handle states. Firstly it will need a reference to it's state, and a method to set a new state. Also removing the line to take keyboard input. This is because in some instances you might want the game to run in real time, but otherwise you might want it to wait for input, so this depends on the state. Hell, you might even want an opening cut scene where they get no input! Up to you. But here is what you should be looking to achieve.
class Game
{
private bool quitting;
private GameState state;
public Game()
{
TCODConsole.initRoot(80, 40, "Name of your game", false);
quitting = false;
//state = NEW TYPE OF FIRST STATE HERE
}
public void Quit()
{
quitting = true;
}
public void Run()
{
while (!quitting && !TCODConsole.isWindowClosed())
{
state.Update();
state.Draw(TCODConsole.root);
TCODConsole.flush();
}
}
public void SetState(GameState state)
{
this.state = state;
}
}
That is pretty much it for structure. You can now swap between states without the need for big, bulky switch statements. I'll give you a little example of a test state to get you started. Feel free to ask any questions.
class TestState : GameState
{
private int ticks;
public TestState(Game game)
: base(game)
{
ticks = 0;
}
public override void Update()
{
TCODConsole.checkForKeypress();
ticks++;
}
public override void Draw(TCODConsole console)
{
console.print(5, 5, "Ticks: " + ticks);
}
}
And don't forget to update that line in the constructor of the Game class.
Edit: Sorry, forgot something, updated it.