Git Product home page Git Product logo

sadconsole's Introduction

SadConsole Logo

Chat on discord NuGet

SadConsole is a C#-based .NET cross-platform terminal, ascii, console, game engine. It simulates these types of programs and with it you can make ascii-styled games for modern platforms. At its heart, SadConsole is really a giant tile-based game engine. However, its object model is conceptually similar to a traditional console app.

While SadConsole is a generic library that doesn't provide any rendering capabilities, "host" libraries are provided that add renderers to SadConsole. The two hosts provided by this library are for SadConsole.Host.MonoGame and SadConsole.Host.SFML. When adding a host library to your project, you don't need to reference the base SadConsole package. If you use MonoGame, you'll also need to add a rendering NuGet package, such as MonoGame.Framework.DesktopGL.

SadConsole currently targets .NET 6, .NET 7, and .NET 8

For the latest changes in this release, see the notes below

Features

Here are some of the features SadConsole supports:

  • Show any number of consoles of any size.
  • Uses graphical tile-based images to build out an ASCII-character font with support for more than 256 characters.
  • Fonts are simply sprite sheet tilesets tied to ascii codes, you can use full graphical tiles if you want.
  • Use more than one font file. However, each console is restricted to a single font.
  • Full GUI system for interactive controls such as list boxes, buttons, and text fields.
  • Importers for DOS ANSI files, TheDraw text fonts, RexPaint, and Playscii.
  • Animated consoles and instruction system to chain commands together.
  • String encoding system for colors and effects while printing.
  • Entity support for drawing thousands of movable objects on the screen
  • Translating images to text-blocks.
  • Keyboard and mouse support.
  • Highly customizable framework.

String display and parsing

string pic

GUI library

GUI library pic

Scrolling

scrolling console

Example startup code

using Console = SadConsole.Console;
using SadConsole;
using SadConsole.Configuration;
using SadRogue.Primitives;

Settings.WindowTitle = "SadConsole Examples";

// Configure how SadConsole starts up
Builder startup = new Builder()
    .SetScreenSize(90, 30)
    .UseDefaultConsole()
    .OnStart(Game_Started)
    .IsStartingScreenFocused(true)
    .ConfigureFonts(true)
    ;

// Setup the engine and start the game
Game.Create(startup);
Game.Instance.Run();
Game.Instance.Dispose();

void Game_Started(object? sender, GameHost host)
{
    ColoredGlyph boxBorder = new(Color.White, Color.Black, 178);
    ColoredGlyph boxFill = new(Color.White, Color.Black);

    Game.Instance.StartingConsole.FillWithRandomGarbage(255);
    Game.Instance.StartingConsole.DrawBox(new Rectangle(2, 2, 26, 5), ShapeParameters.CreateFilled(boxBorder, boxFill));
    Game.Instance.StartingConsole.Print(4, 4, "Welcome to SadConsole!");
}
Imports SadConsole
Imports Console = SadConsole.Console
Imports SadConsole.Configuration
Imports SadRogue.Primitives

Module Module1

    Sub Main()

        Dim startup As New Builder()

        ' Configure how SadConsole starts up
        startup.SetScreenSize(90, 30)
        startup.UseDefaultConsole()
        startup.OnStart(AddressOf Game_Started)
        startup.IsStartingScreenFocused(True)
        startup.ConfigureFonts(True)

        ' Setup the engine and start the game
        SadConsole.Game.Create(startup)
        SadConsole.Game.Instance.Run()
        SadConsole.Game.Instance.Dispose()

    End Sub

    Sub Game_Started(sender As Object, host As GameHost)

        Dim boxBorder = New ColoredGlyph(Color.White, Color.Black, 178)
        Dim boxFill = New ColoredGlyph(Color.White, Color.Black)

        Game.Instance.StartingConsole.FillWithRandomGarbage(255)
        Game.Instance.StartingConsole.DrawBox(New Rectangle(2, 2, 26, 5), ShapeParameters.CreateFilled(boxBorder, boxFill))
        Game.Instance.StartingConsole.Print(4, 4, "Welcome to SadConsole!")

    End Sub

End Module

Latest changes

