0

Я пытаюсь простенькую анимацию подкидывания монетки и тем самым нахождение победителя: орла или решки.

async void TossCoin() {
  var random = new Random();
  await Task.Run(() => {
    //Количестов поворотов монетки
    var number = random.Next(9, 11);
    // Цикл соответствует количеству поворотов монетки
    for (int i = 0; i < number; i++) {
      // Если поворот нечетный, то сторона решки сжимается до тех пор, пока не достигнет ширины 0, а затем орел начинает
      // наоборот набирать ширину, таким образом должна создаваться иллюзия вращения монетки.
      if (i % 2 != 0) {
        while (imageTail.Width > 0) {
          imageTail.Invoke(() => imageTail.Width--);
        }
        imageTail.Invoke(() => imageTail.Visible = false);
        imageEagle.Invoke(() => imageEagle.Visible = true);
        while (imageEagle.Width != 200) {
          imageEagle.Invoke(() => imageEagle.Width++);
        }
      }
      // То же самое, но наоборот
      if (i % 2 == 0) {
        while (imageEagle.Width > 0) {
          imageEagle.Invoke(() => imageEagle.Width--);
        }
        imageTail.Invoke(() => imageTail.Visible = true);
        imageEagle.Invoke(() => imageEagle.Visible = false);
        while (imageTail.Width != 200) {
          imageTail.Invoke(() => imageTail.Width++);
        }
      }
    }
    // Если последний поворот остановилься на стороне решки, то победа засчитывается решке.
    if (imageTail.Visible == true) {
      Coin.CountOfTails++;
      labelCountEagleWins.Invoke(() => labelCountTailsWins.Text = $ "Решка победила {Coin.CountOfTails} раз");
    }
    // То же самое, но наоборот
    else {
      Coin.CountOfEagles++;
      labelCountEagleWins.Invoke(() => labelCountEagleWins.Text = $ "Орёл победил {Coin.CountOfEagles} раз");
    }
  });
}

Проблема в том, что при создании PictureBox, куда помещено изображение одной из двух сторон одной монеты, можно указать только один SizeMode.

var imageEagle = new PictureBox {
  Image = Resources.ImageEagle,
    Location = new Point(this.Width - this.Width / 3 - 55, this.Height / 3 - 40),
    Size = new Size(0, 200),
    Visible = false,
    SizeMode = PictureBoxSizeMode.StretchImage,
};

Таким образом я не могу указать сразу два SizeMode. Либо StretchImage, либо CenterImage. Получается, что в процессе монетка либо сжимается (если указать StretchImage), вместо того, чтобы удалять часть изображения, либо централизуется (если указать CenterImage), но при этом будет терять часть изображения, вместо сжатия.
Можно ли каким-то образом убить двух зайцем одним выстрелом, чтобы и сжимать, сохраняя изображение, и централизовать сжатие?

De.Minov
  • 24,026
  • Зачем использовать сторонний поток, если вся работа всё равно инвокается обратно в UI? ) – aepot Jan 08 '23 at 21:07
  • Используйте исходное изображение с заранее нужным соотношением сторон. А анимацию можно и в GIF засунуть, или даже в MP4. Зря изобретаете. Берите обычный графический редактор и делайте анимацию там. Всё равно этот код выглядит очень жестоко. – aepot Jan 08 '23 at 21:12
  • aepot, сторонний поток использую для того,чтобы на время выполнения приложение не висло и могло дальше продолжать свою работу, в том числе передвигаться по экрану. А инвокаю обратно потому, что если я буду изменять результат победы в главном треде, то он изменится сразу не дождавшись результатов броска, что приведет к неизменности результата. – richmen Jan 08 '23 at 22:35
  • Графический редактор неплохая идея, но неужели все же нельзя сделать так, как я хотел? Или это слишком сложно? Почему код выглядит очень жёстко? – richmen Jan 08 '23 at 22:37
  • Ну далеко ходить не надо, хотя-бы async void, совершенно бессмысленный, так как при возникновении исключения внутри потока, приложение просто упадёт. Добавьте try-catch. Я кучу раз здесь писал об этом. А потом, хотите анимацию свойств толковую - вот пример – aepot Jan 09 '23 at 07:43
  • Ну и рандом создать тоже можно внутри потока, раз уж на то пошло – aepot Jan 09 '23 at 09:25

0 Answers0