goo blog サービス終了のお知らせ 

日々のDraft

回答原案集

擬似乱数

2006-12-05 14:28:38 | プログラム
ロマサガ3の記事を読んでいた。どこの記事だか忘れたが。

その中で「"レアモンスターが出現しない"といった事態は「乱数の偏り」を開発側が予測していなかったからだろう」と言った推測を見かけた。

一般にコンピュータで生成する乱数は擬似乱数というもので
http://www001.upp.so-net.ne.jp/isaku/rand.html

SFCの場合は知らないが、

VB6以前では
Randomize [種番号(省略時は起動時からの時間。単位はミリ秒)]という構文で種を指定して
Rnd関数を実行することで乱数を得る。

ここまで読んで。

自分は
http://www.atmarkit.co.jp/fdotnet/dotnettips/035random/random.html

System.Randomクラスのインスタンスをnewで生成していたが、この関数の質はどうなのだろう、とふと疑問に思ってしまった。

先ほどのページで
「メルセンヌ・ツイスタ法」というものがあることを知ったので
.NETで使えるものはないかと調べたら以下のページにあたった。

メルセンヌツイスタ64bit版.NET対応DLL
http://www.vector.co.jp/soft/winnt/prog/se411196.html

これは俺が今使っている32bit版Windows XPでも使えるのだろうか?(汗





D3D.TextureLoader.FromFileとD3D.Sprite.Draw2D

2006-12-04 18:16:42 | プログラム
タイトルのD3DはMicrosoft.DirectX.Direct3D名前空間です。文字数が50文字なので入らなくて(汗

Public Class DirectGraphicsManager

Implements System.IDisposable

Private presentparameters As New Microsoft.DirectX.Direct3D.PresentParameters

Private Direct3DDevice As Microsoft.DirectX.Direct3D.Device

Private VertexBuffer As Microsoft.DirectX.Direct3D.VertexBuffer
Private stm As Microsoft.DirectX.GraphicsStream
Private disposed As Boolean
Private MyForm As System.Windows.Forms.Form

Private SpriteTexture As Microsoft.DirectX.Direct3D.Texture
Private Sprite As Microsoft.DirectX.Direct3D.Sprite


'// For Debug
Private verts(4) As Microsoft.DirectX.Direct3D.CustomVertex.PositionTextured
Private vertsList As New System.Collections.Generic.List(Of Microsoft.DirectX.Direct3D.CustomVertex.PositionTextured)

Sub New(ByVal parameterForm As System.Windows.Forms.Form)

MyForm = parameterForm
CreateDevice()

End Sub

Sub New()

MyForm = New System.Windows.Forms.Form
MyForm.ClientSize = New System.Drawing.Size(800, 600)

CreateDevice()

Sprite = New Microsoft.DirectX.Direct3D.Sprite(Direct3DDevice)


End Sub

Function CreateDevice() As Boolean

presentparameters.Windowed = True
presentparameters.EnableAutoDepthStencil = True
presentparameters.AutoDepthStencilFormat = Microsoft.DirectX.Direct3D.DepthFormat.D16
presentparameters.SwapEffect = Microsoft.DirectX.Direct3D.SwapEffect.Discard
presentparameters.PresentationInterval = Microsoft.DirectX.Direct3D.PresentInterval.Immediate
presentparameters.BackBufferWidth = 0
presentparameters.BackBufferHeight = 0



presentparameters.DeviceWindowHandle = MyForm.Handle
presentparameters.DeviceWindow = MyForm

MyForm.Show()


'デバイスを作成
'Try

Direct3DDevice = New Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, MyForm, Microsoft.DirectX.Direct3D.CreateFlags.SoftwareVertexProcessing, presentparameters)
System.Console.WriteLine("デバイス生成に成功しました")
VertexBuffer = New Microsoft.DirectX.Direct3D.VertexBuffer(GetType(Microsoft.DirectX.Direct3D.CustomVertex.PositionTextured), 600, Direct3DDevice, 0, Microsoft.DirectX.Direct3D.CustomVertex.PositionTextured.Format, Microsoft.DirectX.Direct3D.Pool.Managed)

''Catch ex As Microsoft.DirectX.Direct3D.DeviceLostException 'デバイスが消失しましたが、現時点ではリセットできません。したがって、レンダリングできません。


'Catch ex As Microsoft.DirectX.Direct3D.DeviceNotResetException 'デバイスが消失しましたが、現時点でリセットできます。


'Catch ex As Microsoft.DirectX.Direct3D.DriverInternalErrorException '内部ドライバ エラー。このエラーを受け取った場合、一般に、アプリケーションはシャットダウンする必要があります。


'Catch ex As Microsoft.DirectX.Direct3D.DriverInvalidCallException 'ドライバは、現在のメソッドの呼び出しが無効であることを報告します。
'Catch ex As Microsoft.DirectX.Direct3D.InvalidCallException 'メソッドの呼び出しが無効です。
'Catch ex As Microsoft.DirectX.Direct3D.InvalidDeviceException '要求されたデバイスの種類が無効です。

'Finally


'End Try

SpriteTexture = Microsoft.DirectX.Direct3D.TextureLoader.FromFile(Direct3DDevice, "C:hoge.png")

Do

Try


Direct3DDevice.Clear(Microsoft.DirectX.Direct3D.ClearFlags.Target Or Microsoft.DirectX.Direct3D.ClearFlags.ZBuffer, System.Drawing.Color.DarkBlue, 1.0F, 0)
Direct3DDevice.Transform.View = Microsoft.DirectX.Matrix.LookAtLH(New Microsoft.DirectX.Vector3(0.0F, 0.0F, -5.0F), New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), New Microsoft.DirectX.Vector3(0.0F, 1.0F, 0.0F))
Direct3DDevice.Transform.Projection = Microsoft.DirectX.Matrix.PerspectiveFovLH(System.Math.PI / 4.0, Single.Parse(MyForm.ClientSize.Width.ToString(System.Globalization.CultureInfo.InvariantCulture), System.Globalization.CultureInfo.InvariantCulture) / Single.Parse(MyForm.ClientSize.Height.ToString(System.Globalization.CultureInfo.InvariantCulture), System.Globalization.CultureInfo.InvariantCulture), 3.0F, 15.0F)
Direct3DDevice.RenderState.CullMode = Microsoft.DirectX.Direct3D.Cull.None
Direct3DDevice.RenderState.Lighting = True