v10.4.0 (03/31/2024)

New versioning system. Versions for SadConsole will be in the following format: [all libs major].[all libs minor].[individual lib revision]

When patches come out for the indvidual libraries, the X in 10.0.X would increment. These would be like host updates, or the extended library, but not public facing changes in SadConsole itself. If SadConsole itself updates, the X in 10.X.0 would increment. All libraries would increment with SadConsole, and the individual lib revisions would reset to 0. The X on X.0.0 would indicate a major change to SadConsole with most likely a lot of bigger breaking changes.

That said, SadConsole is resetting all versions to v10.4.0 for this release. From now on, the new versioning system is in place.

  • [Breaking] A minor breaking change. If you were creating your own IConfigurator startup configs, the Run method's parameter changed from Game to GameHost.

  • [Core] Added Components.Overlay which displays a surface on top of an existing console/surface object as a top layer.

  • [Core] Bug: Font.OnFontChanged wasn't actually being called. It is now.

  • [Core] Added Coroutine NuGet library. This is included now with SadConsole.

  • [Core] Added CoroutineHandlerComponent which is a manager that you can add to an object and coroutines to.

  • [Core] Cursor.PrintCoroutine which prints as a coroutine, pausing at each character.

  • [Core] Instructions.DrawString updated to use Cursor.PrintCoroutine which lets it pretty print word breaks.

  • [Core] XML docs didn't genereate correctly for the last build.

sadconsole's People

Contributors

agitperson avatar amaes1 avatar arxae avatar benhewins avatar chris3606 avatar darrellp avatar enyim avatar erictuvesson avatar eropple avatar failmelon avatar gitter-badger avatar gpugnet avatar ihaveastrongpassword avatar joesunley avatar kaev avatar ltli0n avatar philipbawn avatar qbytx avatar rychup avatar thraka avatar ven0maus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sadconsole's Issues

gameTime available to Console.Update()

I noticed that in the sample games, the gameTime is figured out manually inside the custom console classes. Is there a reason it can't be passed down to the consoles as a parameter?

The Engine receives it in its Update method. It could pass it to the ConsoleRenderStack.Update, which would then pass it to the individual consoles' update methods.

It seems like any game and console would benefit from having the gameTime available. Was it a conscious choice to not include it? Maybe to simplify it?

If not, I could make the change and submit a pull request.

Entity clean up

Look more closely at the design of Entity, Animation, and Frame classes to try and clean things up.

Mouse position not updated

I have been trying to get mouseinput to work, but i only get valid values for the ScreenLocation.
Attached is a screenshot which shows the values in the following format: ConsoleLocation - ScreenLocation - WorldLocation - Console (from MouseInfo)

image

I have put my code in a repository because i don't know where the issue lies. The repository can be found HERE

I check for mouse updates in the GameScreen class.

In this project i used the 2.5.0.0 Nuget package.

Support GamePads

Before the rewrite finishes, gamepad support for the input system should be added.

Format exception in ParseCommandBlink

Hello Thraka.
Found some format exception in DemoProject while run app using os with not english default culture.
Problem in ParseCommandBlink class in double.Parse function, because it use culture-specific dot.
Suggest an option to fix error - add format provider like
double.Parse(parametersArray[1], System.Globalization.CultureInfo.InvariantCulture);
os windows 10

System.FormatException: Входная строка имела неверный формат.
   в System.Number.ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt)
   в System.Double.Parse(String s)
   в SadConsole.StringParser.ParseCommandBlink..ctor(String parameters, ColoredGlyph[] glyphString, ParseCommandStacks commandStack, SurfaceEditor surfaceEditor) в D:\my\SadConsole\src\SadConsole.Shared\StringParser\ParseCommandBlink.cs:строка 22
   в SadConsole.ColoredString.Parse(String value, Int32 surfaceIndex, ISurface surface, SurfaceEditor editor, ParseCommandStacks initialBehaviors) в D:\my\SadConsole\src\SadConsole.Shared\ColoredString.Commands.cs:строка 81

Pretty simple small contributing to the interesting library.

Effects need to be looked at

