【WPF練習13】図形描画と定期処理(7/7) プロジェクトタイプ C# WPFアプリケーション※ プロジェクト名 T10a
ソリューション名 PET10
ターゲットフレームワーク .NET 6.0 (長期的なサポート)
注意 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと. プロジェクトの作成作業については準備 を参照せよ. 13-7. 簡易アニメーションの生成 前回までのWPF練習では,ボタンやラベルなどを用いた典型的なデスクトップアプリのようなものばかりを作っていたが
今回はアニメーションデモやゲームのようなものを作ることを試みてみよう.
そのまえに本節までにアプリに様々な変更を施してきて,見通しが悪くなっているのでMainWindow.xaml
と
MainWindow.xaml.cs
から余計な記述をすべて削除しよう.まずアプリのレイアウトを_ のように
変更するため,MainWindow.xaml
に_ に示す 5箇所 の変更を加える.
ウィンドウのレイアウト 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
37
38
<Window x:Class= "T10a.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:T10a"
mc:Ignorable= "d"
Title= "MainWindow" Height= "600" Width= "600" Background= "#F0F0F0" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height= "Auto" ></RowDefinition>
<RowDefinition Height= "*" ></RowDefinition>
</Grid.RowDefinitions>
<!-- ① Grid.ColumnDefinitions は削除する. -->
<!-- ② Grid.Column削除する↓ ↓Contentを"実行"に変更する. -->
<Button x:Name= "button1" Grid.Row= "0" Content= "実行"
Click= "button1_Click" ></Button>
<!-- ③ button2 は削除する. -->
<!-- ④ Grid.ColumnSpan削除する↓ -->
<Canvas x:Name= "canvas1" Grid.Row= "1"
Background= "White" Width= "512" Height= "512"
ClipToBounds= "True" >
<!-- 楕円(名前: ellipse1) -->
<Ellipse x:Name= "ellipse1" Canvas.Left= "300" Canvas.Top= "320"
Width= "100" Height= "100"
Stroke= "Black" Fill= "Red" ></Ellipse>
<!-- ⑤ 楕円以外は削除する. -->
</Canvas>
</Grid>
</Window>
次にMainWindow.xaml.cs
に_ に示す 5箇所 の変更を加える.
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
public partial class MainWindow : Window
{
private DispatcherTimer timer ;
public MainWindow ()
{
InitializeComponent ();
timer = new DispatcherTimer ();
timer . Interval = new TimeSpan ( 0 , 0 , 1 );
timer . Tick += Timer_Tick ;
// ① timer.Start() の呼び出しを削除する.
}
private void Timer_Tick ( object sender , EventArgs e )
{
// ② Timer_Tick()メソッドの内容を削除する.
}
// ③ count フィールドを削除する.
private void button1_Click ( object sender , RoutedEventArgs e )
{
// ④ button1_Click() メソッドの内容を削除する.
}
// ⑤ button2_Click() メソッドをまるごと削除する.
}
ここまで書けたら起動してみよう._ に示すような見た目になり,
ボタンをクリックしても何も起きないことを確認しておこう.
作業結果 今回は楕円ellipse1
の位置を動的に変更することで,疑似的にアニメーションしているように見せてみよう.
アニメーションの開始はボタンをクリックしたタイミングとする.
MainWindow
クラスを_ に示す通り変更しよう.
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
public partial class MainWindow : Window
{
private DispatcherTimer timer ;
private double speedX ; // 楕円の移動速度(X)
private double speedY ; // 楕円の移動速度(Y)
public MainWindow ()
{
InitializeComponent ();
timer = new DispatcherTimer ();
timer . Interval = new TimeSpan ( 0 , 0 , 0 , 0 , 16 ); // 実行間隔を16ミリ秒に変更
timer . Tick += Timer_Tick ;
speedX = - 4.0 ; // 定期処理のたび X 座標および
speedY = - 3.0 ; // Y 座標にこれらの値を加算する.
}
private void Timer_Tick ( object sender , EventArgs e )
{
// 現在の ellipse1 の中心位置を得る.
// (Canvas.GetLeft/Topから得られるのは左上の座標なので
// ellipse1の幅と高さの半分を足している).
double ballX = Canvas . GetLeft ( ellipse1 ) + ellipse1 . Width / 2 ;
double ballY = Canvas . GetTop ( ellipse1 ) + ellipse1 . Height / 2 ;
// 次の ellipse1 の位置を計算する.
double nextBallX = ballX + speedX ;
double nextBallY = ballY + speedY ;
// ↑で計算した位置を ellipse1 に設定する.
// (中心位置で計算したので左上位置にするために
// ellipse1の幅と高さの半分を引いている).
Canvas . SetLeft ( ellipse1 , nextBallX - ellipse1 . Width / 2 );
Canvas . SetTop ( ellipse1 , nextBallY - ellipse1 . Height / 2 );
}
private void button1_Click ( object sender , RoutedEventArgs e )
{
// タイマーが開始済みの場合は何もしない.
if ( timer . IsEnabled ) return ;
timer . Start (); // 定期処理を開始
}
}
ここまで書けたら起動してボタンをクリックしてみよう._ に示すように,
ellipse1
が左上へ移動していくことが分かるだろう.
作業結果 ellipse1
は放っておくとキャンバスの外に出て見切れてしまう.そこで,
ellipse1
がキャンバスの端まで到達したら反射する ように動きを変更してみよう.
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
private void Timer_Tick ( object sender , EventArgs e )
{
double ballX = Canvas . GetLeft ( ellipse1 ) + ellipse1 . Width / 2 ;
double ballY = Canvas . GetTop ( ellipse1 ) + ellipse1 . Height / 2 ;
double nextBallX = ballX + speedX ;
double nextBallY = ballY + speedY ;
if ( nextBallX < 0 || canvas1 . Width <= nextBallX ) //
{ //
speedX *= - 1 ; //
} // if // 次のボール位置がキャンバスの外に
// 出てしまった場合に,速度を反転する.
if ( nextBallY < 0 || canvas1 . Height <= nextBallY ) //
{ //
speedY *= - 1 ; //
} // if //
Canvas . SetLeft ( ellipse1 , nextBallX - ellipse1 . Width / 2 );
Canvas . SetTop ( ellipse1 , nextBallY - ellipse1 . Height / 2 );
}
ここまで書けたら起動してボタンをクリックしてみよう._ に示すように,
ellipse1
がキャンバス内を動き回ることが分かるだろう.
作業結果 ここまでを確認できたら本チュートリアルは完了である.
次のチュートリアルではこの挙動を応用して簡単なゲームを製作することを試みる.
Last updated on 2024-01-09 Published on 2024-01-09