' stm = VertexBuffer.Lock(0, 0, 0)

'頂点データをバッファに書き込み
' stm.Write(vertsList.ToArray)

'バッファのロックを解除

' VertexBuffer.Unlock()

System.Windows.Forms.Application.DoEvents()


'System.Diagnostics.Debugger.Break()

Direct3DDevice.BeginScene()

Direct3DDevice.SetStreamSource(0, VertexBuffer, 0)
Direct3DDevice.VertexFormat = Microsoft.DirectX.Direct3D.CustomVertex.TransformedColored.Format
Direct3DDevice.DrawPrimitives(Microsoft.DirectX.Direct3D.PrimitiveType.TriangleList, 0, CInt(vertsList.Count / 3))
System.Windows.Forms.Application.DoEvents()


'//スプライト描画
Sprite.Begin(Microsoft.DirectX.Direct3D.SpriteFlags.None)

Sprite.Draw2D(SpriteTexture, New System.Drawing.Rectangle(32, 64, 32, 64), New System.Drawing.SizeF(32, 64), New System.Drawing.PointF(0, 0), 0, New System.Drawing.PointF(20, 20), System.Drawing.Color.White.ToArgb())

Sprite.End()


Direct3DDevice.EndScene()

System.Windows.Forms.Application.DoEvents()

vertsList.Clear()

'// For Retail

System.Windows.Forms.Application.DoEvents()
System.Windows.Forms.Application.DoEvents()
System.Windows.Forms.Application.DoEvents()
System.Windows.Forms.Application.DoEvents()
System.Windows.Forms.Application.DoEvents()

Direct3DDevice.Present()


Catch ex As Microsoft.DirectX.Direct3D.DeviceLostException 'デバイスが消失しましたが、現時点ではリセットできません。したがって、レンダリングできません。
'
System.Threading.Thread.Sleep(10)
Direct3DDevice.Reset(presentparameters)

Catch ex As Microsoft.DirectX.Direct3D.DeviceNotResetException 'デバイスが消失しましたが、現時点でリセットできます。
'
Direct3DDevice.Reset(presentparameters)
'
End Try

Loop
Return True

End Function

'// Microsoftのサイトのどこかからまるっとコピーしたもの

Public Overloads Sub Dispose() Implements System.IDisposable.Dispose
Me.Dispose(True)
' This object will be cleaned up by the Dispose method.
' Therefore, you should call GC.SupressFinalize to
' take this object off the finalization queue
' and prevent finalization code for this object
' from executing a second time.
System.GC.SuppressFinalize(Me)
End Sub

' Dispose(bool disposing) executes in two distinct scenarios.
' If disposing equals true, the method has been called directly
' or indirectly by a user's code. Managed and unmanaged resources
' can be disposed.
' If disposing equals false, the method has been called by the
' runtime from inside the finalizer and you should not reference
' other objects. Only unmanaged resources can be disposed.
Private Overloads Sub Dispose(ByVal disposing As Boolean)
' Check to see if Dispose has already been called.
If Not Me.disposed Then
' If disposing equals true, dispose all managed
' and unmanaged resources.
If disposing Then
' Dispose managed resources.

Direct3DDevice.Dispose()
MyForm.Dispose()
VertexBuffer.Dispose()


End If

' Call the appropriate methods to clean up
' unmanaged resources here.
' If disposing is false,
' only the following code is executed.

End If

disposed = True

End Sub

End Class

なんて打っていたわけなんだが。

Microsoft.DirectX.Direct3D.TextureLoader.FromFile
で読み込んでいるC:hoge.pngってGIMPやPaint.NETなどで128px * 192px(どこぞで配布していたRPGツクール用キャラ画像データ。32px * 48pxの物が4*4並んだ画像)って認識されているんですが

Sprite.Draw2DでNew System.Drawing.Rectangle(32, 48, 32, 48)だとなぜかうまく行かず、手当たり次第に打ってみたNew System.Drawing.Rectangle(32, 64, 32, 64)だとうまくいくんだよなー。

激しく納得がいかなくて悩み中。

バグ修正

2006-11-30 08:03:22 | プログラム
バグの原因発覚。

※注意:Private vertsList As New System.Collections.Generic.List(Of Microsoft.DirectX.Direct3D.CustomVertex.TransformedColored)です。
配列の書式、なんか苦手なのでわざわざリストを使ってますorz

【誤】
Direct3DDevice.DrawPrimitives(Microsoft.DirectX.Direct3D.PrimitiveType.TriangleList, 0, 95)
【正】 Direct3DDevice.DrawPrimitives(Microsoft.DirectX.Direct3D.PrimitiveType.TriangleList, 0, CInt(vertsList.Count / 3))

1.一個の正方形に対してMicrosoft.DirectX.Direct3D.PrimitiveType.TriangleListを2つ、合計6頂点使っている。

2.ただし、何もないマスの頂点情報は記憶しない

3.なおvertsListは何かが存在するマスが持つ頂点の集合である。

