🎮 ブロック崩し
💡 特殊ブロック効果
- ✅ ゴールデン: スコア 2倍!
- ✅ ターコイズ: ボールの減速!
- ✅ パープル: パドルが拡張!
- ✅ ライトグリーン: ボールが増える!
- 💪 グレー: 耐久度 2 の強化ブロック
🏆 ランキング
1. 導入:プロジェクトの概要と学習目標
このプロジェクトは、WordPress プラグインの構造を最大限に活用し、純粋な JavaScript で作成したゲーム(ブロック崩し)を埋め込む方法を実践的に学ぶことを目的としています。
Canvas 要素を用いたゲームの基礎から、複数のオブジェクト(マルチボール)を管理する高度な JavaScript のテクニック、さらには WordPress の AJAX 機能を使ってハイスコアを永続化するバックエンド処理までを網羅します。
本記事を通じて、以下の技術要素の理解を深めることができます。
- Canvas/JavaScript: ゲームループ、衝突判定、そして複雑なゲームロジック(マルチボール)の配列管理。
- WordPress連携: ショートコード、
wp_localize_script、および AJAX を利用したデータの送受信。 - フロントエンド: Bootstrap を活用したレスポンシブな UI の設計。
2. 🔌 WordPress連携の基盤(PHP/HTML)解説
ゲームを WordPress に組み込むには、PHP ファイル (breakout-game.php) がすべての CSS/JS を読み込み、ゲームの UI を構成する HTML フラグメント (game-template.html) を挿入する役割を果たします。
A. ショートコードとファイルのエンキュー
breakout-game.php では、add_shortcode() で[breakout_games]のようなショートコードを登録し、wp_enqueue_script で必要なファイルを読み込んでいます。
特に重要な点は、カスタム CSS を PHP 内の <style> ブロックにインラインで記述し、プラグインのコンテナ (.breakout-game-container) の最大幅(max-width: 700px)を設定している点です。これにより、ゲーム画面以外の UI 要素が広がりすぎることを防ぎ、レスポンシブな表示を可能にしています。
// breakout-game.php (CSS設定箇所)
$custom_style = "
<style>
.breakout-game-container {
width: 100%;
max-width: 700px; /* UI幅の制御 */
margin: 20px auto;
}
/* ... その他のスタイル定義 ... */
</style>";
B. 設定値の橋渡し (wp_localize_script)
JavaScript 側で AJAX のエンドポイントや初期ランキングデータ、使用するアイコンのリストなどのPHP側の情報を利用するために、wp_localize_script を使用します。
// breakout-game.php (wp_localize_script の利用例)
wp_localize_script('breakout-game-script', 'breakoutGameData', array(
'ajax_url' => admin_url('admin-ajax.php'),
'save_action' => 'breakout_save_score',
// ... その他のデータ
));
3. 🖥️ JavaScript:Canvasとゲームループ
game.js は、requestAnimationFrame(draw) を核とするメインのゲームループで動作しています。
A. ボールの速度と動的な角度調整
パドルにボールが当たった際、反射角度を静的にするのではなく、パドルのどの位置に当たったかに基づいて動的に決定しています。
// game.js (パドル衝突時のロジック)
const paddleCenter = paddleX + actualPaddleWidth / 2;
// パドル中心からの相対的な交差位置を -1 から 1 の範囲で計算
const relativeIntersectX = (ball.x - paddleCenter) / (actualPaddleWidth / 2);
const currentSpeed = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
// 角度を決定 (最大 ±60度)
const bounceAngle = relativeIntersectX * (Math.PI / 3);
ball.dx = currentSpeed * Math.sin(bounceAngle);
ball.dy = -currentSpeed * Math.cos(bounceAngle);
// ... 速度調整ロジック ...
さらに、ボールが左右の壁に当たるたびに、ボール個別の wallHitCount を利用して微量な速度増加 (SPEED_INCREMENT) を適用しています。これは、ゲームを進行させるにつれて難易度とスピードが上昇する仕組みを実現しています。
4. 🚀 最重要トピック:マルチボール実装(配列化の技術)
最も大規模な変更は、追加ボールブロック(ライトグリーン)の実装に伴う、ボールの管理方法の変更です。
A. ボールオブジェクトの配列管理
従来の let x, y, dx, dy; のような単一の変数から脱却し、各ボールの状態を保持するオブジェクトの配列 balls へと移行しました。
// game.js (ボールオブジェクトの構造)
balls.push({
x: canvas.width / 2,
y: canvas.height - 30,
dx: initialDx,
dy: initialDy,
radius: ballRadius,
status: 1, // 状態管理 (1: Active, 0: Lost)
wallHitCount: 0
});
B. 描画・衝突判定のループ化
メインループの draw() 関数と collisionDetection() 関数は、すべてこの balls 配列を反復処理するように変更されました。
// game.js (collisionDetection のループ)
balls.forEach(ball => {
if (ball.status === 0) return;
// ここで各ボール (ball.x, ball.y, ball.dx, ball.dy) を使って衝突判定を行う
});
C. 追加ボールの生成とロストの管理
追加ボールブロックが破壊された場合、createNewBall() 関数を呼び出し、既存ボールの速度と方向を継承しつつ、わずかにランダムな調整を加えた新しいボールを配列に追加します。
ボールがパドルをすり抜けてロストした場合、そのボールの status が 0 に設定されます。そして、フレームの最後に balls = balls.filter(ball => ball.status === 1); を実行し、ロストしたボールを配列から完全に削除するクリーンアップ処理を行っています。
// game.js (ボールのクリーンアップ)
// アクティブなボールがない場合、ライフを減らしてリセット
const activeBallsCount = balls.filter(ball => ball.status === 1).length;
if (activeBallsCount === 0) {
lives--;
// ... リセット or ゲームオーバー処理
} else {
// ロストしたボールを配列から削除
balls = balls.filter(ball => ball.status === 1);
}
5. データベース連携(AJAX)とまとめ
スコア保存のフロー
ゲームオーバー時、ユーザーがアイコンを選択した後、JavaScript の saveScoreToRanking() 関数が AJAX を利用してスコア、名前、ステージ情報をサーバーに送信します。
このデータは WordPress の admin-ajax.php 経由で PHP 側の breakout_save_score アクションに渡され、データベースに保存されます。これにより、ブラウザを閉じてもランキングが永続化されます。
今後の拡張性
すべての特殊ブロック(ゴールデン、スロー、拡張パドル、追加ボール)は、ブロックオブジェクト内の isGolden: true のようなブール値フラグで管理されています。この設計により、新しい特殊ブロックやパワーアップを追加する際に、既存の構造を大きく変更することなく、フラグの追加と対応するロジックを collisionDetection() に追加するだけで拡張が可能です。
まとめ
本プロジェクトは、シンプルなゲームを題材としながら、Canvas の描画、オブジェクト指向的な配列管理、そして WordPress プラグイン開発における重要な技術的要素を組み合わせるための、実践的なテンプレートとして機能します。


コメント