Search code examples
c#winformspicturebox

C#, Windows Form, redraw pictureBox


I have a problem with C# game. There are a matrix with randomly-placed wolves and raccoons. When user click the "new game" button I need to generate new positions for animals and redraw my canvas (PicureBox). So, I have no problem with generating, but position of animals in pictureBox do not change (but it shows, when generates first time).

Also I tried to create several pictureBox with animal icons (and move it in game process), but they does not shown (I had added it in this.Controls, but nothing happened). Maybe there is some form manager like web-inspector in browsers to see what exactly happens?

I do not want to move a project to WPF Application.

Pieces of code below:

private static Bitmap _gameArea = new Bitmap(_gameAreaSize, _gameAreaSize);

Painted event (create a table):

        private void drawTable(object sender, PaintEventArgs e)
    {
        Pen p = new Pen(Color.LightSlateGray);

        var g = Graphics.FromImage(_gameArea);
       for (int i = 0; i < Configs.MatrixSize + 1; i++)
        {
            float coord = i * _cellSize;
            if (coord.Equals(_gameAreaSize))
                coord = _gameAreaSize - 1;

           g.DrawLine(p, coord, 0, coord, _gameAreaSize);
           g.DrawLine(p, 0, coord, _gameAreaSize, coord);
        }
        pictureBox1.BackgroundImage = _gameArea;

        g.Dispose();
    }

For game start and for new game click:

        GameLogic.InitGame(); // change positions, without threads
        RefreshMap();

RefreshMap:

        private static void RefreshMap()
    {
        var g = Graphics.FromImage(_gameArea);
        g.Clear(Color.White);
        g.Dispose();

        RefreshRacoons();
        RefreshWolves();
    }

I tried to make smth like this:

        private static void RefreshMap()
    {
        var sync = SynchronizationContext.Current;

        new Thread(__ =>
            sync.Post(_ =>
            {
                var g = Graphics.FromImage(_gameArea);
                g.Clear(Color.White);
                g.Dispose();

                RefreshRacoons();
                RefreshWolves();
            }, null)).Start();
    }

And refresh (with synContext and without it)

private static void RefreshRacoons()
    {
        foreach (var racoon in GameLogic.Racoons)
        {
           var g = Graphics.FromImage(_gameArea);
           g.DrawImage(_racoonImg,
               _cellSize * racoon.X + _offsetX,
               _cellSize * racoon.Y + _offsetY,
               _animalIconWidth,
               _animalIconHeight);

           g.Dispose();

        }
    }
    private static void RefreshWolves()
    {
        var sync = SynchronizationContext.Current;

        foreach (var wolf in GameLogic.Wolves)
        {
            new Thread(__ =>
                sync.Post(_ =>
                {
                    var g = Graphics.FromImage(_gameArea);
                    g.DrawImage(_wolfImg,
                        _cellSize * wolf.X + _offsetX,
                        _cellSize * wolf.Y + _offsetY,
                        _animalIconWidth,
                        _animalIconHeight);
                    g.Dispose();
                }, null)).Start();
        }
    }

Thank you!


Solution

  • My usual disclaimer is this: Windows Forms is not the right environemnt for game development. Turnbased singleplayer or hotseat multiplayer games can work, if you do not overdo it with animations. But Solitaire and Minesweeper are pretty much the upper limit of what is possible.

    There are a number of Dedicateed Display technologies/Engines avalible for game development. But in the end anything that allows you direct, low level drawing access and has a game loop of some sort should work out. While you can fake that in Windows Forms to some degree, you basically end up reinventing the wheel when you have a fully filled up car with keys in the Ignition just standing there.

    For .NET Framework, the dated soluation is the XNA Framework. But if you go for .NET Core, there is at least 3 official solutions: https://www.microsoft.com/net/learn/apps/gaming

    Most of wich work with Mono and some might even work with the .NET Framework (I have not tried it myself).