• 検索結果がありません。

キーボード

ドキュメント内 ウォームアップ講座 51~60 (ページ 54-123)

コンボボックスで指定した 音色で、キーボード上をマウ スカーソルを動かす事に依 り、音を鳴らす事が出来る。

猶、音を鳴らさない様に、マ ウスカーソルをキーボード 上を移動させるには、マウス ボタンを押し下げた状態で、

移動させる。

一般的に、実用プログラムに比較するとゲームプログラムは、高度なテクニックを要求される事が多い。

此処では、ゲームプログラムを作成する事に依り、楽しみ乍ら、プログラムの制作手順を習得する事を 目的として居る。

制作手順としては、実際の作業過程に従い、段階的に機能を追加する方法を採用して居る。

此のプログラムを土台に、更に、各自で機能を追加して行く事が望まれる。

キーボード

VB 2005 ○55

□ アプリケーション画面のデザイン(標準コントロールの利用)

□ プログラムの動作原理(イベント駆動型のプログラム)

□ プログラムの構成要素(オブジェクトとプロパティ)

□ 値の代入(変数、オブジェクトのプロパティ)

□ グラフィックスの利用(Graphicsオブジェクト)

□ 条件に応じた処理(If文の利用)

□ 自動的に行われる処理(タイマーの利用)

今回の課題項目

コントロールの種類 プロパティ プロパティの設定値

フォーム Name MML

FormBorderStyle FixedSingle

MaximizeBox False

StartPosition CenterScreen

Text 音階を鳴らす♪

ピクチャボックス Name picKeyboard

Image keyboard.gif

Size 631, 200

ボタン1 Name btnOpen

Font Times New Roman、16、太字

Text OPEN

ボタン2 Name btnClose

Font Times New Roman、16、太字

Text CLOSE

コンボボックス Name cboTone

Font Times New Roman、12、標準

トラックバー Name barVolume

LargeChange 10

Maximum 127

Value 70

オ オブ ブジ ジェ ェク クト ト・ ・プ プロ ロパ パテ ティ ィ一 一覧 覧

ボタン1 コンボボックス

ピクチャボックス

ボタン2

トラックバー

Imports System.IO

Public Class MML

' API関数の宣言

< System.Runtime.InteropServices.DllImport( _

"winmm.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto )> _ Private Shared Function midiOutOpen( _

ByRef hMidiOut As Integer, _ ByVal uDeviceID As Integer, _ ByVal dwCallback As Integer, _ ByVal dwInstance As Integer, _

ByVal dwFlags As Integer ) As Integer End Function

< System.Runtime.InteropServices.DllImport( _

"winmm.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto )> _ Private Shared Function midiOutShortMsg( _

ByVal hMidiOut As Integer, _

ByVal dwMsg As Integer ) As Integer End Function

< System.Runtime.InteropServices.DllImport( _

"winmm.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto )> _ Private Shared Function midiOutClose( _

ByVal hMidiOut As Integer ) As Integer End Function

< System.Runtime.InteropServices.DllImport( _

"winmm.dll", CharSet:=System.Runtime.InteropServices.CharSet.Auto )> _ Private Shared Function midiOutGetNumDevs( ) As Integer

End Function

' フォームクラスレベルでグローバルな変数の宣言

Private HDL As Integer ' MIDIのハンドル Private Tone( 127 ) As String ' 音色

Private Pos( 35 ) As Rectangle ' 鍵盤の位置 Private ToneNo( 35 ) As String ' 音階番号

Private Cmd As String = "" ' 命令コード保存用 Private Num As Integer = 255

Private Flg As Boolean = False

プロ プ ログ グラ ラム ムリ リス スト ト

' フォームが読み込まれた時の処理

Private Sub MML_Load( ByVal sender As System.Object, ByVal e As System.EventArgs ) _ Handles MyBase.Load

' MIDIデバイスが有るか何うかの判定

If midiOutGetNumDevs( ) = 0 Then

MessageBox.Show( "御使用の環境では、MIDI音源を使用出来ません。" ) Exit Sub

Else

MessageBox.Show( "御使用の環境で、MIDI音源が使用出来ます。" ) End If

' 音色の読込

Dim Sr As StreamReader = New StreamReader( "tone.txt" ) Dim S, D( ) As String

