Game development on .NET

Getting Started with SadConsole

Getting Started with SadConsole
5 (100%) 1 vote
(Video Transcript)
Hi guys, welcome to .GAME. In this episode, we’re gonna take a break from our unity project to take a look at another engine. And to do that, I’ve been joined by Andy DeGeorge, the creator of SadConsole. Welcome Andy.

>> Well, thanks for having me.

>> Why don’t you tell us what SadConsole is?

>> Sure, maybe like a decade ago, I was looking at creating some old school text game engines, using .NET, using the console app, product template and things like that. And there’s limitations, you only get the 16 colors, you have smaller resolution, different things like that. So, I started investigating what other options are there for the .Net Developer to create sort of a old school ASCII text game using .NET as your language or framework. And I found a few things C++ based, with some C# shims, and wrappers and things like that and it never really felt like it was made for the .NET world to bring the .NET developer in and give him a library, him or her-

>> [LAUGH]

>> A library that they could really use and understand as a .NET developer. So I ended up creating my own, a long time ago and over the last few years, I’ve sort of made it public. And I’ve got a few users who are making little games and it just sort of went from there.

>> Awesome, yeah, I saw it. It looks like you have a Reddit and you’re out on GitHub and all sorts of stuff. [CROSSTALK]

>> Yep, open source on GitHub. It’s the project that I do when I come home from work, and when I’m sleeping, I’m probably sleep coding somehow. And I’m always playing around with it, so-

>> Awesome.

>> Yeah, tell me.

>> So what do you have to show us today?

>> So I’m gonna just do a quick run through of how to create a project. And then just do some demos on how it works and explain sort of the backend parts of it as I go.

>> All right.

>> So, it’s on NuGet. There’s packages there for you to get. So it makes it really simple. Currently, it’s powered by MonoGame, which was based on XNA. It’s semi-Microsoft to run it through, I guess, I don’t know. So to create a SadConsole game, it’s really simple. We just start with a console app, which I just used to get the most basic references in ready to go. But what I do is I change it from a console app just to a Windows app. And so we don’t run and get the pop-up with the actual console in there. We should go do that. Set our startup, change it back to Windows. And now, we’re prepped, and we just need to add the NuGet packages for SadConsole, which will automatically add the NuGet packages for MonoGame. So let’s go down there, Install, yep. And let it do its thing. So when you install the NuGet package, you’ll automatically get a pop-up that goes to the Wiki for the GitHub source code, which gives you a sort of a quick run down of what the stuff you just did.

And then a boilerplate code to put in your program that will just get everything setup from MonoGame and SadConsole. So we’ll just go do that right here. And copy that, put that in. So it’s as simple as that. You just add the NuGet package. It goes right in little bit of startup code and you’re ready to go. So let’s run the app real fast and that’s it. So this is what the little starter tutorial gives you is it gives you a SadConsole game that just prints some stuff onto it.

>> Okay.

>> So let’s dive in a little bit to customizing it. First off, the NuGet package installs a font, which is just a JSON definition file that sort of describes how we use these image files to create console text, right? So looking at this, it’s just your sort of standard 256 character, classic DOS terminal font. And it kind of fakes, it’s not really a console. It really is a GPU-bound game that emulates how a console works.

>> That’s right because I think I saw a while back you had posted, I want to say I saw it on Twitter, but it was a 3D representation of a cube, right, that was being mapped to-

>> Yeah, yeah, yeah. So it is MonoGame. It’s running on the GPU so you get the performance. You get high performance. You get coloring alpha channels, all that type of stuff. But you also have the full backend of MonoGame so you get full 3D seam rendering. I’ve been doing a lot of enhancements lately to how SadConcole works so it integrates better into an existing MonoGame game. So for example if you have a 3D world and there’s a computer terminal sitting somewhere, you can have SadConsole running and visual on the computer terminal and then somehow have a character interact with the terminal so [CROSSTALK]

>> It lets you do some neat stuff. Of course, I know this isn’t a one-to-one comparison but my mind completely went to Dave at tentacle and how he used to be able to hook up the console to play, what was it, Maniac Mansion?

>> Yes, the first.

>> So you could really create some pretty neat hybrids.

