Bill Morefield My thoughts, discoveries, and occasional rambiings.

April 1, 2016

Roguelike Development with C# – Part 5: Cleaning up Some Issues

Filed under: c#,gamedev,roguelike — Tags: , , — Bill Morefield @ 9:59 am

First a note that I didn’t get the code for the last couple of articles posted before so that’s been done now. Today’s article will work on setting up some debugging and counter logic that we’ll use going forward. We’re also going to fix a small bug in our handling of turns left in last time.

Last time we created a pair of counters to track how long we’ve been running. The tick variable holds how many times our game has run through the update handler while the turn variable tells us how many times the player has performed an action. We’re going to add three more counters and move these values into a separate class. Create a new file in the program named GameCounters.cs and define it as follows

[code language=”csharp”]class GameCounters
{
public int Tick { get; private set; }
public int Turn { get; private set; }
public DateTime StartTime { get; private set; }
private DateTime LastFrameTime { get; set; }
private double FrameDelta { get; set; }

GameCounters()
{
Tick = Turn = 0;
StartTime = DateTime.Now;
LastFrameTime = StartTime;
FrameDelta = 0.0;
}
}[/code]

This creates a class that holds our current Tick and Turn counters. It also adds three new values that hold the date and time we start our game, the date and time of each frame, and the difference in time since the last frame for each frame.

Now we’ll add a few three more calculated properties to this class. Before the constructor add the following three properties.

[code language=”csharp”]public double SecondsSinceStart => (DateTime.Now – StartTime).TotalSeconds;
public double AverageFPS => Tick / SecondsSinceStart;
public double CurrentFPS => 1.0 / FrameDelta;[/code]

If this looks unfamiliar, I’m using a new syntax introduced in C# 6. This uses the lamba arrow (=>) to define the body for the expression. The effect is exactly the same as if the methods had had a block body with a single return statement. In other words

[code language=”csharp”]
public double CurrentFPS => 1.0 / FrameDelta;
[/code]

is the equivalent of:

[code language=”csharp”]public double CurrentFPS
{
get
{
return 1.0 / FrameDelta;
}
}[/code]

in a smaller space.

For short get methods I find the new syntax easier to read.

We’ll also add methods to the class to update the counters from our Update handler.

[code language=”csharp”]public void NewFrame()
{
DateTime now = DateTime.Now;
Tick++;
FrameDelta = (now – LastFrameTime).TotalSeconds;
LastFrameTime = now;
}

public void NewTurn()
{
Turn++;
}[/code]

Now we need to update our game to use the new class. Replace the two existing counter variables with a single variable of the new GameCounter class.

[code language=”csharp”]private static GameCounters _counters;[/code]

We could initialize the counter class in our OnLoad handler, but I want to keep that to setting the initial game state. Instead we create the instance of the class immediately before starting the loop at the end of the Main method before the _rootConsole.Run(); line.

[code language=”csharp”]_counters = new GameCounters();
_rootConsole.Run();[/code]

We also now need to use the new methods whenever a turn or tick passes instead of directly changing the variables. Replace the turn++ call at the end of the loop handling key strokes with _counters.NewTurn();. Replace the increase of the tick counter at the end of the Update handler with a call to the new method so tick += 1; becomes _counters.NewFrame();.

In additon let’s add a new print statement to show the new counters. In the Render handler after the existing print statement add a new one.

[code language=”csharp”]_rootConsole.Print(1, 2, $"Time since start: {_counters.SecondsSinceStart:.000} Current FPS: {_counters.CurrentFPS:.0 fps} Average FPS: {_counters.AverageFPS:.0} fps", RLColor.White);[/code]

While these print statements are useful, I don’t think we’ll want them on the screen all the time as we add more functionality. Let’s add one more property to the CameCounters class.

[code language=”csharp”]public bool Visible { get; set; }[/code]

and update the constructor to set this property to false initially.

[code language=”csharp”]public GameCounters()
{
Tick = Turn = 0;
StartTime = DateTime.Now;
LastFrameTime = StartTime;
FrameDelta = 0.0;
Visible = false;
}[/code]

We’ll update our Render handler to only show these statements when the Visible property is set to true in our Render handler.

[code language=”csharp”]private static void RootConsole_Render(object sender, UpdateEventArgs e)
{
_rootConsole.Clear();

_rootConsole.SetChar(playerX, playerY, ‘@’);
if (_counters.Visible)
{
_rootConsole.Print(1, 1, $"Current tick: {_counters.Tick} Current turn: {_counters.Turn}", RLColor.White);
_rootConsole.Print(1, 2, $"Time since start: {_counters.SecondsSinceStart:.000} Current FPS: {_counters.CurrentFPS:.0 fps} Average FPS: {_counters.AverageFPS:.0} fps", RLColor.White);
}

_rootConsole.Draw();
}[/code]

