I woke up today and decided to challenge myself with a C# coding project.

Discussion in 'Mixed Languages' started by nosirrahx, Sep 12, 2020.

  1. nosirrahx

    nosirrahx MDL Expert

    Nov 7, 2017
    1,232
    591
    60
    I coded a simulation of the classic predator VS. prey problem where predators and prey battle for survival.

    At this point all of the variables are user controlled but I want to create automation to determine how to set the variables so that the simulation wont end with both going extinct.

    I am seeing a lot of places where duplicate code exists so I think I can probably use delegates to clean it up, never used them before so its time to learn more about them. I am also seeing partial class duplication where I should probably use inheritance, also something I have not actually used yet.

    If someone wants a challenge to encourage learning, this was one hell of a fun project and I got it done in a day so its not crazy difficult.
     
  2. Tiger-1

    Tiger-1 MDL Guru

    Oct 18, 2014
    7,897
    10,733
    240
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. nosirrahx

    nosirrahx MDL Expert

    Nov 7, 2017
    1,232
    591
    60
    #3 nosirrahx, Sep 29, 2020
    Last edited: Sep 29, 2020
    (OP)
    I wrote a console renderer that can be used to make retro looking games using only the console.

    Code:
    int Screen_X_Size = 180, Screen_Y_Size = 120;
    int[,] New_Frame = new int[Screen_X_Size, Screen_Y_Size];
    string[,] Final_Draw = new string[Screen_X_Size / 2, Screen_Y_Size / 2];
    for (int i = 0; i < Screen_Y_Size; i++)
                {
                    for (int j = 0; j < Screen_X_Size; j++)
                    {
                        New_Frame[j, i] = 0;
                    }
                }
                for (int i = 0; i < (Screen_Y_Size / 2); i++)
                {
                    for (int j = 0; j < (Screen_X_Size / 2); j++)
                    {
                        Final_Draw[j, i] = "  ";
                    }
                }
    Console.SetWindowSize(Screen_X_Size, (Screen_Y_Size / 2) + 1);
    Console.CursorVisible = false;
    Console.ForegroundColor = ConsoleColor.White;
    Console.BackgroundColor = ConsoleColor.Black;
    
    
    static void Draw_Screen(int[,] New_Frame, ref string[,] Final_Draw, int Screen_X_Size, int Screen_Y_Size)
            {
                string Shape = "  ";
                int AA, BA, AB, BB;
                for (int i = 0; i < Screen_Y_Size; i += 2)
                {
                    for (int j = 0; j < Screen_X_Size; j += 2)
                    {
                        AA = New_Frame[j, i];
                        BA = New_Frame[j + 1, i];
                        AB = New_Frame[j, i + 1];
                        BB = New_Frame[j + 1, i + 1];
                        if (AA == 0 && AB == 0) { Shape = " "; }
                        if (AA == 1 && AB == 0) { Shape = "▀"; }
                        if (AA == 0 && AB == 1) { Shape = "▄"; }
                        if (AA == 1 && AB == 1) { Shape = "█"; }
                        if (BA == 0 && BB == 0) { Shape += " "; }
                        if (BA == 1 && BB == 0) { Shape += "▀"; }
                        if (BA == 0 && BB == 1) { Shape += "▄"; }
                        if (BA == 1 && BB == 1) { Shape += "█"; }
                        if (Shape != Final_Draw[j / 2, i / 2])
                        {
                            Console.SetCursorPosition(j, i / 2);
                            Console.Write(Shape);
                            Final_Draw[j / 2, i / 2] = Shape;
                        }
                    }
                }
            }
    

    The top part initializes everything and the bottom is the method that you call when you want to draw the next frame. It is optimized to only draw the virtual pixels that have changed.

    int Screen_X_Size = 180, Screen_Y_Size = 120; <- this is what I was using on 1080p and 100% font scaling so if you are using lower resolution or higher font scaling you will need to reduce these numbers and they must be even.

    You create your frame in New_Frame[x,y] and then call Draw_Screen(New_Frame, ref Final_Draw, Screen_X_Size, Screen_Y_Size); Final_Draw needs the ref because the method also changes the array.

    Make sure to start the frame creation process with setting New_Frame[x,y] to all 0s, its super easy to forget this step. You do not need to reinitialize Final_Draw[x,y] because you want it to remember the last frame.

    You can literally take anything that can be converted into a matrix of 0s and 1s and animate it with this code. I made Asteroids with it:

    [​IMG]
     
  4. nosirrahx

    nosirrahx MDL Expert

    Nov 7, 2017
    1,232
    591
    60
    I completely rewrote my console renderer to use the 16 console colors and optimized it to only 0 the base frame if that virtual pixel isn't 0 and only writes to console if the current up/down pixel pair has changed. I am currently coding Pac-Man using this as the final render step.

    Code:
           static void Draw_Screen()
            {
                int OAA, OAB, NAA, NAB;
                for (int i = 0; i < Screen_Y_Size; i += 2)
                {
                    for (int j = 0; j < Screen_X_Size; j++)
                    {
                        NAA = New_Frame[j, i];
                        NAB = New_Frame[j, i + 1];
                        OAA = Old_Frame[j, i];
                        OAB = Old_Frame[j, i + 1];
                        if (NAA != 0 || NAB != 0) { New_Frame[j, i] = 0; New_Frame[j, i + 1] = 0; }
                        if (OAA == NAA && OAB == NAB) { continue; }
                        Old_Frame[j, i] = NAA;
                        Old_Frame[j, i + 1] = NAB;
                        Console.ForegroundColor = (ConsoleColor)NAA;
                        Console.BackgroundColor = (ConsoleColor)NAB;
                        Console.SetCursorPosition(j, i / 2);
                        Console.Write("▀");
                    }
                }
                Console.BackgroundColor = ConsoleColor.Black;
            }
    

    I really like how this half block character is literally the only thing I ever write to console. Manipulating the foreground and background color turns each console character position into 2 virtual pixels with 16 possible colors.

    In the past I had 3 loops though the New_Fame and Old_Frame arrays. 1st set New_Fame to 0, 2nd drew the frame and the 3rd copied New_Frame into Old_Frame. I changed that into a single loop where 0s (to New-Fame) and copy (to Old_Frame) only happen if they need to happen and also happen within the existing loop.

    Here is a screenshot of my current progress. Right now I have the maps done, pellet creator done and the ghost wander AI done. I'm not sure which part I will do next but it will probably be adding Pac-Man and adding controls.

    [​IMG]