0
0

More than 1 year has passed since last update.

Go言語で昔懐かしのPongを作ってみた話

Posted at

はじめに

前回は画面上でボールが動くだけの処理について記載しましたが、
ボールが動くのであれば、昔懐かしのpongのようなホッケーゲームができると思い作成しました。
以下はソースについて記載します。

必要なパッケージのインポート

import (
	"image/color"  // 色を扱うためのパッケージ
	"log"  // ロギングを行うためのパッケージ

	"github.com/hajimehoshi/ebiten/v2"  // Ebitenのパッケージ
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"  // Ebitenのユーティリティパッケージ
)

定数の定義

const (
	screenWidth, screenHeight = 640, 480  // 画面の幅と高さ
	paddleWidth, paddleHeight = 20, 80  // パドルの幅と高さ
	ballSize                  = 20  // ボールの大きさ
	paddleSpeed               = 4  // パドルの速度
)

Game構造体の定義

type Game struct {
	ballPositionX, ballPositionY float64  // ボールの位置
	ballDX, ballDY               float64  // ボールの移動量
	paddle1Y, paddle2Y           float64  // 両パドルの位置
}

Game構造体はゲームの状態を保持します。ボールの位置と移動量、そしてパドルの位置が含まれます。

Updateメソッド

func (g *Game) Update() error {
	g.ballPositionX += g.ballDX  // ボールのX座標を更新
	g.ballPositionY += g.ballDY  // ボールのY座標を更新

	// ボールが画面の左右端に触れたら反射
	if g.ballPositionX < 0 {
		g.ballDX = -g.ballDX
		g.ballPositionX = 0
	} else if g.ballPositionX > screenWidth-ballSize {
		g.ballDX = -g.ballDX
		g.ballPositionX = screenWidth - ballSize
	}
	// ボールが画面の上下端に触れたら反射
	if g.ballPositionY < 0 {
		g.ballDY = -g.ballDY
		g.ballPositionY = 0
	} else if g.ballPositionY > screenHeight-ballSize {
		g.ballDY = -g.ballDY
		g.ballPositionY = screenHeight - ballSize
	}

	// パドルの移動
	if ebiten.IsKeyPressed(ebiten.KeyW) {
		g.paddle1Y -= paddleSpeed  // Wキーでパドル1を上に移動
	}
	if ebiten.IsKeyPressed(ebiten.KeyS) {
		g.paddle1Y += paddleSpeed  // Sキーでパドル1を下に移動
	}
	if ebiten.IsKeyPressed(ebiten.KeyUp) {
		g.paddle2Y -= paddleSpeed  // 上矢印キーでパドル2を上に移動
	}
	if ebiten.IsKeyPressed(ebiten.KeyDown) {
		g.paddle2Y += paddleSpeed  // 下矢印キーでパドル2を下に移動
	}

	// ボールがパドルに当たったら反射
	if (g.ballPositionX < paddleWidth && g.ballPositionY+ballSize > g.paddle1Y && g.ballPositionY < g.paddle1Y+paddleHeight) ||
		(g.ballPositionX+ballSize > screenWidth-paddleWidth && g.ballPositionY+ballSize > g.paddle2Y && g.ballPositionY < g.paddle2Y+paddleHeight) {
		g.ballDX = -g.ballDX
	}

	return nil
}

Updateメソッドでは、ゲームの状態を更新します。ここではボールの位置、ボールの反射、パドルの移動、そしてボールとパドルの衝突を処理しています。

Drawメソッド

func (g *Game) Draw(screen *ebiten.Image) {
	ebitenutil.DrawRect(screen, 10, g.paddle1Y, paddleWidth, paddleHeight, color.White)  // パドル1を描画
	ebitenutil.DrawRect(screen, screenWidth-30, g.paddle2Y, paddleWidth, paddleHeight, color.White)  // パドル2を描画
	ebitenutil.DrawRect(screen, g.ballPositionX, g.ballPositionY, ballSize, ballSize, color.White)  // ボールを描画
}

Drawメソッドでは、ゲームの状態に基づいて画面を描画します。ここではパドルとボールを描画しています。

Layoutメソッド

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
	return screenWidth, screenHeight
}

Layoutメソッドでは、ゲーム画面のサイズを設定します。

main関数

func main() {
	g := &Game{
		ballPositionX: screenWidth / 2,
		ballPositionY: screenHeight / 2,
		ballDX:        2,
		ballDY:        2,
		paddle1Y:      screenHeight/2 - paddleHeight/2,
		paddle2Y:      screenHeight/2 - paddleHeight/2,
	}

	ebiten.SetWindowSize(screenWidth, screenHeight)  // ウィンドウの大きさを設定
	ebiten.SetWindowTitle("Pong")  // ウィンドウのタイトルを設定

	if err := ebiten.RunGame(g); err != nil {
		log.Fatal(err)  // エラーハンドリング
	}
}

main関数では、ゲームの初期化と実行を行います。ゲームの状態を表すGame構造体を初期化し、ウィンドウの大きさとタイトルを設定した後、ゲームを実行します。

現状は、パドルに当たり判定を付け,ただ永遠とはじくだけではありますが、
今後、pongと同じような機能を追加していこうと思います。

以上

前回

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0