【WPF練習14】壁崩し(7/9)
プロジェクトタイプ | C# WPFアプリケーション※ |
---|
プロジェクト名 | T10b |
---|
ソリューション名 | PET10 |
---|
ターゲットフレームワーク | .NET 6.0 (長期的なサポート) |
---|
注意
- 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
- 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
- プロジェクトの作成作業については準備を参照せよ.
14-7. 終了処理の実装
次にゲームの終了処理を実装しよう.ゲームを終了するのは前述したように以下のようなケースである.
- ケースA) ボールが画面の下に落下してしまった場合
- ケースB) すべてのブロックを破壊した場合
これらのケースではゲームの更新処理,つまりタイマー処理を停止すればよいが,ゲームが終了したことを
示す表示がないと不親切である.このためにcanvas1
にラベル(名前:label1
)を追加しよう.
MainWindow.xaml.cs
に_に示す内容を追記する.
MainWindow.xamlの追記内容 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
| <Window x:Class="T10b.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:T10b"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="300" Background="#F0F0F0">
<Grid>
<Viewbox>
<Canvas x:Name="canvas1" Width="600" Height="800"
Background="White" ClipToBounds="True"
MouseMove="canvas1_MouseMove">
<Rectangle x:Name="player" Width="100" Height="20"
Canvas.Left="250" Canvas.Top="700"
Stroke="Black" Fill="Orange"
Tag="Player"></Rectangle>
<Ellipse x:Name="ball" Width="10" Height="10"
Canvas.Left="295" Canvas.Top="685"
Stroke="Black" Fill="Red"></Ellipse>
<!-- メッセージ表示用のラベル -->
<Label x:Name="label1" Width="600"
Canvas.Left="0" Canvas.Top="120"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="72" Background="#7FFFFFFF"
Panel.ZIndex="255"
Content="TEST!"></Label>
</Canvas>
</Viewbox>
</Grid>
</Window>
|
ここまで追記したらデザイナで表示を確認しておこう._のように
画面上に「TEST!
」と表示されているはずである.
作業結果このラベルはゲーム中は非表示にする必要があるので,
.Visibilityプロパティを設定して
非表示にしておこう.このプロパティはWPFのほとんどの部品がもつプロパティで,
表示/非表示を設定することができるプロパティである.MainWindow.xaml
の
label1
に_に示すプロパティを追記する.
MainWindow.xamlの追記内容1
2
3
4
5
6
7
8
| <Label x:Name="label1" Width="600"
Canvas.Left="0" Canvas.Top="120"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="72" Background="#7FFFFFFF"
Panel.ZIndex="255"
Content="TEST!"
Visibility="Hidden"></Label>
|
追記したらデザイナで表示を確認しておこう._のように
label1
が非表示になったはずである.
作業結果それでは終了処理のうちケースAから実装してみよう.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
| 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))
{
// (..中略..)
}// if
double nextBallX = ballX + speedX;
double nextBallY = ballY + speedY;
// ボールが画面の下に落下した場合
if (canvas1.Height <= nextBallY)
{
label1.Content = "GAME OVER"; // label1 の文言を "GAME OVER"にして,
label1.Visibility = Visibility.Visible; // 表示状態にする.
timer.Stop(); // タイマーを停止する.
}// if
if (nextBallX < 0 || canvas1.Width <= nextBallX)
{
speedX *= -1;
ballX = Math.Clamp(nextBallX, 0, canvas1.Width) + EPSILON * speedX;
nextBallX = ballX + speedX;
}// if
// (..以下略..)
|
ここまで書けたら起動してみよう.ボールを画面下に落下させると_に示すように,
「GAME OVER
」の表示が現れてそれ以上のゲームの更新処理が行われなくなるはずである.
作業結果次にケースBの終了処理を実装しよう.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
| 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))
{
// (..中略..)
}//if
double nextBallX = ballX + speedX;
double nextBallY = ballY + speedY;
if (canvas1.Height <= nextBallY)
{
label1.Content = "GAME OVER";
label1.Visibility = Visibility.Visible;
timer.Stop();
}// if
// canavs1 に含まれている四角形のうちブロック役の
// 四角形の数を数える( .Count() メソッド).
var numBricks = (from r in GetRectangles()
where (string)r.Tag == "Bricks"
select r).Count();
if (numBricks == 0) // もうブロックがない場合
{
label1.Content = "CLEAR!"; // label1 の文言を "CLEAR!"にして,
label1.Visibility = Visibility.Visible; // 表示状態にする.
timer.Stop(); // タイマーを停止する.
}// if
if (nextBallX < 0 || canvas1.Width <= nextBallX)
{
speedX *= -1;
ballX = Math.Clamp(nextBallX, 0, canvas1.Width) + EPSILON * speedX;
nextBallX = ballX + speedX;
}// if
// (..以下略..)
|
ここまで書けたら起動してみよう.チートコマンドなどを用いてすべてのブロックを破壊すると_に示すように,
「CLEAR!
」の表示が現れてそれ以上のゲームの更新処理が行われなくなるはずである.
これでおおむねゲームとしての体裁は整ったが,現在の実装方法だとゲームが終了してしまうとアプリケーションを
起動しなおすことでしかリセットができないので不便である.そこで次節ではゲームのリセット機能を実装してみよう.
作業結果Last updated on 2024-01-09
Published on 2024-01-09