>> Yeah, yeah. So I’m working more and more on making sure that integration works. I’ve just, generally from the start, been more about focusing everything on making a SadConsole game.

>> Yeah.

>> It’s dedicated, that’s all it does. That’s what your app or game does. So now I’m expanding more into integration with other games.

>> Awesome.

>> Okay, so back to the code. What we’ll do is, we’re gonna go into the updated. There’s three entry points for your game on this. There’s the EngineStart, which is basically initialization code. This is what you do right when the engine’s initialized. It’s ready to go. But we haven’t drawn anything to the screen and we haven’t done the game update loop yet. Then there’s the engine updated, which your game updated loop. This is where your game logic would go and things like that. So what we’ll do is we’ll jump right into there and we’ll do a check to see if the escape key is hit, and if escape is hit, we quit. Lets see, Engine, keyboard is key released, and then we’ll hit up escape. And then we’ll go SadConsole engine autogame instance and we tell it to exit, exit.

>> So your lack of brackets probably just angered about half the people watching and made the other half quite happy.

>> I don’t know why you would use brackets.

>> [LAUGH]

>> That makes no sense to me at all. I do come from a VB background. I am more than happy to put if’s and and if’s in everywhere in my code. We’ll do another one. Actually, what we’re gonna do is back up in init, we’re gonna toggle full-screen mode by default. So as you saw when we ran, it ran in a window. And so we’ll just tell SadConsole we want to go full-screen. Now, MonoGame has its own built-in full-screen but what this does, is it actually does some automatic stretching and making sure your ratios are right so the full-screen doesn’t stretch the width too wide. So the characters don’t look narrow or different things like that. So SadConsole takes care of some of that logic for you. So if we run that, there we go. So then we hit escape, and we’ve quit. Okay, so next in this Engine start code, when SadConsole initializes, we get a console by default. So this console class right here is not the system.console class. It’s the SadConsole class, just for clarification.

So if SadConsole creates you one of these by default, fills the screen, and you’re just ready to go. You can print to it, you can do whatever you want. So we will take that console and we will make the, Cursor show and we’ll position it right below where we wrote that, where we printed that text. We’ll go one, three, to make it look nice. So we’ll run that again. And now heres our cursor.

>> So now we can say, Hello .GAME! You’re awesome!

>> [LAUGH]

>> Right? So we have a full cursor that we can move around the screen. And type, that’s the interaction. You can turn off that stuff cuz normally you don’t want the user of your game, you’re managing all the printing and stuff for them. But there may be at some point where you want some input. Type in your name, type in your whatever, things like that. So you have full control of that. Now we have the full color spectrum to work with. So another thing we’ll do is we’ll say when we hit the F1 key. We’ll randomly choose a color for our cursor to print as. So F1, and then we’ll set, we’ll get our defaultConsole that we used. So we’ll go SadConsole.Engine, the ActiveConsole, the VirtualCursor, the printAppearance. And then we’ll set the Foreground to, actually instead of just choosing a color we’ll do a random. So I have a bunch of extension methods, helper stuff that I’ve put in like doing gradient colors across text and all sorts of stuff like that. So I will use the static class to get an instance and then I have a just give me a random color.

And SadConsole has its own instance of the random class by default, so we’ll just use that. So now we’ll run that, we’ll say, Hello, we’ll hit F1. And now we have a new color, is, I’ll keep hitting it, a, new color, right? So here we go, we have cool color, cursor printing, things like that. So let’s go into when you’re creating a game usually you have a big map. The character scrolls around the map, things like that. So what we’ll do is we’ll go back up to our defaultConsole and we’ll change the text surface that’s in that background. So the way SadConsole split things out, a console type is a manager. It has your cursor, it has where is it positioned on a screen, input handling for keyboard from mouse, it does all that wrapper stuff. But what it uses behind the scenes is what I call a text surface. Now the text surface is where the actual data is for all of the characters, the colors, the cell. Basically each individual cell that goes in there. You can set the text surface to smaller, bigger, do whatever you want.

And the console is still the same instance that’s managing the text surface. So what we’ll do is in the code we will go back to our text surface, and we’ll change it to a new one. So if we go TextSurface = new TextSurface(). Now instead of our screen size, we had done an 80 by 25, a classic DOS prompt size. We will do something bigger, so let’s go 200 by 200. Now that’s actually going to render 200 by 200 cells, right. So I think that’s 20,000 characters on the screen. We don’t obviously want to render that many characters cuz our screen size is only 80 by 25. So we can set the RenderArea of the TextSurface to a smaller size. So let’s go, we’re gonna start at the top left corner, and we’ll go 80 by 25. And I created, when you’re designing and placing consoles around, I created some helper stuff to help fill out your-

>> Random garbage. [LAUGH]

>> TextSurface with a bunch of stuff so you can sort of see where the balance, what’s going on.

>> Right.

>> So now we have a bigger than life TextSurface sitting there with random stuff. Now obviously we can’t see off the sides cuz it’s off the screen. So let’s see, let’s kill our cursor. And what we’ll do is, we’ll go back down to our input. And we’ll say when the right key is hit, we’re going to tell the TextSurface.RenderArea to move. So instead we’ll do, let’s go to a new line. Let’s see, the existing, we want the existing actually just to make this go quicker and easier. And to make the bracket people happy we’ll do this. And I’ll just go, so it’s easier for us to manage, there we go. Okay, so now we’ll say it equals the renderArea.X keyboard. X + 1, renderArea.Y and renderArea.Width, renderArea.Height. So that we’re not changing or skewing how much we’re showing on the screen and we’re moving. So running that now if we push the right key.

>> We see scrolling and yeah I did on release so it’s as many times as I push it. So we’ll change that, instead of when the key is released, we’ll just go IsKeyDown. So now as we hold it down, it will move and scroll. Now it’s a lot smoother on my screen versus I don’t what comes on as a video, let me see-

>> [LAUGH]

>> But anyways, yep, so we can have a bigger area, a big map. And then as our character walks around it scrolls, involves the character, things like that.

>> The typical map, stop.

>> Traversal.

>> Traversal. Okay, so now let’s get into a little more advanced. What we’ll do is we’ll take the console we have. And let’s do two consoles on the screen at once.

>> Whoa, whoa, whoa, whoa-

>> It’s crazy talk, two consoles, no way, and who cares, let’s do it.

>> [LAUGH]

>> Okay, let’s do, we’re going to change our console to be our 80 by 25 like normal. So this is a normal sized console being displayed on the screen. Or at least the TextSurface the console is showing you is our normal full screen size. And actually we’ll just use the one that’s existing [INAUDIBLE]. Okay, so just so you can see what we got, what we’re starting with. Back to our default tutorial, here’s the console. So instead what we’ll do is we’ll create a whole new console. So console2 = new Console(). And we gotta give it a size, let’s see 80 by 25. So when you create a new console, it creates a TextSurface behind the scenes back in the console at this size. In addition to that, we could instead use an existing TextSurface that already exists. So we already have one in the default console, so we’ll just reuse that. So if we say console2.Position and let’s move it, let’s say, halfway down the screen. new Point() and that would be 0 and what are we, 25, so 13’s about half.

So if we go halfway down, now when we run this we see nothing, no change.

>> It’s so beautiful.

>> Yeah, I know, the classic tutorial, lead your users down the wrong path and show them how they didn’t do something right.

>> [LAUGH]

>> So instead what we’re gonna do is we’re going to actually, we need to tell SadConsole that this console we created, we want in the rendering pipeline. We want through the, to go through the processor, the backend processing systems and all that type of stuff. So we tell the engine we have a property or a field called ConsoleRenderStack. So these are all the consoles that are gonna be rendered and processed for input each pass. So we add that, display it and there we go. So we have the same text data In the back end, being displayed twice on the screen.

>> So it’s a practical usage of this.