To toggle the flag, we’ll use the d key (for Debug). After the case statement for the Q and Escape keys, add one more.

[code language=”csharp”]case RLKey.D:
_counters.Visible = !_counters.Visible;
break;[/code]

If you run the application as it is now, you’ll see that the statements are hidden at first, but will show after you press the D key. Pressing the D key again hides the information.

I also mentioned a bug in our handling of turns. Restart the game and press D. You’ll notice it shows one turn has passed. In fact if you press any key, including unrecognized ones such as F and the turn counter increases. That’s because we’re setting the userAction flag to true any time that we get a keypress.

We only want turns to pass when the player actually performs an action. Interface type activity (such as showing the menu here with the D key) shouldn’t count nor should keys we don’t recognize or act upon. Let’s fix this by only seting the userAction flag to true for keys resulting in the player peforming an action. Change the swtich statement handling keypresses within the Update handler to the following.

[code language=”csharp”]
if (key != null)
{
switch (key.Key)
{
case RLKey.Up:
userAction = true;
playerY -= 1;
break;

case RLKey.Left:
userAction = true;
playerX -= 1;
break;

case RLKey.Down:
userAction = true;
playerY += 1;
break;

case RLKey.Right:
userAction = true;
playerX += 1;
break;

case RLKey.Q:
case RLKey.Escape:
_rootConsole.Close();
break;

case RLKey.D:
_counters.Visible = !_counters.Visible;
break;
}
}[/code]

Now we only set the flag when the user moves. Quitting or toggling the display of debugging information does not count as an action.

Today we’ll do one more change to move the code that should only execute after a turn and the code that executes every time through the Update handler into separate functions. This will leave the Update handler focused on code to process player input.

Create two new methods at the bottom of the Program class.

[code language=”csharp”]private static void ProcessFrame()
{
_counters.NewFrame();
}

private static void ProcessTurn()
{
// Ensure player stays on the screen
if (playerX < 0)
playerX = 0;
if (playerX > screenWidth – 1)
playerX = screenWidth – 1;
if (playerY < 0)
playerY = 0;
if (playerY > screenHeight – 1)
playerY = screenHeight – 1;
_counters.NewTurn();
}[/code]

And change the end of the Update handler to call these methods. Change this part of the Update handler:

[code language=”csharp”]// Turn based events only if userAction is true
if (userAction)
{
// Ensure player stays on the screen
if (playerX < 0)
playerX = 0;
if (playerX > screenWidth – 1)
playerX = screenWidth – 1;
if (playerY < 0)
playerY = 0;
if (playerY > screenHeight – 1)
playerY = screenHeight – 1;
_counters.NewTurn();
}

// Real time actions
_counters.NewFrame();[/code]

into

[code language=”csharp”]// Turn based events only if userAction is true
if (userAction)
{
ProcessTurn();
}

// Update frame timers and counters
ProcessFrame();[/code]

We’ve done a number of changes in this article. download a zip file with the code to this point. Next time we’ll actually start implementing a real game by adding someone else besides our player to the game.

March 21, 2016

Roguelike Development with C# – Part 4: Windows and Turns

Filed under: c#,gamedev,roguelike — Tags: , , — Bill Morefield @ 1:35 pm

The last article recreated our game loop using RLNET. We’re now going to talk a bit more about some of the design choices of RLNET so we can understand how they’ll affect our design moving forward.

First if you ran the last demo (do so now if you didn’t) you likely noticed there were two windows. Our console containing our player and a second console in the background. As our project is set as a Console Application, this console was created even though we don’t want it and don’t use it. We could get rid of the window by hiding it, but a better option in our case is to never create it. Since we’re not a console app anymore, we change our project to work as a Windows application.

Right click the project in Visual Studio’s Solution Explorer and choose Properties. Under the Application tab change the Output type to Windows Application. Save and run and you’ll see no more unwanted console window.

change-output-type

You’ll also notice the window looks quite a bit different now. Our Console based program had a window that was roughly in the 4×3 ratio common to Console apps. The RLNET window though is very elongated.

This is exaggerated by the use of the 2.0 scaling factor, but most comes from our change to square tiles. Most console fonts have characters that taller than they are wide. Moving to characters that are the same height as their width means that the same size window will now look shorter. For now we’ll leave it, but will come back to the window size later.

Moving to RLNET also made another change to our code that isn’t currently obvious. In our Console verion the program waited for keyboard input and then processed that input. It still appears that’s the case, but a quick test will show this is not how RLNET works. Let’s add a simple counter after our other variables.

[code language=”csharp”]
private static int tick = 0;
[/code]

We’ll add a line to print this counter to our RootConsole_Render method.

[code language=”csharp”]
_rootConsole.Print(1, 1, $"Current tick: {tick}", RLColor.White);
[/code]

Note that I’m using a recent feature of C# known as interpolated strings. If you’re not familiar with this syntax $"Current tick: {tick}" is equivalent to string.Format("Current tick: {0}", tick).

If you run the app you’ll see the tick counter increases even when we don’t press a key. That’s because the keyboard check _rootConsole.Keyboard.GetKeyPress() doesn’t wait until a key is pressed. If checks for a key press, but if no keys was pressed it continues and returns a null.

Our game loop therefore now runs in realtime. This is a change from our original game loop using the Console as the Console.ReadKey(true) command does wait until a key is pressed before continuing. It doesn’t matter here since our game does nothing at the moment, but will become more important when we add other objects to the game, especially those hostile to the player. It would be quite a surprise if the player expects a monster to move only as they do, only for it to charge across the map and attack without the player doing a thing.

That doesn’t mean that this real time aspect is a bad thing. In fact we can make a real-time loop like this operate as a turn based loop. It adds a little work on us as a programmer, but gives us flexibility for the future we can use for animations or other things we might want to occur even when there’s no action by the user.

The simplest way to move toward real time would be to loop until a key is pressed. This way the actions of the game only continue after a player action. The code would look like:

[code language=”csharp”]
RLKeyPress key;

do
{
key = _rootConsole.Keyboard.GetKeyPress();
} while (key == null);
[/code]

This won’t work. If you make this change and run the game you’ll find your game won’t respond to any keypress. What we will do instead is a more flexible approach that divides our update handler into real time and turn based components. Let’s add a second counter to track this. After the tick counter we added, add another counter.

[code language=”csharp”]
private static int turn = 0;
[/code]

and change the print statement we added earlier to also show this new counter.
[code language=”csharp”]
_rootConsole.Print(1, 1, $"Current tick: {tick} Current turn: {turn}", RLColor.White);
[/code]

Next we’ll change our Update handler to deal with the mix of events that occur every time we go through the loop (ticks) and events that we’ll process only after the player makes an action (turns).

[code language=”csharp”]
private static void RootConsole_Update(object sender, UpdateEventArgs e)
{
bool userAction = false;

// Handle keyboard input
RLKeyPress key = _rootConsole.Keyboard.GetKeyPress();
if (key != null)
{
userAction = true;
switch (key.Key)
{
case RLKey.I:
playerY -= 1;
break;

case RLKey.J:
playerX -= 1;
break;

case RLKey.M:
playerY += 1;
break;

case RLKey.K:
playerX += 1;
break;

case RLKey.Q:
_rootConsole.Close();
break;
}
}

// Turn based events only if userAction is true
if (userAction)
{
// Ensure player stays on the screen
if (playerX < 0)
playerX = 0;
if (playerX > screenWidth – 1)
playerX = screenWidth – 1;
if (playerY < 0)
playerY = 0;
if (playerY > screenHeight – 1)
playerY = screenHeight – 1;
turn++;
}

// Real time actions
tick += 1;
}
[/code]

Now running the app you’ll see the tick counter increases in real time. Our turn counter only increases when we move our character. As I originally noted, my design for this game will be turn based, that’s a purely a game design choice. Having a creature charging at the player doing nothing can be normal and expected in many games.

One last change to make today. We chose the i,j,k, and m keys out of tradition, but I think most players would be expecting the arrow keys to move the player. So let’s make a change that uses those keys for movement instead, and we’ll also let the escape key end our game.

The i, j, k, and m key arrangement dates back to the popular Unix vi editor. It therefore became rather common in software written for Unix to use these keys for cursor movement. This included Rogue and Nethack.

Change the section managing keyboard input to:

[code language=”csharp”]
if (key != null)
{
userAction = true;
switch (key.Key)
{
case RLKey.Up:
playerY -= 1;
break;

case RLKey.Left:
playerX -= 1;
break;

case RLKey.Down:
playerY += 1;
break;

case RLKey.Right:
playerX += 1;
break;

case RLKey.Q:
case RLKey.Escape:
_rootConsole.Close();
break;
}
}
[/code]

That concludes this tutorial. You can download a zip file with the code to this point. Next we’ll start giving our player something to do other than wander in empty space.

March 15, 2016

Roguelike Development with C# – Part 3: Game Loop with RLNET

Filed under: c#,gamedev,roguelike — Tags: , , — Bill Morefield @ 10:28 am

At the end of the previous part we’d implemented a basic game loop using the Console for input and display. It works pretty well now, but the C# interface to the console is lacking at best. Pretty soon we’ll run into those limitations so we’re going to move to something else before going any further. We’re going to stick with a text based game, we can do that while leaving ourselves flexibility going forward that will make a graphical also possible.

C# libraries related to Roguelikes are a bit scarce compared to some other languages, but there are a several that will work for our needs. In place of using the Windows console I’m going to use RLNET. RLNET provides an API for creating tile based games under .NET that will handle our console output. I also handles our keyboard and mouse input.

Using an external library does add a dependency to our project. That’s a risk worth taking for a learning process like this as this library will save time we can devote to the other aspects of a game. Given that RLNET is open source, meaning we have access to the source code in case of bugs or needed changes, it feels like a safe risk.

Let’s walk through building the same functionality that we had at the end of the last article using RLNET. Begin in Visual Studio by selecting File -> New Project... from the menu. Under Templates choose Visual C# and expand Windows Desktop and choose Classic Desktop -> Empty Project and give it the name RogueLearning.

project-creation

Since we have an empty project, we need to add in the Program.cs class that we’d have created for us using the Console Application. Right click on the project and select Add -> Class. Name the class Program.cs and change it to match the following code. This will create a main method that will be called when our application begins.

[code language=”csharp”]
namespace RogueLearnng
{
class Program
{
static void Main(string[] args)
{
}
}
}
[/code]

We next will add RLNET to our project using the NuGet Package Manager. Right click on the project and select Manage Nuget Packages.... Choose the Browse tab and search for RLNET and click Install. This will add RLNET and its dependency OpenTK to your project. At this time the current version of RLNET is 1.0.6.

While we’re keeping our game text based for simplicity, RLNET actually is tile based. It uses a special image called a Font File to define these tiles. The Font File is a rectangular image containing all the tiles in this one image. These tiles must all be the same size, but there is no requirement that they contain text. They could as easily be made of images that we’d use instead. The format is that used by the popular C language Roguelike library libtcod and you can read more about these files on the libtcod documentation site.

The RLNET download comes with a simple text font file ascii_8x8.png, but the NuGet package does not install it so I’m providing a copy here. Download the file and drag it onto your project in Solution Explorer to add it to your program. In the properties for this file, change the Copy to Output Directory option to Copy if newer. Skip this step, and you’ll get an error when you try to run the app that the bitmap cannot be found.

ascii_8x8

Viewing the file you can see that it is a 128 x 128 pixel image that contains 256 8 x 8 pixels tiles arranged in 16 rows and 16 columns. These tiles correspond pretty closely to the original IBM CGA character set and is popular for text based games like this.

With the library loaded and a font file added to our project, we can being implementing our game loop. First at the top of the Program.cs file we’ll add a reference to the RLNET namespace so we don’t need to prefix it to every method.

[code language=”csharp”]
using RLNET;
[/code]

As in the previous entry, we’ll begin by adding the global variables that will contain our game state to the top of the class before the Main method definition.

[code language=”csharp”]
private static RLRootConsole _rootConsole;
private const int screenWidth = 80;
private const int screenHeight = 24;
private static int playerX;
private static int playerY;
[/code]

Two changes here. We’ve removed the quit flag that’s no longer needed with RLNET. We’ve added a RLRootConsole object that we’ll use to set and render our screen. Now let’s look at the new Main method.

[code language=”csharp”]
static void Main(string[] args)
{
_rootConsole = new RLRootConsole("ascii_8x8.png", screenWidth, screenHeight, 8, 8, 2f, "Rogue Learning");

_rootConsole.OnLoad += RootConsole_OnLoad;
_rootConsole.Render += RootConsole_Render;
_rootConsole.Update += RootConsole_Update;

_rootConsole.Run();
}
[/code]

The first line creates our console object that we’ll be using for display and to read player input. There seven parameters here, and each is important so let’s go through them in detail.

The first parameter “ascii_8x8.png” chooses the font file described earlier. The next two parameters, screenWidth and screenHeight, define the width and height of the console for our game. We’re using the constants declared a moment ago.

The next two parameters relate back to the font file and tell RLNET the size of each tile in pixels. For the ascii_8x8.png file each tile is 8 pixels wide by 8 pixels tall. We next provide a scale factor. This is a float value that zooms the screen by that factor. We’re using 2 here. This will make the display appear more pixelated, but shows up a bit better using these small tiles for screenshots. The last parameter lets us specify the name to appear on the window.

The next three lines set the handlers for the three events that we’ll deal with as our game loop. The first OnLoad event runs when we begin the game loop. The Render handler takes care of the display of the game state to the player. The Update handler allows us to read user input and update the state of the game.

Next we’ll implement these handlers starting with OnLoad:

[code language=”csharp”]
private static void RootConsole_OnLoad(object sender, EventArgs e)
{
playerX = screenWidth / 2;
playerY = screenHeight / 2;
}
[/code]

This performs the step of setting the player’s initial position as we did in the InitializeGame method of the last article. Note that since we defined the size of the console on creation, we do not need to do that here.