For I As Integer = 0 To 127 S = Sr.ReadLine( )

D = S.Split( "," ) Tone( I ) = D( 0 )

cboTone.Items.Add( D( 1 )) Next

Sr.Close( )

' 鍵盤位置の読込

Sr = New StreamReader( "position.txt" ) For I As Integer = 0 To 35

S = Sr.ReadLine( ) D = S.Split( "," )

Pos( I ) = New Rectangle( Integer.Parse( D( 0 )), Integer.Parse( D( 1 )), _ Integer.Parse( D( 2 )), Integer.Parse( D( 3 )))

ToneNo( I ) = D( 4 ) Next

Sr.Close( ) Sr.Dispose( ) End Sub

' ボタン(OPEN)がクリックされた時の処理

Private Sub btnOpen_Click( ByVal sender As System.Object, ByVal e As System.EventArgs ) _ Handles btnOpen.Click

Dim Ret As Integer

' ハンドルの取得(Handleにハンドルが入る)

Ret = midiOutOpen( HDL, -1, 0, 0, 0 )

' コントロールの有効化

btnClose.Enabled = True: cboTone.Enabled = True: picKeyboard.Enabled = True

' ボタン(CLOSER)がクリックされた時の処理

Private Sub btnClose_Click( ByVal sender As System.Object, ByVal e As System.EventArgs ) _ Handles btnClose.Click

' クローズ

midiOutClose( HDL )

' コントロールの無効化

btnClose.Enabled = False: cboTone.Enabled = False: picKeyboard.Enabled = False End Sub

' コンボボックス(TONE)の選択項目が変化した時の処理

Private Sub cboTone_SelectedIndexChanged( ByVal sender As System.Object, _ ByVal e As System.EventArgs ) Handles cboTone.SelectedIndexChanged

Dim Ret As Integer Dim S As String

S = Tone( cboTone.SelectedIndex ) & "C0"

' 音色を変える

Ret = midiOutShortMsg( HDL, System.Convert.ToInt32( S, 16 )) End Sub

' ピクチャボックス(KEYBOARD)でマウスカーソルが移動した時の処理

Private Sub picKeyboard_MouseMove( ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.MouseEventArgs ) Handles picKeyboard.MouseMove

If Flg Then Exit Sub

Dim P As Point = New Point( e.X, e.Y ) Dim N As Integer = 0

Dim S As String = ""

' 鍵盤位置の取得

For I As Integer = 0 To 35

If Pos( I ).Contains( P ) Then N = I: Exit For Next

If Not N = Num Then If Not Cmd = "" Then ' 音を止める

S = Cmd & "80"

midiOutShortMsg( HDL, System.Convert.ToInt32( S, 16 )) End If

' 命令コードの生成

Cmd = ( barVolume.Value.ToString( ) & ToneNo( N )) S = Cmd & "90"

' 音を出す

midiOutShortMsg( HDL, System.Convert.ToInt32( S, 16 )) Num = N

End If End Sub

' ピクチャボックス(KEYBOARD)からマウスカーソルが退去した時の処理

Private Sub picKeyboard_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles picKeyboard.MouseLeave

If Not Cmd = "" Then ' 音を止める

Dim S As String = Cmd & "80"

midiOutShortMsg( HDL, System.Convert.ToInt32( S, 16 )) Cmd = "" : Num = 0

End If End Sub

' ピクチャボックス(KEYBOARD)でマウスボタンが押し下げられた時の処理

Private Sub picKeyboard_MouseDown( ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs ) Handles picKeyboard.MouseDown

Flg = True End Sub

' ピクチャボックス(KEYBOARD)でマウスボタンが離された時の処理

Private Sub picKeyboard_MouseUp( ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs ) Handles picKeyboard.MouseUp

Flg = False End Sub End Class

プログラムの概要

連鎖型落下ゲーム『フルーツ、ポン!』

で有る。

縦か横に同じ図柄のパネルを3個以上 並べて消して行く。消去された処には上 からパネルがスライドダウンして来る。

猶、移動させるパネルをクリックし、次 いで、移動先のパネルをクリックすると 2枚のパネルが入れ替わる。

一般的に、実用プログラムに比較すると ゲームプログラムは、高度なテクニック を要求される事が多い。

