素人がゲームプログラム作成に挑戦
ゲームを買うお金がないから、ゲームを作るというゲームに挑戦!言語はVisual Basic(VB)をメインにC++、C#、Javaは参考程度
Latest Entries
4択クイズを作ってみる その1
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
さて、世間ではテスト勉強やら試験勉強なんかの時期になっていたりするわけですが、勉強で一番苦痛を感じるのが暗記です。
いや、人によっては暗記なんか簡単じゃんっていうかもしれませんが。
で、どうにかして暗記を効率よくできないかなぁと思い、4択クイズを作るということを思いつきました。
ゲームであればやっぱり覚えやすいですし、記憶にも残りやすいかと。
4択クイズといえば、ミリオネアが思いつきますが、あれをゲームにするってのは・・・。
ライフラインとかどう考えても無理です。
ということで、シンプルに問題を出して、4つの選択肢を表示し、その中から選択させ正解か不正解かを判定するようにしようかと思います。
ただし、1問しか問題が出題されないのはゲームになりませんから、10問、20問、30問、40問、50問とコースを用意します。
時間がないときは10問コース、たっぷりあるときは50問コースって感じですかね。
コースを用意するということは、問題を表示する前にあらかじめどのコースをやるかを選ばせるようにしておかなければなりません。
これは、いわゆるタイトル画面やメニュー画面を用意して対応するようにすればよいかと。
で、選んだコースに対応する問題を決められた数だけ出題し、正解・不正解を判定しながらいけば4択クイズはできあがりになります。
全問出題し終わったら正解率に応じて評価をした方がゲーム性が出るかと思いますので、評価画面なんかも用意していきます。
ただ、最後に評価があっても、途中が単調だと面白みがないので、途中でも正解率に応じてサービスを入れるようにします。
大まかに考えれば4択クイズってのは以上の点を踏まえておけばいいかと思います。
細かく考えるといろいろなところで矛盾的なところが出てきますが・・・。
とりあえず、概略としては以下のクラスがあればよいかと。
で、ゲームは今どのシーンなのかを元にそれぞれの処理を行うわけですから、そこらへんのシーンというかモードを考えておかなければなりません。
今回の4択クイズにおけるモードはタイトルモードとゲームモードだけです。
タイトルモードなら、タイトル画面を表示し、ゲームモードなら出題や判定や結果発表を行えばいいわけですね。
オプション画面やセーブ・ロード画面等があるゲームならもう少しモードは増えるかと思いますが、今回の4択クイズの場合はシンプルですね。
このモード状態はゲームクラスが保持するものになります。
モードによって、ゲームクラスはタイトルクラスを利用したり、出題クラスを利用したりすることになります。
細かいところまで記述しだすと長くなるので、とりあえず続きは次回にします。
いや、人によっては暗記なんか簡単じゃんっていうかもしれませんが。
で、どうにかして暗記を効率よくできないかなぁと思い、4択クイズを作るということを思いつきました。
ゲームであればやっぱり覚えやすいですし、記憶にも残りやすいかと。
4択クイズといえば、ミリオネアが思いつきますが、あれをゲームにするってのは・・・。
ライフラインとかどう考えても無理です。
ということで、シンプルに問題を出して、4つの選択肢を表示し、その中から選択させ正解か不正解かを判定するようにしようかと思います。
ただし、1問しか問題が出題されないのはゲームになりませんから、10問、20問、30問、40問、50問とコースを用意します。
時間がないときは10問コース、たっぷりあるときは50問コースって感じですかね。
コースを用意するということは、問題を表示する前にあらかじめどのコースをやるかを選ばせるようにしておかなければなりません。
これは、いわゆるタイトル画面やメニュー画面を用意して対応するようにすればよいかと。
で、選んだコースに対応する問題を決められた数だけ出題し、正解・不正解を判定しながらいけば4択クイズはできあがりになります。
全問出題し終わったら正解率に応じて評価をした方がゲーム性が出るかと思いますので、評価画面なんかも用意していきます。
ただ、最後に評価があっても、途中が単調だと面白みがないので、途中でも正解率に応じてサービスを入れるようにします。
大まかに考えれば4択クイズってのは以上の点を踏まえておけばいいかと思います。
細かく考えるといろいろなところで矛盾的なところが出てきますが・・・。
とりあえず、概略としては以下のクラスがあればよいかと。
- Form1クラス・・・各種イベント管理
- ゲームクラス・・・ゲームに関するクラス・状態を管理
- タイトル・メニュークラス・・・タイトルメニュー画面
- 出題クラス・・・問題の表示、選択肢の正解・不正解判定
- 評価クラス・・・正解率による総合評価
で、ゲームは今どのシーンなのかを元にそれぞれの処理を行うわけですから、そこらへんのシーンというかモードを考えておかなければなりません。
今回の4択クイズにおけるモードはタイトルモードとゲームモードだけです。
タイトルモードなら、タイトル画面を表示し、ゲームモードなら出題や判定や結果発表を行えばいいわけですね。
オプション画面やセーブ・ロード画面等があるゲームならもう少しモードは増えるかと思いますが、今回の4択クイズの場合はシンプルですね。
このモード状態はゲームクラスが保持するものになります。
モードによって、ゲームクラスはタイトルクラスを利用したり、出題クラスを利用したりすることになります。
細かいところまで記述しだすと長くなるので、とりあえず続きは次回にします。
ここでは、ゲームを作成するにあたって、必要となるキャラクタ、マップチップ、背景等の素材を公開しているサイトを紹介していきます。
素材の利用方法等については、各サイトさんの指示に従ってください。
自分のサイトも紹介してほしいという素材屋さんはコメント欄にURL等をお願いします。
素材の利用方法等については、各サイトさんの指示に従ってください。
自分のサイトも紹介してほしいという素材屋さんはコメント欄にURL等をお願いします。
フェードイン&フェードアウト その3
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
フェードイン&フェードアウト その2
それでは、フェードイン・フェードアウトクラスを作成していきます。
フェードイン・フェードアウトの前提となる透明度の変更方法についてはImageAttributesクラスとColorMatrixクラスを利用することでできることを確認しました。
特にColorMatrixクラスの33行列の値が透明度の値になることがわかりました。
この値を一定時間ごとに変更していけばフェードイン・フェードアウトを作ることができます。
実際に作成したプログラムが↓です。
ImageAttributesやColorMatrixはSystem.Drawing.Imaging名前空間の中にあるクラスになります。
これは通常では参照設定がされていませんから、Importsステートメントで参照設定を行っておきます。
Newコンストラクタでは、あらかじめ必要となる設定を行っておきます。
今回は、画像ファイルをプログラムで作成しています。
もちろん、ちゃんとした画像ファイルを用意し、読み込んで利用しても構いません。
Updateメソッドでは一定時間おきに透明度を変更するようにしています。
今回は一定時間を0.1秒としています。
0から1までの範囲内を0.1秒ごとに透明度を変化するようにしていますから、透明から不透明になるまでには1秒程度かかることになります。
ここらへんは0.2秒間隔にしたり、0.1秒おきに0.2ずつ透明度を変化させてたりすれば透明から不透明になるまでの時間を調整することができます。
ちなみに、加算したり減算したりするときの0.1DのDはDecimalのDになります。
そのまま0.1と書いてしまうとDouble型になってしまい、変な誤作動の原因になることもありますからね。
最後にDrawメソッドですが、これはUpdateメソッドにより編集された画像を描画するだけになります。
が、DrawImageメソッドはオーバーロードにより30種類くらいの記述方法が定義されていてどれを使うか悩むところになります。
ImageAttributesをパラメータとして持っている記述方法のものを利用すればいいわけですが、書式が面倒くさい・・・。
とりあえず、これでフェードイン・フェードアウトクラスのできあがりになります。
それでは、フェードイン・フェードアウトクラスを作成していきます。
フェードイン・フェードアウトの前提となる透明度の変更方法についてはImageAttributesクラスとColorMatrixクラスを利用することでできることを確認しました。
特にColorMatrixクラスの33行列の値が透明度の値になることがわかりました。
この値を一定時間ごとに変更していけばフェードイン・フェードアウトを作ることができます。
実際に作成したプログラムが↓です。
Imports System.Drawing.Imaging
Public Class FadeClass
Dim _img As Bitmap
Dim _att As ImageAttributes
Dim _mtx As ColorMatrix
Dim _m33 As Decimal
Dim _lasttime As Double
Dim _fmode As Boolean
Public Sub New(ByVal io As Boolean)
Dim g As Graphics
_fmode = io
_img = New Bitmap(640, 480)
g = Drawing.Graphics.FromImage(_img)
g.FillRectangle(Brushes.Black, New Rectangle(0, 0, 640, 480))
_att = New ImageAttributes
_mtx = New ColorMatrix
_mtx.Matrix00 = 1
_mtx.Matrix11 = 1
_mtx.Matrix22 = 1
_mtx.Matrix44 = 1
End Sub
Public Sub Update(ByVal nowTime As Double, ByVal elapsedTime As Double)
If _lasttime = 0 Then
If _fmode = False Then 'フェードアウト
_m33 = 0D '不透明
Else 'フェードイン
_m33 = 1D '透明
End If
_lasttime = nowTime
ElseIf nowTime - _lasttime > 0.1 Then
If _fmode = False Then 'フェードアウト
If _m33 < 1 Then
_m33 += 0.1D '不透明に
End If
Else 'フェードイン
If _m33 > 0 Then
_m33 -= 0.1D '透明に
End If
End If
_lasttime = nowTime
End If
_mtx.Matrix33 = _m33 'ColorMatrixの33行列に設定
_att.SetColorMatrix(_mtx)
End Sub
Public Sub Draw(ByVal g As Graphics)
g.DrawImage(_img, New Rectangle(0, 0, 640, 480), 0, 0, 640, 480, GraphicsUnit.Pixel, _att)
End Sub
End Class
Public Class FadeClass
Dim _img As Bitmap
Dim _att As ImageAttributes
Dim _mtx As ColorMatrix
Dim _m33 As Decimal
Dim _lasttime As Double
Dim _fmode As Boolean
Public Sub New(ByVal io As Boolean)
Dim g As Graphics
_fmode = io
_img = New Bitmap(640, 480)
g = Drawing.Graphics.FromImage(_img)
g.FillRectangle(Brushes.Black, New Rectangle(0, 0, 640, 480))
_att = New ImageAttributes
_mtx = New ColorMatrix
_mtx.Matrix00 = 1
_mtx.Matrix11 = 1
_mtx.Matrix22 = 1
_mtx.Matrix44 = 1
End Sub
Public Sub Update(ByVal nowTime As Double, ByVal elapsedTime As Double)
If _lasttime = 0 Then
If _fmode = False Then 'フェードアウト
_m33 = 0D '不透明
Else 'フェードイン
_m33 = 1D '透明
End If
_lasttime = nowTime
ElseIf nowTime - _lasttime > 0.1 Then
If _fmode = False Then 'フェードアウト
If _m33 < 1 Then
_m33 += 0.1D '不透明に
End If
Else 'フェードイン
If _m33 > 0 Then
_m33 -= 0.1D '透明に
End If
End If
_lasttime = nowTime
End If
_mtx.Matrix33 = _m33 'ColorMatrixの33行列に設定
_att.SetColorMatrix(_mtx)
End Sub
Public Sub Draw(ByVal g As Graphics)
g.DrawImage(_img, New Rectangle(0, 0, 640, 480), 0, 0, 640, 480, GraphicsUnit.Pixel, _att)
End Sub
End Class
ImageAttributesやColorMatrixはSystem.Drawing.Imaging名前空間の中にあるクラスになります。
これは通常では参照設定がされていませんから、Importsステートメントで参照設定を行っておきます。
Newコンストラクタでは、あらかじめ必要となる設定を行っておきます。
今回は、画像ファイルをプログラムで作成しています。
もちろん、ちゃんとした画像ファイルを用意し、読み込んで利用しても構いません。
Updateメソッドでは一定時間おきに透明度を変更するようにしています。
今回は一定時間を0.1秒としています。
0から1までの範囲内を0.1秒ごとに透明度を変化するようにしていますから、透明から不透明になるまでには1秒程度かかることになります。
ここらへんは0.2秒間隔にしたり、0.1秒おきに0.2ずつ透明度を変化させてたりすれば透明から不透明になるまでの時間を調整することができます。
ちなみに、加算したり減算したりするときの0.1DのDはDecimalのDになります。
そのまま0.1と書いてしまうとDouble型になってしまい、変な誤作動の原因になることもありますからね。
最後にDrawメソッドですが、これはUpdateメソッドにより編集された画像を描画するだけになります。
が、DrawImageメソッドはオーバーロードにより30種類くらいの記述方法が定義されていてどれを使うか悩むところになります。
ImageAttributesをパラメータとして持っている記述方法のものを利用すればいいわけですが、書式が面倒くさい・・・。
とりあえず、これでフェードイン・フェードアウトクラスのできあがりになります。
フェードイン&フェードアウト その2
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
フェードイン&フェードアウト その1の続きです。
フェードイン、フェードアウトのアルゴリズムが整理できたところで、実際にプログラムを作成していきます。
まず、今回作成するクラスはForm1クラスとフェードイン・フェードアウトクラスになります。
Form1クラスはいつものように画面描画やイベント管理を行います。
いわゆるゲームループってやつです。
フェードイン・フェードアウトクラスでは、画像を透明化したり不透明化したりすることを行います。
まず、Form1クラスから作成していきます。
Form1のPaintメソッド内で、更新、描画、強制再描画をいつも通り記述しているわけですが、フラグの状態によりフェードイン・フェードアウトオブジェクトに対しメソッドを実行するようにしています。
これはオブジェクトが生成されていないときに実行されてしまうとインスタンスがありませんとエラーが出てしまいますから、その対策となります。
フェードイン・フェードアウトクラスはマウスクリックイベント時に生成するようにしました。
この生成するタイミングは実際のゲームであればシーンの切り替えやステージの切り替えになるかと思います。
マウスクリックを行うと、フェードイン、フェードアウトが交互に実行されます。
そのために、モードを切り替えるようにしています。
次回はフェードイン・フェードアウトクラスを作成していきます。
フェードイン、フェードアウトのアルゴリズムが整理できたところで、実際にプログラムを作成していきます。
まず、今回作成するクラスはForm1クラスとフェードイン・フェードアウトクラスになります。
Form1クラスはいつものように画面描画やイベント管理を行います。
いわゆるゲームループってやつです。
フェードイン・フェードアウトクラスでは、画像を透明化したり不透明化したりすることを行います。
まず、Form1クラスから作成していきます。
Public Class Form1
Dim swatch As Stopwatch = New Stopwatch( ) 'ストップウォッチ
Dim lastTime As Double '前回実行時の時間
Dim fade As FadeClass 'フェードイン・フェードアウトオブジェクト変数
Dim sflg As Boolean 'フェードイン・フェードアウト開始フラグ
Dim fmode As Boolean 'フェードイン・フェードアウトのモード
Public Sub New( )
' この呼び出しは、Windows フォーム デザイナで必要です。
InitializeComponent( )
' InitializeComponent( ) 呼び出しの後で初期化を追加します。
Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer, True)
Me.ClientSize = New Size(640, 480) 'クライアント領域を640×480に設定
Me.Init( )
End Sub
Sub Init( )
lastTime = 0.0
swatch.Reset( )
swatch.Start( )
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim nowTime As Double = swatch.ElapsedMilliseconds / 1000.0 'Paintメソッドを実行した瞬間の時間
Dim elapsedTime As Double = nowTime - lastTime
lastTime = nowTime
'Update…変更処理
If sflg Then 'フェードイン・フェードアウト開始状態なら
fade.Update(nowTime, elapsedTime)
End If
'Draw…描画処理
If sflg Then 'フェードイン・フェードアウト開始状態なら
fade.Draw(e.Graphics)
End If
Me.Invalidate( ) 'Formの強制描画
End Sub
Private Sub Form1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
fade = New FadeClass(fmode) 'フェードイン・フェードアウトオブジェクトの生成
sflg = True
fmode = Not fmode 'モード切替
End Sub
End Class
Dim swatch As Stopwatch = New Stopwatch( ) 'ストップウォッチ
Dim lastTime As Double '前回実行時の時間
Dim fade As FadeClass 'フェードイン・フェードアウトオブジェクト変数
Dim sflg As Boolean 'フェードイン・フェードアウト開始フラグ
Dim fmode As Boolean 'フェードイン・フェードアウトのモード
Public Sub New( )
' この呼び出しは、Windows フォーム デザイナで必要です。
InitializeComponent( )
' InitializeComponent( ) 呼び出しの後で初期化を追加します。
Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer, True)
Me.ClientSize = New Size(640, 480) 'クライアント領域を640×480に設定
Me.Init( )
End Sub
Sub Init( )
lastTime = 0.0
swatch.Reset( )
swatch.Start( )
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim nowTime As Double = swatch.ElapsedMilliseconds / 1000.0 'Paintメソッドを実行した瞬間の時間
Dim elapsedTime As Double = nowTime - lastTime
lastTime = nowTime
'Update…変更処理
If sflg Then 'フェードイン・フェードアウト開始状態なら
fade.Update(nowTime, elapsedTime)
End If
'Draw…描画処理
If sflg Then 'フェードイン・フェードアウト開始状態なら
fade.Draw(e.Graphics)
End If
Me.Invalidate( ) 'Formの強制描画
End Sub
Private Sub Form1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
fade = New FadeClass(fmode) 'フェードイン・フェードアウトオブジェクトの生成
sflg = True
fmode = Not fmode 'モード切替
End Sub
End Class
Form1のPaintメソッド内で、更新、描画、強制再描画をいつも通り記述しているわけですが、フラグの状態によりフェードイン・フェードアウトオブジェクトに対しメソッドを実行するようにしています。
これはオブジェクトが生成されていないときに実行されてしまうとインスタンスがありませんとエラーが出てしまいますから、その対策となります。
フェードイン・フェードアウトクラスはマウスクリックイベント時に生成するようにしました。
この生成するタイミングは実際のゲームであればシーンの切り替えやステージの切り替えになるかと思います。
マウスクリックを行うと、フェードイン、フェードアウトが交互に実行されます。
そのために、モードを切り替えるようにしています。
次回はフェードイン・フェードアウトクラスを作成していきます。
フェードイン&フェードアウト その1
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
今回はゲームのエフェクト効果についてやってみます。
まず挑戦するのは、ステージ切り替えやシーン切り替えでも利用されるフェードインとフェードアウトです。
ご存知のようにフェードインは不透明な画像が透明になる効果、フェードアウトは透明な画像が不透明になる効果です。
表示している画像の上に黒画像や白画像を重ねて透明度を変更するってことですね。
画像の特定の色を透明にするのは、画像ファイルの透明化でも紹介したようにMakeTransparentメソッドで行えます。
しかし、今回のフェードイン、フェードアウトは画像全体を透明にしたり半透明にしたりしていきますから、MakeTransparentメソッドでは処理できません。
フェードイン、フェードアウトを行ううえでポイントになることはどうやって画像ファイルを半透明にするかです。
画像を半透明にするためにはSystem.Drawing.Imaging名前空間にあるImageAttributesクラスとColorMatrixクラスを利用します。
これら2つのクラスを利用したサンプルページカラー行列を使用したイメージのアルファ値の設定を見ると、画像の透明度を変更するためには、ColorMatrixの行列33が透明度を表していることがわかります。
ColorMatrix行列は5行5列で構成されているようですが、数学の1行1列は0行0列になります。
ですから、プログラムでの3行3列は数学の4行4列目ということになります。
ColorMatrixを作成したら、ImageAttributesオブジェクトのSetColorMatrixメソッドにColorMatrixオブジェクトを渡せばできあがりみたいです。
ただ、今回のテーマは半透明を作るわけではなく、フェードインとフェードアウトを作るわけですから、このままMSDNのサンプルを使ってもできあがりになりません。
フェードインとフェードアウトの考え方は最初にも書いたように不透明から透明、透明から不透明にするということです。
これは、透明度を変化させればよいってことですから、描画するときに透明度を変更してあげればよいということになります。
透明度はColorMatrixの33行列ですね。
とまぁ、MSDNを参考にすればなんとかなるわけなんですが、もうちょっとわかりやすくサイトを作ってもらえないかと。
素人が見るページじゃないとつくづく思いますね。
次回は実際にVBでプログラムを作っていきます。
まず挑戦するのは、ステージ切り替えやシーン切り替えでも利用されるフェードインとフェードアウトです。
ご存知のようにフェードインは不透明な画像が透明になる効果、フェードアウトは透明な画像が不透明になる効果です。
表示している画像の上に黒画像や白画像を重ねて透明度を変更するってことですね。
画像の特定の色を透明にするのは、画像ファイルの透明化でも紹介したようにMakeTransparentメソッドで行えます。
しかし、今回のフェードイン、フェードアウトは画像全体を透明にしたり半透明にしたりしていきますから、MakeTransparentメソッドでは処理できません。
フェードイン、フェードアウトを行ううえでポイントになることはどうやって画像ファイルを半透明にするかです。
画像を半透明にするためにはSystem.Drawing.Imaging名前空間にあるImageAttributesクラスとColorMatrixクラスを利用します。
これら2つのクラスを利用したサンプルページカラー行列を使用したイメージのアルファ値の設定を見ると、画像の透明度を変更するためには、ColorMatrixの行列33が透明度を表していることがわかります。
ColorMatrix行列は5行5列で構成されているようですが、数学の1行1列は0行0列になります。
ですから、プログラムでの3行3列は数学の4行4列目ということになります。
ColorMatrixを作成したら、ImageAttributesオブジェクトのSetColorMatrixメソッドにColorMatrixオブジェクトを渡せばできあがりみたいです。
ただ、今回のテーマは半透明を作るわけではなく、フェードインとフェードアウトを作るわけですから、このままMSDNのサンプルを使ってもできあがりになりません。
フェードインとフェードアウトの考え方は最初にも書いたように不透明から透明、透明から不透明にするということです。
これは、透明度を変化させればよいってことですから、描画するときに透明度を変更してあげればよいということになります。
透明度はColorMatrixの33行列ですね。
とまぁ、MSDNを参考にすればなんとかなるわけなんですが、もうちょっとわかりやすくサイトを作ってもらえないかと。
素人が見るページじゃないとつくづく思いますね。
次回は実際にVBでプログラムを作っていきます。
最近はなかなかいい本が出版されないですね。
とりあえず、今回は持っていたら便利かなという本を紹介しておきます。
Visual Basic 2008パーフェクトマスター
この本は入門書には載っていないかゆいところまで手が届く本になります。
入門書での勉強が終わった方は一度読んでおくとよいかもしれません。
入門書の補足としても使える本になります。
ゲームを作るならコントロールとかの使い方がいっぱい書いてある本より、それ以外の小技が載っている本のほうが使えますね。
まぁ、そういう本は出版しても限られた人しか買いませんから出版するメリットはないんでしょうけど。
とりあえず、今回は持っていたら便利かなという本を紹介しておきます。
この本は入門書には載っていないかゆいところまで手が届く本になります。
入門書での勉強が終わった方は一度読んでおくとよいかもしれません。
入門書の補足としても使える本になります。
ゲームを作るならコントロールとかの使い方がいっぱい書いてある本より、それ以外の小技が載っている本のほうが使えますね。
まぁ、そういう本は出版しても限られた人しか買いませんから出版するメリットはないんでしょうけど。
テキストデータの暗号化
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
ゲームを作っていくと、外部ファイルからデータを読み込み、セリフとして利用したりイベント処理用として利用したりすることがあります。
このファイルはゲームの内容を思いっきり記述した重要なデータになるわけです。
となると普通にファイルを開かれて見られてしまうと、ゲームのネタばれになったり、改造されてゲームとしては楽しめないようになったりします。
簡単に見られないようにするためにはどうするかというと、手っ取り早いのが暗号化でしょう。
暗号化してしまえば、何を書いているか判断するのは難しくなります。
で、VBで暗号化を考えてみました。
普通に考えると、文字コードに同一パターンで生成される乱数を加算して文字コードをずらせば暗号化になります。
文字コードがずれれば言語として認識しにくくなりますからね。
で、複合化は暗号化のときと同じ乱数を同一パターンで生成し、減算すれば元に戻せます。
これで作ってみると、1バイト文字と2バイト文字が混じっているとなかなかうまくいかず・・・。
暗号はできるけど、複合がうまくいかないんですね。
さて、どうするかと悩んでネットで調べたら・・・さすがMicrosoft。
探していた暗号化用の特集を作っているじゃないですか。↓
10 行でズバリ !! 暗号化 (VB)
なんかよくわからないオブジェクトを使っていますが・・・。
とりあえずこの通り作ってみると暗号化と複合化ができます。
実際のゲームでは暗号化したファイルを読み込み、複合化して利用していくわけですからそこらへんを作ることができるかどうかが、ポイントになりそうです。
このファイルはゲームの内容を思いっきり記述した重要なデータになるわけです。
となると普通にファイルを開かれて見られてしまうと、ゲームのネタばれになったり、改造されてゲームとしては楽しめないようになったりします。
簡単に見られないようにするためにはどうするかというと、手っ取り早いのが暗号化でしょう。
暗号化してしまえば、何を書いているか判断するのは難しくなります。
で、VBで暗号化を考えてみました。
普通に考えると、文字コードに同一パターンで生成される乱数を加算して文字コードをずらせば暗号化になります。
文字コードがずれれば言語として認識しにくくなりますからね。
で、複合化は暗号化のときと同じ乱数を同一パターンで生成し、減算すれば元に戻せます。
これで作ってみると、1バイト文字と2バイト文字が混じっているとなかなかうまくいかず・・・。
暗号はできるけど、複合がうまくいかないんですね。
さて、どうするかと悩んでネットで調べたら・・・さすがMicrosoft。
探していた暗号化用の特集を作っているじゃないですか。↓
10 行でズバリ !! 暗号化 (VB)
なんかよくわからないオブジェクトを使っていますが・・・。
とりあえずこの通り作ってみると暗号化と複合化ができます。
実際のゲームでは暗号化したファイルを読み込み、複合化して利用していくわけですからそこらへんを作ることができるかどうかが、ポイントになりそうです。
文字のアンチエイリアス
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
セリフ枠の表示 その9で一通りセリフ関係の処理はできあがったわけですが、ちょっと気になる点がありました。
何が気になったかというと、セリフを表示したときに画面に描画される文字がギザギザということ。
いわゆるアンチエイリアスがかかっていないためになってしまう現象です。
これをどうにかしないとなんか見栄えが悪いわけです。
アンチエイリアスの設定方法は、Visual Basic 2008入門という本で見覚えがあったので調べてみました。
この本によるとグラフィックオブジェクトのTextRenderingHintプロパティを設定すればよいらしいです。
まぁ、なんかピンボケしたような感じになりますが、ギザギザより見栄えが良いので問題なし。
プログラムは一行だけ追加してあげます。
アンチエイリアスの設定はいくつかの種類があるようですが、今回利用したものが一番しっくりきました。
何が気になったかというと、セリフを表示したときに画面に描画される文字がギザギザということ。
いわゆるアンチエイリアスがかかっていないためになってしまう現象です。
これをどうにかしないとなんか見栄えが悪いわけです。
アンチエイリアスの設定方法は、Visual Basic 2008入門という本で見覚えがあったので調べてみました。
この本によるとグラフィックオブジェクトのTextRenderingHintプロパティを設定すればよいらしいです。
まぁ、なんかピンボケしたような感じになりますが、ギザギザより見栄えが良いので問題なし。
プログラムは一行だけ追加してあげます。
Public Class MessageClass
…(省略)
Public Sub Draw(ByVal g As Graphics)
Dim dy As Integer = 0
If mflg = True Then
g.DrawImage(img, 0, 320)
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
For i As Integer = 0 To dmsg.Count - 1
If i = dmsg.Count - 1 Then '最終行なら
g.DrawString(dmsg(i) & dmark, mfont, Brushes.White, 20, 342 + dy)
Else
g.DrawString(dmsg(i), mfont, Brushes.White, 20, 342 + dy)
End If
dy += 24
Next
End If
End Sub
…(省略)
End Class
…(省略)
Public Sub Draw(ByVal g As Graphics)
Dim dy As Integer = 0
If mflg = True Then
g.DrawImage(img, 0, 320)
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
For i As Integer = 0 To dmsg.Count - 1
If i = dmsg.Count - 1 Then '最終行なら
g.DrawString(dmsg(i) & dmark, mfont, Brushes.White, 20, 342 + dy)
Else
g.DrawString(dmsg(i), mfont, Brushes.White, 20, 342 + dy)
End If
dy += 24
Next
End If
End Sub
…(省略)
End Class
アンチエイリアスの設定はいくつかの種類があるようですが、今回利用したものが一番しっくりきました。
マップチップ その10
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
マップチップ その9の続きです。
今回はマップクラスに追加するマップチップクラスを作成していきます。
このマップチップクラスから作成したオブジェクトをマップクラスのマップ配列に追加することでマップを作成していきます。
マップチップクラスに必要な情報は、マップチップ番号と移動可能かどうかの情報になります。
本格的に考えればイベント情報とかも設定する必要があるのでしょうが、とりあえずはシンプルに作成していきます。
このマップチップクラスの役割はひとつのマップチップが特定の情報を保持するということだけです。
ですから、プログラムとしてはデータの設定とデータの取得だけとなります。
マップチップが持つフィールドをPublicで公開してもよいでしょうが、プロパティで操作するようにした方がベターでしょうから、プロパティを作成してフィールドを操作するようにしておきます。
ということで、そこらへんを考慮して作成したプログラムは以下のような感じです。
これでマップチップクラスができあがりました。
あとはキャラクタクラスになりますね。
移動可否情報を元に移動できるかどうか判断できるようマップクラスとマップチップクラスを作成しましたから、この情報を利用して処理をさせていけばよいわけです。
ただし、マップ情報はキャラクタクラスから見るとわかりません。
そこで、親であるGameクラスからキャラクタクラスにマップ情報を渡す作業を行ってあげます。
渡すタイミングはキー入力があったときです。
それ以外はマップとキャラクタは関連を持ちません。
プログラムとしては、以前作成したものとほとんど変わりません。
変わるところはキー入力時の処理だけになります。
これでマップ情報を元に移動できるマップチップなら移動し、移動できないマップチップなら移動しないように制御することができました。
ポイントはキー入力処理でマップ情報を受け渡しするということですね。
Gameクラスのキー入力処理でマップオブジェクトを渡してあげれば、キャラクタクラスでマップ情報を参照することができるようになります。
今回はマップクラスに追加するマップチップクラスを作成していきます。
このマップチップクラスから作成したオブジェクトをマップクラスのマップ配列に追加することでマップを作成していきます。
マップチップクラスに必要な情報は、マップチップ番号と移動可能かどうかの情報になります。
本格的に考えればイベント情報とかも設定する必要があるのでしょうが、とりあえずはシンプルに作成していきます。
このマップチップクラスの役割はひとつのマップチップが特定の情報を保持するということだけです。
ですから、プログラムとしてはデータの設定とデータの取得だけとなります。
マップチップが持つフィールドをPublicで公開してもよいでしょうが、プロパティで操作するようにした方がベターでしょうから、プロパティを作成してフィールドを操作するようにしておきます。
ということで、そこらへんを考慮して作成したプログラムは以下のような感じです。
Public Class MaptipClass
Dim _tNo As Integer 'マップチップ番号
Dim _mflg As Boolean '移動可否フラグ
Public Sub New(ByVal t As Integer)
_tNo = t
End Sub
Public Property TipNo( ) As Integer
Get
Return _tNo
End Get
Set(ByVal value As Integer)
_tNo = value
End Set
End Property
Public Property MoveFlg( ) As Boolean
Get
Return _mflg
End Get
Set(ByVal value As Boolean)
_mflg = value
End Set
End Property
End Class
Dim _tNo As Integer 'マップチップ番号
Dim _mflg As Boolean '移動可否フラグ
Public Sub New(ByVal t As Integer)
_tNo = t
End Sub
Public Property TipNo( ) As Integer
Get
Return _tNo
End Get
Set(ByVal value As Integer)
_tNo = value
End Set
End Property
Public Property MoveFlg( ) As Boolean
Get
Return _mflg
End Get
Set(ByVal value As Boolean)
_mflg = value
End Set
End Property
End Class
これでマップチップクラスができあがりました。
あとはキャラクタクラスになりますね。
移動可否情報を元に移動できるかどうか判断できるようマップクラスとマップチップクラスを作成しましたから、この情報を利用して処理をさせていけばよいわけです。
ただし、マップ情報はキャラクタクラスから見るとわかりません。
そこで、親であるGameクラスからキャラクタクラスにマップ情報を渡す作業を行ってあげます。
渡すタイミングはキー入力があったときです。
それ以外はマップとキャラクタは関連を持ちません。
プログラムとしては、以前作成したものとほとんど変わりません。
変わるところはキー入力時の処理だけになります。
Public Class CharaClass
Enum Direction
down = 0 '前向き
up = 1 '後ろ向き
left = 2 '左向き
right = 3 '右向き
End Enum
Const ImgWidth As Integer = 32 '画像横幅
Const ImgHeight As Integer = 32 '画像縦幅
Const MoveSpd As Integer = 64 '移動速度
Dim img As Bitmap = New Bitmap(My.Resources.anime6) 'スプライト画像
Dim imgRect(,) As Rectangle '画像矩形配列
Dim iNo As Integer '表示画像インデックス
Dim direct As Direction
Dim position As Point '画像表示座標ブロック
Dim locate As PointF '画像表示座標
Dim destination As PointF '目的座標
Dim velocity As PointF '移動ベクトル
Dim MoveFlg As Boolean
Public Sub New(ByVal px As Integer, ByVal py As Integer)
imgRect = New Rectangle(3, 3) { }
For y As Integer = 0 To imgRect.GetUpperBound(0)
For x As Integer = 0 To imgRect.GetUpperBound(1)
imgRect(y, x) = New Rectangle(x * ImgWidth, y * ImgHeight, ImgWidth, ImgHeight)
Next
Next
iNo = 0
direct = Direction.down '前向き
position = New Point(px, py) '初期位置
locate = New PointF(position.X * ImgWidth, position.Y * ImgHeight)
destination = locate
velocity = New PointF(0, 0)
End Sub
Public Sub Update(ByVal nowTime As Double, ByVal elapsedTime As Double)
iNo = CInt(Fix((nowTime * 2) Mod 4.0F))
If MoveFlg Then
locate.X += velocity.X * CSng(elapsedTime)
locate.Y += velocity.Y * CSng(elapsedTime)
Select Case direct
Case Direction.up
If locate.Y <= destination.Y Then
position.Y -= 1
locate.Y = position.Y * ImgHeight
MoveFlg = False
End If
Case Direction.down
If locate.Y >= destination.Y Then
position.Y += 1
locate.Y = position.Y * ImgHeight
MoveFlg = False
End If
Case Direction.left
If locate.X <= destination.X Then
position.X -= 1
locate.X = position.X * ImgWidth
MoveFlg = False
End If
Case Direction.right
If locate.X >= destination.X Then
position.X += 1
locate.X = position.X * ImgWidth
MoveFlg = False
End If
End Select
End If
End Sub
Public Sub Draw(ByVal g As Graphics)
g.DrawImage(img, locate.X, locate.Y, imgRect(direct, iNo), GraphicsUnit.Pixel)
End Sub
Public Sub KeyDown(ByVal k As Keys, ByVal _map As MapClass)
If MoveFlg = False Then
Select Case k
Case Keys.Up
If _map.MapData(position.Y - 1, position.X).MoveFlg Then
direct = Direction.up
velocity = New PointF(0, -MoveSpd)
MoveFlg = True
End If
Case Keys.Down
If _map.MapData(position.Y + 1, position.X).MoveFlg Then
direct = Direction.down
velocity = New PointF(0, MoveSpd)
MoveFlg = True
End If
Case Keys.Left
If _map.MapData(position.Y, position.X - 1).MoveFlg Then
direct = Direction.left
velocity = New PointF(-MoveSpd, 0)
MoveFlg = True
End If
Case Keys.Right
If _map.MapData(position.Y, position.X + 1).MoveFlg Then
direct = Direction.right
velocity = New PointF(MoveSpd, 0)
MoveFlg = True
End If
End Select
destination = New PointF(locate.X + velocity.X / 2, locate.Y + velocity.Y / 2)
If destination.X < 0 OrElse destination.X > 640 - ImgWidth _
OrElse destination.Y < 0 OrElse destination.Y > 480 - ImgHeight Then
velocity = New Point(0, 0)
MoveFlg = False
End If
End If
End Sub
End Class
Enum Direction
down = 0 '前向き
up = 1 '後ろ向き
left = 2 '左向き
right = 3 '右向き
End Enum
Const ImgWidth As Integer = 32 '画像横幅
Const ImgHeight As Integer = 32 '画像縦幅
Const MoveSpd As Integer = 64 '移動速度
Dim img As Bitmap = New Bitmap(My.Resources.anime6) 'スプライト画像
Dim imgRect(,) As Rectangle '画像矩形配列
Dim iNo As Integer '表示画像インデックス
Dim direct As Direction
Dim position As Point '画像表示座標ブロック
Dim locate As PointF '画像表示座標
Dim destination As PointF '目的座標
Dim velocity As PointF '移動ベクトル
Dim MoveFlg As Boolean
Public Sub New(ByVal px As Integer, ByVal py As Integer)
imgRect = New Rectangle(3, 3) { }
For y As Integer = 0 To imgRect.GetUpperBound(0)
For x As Integer = 0 To imgRect.GetUpperBound(1)
imgRect(y, x) = New Rectangle(x * ImgWidth, y * ImgHeight, ImgWidth, ImgHeight)
Next
Next
iNo = 0
direct = Direction.down '前向き
position = New Point(px, py) '初期位置
locate = New PointF(position.X * ImgWidth, position.Y * ImgHeight)
destination = locate
velocity = New PointF(0, 0)
End Sub
Public Sub Update(ByVal nowTime As Double, ByVal elapsedTime As Double)
iNo = CInt(Fix((nowTime * 2) Mod 4.0F))
If MoveFlg Then
locate.X += velocity.X * CSng(elapsedTime)
locate.Y += velocity.Y * CSng(elapsedTime)
Select Case direct
Case Direction.up
If locate.Y <= destination.Y Then
position.Y -= 1
locate.Y = position.Y * ImgHeight
MoveFlg = False
End If
Case Direction.down
If locate.Y >= destination.Y Then
position.Y += 1
locate.Y = position.Y * ImgHeight
MoveFlg = False
End If
Case Direction.left
If locate.X <= destination.X Then
position.X -= 1
locate.X = position.X * ImgWidth
MoveFlg = False
End If
Case Direction.right
If locate.X >= destination.X Then
position.X += 1
locate.X = position.X * ImgWidth
MoveFlg = False
End If
End Select
End If
End Sub
Public Sub Draw(ByVal g As Graphics)
g.DrawImage(img, locate.X, locate.Y, imgRect(direct, iNo), GraphicsUnit.Pixel)
End Sub
Public Sub KeyDown(ByVal k As Keys, ByVal _map As MapClass)
If MoveFlg = False Then
Select Case k
Case Keys.Up
If _map.MapData(position.Y - 1, position.X).MoveFlg Then
direct = Direction.up
velocity = New PointF(0, -MoveSpd)
MoveFlg = True
End If
Case Keys.Down
If _map.MapData(position.Y + 1, position.X).MoveFlg Then
direct = Direction.down
velocity = New PointF(0, MoveSpd)
MoveFlg = True
End If
Case Keys.Left
If _map.MapData(position.Y, position.X - 1).MoveFlg Then
direct = Direction.left
velocity = New PointF(-MoveSpd, 0)
MoveFlg = True
End If
Case Keys.Right
If _map.MapData(position.Y, position.X + 1).MoveFlg Then
direct = Direction.right
velocity = New PointF(MoveSpd, 0)
MoveFlg = True
End If
End Select
destination = New PointF(locate.X + velocity.X / 2, locate.Y + velocity.Y / 2)
If destination.X < 0 OrElse destination.X > 640 - ImgWidth _
OrElse destination.Y < 0 OrElse destination.Y > 480 - ImgHeight Then
velocity = New Point(0, 0)
MoveFlg = False
End If
End If
End Sub
End Class
これでマップ情報を元に移動できるマップチップなら移動し、移動できないマップチップなら移動しないように制御することができました。
ポイントはキー入力処理でマップ情報を受け渡しするということですね。
Gameクラスのキー入力処理でマップオブジェクトを渡してあげれば、キャラクタクラスでマップ情報を参照することができるようになります。
マップチップ その9
- ジャンル : コンピュータ
- スレッドテーマ : Visual Basic
マップチップ その8の続きです。
まず、マップクラスから作成していきます。
このマップクラスは以前作成したものを改造しています。
ただ、改造点が多いため作り直しましたが・・・。
このクラスでのポイントは外部ファイルからマップデータを読み込み、マップ配列を作成していくことです。
ただし、マップ配列にはマップチップオブジェクトを追加するようにしています。
マップチップオブジェクトにはマップチップ番号と移動可否情報が含まれています。
これをファイルから読み込みながらマップ配列に追加すればマップクラスはできあがりになります。
今回のマップチップファイルにはチップ番号と移動可否情報が一緒に保存されています。
ただ、それぞれのデータの開始位置には目印を記述していますから、これを利用することで特定のデータのみ処理してマップ配列に追加しています。
基本的な読み込み処理からマップへの追加処理の流れは、1行読み出してリストに追加し、追加したデータをカンマで分割しマップ配列に追加となっています。
ちょっと癖のあるやり方ですが、これしか思いつかなかったので。
またいいやり方があれば、作り直すかもしれませんが、とりあえずはこれでいきます。
次回はマップチップクラスを作成していきます。
これを作成しないことにはマップクラスは完成しませんからね。
まず、マップクラスから作成していきます。
このマップクラスは以前作成したものを改造しています。
ただ、改造点が多いため作り直しましたが・・・。
このクラスでのポイントは外部ファイルからマップデータを読み込み、マップ配列を作成していくことです。
ただし、マップ配列にはマップチップオブジェクトを追加するようにしています。
マップチップオブジェクトにはマップチップ番号と移動可否情報が含まれています。
これをファイルから読み込みながらマップ配列に追加すればマップクラスはできあがりになります。
Imports System.IO
Imports System.Text
Public Class MapClass
Const TipSize As Integer = 32
Public MapData(,) As MaptipClass
Dim _MapImg As Bitmap
Dim _MapRect( ) As Rectangle
Dim _xCnt, _yCnt As Integer 'マップチップの数(行数・列数)
Public Sub New( )
Dim sr As StreamReader = New StreamReader("data\mapfile.txt")
Dim buffer As String = "" '1行分のデータ
Dim dlist As List(Of String) = New List(Of String) '読み込んだデータのリスト
Dim dtip( ) As String '1マス分のチップ番号配列
Dim r As Integer '読み込み開始行
_xCnt = 19 'Xマス数
_yCnt = 14 'Yマス数
MapData = New MaptipClass(_yCnt, _xCnt) { }
_MapImg = New Bitmap(My.Resources.map) '画像の読み込み
buffer = sr.ReadLine
Do Until buffer Is Nothing
dlist.Add(buffer)
buffer = sr.ReadLine
Loop
r = dlist.IndexOf("::マップデータ") + 1 'ここからマップチップ配列を作成
For y As Integer = r To r + _yCnt
dtip = dlist(y).Split(",")
For x As Integer = 0 To _xCnt
MapData(y - r, x) = New MaptipClass(dtip(x))
Next
Next
r = dlist.IndexOf("::移動可否") + 1 'ここから移動可否配列を作成
For y As Integer = r To r + _yCnt
dtip = dlist(y).Split(",")
For x As Integer = 0 To _xCnt
MapData(y - r, x).MoveFlg = dtip(x)
Next
Next
Me.MakeRect( ) '画像矩形の作成メソッド呼び出し
End Sub
Sub MakeRect( )
Dim i As Integer = 0
_MapRect = New Rectangle(5) { }
For y As Integer = 0 To 1
For x As Integer = 0 To 2
_MapRect(i) = New Rectangle(x * TipSize, y * TipSize, TipSize, TipSize)
i += 1
Next
Next
End Sub
Public Sub Draw(ByVal g As Graphics)
For y As Integer = 0 To MapData.GetUpperBound(0)
For x As Integer = 0 To MapData.GetUpperBound(1)
g.DrawImage(_MapImg, x * TipSize, y * TipSize, _MapRect(MapData(y, x).TipNo), GraphicsUnit.Pixel)
Next
Next
End Sub
End Class
Imports System.Text
Public Class MapClass
Const TipSize As Integer = 32
Public MapData(,) As MaptipClass
Dim _MapImg As Bitmap
Dim _MapRect( ) As Rectangle
Dim _xCnt, _yCnt As Integer 'マップチップの数(行数・列数)
Public Sub New( )
Dim sr As StreamReader = New StreamReader("data\mapfile.txt")
Dim buffer As String = "" '1行分のデータ
Dim dlist As List(Of String) = New List(Of String) '読み込んだデータのリスト
Dim dtip( ) As String '1マス分のチップ番号配列
Dim r As Integer '読み込み開始行
_xCnt = 19 'Xマス数
_yCnt = 14 'Yマス数
MapData = New MaptipClass(_yCnt, _xCnt) { }
_MapImg = New Bitmap(My.Resources.map) '画像の読み込み
buffer = sr.ReadLine
Do Until buffer Is Nothing
dlist.Add(buffer)
buffer = sr.ReadLine
Loop
r = dlist.IndexOf("::マップデータ") + 1 'ここからマップチップ配列を作成
For y As Integer = r To r + _yCnt
dtip = dlist(y).Split(",")
For x As Integer = 0 To _xCnt
MapData(y - r, x) = New MaptipClass(dtip(x))
Next
Next
r = dlist.IndexOf("::移動可否") + 1 'ここから移動可否配列を作成
For y As Integer = r To r + _yCnt
dtip = dlist(y).Split(",")
For x As Integer = 0 To _xCnt
MapData(y - r, x).MoveFlg = dtip(x)
Next
Next
Me.MakeRect( ) '画像矩形の作成メソッド呼び出し
End Sub
Sub MakeRect( )
Dim i As Integer = 0
_MapRect = New Rectangle(5) { }
For y As Integer = 0 To 1
For x As Integer = 0 To 2
_MapRect(i) = New Rectangle(x * TipSize, y * TipSize, TipSize, TipSize)
i += 1
Next
Next
End Sub
Public Sub Draw(ByVal g As Graphics)
For y As Integer = 0 To MapData.GetUpperBound(0)
For x As Integer = 0 To MapData.GetUpperBound(1)
g.DrawImage(_MapImg, x * TipSize, y * TipSize, _MapRect(MapData(y, x).TipNo), GraphicsUnit.Pixel)
Next
Next
End Sub
End Class
今回のマップチップファイルにはチップ番号と移動可否情報が一緒に保存されています。
ただ、それぞれのデータの開始位置には目印を記述していますから、これを利用することで特定のデータのみ処理してマップ配列に追加しています。
基本的な読み込み処理からマップへの追加処理の流れは、1行読み出してリストに追加し、追加したデータをカンマで分割しマップ配列に追加となっています。
ちょっと癖のあるやり方ですが、これしか思いつかなかったので。
またいいやり方があれば、作り直すかもしれませんが、とりあえずはこれでいきます。
次回はマップチップクラスを作成していきます。
これを作成しないことにはマップクラスは完成しませんからね。