How should effects be managed? V3 has an effects manager but it's sort of disconnected from the SurfaceEditor class. Perhaps the SurfaceEditor class should allow you to attach an effects manager? Since a console inherits from SurfaceEditor now, it would have support for effects like the pre nuget versions did.

REXPaint IndexOutOfBoundsException

Hi, finally back to trying to get a game going and am re-familiarizing myself with your library. I updated from nuget tonight (4.1.2-pre7) based on some interesting looking stuff from reddit.

Tonight I decided to test the REXPaint integration. I created a simple file using REXPaint v1.03 (attached).

I tried to create a simple console class that includes the the following code in the constructor:

            Image InputTemplate;
            string inputPath;

            // Load REXPaint Template
            inputPath = ConsoleConstants.RexPaintFilePath + "InputFrame.xp";

            using (FileStream fs = File.OpenRead(inputPath))
            {
                InputTemplate = Image.Load(fs);
            }

            // Write REXPaint image to this consoles surface
            this.TextSurface = InputTemplate.ToTextSurface();

I get the following exception when calling ToTextSurface():

ArgumentOutOfRangeException was unhandled HResult=-2146233086 Message=Specified argument was out of the range of valid values. Parameter name: index ParamName=index Source=SadConsole.Core.Windows StackTrace: at SadConsole.Consoles.LayeredTextSurface.SetActiveLayer(Int32 index) at SadConsole.Consoles.LayeredTextSurface..ctor(Int32 width, Int32 height, Font font, Int32 layers) at SadConsole.Consoles.LayeredTextSurface..ctor(Int32 width, Int32 height, Int32 layers) at SadConsole.Readers.REXPaint.Image.ToTextSurface()

The InputTemplate object has the following values:

-       InputTemplate   {SadConsole.Readers.REXPaint.Image} SadConsole.Readers.REXPaint.Image
        Height  0x00000003  int
        LayerCount  0x00000000  int
-       Layers  Count = 0x00000001  System.Collections.ObjectModel.ReadOnlyCollection<SadConsole.Readers.REXPaint.Layer>
-       [0] {SadConsole.Readers.REXPaint.Layer} SadConsole.Readers.REXPaint.Layer
+       Cells   Count = 0x000000f0  System.Collections.ObjectModel.ReadOnlyCollection<SadConsole.Readers.REXPaint.Cell>
        Height  0x00000003  int
        Width   0x00000050  int
+       Non-Public members      
+       Raw View        
        Version 0x00000001  int
        Width   0x00000050  int
+       Non-Public members      

InputFrame.zip

[Request] Embeddable into WPF form

The ability to embed the console window into a WPF form so native controls can be used in cases where the SadConsole.Controls package comes short in regards to ui complexity

UWP Windows 10 port

Wow, this project looks really awesome!
Any chance to get it ported for UWP Windows 10?

I'll be glad to help (create and provide patch or fork your project) but I'm new in SadConsole and MonoDevelop (but not in Windows Phone or UWP), just built the solution and enjoyed the pretty nice demos. So, if you can provide me some tips, it will be great!

hiding system mouse cursor

My humble apologies, but I seem to be unable to hide the system mouse cursor. I'm tracking the mouse position via an updating GameObject, but am still seeing the system mouse cursor.

Is there an Engine flag or call to hide this?

Window Resizing

What is the proper way to handle window resizing?

Window.AllowUserResizing = true;

Setting that to true, the window re-sizes fine but the mouse pointer gets offset.

Is there something I need to do in the Window_ClientSizeChanged event?

VirtualCursor.AutomaticallyShiftRowsUp is off-by-one.

(I'm using F#, so I don't have an easy test case).
If I make a window, say, 10x10 - then write 9 rows of 10 characters, all is good.

If VirtualCursor.AutomaticallyShiftRowsUp = true and I try to write 10 rows, the first 9 rows are all shifted up one - the top row is lost, and the bottom row of the console is not drawn to.

Is this intended behaviour or just off-by-one?

Nuget issue with SadConsole.Core package when .NET < 4.6

When installing the SadConsole.Core package through nuget, no references are made (the font files are added correctly).

