このページは、現在こちらのページへ移行しています。 この講座は Microsoft .NET Framework SDK で動作確認しています サンプルのプログラムは Microsoft C# 言語を用いています この講座は、C# 言語の知識とオブジェクト指向の理解を前提としています Microsoft .NET の概要については、「C#入門」を参照してください
並列的継承の問題点 C++の継承が、いかに柔軟なものかは前回で理解していただけたと思います ですが、継承によっては非常に難しい問題が発生します 継承が複雑になると、同じクラスを2度継承するという事態が発生します 基本クラス || 派生クラス1派生クラス2 || 派生クラス3 図を見てわかるように、派生クラス3が基本クラスを2度継承しています 派生クラス1と派生クラス2が、基本クラスを継承しているためです #include<iostream> using namespace std; class Base { public: char *name; }; class Derived1: public Base { public: int age; }; class Derived2 : public Base { public: char *sex; }; class Derived3 :
クラス名を伝える クラスのメンバとして、他のクラスのオブジェクトを保有したり また、メンバ関数型のクラスのオブジェクトを受け取る場合があります これが、相互で行われた場合難しい問題が発生します 一方のクラスがまだ定義されていないということになります といって、両方のクラスを同時に定義するのは無理な話です class A { void getB(B &); }; class B {... これを見ればわかるように、class A の定義の時点で B は定義されていません そこで、前方宣言(または前方参照)を用いてコンパイラにクラス名を教えます クラス名を伝えることで、コンパイラはそのクラスを認識できます ただし、クラスメンバの定義などはその時点で定義されていないので使えません class class-name; これを、クラス定義よりも前に記述することで 指定された class-name ク
関数のインライン展開 Cプログラマの多くは、1行程度で終了する簡易関数はマクロで実装したと思います C言語のマクロ関数は、短い関数で関数のオーバーヘッドを避ける手段の一つでした しかし、マクロ関数は仮引数の展開を正確に行うために括弧をつけます そこでC++で、マクロ関数のような処理を必要とする場合インライン関数が有効です (もちろん、Cに慣れ親しんでいるのならマクロでもかまわないが) インライン関数は、実際に呼び出すことはなく呼び出しごとにインラインで展開する関数です マクロとは異なり関数と同様の扱いで仮引数などを指定することが可能です これによって、関数の呼び出しや仮引数のオーバヘッドタイムを減少させることができます インライン関数の宣言は、関数の先頭に inline 指定子を指定します inline type function(); これで、短い関数の呼び出しにかかるオーバヘッドをなく
識別子の衝突 C言語を熟知している型であれば、ローカル変数名とグローバル変数名が同じだったとき 関数内で変数にアクセスすればどうなるか、すでにご存知だと思います 同様の現象がクラスのメンバ関数内とメンバ変数で発生します メンバ関数内のローカル変数名と、同クラスのメンバ変数名が同じだった時です 次のプログラムを実行した時のことを考えてください #include <iostream> using namespace std; class Kitty { public: char *str; void print(char *); }; void Kitty::print(char *str) { cout << str; } int main() { Kitty obj; obj.str = "Kitty on your lap"; obj.print("Di_Gi_Gharat"); ret
この講座は Intel 社の 80x86 互換プロセッサを想定します 80x86 アセンブラまたはその互換アセンブラ以外では正常に動作しません この講座のサンプルプログラムを実行した結果について、一切の責任は持てません この講座のサンプルソースは、Windows 98 SE のMS-DOSプロンプトで動作確認しています DEBUGを使ったアセンブラは、ソース上の数値は16進数と解釈されますが 他のアセンブラで、16進数を表現するには数字の後に H をつける必要があります
本書は C 言語の習得者が Windows 上で動作するグラフィカルなゲームアプリケーションを開発できるようになるまでを導く、ゲーム開発と Windows API のための学習書です。 複雑な C++ 言語は使わずに、C 言語だけで Windows 上で動作するウィンドウアプリケーションの開発方法をシンプルに、サンプルコードを交えながら解説します。 Windows 上で動作するグラフィカルなゲームプログラムを作成するには、Windows API (Windows が提供しているウィンドウなどを制御するための関数群)を理解しなければなりません。 本書では、ゲーム開発に必要な API や、応用可能と思われる API を中心にウィンドウアプリケーションの開発方法を解説するため、Windows プログラミング入門者がスマートにゲーム開発にまでたどり着くことができます。 通常の Windows AP
透視法射影 ここでは、射影変換を解説します これまでの頂点は2次元のものでしたが、これでようやく Z 座標を自由に使えるようになります 射影変換の目的は視体積の定義です どの程度の範囲で、どこまで見ることができるのかという問題を解決します これは、カメラのレンズを選択する作業に似ています 射影行列を選択するために、最初に glMatrixMode() で GL_PROJECTION を指定します そして、必要であれば単位行列をセットしてから、変換を行うと良いでしょう 射影には、代表して2つの方法が存在します そのひとつが透視法射影と呼ばれるもので 人間の感覚に極めて近い遠近法による描画を行います 透視法射影は、近くにあるものほど大きく、遠くにあるものほど小さく見せます つまり、視野が視点を頭としたピラミッド型のように構成されているのです 人間の視点で世界を見ているような、リアリティが求めら
入力イベントの処理 実用的な3次元グラフィックソフトウェアは、必然的に動的にならざるを得ません また、ユーザーの要求を受け、適切に処理できなければならないでしょう これを実現するためには、イベント処理を行う必要があります OpenGL はプラットフォーム固有の処理には関与しません そのため、イベントを処理するためにはシステム固有の API を呼び出す必要があります しかし、この場合は何らかのシステムに依存したコードになってしまうため この場では GLUT を駆使して、GLUT に準拠したコードを記述することにしましょう まず、基本的なポインティング デバイスの入力を処理するプログラムを実現します イベント処理は、ディスプレイ コールバック同様に、専用の関数にコールバック関数を登録します マウスイベントには glutMouseFunc() 関数が対応しています void glutMouseF
頂点配列を有効化するには、GL_VERTEX_ARRAY を glEnableClientState() に指定します なぜ、この定数が glEnable() 関数で有効化することができないかというと このような配列情報はサーバーではなく、クライアントに保存されるためです 次に、配列データを作成して保存する必要があります ここで言う「配列」はプログラミング言語の配列ではなく OpenGL における配列です 頂点配列を定義するには glVertexPointer() 関数を使います void glVertexPointer( GLint size , GLenum type , GLsizei stride , GLsizei count, const GLvoid *pointer ); size には、頂点データのサイズを指定します ここで言うサイズは、頂点データが保有する座標情報の数で
塗りつぶしアイコン 通常、ポリゴンの塗りつぶしは全体を固定して塗りつぶしますが 破線を描画したように、ビット配列をパターンとした点描処理で塗りつぶすことも可能です ビット配列は縦横 32 ビット、128 バイトの配列で構成されます やはり、ビットが 1 であればピクセルが描画され、0 であれば描画されません この縦横32ビットのアイコンを繰り返してポリゴンが塗りつぶされます ポリゴンの点描を有効化するには、GL_POLYGON_STIPPLE を有効化する必要があります パターン配列は glPolygonStipple() 関数で設定することができます void glPolygonStipple(const GLubyte *mask); mask には、点描パターンを表す128バイトの配列へのポインタを指定します #include <windows.h> #include <GL/gl.
点や線の大きさ GL_POINTS によって作られた頂点は、それぞれが点として描画されます しかし、デフォルトの点では限りなく小さいため、ほとんど見えないことでしょう デフォルトでは 1.0 が線の太さとして設定されています これは、点を 1 × 1 ピクセルの正方形として描画することを表しています 点の太さは glPointSize() 関数を使って設定することができます また、太さを取得したいのであれば glGet() に GL_POINT_SIZE を要求するとよいでしょう void glPointSize(GLfloat size); size には点の直径を指定します #include <windows.h> #include <stdio.h> #include <GL/gl.h> #include <GL/glut.h> int pointSize = 1; void dis
オブジェクトの状態 OpenGL は描画に関する様々な情報を状態変数として内部に保持しています つまり、OpenGL は様々なプロパティを持ち、これを変更する手段を提供しているのです 状態変数は、特定の関数を使って制御できるため、スマートに制御することができます OpenGL は驚くほど多くの状態変数を持っています 残念ながら、そのすべてをここで紹介し、意味を説明することは不可能です しかし、それらを制御する方法については、比較的簡単に説明することができるでしょう OpenGL では、状態変数を表す定数が定義されています 私たちは、この定数と値を組み合わせて状態変数を制御することができるのです 状態変数を得るには、次の関数のいずれかを使います void glGetBooleanv(GLenum pname , GLboolean * params); void glGetDoublev(G
glVertex() 関数を使って頂点を設定する場合 必ず glBegin() 関数の後、glEnd() 関数の前に glVertex() 関数を呼び出さなければなりません それ以外の位置で glVertex() 関数を呼び出しても、動作は保障されません 座標は、画面中央を (0 , 0) とするワールド座標系となっています これは、カメラのレンズから見える世界を想像するとわかりやすいでしょう また、何らかの頂点を原点にする座標系を、ワールド座標に対してモデル座標と呼びます 視点や座標変換については、これから少しずつ解説していきます デフォルトでは、カメラは原点に配置され、負の z 軸方向を指しています 2次元グラフィックスと異なり、どんなに大きなオブジェクトを描画しても カメラを引いて遠くから見れば小さくなることを忘れないで下さい 逆に、どんなに小さなものでも近くで見れば大きく見えます
OpenGL Utility Toolkit OpenGL はシステムに依存しないレンダリングサービスを提供しています しかし、ウィンドウを表示せずにグラフィックを描画することはできません その部分はどうしても、システムに依存したコードを書かなければならないことになります この問題は OpenGL Utility Toolkit、通称 GLUT を用いることで解決することもできます システムの能力を発揮させるためには GLUT は役不足ですが こうした解説の場で、システムに依存しないコードを書くためには十分です この講座では、ソースが特定のシステムに依存しないようにするために GLUT を使います GLUT は Mark Kilgard 氏が作成したウィンドウ・ツールキットです すでに多くの環境に移植されており、Web から無料で手に入れることができます これを使えば、ウィンドウの生成やイ
グラフィックス インターフェイス 多くの Windows プログラマは、高度なグラフィックス処理を実現するためのテクノロジとして DirectX という選択肢を保有していることでしょう DirectX は GDI では実現が難しい高速なグラフィックスや入出力処理を実現してくれます そのため、多くの Windows ゲームは DirectX を利用しています しかし、筆者のソフトウェア開発戦略において 「特定企業の利益誘導となりかねない製品技術は学ばないし教えない」という 基本方針を貫いているため DirectX には強い抵抗がありました DirectX は Microsoft Windows に強く依存した技術であり 再利用や将来性、移植性において疑問が残ります 筆者は、これに代わる技術を求めていました 方法のひとつとして考えたのが、独自のグラフィックス・インターフェイスの開発です 主に
線を描く 論理的には、全ての描画操作はピクセル操作につながるので 前回のピクセル操作ができれば、あらゆるグラフィックプログラムができますが 図の描画などの操作をSetPixel()で行うというのはあまりにも不合理です 当然、デバイスドライバレベルでの線の描画のほうが効率的ですし 複雑なグラフィック操作を一括して行うコードに置き換えたほうが保守性もあります 線を描画するには、まずMoveToEx()でカレントポジションを決定します 線などの一部の描画命令は、このカレントポジションの影響を受けます BOOL MoveToEx(HDC hdc , int X , int Y , LPPOINT lpPoint); hdcには、デバイスコンテキストのハンドルを XとYには、カレントポジションとなる座標を表すX座標とY座標を指定します lpPointは、以前設定されていたカレントポジションが格納され
背景の描画 デバイスコンテキストの属性を操作することで、背景色を指定できます 背景色は、ウィンドウの背景ではなく描画した文字などの背景です デフォルトで背景色は白ですが、これを変更することができます 意識しませんでしたが、実は文字などを描画する時に プログラムは背景色で塗りつぶしてから文字を描画していたのです 背景色を指定するにはSetBkColor()関数を呼び出します COLORREF SetBkColor(HDC hdc , COLORREF crColor); hdcには、デバイスコンテキストのハンドルを crColorには、背景色を表すCOLORREF型を渡します 戻り値は、以前設定されていた色を返します 関数が失敗するとCLR_INVALIDが返ります また、現在の背景色を得るGetBkColor()関数も存在します しかし、背景を塗りつぶす必要がなく 現在の背景を残したい場合
クライアントエリアのサイズを得る より柔軟な文字列表現をしたい場合、TextOut()関数では不十分な面があります この関数は、たとえクライアントエリアの幅が文字列より小さくなっても 文字列は改行されることなく、クライアントエリアから途切れてしまいます //ウィンドウの外に描画されることはありません そこで、クライアントエリアのサイズを知る必要があります 現在のクライアントエリアのサイズを得るには GetClientRect() 関数を使います BOOL GetClientRect(HWND hWnd , LPRECT lpRect); hWnd は、ウィンドウのハンドルを指定し lpRect は、サイズを格納する RECT 構造体へのポインタです 左上の座標 top と left は必ず0になります これと、フォントメトリックスを計算し ウィンドウサイズによって動的な改行を表現することが
リリース、障害情報などのサービスのお知らせ
最新の人気エントリーの配信
処理を実行中です
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く