【C#】ピンポンゲームを作ろう メモ帳でプログラミング

C#ライン

ピンポンゲーム

今回の記事もメモ帳を使ったC#プログラミングをご紹介します。コンピュータと対戦するピンポンゲームを作成します。画像を使わずにメモ帳プログラミングでボール、バー、スコア表示を描画します。コード全文ご紹介しますのでぜひ昔懐かしのレトロ風ゲームで遊んでみてください!

準備

以前の記事を参考にC# を実行させるためのコンパイラのbatファイルを作成します。次も同様に以前の記事を参考にプログラムを実行するファイルを作成します。ファイル名は「pingpong.cs」にしましょう。この記事の最後に全コードを掲載していますのでメモ帳に全てコピペし保存します。コマンドプロンプトを起動し下記コマンドを実行します。

>cs pingpong.cs

コンパイルが成功すると「pingpong.exe」の実行ファイルがcsファイルと同じ場所に作成されます。

「pingpong.exe」をダブルクリックするとゲームがスタートします。

遊び方

ゲームがスターとするといきなりボールが動き出しますのでマウス上下でバーを操作しボールを打ち返します。右側がPLAYER、左側がENEMYです。10ポイント先取すると勝ちです。

全コード

下記がプログラムの全コードです。コードの詳細説明はしませんがコメントアウトで簡単に処理の説明を記述してあります。

using System;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

class FormPingPong : Form
{
    Label labelTitle = new Label();

    int ballSize = 30;
    int barWidth = 20;
    int barHeight = 120;
    int ballX, ballY;
    int dx = 5, dy = 5;
    int playerBarX, enemyBarX;
    int playerBarY, enemyBarY;
    int playerScore = 0, enemyScore = 0;
    int count = 0;
    Timer gameTimer;
    Random random = new Random();
  
    public FormPingPong()
    {
      //Size = new Size(600, 450);
      InitializeComponent(); 
      InitGame();   
    }

	private void InitializeComponent()
	{
        ///
        ///ラベルタイトルの設定
        ///
        this.labelTitle.AutoSize = true;
	this.labelTitle.Font = new Font("メイリオ", 24, FontStyle.Bold);
        this.labelTitle.Location = new Point(300, 10);
        this.labelTitle.Name = "labelTitle";
        this.labelTitle.Size = new Size(350, 60);
        this.labelTitle.Text = "ピンポンゲーム";
	///
     ///フォームFormSlotの設定
        ///
        this.Name = "FormPingPongs";
        this.Text = "ピンポンゲーム";
        this.AutoScaleDimensions = new SizeF(8, 15);
        this.AutoScaleMode = AutoScaleMode.Font;
        this.ClientSize = new Size(600, 450);
        this.Controls.Add(this.labelTitle);
    }

    private void InitGame()
    {
        // 初期化処理
        this.Width = 800;
        this.Height = 600;
        this.DoubleBuffered = true;

        // ボールの初期位置
        ballX = this.Width / 2 - ballSize / 2;
        ballY = this.Height / 2 - ballSize / 2;

        // プレイヤーと敵のバーの初期位置
        playerBarX = this.Width - barWidth - 50;
        enemyBarX = 50;
        playerBarY = this.Height / 2 - barHeight / 2;
        enemyBarY = this.Height / 2 - barHeight / 2;

        // ゲームタイマーの設定
        gameTimer = new Timer();
        gameTimer.Interval = 10;
        gameTimer.Tick += GameTick;
        gameTimer.Start();
    }

    private void GameTick(object sender, EventArgs e)
    {
        // ボールの移動
        ballX += dx;
        ballY += dy;


        // ボールの壁との衝突判定
        if (ballY <= 0 || ballY >= this.Height - ballSize)
        {
            dy = -dy;
        }

        // プレイヤーのバーにボールが当たったら跳ね返す
        if (ballX + ballSize >= playerBarX && ballY + ballSize >= playerBarY && ballY <= playerBarY + barHeight)
        {
            count += 1;
            dx = -Math.Abs(dx);
            dx = dx / Math.Abs(dx) * random.Next(5, 20);  // 速度ランダム化
        }

 
        // 敵のバーにボールが当たったら跳ね返す
        if (ballX <= enemyBarX + barWidth && ballY + ballSize >= enemyBarY && ballY <= enemyBarY + barHeight)
        {
            dx = Math.Abs(dx);
            dx = dx / Math.Abs(dx) * random.Next(5, 20);  // 速度ランダム化
        }

        // 敵のバーの自動移動
        if (enemyBarY + barHeight / 2 > ballY)
            enemyBarY -= 5;
        else
            enemyBarY += 5;
            //5回に1回チャンス
            if (count % 5 == 0) { 
                enemyBarY -= 2;
            }

        // 敵のバーが画面外に出ないようにする
        if (enemyBarY < 0)
            enemyBarY = 0;
        if (enemyBarY > this.Height - barHeight)
            enemyBarY = this.Height - barHeight;

        // スコア判定
        if (ballX <= 0)
        {
            playerScore++;
            count = 0;
            ResetBall();
        }
        if (ballX >= this.Width - ballSize)
        {
            enemyScore++;
            count = 0;
            ResetBall();
        }

        // 勝敗判定
        if (playerScore >= 10)
        {
            gameTimer.Stop();
            this.labelTitle.Text = "PLAYER WIN";
            InitGame();
        }
        if (enemyScore >= 10)
        {
            gameTimer.Stop();
            this.labelTitle.Text = "ENEMY WIN";
            InitGame();
        }

        // 画面の再描画
        Invalidate();
    }

    private void ResetBall()
    {
        ballX = this.Width / 2 - ballSize / 2;
        ballY = this.Height / 2 - ballSize / 2;
        dx = random.Next(2) == 0 ? 5 : -5;
        dy = random.Next(2) == 0 ? 5 : -5;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;

        // 背景を黒で塗りつぶす
        g.Clear(Color.Black);

        // プレイヤーのバーを描画
        g.FillRectangle(Brushes.Blue, playerBarX, playerBarY, barWidth, barHeight);

        // 敵のバーを描画
        g.FillRectangle(Brushes.Red, enemyBarX, enemyBarY, barWidth, barHeight);

        // ボールを描画
        g.FillEllipse(Brushes.White, ballX, ballY, ballSize, ballSize);

       	// スコアを表示
    	g.DrawString("PLAYER: " + playerScore.ToString(), 
            new Font("メイリオ", 18), Brushes.White, this.Width - 160, 10);
        g.DrawString("ENEMY: " + enemyScore.ToString(), 
            new Font("メイリオ", 18), Brushes.White, 20, 10);
        g.DrawString("COUNT: " + count.ToString(), 
            new Font("メイリオ", 18), Brushes.White, 320, 80);
	}

    // マウスの移動に応じてプレイヤーのバーを移動
    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        playerBarY = e.Y - barHeight / 2;

        // プレイヤーのバーが画面外に出ないようにする
        if (playerBarY < 0)
            playerBarY = 0;
        if (playerBarY > this.Height - barHeight)
            playerBarY = this.Height - barHeight;

        Invalidate();  // 再描画
    }


    static void Main()
    {
        Application.Run( new FormPingPong() );
    }

}

まとめ

いかがだったでしょうか。このようにメモ帳プログラミングで昔懐かしのレトロゲームを作成することができます。コード量はちょっと多めですがゲームの作り方がちょっとでも伝わればと思います。この機会にゲームプログラミングをはじめてみましょう!

コメント