Javaでクラシックなピンポンゲームを作成する

ピンポンを示すGIF。

この記事のピンポンゲームを示すGIF。

古典的なピンポンゲームを再現する方法を説明するチュートリアルをお探しですか?次に、もう探す必要はありません。この記事では、ProcessingライブラリとJavaを使用してゲームを再作成することに焦点を当てています。また、別のゲームを作成したい場合に、古典的なヘビゲームを再現する方法についての別の記事を書きました。

1.Processingをダウンロードしてインストールします

Processingをダウンロードするには、processing.org / downloadにアクセスし、優先プラットフォームに一致するバージョンを選択してください。

2.処理とは何ですか?

Processingは、グラフィカルライブラリと統合開発環境(IDE)を提供し、プログラミング言語Java(Wikipedia、2022a)を使用します。

3.ゲームの要件

ゲームの要件は、2つの異なる部分で提示されます。最初の部分では、プレーヤー、ボール、および環境の表現に関連する視覚的な要件について説明します。2番目の部分では、さまざまなオブジェクトとアプリケーションがどのように動作するかという機能要件について説明します。

3.1視覚的要件

  • プレーヤーオブジェクトは長方形で表す必要があります。
  • ボールオブジェクトは円で表す必要があります。
  • ゲームには、各プレーヤーのスコアを示す2つのテキスト要素が含まれている必要があります。

3.1機能要件

  • プレーヤーオブジェクトは、y軸上でのみ移動できる必要があります。
  • ボールオブジェクトは、x軸とy軸で移動できる必要があります。
  • ボールオブジェクトは、プレーヤーオブジェクトと重なる場合、x軸上の方向を反対方向に変更する必要があります。
  • ボールオブジェクトがy軸で画面の外に移動した場合、ボールオブジェクトはy軸での方向を反対に変更する必要があります。
  • ボールオブジェクトがx軸で画面の外に移動した場合は、ボールオブジェクトの位置と方向をリセットする必要があります。
  • ボールが反対側の画面から移動するたびに、プレーヤーはポイントを獲得します。
  • 最初のプレーヤーはキーボードで制御し、2番目のプレーヤーはコンピューターで制御する必要があります。

4.ゲームオブジェクト

ゲームには2つの異なるクラスが含まれます。1つはプレーヤーオブジェクトを表し、もう1つはボールオブジェクトを表します。図1は、2つのクラスを含むUMLクラス図を示しています。UMLクラス図について聞いたことがない人にとっては、それは単にシステムのクラス、プロパティ、メソッド、および関係を含む図です(Wikipedia、2022b)。

図1:ピンポンゲームで使用される2つのクラスを示すUMLクラス図。

図1:ピンポンゲームで使用される2つのクラスを示すUMLクラス図。

4.1プレーヤーオブジェクト

プレーヤークラスは両方のプレーヤーのオブジェクトを作成するために使用されるため、位置とy方向はプレーヤーごとに一意であることが重要ですが、値が値であるため、幅、高さ、境界は静的変数である可能性があると主張できます。すべてのオブジェクトで同じです。図2は、プレーヤーの配置と動きの境界の背後にある考え方を示しています。

各プレーヤーのプロパティと、プレーヤーが移動できるパス(赤い線)を示すGIF。

図2:各プレーヤーのプロパティとプレーヤーが移動できるパス(赤い線)を示すGIF。

4.1.1。プレーヤーのプロパティ

クラスには5つのプロパティが必要であり(図1を参照)、これらの各プロパティには次の目的があります。

  • positionPVectorプレーヤーのxとyの位置を定義するA。
  • yDirfloatプレーヤーの動きの方向と速度を定義するA。
  • wfloatプレーヤーの長方形の幅を定義します。
  • hfloatプレーヤーの長方形の高さを定義します。
  • bfloatプレーヤーの動きの境界を定義します。

プレーヤークラスのプロパティの実装を図3に示します。

class Player {
  // Current position
  PVector position;
  
  // Movement direction
  float yDir;
  
  // Size
  float w = 10;
  float h = 25;
  
  // Boundaries
  float b = 15;
}

図3:プレーヤークラスのプロパティの実装を示しています。

4.1.2。プレイヤーメソッド

このクラスには5つのメソッドも必要であり(図1を参照)、これらの各プロパティには次の目的があります。

  • update()—ビジュアルオブジェクトの移動、境界チェック、および描画に関連するプレーヤーの動作を更新するために使用されるvoidメソッド。
  • setDirection(yDir)—y軸上のプレーヤーオブジェクトの方向を更新するために使用されるセッターメソッド。
  • getPosition()—プレーヤーオブジェクトの位置を返すgetterメソッド。
  • getHeight()—プレーヤーオブジェクトの高さを返すgetterメソッド。
  • getWidth()—プレーヤーオブジェクトの幅を返すgetterメソッド。

Playerクラスには、y軸上の位置と方向の初期値を設定するコンストラクターも必要です。コンストラクターの引数は、コンストラクター内でプレーヤーの位置の新しいオブジェクトfloatsのインスタンスを作成するために使用される開始位置を表すように設計されています。PVector

これにより、プレーヤーオブジェクトがメモリ内の同じオブジェクトを参照しないようになります。これは、インスタンス化PVector時に複数のプレーヤーオブジェクトに同じオブジェクトが与えられた場合に発生する可能性があります。PVector

方向のgetterメソッドを使用すると、クラス外のオブジェクトに方向を設定できます。position、height、widthのsetterメソッドを使用すると、クラス外のオブジェクトでこれらのプロパティを読み取ることができます(図の実装を参照)。 4)。

class Player {
  
  // ... Properties here.

  // Player constructor
  public Player(float x, float y, float yDir) {
    this.position = new PVector(x, y);
    this.yDir = yDir;
  }
  
  // Setter Methods
  
  public void setDirection(float yDir) {
    this.yDir = yDir;
  }
  
  // Getter Methods
  
  public PVector getPosition() {
    return position;
  }
  
  public float getHeight() {
    return h;
  }
  
  public float getWidth() {
    return w;
  }
}

図4:プレーヤーコンストラクター、およびゲッターメソッドとセッターメソッドの実装を示しています。

プレーヤークラスで必要な最後のメソッドはupdate()メソッドです。図5に、メソッドの実装を示します。

class Player {
  
  // ... Properties here.
  // ... Player constructor here.
  // ... Setter Methods here.
  // ... Getter Methods here.
  
  public void update() {
    // Update player position
    position.y += yDir;
    
    // Have the player reached
    // the top?
    if (position.y < b) {
      // Stop movement at the top
      position.y = b;
    // Have the player reached
    // the bottom?
    } else if (position.y > height-b-h) {
      // Stop the movement at the bottom
      position.y = height-b-h;
    }
    
    // Set player color to white
    fill(255);
    // Draw rectangle
    rect(position.x, position.y, w, h);
  }
}

図5:プレーヤーの更新メソッドの実装を示しています。

その動作は次のように説明できます。

  • 10行目—この行は、の値が正の場合はプレーヤーのy位置を増やし、の値が負ydirの場合はプレーヤーのy位置を減らします。ydir
  • 14行目—最初の行は、プレーヤーのy位置がb、プレーヤーの動きの境界を定義するために使用された値よりも小さいかどうかをチェックします。つまり、プレーヤーが画面上部の境界に達した場合です。
  • 16行目—プレーヤーのy位置をの値にリセットして、プレーヤーbが画面の上部に向かってそれ以上移動しないようにします。
  • 19行目— 14行目と同様のチェックですが、代わりにプレーヤーが画面の下部に到達したかどうかをチェックします。このチェックには、プレーヤーの高さと、b長方形が正しい位置で停止することを確認するためのの値が含まれます(説明については図6を参照)。
  • 21行目—画面下部のプレーヤーのy位置をリセットして、プレーヤーがy軸上で画面の外に移動しないようにします。

プレーヤーオブジェクトはアンカーポイント(positionプロパティの値)で移動するため、画面の高さからbとhを引いたところで停止して、長方形の下側が境界に達したときに確実に停止するようにする必要があります。

図6:プレーヤーオブジェクトはアンカーポイント(positionプロパティの値)で移動するため、画面の高さbを引いたところでh停止し、長方形の下側が境界に達したときに確実に停止する必要があります。

プレーヤークラスの最後の例は、このリンクにあります。

4.2ボールオブジェクト

ボールクラスはプレーヤークラスと非常に似ていますが、x軸とy軸の両方で移動できます。図7は、ボールが移動するときにボールの位置と方向の値がどのように変化するかを示しています。

ボールオブジェクトのプロパティを示すGIF。

図7:ボールオブジェクトのプロパティを示すGIF。

4.1.1。ボールのプロパティ

図1は、ボールクラスに次のように説明できる4つのプロパティが必要であることを示しています。

  • positionPVectorボールのxとyの位置を定義するA。
  • directionPVectorボールの動きの方向と速度を定義するA。
  • dfloatボールの円の直径を定義します。
  • sfloatボールの開始速度を定義します。

ボールのプロパティの実装を図8に示します。

class Ball {
  // Current position
  PVector position;
  
  // Current direction
  PVector direction;
  
  // Diameter of the circle
  float d = 15;
  
  // The speed of the ball
  float s = 5;
}

図8:ボールクラスのプロパティの実装。

4.1.2。ボールメソッド

ボールクラスには、プレーヤークラスとして次のように説明できる5つのメソッドも必要です。

  • update()—ボールの動き、境界、およびビジュアルを更新するvoidメソッド。
  • getPosition()—ボールの位置を返すゲッターメソッド。
  • resetMovement()—ボールの位置を画面の中央にリセットし、その方向をランダムな値にリセットするvoidメソッド。
  • setDirection(x)-ボールのx方向を設定するセッターメソッド。
  • overlapsWith(player)—ボールが指定されたプレーヤーとオーバーラップした場合にtrueを返すブールメソッド。

ボールのコンストラクターとメソッド、、、、の実装を図getPosition()9resetMovement()に示します。setDirection(x)update()

class Ball {
  
  // ... Properties here.
  
  // Ball constructor
  public Ball() {
    resetMovement();
  }
  
  // Getter Methods
  
  public PVector getPosition() {
    return position;
  }
  
  // Reset position and randomize direction.
  