When trying to add for example the SadConsole.GameHelper package, i receive the following error:
image

When changing my project to use .NET 4.6, it installs correctly.
So when the project is < 4.6, then the package installation fails silently

EntityBase constructor base() call missing parameter (1,1) on wiki

Project files have the correct version, its the text tutorial having the issue

Also the player constructor is using '@', when EntityBase expects an integer. this is in both the wiki and downloaded Project files

Ok, dont know if I should open up a new issue for all of these, but found another error.

At the end of part 2 you tell to add IsTileWalkable method to MapConsole.cs but it should go into Map.cs

Font Handling Enhancements

I wasn't sure if this is something that should be an Issue or if I should have made a pull request instead.

In Font.cs on line 116 (and again on 303, 307, 308) you reference Engine.FontColumns (which has a constant value of 16). Can that be switched to a Columns property that works identical to Rows from FontMaster?

Also is it possible to include a constructor for FontMaster to initialise from a Texture2D (including parameters for the character width/height and font name)?

My aim with both changes is to allow me to pre-process a font file dynamically and allow me to support more layout formats, without having to convert the files (support the layouts from TCOD for instance). All the processing would happen on the Texture (which can be either SFML or MonoGame based), which I can then feed into the FontMaster.

Sorry if this should be a PR instead, first time posting here

Font does not exist?

fresh download, and when using the startup guide Program.cs for(both mono and SFML), I get the following error:
`An unhandled exception of type 'System.Exception' occurred in SadConsole.Core.Windows.dll

Additional information: Font does not exist: IBM.font`

Line.Draw(IEnumerable<Cell> cells) doesn't handle effect

When the effect engine changed from being managed by a cell to being managed by a cellsurface, the Line.Draw(IEnumerable cells) method wasn't updated.

This method should have the a 2nd parameter which is the cellsurface being used. If not passed, do not process effects.

Another helper for this would be a method on the cellsurface, something like ResyncEffects(Cells) where you pass in a collection of cells, and it examines them for effect information and makes sure the cellsurface effect manager knows about their state and syncs with it.

Positioning a LayeredConsole is not the same as positioning a non-LayeredConsole

Same person as on Reddit.

So in the game i'm working on, i need to have a ControlsConsole on the left side. And the map console (a LayeredConsole) should be moved to the right. But it doesn't happen. I have setup a example case.

The 2 consoles in this example should be slightly staggerd. The blue console (a LayeredConsole) is set to position 10, 10. The red console (a ControlsConsole) is set to 15, 15. But as you can see on the screenshot, only the red console is staggered.

Screenshot:
me0udxq

The code is pretty simple:
Program.cs

class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            using (var game = new MyGame())
            {
                game.Run();
            }
        }
    }

MyGame.cs

class MyGame : Game
    {
        GraphicsDeviceManager graphics;

        public MyGame()
        {
            graphics = new GraphicsDeviceManager(this);

            var sadConsoleComponent = new SadConsole.EngineGameComponent(this, () =>
            {
                SadConsole.Engine.Initialize(GraphicsDevice);

                using (var stream = System.IO.File.OpenRead("Fonts/IBM.font"))
                {
                    SadConsole.Engine.DefaultFont = SadConsole.Serializer.Deserialize<SadConsole.Font>(stream);
                }

                SadConsole.Engine.Fonts.Add(SadConsole.Engine.DefaultFont.Name, SadConsole.Engine.DefaultFont, true);

                int width = 50;
                int height = 25;

                SadConsole.Engine.DefaultFont.ResizeGraphicsDeviceManager(graphics, width, height, 0, 0);

                var con1 = new Console1(1, 25, 25) { Position = new Point(10, 10) };
                var con2 = new Console2(25, 25) { Position = new Point(15, 15) };

                SadConsole.Engine.ConsoleRenderStack.Add(con1);
                SadConsole.Engine.ConsoleRenderStack.Add(con2);
            });

            Components.Add(sadConsoleComponent);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            base.Draw(gameTime);
        }
    }

    public class Console1 : SadConsole.Consoles.LayeredConsole
    {
        public Console1(int layers, int width, int height) : base(layers, width, height)
        {
            CellData.DefaultBackground = Color.Blue;
        }
    }

    public class Console2 : SadConsole.Consoles.ControlsConsole
    {
        public Console2(int width, int height) : base(width, height)
        {
            CellData.DefaultBackground = Color.Red;
        }
    }