此処では、ゲームプログラムを作成する 事に依り、楽しみ乍ら、プログラムの制 作手順を習得する事を目的として居る。

制作手順としては、実際の作業過程に従

い、段階的に機能を追加する方法を採用して居る。

此のプログラムを土台に、更に、各自で機能を追加して行く事が望まれる。

フルーツ ポン!

VB 2005 ○56

□ アプリケーション画面のデザイン(標準コントロールの利用)

□ プログラムの動作原理(イベント駆動型のプログラム)

□ プログラムの構成要素(オブジェクトとプロパティ)

□ 値の代入(変数、オブジェクトのプロパティ)

□ グラフィックスの利用(Graphicsオブジェクト)

□ 条件に応じた処理(If文の利用)

□ 自動的に行われる処理(タイマーの利用)

今回の課題項目

コントロールの種類 プロパティ プロパティの設定値 フォーム Name fruits

FormBorderStyle FixedSingle

MaximizeBox False

StartPosition CenterScreen

Text Fruits Pon (尾立作品のリメイク)

ピクチャボックス1 Name picScore

Image score.gif

Size 49, 314

ピクチャボックス2 Name picG

BackColor White

BorderStyle FixedSingle

Size 290, 354

ピクチャボックス3 Name picTime

BorderStyle Fixed3D

Size 16, 354

ラベル1 Name lblTotalCaption

Font MS 明朝、12、太字

Text 合計

オ オブ ブジ ジェ ェク クト ト・ ・プ プロ ロパ パテ ティ ィ一 一覧 覧

ボタン1

ピクチャボックス1

ボタン2 ピクチャボックス2

ラベル1 ラベル2

ラベル4 ラベル3

ピクチャボックス3

コントロールの種類 プロパティ プロパティの設定値 ラベル2 Name lblGcnt

AutoSize False

BackColor White

Font MS 明朝、12、太字

Size 80, 16

Text 0

TextAlign MiddleRight

ラベル3 Name lblMes

AutoSize False

BackColor 192, 255, 255

BorderStyle FixedSingle

Font HG創英角ポップ体、16、太字

ForeColor Red

Size 250, 90

Text 開始ボタンクリックで

ゲームスタート!

TextAlign MiddleCenter

ラベル4 Name lblExplain

AutoSize False

Font MS 明朝、10、太字

Size 489, 36

Text ルールは簡単です。隣り合う2個のパネルを入

れ替えて、縦か横に3個以上揃えましょう。右 側のメーターが一杯に成る迄に幾つ消せるか な!!

ボタン1 Name btnStart

Font MS 明朝、12、太字

Text 開始

ボタン2 Name btnFinish

Font MS 明朝、12、太字

Text 終了

此のプログラムは、以前、ノアに居られた尾立先生が製作された物を、リメイクした 物です。従来のプログラムでは、正確なタイマー処理を行うのに、API関数が使用さ れて居ましたが、今回は、.NET Frameworkの機能で有るSystem.Timers名前空間

の Timer オブジェクトを使用しました。完全な別スレッドで処理が行われる為、正

確なタイマー処理が行えます。但し、フォームのコントロールを操作するには、デリ ゲート機能を使用する必要が有ります。少し難しいかも知れませんが、役に立つ知識 に成る筈です。少しコードが長いですが、其の分、楽しいです。

Public Class fruits

Private Const ENP As Integer = 20 Private Const INS As Integer = 21

Private Map( 9, 7 ) As Integer

Private Map1( 9, 7 ), Map2( 9, 7 ), Map3( 19, 7 ) As Integer Private Fcnt( 7 ), Tcnt, Ecnt As Integer

Private Px1, Py1, Px2, Py2 As Integer Private Sx, Sy, Ex, Ey As Integer Private FirstFlg, EndFlg As Boolean Private Cstop, Sact, Gact As Boolean

Private lblFcnt( 7 ) As Label Private Bm As Bitmap Private Gr, Gt As Graphics

Private Rn As Random = New Random( )

Private Tm As System.Timers.Timer = New System.Timers.Timer( )

Delegate Sub TimerDelegate( )

' フォームが読み込まれた時の処理

Private Sub fruits_Load( ByVal sender As System.Object, ByVal e As System.EventArgs ) _ Handles MyBase.Load

