タグ別アーカイブ: C#

3Dでのカメラ設定


デバイスのプロパティ Device.Transform.View に、Matrix インスタンスを指定することで設定可能。

// 左手座標の視点マトリクスを構築する
public static Matrix Matrix.LookAtLH(
    Vector3 cameraPosition, // カメラの位置。
    Vector3 cameraTarget, // カメラの見ている位置。
    Vector3 cameraUpVector // カメラの頭の方向(例: 正立は new Vector3(0f,1f,0f), 倒立は new Vector3(0f,-1f,0f)). 方向を指定する目的なので、ベクトルの大きさは問わない
)

例:

Device device;
 
// ..中略..
 
// 座標 (0,0,-10) から正立状態で 座標 (0,0,0) を見る
device.Transform.View = Matrix.LookAtLH(
    new Vector3(0f, 0f, -10.0f),
    new Vector3(0f,0f,0f),
    new Vector3(0f,1f,0f) );
    
);

実際に表示するには、さらに 3D から 2D への投影の設定を行う必要があります。
この設定を行うには Device.Transform.Projection プロパティに Matrix インスタンスを指定します。

// 左手座標のパースペクティブマトリクスを構築する
public Matrix Matrix.PerspectiveFovLH(
    float fieldOfViewY, // (カメラから見て) Y軸方向の視野。ラジアンで指定する。(1/4 π == 45度 くらいが適切)
    float aspectRatio, // 2Dに変換後の画面のアスペクト比(横幅 ÷ 縦幅) (例: 高さも幅も同じなら 1.0f, 汎用:(float)device.Viewport.Width / (float)device.Viewport.Height )
    float znearPlane, // (カメラから見た)可視範囲のうち、最も近い距離(1.0f)
    float zfarPlane // (カメラから見た)可視範囲のうち、最も遠い距離 (100.0f)
);

例:

Device device;
// …中略…
 
device.Transform.View = … // 略
 
// 上下角度45度で奥行き 1.0f 前方から 100.0f 前方までの範囲を表示する
device.Transform.Projection = Matrix.PerspectiveFovLH(
    (float) Math.PI / 4,
    (float) device.Viewport.Width / device.Viewport.Height,
    1.0f, 100.0f );

ちなみに、Matrix.PerspectiveForLH ではなくて Matrix.PerspectiveFovLH なので注意してください。for でなく fov です。
 
参考:
チュートリアル3 行列の使い方(MSDN Direct3D)
Matrix.LookAtLH メソッド(MSDN)
ビュー行列を設定する(MSDN)
Matrix.PerspectiveFovLH メソッド

UDP 通信を簡単に行うには


Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.SendTo(…);
socket.ReceiveFrom(…);

のように System.Net.Sockets.Socket を使う方法もありますが、System.Net.Sockets.UdpClient を使うと簡単に UDP 通信を行うことができます。

// 必要な宣言
using System.Net;
using System.Net.Sockets;

private void DoSend(){
// 送信元とするポート
int localPort = 1234;
 
UdpClient client = new UdpClient(localPort);
 
// UDP パケットの送信先
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(“192.168.2.1”), 5678);
// 送信する内容(バイト配列で指定)
byte[] msg = Encoding.ASCII.GetBytes(“Hello, world\n”);
 
// 送信する
client.Send(msg, msg.Length, remoteEP);
// // 同じ場所に送信し続ける場合は次のように接続と送信をわけてもよい
// client.Connect(remoteEP);
// client.Send(msg, msg.Length);
}

以下のようにすれば、受信ができます。

private void DoReceive(){
int localPort = 5678;
UdpClient client = new UdpClient(localPort);
 
// 送信元。任意のIPアドレス、任意のポートから許可
IPEndPoint remoteEP = IPEndPoint(IPAddress.Any, 0);
 
// 受信するまで待ち続ける
byte[] res = client.Receive(ref remoteEP);
 
// バイト配列から ASCII 文字列に変換して表示
System.Console.Write(
   “送信元:” + remoteEP + “\n” + // 実際に送信が行われた IPアドレス, ポートが格納されているので一緒に表示
   “受信内容:”+Encoding.ASCII.GetString(res)
  );
}

