【WPF練習14】壁崩し(6/9)
プロジェクトタイプ | C# WPFアプリケーション※ |
---|
プロジェクト名 | T10b |
---|
ソリューション名 | PET10 |
---|
ターゲットフレームワーク | .NET 6.0 (長期的なサポート) |
---|
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備を参照せよ.
14-6. デバッグ用のチートコマンドの作成
終了処理を作成して試すためには,ボールをわざと取りこぼして画面の下に落としたり,
ブロックをすべて破壊する必要がある.前者に関しては簡単に試すことができるが,
後者は難しい.また後述するが現在のボールの挙動の実装では,ボールがいつまで経っても
すべてのブロックを破壊できない場合がある.
このためブロックをすべて破壊するためのデバッグ用のチートコマンドを実装することにしよう.
今回はキーボードのコントロールキーが押されている場合に,ボールが手近なブロックにホーミングするようにしてみる.
Timer_Tick()
メソッドに_に示す内容を追記しよう.
MainWindow.xaml.csの追記内容 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| private void Timer_Tick(object sender, EventArgs e)
{
const double EPSILON = 1 / 256.0;
double ballX = Canvas.GetLeft(ball) + ball.Width / 2;
double ballY = Canvas.GetTop(ball) + ball.Height / 2;
// デバッグ用のチートコマンド
if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) // コントロールキーが押されている場合
{
// canavs1 に含まれている四角形のうちブロック役のものを取り出す.
var bricks = from r in GetRectangles()
where (string)r.Tag == "Bricks"
select r;
Rectangle nearestBrick = null; // 最も近いブロックを格納するための変数
double nearestDist = double.PositiveInfinity; // そのブロックまでの距離
Vector targetDir; // そのブロックへの方向ベクトル
var ballPos = new Vector(ballX, ballY); // 現在のボールの位置
// ボールに最も近いブロックを検索する.
foreach (var brick in bricks)
{
// ブロックの中心位置を計算する
var brickCenter = new Vector(
Canvas.GetLeft(brick) + brick.Width / 2,
Canvas.GetTop(brick) + brick.Height / 2
);
var dir = brickCenter - ballPos; // ボールの位置からブロックへ向かうベクトル
if (dir.Length < nearestDist) // より近い(≒短い)ベクトルが見つかった場合
{
// 最も近いブロックなどの変数を更新する.
nearestBrick = brick;
nearestDist = dir.Length;
targetDir = dir;
}// if
}// foreach
if (nearestBrick != null) // 最も近いブロックが見つかった場合
{
targetDir.Normalize();
targetDir *= 10;
speedX = targetDir.X; // 速度ベクトルを見つかったブロックへの
speedY = targetDir.Y; // 方向ベクトルに強制的に変更する.
}// if
}//if
double nextBallX = ballX + speedX;
double nextBallY = ballY + speedY;
if (nextBallX < 0 || canvas1.Width <= nextBallX)
{
speedX *= -1;
ballX = Math.Clamp(nextBallX, 0, canvas1.Width) + EPSILON * speedX;
nextBallX = ballX + speedX;
}// if
// (..以下略..)
|
ここまで書けたら起動してみよう.コントロールキーを押しっぱなしにしておくと,
_に示すようにボールが自動的にすべてのブロックを破壊してくれるはずである.
このチートコマンドを用意したうえで次節でゲームの処理を実装することにしよう.
作業結果Last updated on 2024-01-09
Published on 2024-01-09