  public void resetMovement() {
    // Set position to the center of the screen
    position = new PVector(width/2, height/2);
    
    // Get a random speed
    float speed = random(-s, s);
    // Set the y direction to half of the speed
    // to ensure it moves faster in the left or
    // right direction
    direction = new PVector(speed, speed/2);
  }
  
  // Set direction on the x-axis.
  
  public void setDirection(float x) {
     direction.x = x * speed;
  }
  
  // Updates the ball's position, add boundaries 
  // and draw its visuals.
  
  public void update() {
    // Add velocity
    position.add(direction);
    
    // Check if the ball has reached the top
    // or the bottom of the screen.
    if (position.y < 0 || position.y > height) {
      // Invert the direction on the y-axis.
      direction.y = -direction.y;
    }
    
    // Set the fill color to white.
    fill(255);
    // Draw the ball's circle.
    circle(position.x, position.y, d); 
  }
}

図9:ボールのコンストラクターの実装、およびメソッドgetPosition()、resetMovement()、invertDirectionX()、およびupdate()。

4.1.2。衝突方法

ボールクラスに実装する必要がある最後のメソッドはoverlapsWith(player)メソッドです。実装を示す前に、ソリューションの背後にある数学的アイデアについて簡単に説明したいと思います。

図10は、座標系内に描画されたボールを示しています。アンカーポイントはオリゴに配置されています。アンカーポイントはpositionボールの特性と同じです。

図の各ベクトル/矢印は、衝突チェックで使用する必要があるアンカーポイントを基準にしたポイントを指しています。ポイントは、度をラジアンに変換する式と回転行列によって計算できます。

この図は、座標系内で描画されたボールを示しています。 アンカーポイントはボールの位置であり、各ベクトル/矢印はボールのアンカーポイントを基準にしたポイントを指します。 各ベクトルは45度回転します。

図10:この図は、座標系内に描画されたボールを示しています。アンカーポイントはボールの位置であり、各ベクトル/矢印はボールのアンカーポイントを基準にしたポイントを指します。各ベクトルは45度回転します。

度をラジアンに変換する式は、次のように定義できます(Wikipedia、2022c)。

度をラジアンに変換するための式。

ベクトルv、 θラジアンを回転させる式は次のように定義できます(Wikipedia、2022d)。

ベクトルv、θラジアンを回転させるための式

上記の式で計算されたポイントは、そのうちの1つがプレーヤーのコーナーポイントの間にあるかどうかを確認するために使用されます。これは、ボールがプレーヤーとオーバーラップしていることを意味します(図11を参照)。

図11:この図は、プレーヤーオブジェクトがボールオブジェクトと重なっているところを示しています。また、位置、幅、高さのプロパティに基づいて、プレーヤーの各コーナーポイントが表示されます。

図12の24行目は、度をラジアンに変換するために使用される式の実装を示し、図12の28〜29行目は、2Dベクトルを45度回転するために使用される回転行列の実装を示しています。

図12の33〜34行目は、ポイントがプレーヤーのコーナーポイント内にある場合にtrueを返すチェックを示しています。

class Ball {
  
  // ... Properties here.
  // ... Ball constructor
  // ... Getter Methods
  // ... Reset position and randomize direction method here.
  // ... Invert direction method here.
  // ... Update method here.
  
  public boolean overlapsWith(Player player) {
    // Get player position,
    // width, and height.
    var p = player.getPosition();
    var w = player.getWidth();
    var h = player.getHeight();
    
    // Calculate radius.
    var r = d/2;
    
    // Loop eight points.
    for (int i = 0; i < 8; i++) {
       
       // Convert i * 45 degrees to radians. 
       var degree = (i * 45) * (PI/180);
       
       // Calculate x and y points by rotating a vector
       // relative to the position 45 degrees
       var x = r * cos(position.x + degree) + position.x;
       var y = r * sin(position.y + degree) + position.y;

       // Return true if the point is within on both
       // the x-axis and the y-axis.
       if (p.x < x && x < p.x + w &&
           p.y < y && y < p.y + h) return true;
    }
    
    // If none of the points were within
    // the player, return false.
    return false;
  }
}

図12:この図は、「overlapsWith(player)」メソッドの実装を示しています。

ボールクラスの最後の例は、このリンクにあります。

5.処理制御フローの設定

アプリケーションにはsetup()、アプリケーションの起動時に実行されるメソッドdraw()(Processing.org、2022a)、停止するまでフレームごとに1回実行されるメソッド(Processing.org、2022b)、およびkeyPressed()キーが押されました(Processing.org、2022c)。

5.1グローバルプロパティ

ゲームには、プレーヤーオブジェクト、ボールオブジェクト、速度、およびプレーヤースコアを参照するために使用されるいくつかのグローバルプロパティが必要です(図13を参照)。

// Define movement speed
float speed = 3;

// Define scores
float p1Score = 0;
float p2Score = 0;

// Define player variables
Player p1;
Player p2;

// Define ball variables
Ball ball;

// Define the last x position
// of the ball
float lastBallPositionX = 0;

図13:ゲームのグローバルプロパティの実装を示しています。

5.2セットアップ

このsetup()メソッドは、プレーヤーとボールのインスタンスを初期化し、画面サイズを設定するために使用されます(図14を参照)。

// ... Global properties here.