Our Render handler also looks familiar:

[code language=”csharp”]
private static void RootConsole_Render(object sender, UpdateEventArgs e)
{
_rootConsole.Clear();

_rootConsole.SetChar(playerX, playerY, ‘@’);

_rootConsole.Draw();
}
[/code]

We first clear the console so we have an empty display to begin. We then set the @ character at the player’s current position. Last we draw the current console to the window.

What we’re doing when setting the @ character is a little more complicated than it sounds. We aren’t displaying text directly as we were in the Console based version. We’re telling RLNET to display a tile at the player’s position. That tile is the integer value of the @ character, which is 64. Tile 64 of the loaded font file is a graphic that looks like the @ character. If you didn’t follow that, don’t worry about it for now. With our current font file the distinction isn’t important as characters and tiles match. We’ll go in more depth when needed.

Last we have the Update handler.

[code language=”csharp”]
private static void RootConsole_Update(object sender, UpdateEventArgs e)
{
// Handle keyboard input
RLKeyPress key = _rootConsole.Keyboard.GetKeyPress();
if(key != null)
{
switch(key.Key)
{
case RLKey.I:
playerY -= 1;
break;

case RLKey.J:
playerX -= 1;
break;

case RLKey.M:
playerY += 1;
break;

case RLKey.K:
playerX += 1;
break;

case RLKey.Q:
_rootConsole.Close();
break;
}
}

// Ensure player stays on the screen
if (playerX < 0)
playerX = 0;
if (playerX > screenWidth – 1)
playerX = screenWidth – 1;
if (playerY < 0)
playerY = 0;
if (playerY > screenHeight – 1)
playerY = screenHeight – 1;
}
[/code]

Again the code should look familiar. We now use the RLNET library to get our keyboard press, but otherwise we check for the i,j,k, or m keys as before and update the position as we did before. We also handle the quit method here by using the Close method on the console to end the game. After dealing with player input, we ensure the player isn’t trying to wander off the screen and correct if needed.

At this point we have recreated the previous demo using RLNET. This tutorial has already run a bit long, so we’ll stop there for this article and you can download the code to this point. Next time we’ll delve a bit more into the Update handler and discuss some subtle changes the move to RLNET brought.

March 9, 2016

Roguelike Development with C# – Part 2: A Basic Game Loop

Filed under: c#,gamedev,roguelike — Tags: , , — Bill Morefield @ 10:53 am

To begin the game, we’ll start with a game loop. Every game works through the same basic three steps.

  1. Initialize
  2. Update
  3. Draw

In step one, the program sets up the inital state of the game. The game then repeats steps two and three until the game ends. To start with I’m going to build a simple Command Line project using the built in Console class in C#.

For the initial pass we’ll keep things simple. Our goal is to create a player character that can be moved around the screen with the keyboard. We’ll use the i, j, k, and m keys as in the classic Nethack to move. We’ll also use the @ character for our player, again as in Nethack (and most other text Roguelikes).

[code language=”csharp”]
private static bool quit = false;
private const int screenWidth = 80;
private const int screenHeight = 24;
private static int playerX;
private static int playerY;

static void Main(string[] args)
{
// Register Ctrl+C handler and hide the cursor
Console.CancelKeyPress += ConsoleOnCancelKeyPress;
Console.CursorVisible = false;

// Initialize Game variables
InitializeGame();

// Enter Game Loop
GameLoop();
}
[/code]

We begin by defining five variables. The first stores a flag we can set to quit the game. We also store the size of the game screen along with the player’s current position.

A C# console app begins executing our Main method here. First I add a handler function that will be called when Ctrl+C is pressed. Next we hides the cursor and then call InitializeGame() to set up he initial state of our game by setting the variables above.

[code language=”csharp”]
private static void InitializeGame()
{
// Set window size
Console.SetWindowSize(screenWidth, screenHeight);
Console.SetBufferSize(screenWidth, screenHeight);

// Set initial player position to center of screen
playerX = screenWidth/2;
playerY = screenHeight/2;
}
[/code]

The first two lines set the window and buffer size of the Console to match our specified values. We then set the initial player position to the center of the screen.

That handler code by the way just sets the quit variable to true.

[code language=”csharp”]
private static void ConsoleOnCancelKeyPress(object sender, ConsoleCancelEventArgs consoleCancelEventArgs)
{
// Set flag that we’ll use to cancel on our own terms
quit = true;
consoleCancelEventArgs.Cancel = true;
}
[/code]

Next comes the heart of the game, our game loop code.

