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 30, 2016

Article Published: Best Image Editors for OS X

Filed under: article — Tags: — Bill Morefield @ 8:57 pm

Recent article of mine published on Best Image Editors for OS X at raywenderlich.com.

February 5, 2016

Articles on Markdown and Paintcode

Filed under: Uncategorized — Bill Morefield @ 10:42 am

Two recent articles of mine published on the RAYWENDERLICH site. From earlier this week an article on the Top Five OS X Markdown Editors. From back in November a review of Paintcode.

January 22, 2014

Cisco ASDM gives “Missing required Permissions manifest attribute in main jar” Error

Filed under: Cisco — Tags: , — Bill Morefield @ 4:45 pm

Java pushed out a new update recently that implemented a change that had been warned about for a while. by default it now no longer allows running apps that are unsigned, self-signed, or without permission attributes.

This includes Cisco ASDM manager. The quick fix (other than Cisco adding the missing permission attributes file) is to add the web address where ASDM is accessed as an exception. You can do do this in Java Settings control panel. This is reached under Window by the Java option under Control Panel.

There select the Security tab and click the Edit Site List… button next to the Exception Site List. Here add the URL to the firewalls that you access with ASDM. After doing this, ASDM will connect and work again normally.

Interestingly enough given Java’s sudden concern about my security, it still asks to install the Ask Toolbar every update….

More info on the change at http://www.java.com/en/download/help/java_blocked.xml

Powered by WordPress