void setup() {  
  size(500, 500); // Set screen size
  
  // Create the player instances
  // at each side of the screen,
  // with no y-direction.
  p1 = new Player(10, height/2, 0);
  p2 = new Player(width-20, height/2, 0);

  // Create the ball instance
  ball = new Ball();
}

図14:ゲームのセットアップメソッドの実装を示しています。

5.3ドロー

このdraw()メソッドは、ゲームの繰り返しロジックに使用されます。図15の20〜33行目は、ボールが画面の外にあるかどうかをチェックするifステートメントとelseステートメントを示しています。その場合、プレーヤーの1人が1ポイントを獲得し、ボールの位置と方向がリセットされます。図14の36〜29行目は、プレーヤーの1人がボールとオーバーラップしてボールのx方向を反転させた場合に、真と評価されるチェックを示しています。図14の43〜58行目は、コンピューターがプレーヤーオブジェクト(p2)を制御する方法の小さな実装を示し、61〜64行目は、プレーヤーのスコアテキストの実装を示しています。

// ... Global properties here.
// ... Setup method here.

void draw() {
  // Set screen background to black.
  background(0);
  
  // Update players.
  p1.update();
  p2.update();
  
  // Update ball.
  ball.update();
  
  // Get ball position
  PVector ballPosition = ball.getPosition(); 

  // Is the ball outside the
  // screen on the left side?
  if (ballPosition.x < 0) {
    // Give P2 one point.
    p2Score += 1;
    // Reset ball position and direction.
    ball.resetMovement(); 
  }
  // Or, is the ball outside the
  // screen on the right side?
  else if (ballPosition.x > width) {
    // Give P1 one point.
    p1Score += 1;
    // Reset ball position and direction.
    ball.resetMovement(); 
  }
  
  // Do the ball overlaps with one of the players?
  if (ball.overlapsWith(p1)) {
    // Invert x-direction.
    ball.setDirection(1); 
  }
  if (ball.overlapsWith(p2)) {
    // Invert x-direction.
    ball.setDirection(-1); 
  }
  
  // Move P2 towards the ball if the ball
  // is moving towards P2's position
  if (lastBallPositionX < ballPosition.x) {
    // Get P2's position
    PVector p2Position = p2.getPosition();
    // Calculate direction
    float directionToBallY = ballPosition.y - p2Position.y;
    // Constrain the value between -1 and 1
    directionToBallY = constrain(directionToBallY, -1, 1);
    // Add speed
    directionToBallY *= speed;
    // Set P2 direction
    p2.setDirection(directionToBallY); 
  }
      
  // Cache the ball's x position
  // for next check
  lastBallPositionX = ballPosition.x;
  
  // Set the fill color to white.
  fill(255);
  // Draw the player's score on each side.
  text("P1 Score: " + p1Score, 10, 20);
  text("P2 Score: " + p2Score, width-80, 20);
}

図15:ゲームの描画メソッドの実装を示しています。

5.4 KeyPressed

ゲームに必要な最後のコードは、p1オブジェクトを移動するキーボードイベントを処理する機能のためのものです(図16を参照)。

// ... Global properties here.
// ... Setup method here.
// ... Draw method here.

void keyPressed() {
  // Move up
  if (key == 'w') p1.setDirection(-speed);
  // Move down
  else if (key == 's') p1.setDirection(speed);
}

図16:ゲームのkeyPressedメソッドの実装を示しています。

6.まとめ

この記事のピンポンゲームは、ProcessingライブラリとJavaを使用して作成されています。これには、Playerプレーヤーオブジェクトを表すためにBall使用されるクラスと、ボールオブジェクトを表すために使用されるクラスの2つのクラスが含まれています。

これらのクラスはsetup() draw()、 ProcessingのkeyPressed()メソッド内で一緒に使用され、ゲームの継続的な動作と構造を設定します。s最初のプレーヤーオブジェクトは、とを使用してキーボードで制御できw、2番目のプレーヤーオブジェクトはコンピューターで制御されます。

完全なゲームの例は、このリンクにあります。

参考文献

En.wikipedia.org。(2022a)。処理(プログラミング言語)—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Processing_(programming_language) >[2022年4月30日アクセス]。

En.wikipedia.org。(2022b)。クラス図—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Class_diagram >[2022年5月16日アクセス]。

En.wikipedia.org。(2022c)。ラジアン—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Radian >[2022年5月17日アクセス]。

En.wikipedia.org。(2022d)。回転行列—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Rotation_matrix >[2022年5月17日アクセス]。

Processing.org。(2022a)。setup()[オンライン]次のURLで入手可能:< https://processing.org/reference/setup_.html >[2022年4月30日アクセス]。

Processing.org。(2022b)。draw()[オンライン]次のURLで入手可能:< https://processing.org/reference/draw_.html >[2022年4月30日アクセス]。

Processing.org。(2022c)。keyPressed()[オンライン]次の場所で入手可能:< https://processing.org/reference/keyPressed_.html >[2022年4月30日アクセス]。

ソース:https ://betterprogramming.pub/create-the-classic-ping-pong-game-3aea1f7b16e6  

#pingpong  #game #java 

What is GEEK

Buddha Community

Javaでクラシックなピンポンゲームを作成する