>> Well, so you wouldn’t normally print the same exact text data. But you could do something where you have a mini map, and you can change the fonts. So the text data is, doesn’t rely on the font, that’s graphic that’s backing it. So you can say, this console uses this font, this console uses a different font. And you can sorta use the same text data on the backend and things like that. So you could duplicate essentially one whole console into a really small console or to a bigger console or something like that. And mirror the data on the screen somewhere. So let’s quit that, now what we’ll do is instead of doing the exact same data. Let’s do two separate pieces of data. So the first thing we will shrink the existing console’s TextSurface to the halfway. I’m gonna do TextSurface, let’s say 80 width, and let’s say the top one will be 12. And, that print doesn’t care. Let’s do this one, get a new one. This is 80 by 13 to fill the rest of the screen. And I think this needs, does this this need to go?

This needs to go at 12. All right, so console two is positioned there. Console one is positioned at the top. And we need to tell console 2, hey, we wanna print stuff too. So we’ll print at the same 1, 1, and we’ll print hello from console 2. Now when we assigned a new text surface to our default console, we cleared the data that was there. So if we had left that print statement above that said welcome to sad console, it would’ve been cleared out, because we just changed the backing data. So we need to do a print statement here also, with the new tech surface as the back. 1, 1, hello from console 1. Now [INAUDIBLE] clean the code up a bit space out, and let’s run that. There we go. So now we actually have two different consoles now. You can’t really see where they are, right? Because it’s all black. What we’ll do is before we print, we’ll do a fill. So let’s go foreground, I don’t know, color

>> Blue.

>> Blue, and a background, a contrasting background to blue. Yellow.

>> Yeah.

>> Color that yellow, and we’ll fill it with the zero character, which is nothing. And then the mirror effects. We can do mirror effects, like flip. You can flip the cell vertical or horizontal. So you can essentially create whole new character sets based off of existing character sets just by flipping and mirroring. And how about the bottom one, let’s do that one, too. We can do opposite, blue and yellow, or I mean yellow and blue. [INAUDIBLE] Yellow and blue.

>> It was sad how much excitement I had to contribute the word blue to that?

>> Blue, yeah.

>> Yay. [LAUGH]

>> So yep, so now we have two whole consoles so you could split the screen up, partition it out, message area, input, status of your character [INAUDIBLE], all sorts of stuff like that. So that’s sort of a basic run down of just how SadConsole works. It’s easy to get in to get programming. So this is the code where or I have a project that is on GitHub. There’s a bunch of source code on there. It’s examples, I use that in my test. Cuz it’s a little hard to write unit tests when you have to visually look at something and see, did the color actually work? You can test the back, but is it rendering the way it should render? So actually I always create a bunch of example consoles that demonstrate and validate the existing code base. And show anybody how to do something with SadConsole. So one of the things I do is, there’s another library called RogueSharp, which sort of adds a bunch of helper stuff like random dice, and map generation and stuff for whoever was making a rogue like game in C sharp.

So I coupled that with SadConsole, and created a little quick demo of walking your little character around. I randomly generated a map with line of sight, and stuff like that.

>> Awesome! So how long did this take you to put together?

>> Not too long. Here we found the little guy, yay. You’re supposed to hunt and find the little monster. So, it didn’t take too long for me, obviously. I know SadConsole very easily. So I, I know how to do everything I want in SadConsole. It was more of just learning the RogueSharp. How does that work with creating a level and stuff like that. So I’m looking to integrate more with RogueSharp and create more, or supplement each other as a good combination to make a Rogue like game. Yeah.

>> Awesome, so is this setting up two consoles then, left and the right?

>> Yep, yep, so this is two consoles. Obviously the left side, like we had done, is a view. A render view of the huge console in the back, and just displaying what’s should be visible as we move around.

>> Awesome, so you also have like a UI where you can kind of paint and draw things on, right? So in order to have that room and the stuff that you are kind of showing, you technically could draw out the maps if somebody didn’t want to randomly generate them, right?

>> Yes, yeah, I have one of my projects on there is just called a SadConsole editor, and it’s a GUI graphical editor to basically paint and draw consoles. Kind of like the old ANSI editor tools from the good old days. Power to my BBS people and so part of that actually, if we go with the GitHub, if we look at the GitHub repository, I have actually some demo screens that just sort of show doing things. So here’s an animation of. I have a whole GUI library that does buttons, scroll bars, list boxes, all sorts of stuff like that. And it does a bunch of theming stuff, so you can actually change the themes of all the controls to different colors. And it replicates across your entire library, or your game, stuff like that.

