Exemplo n.º 1
0
 private static void AddStr(int y, int x, string str)
 {
     if (x >= 0 && x < NCurses.Columns && y >= 0 && y < NCurses.Lines)
     {
         NCurses.MoveAddString(y, x, str);
     }
 }
Exemplo n.º 2
0
 private void Update()
 {
     NCurses.GetChar();
     UpdateSnakeDirection(NCurses.GetChar());
     CheckEatApple();
     CheckSnakeOutOfBounds();
 }
Exemplo n.º 3
0
        static void Main(string[] args)
        {
            short[]        colorMap = new short[] { 1, 2 };
            IntPtr         screen   = default;
            NCursesDisplay display  = null;
            IChip8Device   device   = null;

            Func <bool>[] initializers =
            {
                () => InitializeNCurses(ref screen,        colorMap,        DefaultWidth, DefaultHeight),
                () => InitializeDisplayBuffer(ref display, screen,          colorMap),
                () => BuildDevice(ref device,              display.Buffer),
                () => LoadProgram(device,                  "program")
            };

            try
            {
                if (initializers.All(p => p()))
                {
                    Run(device, display);
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine($"Caught an exception: {e.Message}");
            }

            NCurses.EndWin();
        }
Exemplo n.º 4
0
        private static bool InitializeNCurses(ref IntPtr screen, short[] colorMap, Byte width, Byte height)
        {
            screen = NCurses.InitScreen();

            if (NCurses.HasColors() == false)
            {
                Console.WriteLine("Your terminal doesn't support colored output.");
                NCurses.EndWin();
                return(false);
            }

            if ((NCurses.Columns < width - 1) || (NCurses.Lines < height - 1))
            {
                Console.WriteLine($"Your terminal must be {width}x{height}. You have {NCurses.Columns}x{NCurses.Lines}");
                NCurses.EndWin();
                return(false);
            }

            NCurses.NoDelay(screen, true);
            NCurses.NoEcho();
            NCurses.AttributeSet(CursesAttribute.NORMAL);
            NCurses.StartColor();
            NCurses.InitPair(colorMap[0], CursesColor.BLACK, CursesColor.BLACK);
            NCurses.InitPair(colorMap[1], CursesColor.WHITE, CursesColor.WHITE);

            return(true);
        }
Exemplo n.º 5
0
 private void RenderSnake()
 {
     foreach (var coord in snake.Coordinates)
     {
         NCurses.MoveAddChar(coord.Y + 1, coord.X + 1, Snake.SYMBOL_BODY);
     }
     NCurses.MoveAddChar(snake.Coordinates.First.Value.Y + 1, snake.Coordinates.First.Value.X + 1, Snake.SYMBOL_HEAD);
 }
Exemplo n.º 6
0
 private void Move(int x, int y)
 {
     if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
     {
         NCurses.Move(y, x);
     }
     else
     {
         Console.SetCursorPosition(x, y);
     }
 }
Exemplo n.º 7
0
 private void AutoResize()
 {
     if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
     {
         NCurses.ResizeTerminal(Width < NCurses.Columns ? NCurses.Columns : Width, NCurses.Lines);
     }
     else
     {
         Console.SetBufferSize(Width < Console.BufferWidth ? Console.BufferWidth : Width, Console.BufferHeight);
     }
 }
 internal void SetCursorPosition(Point position)
 {
     if (!usingLinux)
     {
         Win32.SetConsoleCursorPosition(stdOutputHandle, new COORD((short)position.x, (short)position.y));
     }
     else
     {
         NCurses.move(position.y, position.x);
         NCurses.refresh();
     }
 }
Exemplo n.º 9
0
        private void Render()
        {
            NCurses.Clear();
            NCurses.NoDelay(screen, true);

            RenderBorders();
            RenderSnake();
            RenderApple();
            RenderScore();

            NCurses.Refresh();
        }
Exemplo n.º 10
0
        private static void Fireworks()
        {
            NCurses.NoDelay(Screen, true);
            NCurses.NoEcho();

            if (NCurses.HasColors())
            {
                NCurses.StartColor();
                for (short i = 1; i < 8; i++)
                {
                    NCurses.InitPair(i, color_table[i], CursesColor.BLACK);
                }
            }

            int flag = 0;

            while (NCurses.GetChar() == -1)
            {
                int start, end, row, diff, direction;
                do
                {
                    start     = rng.Next(NCurses.Columns - 3);
                    end       = rng.Next(NCurses.Columns - 3);
                    start     = (start < 2) ? 2 : start;
                    end       = (end < 2) ? 2 : end;
                    direction = (start > end) ? -1 : 1;
                    diff      = Math.Abs(start - end);
                } while (diff < 2 || diff >= NCurses.Lines - 2);

                NCurses.AttributeSet(CursesAttribute.NORMAL);
                for (row = 1; row < diff; ++row)
                {
                    NCurses.MoveAddString(NCurses.Lines - row, row * direction + start, (direction < 0) ? "\\" : "/");
                    if (flag++ > 0)
                    {
                        MyRefresh();
                        NCurses.Erase();
                        flag = 0;
                    }
                }

                if (flag++ > 0)
                {
                    MyRefresh();
                    flag = 0;
                }

                Explode(NCurses.Lines - row, diff * direction + start);
                NCurses.Erase();
                MyRefresh();
            }
        }
Exemplo n.º 11
0
        public Game(Size size, int baseSnakeSize = 4)
        {
            this.size = size;

            random = new Random();
            snake  = new Snake(new Point(size.Height / 2, size.Width / 2), baseSnakeSize);
            GenerateNewApple();

            PlayerScore = 0;
            isGameOver  = false;

            screen = NCurses.InitScreen();
            NCurses.NoEcho();
        }
Exemplo n.º 12
0
        private void RenderBorders()
        {
            for (int i = 0; i < size.Width + 2; i++)
            {
                NCurses.MoveAddChar(0, i, SYMBOL_BORDER_HORIZONTAL);
                NCurses.MoveAddChar(size.Height + 1, i, SYMBOL_BORDER_HORIZONTAL);
            }

            for (int i = 0; i < size.Height; i++)
            {
                NCurses.MoveAddChar(i + 1, 0, SYMBOL_BORDER_VERTICAL);
                NCurses.MoveAddChar(i + 1, size.Width + 1, SYMBOL_BORDER_VERTICAL);
            }
        }
Exemplo n.º 13
0
        private static void Explode(int row, int col)
        {
            NCurses.Erase();
            AddStr(row, col, "-");
            MyRefresh();

            col--;

            GetColor();
            AddStr(row - 1, col, " - ");
            AddStr(row, col, "-+-");
            AddStr(row + 1, col, " - ");
            MyRefresh();

            col--;

            GetColor();
            AddStr(row - 2, col, " --- ");
            AddStr(row - 1, col, "-+++-");
            AddStr(row, col, "-+#+-");
            AddStr(row + 1, col, "-+++-");
            AddStr(row + 2, col, " --- ");
            MyRefresh();

            GetColor();
            AddStr(row - 2, col, " +++ ");
            AddStr(row - 1, col, "++#++");
            AddStr(row, col, "+# #+");
            AddStr(row + 1, col, "++#++");
            AddStr(row + 2, col, " +++ ");
            MyRefresh();

            GetColor();
            AddStr(row - 2, col, "  #  ");
            AddStr(row - 1, col, "## ##");
            AddStr(row, col, "#   #");
            AddStr(row + 1, col, "## ##");
            AddStr(row + 2, col, "  #  ");
            MyRefresh();

            GetColor();
            AddStr(row - 2, col, " # # ");
            AddStr(row - 1, col, "#   #");
            AddStr(row, col, "     ");
            AddStr(row + 1, col, "#   #");
            AddStr(row + 2, col, " # # ");
            MyRefresh();
        }
Exemplo n.º 14
0
 /// <summary>
 /// Делает курсор консоли невидимым и устанавливает значение
 /// CursorIsVisible в false.
 /// </summary>
 internal void HideCursor()
 {
     if (!usingLinux)
     {
         CONSOLE_CURSOR_INFO consoleCursorInfo = new CONSOLE_CURSOR_INFO {
             Size    = 5,
             Visible = false
         };
         Win32.SetConsoleCursorInfo(stdOutputHandle, ref consoleCursorInfo);
     }
     else
     {
         NCurses.curs_set(CursorVisibility.Invisible);
     }
     CursorIsVisible = false;
 }
Exemplo n.º 15
0
        public void Print(Board board)
        {
            NCurses.NoDelay(Screen, true);
            NCurses.NoEcho();

            for (int i = 0; i < board.height; i++)
            {
                StringBuilder buffer = new StringBuilder();
                for (int j = 0; j < board.width; j++)
                {
                    buffer.Append(board.board[i, j] ? '■' : ' ');
                }
                NCurses.MoveAddString(i, 0, buffer.ToString());
            }
            NCurses.Refresh();
        }
Exemplo n.º 16
0
 /// <summary>
 /// Writes collected data to console screen buffer, but paints specified rect only.
 /// </summary>
 public virtual void Flush(Rect affectedRect)
 {
     if (stdOutputHandle != IntPtr.Zero)
     {
         // we are in windows environment
         SMALL_RECT rect = new SMALL_RECT((short)affectedRect.x, (short)affectedRect.y,
                                          (short)(affectedRect.width + affectedRect.x), (short)(affectedRect.height + affectedRect.y));
         if (!Win32.WriteConsoleOutputCore(stdOutputHandle, buffer, new COORD((short)size.Width, (short)size.Height),
                                           new COORD((short)affectedRect.x, (short)affectedRect.y), ref rect))
         {
             throw new InvalidOperationException(string.Format("Cannot write to console : {0}", Win32.GetLastErrorMessage()));
         }
     }
     else
     {
         // we are in linux
         for (int i = 0; i < affectedRect.width; i++)
         {
             int x = i + affectedRect.x;
             for (int j = 0; j < affectedRect.height; j++)
             {
                 int y = j + affectedRect.y;
                 // todo : convert attributes and optimize rendering
                 bool  fgIntensity;
                 short index = NCurses.winAttrsToNCursesAttrs(buffer[y, x].Attributes,
                                                              out fgIntensity);
                 if (fgIntensity)
                 {
                     NCurses.attrset(
                         (int)(NCurses.COLOR_PAIR(index) | NCurses.A_BOLD));
                 }
                 else
                 {
                     NCurses.attrset(
                         (int)NCurses.COLOR_PAIR(index));
                 }
                 char outChar = buffer[y, x].UnicodeChar != '\0' ? (buffer[y, x].UnicodeChar) : ' ';
                 NCurses.mvaddstr(y, x, new string(outChar, 1));
             }
         }
         NCurses.refresh();
     }
 }
Exemplo n.º 17
0
        private void processInputEvent(INPUT_RECORD inputRecord)
        {
            if (inputRecord.EventType == EventType.WINDOW_BUFFER_SIZE_EVENT)
            {
                if (usingLinux)
                {
                    // Reinitializing ncurses to deal with new dimensions
                    // http://stackoverflow.com/questions/13707137/ncurses-resizing-glitch
                    NCurses.endwin();
                    // Needs to be called after an endwin() so ncurses will initialize
                    // itself with the new terminal dimensions.
                    NCurses.refresh();
                    NCurses.clear();
                }

                COORD dwSize = inputRecord.WindowBufferSizeEvent.dwSize;

                // Invoke default handler if no custom handlers attached and
                // userCanvasSize and userRootElementRect are not defined
                if (TerminalSizeChanged == null &&
                    userCanvasSize.IsEmpty &&
                    userRootElementRect.IsEmpty)
                {
                    OnTerminalSizeChangedDefault(this, new TerminalSizeChangedEventArgs(dwSize.X, dwSize.Y));
                }
                else if (TerminalSizeChanged != null)
                {
                    TerminalSizeChanged.Invoke(this, new TerminalSizeChangedEventArgs(dwSize.X, dwSize.Y));
                }

                // Refresh whole display
                renderer.FinallyApplyChangesToCanvas(true);

                return;
            }
            eventManager.ParseInputEvent(inputRecord, mainControl);
        }
Exemplo n.º 18
0
        private void runLinux(Control control)
        {
            this.mainControl = control;

            if (userCanvasSize.IsEmpty)
            {
                // Create physical canvas with actual terminal size
                winsize ws = Libc.GetTerminalSize(isDarwin);
                canvas = new PhysicalCanvas(ws.ws_col, ws.ws_row);
            }
            else
            {
                canvas = new PhysicalCanvas(userCanvasSize.Width, userCanvasSize.Height);
            }
            renderer.Canvas          = canvas;
            renderer.RootElementRect = userRootElementRect.IsEmpty
                ? new Rect(canvas.Size) : userRootElementRect;
            renderer.RootElement = mainControl;
            //
            mainControl.Invalidate();

            // Terminal initialization sequence

            // This is magic workaround to avoid messing up terminal after program finish
            // The bug is described at https://bugzilla.xamarin.com/show_bug.cgi?id=15118
            bool ignored = Console.KeyAvailable;

            IntPtr stdscr = NCurses.initscr();

            NCurses.cbreak();
            NCurses.noecho();
            NCurses.nonl();
            NCurses.intrflush(stdscr, false);
            NCurses.keypad(stdscr, true);
            NCurses.start_color();

            HideCursor();
            try {
                renderer.UpdateLayout( );
                renderer.FinallyApplyChangesToCanvas(  );

                termkeyHandle = LibTermKey.termkey_new(0, TermKeyFlag.TERMKEY_FLAG_SPACESYMBOL);

                // Setup the input mode
                Console.Write("\x1B[?1002h");
                pollfd fd = new pollfd( );
                fd.fd     = 0;
                fd.events = POLL_EVENTS.POLLIN;

                pollfd[] fds = new pollfd[2];
                fds[0] = fd;
                fds[1] = new pollfd( );
                int pipeResult = Libc.pipe(pipeFds);
                if (pipeResult == -1)
                {
                    throw new InvalidOperationException("Cannot create self-pipe.");
                }
                fds[1].fd     = pipeFds[0];
                fds[1].events = POLL_EVENTS.POLLIN;

                try {
#if !WIN32
                    // Catch SIGWINCH to handle terminal resizing
                    UnixSignal[] signals = new UnixSignal [] {
                        new UnixSignal(Signum.SIGWINCH)
                    };
                    Thread signal_thread = new Thread(delegate() {
                        while (true)
                        {
                            // Wait for a signal to be delivered
                            int index     = UnixSignal.WaitAny(signals, -1);
                            Signum signal = signals [index].Signum;
                            Libc.writeInt64(pipeFds[1], 2);
                        }
                    }
                                                      );
                    signal_thread.IsBackground = false;
                    signal_thread.Start();
#endif
                    TermKeyKey key = new TermKeyKey( );
                    //
                    this.running      = true;
                    this.mainThreadId = Thread.CurrentThread.ManagedThreadId;
                    //
                    int nextwait = -1;
                    while (true)
                    {
                        int pollRes = Libc.poll(fds, 2, nextwait);
                        if (pollRes == 0)
                        {
                            if (nextwait == -1)
                            {
                                throw new InvalidOperationException("Assertion failed.");
                            }
                            if (TermKeyResult.TERMKEY_RES_KEY == LibTermKey.termkey_getkey_force(termkeyHandle, ref key))
                            {
                                processLinuxInput(key);
                            }
                        }
                        if (pollRes == -1)
                        {
                            int errorCode = Marshal.GetLastWin32Error();
                            if (errorCode != Libc.EINTR)
                            {
                                throw new InvalidOperationException(string.Format("poll() returned with error code {0}", errorCode));
                            }
                        }

                        if (fds[1].revents != POLL_EVENTS.NONE)
                        {
                            UInt64 u;
                            Libc.readInt64(fds[1].fd, out u);
                            if (u == 1)
                            {
                                // Exit from application
#if !WIN32
                                signal_thread.Abort();
#endif
                                break;
                            }
                            if (u == 2)
                            {
                                // Get new term size and process appropriate INPUT_RECORD event
                                INPUT_RECORD inputRecord = new INPUT_RECORD( );
                                inputRecord.EventType = EventType.WINDOW_BUFFER_SIZE_EVENT;

                                winsize ws = Libc.GetTerminalSize(isDarwin);

                                inputRecord.WindowBufferSizeEvent.dwSize.X = ( short )ws.ws_col;
                                inputRecord.WindowBufferSizeEvent.dwSize.Y = ( short )ws.ws_row;
                                processInputEvent(inputRecord);
                            }
                            if (u == 3)
                            {
                                // It is signal from async actions invocation stuff
                            }
                        }

                        if ((fds[0].revents & POLL_EVENTS.POLLIN) == POLL_EVENTS.POLLIN ||
                            (fds[0].revents & POLL_EVENTS.POLLHUP) == POLL_EVENTS.POLLHUP ||
                            (fds[0].revents & POLL_EVENTS.POLLERR) == POLL_EVENTS.POLLERR)
                        {
                            LibTermKey.termkey_advisereadable(termkeyHandle);
                        }

                        TermKeyResult result = (LibTermKey.termkey_getkey(termkeyHandle, ref key));
                        while (result == TermKeyResult.TERMKEY_RES_KEY)
                        {
                            processLinuxInput(key);
                            result = (LibTermKey.termkey_getkey(termkeyHandle, ref key));
                        }

                        if (result == TermKeyResult.TERMKEY_RES_AGAIN)
                        {
                            nextwait = LibTermKey.termkey_get_waittime(termkeyHandle);
                        }
                        else
                        {
                            nextwait = -1;
                        }

                        while (true)
                        {
                            bool anyInvokeActions      = isAnyInvokeActions( );
                            bool anyRoutedEvent        = !EventManager.IsQueueEmpty( );
                            bool anyLayoutToRevalidate = renderer.AnyControlInvalidated;

                            if (!anyInvokeActions && !anyRoutedEvent && !anyLayoutToRevalidate)
                            {
                                break;
                            }

                            EventManager.ProcessEvents();
                            processInvokeActions(  );
                            renderer.UpdateLayout(  );
                        }

                        renderer.FinallyApplyChangesToCanvas( );
                    }
                } finally {
                    LibTermKey.termkey_destroy(termkeyHandle);
                    Libc.close(pipeFds[0]);
                    Libc.close(pipeFds[1]);
                    Console.Write("\x1B[?1002l");
                }
            } finally {
                // Restore cursor visibility before exit
                ShowCursor( );
                NCurses.endwin( );
            }

            renderer.RootElement = null;
        }
Exemplo n.º 19
0
 private static void MyRefresh()
 {
     NCurses.Nap(FRAMERATE);
     NCurses.Move(NCurses.Lines - 1, NCurses.Columns - 1);
     NCurses.Refresh();
 }
Exemplo n.º 20
0
 private void RenderApple()
 {
     NCurses.MoveAddChar(apple.Position.Y + 1, apple.Position.X + 1, Apple.SYMBOL);
 }
Exemplo n.º 21
0
 private void RenderScore()
 {
     NCurses.MoveAddString(size.Height + 2, 0, "Score : " + PlayerScore.ToString());
 }
Exemplo n.º 22
0
        private static void GetColor()
        {
            uint bold = (rng.Next(2) > 0) ? CursesAttribute.BOLD : CursesAttribute.NORMAL;

            NCurses.AttributeSet(NCurses.ColorPair((short)rng.Next(8)) | bold);
        }