Javaでクラシックなピンポンゲームを作成する

ピンポンを示すGIF。

この記事のピンポンゲームを示すGIF。

古典的なピンポンゲームを再現する方法を説明するチュートリアルをお探しですか?次に、もう探す必要はありません。この記事では、ProcessingライブラリとJavaを使用してゲームを再作成することに焦点を当てています。また、別のゲームを作成したい場合に、古典的なヘビゲームを再現する方法についての別の記事を書きました。

1.Processingをダウンロードしてインストールします

Processingをダウンロードするには、processing.org / downloadにアクセスし、優先プラットフォームに一致するバージョンを選択してください。

2.処理とは何ですか?

Processingは、グラフィカルライブラリと統合開発環境(IDE)を提供し、プログラミング言語Java(Wikipedia、2022a)を使用します。

3.ゲームの要件

ゲームの要件は、2つの異なる部分で提示されます。最初の部分では、プレーヤー、ボール、および環境の表現に関連する視覚的な要件について説明します。2番目の部分では、さまざまなオブジェクトとアプリケーションがどのように動作するかという機能要件について説明します。

3.1視覚的要件

  • プレーヤーオブジェクトは長方形で表す必要があります。
  • ボールオブジェクトは円で表す必要があります。
  • ゲームには、各プレーヤーのスコアを示す2つのテキスト要素が含まれている必要があります。

3.1機能要件

  • プレーヤーオブジェクトは、y軸上でのみ移動できる必要があります。
  • ボールオブジェクトは、x軸とy軸で移動できる必要があります。
  • ボールオブジェクトは、プレーヤーオブジェクトと重なる場合、x軸上の方向を反対方向に変更する必要があります。
  • ボールオブジェクトがy軸で画面の外に移動した場合、ボールオブジェクトはy軸での方向を反対に変更する必要があります。
  • ボールオブジェクトがx軸で画面の外に移動した場合は、ボールオブジェクトの位置と方向をリセットする必要があります。
  • ボールが反対側の画面から移動するたびに、プレーヤーはポイントを獲得します。
  • 最初のプレーヤーはキーボードで制御し、2番目のプレーヤーはコンピューターで制御する必要があります。

4.ゲームオブジェクト

ゲームには2つの異なるクラスが含まれます。1つはプレーヤーオブジェクトを表し、もう1つはボールオブジェクトを表します。図1は、2つのクラスを含むUMLクラス図を示しています。UMLクラス図について聞いたことがない人にとっては、それは単にシステムのクラス、プロパティ、メソッド、および関係を含む図です(Wikipedia、2022b)。

図1:ピンポンゲームで使用される2つのクラスを示すUMLクラス図。

図1:ピンポンゲームで使用される2つのクラスを示すUMLクラス図。

4.1プレーヤーオブジェクト

プレーヤークラスは両方のプレーヤーのオブジェクトを作成するために使用されるため、位置とy方向はプレーヤーごとに一意であることが重要ですが、値が値であるため、幅、高さ、境界は静的変数である可能性があると主張できます。すべてのオブジェクトで同じです。図2は、プレーヤーの配置と動きの境界の背後にある考え方を示しています。

各プレーヤーのプロパティと、プレーヤーが移動できるパス(赤い線)を示すGIF。

図2:各プレーヤーのプロパティとプレーヤーが移動できるパス(赤い線)を示すGIF。

4.1.1。プレーヤーのプロパティ

クラスには5つのプロパティが必要であり(図1を参照)、これらの各プロパティには次の目的があります。

  • positionPVectorプレーヤーのxとyの位置を定義するA。
  • yDirfloatプレーヤーの動きの方向と速度を定義するA。
  • wfloatプレーヤーの長方形の幅を定義します。
  • hfloatプレーヤーの長方形の高さを定義します。
  • bfloatプレーヤーの動きの境界を定義します。

プレーヤークラスのプロパティの実装を図3に示します。

class Player {
  // Current position
  PVector position;
  
  // Movement direction
  float yDir;
  
  // Size
  float w = 10;
  float h = 25;
  
  // Boundaries
  float b = 15;
}

図3:プレーヤークラスのプロパティの実装を示しています。

4.1.2。プレイヤーメソッド

このクラスには5つのメソッドも必要であり(図1を参照)、これらの各プロパティには次の目的があります。

  • update()—ビジュアルオブジェクトの移動、境界チェック、および描画に関連するプレーヤーの動作を更新するために使用されるvoidメソッド。
  • setDirection(yDir)—y軸上のプレーヤーオブジェクトの方向を更新するために使用されるセッターメソッド。
  • getPosition()—プレーヤーオブジェクトの位置を返すgetterメソッド。
  • getHeight()—プレーヤーオブジェクトの高さを返すgetterメソッド。
  • getWidth()—プレーヤーオブジェクトの幅を返すgetterメソッド。

Playerクラスには、y軸上の位置と方向の初期値を設定するコンストラクターも必要です。コンストラクターの引数は、コンストラクター内でプレーヤーの位置の新しいオブジェクトfloatsのインスタンスを作成するために使用される開始位置を表すように設計されています。PVector

これにより、プレーヤーオブジェクトがメモリ内の同じオブジェクトを参照しないようになります。これは、インスタンス化PVector時に複数のプレーヤーオブジェクトに同じオブジェクトが与えられた場合に発生する可能性があります。PVector

方向のgetterメソッドを使用すると、クラス外のオブジェクトに方向を設定できます。position、height、widthのsetterメソッドを使用すると、クラス外のオブジェクトでこれらのプロパティを読み取ることができます(図の実装を参照)。 4)。

class Player {
  
  // ... Properties here.

  // Player constructor
  public Player(float x, float y, float yDir) {
    this.position = new PVector(x, y);
    this.yDir = yDir;
  }
  
  // Setter Methods
  
  public void setDirection(float yDir) {
    this.yDir = yDir;
  }
  
  // Getter Methods
  
  public PVector getPosition() {
    return position;
  }
  
  public float getHeight() {
    return h;
  }
  
  public float getWidth() {
    return w;
  }
}

図4:プレーヤーコンストラクター、およびゲッターメソッドとセッターメソッドの実装を示しています。

プレーヤークラスで必要な最後のメソッドはupdate()メソッドです。図5に、メソッドの実装を示します。

class Player {
  
  // ... Properties here.
  // ... Player constructor here.
  // ... Setter Methods here.
  // ... Getter Methods here.
  
  public void update() {
    // Update player position
    position.y += yDir;
    
    // Have the player reached
    // the top?
    if (position.y < b) {
      // Stop movement at the top
      position.y = b;
    // Have the player reached
    // the bottom?
    } else if (position.y > height-b-h) {
      // Stop the movement at the bottom
      position.y = height-b-h;
    }
    
    // Set player color to white
    fill(255);
    // Draw rectangle
    rect(position.x, position.y, w, h);
  }
}

図5:プレーヤーの更新メソッドの実装を示しています。

その動作は次のように説明できます。

  • 10行目—この行は、の値が正の場合はプレーヤーのy位置を増やし、の値が負ydirの場合はプレーヤーのy位置を減らします。ydir
  • 14行目—最初の行は、プレーヤーのy位置がb、プレーヤーの動きの境界を定義するために使用された値よりも小さいかどうかをチェックします。つまり、プレーヤーが画面上部の境界に達した場合です。
  • 16行目—プレーヤーのy位置をの値にリセットして、プレーヤーbが画面の上部に向かってそれ以上移動しないようにします。
  • 19行目— 14行目と同様のチェックですが、代わりにプレーヤーが画面の下部に到達したかどうかをチェックします。このチェックには、プレーヤーの高さと、b長方形が正しい位置で停止することを確認するためのの値が含まれます(説明については図6を参照)。
  • 21行目—画面下部のプレーヤーのy位置をリセットして、プレーヤーがy軸上で画面の外に移動しないようにします。

プレーヤーオブジェクトはアンカーポイント(positionプロパティの値)で移動するため、画面の高さからbとhを引いたところで停止して、長方形の下側が境界に達したときに確実に停止するようにする必要があります。

図6:プレーヤーオブジェクトはアンカーポイント(positionプロパティの値)で移動するため、画面の高さbを引いたところでh停止し、長方形の下側が境界に達したときに確実に停止する必要があります。

プレーヤークラスの最後の例は、このリンクにあります。

4.2ボールオブジェクト

ボールクラスはプレーヤークラスと非常に似ていますが、x軸とy軸の両方で移動できます。図7は、ボールが移動するときにボールの位置と方向の値がどのように変化するかを示しています。

ボールオブジェクトのプロパティを示すGIF。

図7:ボールオブジェクトのプロパティを示すGIF。

4.1.1。ボールのプロパティ

図1は、ボールクラスに次のように説明できる4つのプロパティが必要であることを示しています。

  • positionPVectorボールのxとyの位置を定義するA。
  • directionPVectorボールの動きの方向と速度を定義するA。
  • dfloatボールの円の直径を定義します。
  • sfloatボールの開始速度を定義します。

ボールのプロパティの実装を図8に示します。

class Ball {
  // Current position
  PVector position;
  
  // Current direction
  PVector direction;
  
  // Diameter of the circle
  float d = 15;
  
  // The speed of the ball
  float s = 5;
}

図8:ボールクラスのプロパティの実装。

4.1.2。ボールメソッド

ボールクラスには、プレーヤークラスとして次のように説明できる5つのメソッドも必要です。

  • update()—ボールの動き、境界、およびビジュアルを更新するvoidメソッド。
  • getPosition()—ボールの位置を返すゲッターメソッド。
  • resetMovement()—ボールの位置を画面の中央にリセットし、その方向をランダムな値にリセットするvoidメソッド。
  • setDirection(x)-ボールのx方向を設定するセッターメソッド。
  • overlapsWith(player)—ボールが指定されたプレーヤーとオーバーラップした場合にtrueを返すブールメソッド。

ボールのコンストラクターとメソッド、、、、の実装を図getPosition()9resetMovement()に示します。setDirection(x)update()

class Ball {
  
  // ... Properties here.
  
  // Ball constructor
  public Ball() {
    resetMovement();
  }
  
  // Getter Methods
  
  public PVector getPosition() {
    return position;
  }
  
  // Reset position and randomize direction.
  