4.デフォルトでは91マスであり(あれ?14 * 7 = 98だぞ、今計算すると(滝汗)、確か元々は利用していたPrimitiveTypeが異なっていて、これだけあれば十分かと思って数値を直書きしたことを忘れてました。

よって、48マス * 2 = 96 > 95となる

そっか、何も消さないで居ると24番目(48個目)で描写されなくなる理由はコレだったのかー?
どーりでキャラクターベースの正しいデータと画面上の表示状態が一致しないと思った。

多分正常動作・・・しているはず。

後は音声処理と性能改善とエラー処理

#・・・・あれ?TaoとかSDLを使う前に力尽きた?(汗

※Apple Human Interface GuideLineだとそういうものはある程度機能を組み上げてからやるんじゃなくて組みながら観察しろ、とかあったが(汗


ByRef

2006-11-29 22:02:49 | プログラム
FxCopに指摘されていた、長い間ByRefになっていた箇所を修正。

Class A

Sub New()
End Sub

Function hoge(ByRef parameterStatusManager As StatusManager) As Boolean

IF Case1 Then

parameterStatusManager.CurrentStatus = P

ElseIF Case2 Then


ElseIF Case3 Then




End IF

End Sub

End Class

Class B

Private ObjectA As New A

Sub New()
End Sub

Sub fuga()

ObjectA.hoge()

End Sub

End Class

Class StatusManager

Private CurrentApplicationStatus

Property CurrentStatus
Set(EnumStatus As EnumApplicationStatus)

CurrentApplicationStatus = EnumStatus

End Set

Get

Return Me.CurrentApplicationStatus

End Get

End Property

End Class

Module MainModule

Sub Main()

Dim ObjectB As New B

ObjectB.fuga()

End Sub

End Module

みたいになっていた。

ByRefにしないためには、ObjectAを呼び出しているObjectB側のメソッドで値を代入してやるように変えればいいか。そうすると場合分けされているClassAのメンバ関数hoge()の戻り値がEnumApplicationStatusクラスであればいいから・・・・
んー返り値Booleanか・・・・攻め込んだら返り血を浴びるような変更が沢山出そうだな・・・・

と思ったら、Case2もCase3もCase4も・・・Returnしていないではないか(汗
僕は基本的に成功・失敗を後で取得できるような関数に全てしておいた方が良いと思っているからサブルーチンではなく、殆ど返り値はBooleanにしている。
そのため、処理そのものに関係ないものでも無意識にBooleanにしていたが、
それを利用したために好転した・・・・気がする。

#ああ自分でも何言っているんだかわからん。

メモ

2006-11-24 08:41:05 | プログラム
修正点:
1.何故か配列表記になっていたところを修正
2.データ上ある程度のケースで動作していることを確認

バグ・問題点
1.画像処理が追いついてないので現在の状況がわかりにくい。デバッグ用の確認ルーチンを準備して対処したとは言え。ボトルネックになっている場所を探して修正すべき
2.消えないときがある
3.何故かAugumentException(添字や引数に関するエラー)が出ることがある

メモ

2006-11-23 22:37:48 | プログラム
異なる二つのSystem.Randomを連続で生成しようとすると
処理自体が早すぎてシード値System.DateTime.Now.Millisecondが一致してしまい、
乱数とは言い難い状況になっていたので
悔しいけどSystem.Random型変数を単独で持たず、引数として受け取るようにした。
==========================================
テスト効率Upのためテストデータ自動作成ツールを作りテストすることにした。まだ作ってないけど。

ぼやき2

2006-11-22 19:40:12 | プログラム
1.とりあえず落ちてくるようになった。その間隔が早すぎて点滅にしか見えなかったので時間調整。

2.キーボードやコントローラのポーリングで受け取ったと見なすタイミングってどれくらいが一般的なんだ?

3. 2を調べた上で最適な管理方法を考え直す

4.どこかで行っているはずだが、効いていないので
フィールド内に収まるかどうかの判定。(下に行けない時だけ、GeneralStatusManagerExのステータスが変化するようにする)
→怪しいところ発見。直してないけど

5.あらゆるところで引数になってしまっている余計なオブジェクトを他の所にソフトウェア設計的に合理的な説明付きで移管できたらいいけど・・何か望み薄そうな。

6.前回いい加減に書いたルーチンの見直し

7.ある程度頑張ったら音声系(Direct Audio)を実装してみる

8.ドキュメント整備

う"っ・・・・

2006-11-22 17:30:50 | プログラム
しまった・・・・
List(Of T)を全部Nothingにする方法を考えてなかった!
っていうかエラーが出てから気づいた。

MSDN見ててClearが使えることに気づいた。これで良し。動かないけど(汗)

#ループが多いのでIEnumerateくらいは容易に使えるように思考を柔らかくしたいと思いつつも、中々やらない


3Dと行列

2006-11-21 20:36:24 | プログラム
http://www012.upp.so-net.ne.jp/flab/3d/

やったー頂点が表示されなかった理由判明!

presentParameters.Windowed = True
presentParameters.EnableAutoDepthStencil = True
presentParameters.AutoDepthStencilFormat = Microsoft.DirectX.Direct3D.DepthFormat.D16

presentParameters.SwapEffect = Microsoft.DirectX.Direct3D.SwapEffect.Discard
presentParameters.PresentationInterval = Microsoft.DirectX.Direct3D.PresentInterval.Immediate
presentParameters.BackBufferWidth = 0
presentParameters.BackBufferHeight = 0

しているので

Do


Try

Direct3DDevice.Clear(Microsoft.DirectX.Direct3D.ClearFlags.Target Or Microsoft.DirectX.Direct3D.ClearFlags.ZBuffer, System.Drawing.Color.DarkBlue, 1.0F, 0)
Direct3DDevice.Transform.View = Microsoft.DirectX.Matrix.LookAtLH(New Microsoft.DirectX.Vector3(0.0F, 0.0F, -5.0F), New Microsoft.DirectX.Vector3(0.0F, 0.0F, 0.0F), New Microsoft.DirectX.Vector3(0.0F, 1.0F, 0.0F))
Direct3DDevice.Transform.Projection = Microsoft.DirectX.Matrix.PerspectiveFovLH(System.Math.PI / 4.0, Single.Parse(MyForm.ClientSize.Width.ToString) / Single.Parse(MyForm.ClientSize.Height.ToString), 3.0F, 15.0F)
Direct3DDevice.RenderState.Lighting = True

DrawGround()

'System.Diagnostics.Debugger.Break()
Direct3DDevice.BeginScene()

Catch ex As System.Exception

(中略)


End Try

Loop

一回一回ZBufferをクリアして、カメラとライトの設定をするようにしてあげたら上手く行った。

参照

2006-11-15 22:07:31 | プログラム
VB.NETで例のものを書いている。
できるだけ汎用性や互換性を保つことを念頭に置いている

ただ、余計なトラブルが増えることを懸念して

喩えコードがかなり助長になろうが
後で判別しやすいように
名前空間の省略はできるだけしないようにしている。
ソース中に現れないものを除けば(これらはVisual Studio Express Editionでソリューションの「プロパティ」-「参照」から確認できる。SharpDevelop 1.xをインストールした当初は、何故かCInt関数とかが使えない!とか思って驚いた覚えがあるような。もちろんその当時はVisual Studio Express Editionは無かった)
Importsを全く使ってない

できるだけデフォルトで読み込まれるものを消しておく。問題はなくても。

現在取り除けていないのは

System
System.Collections.Generics

の二つ。

Systemは
System.IDisposableと
System.Exceptionが主な原因

20個の修正が必要

System.Collections.Genericsは
Dim hoge As List(Of fuga)って書いてきたので22個の修正が必要

置換でいけるか?

使っているライブラリは以下の四つ。将来的にMicrosoft.DirectX.DirectDrawを使うであろうと見られる。DirectGraphicsじゃないのは、俺が3Dを理解できなかったから。

Microsoft.DirectX
Microsoft.DirectX.DirectInput
System
System.Windows.Forms

SystemやSystem.Windows.FormsはMono Project等で実装されているとは自分は思うが、DirectXのライブラリを他の環境に持って行って動くか自信がない。
(より互換性重視にするため IsNothing(foo)関数を使っていたのをfoo Is Nothingと直し、Microsoft.VisualBasicを削除)

様々なところでSDLってのがあると聞いていたので
http://tokyo.cool.ne.jp/sdl/index0.html
調べようとする

・・・・が、SDLは・・・「Visual C++ 5,6,7」?ってことは・・・良く理解してないけど.NETからは使えないのかなぁと
http://tokyo.cool.ne.jp/sdl/index0.html

なんとなく「SDL .NET」で「SDL.NETっぽい名前ないかなぁ」とか思いながらGoogle検索してみたら

SDL.NET
http://cs-sdl.sourceforge.net/index.php/Main_Page

あった。ま、確認してみます。