TCP 版の TcpClient もあります。
 
参考:
UdpClient クラス (System.Net.Sockets)
TcpClient クラス
Socket クラス(System.Net.Sockets)

enum 型の一覧を得る


列挙型のすべての要素を得るには、Enum.GetValues() や Enum.GetNames() を使います。

private enum UserType {
    Guest = 1,
    Member,
    VIP,
    Refused = 99
}
 
private void SomeMethod(){
    foreach(UserType type in Enum.GetValues(typeof(UserType))){
        System.Console.Write(type + ” = ” + ((int) type)+ “\n”);
    }
}

結果:

Guest = 1
Member = 2
VIP = 3
Refused = 99

C# で DirectX


.NET Framework で DirectX を利用するには、Microsoft DirectX SDK を利用するのが一般的です。
 
マネージコードの使用に関するヒント(MSDN)
Direct3D のチュートリアル(MSDN)
参考になりますが、とくにチュートリアル3以降、部分解説になっているので完全に動作させるにはSDK 付属のチュートリアルのソースの参照が必須です。
サンプルソースは

(SDK ルート)\Samples\Managed\Direct3D\Tutorials

にあります。

別オブジェクトからフォームインスタンスの参照を得るには?


.NET Framework 2.0 以降のみですが、System.Windows.Forms.Application クラスの静的プロパティ、 OpenForms により、開いているフォームインスタンスを参照することができます。
 

Form form = Application.OpenForms[0]; // 開いているフォームのうち一番古いものを得る

 

Form form = Application.OpenForms[“form1”]; // form1 という名前のフォームインスタンスを得る

 
参考:
Windowsフォームでフォームのコレクションを使用するには?
Application.OpenForms プロパティ(MSDN)
FormCollection クラス

C# で Java と同等のアクセス制限をかける


Java プログラマが C# を学ぶ際のメモその2。
 
– Java
public: どこからでもアクセス可
protected: 自クラス内と子孫クラス、または同一パッケージ内であればアクセス可(default 権限も兼用)。
default: 同一パッケージ内からのみアクセス可。アクセス修飾子を省略した場合のデフォルト。
private: 自クラス内からのみアクセス可。
 
– C#
public: どこからでもアクセス可(入れ子 enum,interface のデフォルト)。
protected internal: 同一アセンブリ(DLL ファイル, EXE ファイル等)内と子孫からアクセス可。
internal: 同一アセンブリ内からのみアクセス可(名前空間直下で宣言したコンテナのデフォルト)。
protected: 自コンテナ(クラス等)内と子孫からのみアクセス可。(Java と違い同一名前空間は不可)
private: 自コンテナのみからアクセス可(入れ子 class, struct のデフォルト)。
 