[code language=”csharp”]
private static void GameLoop()
{
while (!quit)
{
// Sleep a short period at the end of each iteration of the loop
Thread.Sleep(100);

// The Render section
// Clear the console before we draw
Console.Clear();

// Draw the player at the current position in white
Console.SetCursorPosition(playerX, playerY);
Console.ForegroundColor = ConsoleColor.White;
Console.Write(‘@’);

// The Update section
// Wait for a key press and do not display key on the console
ConsoleKeyInfo character = Console.ReadKey(true);

// Handle the player input
switch (character.KeyChar)
{
case ‘i’:
playerY -= 1;
break;
case ‘j’:
playerX -= 1;
break;
case ‘k’:
playerX += 1;
break;
case ‘m’:
playerY += 1;
break;
case ‘q’:
quit = true;
break;
}

// Ensure player is still on the screen
if (playerX < 0)
playerX = 0;
if (playerX > screenWidth – 1)
playerX = screenWidth – 1;
if (playerY < 0)
playerY = 0;
if (playerY > screenHeight – 1)
playerY = screenHeight – 1;
}
}
[/code]

The method begins with a while loop hat loops until the quit variable we defined earlier is true. Each pass through the loop begins with a short pause of 100ms. Given how little we’re doing at this stage of the loop, this pause keeps the pacing of our movement more controllable.

In this first pass I swapped the order of the render and update sections of the loop from above. They should occur be in the opposite order, but we’ll go with the code as written for now. These two sections repeat until we quit the game (or close the app).

The render section displays the current state of the game world and displays it to the player. Our loop begins by clearing the console giving a blank screen to draw on. Next the code prints the ‘@’ character, the player, in white at the player’s current position as specified by those variables we defined earlier.

The render section completed, the code continues to the update portion. Update handles user input and updates the game state to reflect that input.

We’re using a turn based approach and not real time. The Console.ReadKey method waits on a keypress before continuing. After the keypress, we interpret pressing the i,j,k, or m key as a request to move up, left, right, and down respectively and update the player’s position to match. We also respond to the q key by setting that quit flag to true which will end end the while loop the next time through, and thus end the game. Other keys are ignored.

After movement is processed, we check the player’s position and if the player has moved off the screen, then we shift the player back to the edge of the screen. If we didn’t do this then our game would crash with an exception when we attempted to print our character outside the defined screen. In a “real” game this check would better be done before responding to the move request.

You can download a full sample project for this simple game. Running the code as is gives us what we’d set out to accomplish. The player can move around the screen until pressing q or Ctrl-c to quit. It’s not much of a game, it’s barely even a demo, but it does give you a framework and start to build on. This basic process of update and render lies at the heart of any game.

March 6, 2016

Roguelike Development with C# – Part 1: Introduction

Filed under: c#,gamedev,roguelike — Tags: , , — Bill Morefield @ 11:00 am

Welcome to the first in an indefinite series of article covering my experiments creating Roguelike games using C#. I developed a renewed interest in the genre a couple years ago when I rediscovered Nethack, one of the many descendants of Rogue which gives its name to the genre of Roguelikes.

Defining a Roguelike is a bit difficult, especially as the term has come to be popular in the independent and small studio game space. There are a number of definitions proposed for Roguelikes, but .

To start I’m looking at exploring the traditional roguelike structure. The basic game here will be a single player RPG where the player controls a single character. We’ll stick with the traditional dungeon crawl setting using procedural world generation along with random distribution of creatures, items, etc. The game will be turn based, allowing the player time to consider each decision. We’ll also set the game with permadeath.

This last feature means that the player’s character dies, then the game is over. No checkpoint to start back from, no loading last save and trying again. Spend hours playing and then do something stupid and die? Too bad. It’s a harsh feature compared to many games where you can quickly save before doing almost anything.

The goal here isn’t to recreate Nethack or even necessarily produce a high quality game. I plan to write a playable and hopefully enjoyable game, but my primary goal is to learn. It’s been a while since I’ve done any type of game programming and I think this could be a fun project. I though it would be an intersting experience to document the process here and in the process also create a tutorial on build a Roguelike game in C#.

So a few decisions on what I’ll be creating. The game and tutorial will be written for Windows using C#. Most of the original Roguelike games used console graphics and I’ll do the same in this tutorial to keep things a little simpler. I’m also intentionally being a bit vague on when the program and tutorial are complete. I want to explore and try things by starting small and simple and building the program from there. I may restart any time and begin with the knowledge I’ve learned so far.

I’ll be writing this using a somewhat “warts and all” approach. I plan to document each step, misstep, and mistake. Each article will come with source code of the program implemented to that point and possibly the occasional side experiment. The code along with all displayed in the articles can be used for educational and research purposes. Feel free to use the overall code as a starting point for your own work. Please don’t simply take the code, change some words, and publish it as your own.

I’ll be using Visual Studio 2015 for development to take advantage of the newest features in C#. A few years ago I did some initial work against the console directly, but found C# support for the console too limited for what I’ll need going forward. Instead we’ll use a Console library for C#.