' 得点表示用ラベルの生成

Dim T As Integer = picScore.Top + 16 For I As Integer = 0 To 7

lblFcnt( I ) = New Label With lblFcnt( I )

.Size = New Size( 80, 16 )

.Location = New Point( 103, I * 40 + T ) .BackColor = Color.White

.Font = New Font( "MS 明朝", 12, FontStyle.Bold, GraphicsUnit.Point ) .TextAlign = ContentAlignment.MiddleRight

End With

Me.Controls.Add( lblFcnt( I )) Next

' 画像の読込

Bm = New Bitmap( "fruits.gif" )

' Graphicsオブジェクトのインスタンス生成

With picG

.Image = New Bitmap( .Width, .Height ) Gr = Graphics.FromImage( .Image )

プロ プ ログ グラ ラム ムリ リス スト ト

With picTime

.Image = New Bitmap( .Width, .Height ) Gt = Graphics.FromImage( .Image ) End With

' タイマーの設定

AddHandler Tm.Elapsed, _

New System.Timers.ElapsedEventHandler( AddressOf TimerProc ) Tm.Interval = 500

Tm.AutoReset = True End Sub

' フォームが閉じられ様とした時の処理

Private Sub fruits_FormClosing( ByVal sender As Object, _

ByVal e As System.Windows.Forms.FormClosingEventArgs ) Handles Me.FormClosing

Gr.Dispose( ) Application.Exit( ) End Sub

' ボタン(開始)がクリックされた時の処理

Private Sub btnStart_Click( ByVal sender As System.Object, ByVal e As System.EventArgs ) _ Handles btnStart.Click

Dim I, X, Y, N As Integer Dim R As Rectangle

Gact = True : EndFlg = False : Cstop = False Sx = 0 : Sy = 349 : Ex = 13 : Ey = 349

Ecnt = 0

Gt.Clear( Color.White ) : picTime.Refresh( ) Gr.Clear( Color.White )

For Y = 0 To 9 For X = 0 To 7 Do

N = Rn.Next( 0, 8 )

Loop Until PutChk( N, Y, X )

R = New Rectangle( 0, N * 32, 32, 32 )

Gr.DrawImage( Bm, X * 32 + 16, Y * 32 + 16, R, GraphicsUnit.Pixel ) Map( Y, X ) = N

Next Next

picG.Refresh( ) For I = 0 To 7

Fcnt( I ) = 0 : lblFcnt( I ).Text = Fcnt( I ).ToString( ) Next

Tcnt = 0 : lblGcnt.Text = Tcnt.ToString( )

FirstFlg = False : lblMes.Visible = False : Tm.Enabled = True End Sub

' ボタン(終了)がクリックされた時の処理

Private Sub btnFinish_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnFinish.Click

Me.Close( ) End Sub

' ピクチャボックスでマウスボタンが押し下げられた時の処理

Private Sub picG_MouseDown( ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.MouseEventArgs ) Handles picG.MouseDown

Dim X As Integer = e.X Dim Y As Integer = e.Y Dim C As Integer Dim R As Rectangle

If X >= 16 And X <= 271 And Y >= 16 And Y <= 335 And _ EndFlg = False And Gact = True Then

X = X - 16 : Y = Y - 16 If FirstFlg = False Then

Py1 = Int( Y / 32 ) : Px1 = Int( X / 32 ) If Map( Py1, Px1 ) <= 7 Then FirstFlg = True

R = New Rectangle( 32, Map( Py1, Px1 ) * 32, 32, 32 )

Gr.DrawImage( Bm, Px1 * 32 + 16, Py1 * 32 + 16, R, GraphicsUnit.Pixel ) picG.Refresh( )

Else

Cstop = True : Ecnt = 0

Select Case Map( Py1, Px1 ) Case 8

Call ChrDel( Py1, Px1, 1 ): Call MoveProc( ): Call SetProc( ) Case 9

Call ChrDel( Py1, Px1, 2 ): Call MoveProc( ): Call SetProc( ) Case 10

Call Del3Line( Py1, Px1 ): Call MoveProc( ): Call SetProc( ) Case 11

Call ChrDel( Py1, Px1, 3 ): Call MoveProc( ): Call SetProc( ) Case 12

Call ChrChange( Py1, Px1 ) Case 13

Call Vsort( Py1, Px1 ) End Select

While MatchChk( ) = True

Application.DoEvents( ) : System.Threading.Thread.Sleep( 200 ) Call EraseProc( ): Call MoveProc( ): Call SetProc( )

End While Cstop = False

If NoMoreMove( ) = True And Sact = False Then While NoMoreMove( ) = True

Call ReInitialize( ) End While

End If End If Else

Py2 = Int( Y / 32 ) : Px2 = Int( X / 32 ) If Py1 = Py2 And Px1 = Px2 Then FirstFlg = False

R = New Rectangle( 0, Map( Py1, Px1 ) * 32, 32, 32 )

Gr.DrawImage( Bm, Px1 * 32 + 16, Py1 * 32 + 16, R, GraphicsUnit.Pixel ) picG.Refresh( )

End If

If ( Py1 = Py2 And ( Px1 = Px2 + 1 Or Px1 = Px2 – 1 )) Or _ ( Px1 = Px2 And ( Py1 = Py2 + 1 Or Py1 = Py2 - 1 )) Then

C = Map( Py1, Px1 ): Map( Py1, Px1 ) = Map( Py2, Px2 ): Map( Py2, Px2 ) = C If MatchChk( ) = True Then

C = Map( Py1, Px1 ): Map( Py1, Px1 ) = Map( Py2, Px2 ): Map( Py2, Px2 ) = C Call TwoFlip( True )

R = New Rectangle( 0, Map( Py2, Px2 ) * 32, 32, 32 )

Gr.DrawImage( Bm, Px1 * 32 + 16, Py1 * 32 + 16, R, GraphicsUnit.Pixel ) R = New Rectangle( 0, Map( Py1, Px1 ) * 32, 32, 32 )

Gr.DrawImage( Bm, Px2 * 32 + 16, Py2 * 32 + 16, R, GraphicsUnit.Pixel) picG.Refresh( )

FirstFlg = False

C = Map( Py1, Px1 ): Map( Py1, Px1 ) = Map( Py2, Px2 ): Map( Py2, Px2 ) = C Do

Application.DoEvents( ) : System.Threading.Thread.Sleep( 200 ) Call EraseProc( ): Call MoveProc( ): Call SetProc( )

Loop While MatchChk( ) = True

If NoMoreMove( ) = True And Sact = False Then While NoMoreMove( ) = True

Call ReInitialize( ) End While

End If Else

C = Map( Py1, Px1 )

Map( Py1, Px1 ) = Map( Py2, Px2 ) Map( Py2, Px2 ) = C

Call TwoFlip( False ) FirstFlg = False End If

End If End If End If End Sub

'=======================

' ジェネラルプロシージャ

'=======================

' タイマー処理を行うジェネラルプロシージャ

Private Sub TimerProc( ByVal sender As Object, _ ByVal e As System.Timers.ElapsedEventArgs ) If Gact = True Then

Invoke( New TimerDelegate( AddressOf DrawTimer )) Sy -= 1: Ey -= 1

If Sy <= -1 Then Tm.Enabled = False EndFlg = True

Invoke( New TimerDelegate( AddressOf ShowGameOver )) Gact = False

End If End If End Sub

' 経過時間を表示するジェネラルプロシージャ(デリゲート用)

Private Sub DrawTimer( )

Gt.DrawLine( Pens.Magenta, Sx, Sy, Ex, Ey ) picTime.Refresh( )

End Sub

' 遊戯終了を表示するジェネラルプロシージャ(デリゲート用)

Private Sub ShowGameOver( ) lblMes.BackColor = Color.Yellow lblMes.Text = "Game Over"

lblMes.Visible = True End Sub

' 最初から3個並ぶのを検証するジェネラルプロシージャ

Private Function PutChk( ByVal N As Integer, ByVal Y As Integer, ByVal X As Integer ) _ As Boolean

If X > 1 Then

If N = Map( Y, X – 1 ) And N = Map( Y, X - 2 ) Then Return False

End If End If

If Y > 1 Then

If N = Map( Y - 1, X ) And N = Map( Y - 2, X ) Then Return False

End If End If Return True End Function

ドキュメント内 ウォームアップ講座 51~60 (ページ 54-123)

関連したドキュメント