0

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!

LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • In each loop of RefreshRacoons and RefreshWolves you restart from scratch. Also: you don't re-assign the result to the pbox.image but you have to.. Not sure why you complicate matters with thread and sync before the basics are working. – TaW Apr 18 '18 at 13:35
  • 1
    I find method "pictureBoxElem.Refresh()" and tried it (and move creating and disposing out of loop), and now animals change their position, thanks! I had no idea why firstly they shown, and next icons do not do it – Олень Безрогий Apr 18 '18 at 13:49
  • Im not seeing any code here to randomize the wolves or raccoons locations – BugFinder Apr 18 '18 at 13:58
  • I do not understand for what, they randomize correctly (checked in debugging), and now programm work correctly at all (I dont know how I can close a question) – Олень Безрогий Apr 18 '18 at 14:02
  • Post your own answer and accept it if you have one. – LarsTech Apr 18 '18 at 14:10
  • You changed the bitmap but PictureBox is completely unaware of it. You didn't reassign its BackgroundImage property and the Image class has no events. You therefore have to help, add pictureBox1.Invalidate(). – Hans Passant Apr 18 '18 at 14:25

1 Answers1

-2

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).

Christopher
  • 9,634
  • 2
  • 17
  • 31