ゲーム実装で身に付くプログラミング 第12回

背景色を反映させる

背景色を反映させる

このゲームのテーマでもある背景色を、「rgb」配列に応じて反映させます(図3)。背景色の(R,G,B)は、rgb配列の要素の最大値を分母にし、各要素に255(色は0~255の範囲で表す)を乗算して求めます。つまり要素の数値が大きいほどその色が明るくなります。

図3:背景色を反映

・サンプルコード「MainWindow.xaml.cs」ファイル

(前略)

namespace colorWinUI
{
    public sealed partial class MainWindow : Window
    {
        DispatcherTimer timer = new();
        List<Sprite> sprites = new();
        readonly Random rand = new();
        int stage = 2;
        readonly int[] rgb = new int[3];
        readonly List<MediaPlayer> sounds = new();

        public MainWindow()
        {
(中略)
        }

        private void TitleImage_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
(中略)
        }

        void Init()
        {
            rgb[0] = 0;
            rgb[1] = 0;
            rgb[2] = 0;
            while (rgb[0] == rgb[1])
            {
                rgb[0] = rand.Next(0, stage);
                rgb[1] = rand.Next(0, stage);
                rgb[2] = rand.Next(0, stage);
            }
            ImageCanvas.Children.Clear();
            sprites.Clear();
            for (int i = 0; i < 3 * stage; i++)
            {
                sprites.Add(new Sprite(ImageCanvas, i % 3));
                int count = ImageCanvas.Children.Count - 1;
                ImageCanvas.Children[count].PointerPressed += Child_PointerPressed;
            }
        }

        void Child_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
        }

        void Timer_Tick(object? sender, object e)
        {
            var flg = 0;
            for (int i = 0; i < sprites.Count; i++)
            {
                flg += sprites[i].Update(ImageCanvas,i);
            }
            // ゲームオーバー判定
            if (flg == 0)
            {
                timer.Stop();
                TitleGrid.Visibility = Visibility.Visible;
                sounds[1].Play();
            }
            // 背景描画とステージクリア判定
            if (BgColor())
            {
                stage++;
                Init();
                sounds[2].Play();
            }
        }

        bool BgColor()
        {
            int max = rgb[0] < rgb[1] ? (rgb[1] < rgb[2] ? 2 : 1) : (rgb[0] < rgb[2] ? 2 : 0);
            int i = 255 / rgb[max];
            byte r = (byte)(i * rgb[0]);
            byte g = (byte)(i * rgb[1]);
            byte b = (byte)(i * rgb[2]);
            var color = Windows.UI.Color.FromArgb(255, r, g, b);
            RootGrid.Background = new SolidColorBrush(color);
            if (r == g && g == b) return true;
            return false;
        }
    }
}

【サンプルコードの解説】
rgb配列を3要素で宣言します。
「Init」メソッドでゲーム開始時にrgbの各要素を1~stage未満のランダムな整数にセットします。
「Timer_Tick」メソッドで毎フレーム背景色をセットし、背景色が真っ白(r・g・bが同じ数値)になったら"StageClear.ogg"サウンドを再生し、stageプロパティをインクリメントして次のステージへ遷移します。
「BgColor」メソッドで、例えばrgbの各要素が(3,5,4)なら(R,G,B)=(255*3/5,255*5/5,255*4/5)のように計算します。r・g・bの各変数が同値、つまり真っ白なら戻り値としてtrueを返します。

色ブロックをクリックして背景色に混ぜる

色ブロックがクリックされたら消して、その色のrgb要素をインクリメントします。rgb要素は単なる0~の整数で、BgColorメソッドで背景色で使う色に変換します。

・サンプルコード「MainWindow.xaml.cs」ファイル

(前略)

namespace colorWinUI
{
    public sealed partial class MainWindow : Window
    {
(中略)

        public MainWindow()
        {
(中略)
        }

        private void TitleImage_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
(中略)
        }

        void Init()
        {
(中略)
        }

        void Child_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            var child = (UIElement)sender;
            for (int i = 0; i < ImageCanvas.Children.Count; i++)
            {
                if (ImageCanvas.Children[i] == child)
                {
                    sprites[i].x = 1000000;
                    rgb[sprites[i].color]++;
                    sounds[3].Pause();
                    sounds[3].PlaybackSession.Position = TimeSpan.Zero;
                    sounds[3].Play();
                    break;
                }
            }
        }

        void Timer_Tick(object? sender, object e)
        {
(中略)
        }

        bool BgColor()
        {
(中略)
        }
    }
}

【サンプルコードの解説】
ImageCanvasの各色ブロックがマウスで押されたらChild_PointerPressedが呼ばれ、色ブロックのSpriteをsprites配列から削除するのではなく、画面外の遠くに移動して見えなくします。その色のrgb要素をインクリメントし、"Mix.ogg"サウンドを頭出しして再生します。

【コラム】作家アーティスト会社役員

「作家アーティスト会社役員」でググると僕のプロフィールサイトが1番にヒットします。でも、手塚治虫先輩は漫画家でアーティストで会社経営者で医学博士でした。しかもどれも超一流。レベルが違いました…。

おわりに

今回は、第6回と同じ「C#」言語でプログラミングしました。UIフレームワークは最新鋭の「WinUI」を使いましたが、UIをXAMLで構築する以外は「Windows Forms」と大差なかったのではないかと思います。今後「.NET」の「WPF」と「UWP」でも解説できたらと思います。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored