1652785380
この記事のピンポンゲームを示すGIF。
古典的なピンポンゲームを再現する方法を説明するチュートリアルをお探しですか?次に、もう探す必要はありません。この記事では、ProcessingライブラリとJavaを使用してゲームを再作成することに焦点を当てています。また、別のゲームを作成したい場合に、古典的なヘビゲームを再現する方法についての別の記事を書きました。
1.Processingをダウンロードしてインストールします
Processingをダウンロードするには、processing.org / downloadにアクセスし、優先プラットフォームに一致するバージョンを選択してください。
2.処理とは何ですか?
Processingは、グラフィカルライブラリと統合開発環境(IDE)を提供し、プログラミング言語Java(Wikipedia、2022a)を使用します。
3.ゲームの要件
ゲームの要件は、2つの異なる部分で提示されます。最初の部分では、プレーヤー、ボール、および環境の表現に関連する視覚的な要件について説明します。2番目の部分では、さまざまなオブジェクトとアプリケーションがどのように動作するかという機能要件について説明します。
4.ゲームオブジェクト
ゲームには2つの異なるクラスが含まれます。1つはプレーヤーオブジェクトを表し、もう1つはボールオブジェクトを表します。図1は、2つのクラスを含むUMLクラス図を示しています。UMLクラス図について聞いたことがない人にとっては、それは単にシステムのクラス、プロパティ、メソッド、および関係を含む図です(Wikipedia、2022b)。
図1:ピンポンゲームで使用される2つのクラスを示すUMLクラス図。
プレーヤークラスは両方のプレーヤーのオブジェクトを作成するために使用されるため、位置とy方向はプレーヤーごとに一意であることが重要ですが、値が値であるため、幅、高さ、境界は静的変数である可能性があると主張できます。すべてのオブジェクトで同じです。図2は、プレーヤーの配置と動きの境界の背後にある考え方を示しています。
図2:各プレーヤーのプロパティとプレーヤーが移動できるパス(赤い線)を示すGIF。
4.1.1。プレーヤーのプロパティ
クラスには5つのプロパティが必要であり(図1を参照)、これらの各プロパティには次の目的があります。
position
—PVector
プレーヤーのxとyの位置を定義するA。yDir
—float
プレーヤーの動きの方向と速度を定義するA。w
—float
プレーヤーの長方形の幅を定義します。h
—float
プレーヤーの長方形の高さを定義します。b
—float
プレーヤーの動きの境界を定義します。プレーヤークラスのプロパティの実装を図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:プレーヤーの更新メソッドの実装を示しています。
その動作は次のように説明できます。
ydir
の場合はプレーヤーのy位置を減らします。ydir
b
、プレーヤーの動きの境界を定義するために使用された値よりも小さいかどうかをチェックします。つまり、プレーヤーが画面上部の境界に達した場合です。b
が画面の上部に向かってそれ以上移動しないようにします。b
長方形が正しい位置で停止することを確認するためのの値が含まれます(説明については図6を参照)。図6:プレーヤーオブジェクトはアンカーポイント(positionプロパティの値)で移動するため、画面の高さb
を引いたところでh
停止し、長方形の下側が境界に達したときに確実に停止する必要があります。
プレーヤークラスの最後の例は、このリンクにあります。
ボールクラスはプレーヤークラスと非常に似ていますが、x軸とy軸の両方で移動できます。図7は、ボールが移動するときにボールの位置と方向の値がどのように変化するかを示しています。
図7:ボールオブジェクトのプロパティを示すGIF。
4.1.1。ボールのプロパティ
図1は、ボールクラスに次のように説明できる4つのプロパティが必要であることを示しています。
position
—PVector
ボールのxとyの位置を定義するA。direction
—PVector
ボールの動きの方向と速度を定義するA。d
—float
ボールの円の直径を定義します。s
—float
ボールの開始速度を定義します。ボールのプロパティの実装を図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
ボールの特性と同じです。
図の各ベクトル/矢印は、衝突チェックで使用する必要があるアンカーポイントを基準にしたポイントを指しています。ポイントは、度をラジアンに変換する式と回転行列によって計算できます。
図10:この図は、座標系内に描画されたボールを示しています。アンカーポイントはボールの位置であり、各ベクトル/矢印はボールのアンカーポイントを基準にしたポイントを指します。各ベクトルは45度回転します。
度をラジアンに変換する式は、次のように定義できます(Wikipedia、2022c)。
ベクトルv、 θラジアンを回転させる式は次のように定義できます(Wikipedia、2022d)。
上記の式で計算されたポイントは、そのうちの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)。
ゲームには、プレーヤーオブジェクト、ボールオブジェクト、速度、およびプレーヤースコアを参照するために使用されるいくつかのグローバルプロパティが必要です(図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:ゲームのグローバルプロパティの実装を示しています。
この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:ゲームのセットアップメソッドの実装を示しています。
この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:ゲームの描画メソッドの実装を示しています。
ゲームに必要な最後のコードは、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
1652785380
この記事のピンポンゲームを示すGIF。
古典的なピンポンゲームを再現する方法を説明するチュートリアルをお探しですか?次に、もう探す必要はありません。この記事では、ProcessingライブラリとJavaを使用してゲームを再作成することに焦点を当てています。また、別のゲームを作成したい場合に、古典的なヘビゲームを再現する方法についての別の記事を書きました。
1.Processingをダウンロードしてインストールします
Processingをダウンロードするには、processing.org / downloadにアクセスし、優先プラットフォームに一致するバージョンを選択してください。
2.処理とは何ですか?
Processingは、グラフィカルライブラリと統合開発環境(IDE)を提供し、プログラミング言語Java(Wikipedia、2022a)を使用します。
3.ゲームの要件
ゲームの要件は、2つの異なる部分で提示されます。最初の部分では、プレーヤー、ボール、および環境の表現に関連する視覚的な要件について説明します。2番目の部分では、さまざまなオブジェクトとアプリケーションがどのように動作するかという機能要件について説明します。
4.ゲームオブジェクト
ゲームには2つの異なるクラスが含まれます。1つはプレーヤーオブジェクトを表し、もう1つはボールオブジェクトを表します。図1は、2つのクラスを含むUMLクラス図を示しています。UMLクラス図について聞いたことがない人にとっては、それは単にシステムのクラス、プロパティ、メソッド、および関係を含む図です(Wikipedia、2022b)。
図1:ピンポンゲームで使用される2つのクラスを示すUMLクラス図。
プレーヤークラスは両方のプレーヤーのオブジェクトを作成するために使用されるため、位置とy方向はプレーヤーごとに一意であることが重要ですが、値が値であるため、幅、高さ、境界は静的変数である可能性があると主張できます。すべてのオブジェクトで同じです。図2は、プレーヤーの配置と動きの境界の背後にある考え方を示しています。
図2:各プレーヤーのプロパティとプレーヤーが移動できるパス(赤い線)を示すGIF。
4.1.1。プレーヤーのプロパティ
クラスには5つのプロパティが必要であり(図1を参照)、これらの各プロパティには次の目的があります。
position
—PVector
プレーヤーのxとyの位置を定義するA。yDir
—float
プレーヤーの動きの方向と速度を定義するA。w
—float
プレーヤーの長方形の幅を定義します。h
—float
プレーヤーの長方形の高さを定義します。b
—float
プレーヤーの動きの境界を定義します。プレーヤークラスのプロパティの実装を図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:プレーヤーの更新メソッドの実装を示しています。
その動作は次のように説明できます。
ydir
の場合はプレーヤーのy位置を減らします。ydir
b
、プレーヤーの動きの境界を定義するために使用された値よりも小さいかどうかをチェックします。つまり、プレーヤーが画面上部の境界に達した場合です。b
が画面の上部に向かってそれ以上移動しないようにします。b
長方形が正しい位置で停止することを確認するためのの値が含まれます(説明については図6を参照)。図6:プレーヤーオブジェクトはアンカーポイント(positionプロパティの値)で移動するため、画面の高さb
を引いたところでh
停止し、長方形の下側が境界に達したときに確実に停止する必要があります。
プレーヤークラスの最後の例は、このリンクにあります。
ボールクラスはプレーヤークラスと非常に似ていますが、x軸とy軸の両方で移動できます。図7は、ボールが移動するときにボールの位置と方向の値がどのように変化するかを示しています。
図7:ボールオブジェクトのプロパティを示すGIF。
4.1.1。ボールのプロパティ
図1は、ボールクラスに次のように説明できる4つのプロパティが必要であることを示しています。
position
—PVector
ボールのxとyの位置を定義するA。direction
—PVector
ボールの動きの方向と速度を定義するA。d
—float
ボールの円の直径を定義します。s
—float
ボールの開始速度を定義します。ボールのプロパティの実装を図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
ボールの特性と同じです。
図の各ベクトル/矢印は、衝突チェックで使用する必要があるアンカーポイントを基準にしたポイントを指しています。ポイントは、度をラジアンに変換する式と回転行列によって計算できます。
図10:この図は、座標系内に描画されたボールを示しています。アンカーポイントはボールの位置であり、各ベクトル/矢印はボールのアンカーポイントを基準にしたポイントを指します。各ベクトルは45度回転します。
度をラジアンに変換する式は、次のように定義できます(Wikipedia、2022c)。
ベクトルv、 θラジアンを回転させる式は次のように定義できます(Wikipedia、2022d)。
上記の式で計算されたポイントは、そのうちの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)。
ゲームには、プレーヤーオブジェクト、ボールオブジェクト、速度、およびプレーヤースコアを参照するために使用されるいくつかのグローバルプロパティが必要です(図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:ゲームのグローバルプロパティの実装を示しています。
この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:ゲームのセットアップメソッドの実装を示しています。
この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:ゲームの描画メソッドの実装を示しています。
ゲームに必要な最後のコードは、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