That’s all for this article. Next time we code.

January 15, 2013

Arbitrary Sorting Order in Linq To SQL

Filed under: c#,development — Tags: , , — Bill Morefield @ 3:22 pm

I ran into a situation recently that took me some time to work out and thought I’d document here. I have an older ASP.NET Web Forms application I help maintain. Some upgrades and changes to the workflow used by the customer had meant a few assumptions I’d made no longer applied.

The biggest of these was that a list of values no longer returned from the database the way I’d assumed before. Here is the Linq to Sql that pulled the values to that point.

   1:  var plans = from m in dc.MenuPlans
   2:              where m.client == CurrentClient && m.year == year &&
   3:                  m.month == month && m.day == day
   4:              select m;

As you might guess from this code, it pulls a set of menu plans from a database for a client. Each menu plan is specific to a day. What you can’t see here is that each meal has a meal name that is simply “Breakfast”, “Lunch”, “Dinner”, or “Snack”. Before the meals had been entered in that order and the creation method ensured they showed up in the order being entered.

Now they were being entered in a different order by multiple people and the order of creation no longer worked. The desired order was still breakfast, lunch, dinner, and then snack at the end. Sorting simply by the column wouldn’t work as that would produce an alphabetical order resulting in breakfast, dinner, lunch, and then snack. Close, but not quite.

What I needed was a custom ordering sequence. I could pull the items over in four groups and then append them to a final list, but that seemed messy and slow. I wanted a solution to do so at the database and not have to bring the elements in and sort in memory. I finally worked out a nice solution with this code.

   1:  var plans = from m in dc.MenuPlans
   2:              where m.client == CurrentClient && m.year == year &&
   3:                 m.month == month && m.day == day
   4:              orderby m.mealname == "Breakfast" ? 1 :
   5:                 m.mealname == "Lunch" ? 2 :
   6:                 m.mealname == "Dinner" ? 3 : 4
   7:              select m;

The new code lies on lines 4-6. What I do is compare the element that I want to sort by to the values in the order I wish things to show. I’m using the binary operator here. If you’re not familiar with it, this works like a compact if/then statement. The binary operator:

   1:  return x > 0 ? 0 : 1

Is equivalent to the following if/then statement.

   1:  if(x > 0)
   2:     return 0;
   3:  else
   4:     return 1

So the code lets me map the string values to numeric values arbitrarily. Breakfast maps to 1, Lunch maps to 2, Dinner maps to 3, and any other value to 4. Since the result of this is a set of integers, the ordering works the way I want.

While the code looks a bit messy, it translates nicely to SQL that runs on the database server through a CASE statement and I get the order I want without any extra processing in the web application.

April 9, 2012

Skinning a Windows Form Application

Filed under: c#,development,windowsforms — Tags: , , , — Bill Morefield @ 9:30 am

The normal application window looks like a simple, basic rectangle.  For most uses it works quite well though providing a nice and familiar wrapper for a program.  It’s a bit boring though.  Sometimes though you create a program that doesn’t quite fit the normal square window.  Maybe you’re creating a custom display.  Whatever the reason, you are not limited to the standard window look.

I recently started updating and cleaning up a few applications I’ve written for my own use.  One of them works as a target to drag files onto and really cried out for something other than a square window.  I decided to create a nicer interface and in this post I’m going to show how to create a Windows form application with a custom look.

Step One: Tear Down the Default Form

When you skin a window, some of the things that Windows normally does for you now have to be done manually. Before we apply our custom look, we’ll start by getting rid of things we don’t want and then recreating those lost elements.  Let’s start with the form that you get when create a new Windows Form application in Visual Studio 2010. It looks like this when you run the application.

clip_image001

We want to get rid of the menu bar and those buttons in the top right window.  We can easily do this by changing the window type. In the form’s properties Change the FormBorderStyle attribute from the default Sizable to None.

clip_image002

If you run the program at this point you will get a plain grey window.  If you try to click on the window and move it, you will find it ignores your request. If you try to resize the window, that also will not work. You will also find nothing to click and exit the application.  By changing the border style to none, we also lost the built in support to move the window, close the application, and resize the window.

Step Two: Recreate Lost Functionality

We therefore need to add any of these features that we want the user to have. At the least we should give the user a way to close our program. For simplicity, I’m going to add a handler so that if someone right clicks on the window, the program exits.  In a real program, right clicking might bring up a context menu with an exit option.  The method it’s invoked doesn’t matter as this code will close your application.

        private void SkinnedWindow_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                Application.Exit();
            }
        }

If you now run the program, you will again see a simple gray square.  If you right click on the window, the application will nicely exit.