  public void resetMovement() {
    // Set position to the center of the screen
    position = new PVector(width/2, height/2);
    
    // Get a random speed
    float speed = random(-s, s);
    // Set the y direction to half of the speed
    // to ensure it moves faster in the left or
    // right direction
    direction = new PVector(speed, speed/2);
  }
  
  // Set direction on the x-axis.
  
  public void setDirection(float x) {
     direction.x = x * speed;
  }
  
  // Updates the ball's position, add boundaries 
  // and draw its visuals.
  
  public void update() {
    // Add velocity
    position.add(direction);
    
    // Check if the ball has reached the top
    // or the bottom of the screen.
    if (position.y < 0 || position.y > height) {
      // Invert the direction on the y-axis.
      direction.y = -direction.y;
    }
    
    // Set the fill color to white.
    fill(255);
    // Draw the ball's circle.
    circle(position.x, position.y, d); 
  }
}

図9:ボールのコンストラクターの実装、およびメソッドgetPosition()、resetMovement()、invertDirectionX()、およびupdate()。

4.1.2。衝突方法

ボールクラスに実装する必要がある最後のメソッドはoverlapsWith(player)メソッドです。実装を示す前に、ソリューションの背後にある数学的アイデアについて簡単に説明したいと思います。

図10は、座標系内に描画されたボールを示しています。アンカーポイントはオリゴに配置されています。アンカーポイントはpositionボールの特性と同じです。

図の各ベクトル/矢印は、衝突チェックで使用する必要があるアンカーポイントを基準にしたポイントを指しています。ポイントは、度をラジアンに変換する式と回転行列によって計算できます。

この図は、座標系内で描画されたボールを示しています。 アンカーポイントはボールの位置であり、各ベクトル/矢印はボールのアンカーポイントを基準にしたポイントを指します。 各ベクトルは45度回転します。

図10:この図は、座標系内に描画されたボールを示しています。アンカーポイントはボールの位置であり、各ベクトル/矢印はボールのアンカーポイントを基準にしたポイントを指します。各ベクトルは45度回転します。

度をラジアンに変換する式は、次のように定義できます(Wikipedia、2022c)。

度をラジアンに変換するための式。

ベクトルv、 θラジアンを回転させる式は次のように定義できます(Wikipedia、2022d)。

ベクトルv、θラジアンを回転させるための式

上記の式で計算されたポイントは、そのうちの1つがプレーヤーのコーナーポイントの間にあるかどうかを確認するために使用されます。これは、ボールがプレーヤーとオーバーラップしていることを意味します(図11を参照)。

図11:この図は、プレーヤーオブジェクトがボールオブジェクトと重なっているところを示しています。また、位置、幅、高さのプロパティに基づいて、プレーヤーの各コーナーポイントが表示されます。

図12の24行目は、度をラジアンに変換するために使用される式の実装を示し、図12の28〜29行目は、2Dベクトルを45度回転するために使用される回転行列の実装を示しています。

図12の33〜34行目は、ポイントがプレーヤーのコーナーポイント内にある場合にtrueを返すチェックを示しています。

class Ball {
  
  // ... Properties here.
  // ... Ball constructor
  // ... Getter Methods
  // ... Reset position and randomize direction method here.
  // ... Invert direction method here.
  // ... Update method here.
  
  public boolean overlapsWith(Player player) {
    // Get player position,
    // width, and height.
    var p = player.getPosition();
    var w = player.getWidth();
    var h = player.getHeight();
    
    // Calculate radius.
    var r = d/2;
    
    // Loop eight points.
    for (int i = 0; i < 8; i++) {
       
       // Convert i * 45 degrees to radians. 
       var degree = (i * 45) * (PI/180);
       
       // Calculate x and y points by rotating a vector
       // relative to the position 45 degrees
       var x = r * cos(position.x + degree) + position.x;
       var y = r * sin(position.y + degree) + position.y;

       // Return true if the point is within on both
       // the x-axis and the y-axis.
       if (p.x < x && x < p.x + w &&
           p.y < y && y < p.y + h) return true;
    }
    
    // If none of the points were within
    // the player, return false.
    return false;
  }
}

図12:この図は、「overlapsWith(player)」メソッドの実装を示しています。

ボールクラスの最後の例は、このリンクにあります。

5.処理制御フローの設定

アプリケーションにはsetup()、アプリケーションの起動時に実行されるメソッドdraw()(Processing.org、2022a)、停止するまでフレームごとに1回実行されるメソッド(Processing.org、2022b)、およびkeyPressed()キーが押されました(Processing.org、2022c)。

5.1グローバルプロパティ

ゲームには、プレーヤーオブジェクト、ボールオブジェクト、速度、およびプレーヤースコアを参照するために使用されるいくつかのグローバルプロパティが必要です(図13を参照)。

// Define movement speed
float speed = 3;

// Define scores
float p1Score = 0;
float p2Score = 0;

// Define player variables
Player p1;
Player p2;

// Define ball variables
Ball ball;

// Define the last x position
// of the ball
float lastBallPositionX = 0;

図13:ゲームのグローバルプロパティの実装を示しています。

5.2セットアップ

このsetup()メソッドは、プレーヤーとボールのインスタンスを初期化し、画面サイズを設定するために使用されます(図14を参照)。

// ... Global properties here.