注意すべきは、protected の動作の違いと、default(Java) と internal(C#) の制限範囲の違いです。
Java では、パッケージレベルでの制限が可能ですが、言語で制限をかけただけだと外部ファイルからのパッケージへの侵入が可能です。
これを防ぐには JAR を作る時にシーリング機構を利用すれば、そのパッケージの利用者の侵入を制限することができます。
マニフェストの不正な書き換えを防ぐにはJARへの署名機能等を使えばよさそうです。
 
C# では、アセンブリ(プログラム, ライブラリ)単位でのアクセス制限が可能で、名前空間単位では制限できません。アクセス制限がソースファイル単位ではないことに注意してください。
参考:
C# プログラマーズリファレンス – アクセシビリティレベル
JARマニフェストのメイン属性
JavaHouse Brewers 19189 – Package Joining Attack(JDK1.2 での話)

C#.NET と MVC(PAC)


件名:PACパターンにおいて、Formクラスはコントロール層なのか?
自動生成の Form だと、MVC の V+C な動作をしていますね。
結論としては、ここの流れどおり、コントローラを別に作って、そっちをエントリポイントにするのがベターじゃないかなと思います。
 
2006-02-08 追記:
よく使われる Application.Run(Form) だと、せっかく Main() メソッドを分離してもイベントハンドラの段階で V+C な形になってしまうので、ApplicationContext インターフェイスを実装してこれを Application.Run(ApplicationContext) に渡してやると、コントローラとビューの分離がよりスマートにできる。
 
2007-04-10 追記:
ApplicationContext を利用した場合の実装例はこんな感じになります。

using System;
using System.Windows.Forms;
 
class Controller : ApplicationContext{
    // MVC の view レイヤ( Controller との接合部のみを IView として interface にしてもよい)
    private Form1 view;
 
    // コンストラクタ
    internal Controller(){
        view = new Form1();

// フォームが閉じられた時にアプリケーションを終了させるためのイベントハンドラを追加。
view.Dispose += new EventHandler( delegate (object sender, EventArgs e){
Dispose();
Application.Exit();
});
// フォームを表示
view.Show();
    }
}

あとはこれを Program.cs などエントリポイント( static void Main(string[]) 関数)の

Application.Run(new Form1);

などとなっている箇所を

Application.Run(new Controller());

のようにすれば、直接 Form を呼び出す実装ではなく ApplicationContext を介した実装になります。
 
参考:
.NET TIPS – VB.NETでアプリケーション起動時に実行されるフォームを変更するには?(@IT)
VS.NET でのエントリポイントの設定の仕方について書かれています。
Application.Runメソッド(ApplicationContext) (MSDN -> .NET Framework-> リファレンス -> クラスライブラリ -> System.Windows.Forms -> Application クラス -> メソッド -> Run メソッド)
リンク先のサンプルの動作には次の宣言が必要。また、MyForm1, MyForm2 というフォームクラスを用意する必要がある。

using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.ComponentModel;
using System.Text;

C# で Java の final と同等の制限をかける


Java プログラマが C# を学ぶ際のメモ。final については探しても見当たらなかったので書いておきます。
 
定数に対しては const 識別子, コンストラクタ値を設定する書き込み禁止フィールドについては readonly 識別子を使います。

class Foo {
    private const int NUM_MAX = 65535; // 定数値。コンストラクタでの遅延代入が不可。
    private readonly int _id; // 書き込み禁止値。コンストラクタで遅延代入が可能。
    
    public Foo(int id){
        _id = id;
    }
}

ただし、メソッド中で、遅延代入をする方法はなさそうです。

    public doSomething(){
        readonly int j = 1; // これはエラー。readonly はフィールドでのみ可能。
        const int N;
        N = 10; // これもエラー。const は宣言と同時に代入しなければならない。
    }

同様に、引数の final (引数の変数への再代入禁止)を C# で利用することはできません。

public void doSomeThing2(const int number); // const は引数には適用不可

 
クラスに対しては、sealed 識別子が同等の効果をもちます。

sealed class FinalClass{ /* … */ }

 
Java におけるメソッドの宣言に対しての final は、C# ではデフォルトの実装のため、ポリモーフィズムについては C# のほうが Java より制限的といえます。
 
final でない(オーバーライド可能な)メソッドを定義するには、親で virtual 識別子をつけて宣言し、かつ子で override 識別子で明示してオーバーライドします。
override 識別子をつけている場合、さらにその子クラスでも再帰的にオーバーライドが可能です。オーバーライド可能なメソッドに対して「オーバーライドした上で子には禁止する」という動作を実装する場合は、クラスと同様に sealed 識別子を利用します。

class Parent {
    public virtual void Greet(){ // オーバーライド可能
        Console.WriteLine(“Hello”);
    }
    public void StandUp(){ // オーバーライド禁止。オーバーライドしようとするとコンパイルエラー
        // …
    }
}
 
class Child : Parent {
    public override void Greet(){ // オーバーライド。明示しないとコンパイルエラー
        Console.WriteLine(“Hi!!”);
    }
}
class GrandChild : Child {
    public sealed override void Greet(){ // オーバーライド。ただし、このクラスの子にはオーバーライドを許さない。
    }
}

 
参考:
C# のキーワード(MSDN)
C# で Java の final の 1機能を使いたい(@IT Java Solution Forum)
J# は final の嵐