はじめに
こんにちは!今回は、PowerShellを使ってブロック崩しゲームを実装する方法を紹介します。.NETのWindows Forms を利用して、グラフィカルなゲーム画面を作成し、キー入力操作とスコア機能を追加します。
前回の記事ではコンソールの画面に出力していたのを、今回は.NETのWindows Forms を画面のフレームワークとして採用しました。
目次
- 要件
- 仕様
- 環境設定
- ゲームの基本構造
- ゲームオブジェクトの実装
- キー入力の処理
- スコア機能の実装
- ゲームロジックの実装
- 画面の描画
- ゲームループの実装
- 完全なソースコード
- まとめ
1. 要件
このプロジェクトでは、以下の要件を満たすブロック崩しゲームを作成します:
- PowerShellを使用して実装すること
- グラフィカルなユーザーインターフェースを持つこと
- プレイヤーがパドルを操作してボールを打ち返せること
- 複数のブロックを配置し、ボールが当たると消えること
- スコア機能を実装すること
- ゲームオーバーとクリア条件を設定すること
2. 仕様
上記の要件を満たすため、以下の仕様で実装を行います:
-
使用技術:
- PowerShell
- .NET Framework(System.Windows.Forms, System.Drawing)
-
ゲーム画面:
- サイズ:400x500ピクセル
- 背景色:黒
-
ゲームオブジェクト:
- パドル:
- サイズ:幅100ピクセル、高さ10ピクセル
- 初期位置:画面下部中央
- 移動速度:5ピクセル/フレーム
- ボール:
- サイズ:直径10ピクセル
- 初期位置:画面中央
- 初期速度:X方向2ピクセル/フレーム、Y方向-2ピクセル/フレーム
- ブロック:
- サイズ:幅50ピクセル、高さ20ピクセル
- 配置:7列3行(計21個)
- パドル:
-
操作方法:
- 左矢印キー:パドルを左に移動
- 右矢印キー:パドルを右に移動
-
スコアシステム:
- 初期スコア:0点
- ブロック1個につき10点加算
-
ゲーム終了条件:
- ゲームオーバー:ボールが画面下端に到達
- クリア:すべてのブロックを破壊
-
その他:
- フレームレート:約60FPS(タイマー間隔15ミリ秒)
- 衝突判定:単純な矩形判定を使用
これらの仕様に基づいて、以降のセクションでゲームの実装を進めていきます。
3. 環境設定
PowerShellとWindows Formsを使用するため、特別な環境設定は必要ありません。Windows 10以降のOSであれば、標準でPowerShellが利用可能です。
4. ゲームの基本構造
まず、ゲームの基本構造を作成します。Windows Formsを使用してゲームウィンドウを作成し、ゲームオブジェクト(パドル、ボール、ブロック)を定義します。
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell ブロック崩し"
$form.Size = New-Object System.Drawing.Size(400, 500)
$form.StartPosition = "CenterScreen"
$form.BackColor = [System.Drawing.Color]::Black
$graphics = $form.CreateGraphics()
5. ゲームオブジェクトの実装
次に、ゲームオブジェクトを定義します。パドル、ボール、ブロックをそれぞれ構造体として実装します。
$paddle = @{
X = 150
Y = 450
Width = 100
Height = 10
Speed = 5
}
$ball = @{
X = 200
Y = 250
Size = 10
SpeedX = 2
SpeedY = -2
}
$blocks = @()
$blockWidth = 50
$blockHeight = 20
for ($i = 0; $i -lt 7; $i++) {
for ($j = 0; $j -lt 3; $j++) {
$blocks += @{
X = $i * ($blockWidth + 10) + 25
Y = $j * ($blockHeight + 10) + 50
Width = $blockWidth
Height = $blockHeight
IsVisible = $true
}
}
}
6. キー入力の処理
キー入力の処理方法を改善します。GetAsyncKeyState
を使用してキー入力を検出します。
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class KeyboardInput {
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(int vKey);
}
"@
function IsKeyPressed($key) {
return ([KeyboardInput]::GetAsyncKeyState($key) -band 0x8000) -ne 0
}
7. スコア機能の実装
スコア機能を実装します。ゲーム開始時のスコアを0とし、ブロックを壊すたびにスコアが増加するようにします。
$score = 0
function UpdateScore {
$script:score += 10
}
8. ゲームロジックの実装
ゲームロジックを実装します。ボールの移動、衝突判定、スコア管理などを行います。
function MoveBall {
$ball.X += $ball.SpeedX
$ball.Y += $ball.SpeedY
# 壁との衝突判定
if ($ball.X -le 0 -or $ball.X -ge ($form.Width - $ball.Size)) {
$ball.SpeedX *= -1
}
if ($ball.Y -le 0) {
$ball.SpeedY *= -1
}
# パドルとの衝突判定
if ($ball.Y -ge $paddle.Y - $ball.Size -and
$ball.X -ge $paddle.X -and
$ball.X -le $paddle.X + $paddle.Width) {
$ball.SpeedY *= -1
}
# ブロックとの衝突判定
for ($i = 0; $i -lt $blocks.Count; $i++) {
if ($blocks[$i].IsVisible -and
$ball.X -ge $blocks[$i].X -and
$ball.X -le $blocks[$i].X + $blocks[$i].Width -and
$ball.Y -ge $blocks[$i].Y -and
$ball.Y -le $blocks[$i].Y + $blocks[$i].Height) {
$blocks[$i].IsVisible = $false
$ball.SpeedY *= -1
UpdateScore # スコアを更新
break
}
}
}
function MovePaddle {
if (IsKeyPressed([System.Windows.Forms.Keys]::Left)) {
$paddle.X -= $paddle.Speed
}
if (IsKeyPressed([System.Windows.Forms.Keys]::Right)) {
$paddle.X += $paddle.Speed
}
$paddle.X = [Math]::Max(0, [Math]::Min($form.Width - $paddle.Width, $paddle.X))
}
9. 画面の描画
ゲームオブジェクトとスコアを描画する関数を実装します。
function DrawGame {
$graphics.Clear([System.Drawing.Color]::Black)
# パドルの描画
$graphics.FillRectangle([System.Drawing.Brushes]::White, $paddle.X, $paddle.Y, $paddle.Width, $paddle.Height)
# ボールの描画
$graphics.FillEllipse([System.Drawing.Brushes]::White, $ball.X, $ball.Y, $ball.Size, $ball.Size)
# ブロックの描画
foreach ($block in $blocks) {
if ($block.IsVisible) {
$graphics.FillRectangle([System.Drawing.Brushes]::Blue, $block.X, $block.Y, $block.Width, $block.Height)
}
}
# スコアの描画
$font = New-Object System.Drawing.Font("Arial", 12)
$brush = [System.Drawing.Brushes]::White
$graphics.DrawString("Score: $score", $font, $brush, 10, 10)
}
10. ゲームループの実装
最後に、ゲームループを実装して、ゲームを動作させます。
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 15
$timer.Add_Tick({
MoveBall
MovePaddle
DrawGame
# ゲームオーバー判定
if ($ball.Y -gt $form.Height) {
$timer.Stop()
[System.Windows.Forms.MessageBox]::Show("ゲームオーバー`nスコア: $score", "PowerShell ブロック崩し")
$form.Close()
}
# クリア判定
if (-not ($blocks | Where-Object { $_.IsVisible })) {
$timer.Stop()
[System.Windows.Forms.MessageBox]::Show("クリア!おめでとうございます!`nスコア: $score", "PowerShell ブロック崩し")
$form.Close()
}
})
$form.Add_Shown({$timer.Start()})
$form.Add_FormClosing({$timer.Stop()})
$form.ShowDialog()
11. 完全なソースコード
クラス図
シーケンス図
以下は、これまでの実装をまとめた完全なソースコードです。
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class KeyboardInput {
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(int vKey);
}
"@
$form = New-Object System.Windows.Forms.Form
$form.Text = "PowerShell ブロック崩し"
$form.Size = New-Object System.Drawing.Size(400, 500)
$form.StartPosition = "CenterScreen"
$form.BackColor = [System.Drawing.Color]::Black
$graphics = $form.CreateGraphics()
$paddle = @{
X = 150
Y = 450
Width = 100
Height = 10
Speed = 5
}
$ball = @{
X = 200
Y = 250
Size = 10
SpeedX = 2
SpeedY = -2
}
$blocks = @()
$blockWidth = 50
$blockHeight = 20
for ($i = 0; $i -lt 7; $i++) {
for ($j = 0; $j -lt 3; $j++) {
$blocks += @{
X = $i * ($blockWidth + 10) + 25
Y = $j * ($blockHeight + 10) + 50
Width = $blockWidth
Height = $blockHeight
IsVisible = $true
}
}
}
$score = 0
function IsKeyPressed($key) {
return ([KeyboardInput]::GetAsyncKeyState($key) -band 0x8000) -ne 0
}
function UpdateScore {
$script:score += 10
}
function MoveBall {
$ball.X += $ball.SpeedX
$ball.Y += $ball.SpeedY
if ($ball.X -le 0 -or $ball.X -ge ($form.Width - $ball.Size)) {
$ball.SpeedX *= -1
}
if ($ball.Y -le 0) {
$ball.SpeedY *= -1
}
if ($ball.Y -ge $paddle.Y - $ball.Size -and
$ball.X -ge $paddle.X -and
$ball.X -le $paddle.X + $paddle.Width) {
$ball.SpeedY *= -1
}
for ($i = 0; $i -lt $blocks.Count; $i++) {
if ($blocks[$i].IsVisible -and
$ball.X -ge $blocks[$i].X -and
$ball.X -le $blocks[$i].X + $blocks[$i].Width -and
$ball.Y -ge $blocks[$i].Y -and
$ball.Y -le $blocks[$i].Y + $blocks[$i].Height) {
$blocks[$i].IsVisible = $false
$ball.SpeedY *= -1
UpdateScore
break
}
}
}
function MovePaddle {
if (IsKeyPressed([System.Windows.Forms.Keys]::Left)) {
$paddle.X -= $paddle.Speed
}
if (IsKeyPressed([System.Windows.Forms.Keys]::Right)) {
$paddle.X += $paddle.Speed
}
$paddle.X = [Math]::Max(0, [Math]::Min($form.Width - $paddle.Width, $paddle.X))
}
function DrawGame {
$graphics.Clear([System.Drawing.Color]::Black)
$graphics.FillRectangle([System.Drawing.Brushes]::White, $paddle.X, $paddle.Y, $paddle.Width, $paddle.Height)
$graphics.FillEllipse([System.Drawing.Brushes]::White, $ball.X, $ball.Y, $ball.Size, $ball.Size)
foreach ($block in $blocks) {
if ($block.IsVisible) {
$graphics.FillRectangle([System.Drawing.Brushes]::Blue, $block.X, $block.Y, $block.Width, $block.Height)
}
}
$font = New-Object System.Drawing.Font("Arial", 12)
$brush = [System.Drawing.Brushes]::White
$graphics.DrawString("Score: $score", $font, $brush, 10, 10)
}
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 15
$timer.Add_Tick({
MoveBall
MovePaddle
DrawGame
if ($ball.Y -gt $form.Height) {
$timer.Stop()
[System.Windows.Forms.MessageBox]::Show("ゲームオーバー`nスコア: $score", "PowerShell ブロック崩し")
$form.Close()
}
if (-not ($blocks | Where-Object { $_.IsVisible })) {
$timer.Stop()
[System.Windows.Forms.MessageBox]::Show("クリア!おめでとうございます!`nスコア: $score", "PowerShell ブロック崩し")
$form.Close()
}
})
$form.Add_Shown({$timer.Start()})
$form.Add_FormClosing({$timer.Stop()})
$form.ShowDialog()
12. まとめ
以上で、PowerShellを使用したブロック崩しゲームの実装が完了しました。このコードを実行すると、シンプルながらも楽しいブロック崩しゲームをプレイすることができます。
主な特徴:
- Windows Formsを使用したグラフィカルなインターフェース
- 改善されたキー入力処理(
GetAsyncKeyState
の使用) - スコア機能の実装(ブロックを壊すとスコアが増加)
- ゲームオーバーとクリア時のスコア表示
PowerShellは通常、システム管理やスクリプト作成に使用されますが、このように創造的な用途にも適用できることがわかります。さらに改良を加えて、以下のような機能を実装してみるのも面白いでしょう:
- レベルデザイン(複数のステージ)
- サウンドエフェクト
- パワーアップアイテム
- 難易度設定
- ハイスコア機能
このプロジェクトを通じて、PowerShellの柔軟性と.NET Frameworkとの連携の可能性を探ることができました。システム管理者やIT専門家だけでなく、プログラミング初心者にとっても、PowerShellの可能性を広げる良い例となるでしょう。
ゲーム開発の楽しさを体験しながら、プログラミングスキルを向上させることができます。ぜひ、このコードをベースに自分なりのアイデアを追加して、オリジナルのゲームを作成してみてください。
Happy coding!