├── App.config ├── Core ├── MathF.cs ├── Enums.cs ├── Examples │ ├── Primitives.cs │ ├── ImageConverting.cs │ └── Raycasting.cs ├── ConsoleListiner.cs ├── NativeMethods.cs ├── Engine.cs └── ColorUtilites.cs ├── Readme.md ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── ConsoleGameEngine.csproj └── .gitignore /App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Core/MathF.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | 4 | namespace MaximovInk.ConsoleGameEngine.Core 5 | { 6 | public static class MathF 7 | { 8 | public static T Clamp(this T val, T min, T max) where T : IComparable 9 | { 10 | if (val.CompareTo(min) < 0) return min; 11 | else if (val.CompareTo(max) > 0) return max; 12 | else return val; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # ConsoleRenderingEngine 2 | - Can convert RGB colors to console colors , and back. 3 | - Can blend two console colors. 4 | - Can draw basic shapes. 5 | - Contain examples : raycasting , image loading and drawing primitives 6 | 7 | Screenshots: 8 | ![Raycasting](https://i.imgur.com/8xcIdZs.png) 9 | ![Image loading](https://i.imgur.com/ldrdkqR.png) 10 | ![Drawing primitives](https://i.imgur.com/LrdxRdA.png) 11 | 12 | Video: 13 | 14 | [![Watch the video](https://i.ytimg.com/vi/enq7hgUtuYI/hqdefault.jpg)](https://www.youtube.com/watch?v=enq7hgUtuYI) 15 | -------------------------------------------------------------------------------- /Core/Enums.cs: -------------------------------------------------------------------------------- 1 | namespace MaximovInk.ConsoleGameEngine 2 | { 3 | public enum Character : short 4 | { 5 | Null = 0x0000, 6 | Full = 0x00DB, 7 | Dark = 0x00B2, 8 | Medium = 0x00B1, 9 | Light = 0x00B0, 10 | } 11 | 12 | public enum COLOR : short 13 | { 14 | FG_BLACK = 0, 15 | FG_DARK_BLUE = 1, 16 | FG_DARK_GREEN = 2, 17 | FG_DARK_CYAN = 3, 18 | FG_DARK_RED = 4, 19 | FG_DARK_MAGENTA = 5, 20 | FG_DARK_YELLOW = 6, 21 | FG_GREY = 7, 22 | FG_DARK_GREY = 8, 23 | FG_BLUE = 9, 24 | FG_GREEN = 10, 25 | FG_CYAN = 11, 26 | FG_RED = 12, 27 | FG_MAGENTA = 13, 28 | FG_YELLOW = 14, 29 | FG_WHITE = 15, 30 | BG_BLACK = 0, 31 | BG_DARK_BLUE = 16, 32 | BG_DARK_GREEN = 32, 33 | BG_DARK_CYAN = 48, 34 | BG_DARK_RED = 64, 35 | BG_DARK_MAGENTA = 80, 36 | BG_DARK_YELLOW = 96, 37 | BG_GREY = 112, 38 | BG_DARK_GREY = 128, 39 | BG_BLUE = 144, 40 | BG_GREEN = 160, 41 | BG_CYAN = 176, 42 | BG_RED = 192, 43 | BG_MAGENTA = 208, 44 | BG_YELLOW = 224, 45 | BG_WHITE = 240, 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MaximovInk.ConsoleGameEngine 4 | { 5 | public class Program 6 | { 7 | [STAThread] 8 | private static void Main() 9 | { 10 | bool select = false; 11 | 12 | char Char; 13 | Engine e = new Engine(); 14 | 15 | while (select == false) 16 | { 17 | Console.WriteLine("Hello, this is examples.. Write 1 - raycasting ,2 - image loading,3 - primitives to play"); 18 | 19 | Char = Console.ReadLine()[0]; 20 | 21 | switch (Char) 22 | { 23 | case '1': 24 | e = new Raycasting(); 25 | select = true; 26 | break; 27 | case '2': 28 | e = new ImageConverting(); 29 | select = true; 30 | break; 31 | case '3': 32 | e = new Primitives(); 33 | select = true; 34 | break; 35 | default: 36 | break; 37 | } 38 | } 39 | 40 | e.StartLoop(); 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Общие сведения об этой сборке предоставляются следующим набором 6 | // набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, 7 | // связанные со сборкой. 8 | [assembly: AssemblyTitle("ConsoleGameEngine")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ConsoleGameEngine")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми 18 | // для компонентов COM. Если необходимо обратиться к типу в этой сборке через 19 | // COM, задайте атрибуту ComVisible значение TRUE для этого типа. 20 | [assembly: ComVisible(false)] 21 | 22 | // Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM 23 | [assembly: Guid("793982aa-527b-419e-a924-01da6da22212")] 24 | 25 | // Сведения о версии сборки состоят из следующих четырех значений: 26 | // 27 | // Основной номер версии 28 | // Дополнительный номер версии 29 | // Номер сборки 30 | // Редакция 31 | // 32 | // Можно задать все значения или принять номер сборки и номер редакции по умолчанию. 33 | // используя "*", как показано ниже: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Core/Examples/Primitives.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace MaximovInk.ConsoleGameEngine 4 | { 5 | public class Primitives : Engine 6 | { 7 | public Primitives(short width = 182, short height = 53, string Title = "Console engine", short fontw = 16, short fonth = 16, bool showFps = true) : base(width, height, Title, fontw, fonth, showFps) 8 | { 9 | } 10 | 11 | protected override void OnStart() 12 | { 13 | //Draw symbol from char 14 | DrawChar(0, 0, '#', 15); 15 | //Draw symbol from short 16 | DrawPixel(2, 0, (short)Character.Medium, (short) (COLOR.FG_BLUE | COLOR.BG_RED)); 17 | //Draw line 18 | DrawLine(1, 2, 3, 20, (short)Character.Full, (short)COLOR.FG_CYAN); 19 | //Draw line gradient 20 | DrawLineGradient(3, 2, 5, 20, (short)COLOR.FG_RED, (short)COLOR.FG_BLUE); 21 | //Draw text 22 | DrawText(4, 0, "This is text ..", (short)(COLOR.BG_YELLOW | COLOR.FG_BLUE)); 23 | /* 24 | Convert rgb color to ConsoleColor! 25 | */ 26 | COLOR cl; 27 | Character ch; 28 | ColorUtilites.GetConsoleColor(Color.Crimson, out ch, out cl); 29 | DrawRect(6, 2, 3, 3, (short)ch, (short)cl); 30 | //Draw rect 31 | DrawRect(11, 2, 4, 4, (short)Character.Full, (short)COLOR.FG_GREEN); 32 | //Draw cicrle 33 | DrawCircle(13, 15, 6,(short)'*', 12); 34 | //Draw triangle 35 | DrawTriangle(21, 41, 25, 0, 0, 25, (short)Character.Dark, (short)COLOR.FG_GREEN); 36 | 37 | FillRect(43, 0, 20, 20, (short)Character.Medium, (short)(COLOR.FG_YELLOW | COLOR.BG_BLUE)); 38 | 39 | Apply(); 40 | } 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Core/ConsoleListiner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using static MaximovInk.ConsoleGameEngine.Core.NativeMethods; 4 | 5 | namespace MaximovInk.ConsoleGameEngine.Core 6 | { 7 | public static class ConsoleListiner 8 | { 9 | public static event ConsoleMouseEvent MouseEvent; 10 | 11 | public static event ConsoleKeyEvent KeyEvent; 12 | 13 | public static event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent; 14 | 15 | private static bool Run = false; 16 | 17 | public static void Start() 18 | { 19 | if (!Run) 20 | { 21 | Run = true; 22 | IntPtr handleIn = GetStdHandle(STD_INPUT_HANDLE); 23 | new Thread(() => 24 | { 25 | while (true) 26 | { 27 | uint numRead = 0; 28 | INPUT_RECORD[] record = new INPUT_RECORD[1]; 29 | record[0] = new INPUT_RECORD(); 30 | ReadConsoleInput(handleIn, record, 1, ref numRead); 31 | if (Run) 32 | switch (record[0].EventType) 33 | { 34 | case INPUT_RECORD.MOUSE_EVENT: 35 | MouseEvent?.Invoke(record[0].MouseEvent); 36 | break; 37 | case INPUT_RECORD.KEY_EVENT: 38 | KeyEvent?.Invoke(record[0].KeyEvent); 39 | break; 40 | case INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT: 41 | WindowBufferSizeEvent?.Invoke(record[0].WindowBufferSizeEvent); 42 | break; 43 | } 44 | else 45 | { 46 | uint numWritten = 0; 47 | WriteConsoleInput(handleIn, record, 1, ref numWritten); 48 | return; 49 | } 50 | } 51 | }).Start(); 52 | } 53 | } 54 | 55 | public static void Stop() => Run = false; 56 | 57 | public delegate void ConsoleMouseEvent(MOUSE_EVENT_RECORD r); 58 | 59 | public delegate void ConsoleKeyEvent(KEY_EVENT_RECORD r); 60 | 61 | public delegate void ConsoleWindowBufferSizeEvent(WINDOW_BUFFER_SIZE_RECORD r); 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Core/Examples/ImageConverting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Drawing2D; 4 | using System.Drawing.Imaging; 5 | 6 | namespace MaximovInk.ConsoleGameEngine 7 | { 8 | public class ImageConverting : Engine 9 | { 10 | private Bitmap bitmap; 11 | 12 | public ImageConverting(short width = 460, short height = 150, string Title = "Raycasting", short fontw = 6, short fonth = 6, bool showFps = true) 13 | : base(width, height, Title, fontw, fonth, showFps) 14 | { 15 | } 16 | 17 | protected override void OnStart() 18 | { 19 | var b = new Bitmap("image.jpg"); 20 | bitmap = (Bitmap)FixedSize(b, Height, Width, false); 21 | 22 | for (int x = 0; x < bitmap.Width; x++) 23 | { 24 | for (int y = 0; y < bitmap.Height; y++) 25 | { 26 | Character ch = Character.Full; 27 | COLOR color = COLOR.FG_WHITE; 28 | ColorUtilites.GetConsoleColor(bitmap.GetPixel(x, y), out ch, out color); 29 | 30 | DrawPixel((short)x, (short)y, (short)ch, (short)color); 31 | } 32 | } 33 | 34 | Apply(); 35 | 36 | } 37 | 38 | public static Image FixedSize(Image imgPhoto, int Height, int Width, bool needToFill) 39 | { 40 | int sourceWidth = imgPhoto.Width; 41 | int sourceHeight = imgPhoto.Height; 42 | int sourceX = 0; 43 | int sourceY = 0; 44 | int destX = 0; 45 | int destY = 0; 46 | 47 | float nPercent = 0; 48 | float nPercentW = 0; 49 | float nPercentH = 0; 50 | 51 | nPercentW = (Width / (float)sourceWidth); 52 | nPercentH = (Height / (float)sourceHeight); 53 | if (!needToFill) 54 | { 55 | if (nPercentH < nPercentW) 56 | { 57 | nPercent = nPercentH; 58 | } 59 | else 60 | { 61 | nPercent = nPercentW; 62 | } 63 | } 64 | else 65 | { 66 | if (nPercentH > nPercentW) 67 | { 68 | nPercent = nPercentH; 69 | destX = (int)Math.Round((Width - 70 | (sourceWidth * nPercent)) / 2); 71 | } 72 | else 73 | { 74 | nPercent = nPercentW; 75 | destY = (int)Math.Round((Height - 76 | (sourceHeight * nPercent)) / 2); 77 | } 78 | } 79 | 80 | if (nPercent > 1) 81 | nPercent = 1; 82 | 83 | int destWidth = (int)Math.Round(sourceWidth * nPercent); 84 | int destHeight = (int)Math.Round(sourceHeight * nPercent); 85 | 86 | Bitmap bmPhoto = new Bitmap( 87 | destWidth <= Width ? destWidth : Width, 88 | destHeight < Height ? destHeight : Height, 89 | PixelFormat.Format32bppRgb); 90 | 91 | Graphics grPhoto = Graphics.FromImage(bmPhoto); 92 | grPhoto.Clear(Color.White); 93 | grPhoto.InterpolationMode = InterpolationMode.Default; 94 | grPhoto.CompositingQuality = CompositingQuality.HighQuality; 95 | grPhoto.SmoothingMode = SmoothingMode.HighQuality; 96 | 97 | grPhoto.DrawImage(imgPhoto, 98 | new Rectangle(destX, destY, destWidth, destHeight), 99 | new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), 100 | GraphicsUnit.Pixel); 101 | 102 | grPhoto.Dispose(); 103 | return bmPhoto; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /ConsoleGameEngine.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {793982AA-527B-419E-A924-01DA6DA22212} 8 | Exe 9 | MaximovInk.ConsoleGameEngine 10 | ConsoleGameEngine 11 | v4.7.1 12 | 512 13 | true 14 | true 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | AnyCPU 33 | true 34 | full 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 4 40 | false 41 | 42 | 43 | AnyCPU 44 | pdbonly 45 | true 46 | bin\Release\ 47 | TRACE 48 | prompt 49 | 4 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | False 81 | Microsoft .NET Framework 4.7.1 %28x86 и x64%29 82 | true 83 | 84 | 85 | False 86 | .NET Framework 3.5 SP1 87 | false 88 | 89 | 90 | 91 | 92 | PreserveNewest 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /Core/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace MaximovInk.ConsoleGameEngine.Core 5 | { 6 | public static class NativeMethods 7 | { 8 | public const int STDIN = -10; 9 | public const int STDOUT = -11; 10 | public const int STDERR = -12; 11 | public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); 12 | 13 | public struct COORD 14 | { 15 | public short X; 16 | public short Y; 17 | 18 | public COORD(short x, short y) 19 | { 20 | X = x; 21 | Y = y; 22 | } 23 | } 24 | 25 | [StructLayout(LayoutKind.Explicit)] 26 | public struct INPUT_RECORD 27 | { 28 | public const ushort KEY_EVENT = 0x0001, 29 | MOUSE_EVENT = 0x0002, 30 | WINDOW_BUFFER_SIZE_EVENT = 0x0004; //more 31 | 32 | [FieldOffset(0)] 33 | public ushort EventType; 34 | [FieldOffset(4)] 35 | public KEY_EVENT_RECORD KeyEvent; 36 | [FieldOffset(4)] 37 | public MOUSE_EVENT_RECORD MouseEvent; 38 | [FieldOffset(4)] 39 | public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; 40 | /* 41 | and: 42 | MENU_EVENT_RECORD MenuEvent; 43 | FOCUS_EVENT_RECORD FocusEvent; 44 | */ 45 | } 46 | 47 | [StructLayout(LayoutKind.Sequential)] 48 | public struct CONSOLE_SCREEN_BUFFER_INFO 49 | { 50 | public COORD dwSize; 51 | public COORD dwCursorPosition; 52 | public short wAttributes; 53 | public SmallRect srWindow; 54 | public COORD dwMaximumWindowSize; 55 | } 56 | 57 | [StructLayout(LayoutKind.Explicit)] 58 | public struct CharInfo 59 | { 60 | [FieldOffset(0)] 61 | internal char UnicodeChar; 62 | [FieldOffset(0)] 63 | internal short AsciiChar; 64 | [FieldOffset(2)] 65 | internal short Attributes; 66 | } 67 | 68 | [StructLayout(LayoutKind.Sequential)] 69 | public struct SmallRect 70 | { 71 | public short Left; 72 | public short Top; 73 | public short Right; 74 | public short Bottom; 75 | } 76 | 77 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 78 | public struct CONSOLE_FONT_INFO_EX 79 | { 80 | public uint cbSize; 81 | public uint nFont; 82 | public COORD dwFontSize; 83 | public int FontFamily; 84 | public int FontWeight; 85 | 86 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 87 | public string FaceName; 88 | } 89 | 90 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 91 | public struct CONSOLE_FONT_INFOEX 92 | { 93 | public uint cbSize; 94 | public uint nFont; 95 | public COORD dwFontSize; 96 | public int FontFamily; 97 | public int FontWeight; 98 | 99 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 100 | public string FaceName; 101 | } 102 | 103 | public struct MOUSE_EVENT_RECORD 104 | { 105 | public COORD dwMousePosition; 106 | 107 | public const uint FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001, 108 | FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004, 109 | FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008, 110 | FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010, 111 | RIGHTMOST_BUTTON_PRESSED = 0x0002; 112 | public uint dwButtonState; 113 | 114 | public const int CAPSLOCK_ON = 0x0080, 115 | ENHANCED_KEY = 0x0100, 116 | LEFT_ALT_PRESSED = 0x0002, 117 | LEFT_CTRL_PRESSED = 0x0008, 118 | NUMLOCK_ON = 0x0020, 119 | RIGHT_ALT_PRESSED = 0x0001, 120 | RIGHT_CTRL_PRESSED = 0x0004, 121 | SCROLLLOCK_ON = 0x0040, 122 | SHIFT_PRESSED = 0x0010; 123 | public uint dwControlKeyState; 124 | 125 | public const int DOUBLE_CLICK = 0x0002, 126 | MOUSE_HWHEELED = 0x0008, 127 | MOUSE_MOVED = 0x0001, 128 | MOUSE_WHEELED = 0x0004; 129 | public uint dwEventFlags; 130 | } 131 | 132 | [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] 133 | public struct KEY_EVENT_RECORD 134 | { 135 | [FieldOffset(0)] 136 | public bool bKeyDown; 137 | [FieldOffset(4)] 138 | public ushort wRepeatCount; 139 | [FieldOffset(6)] 140 | public ushort wVirtualKeyCode; 141 | [FieldOffset(8)] 142 | public ushort wVirtualScanCode; 143 | [FieldOffset(10)] 144 | public char UnicodeChar; 145 | [FieldOffset(10)] 146 | public byte AsciiChar; 147 | 148 | public const int CAPSLOCK_ON = 0x0080, 149 | ENHANCED_KEY = 0x0100, 150 | LEFT_ALT_PRESSED = 0x0002, 151 | LEFT_CTRL_PRESSED = 0x0008, 152 | NUMLOCK_ON = 0x0020, 153 | RIGHT_ALT_PRESSED = 0x0001, 154 | RIGHT_CTRL_PRESSED = 0x0004, 155 | SCROLLLOCK_ON = 0x0040, 156 | SHIFT_PRESSED = 0x0010; 157 | [FieldOffset(12)] 158 | public uint dwControlKeyState; 159 | } 160 | 161 | public struct WINDOW_BUFFER_SIZE_RECORD 162 | { 163 | public COORD dwSize; 164 | } 165 | 166 | public const uint STD_INPUT_HANDLE = unchecked((uint)-10), 167 | STD_OUTPUT_HANDLE = unchecked((uint)-11), 168 | STD_ERROR_HANDLE = unchecked((uint)-12); 169 | 170 | [DllImport("kernel32.dll")] 171 | public static extern IntPtr GetStdHandle(uint nStdHandle); 172 | 173 | [Flags] 174 | public enum ConsoleModes : uint 175 | { 176 | ENABLE_PROCESSED_INPUT = 0x0001, 177 | ENABLE_LINE_INPUT = 0x0002, 178 | ENABLE_ECHO_INPUT = 0x0004, 179 | ENABLE_WINDOW_INPUT = 0x0008, 180 | ENABLE_MOUSE_INPUT = 0x0010, 181 | ENABLE_INSERT_MODE = 0x0020, 182 | ENABLE_QUICK_EDIT_MODE = 0x0040, 183 | ENABLE_EXTENDED_FLAGS = 0x0080, 184 | ENABLE_AUTO_POSITION = 0x0100, 185 | 186 | ENABLE_PROCESSED_OUTPUT = 0x0001, 187 | ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002, 188 | ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004, 189 | DISABLE_NEWLINE_AUTO_RETURN = 0x0008, 190 | ENABLE_LVB_GRID_WORLDWIDE = 0x0010 191 | } 192 | 193 | /* public const uint ENABLE_MOUSE_INPUT = 0x0010, 194 | ENABLE_QUICK_EDIT_MODE = 0x0040, 195 | ENABLE_EXTENDED_FLAGS = 0x0080, 196 | ENABLE_ECHO_INPUT = 0x0004, 197 | ENABLE_WINDOW_INPUT = 0x0008; //more*/ 198 | 199 | [DllImport("kernel32.dll")] 200 | public static extern bool GetConsoleMode(IntPtr hConsoleInput, ref uint lpMode); 201 | 202 | [DllImport("kernel32.dll")] 203 | public static extern bool SetConsoleMode(IntPtr hConsoleInput, uint dwMode); 204 | 205 | 206 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] 207 | public static extern bool ReadConsoleInput(IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsRead); 208 | 209 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] 210 | public static extern bool WriteConsoleInput(IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsWritten); 211 | 212 | 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /Core/Examples/Raycasting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using static MaximovInk.ConsoleGameEngine.Core.NativeMethods; 3 | 4 | namespace MaximovInk.ConsoleGameEngine 5 | { 6 | public class Raycasting : Engine 7 | { 8 | private short w = 24; 9 | private short h = 24; 10 | 11 | private float scaleX; 12 | private float scaleY; 13 | 14 | private float lastMousePosX = 0; 15 | 16 | private int[,] worldMap = new int[,] 17 | { 18 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 19 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 20 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 21 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 22 | {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, 23 | {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, 24 | {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1}, 25 | {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1}, 26 | {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1}, 27 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 28 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 29 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 30 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 31 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 32 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 33 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 34 | {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 35 | {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 36 | {1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 37 | {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 38 | {1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 39 | {1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 40 | {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 41 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} 42 | }; 43 | 44 | double posX = 22, posY = 12; //x and y start position 45 | double dirX = -1, dirY = 0; //initial direction vector 46 | double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane 47 | 48 | public Raycasting(short width = 840/2, short height = 254/2, string Title = "Console engine", short fontw = 4, short fonth = 4, bool showFps = true) : base(width, height, Title, fontw, fonth, showFps) 49 | { 50 | } 51 | 52 | protected override void OnDraw() 53 | { 54 | Clear(); 55 | for (int x = 0; x < w; x++) 56 | { 57 | //calculate ray position and direction 58 | double cameraX = 2 * x / (double)w - 1; //x-coordinate in camera space 59 | double rayDirX = dirX + planeX * cameraX; 60 | double rayDirY = dirY + planeY * cameraX; 61 | //which box of the map we're in 62 | int mapX = (int)posX; 63 | int mapY = (int)posY; 64 | 65 | //length of ray from current position to next x or y-side 66 | double sideDistX; 67 | double sideDistY; 68 | 69 | //length of ray from one x or y-side to next x or y-side 70 | double deltaDistX = Math.Abs(1 / rayDirX); 71 | double deltaDistY = Math.Abs(1 / rayDirY); 72 | double perpWallDist; 73 | 74 | //what direction to step in x or y-direction (either +1 or -1) 75 | int stepX; 76 | int stepY; 77 | 78 | int hit = 0; //was there a wall hit? 79 | int side = 0; //was a NS or a EW wall hit? 80 | 81 | if (rayDirX < 0) 82 | { 83 | stepX = -1; 84 | sideDistX = (posX - mapX) * deltaDistX; 85 | } 86 | else 87 | { 88 | stepX = 1; 89 | sideDistX = (mapX + 1.0 - posX) * deltaDistX; 90 | } 91 | if (rayDirY < 0) 92 | { 93 | stepY = -1; 94 | sideDistY = (posY - mapY) * deltaDistY; 95 | } 96 | else 97 | { 98 | stepY = 1; 99 | sideDistY = (mapY + 1.0 - posY) * deltaDistY; 100 | } 101 | 102 | while (hit == 0) 103 | { 104 | if (sideDistX < sideDistY) 105 | { 106 | sideDistX += deltaDistX; 107 | mapX += stepX; 108 | side = 0; 109 | } 110 | else 111 | { 112 | sideDistY += deltaDistY; 113 | mapY += stepY; 114 | side = 1; 115 | } 116 | 117 | if (worldMap[mapX,mapY] > 0) hit = 1; 118 | } 119 | 120 | if (side == 0) perpWallDist = (mapX - posX + (1 - stepX) / 2) / rayDirX; 121 | else perpWallDist = (mapY - posY + (1 - stepY) / 2) / rayDirY; 122 | 123 | int lineHeight = (int)(h / perpWallDist); 124 | 125 | int drawStart = -lineHeight / 2 + h / 2; 126 | if (drawStart < 0) drawStart = 0; 127 | int drawEnd = lineHeight / 2 + h / 2; 128 | if (drawEnd >= h) drawEnd = h - 1; 129 | 130 | COLOR color; 131 | Character character = Character.Full; 132 | 133 | switch (worldMap[mapX,mapY]) 134 | { 135 | case 1: color = COLOR.FG_RED; break; 136 | case 2: color = COLOR.FG_GREEN; break; 137 | case 3: color = COLOR.FG_BLUE; break; 138 | case 4: color = COLOR.FG_WHITE; break; 139 | default: color = COLOR.FG_YELLOW; break; 140 | } 141 | 142 | if (side == 1) { character = Character.Medium; } 143 | 144 | 145 | 146 | DrawLine((short)x, (short)drawStart, (short)x, (short)drawEnd, (short)character, (short)color); 147 | 148 | } 149 | 150 | Apply(); 151 | } 152 | 153 | protected override void OnKey(KEY_EVENT_RECORD e) 154 | { 155 | double moveSpeed = 5.0 * elapsed; 156 | 157 | if (e.bKeyDown == true) 158 | { 159 | if (e.UnicodeChar == 'w') 160 | { 161 | if (posX + dirX * moveSpeed > 0 && posX + dirX * moveSpeed < worldMap.GetLength(0)) 162 | { 163 | if (worldMap[(int)(posX + dirX * moveSpeed), (int)posY] == 0) posX += dirX * moveSpeed; 164 | if (worldMap[(int)(posX), (int)(posY + dirY * moveSpeed)] == 0) posY += dirY * moveSpeed; 165 | } 166 | } 167 | if (e.UnicodeChar == 's') 168 | { 169 | if (posX - dirX * moveSpeed > 0 && posX - dirX * moveSpeed < worldMap.GetLength(0)) 170 | { 171 | if (worldMap[(int)(posX - dirX * moveSpeed), (int)posY] == 0) posX -= dirX * moveSpeed; 172 | if (worldMap[(int)(posX), (int)(posY - dirY * moveSpeed)] == 0) posY -= dirY * moveSpeed; 173 | } 174 | 175 | } 176 | } 177 | } 178 | 179 | protected override void OnMouse(MOUSE_EVENT_RECORD m) 180 | { 181 | double rotSpeed = 3.0 * elapsed; 182 | if (m.dwMousePosition.X != lastMousePosX ) 183 | { 184 | float deltaX = m.dwMousePosition.X - lastMousePosX; 185 | lastMousePosX = m.dwMousePosition.X; 186 | if (deltaX > 0) 187 | { 188 | double oldDirX = dirX; 189 | dirX = dirX * Math.Cos(-rotSpeed) - dirY * Math.Sin(-rotSpeed); 190 | dirY = oldDirX * Math.Sin(-rotSpeed) + dirY * Math.Cos(-rotSpeed); 191 | double oldPlaneX = planeX; 192 | planeX = planeX * Math.Cos(-rotSpeed) - planeY * Math.Sin(-rotSpeed); 193 | planeY = oldPlaneX * Math.Sin(-rotSpeed) + planeY * Math.Cos(-rotSpeed); 194 | } 195 | else 196 | { 197 | double oldDirX = dirX; 198 | dirX = dirX * Math.Cos(rotSpeed) - dirY * Math.Sin(rotSpeed); 199 | dirY = oldDirX * Math.Sin(rotSpeed) + dirY * Math.Cos(rotSpeed); 200 | double oldPlaneX = planeX; 201 | planeX = planeX * Math.Cos(rotSpeed) - planeY * Math.Sin(rotSpeed); 202 | planeY = oldPlaneX * Math.Sin(rotSpeed) + planeY * Math.Cos(rotSpeed); 203 | } 204 | } 205 | 206 | } 207 | 208 | protected override void OnStart() 209 | { 210 | scaleX = Width / w; 211 | scaleY = Height / h; 212 | 213 | w *= (short)scaleX; 214 | h *= (short)scaleY; 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /Core/Engine.cs: -------------------------------------------------------------------------------- 1 | using MaximovInk.ConsoleGameEngine.Core; 2 | using System; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.Runtime.InteropServices; 6 | using System.Threading; 7 | using static MaximovInk.ConsoleGameEngine.Core.NativeMethods; 8 | 9 | namespace MaximovInk.ConsoleGameEngine 10 | { 11 | public class Engine 12 | { 13 | public short Width { get; protected set; } 14 | public short Height { get; protected set; } 15 | public CharInfo[] buffer; 16 | protected SmallRect rect; 17 | 18 | public bool isRun = false; 19 | 20 | protected Thread Thread; 21 | protected float elapsed { get; private set; } 22 | private Stopwatch sw; 23 | 24 | protected string title; 25 | 26 | protected bool ShowFPS = true; 27 | protected bool CountFrameRate = true; 28 | 29 | public Engine(short width = 240, short height = 80 , string Title ="Console engine", short fontw = 12, short fonth = 12, bool showFps = true ) 30 | { 31 | Width = width; 32 | Height = height; 33 | SetConsoleCP(437); 34 | SetConsoleOutputCP(437); 35 | buffer = new CharInfo[Width * Height]; 36 | 37 | rect = new SmallRect() { Left = 0, Top = 0, Right = Width, Bottom = Height }; 38 | Console.CursorVisible = false; 39 | Console.SetWindowPosition(0, 0); 40 | 41 | CONSOLE_FONT_INFO_EX ConsoleFontInfo = new CONSOLE_FONT_INFO_EX(); 42 | ConsoleFontInfo.cbSize = (uint)Marshal.SizeOf(ConsoleFontInfo); 43 | ConsoleFontInfo.FaceName = "Lucida Console"; 44 | ConsoleFontInfo.dwFontSize.X = fontw; 45 | ConsoleFontInfo.dwFontSize.Y = fonth; 46 | 47 | SetCurrentConsoleFontEx(GetStdHandle(STDOUT), false, ref ConsoleFontInfo); 48 | 49 | IntPtr inHandle = GetStdHandle(STDIN); 50 | uint mode = 0; 51 | GetConsoleMode(inHandle, ref mode); 52 | //mode &= ~ENABLE_QUICK_EDIT_MODE; 53 | mode |= (uint)ConsoleModes.ENABLE_WINDOW_INPUT; 54 | mode |= (uint)ConsoleModes.ENABLE_MOUSE_INPUT; 55 | mode &= ~(uint)ConsoleModes.ENABLE_QUICK_EDIT_MODE; 56 | 57 | 58 | SetConsoleMode(inHandle, mode); 59 | 60 | Console.SetWindowSize(width, height); 61 | Console.SetBufferSize(width, height); 62 | 63 | ShowFPS = showFps; 64 | 65 | Console.Title = Title; 66 | title = Title; 67 | } 68 | 69 | public void StartLoop() 70 | { 71 | isRun = true; 72 | Thread = new Thread(GameThread); 73 | Thread.Priority = ThreadPriority.Highest; 74 | sw = new Stopwatch(); 75 | ConsoleListiner.Start(); 76 | ConsoleListiner.KeyEvent += OnKey; 77 | ConsoleListiner.MouseEvent += OnMouse; 78 | OnStart(); 79 | Thread.Start(); 80 | } 81 | 82 | private void GameThread() 83 | { 84 | while (isRun) 85 | { 86 | bool f = CountFrameRate; 87 | if (f) 88 | { 89 | sw.Start(); 90 | } 91 | 92 | OnUpdate(); 93 | OnDraw(); 94 | if (ShowFPS) 95 | { 96 | Debug.WriteLine("GGG"); 97 | DrawText(0, 0, "FPS:" + (1 / elapsed), 1); 98 | } 99 | 100 | if (f) 101 | { 102 | elapsed = (float)sw.Elapsed.TotalSeconds; 103 | sw.Stop(); 104 | sw.Reset(); 105 | } 106 | } 107 | ConsoleListiner.Stop(); 108 | ConsoleListiner.KeyEvent -= OnKey; 109 | ConsoleListiner.MouseEvent -= OnMouse; 110 | } 111 | 112 | protected virtual void OnKey(KEY_EVENT_RECORD e) 113 | { 114 | 115 | } 116 | 117 | protected virtual void OnMouse(MOUSE_EVENT_RECORD m) 118 | { 119 | 120 | } 121 | 122 | public void DrawTriangle(short x1, short x2, short x3 , short y1, short y2, short y3, short character, short color) 123 | { 124 | DrawLine(x1, y1, x2, y2,character,color); 125 | DrawLine(x1, y1, x3, y3,character,color); 126 | DrawLine(x2, y2, x3, y3, character, color); 127 | } 128 | 129 | public void DrawRect(short x, short y, short width, short height, short character, short color) 130 | { 131 | DrawLine(x, y, x, (short)(height + y), character, color); 132 | DrawLine(x, y, (short)(width + x), y, character, color); 133 | DrawLine(x, (short)(y+height), (short)(width + x), (short)(height + y), character, color); 134 | DrawLine((short)(x+width), y, (short)(width + x), (short)(height + y), character, color); 135 | } 136 | 137 | public void DrawCircle(short x0, short y0, short radius, short character, short color) 138 | { 139 | int x = 0, y = radius; 140 | int d = 3 - 2 * radius; 141 | 142 | DrawCircle(x0, (short)x, y0, (short)y, character, color); 143 | 144 | while (y >= x) 145 | { 146 | x++; 147 | if (d > 0) 148 | { 149 | y--; 150 | d = d + 4 * (x - y) + 10; 151 | } 152 | else 153 | d = d + 4 * x + 6; 154 | 155 | DrawCircle(x0, (short)x, y0, (short)y, character, color); 156 | } 157 | 158 | } 159 | 160 | private void DrawCircle(short x0, short x, short y0, short y , short character , short color) 161 | { 162 | DrawPixel((short)(x0 + x), (short)(y0 + y), character, color); 163 | DrawPixel((short)(x0 - x), (short)(y0 + y), character, color); 164 | DrawPixel((short)(x0 + x), (short)(y0 - y), character, color); 165 | DrawPixel((short)(x0 - x), (short)(y0 - y), character, color); 166 | DrawPixel((short)(x0 + y), (short)(y0 + x), character, color); 167 | DrawPixel((short)(x0 - y), (short)(y0 + x), character, color); 168 | DrawPixel((short)(x0 + y), (short)(y0 - x), character, color); 169 | DrawPixel((short)(x0 - y), (short)(y0 - x), character, color); 170 | } 171 | 172 | public void DrawLineGradient(short x, short y, short x2, short y2, short color1, short color2) 173 | { 174 | int w = x2 - x; 175 | int h = y2 - y; 176 | short dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0; 177 | if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1; 178 | if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1; 179 | if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1; 180 | int longest = Math.Abs(w); 181 | int shortest = Math.Abs(h); 182 | if (!(longest > shortest)) 183 | { 184 | longest = Math.Abs(h); 185 | shortest = Math.Abs(w); 186 | if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1; 187 | dx2 = 0; 188 | } 189 | int numerator = longest >> 1; 190 | 191 | Color one = ((COLOR)color1).GetRGB(); 192 | Color two = ((COLOR)color2).GetRGB(); 193 | 194 | for (int i = 0; i <= longest; i++) 195 | { 196 | COLOR cl; 197 | Character ch; 198 | 199 | ColorUtilites.CombineTwoColors(((COLOR)color1), ((COLOR)color2), (float)i / longest, out ch, out cl); 200 | 201 | DrawPixel(x, y, (short)ch, (short)cl); 202 | numerator += shortest; 203 | if (!(numerator < longest)) 204 | { 205 | numerator -= longest; 206 | x += dx1; 207 | y += dy1; 208 | } 209 | else 210 | { 211 | x += dx2; 212 | y += dy2; 213 | } 214 | 215 | } 216 | } 217 | 218 | public void DrawLine(short x, short y, short x2, short y2, short character, short color) 219 | { 220 | int w = x2 - x; 221 | int h = y2 - y; 222 | short dx1 = 0, dy1 = 0, dx2 = 0, dy2 = 0; 223 | if (w < 0) dx1 = -1; else if (w > 0) dx1 = 1; 224 | if (h < 0) dy1 = -1; else if (h > 0) dy1 = 1; 225 | if (w < 0) dx2 = -1; else if (w > 0) dx2 = 1; 226 | int longest = Math.Abs(w); 227 | int shortest = Math.Abs(h); 228 | if (!(longest > shortest)) 229 | { 230 | longest = Math.Abs(h); 231 | shortest = Math.Abs(w); 232 | if (h < 0) dy2 = -1; else if (h > 0) dy2 = 1; 233 | dx2 = 0; 234 | } 235 | int numerator = longest >> 1; 236 | for (int i = 0; i <= longest; i++) 237 | { 238 | DrawPixel(x, y, character, color); 239 | numerator += shortest; 240 | if (!(numerator < longest)) 241 | { 242 | numerator -= longest; 243 | x += dx1; 244 | y += dy1; 245 | } 246 | else 247 | { 248 | x += dx2; 249 | y += dy2; 250 | } 251 | } 252 | } 253 | 254 | public void DrawPixel(short x, short y, short symbol, short color) 255 | { 256 | DrawChar(x, y, (char)symbol, color); 257 | } 258 | 259 | public void DrawText(short x, short y, string text, short color) 260 | { 261 | char[] chars = text.ToCharArray(); 262 | 263 | for (int i = 0; i < chars.Length; i++) 264 | { 265 | DrawChar((short)(x + i), y, chars[i], color); 266 | } 267 | } 268 | 269 | public void DrawChar(short x, short y, char @char, short color) 270 | { 271 | SetPixel(x, y, new CharInfo() { Attributes = color, UnicodeChar = @char }); 272 | } 273 | 274 | public void FillRect(short x, short y, short width, short height, short character, short color) 275 | { 276 | for (int w = 0; w < width; w++) 277 | { 278 | for (int h = 0; h < height; h++) 279 | { 280 | DrawPixel((short)(x + w), (short)(y + h), character, color); 281 | } 282 | } 283 | } 284 | 285 | protected void SetPixel(short x, short y, CharInfo @char) 286 | { 287 | if (x >= 0 && y >= 0 && x < Width && y < Height) 288 | { 289 | buffer[y * Width + x] = @char; 290 | } 291 | } 292 | 293 | public CharInfo GetPixel(short x, short y) 294 | { 295 | x = (short)MathF.Clamp(x, 0, Width); 296 | y = (short)MathF.Clamp(y, 0, Height); 297 | return buffer[y * Width + x]; 298 | } 299 | 300 | protected void Apply() 301 | { 302 | WriteConsoleOutput(GetStdHandle(STDOUT), buffer, new COORD(Width, Height), new COORD(0, 0), ref rect); 303 | } 304 | 305 | protected void Clear() 306 | { 307 | CharInfo ch = new CharInfo(); 308 | 309 | for (int i = 0; i < buffer.Length; i++) 310 | { 311 | buffer[i] = ch; 312 | } 313 | } 314 | 315 | protected virtual void OnStart() 316 | { 317 | 318 | } 319 | protected virtual void OnUpdate() 320 | { 321 | 322 | } 323 | protected virtual void OnDraw() 324 | { 325 | 326 | } 327 | 328 | [DllImport("kernel32.dll", SetLastError = true)] 329 | static extern bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, COORD size); 330 | 331 | [DllImport("kernel32.dll", SetLastError = true)] 332 | static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, SmallRect rect); 333 | 334 | [DllImport("kernel32.dll",SetLastError =true)] 335 | static extern bool SetConsoleOutputCP(uint CodePageId); 336 | 337 | [DllImport("kernel32.dll", SetLastError = true)] 338 | static extern bool SetConsoleCP(uint CodePageId); 339 | 340 | [DllImport("kernel32.dll", SetLastError = true)] 341 | static extern bool WriteConsoleOutput(IntPtr hConsoleOutput, CharInfo[] buffer, COORD bufferSize, COORD bufferCoord, ref SmallRect region); 342 | 343 | [DllImport("kernel32.dll", SetLastError = true)] 344 | static extern IntPtr GetStdHandle(int handle); 345 | 346 | [DllImport("kernel32.dll")] 347 | static extern uint GetLastError(); 348 | 349 | [DllImport("kernel32.dll", SetLastError = true)] 350 | public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO buffer); 351 | 352 | [DllImport("kernel32.dll", SetLastError = true)] 353 | static extern int SetCurrentConsoleFontEx(IntPtr ConsoleOutput,bool MaximumWindow, ref CONSOLE_FONT_INFO_EX ConsoleCurrentFontEx); 354 | 355 | [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 356 | extern static bool GetCurrentConsoleFontEx(IntPtr hConsoleOutput,bool bMaximumWindow,ref CONSOLE_FONT_INFOEX info); 357 | 358 | 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /Core/ColorUtilites.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace MaximovInk.ConsoleGameEngine 5 | { 6 | public static class ColorUtilites 7 | { 8 | public static COLOR GetConsoleColor16(this Color color) 9 | { 10 | if (color.GetSaturation() < 0.5) 11 | { 12 | 13 | float satur = color.GetBrightness() * 3.5f; 14 | 15 | if (satur == 0) 16 | { 17 | return COLOR.FG_BLACK; 18 | } 19 | 20 | } 21 | int hue = (int)Math.Round(color.GetHue() / 60, MidpointRounding.AwayFromZero); 22 | if (color.GetBrightness() < 0.4) 23 | { 24 | switch (hue) 25 | { 26 | case 1: return COLOR.FG_DARK_YELLOW; 27 | case 2: return COLOR.FG_DARK_GREEN; 28 | case 3: return COLOR.FG_DARK_CYAN; 29 | case 4: return COLOR.FG_DARK_BLUE; 30 | case 5: return COLOR.FG_DARK_MAGENTA; 31 | default: return COLOR.FG_DARK_RED; 32 | } 33 | } 34 | switch (hue) 35 | { 36 | case 1: return COLOR.FG_YELLOW; 37 | case 2: return COLOR.FG_GREEN; 38 | case 3: return COLOR.FG_CYAN; 39 | case 4: return COLOR.FG_BLUE; 40 | case 5: return COLOR.FG_MAGENTA; 41 | default: return COLOR.FG_RED; 42 | } 43 | } 44 | 45 | public static void GetConsoleColor(this Color color, out Character ch, out COLOR cl) 46 | { 47 | ch = Character.Null; 48 | cl = COLOR.BG_BLACK; 49 | 50 | float satur = color.GetSaturation(); 51 | float light = color.GetBrightness(); 52 | float hue = color.GetHue(); 53 | 54 | if (satur < 0.1f | light > 0.8f) 55 | { 56 | ch = Character.Full; 57 | cl = COLOR.BG_BLACK; 58 | 59 | ch = light < 0.2 ? Character.Light : light < 0.5 ? Character.Medium : light < 0.8 ? Character.Dark : Character.Full; 60 | 61 | if (light == 0) 62 | { 63 | cl = COLOR.FG_BLACK | COLOR.BG_BLACK; 64 | ch = Character.Medium; 65 | } 66 | else if (light <= 0.1) 67 | { 68 | cl = COLOR.FG_DARK_GREY | COLOR.BG_BLACK; 69 | ch = Character.Medium; 70 | } 71 | else if (light <= 0.3) 72 | { 73 | cl = COLOR.FG_DARK_GREY; 74 | ch = Character.Full; 75 | } 76 | else if (light <= 0.5) 77 | { 78 | cl = COLOR.FG_DARK_GREY | COLOR.BG_GREY; 79 | ch = Character.Medium; 80 | } 81 | else if (light <= 0.6) 82 | { 83 | cl = COLOR.FG_GREY; 84 | ch = Character.Full; 85 | } 86 | else if (light <= 0.8) 87 | { 88 | cl = COLOR.FG_GREY | COLOR.BG_WHITE; 89 | ch = Character.Medium; 90 | } 91 | else 92 | { 93 | cl = COLOR.FG_WHITE; 94 | ch = Character.Full; 95 | } 96 | } 97 | else 98 | { 99 | if (hue <= 10) 100 | { 101 | if (light <= 0.4) 102 | { 103 | cl = COLOR.FG_DARK_RED; 104 | ch = Character.Dark; 105 | } 106 | else if (light <= 0.5) 107 | { 108 | cl = COLOR.FG_RED; 109 | ch = Character.Dark; 110 | } 111 | else if (light <= 0.7) 112 | { 113 | cl = COLOR.FG_RED | COLOR.BG_WHITE; 114 | ch = Character.Medium; 115 | } 116 | else 117 | { 118 | cl = COLOR.FG_RED | COLOR.BG_WHITE; 119 | ch = Character.Light; 120 | } 121 | } 122 | else if (hue <= 30) 123 | { 124 | if (light <= 0.3) 125 | { 126 | cl = COLOR.FG_DARK_RED | COLOR.BG_YELLOW; 127 | ch = Character.Dark; 128 | } 129 | else if (light <= 0.4) 130 | { 131 | cl = COLOR.FG_DARK_RED | COLOR.BG_YELLOW; 132 | ch = Character.Medium; 133 | } 134 | else if (light <= 0.5) 135 | { 136 | cl = COLOR.FG_RED | COLOR.BG_YELLOW; 137 | ch = Character.Medium; 138 | } 139 | else if (light <= 0.7) 140 | { 141 | cl = COLOR.FG_RED | COLOR.BG_WHITE; 142 | ch = Character.Medium; 143 | } 144 | else 145 | { 146 | cl = COLOR.FG_RED | COLOR.BG_WHITE; 147 | ch = Character.Light; 148 | } 149 | } 150 | else if (hue <= 45) 151 | { 152 | if (light <= 0.3) 153 | { 154 | cl = COLOR.FG_YELLOW | COLOR.BG_DARK_RED; 155 | ch = Character.Dark; 156 | } 157 | else if (light <= 0.6) 158 | { 159 | cl = COLOR.FG_YELLOW | COLOR.BG_RED; 160 | ch = Character.Medium; 161 | } 162 | else if (light <= 0.7) 163 | { 164 | cl = COLOR.FG_YELLOW | COLOR.BG_RED; 165 | ch = Character.Light; 166 | } 167 | else 168 | { 169 | cl = COLOR.FG_YELLOW | COLOR.BG_RED; 170 | ch = Character.Light; 171 | } 172 | } 173 | else if (hue <= 65) 174 | { 175 | if (light <= 0.4) 176 | { 177 | cl = COLOR.FG_DARK_YELLOW; 178 | ch = Character.Dark; 179 | } 180 | else if (light <= 0.5) 181 | { 182 | cl = COLOR.FG_YELLOW; 183 | ch = Character.Dark; 184 | } 185 | else if (light <= 0.6) 186 | { 187 | cl = COLOR.FG_YELLOW | COLOR.BG_YELLOW; 188 | ch = Character.Light; 189 | } 190 | else 191 | { 192 | cl = COLOR.FG_YELLOW | COLOR.BG_WHITE; 193 | ch = Character.Light; 194 | } 195 | } 196 | else if (hue <= 96) 197 | { 198 | if (light <= 0.3) 199 | { 200 | cl = COLOR.FG_DARK_GREEN | COLOR.BG_DARK_YELLOW; 201 | ch = Character.Dark; 202 | } 203 | else if (light <= 0.5) 204 | { 205 | cl = COLOR.FG_DARK_GREEN | COLOR.BG_DARK_YELLOW; 206 | ch = Character.Medium; 207 | } 208 | else if (light <= 0.6) 209 | { 210 | cl = COLOR.FG_GREEN | COLOR.BG_YELLOW; 211 | ch = Character.Medium; 212 | } 213 | else if (light <= 0.7) 214 | { 215 | cl = COLOR.FG_GREEN | COLOR.BG_YELLOW; 216 | ch = Character.Light; 217 | } 218 | else 219 | { 220 | cl = COLOR.FG_GREEN | COLOR.BG_WHITE; 221 | ch = Character.Light; 222 | } 223 | } 224 | else if (hue <= 150) 225 | { 226 | if (light <= 0.3) 227 | { 228 | cl = COLOR.FG_DARK_GREEN; 229 | ch = Character.Dark; 230 | } 231 | else if (light <= 0.5) 232 | { 233 | cl = COLOR.FG_DARK_GREEN; 234 | ch = Character.Dark; 235 | } 236 | else if (light <= 0.7) 237 | { 238 | cl = COLOR.FG_GREEN; 239 | ch = Character.Dark; 240 | } 241 | else 242 | { 243 | cl = COLOR.FG_GREEN | COLOR.BG_WHITE; 244 | ch = Character.Light; 245 | } 246 | } 247 | else if (hue <= 150) 248 | { 249 | if (light <= 0.3) 250 | { 251 | cl = COLOR.FG_DARK_CYAN | COLOR.BG_DARK_GREEN; 252 | ch = Character.Dark; 253 | } 254 | else if (light <= 0.5) 255 | { 256 | cl = COLOR.FG_DARK_CYAN | COLOR.BG_DARK_GREEN; 257 | ch = Character.Medium; 258 | } 259 | else if (light <= 0.6) 260 | { 261 | cl = COLOR.FG_CYAN | COLOR.BG_GREEN; 262 | ch = Character.Medium; 263 | } 264 | else if (light <= 0.7) 265 | { 266 | cl = COLOR.FG_CYAN | COLOR.BG_GREEN; 267 | ch = Character.Light; 268 | } 269 | else 270 | { 271 | cl = COLOR.FG_CYAN | COLOR.BG_WHITE; 272 | ch = Character.Light; 273 | } 274 | } 275 | else if (hue <= 190) 276 | { 277 | if (light <= 0.3) 278 | { 279 | cl = COLOR.FG_DARK_CYAN; 280 | ch = Character.Dark; 281 | } 282 | else if (light <= 0.5) 283 | { 284 | cl = COLOR.FG_DARK_CYAN; 285 | ch = Character.Dark; 286 | } 287 | else if (light <= 0.7) 288 | { 289 | cl = COLOR.FG_CYAN; 290 | ch = Character.Dark; 291 | } 292 | else 293 | { 294 | cl = COLOR.FG_CYAN | COLOR.BG_WHITE; 295 | ch = Character.Light; 296 | } 297 | } 298 | else if (hue <= 220) 299 | { 300 | if (light <= 0.3) 301 | { 302 | cl = COLOR.FG_DARK_CYAN | COLOR.BG_DARK_BLUE; 303 | ch = Character.Dark; 304 | } 305 | else if (light <= 0.5) 306 | { 307 | cl = COLOR.FG_DARK_CYAN | COLOR.BG_DARK_BLUE; 308 | ch = Character.Medium; 309 | } 310 | else if (light <= 0.7) 311 | { 312 | cl = COLOR.FG_CYAN | COLOR.BG_BLUE; 313 | ch = Character.Medium; 314 | } 315 | else 316 | { 317 | cl = COLOR.FG_CYAN | COLOR.BG_WHITE; 318 | ch = Character.Light; 319 | } 320 | } 321 | else if (hue <= 240) 322 | { 323 | if (light <= 0.3) 324 | { 325 | cl = COLOR.FG_DARK_BLUE; 326 | ch = Character.Dark; 327 | } 328 | else if (light <= 0.5) 329 | { 330 | cl = COLOR.FG_DARK_BLUE; 331 | ch = Character.Dark; 332 | } 333 | else if (light <= 0.7) 334 | { 335 | cl = COLOR.FG_BLUE; 336 | ch = Character.Dark; 337 | } 338 | else 339 | { 340 | cl = COLOR.FG_BLUE | COLOR.BG_WHITE; 341 | ch = Character.Light; 342 | } 343 | } 344 | else if (hue <= 275) 345 | { 346 | if (light <= 0.3) 347 | { 348 | cl = COLOR.FG_DARK_BLUE | COLOR.BG_DARK_MAGENTA; 349 | ch = Character.Dark; 350 | } 351 | else if (light <= 0.5) 352 | { 353 | cl = COLOR.FG_DARK_BLUE | COLOR.BG_DARK_MAGENTA; 354 | ch = Character.Medium; 355 | } 356 | else if (light <= 0.6) 357 | { 358 | cl = COLOR.FG_BLUE | COLOR.BG_MAGENTA; 359 | ch = Character.Medium; 360 | } 361 | else if (light <= 0.7) 362 | { 363 | cl = COLOR.FG_BLUE | COLOR.BG_MAGENTA; 364 | ch = Character.Light; 365 | } 366 | else 367 | { 368 | cl = COLOR.FG_BLUE | COLOR.BG_WHITE; 369 | ch = Character.Light; 370 | } 371 | } 372 | else if (hue <= 320) 373 | { 374 | if (light <= 0.3) 375 | { 376 | cl = COLOR.FG_DARK_MAGENTA; 377 | ch = Character.Dark; 378 | } 379 | else if (light <= 0.5) 380 | { 381 | cl = COLOR.FG_DARK_MAGENTA; 382 | ch = Character.Dark; 383 | } 384 | else if (light <= 0.7) 385 | { 386 | cl = COLOR.FG_MAGENTA; 387 | ch = Character.Dark; 388 | } 389 | else 390 | { 391 | cl = COLOR.FG_MAGENTA | COLOR.BG_WHITE; 392 | ch = Character.Light; 393 | } 394 | } 395 | else 396 | { 397 | if (light <= 0.3) 398 | { 399 | cl = COLOR.FG_DARK_MAGENTA | COLOR.BG_DARK_RED; 400 | ch = Character.Dark; 401 | } 402 | else if (light <= 0.5) 403 | { 404 | cl = COLOR.FG_DARK_MAGENTA | COLOR.BG_DARK_RED; 405 | ch = Character.Medium; 406 | } 407 | else if (light <= 0.6) 408 | { 409 | cl = COLOR.FG_MAGENTA | COLOR.BG_RED; 410 | ch = Character.Medium; 411 | } 412 | else if (light <= 0.7) 413 | { 414 | cl = COLOR.FG_MAGENTA | COLOR.BG_RED; 415 | ch = Character.Light; 416 | } 417 | else 418 | { 419 | cl = COLOR.FG_MAGENTA | COLOR.BG_WHITE; 420 | ch = Character.Light; 421 | } 422 | } 423 | 424 | } 425 | 426 | } 427 | 428 | public static Color GetRGB(this COLOR color) 429 | { 430 | switch (color) 431 | { 432 | case COLOR.FG_DARK_BLUE: 433 | return Color.FromArgb(0, 0, 128); 434 | case COLOR.FG_DARK_GREEN: 435 | return Color.FromArgb(0, 128, 0); 436 | case COLOR.FG_DARK_CYAN: 437 | return Color.FromArgb(0, 128, 128); 438 | case COLOR.FG_DARK_RED: 439 | return Color.FromArgb(128, 0, 0); 440 | case COLOR.FG_DARK_MAGENTA: 441 | return Color.FromArgb(128, 0, 128); 442 | case COLOR.FG_DARK_YELLOW: 443 | return Color.FromArgb(128, 128, 0); 444 | case COLOR.FG_GREY: 445 | return Color.FromArgb(128, 128, 128); 446 | case COLOR.FG_DARK_GREY: 447 | return Color.FromArgb(192, 192, 192); 448 | case COLOR.FG_BLUE: 449 | return Color.FromArgb(0, 0, 255); 450 | case COLOR.FG_GREEN: 451 | return Color.FromArgb(0, 255, 0); 452 | case COLOR.FG_CYAN: 453 | return Color.FromArgb(0, 255, 255); 454 | case COLOR.FG_RED: 455 | return Color.FromArgb(255, 0, 0); 456 | case COLOR.FG_MAGENTA: 457 | return Color.FromArgb(255, 0,255); 458 | case COLOR.FG_YELLOW: 459 | return Color.FromArgb(255, 255, 0); 460 | case COLOR.FG_WHITE: 461 | return Color.FromArgb(255, 255, 255); 462 | default: 463 | return Color.FromArgb(0, 0, 0); 464 | } 465 | } 466 | 467 | public static COLOR InvertFBG(COLOR color) 468 | { 469 | switch (color) 470 | { 471 | case COLOR.FG_BLACK: 472 | return COLOR.BG_BLACK; 473 | case COLOR.FG_DARK_BLUE: 474 | return COLOR.BG_DARK_GREEN; 475 | case COLOR.FG_DARK_GREEN: 476 | return COLOR.BG_DARK_GREEN; 477 | case COLOR.FG_DARK_CYAN: 478 | return COLOR.BG_DARK_CYAN; 479 | case COLOR.FG_DARK_RED: 480 | return COLOR.BG_DARK_RED; 481 | case COLOR.FG_DARK_MAGENTA: 482 | return COLOR.BG_DARK_MAGENTA; 483 | case COLOR.FG_DARK_YELLOW: 484 | return COLOR.BG_DARK_YELLOW; 485 | case COLOR.FG_GREY: 486 | return COLOR.BG_GREY; 487 | case COLOR.FG_DARK_GREY: 488 | return COLOR.BG_DARK_GREY; 489 | case COLOR.FG_BLUE: 490 | return COLOR.BG_BLUE; 491 | case COLOR.FG_GREEN: 492 | return COLOR.BG_GREEN; 493 | case COLOR.FG_CYAN: 494 | return COLOR.BG_CYAN; 495 | case COLOR.FG_RED: 496 | return COLOR.BG_RED; 497 | case COLOR.FG_MAGENTA: 498 | return COLOR.BG_MAGENTA; 499 | case COLOR.FG_YELLOW: 500 | return COLOR.BG_YELLOW; 501 | case COLOR.FG_WHITE: 502 | return COLOR.BG_WHITE; 503 | case COLOR.BG_DARK_BLUE: 504 | return COLOR.FG_DARK_BLUE; 505 | case COLOR.BG_DARK_GREEN: 506 | return COLOR.FG_DARK_GREEN; 507 | case COLOR.BG_DARK_CYAN: 508 | return COLOR.FG_DARK_CYAN; 509 | case COLOR.BG_DARK_RED: 510 | return COLOR.FG_DARK_RED; 511 | case COLOR.BG_DARK_MAGENTA: 512 | return COLOR.FG_DARK_MAGENTA; 513 | case COLOR.BG_DARK_YELLOW: 514 | return COLOR.FG_DARK_YELLOW; 515 | case COLOR.BG_GREY: 516 | return COLOR.FG_GREY; 517 | case COLOR.BG_DARK_GREY: 518 | return COLOR.FG_DARK_GREY; 519 | case COLOR.BG_BLUE: 520 | return COLOR.FG_BLUE; 521 | case COLOR.BG_GREEN: 522 | return COLOR.FG_GREEN; 523 | case COLOR.BG_CYAN: 524 | return COLOR.FG_CYAN; 525 | case COLOR.BG_RED: 526 | return COLOR.FG_RED; 527 | case COLOR.BG_MAGENTA: 528 | return COLOR.BG_MAGENTA; 529 | case COLOR.BG_YELLOW: 530 | return COLOR.FG_YELLOW; 531 | case COLOR.BG_WHITE: 532 | return COLOR.FG_WHITE; 533 | default: 534 | return COLOR.FG_BLACK; 535 | } 536 | } 537 | 538 | public static void CombineTwoColors(COLOR one, COLOR two, float mix, out Character ch, out COLOR cl) 539 | { 540 | ch = Character.Null; 541 | cl = COLOR.BG_BLACK; 542 | 543 | if (mix < 0.05f) 544 | { 545 | //full 546 | ch = Character.Full; 547 | cl = one | InvertFBG(two); 548 | } 549 | else if (mix < 0.4f) 550 | { 551 | //dark 552 | ch = Character.Dark; 553 | cl = one | InvertFBG(two); 554 | } 555 | else if (mix < 0.6f) 556 | { 557 | //medium 558 | ch = Character.Medium; 559 | cl = one | InvertFBG(two); 560 | } 561 | else if (mix <= 0.95f) 562 | { 563 | //dark 564 | ch = Character.Dark; 565 | cl = two | InvertFBG(one); 566 | } 567 | else 568 | { 569 | //full 570 | ch = Character.Full; 571 | cl = two | InvertFBG(one); 572 | } 573 | } 574 | } 575 | } 576 | --------------------------------------------------------------------------------