>> So, it’s really the notion of taking the old school, console style, ASCII games, and modernizing it, with buttons and, you know whatever. So you really, sky’s the limit, it sounds like in what you can do, and if I recall correctly, you even have like a whole sequence and animation kind of stuff set on the other?

>> Yeah, yeah I have on the. So the other library I’ve been working on is, now that SadConsole is pretty well baked, it works good. I’ve been working on a library to sort of help game makers, so for example. Creating entities that walk around the map, and that you can position relative to the map, and things like that. I’ve started working on a library, it’s just called Game Helpers or whatever, that handles all that type of stuff for you, so you don’t have to worry about that. And so part of that is an animation system. So if you, basically, it’s just a bunch of tech surfaces that are flipped based on time. And taking that and then wrapping that in a small console that doesn’t necessarily handle mouse integration, and stuff like that. That you can now have explosion that comes out, or things like that on the screen, and place them or destroy them as you need to and manage that type of stuff.

>> Awesome.

>> So it works on, it’s running on .NET. Runs on Mono, so it easily works on Mac and Linux, and I’ve been working on getting Android working better, but I just started looking at that. So learning, how does Android work with the assets, and getting the files in there. So I gotta write tutorials for that. And then I’ve been working on getting a universal app version, so that we can hit Windows 10 stores, and have fun with that. So I’m trying to get it on everything, and because it’s MonoGame, it should be on everything.

>> [LAUGH] Awesome. And are you looking for contributors?

>> I’ve always taken pull requests. I got a few issues here, mostly from me, but I have a few others. And that’s with the Android and the Universal Windows app stuff. Those are from people saying hey I’m trying to do this on here. I got some code. Here’s what’s kind of working, here’s what’s not working. And they’ve been contributing and helping out. So anybody who wants to do pull requests, I’m more than willing to get it in there, because any help is good help.

>> Awesome, all right, well, I’m assuming that’s all you have?

>> Yep, that’s it.

>> Okay.

>> Maybe we’ll come back for another one. And so some more stuff.

>> I’m gonna hold you to that.

>> And some fancy shmancy demos.

>> Awesome, I’ve seen some pretty neat stuff that’s been created with this. So I’m definitely excited, and you’re more than welcome to come back any time.

>> Okay.

>> All right, so thanks for joining us for this episode. As he mentioned, you can go ahead and get the project on GitHub to start creating your own games, or if you want to start contributing. It sounds like you can also open up issues and do pull requests to do that. There’s also a subreddit. Was it SadConsole?

>> Yeah, yeah, just SadConsole.

>> SadConsole.

>> Yeah, so I get a lot of pings on there from people who are asking questions. And usually when somebody has a question and they can’t figure something out, I go write an article on the wiki to demonstrate how to do that. And I have a, actually I have on the wiki, there is a, I think it’s about five part Rogue like making a Rogue like from scratch series. It’s not complete yet because I sort of, I get going on it and then I’m like that’s good enough for now. And I want to go work on the engine more, and do things like that so when people start bugging me about, hey when’s the next part, then I’ll probably write the next part.

>> [LAUGH] So bug him is what I’m hearing.

>> Yeah, yeah, no.

>> [LAUGH]


Read the video

In this episode, Andy De George joins us to talk about SadConsole. SadConsole is a MonoGame 3.5-based game library (using .NET 4.5) that provides an engine to emulate old-school console and command prompt style graphics. To start, we will look at how you get up and running within minutes. Then we’ll explore some of the basic functionality and principles such as working with multiple consoles, altering the text color and interact with inputs. 


  1. .GAME GitHub Repo
  2. SadConsole GitHub Repo
  3. SadConsole Editor GitHub Repo
  4. SadConsole SubReddit


dotGame is a blog dedicated to game development with a primary focus on .NET technology. The episodes will focus on tutorials, tips and tricks and interviews. All tutorial project files can be found on the .GAME GitHub repository. Have a topic you'd like to see covered? Great! You can request a topic by opening an issue on the GitHub repository or by emailing General feedback can also be directed to

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    1Code.Blog - Your #1 Code Blog