Redo serialization for all class types

Serialization is currently a mix of intraclass and exterclass systems. All should be moved to exterclass with intraclass interfaces for load and save.

Virtual Cursor should allow you to set a sub rect bounds

Problem

Right now the virtual cursor uses the entire console surface for editing. This doesn't work well on console sub types such as the window. The window has a border and title around the inner edge of the console. The virtual cursor would write over that.

Solution

By defining a region the cursor uses, you can limit the axis the cursor is allowed to enter. This means line wrapping can happen before the end of the console, and the carriage return will put the cursor within the set bounds instead of 0.

Another feature that could be added is the ability to shift the region instead of the entire console.

Unable to add SDL2.dll to Visual Studio 2017 project

Admittedly I'm a bit new to C# development, but in following your tutorial, I was unable to add any SDL2.dll file to my VS 2017 project. I tried the one from your link, as well as the 32-bit and 64-bit DLLs from the SDL2 site directly. Every time I get the message:

"A reference to <...the SDL2 file path> could not be added. Please make sure the file is accessible, and that it is a valid assembly or COM component."

Also tried messing with the .NET Framework version, and even trying the sdl2 Nuget package, but nothing worked.

NuGet porting?

Hi!, great library! Is possibile to update to monogame 3.2 and publish to NuGet?

Thank you!!

Subconsoles

I'd like to do something like the RogueSharp tutorial, where I have separate consoles for the map, message log etc. that are all indepent of one another, and drawn on separately. Whats the best way to achieve this?

Porting to OS X/Linux

Hey--

So as per our brief chat on Twitter, I think this library is pretty fantastic; I'm evaluating a few solutions and I think this might scratch my itch for some prototyping I want to get done. I work primarily on a Mac these days, though, so I'd like to look into porting this.

As it currently stands, there are hard deps in all projects on MonoGame.Framework. Which is cool, except (to the best of my knowledge) that means we have either a combinatoric explosion of project files (SadConsole.Core.Windows, SadConsole.Core.MacOS, etc.) or project files rely on external settings and so can't be manipulated in Visual Studio without those settings being destroyed (been there, swore at that).

What I'm wondering about is whether or not it makes sense to build this as a PCL, maybe unifying the various subprojects into one or two, and expecting the user to link the correct version of MonoGame. This was illuminating to me the first time I tried it:

http://www.craftworkgames.com/blog/day-6-running-with-monogame-portable/

REXReader not displaying correctly

@Thraka Thanks for the extensive library. I'm considering making a procedurally generated text rpg and your library has a lot of nice options. I'd like to develop a few screens (menu, game screen, etc.) in REXPaint and then import them to add values. To test, I made a simple two layer REXPaint.xp image (attached), using REXPaint 0.99r9.

Rendering using REXReader does not produce the same result as the opening in REXPaint. I used the following code:

SadConsole.Readers.REXPaint.RexReader reader = new SadConsole.Readers.REXPaint.RexReader("...\test.xp");
var tileMap = reader.GetMap();            
var console = tileMap.ToLayeredConsole();

SadConsole.Engine.ConsoleRenderStack.Add(console);
SadConsole.Engine.ActiveConsole = SadConsole.Engine.ConsoleRenderStack[0];

Am I missing a step or is it something else (magenta vs transparent)? Thanks again.
test.zip

Example project(s?) don't work

I just tried checking downloading the repo, opening the sln and running the Castle example. It breaks on MonoGameEngine:87 because MonoGameInstance hasn't been instantiated.

There are a number of Initialize methods and one of them does set MonoGameInstance. If you copy that line, MonoGameEngine:157, and paste it at the top of the Initialize method in use (MonoGameEngine:55) then Castle runs perfectly.

I've only tested this with Castle, but I suspect it affects the others too. It looks like there was some sort of oversight or flawed VC conflict resolution? Tested on Win 10, VS2015

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.