void setup() {  
  size(500, 500); // Set screen size
  
  // Create the player instances
  // at each side of the screen,
  // with no y-direction.
  p1 = new Player(10, height/2, 0);
  p2 = new Player(width-20, height/2, 0);

  // Create the ball instance
  ball = new Ball();
}

図14:ゲームのセットアップメソッドの実装を示しています。

5.3ドロー

このdraw()メソッドは、ゲームの繰り返しロジックに使用されます。図15の20〜33行目は、ボールが画面の外にあるかどうかをチェックするifステートメントとelseステートメントを示しています。その場合、プレーヤーの1人が1ポイントを獲得し、ボールの位置と方向がリセットされます。図14の36〜29行目は、プレーヤーの1人がボールとオーバーラップしてボールのx方向を反転させた場合に、真と評価されるチェックを示しています。図14の43〜58行目は、コンピューターがプレーヤーオブジェクト(p2)を制御する方法の小さな実装を示し、61〜64行目は、プレーヤーのスコアテキストの実装を示しています。

// ... Global properties here.
// ... Setup method here.

void draw() {
  // Set screen background to black.
  background(0);
  
  // Update players.
  p1.update();
  p2.update();
  
  // Update ball.
  ball.update();
  
  // Get ball position
  PVector ballPosition = ball.getPosition(); 

  // Is the ball outside the
  // screen on the left side?
  if (ballPosition.x < 0) {
    // Give P2 one point.
    p2Score += 1;
    // Reset ball position and direction.
    ball.resetMovement(); 
  }
  // Or, is the ball outside the
  // screen on the right side?
  else if (ballPosition.x > width) {
    // Give P1 one point.
    p1Score += 1;
    // Reset ball position and direction.
    ball.resetMovement(); 
  }
  
  // Do the ball overlaps with one of the players?
  if (ball.overlapsWith(p1)) {
    // Invert x-direction.
    ball.setDirection(1); 
  }
  if (ball.overlapsWith(p2)) {
    // Invert x-direction.
    ball.setDirection(-1); 
  }
  
  // Move P2 towards the ball if the ball
  // is moving towards P2's position
  if (lastBallPositionX < ballPosition.x) {
    // Get P2's position
    PVector p2Position = p2.getPosition();
    // Calculate direction
    float directionToBallY = ballPosition.y - p2Position.y;
    // Constrain the value between -1 and 1
    directionToBallY = constrain(directionToBallY, -1, 1);
    // Add speed
    directionToBallY *= speed;
    // Set P2 direction
    p2.setDirection(directionToBallY); 
  }
      
  // Cache the ball's x position
  // for next check
  lastBallPositionX = ballPosition.x;
  
  // Set the fill color to white.
  fill(255);
  // Draw the player's score on each side.
  text("P1 Score: " + p1Score, 10, 20);
  text("P2 Score: " + p2Score, width-80, 20);
}

図15:ゲームの描画メソッドの実装を示しています。

5.4 KeyPressed

ゲームに必要な最後のコードは、p1オブジェクトを移動するキーボードイベントを処理する機能のためのものです(図16を参照)。

// ... Global properties here.
// ... Setup method here.
// ... Draw method here.

void keyPressed() {
  // Move up
  if (key == 'w') p1.setDirection(-speed);
  // Move down
  else if (key == 's') p1.setDirection(speed);
}

図16:ゲームのkeyPressedメソッドの実装を示しています。

6.まとめ

この記事のピンポンゲームは、ProcessingライブラリとJavaを使用して作成されています。これには、Playerプレーヤーオブジェクトを表すためにBall使用されるクラスと、ボールオブジェクトを表すために使用されるクラスの2つのクラスが含まれています。

これらのクラスはsetup() draw()、 ProcessingのkeyPressed()メソッド内で一緒に使用され、ゲームの継続的な動作と構造を設定します。s最初のプレーヤーオブジェクトは、とを使用してキーボードで制御できw、2番目のプレーヤーオブジェクトはコンピューターで制御されます。

完全なゲームの例は、このリンクにあります。

参考文献

En.wikipedia.org。(2022a)。処理(プログラミング言語)—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Processing_(programming_language) >[2022年4月30日アクセス]。

En.wikipedia.org。(2022b)。クラス図—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Class_diagram >[2022年5月16日アクセス]。

En.wikipedia.org。(2022c)。ラジアン—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Radian >[2022年5月17日アクセス]。

En.wikipedia.org。(2022d)。回転行列—ウィキペディア。[オンライン]次のURLで入手可能:< https://en.wikipedia.org/wiki/Rotation_matrix >[2022年5月17日アクセス]。

Processing.org。(2022a)。setup()[オンライン]次のURLで入手可能:< https://processing.org/reference/setup_.html >[2022年4月30日アクセス]。

Processing.org。(2022b)。draw()[オンライン]次のURLで入手可能:< https://processing.org/reference/draw_.html >[2022年4月30日アクセス]。

Processing.org。(2022c)。keyPressed()[オンライン]次の場所で入手可能:< https://processing.org/reference/keyPressed_.html >[2022年4月30日アクセス]。

ソース:https ://betterprogramming.pub/create-the-classic-ping-pong-game-3aea1f7b16e6  

#pingpong  #game #java