In most cases we will still want to allow the user to move our application.  I found a good way to allow moving a skinned windows is to start the move when the user presses the left mouse button while on the window. They can then move the window while they hold the left button down. When the user releases the left mouse button, the window will remain at that location.

To implement this, the application needs to handle the MouseDown, MouseMove, and MouseUp events for the form. In addition, we’ll need to keep track of when we’re moving or dragging the window and the form’s location when we start moving it. So we’ll add two variables to the form class store this information.

        private Point _offsetPoint;
        private bool _dragging;

When the user clicks the left mouse button on the window we simply want to note that we’re entering a state where the user is moving the window and store the initial location where the user clicked the mouse.

        private void SkinnedWindow_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                _offsetPoint = new Point(e.X, e.Y);
                _dragging = true;
            }
        }

In the MouseMove event we first check to see if we’re moving the window by checking the bool we set when the left button was clicked. If so then we’ll take a note of the current location of the mouse and convert that to a screen point.  We then set the form’s location to this new point which is the difference between this screen point and the original locaiton.

        private void SkinnedWindow_MouseMove(object sender, MouseEventArgs e)
        {
            if (_dragging)
            {
                Point mousePoint = new Point(e.X, e.Y);
                Point screenPoint = PointToScreen(mousePoint);
                Location = new Point(screenPoint.X - _offsetPoint.X, screenPoint.Y - _offsetPoint.Y);
            }
        }

When the user releases the left mouse button, we just need to note that we’re no longer moving the window by setting our flag to false.  Our form location is already where we want to leave the form.

        private void SkinnedWindow_MouseUp(object sender, MouseEventArgs e)
        {
            _dragging = false;
        }

If you run the program now, you’ll still see a gray window.  You can still right click and exit as before.  Now you can also move the form around. If you click inside the window and hold the mouse button down, you can drag the window around the screen. When you release the button the window will stay where it was.

In my application, I did not want the user to arbitrarily resize the window. In my application, I provided a context menu the user can select from a few predetermined sizes. When the user selects a size I set the size of the window using the Size property for the form. You could also do something similar to how we handled moving the window if you want to give the user more flexibility on resizing the window.

Step Three: The New Look

We’ve now implemented the basic functionality we’d lost so we can now focus on making the window look how we want. For this sample, I’m going to select an image from the Visual Studio image library.  I’m using the 007_PrintView_128x128_72.png image located in the library under Actions\png_format\WinVista. You can be any image, but for simplicity it should be a format that natively supports transparency for areas that are not part of the image.

clip_image004

First add the image to our project as a resource. To do this, go to the Project’s properties and select the Resources tab. Select Add Resource -> Add Existing File…. In the dialog that opens find and select the image that you wish to use for your application’s appearance. You will see a new Resources folder appear in the project and our graphic will appear under it. We can now reference this resource in our program when we want to draw the image.

In our case we want our entire window to appear as this image. Since the image I am using is 128 x 128 and I am not going to let the user resize the window, I will set the window on startup to this size. I can do this by going to the Properties of the form and setting the size to 128, 128 which the window the form to same size as the graphic that I’m using.

clip_image005

I will use this graphic as my window.  To give my form this custom look I implement the Paint event of the form.  In the Paint event, I first load the image. Here I’m doing it from the image resource.  You could also add the image as a file in the project and create the image from that file.

The code below will always resize the image to fill the window.  It changes a few settings to improve the quality of the resizing.  Since we above set our window size to 128 x 128, the same as the image, no resizing will be needed.  To see the effect of this, you can change the size of the window to a different value and the image will be scaled appropriately.

        private void SkinnedWindow_Paint(object sender, PaintEventArgs e)
        {
            // Get Image from resources
            using (Image folderImage = Resources.Network)
            {
                // Set to high quality and draw image onto background
                e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                e.Graphics.DrawImage(folderImage, 0, 0, Width, Height);
            }
        }

We’re almost there.  If we run the application now our window appears.  We see our graphic, but they gray background from the form still shows.

clip_image006

Our last step is to get rid of the form background. We do this by setting the background color of the form to a know value. By default it is set to the Control value which can be changed by the user if they customize the appearance of Windows or use a Windows Theme. Since we want our form background to always be transparent we’ll change this to a known value. The form property we need to change is BackColor and here I’m changing the value to white.

clip_image007

Next we want to set the TransparencyKey property to match this new BackColor property. This property tells Windows to treat any part of the form that is this color as transparent and let whatever lies under it show through.

clip_image008

After this change when we run our application, we get a nice transparent window that looks just like our image. Below you can see the image placed on top of Visual Studio 2010. Notice that the transparent parts of the image are not considered part of the form. If we right click or left click and drag in the top right area just above the printer, it does not register as a click on our form and will bring up the application behind ours.

clip_image009

You can download a sample project with this code for VS 2010 .

Powered by WordPress