SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

C++Builder XE2+FireMonkeyで昔のラケットゲームを再構築してみる(3)

15年前の入門書の課題を、最新の開発環境を使って再挑戦

  • X ポスト
  • このエントリーをはてなブックマークに追加

ラケットの当たり判定

当たり判定関数の作成

 ラケットにボールが当たったかの判定は、ボールの現在位置と次の位置を結ぶ線と、ラケットが交差するかどうかで判別します。Y座標がラケットの位置のときのボールのX座標を求めるには、DeltaX、DeltaYを利用します。

 CheckHit関数は、ラケットでボールをヒットしたかどうかの判別を行う関数です。引数のox、oyはボールの移動前の座標です。nx、nyは異動後の座標で、ラケットに当たったときには、ラケット上の座標に変更されます。Position型のr変数は、ラケットの座標を表します。この関数は、ラケットに当たったときはtrueを返し、当たっていないときはfalseを返します。

bool __fastcall TGameForm::CheckHit(int ox, int oy, int &nx, int &ny, TPosition *r)
{
    int ncx;
    if (oy < ny) {  // ボールが下に向かって動いているとき
        // ボールがラケットの Y座標を通過したか?
        if (oy < r->Y && ny >= r->Y) {
            // ラケットとボールの奇跡の交点のX座標を求める
            ncx = ox + (int)((double)DeltaX * (double)(oy - r->Y) / (double)(oy - ny));
            // 交点のX座標がラケットの矩形内にあるか?
            if (ncx > r->X - Ball->Width && ncx < r->X + Racket->Width) {
                // 交点の座標を移動後のボール座標にセット
                nx = ncx;
                ny = oy + (int)((double)DeltaY * (double)(oy - r->Y) / (double)(oy - ny));
                return true;
            }
        }
    }
    else {  // ボールが上に向かって動いているとき
        // ボールがラケットの Y座標を通過したか?
        if (oy < r->Y + Racket->Height && ny >= r->Y + Racket->Height) {
            // ラケットとボールの奇跡の交点のX座標を求める
            ncx = ox + (int)((double)DeltaX * (double)(oy - (r->Y + Racket->Height)) 
                      / (double)(oy - ny));
            // 交点のX座標がラケットの矩形内にあるか?
            if (ncx > r->X - Ball->Width && ncx < r->X + Racket->Width) {
                // 交点の座標を移動後のボール座標にセット
                nx = ncx;
                ny = oy + (int)((double)DeltaY * (double)(oy - (r->Y + Racket->Height))
                      / (double)(oy - ny));
                return true;
            }
        }
    }
    return false;
}

 GameUnit.h にこの関数の宣言を追加します。

private:    // ユーザー宣言
    int Ang, DeltaX, DeltaY;
    double Speed;
    void __fastcall MoveBall();
    void __fastcall CalcNewDelta();
    bool __fastcall CheckHit(int ox, int oy, int &nx, int &ny, TPosition *r);

MoveBall内にラケットの当たり判定を追加

 この関数は、MoveBall関数内で使用します。MoveBall関数の以下の箇所にラケットの当たり判定を処理するコードを記述します(太字部分)。ここでは、ラケットの角でボールをひっかけたときに思わぬ方向に跳ね返るコードも追加しています。

void __fastcall TGameForm::MoveBall()
{
    // 移動後のボールの位置を計算します
    int x = Ball->Position->X + DeltaX;
    int y = Ball->Position->Y + DeltaY;

    // ラケットにヒットしたかどうかを判定
    TPosition *pos = Racket->Position; // ラケットの座標
    if (CheckHit(Ball->Position->X, Ball->Position->Y, x, y, pos)) {
        if (x < pos->X + 2 || x + Ball->Width > pos->X + pos Width - 2)
            Ang = 360 - Ang + (random(60) - 30);  // 角で引っかけた
        else
            Ang = 360 - Ang;  // 正しくヒット
        Ball->Position->X = x;
        Ball->Position->Y = y;
        CalcNewDelta();
        MessageBeep(-1);
        return;
    }

    // 壁に当たったかの判定
    if (y + Ball->Height >= Court->Height) {  // 下の壁
        // 壁に当たった
            :
            :
            :

動作を確認してみる

 では、プログラムを実行して動作を確認してみましょう。

図5 ラケットに当たった
図5 ラケットに当たった

 ラケットを上手に動かして、正しい位置でボールを打つとちゃんと跳ね返りますが、ラケットの角でひっかけてしまうと、思わぬ方向に飛びます。このときの角度の計算には、乱数を使っています。

図6 ラケットの角でボールをひっかけた
図6 ラケットの角でボールをひっかけた

 ラケットとボールを移動させるコートを記述して、だいぶゲームらしくなってきましたね。

 次回は、スコアのカウントや、ボールを打ち損ねたときのラケットの処理など、ゲームの進行にかかわるコードを記述して、ゲームを完成させます。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

EDN編集部(イーディーエヌ編集部)

エンバカデロ・デベロッパーネットワーク(EDN)は、ソフトウェア開発者とデータベース技術者のための技術情報サイトです。Delphi、C++Builderをはじめとする開発ツールやER/Studioなどのデータベースツールに関連する技術記事、ビデオなどを提供しています。EDN編集部は、EDN記事と連携...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6635 2012/06/28 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング