過去ログ 1
過去ログは下にいくほど新しい記事となっております。
※注意:このサイトにあるプログラムのソースコードや、その他の情報はすべて無保証です。やばいと思ったら実行しないでください。コンパイル、実行などによって生じた損害に対する責任は負いませんので、ご了承ください。
ページスタイル変更
12-4-2009
えー 長い間放置していたら、とんでもないことになっておりまして。トップページに誰もこないわけであります。
誰もサイトを訪れないというわけではなく、FreeCivのページのみがアクセス数を稼いでいる状態でありまして。
これではLinuxサイトではなく、FreeCivサイトになってしまっている状態でしたので、まあ、ちょっとLinuxサイトに戻そうか、ということでレイアウト変更しました。今頃になって旧スタイルのレイアウトずれを発見しましたし。
トップページにこのような落書きができるようになりました。で、落書きでアクセス数を稼ごうという戦略です。
ネタはいくらか…あると思います。
↓これ、とか。。。
でも、次回更新タイトル名が「カーネルパニック」、「起動しないX Window」とかになるとあまりにも不吉なのでこれはまた今度のお楽しみにしておきます。
初回のトピックは何にしようか。
「Linuxインストール」とかいいんじゃない?と思ったら過去に書いた記事があるし、ここは適当にスクリーンショットを貼ってごまかすとしよう。初回だし。
Extreme Tux Racer
(いまいちスピード感が出ていないのとタイムが悪いのはなんでだろう。)
Tuxが雪(氷)の上を滑るゲームです。勢いをつけて空を飛んだり結構フリーダムに動ける楽しいゲームですよ。
Windows版もあるみたいですね。
短時間で終わるので、ちょっとした時間でも楽しめます。
Linuxのゲームは地味だと思われがちですが、そんなことはありません。Tux Racerのようにフル3Dの楽しいゲームもあります。ただ、やる人というかOSの使用者が少ないため、ゲームを作る人があまりいないので、目立たないだけです。まあ、DirectXは動かないけど・・・。(OpenGLは動くよ!)
チェス
一気に地味になった。
やってみたけど、最近駒の動かし方を覚えた程度なので、勝っているのか、負けているのか分からない。
FreeCiv
FreeCiv序盤戦。暇な人はどーぞ。→基本戦略
※コメント、トラックバックはできません。(ブログじゃないから)
ちょっとはマシになったかな
13-4-2009
何のことかって、そりゃあ、ゲーム画像の話です。(Extreme Tux Racer)
スクリーンショットをとるときにどうしてもジョイスティックから手を離すので、あまりおもしろい画像にならないけど、「ペンギンが飛んでいる!」姿はなかなか格好がいいでしょう?
(落下するときは痛くないのかな?)
昨日の記事の訂正
FreeCivのページしかアクセスされていないっての、あれ間違い。
アクセス解析見たら、GCCのページがなぜか結構アクセスされている。
C言語プログラムのサイトは山ほどあるけど、ここのサイトのはどんな内容なの?という人は、これを見れば一発です。これがすべて理解できたら、このサイトには用はないでしょう→ポインタ60例。
そろそろg++のコーナーでも作ろうか。。。
昔話
そういえば昔、GCCの延長企画でGTK+のコーナーがあったんだけど、あれはどこにいったのだろう?
たしか、意味不明な仮面のアプレットを作った頃にはまだあったような・・・。
まあ、ああいうGUIアプリケーションを作成したいのなら、JAVAを使った方が楽だよ。NetBeansのIDEもあるし。
どうしても
どうしてもGTK+を使いたい、GTK+に興味がある。という人は、ここでも参考にしてみて。(メンテナンスがまったくかかっていないので、記事が古いです。内容に誤りがあるかも。また、各関数に関する説明があまり詳しくないので、開発者用ヘルププログラムやwebのリソースが必須です。)
※コメント、トラックバックはできません。(ブログじゃないから)
落下!!
14-4-2009
g++
C++の書き方ですね。
C++はC言語の拡張ですので、C言語でできることはC++でできます。
↓もC++としてコンパイルすれば、できます。
#include <stdio.h> int main(){ printf("Hello World"); return 0; }
C++で大きく変わったのはclassが取り入れられて、オブジェクト指向言語になったことです。
classとは
拡張(継承)機能をもつ、変数と関数の集まりです。
一つのクラスの中で、処理が完結するようになっていれば(グローバル変数の参照など、外部に依存した作りとなっていなければ)、クラスごと別のプログラムに流用できます。
一つの処理を明確にブロック化した様なものです。
どうやってclassを作るのか
作り方は簡単です。構造体を作るのと同じようにします。
class myclass{ public: int a; int func(int value){ return value*value; } };
こんな感じです。publicとなっているのは、クラス外部からのアクセスを許可するというものです。上の例では、変数aの読み書きとメソッド(クラス内の関数)funcの呼び出しができます。
外部からアクセスされたくない場合は、privateを指定します。
class myclass{ private: int a; int func(int value){ return value*value; } };
ただ、この例だと、myclassのメンバには誰もアクセスできなくなります。
funcのみ、外部からアクセスできるようにしましょう。↓の例ではfuncは外部からアクセス可能、aは外部からアクセス不可能(クラス内のメソッドからはアクセス可能)となります。
class myclass{ private: int a; public: int func(int value){ a = value; return value*value; } };
クラスのメンバにアクセスするには
構造体と同じようにします。こんな感じ。
#include <stdio.h> class myclass{ private: int a; public: int func(int value){ a = value; return value*value; } }; int main(){ myclass c; // クラスの実体(インスタンス/オブジェクト)の作成 printf("%d",c.func(2)); return 0; }
メソッドの呼び出しというのが、C言語になくて新鮮な感じですね。
コンパイルする時には
g++を使います。
$ g++ test.cpp
みたいな感じです。拡張子は「c plus plus」からcppです。
-- 次回に続く --
※コメント、トラックバックはできません。(ブログじゃないから)
G言語が出てきたらG++言語も出てくるんだろうな縲鰀
15-4-2009
昨日の記事を見ながら↑のようなことを考えていました。
g++はC++のコンパイラなので、新しい言語の話ではないです。まあ、現在D言語までできているので、G++の登場まで、最短でE、F、G、G++と4世代、C言語のような運命を辿るとしたら、D++、D#、E、E++、E#、F、F++、F#、G、G++と10世代先になってしまい、まだまだ未来の話であります。
今日のg++
C++の書き方です。
昨日、クラスの作成方法とそのオブジェクトの作成方法、使い方をやりました。
クラスをヘルプや辞書などで調べると単純に「雛形」とだけ書いてあることもあり、まあ、プログラミング初学者の方が「???」となり、実体がよくつかめないなあ、と、なるわけです。クラスは実体じゃないから、実体がつかめないのはあたりまえ・・・という変な冗談はおいておいて、要はクラスの作成時点では宣言・定義をしているだけなのです。
昨日の例をそのまま使うと、
class myclass{ public: int a; int func(int value){ return value*value; } };
このクラスの定義では、
- myclassには以下の変数・メソッドが含まれている。
- 以下の変数・メソッドは外部からのアクセスが可能である。
- int型の変数a。
- int型返り値のメソッドfunc。
と、myclassのメンバに何が含まれるかを取り決めています。
実際に使う場合はmyclass型の変数(これをオブジェクトまたはインスタンスといいます。テストによく出るので要注意!→基本情報を受ける方)を作成し、実体とします。メンバ変数、メソッドには原則この実体からアクセスすることになります。(staticなメソッドなど例外はあります)。
文章にすると難しそうですが、C言語で構造体が使える方は、そのまま構造体→クラスと考えればそんなに悩むことはないと思います。
#include <stdio.h> typedef struct{ int a; } mystr; int main(){ mystr c; c.a = 10; printf("%d",c.a); return 0; }
#include <stdio.h> class myclass{ public: int a; }; int main(){ myclass c; c.a = 10; printf("%d",c.a); return 0; }
ちなみにC++ではtypedefなしで、次のような書き方が許可されるようになりました。
#include <stdio.h> struct mystr{ int a; }; int main(){ mystr c; c.a = 10; printf("%d",c.a); return 0; }
newとdelete
いよいよニュータイプになる時が来ました。ニュータイプ?いやただnewを使うだけですよ。
さて、下の例を見てください。
#include <stdio.h> class myclass{ private: int a; public: int func(int value){ a = value; return value*value; } }; int main(){ myclass *c; // 都合により以下省略 }
cはmyclassのポインタです。ポインタは実体じゃないのでそのまま使うことができません。アクセス違反になってしまいます(この辺はC言語と同じです)。
ポインタを使う場合は、安全な領域を確保してから使用しなければなりませんので、1)別のポインタではない実体にアドレスを合わせてから使用する、2)安全な領域を確保する、のいずれかの方法を採らなければなりません。
1の方法はそのまま、
// 前略 int main(){ myclass *c; myclass x; c = &x; // 都合により以下省略 }
とかやればいいだけなので、置いておきます。
2の場合、C言語ではmallocやcallocでしたが、C++ではそれらの代わりにnewを使います。
// 前略 int main(){ myclass *c; c = new myclass(); // 都合により以下省略 }
みたいな感じです。下のようにもう少し簡略化した書き方をすることもあります。
// 前略 int main(){ myclass *c = new myclass(); // 都合により以下省略 }
さて、newで確保した領域がいらなくなった場合は、deleteします。
// 前略 int main(){ myclass *c = new myclass(); // 都合により省略 delete c; // 都合により以下省略 }
全部書くと、下のようになります。ポインタのオブジェクトのメンバに対しては「->」を使います。この辺もC言語の構造体と変わりません。
#include <stdio.h> class myclass{ private: int a; public: int func(int value){ a = value; return value*value; } }; int main(){ myclass *c = new myclass(); printf("%d",c->func(2)); delete c; return 0; }
コンストラクタとデストラクタ
さて、newの使い方で、
myclass *c = new myclass();
このmyclass()の括弧は一体何を意味するのでしょうか。
これはコンストラクタという特殊なメソッドに対する引数を指定するのです。
コンストラクタとは、newされたときに呼び出されるメソッドです。またdeleteされたときにはデストラクタと呼ばれるメソッドが呼び出されます。
コンストラクタ、デストラクタで初期化処理、終了処理(メモリの解放など)ができます。まったく便利なものです。
コンストラクタとデストラクタの作り方
コンストラクタ、デストラクタ作成時の注意は以下のとおりです。
- コンストラクタはクラスの名前と同じ名前でなければならない。
- デストラクタはクラスの名前の前にチルダ「~」をつけた名前でなければならない。
- コンストラクタ、デストラクタは型を設定することができない。
実際に作ってみると、こんな感じになります。
class myclass{ private: int a; public: myclass(int value){ a = value; } ~myclass(){ a = 0; } int func(int value){ return a*value; // (ちょっと変えてみました。) } };
「myclass」がコンストラクタで、newしたときに入れられた値を、メンバ変数aにセットします。「~myclass」がデストラクタで、aに0をセットします。
このクラスを使うと、この様になります。(func()が今までと違うので、注意)
#include <stdio.h> class myclass{ private: int a; public: myclass(int value){ a = value; } ~myclass(){ a = 0; } int func(int value){ return a*value; // (ちょっと変えてみました。) } }; int main(){ myclass *c = new myclass(3); printf("%d",c->func(2)); delete c; return 0; }
-- 続く --
やっぱり、絵がないと色がないよね。
でもペンギンネタも飽きたし・・・。
これで勘弁してください!!
※コメント、トラックバックはできません。(ブログじゃないから)
珍しく更新が続いている
16-4-2009
↓これの作り方でもやろうか。
絵の書き方、3Dモデルの作成方法ではなく、プログラミングの方ね。
SDL
Simple DirectMedia Layerの略。要はゲームを作るためのライブラリ。
gcc、g++のような開発環境がデフォルトで用意されているLinuxなら、ゲームプログラムも特に用意なくできるぜーという話をしていきます。
SDLの準備
公式サイトから、ライブラリをダウンロードし、インストールします。
SDLは必須。SDL_***はオプションだけど、できればあった方がいいと思う。SDL_imageは各種画像を扱うのに必要(SDL単体ではビットマップのみ)、SDL_ttfはttfフォントを扱うのに必要、SDL_mixerはサウンドを扱うのに必要、SDL_netはネトゲを作るのに必要。
起動 & 終了
一応、ここではC言語として作成していきます(gccを使用)が、C++で作ることも可能です(コンパイラとしてgccではなく、g++を使用する)。下の空のプログラムに処理を入れていく形で作成していきます。
#include <SDL/SDL.h> int main(){ /* ここに処理を入れます */ return 0; }
SDLを起動する命令はSDL_Init()です。
int SDL_Init(Uint32 flags);
「flags」には起動するサブシステムを指定します。(参考)
とくに「これだけを起動したい」ということがなければ、すべて起動しましょう。すべてを起動する場合は、SDL_INIT_EVERYTHINGを指定します。
成功したら0、失敗したら-1が返ります。
SDLを終了する命令はSDL_Quit()です。
void SDL_Quit(void);
以上、起動と終了を空のプログラムに入れるとこの様になります。
#include <SDL/SDL.h> int main(){ SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ /* ここに処理を入れます */ SDL_Quit(); /* SDL終了 */ return 0; }
コンパイルは、SDLライブラリを使いますので、次のようになります。
$ gcc test.c -lSDL
実行すると、そのまま終了します(当然か)。
画面の作成
さて、次に描画する画面を作成します。
SDL_SetVideoMode()にて作成します。
SDL_Surface* SDL_SetVideoMode(int width, int height, int bitsperpixel, Uint32 flags);
widthは幅、heightは高さ、bitsperpixelは1ピクセルあたりのビット数で、32とかにしておくと綺麗に描画できます。
flagsにはここの表に載っているパラメータがセットできます。SDL_SWSURFACEとか、SDL_HWSURFACEなんかをセットしておきます(グラフィックボードが優秀ならSDL_HWSURFACEかな?うちの環境だとよく分からない)。フルスクリーンにしたければSDL_FULLSCREENです。
成功すると、フレームバッファのサーフェスが返ります。失敗すると、NULLが返ります。
#include <SDL/SDL.h> int main(){ SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); SDL_Quit(); /* SDL終了 */ return 0; }
さて、これにもう一つ処理を入れておきます。
大したことはありません。このプログラムを実行すると、ウインドウ作成後すぐに終了してしまうので、スリープを入れるだけです。
void SDL_Delay(Uint32 ms);
msはミリ秒単位でスリープ時間を設定します。
#include <SDL/SDL.h> int main(){ SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); SDL_Delay(3000); SDL_Quit(); /* SDL終了 */ return 0; }
実行すると次のようになります。
-- 続く --
参考サイト : SDL Documentation Wiki
今日のg++
今まで、クラスの中にメソッドを書いてきました。(↓のような感じ)
class myclass{ private: int a; public: myclass(int value){ a = value; } ~myclass(){ a = 0; } int func(int value){ return a*value; } };
このサイズのクラスならまだいいのですが、もっとたくさんの変数、メソッドを持つクラスを書くとなると、クラスの定義の中にメソッドの中身を書くと大変見にくくなります。
そこで、処理内容をクラスの外に記述するようにしてみましょう。
::
これを実現するために、「::」を使用します。コロンを2つ並べたものです。次のように記述します。
class myclass{ private: int a; public: myclass(int value); ~myclass(); int func(int value); }; myclass::myclass(int value){ a = value; } myclass::~myclass(){ a = 0; } int myclass::func(int value){ return a*value; }
「クラス::メソッド」のように書きます。型がある場合(コンストラクタ、デストラクタ以外すべてそうですが)は型を最初に書きます。(「型名 クラス::メソッド」といった具合)
よくやる手として、定義部分と実際の処理部分を別ファイルに分けるということが行われます。すなわち、
// myclass.h class myclass{ private: int a; public: myclass(int value); ~myclass(); int func(int value); };
// myclass.cpp #include "myclass.h" myclass::myclass(int value){ a = value; } myclass::~myclass(){ a = 0; } int myclass::func(int value){ return a*value; }
といった感じでプロジェクト(プログラムを作成するためのファイル群)の構成が行われることがしばしばあります。
※コメント、トラックバックはできません。(ブログじゃないから)
だいぶ長くなってきたので
17-4-2009
古い記事から順に別ページに移動させていきます。
g++とSDLはある程度の量になったら再編成して別にページを作ろうかな。
SDL - 昨日の続き
昨日はここまでやりました。
今日はいよいよ画面に画像を表示します。
画像の読み込み
とりあえず何か画像を用意してください。なかったら、下の画像でも使ってください。
画像読み込みはIMG_Load()で行います。
SDL_Surface *IMG_Load(const char *file);
なお、これを使うにはSDL_imageのライブラリが必要になります。(入手→SDL_image)
これを使いたくない場合は、SDL_LoadBMP()で読み込みができますが、名前のとおり、ビットマップファイルの読み込みしかできません。(尚、上のペンギン画像はpngなので、SDL_LoadBMP()では読み込みできません。)
SDL_Surface *SDL_LoadBMP(const char *file);
どちらの関数を使うにしても、fileでファイル名を指定し、読み込みが成功すると、SDL_Surface構造体の形で画像データが取得できます。失敗したらNULLが返ります。
なお、SDL_Surface構造体は以下のメンバを持っています。(SDL_video.hより)
typedef struct SDL_Surface { Uint32 flags; /* Read-only */ SDL_PixelFormat *format; /* Read-only */ int w, h; /* Read-only */ Uint16 pitch; /* Read-only */ void *pixels; /* Read-write */ int offset; /* Private */ /* Hardware-specific surface info */ struct private_hwdata *hwdata; /* clipping information */ SDL_Rect clip_rect; /* Read-only */ Uint32 unused1; /* for binary compatibility */ /* Allow recursive locks */ Uint32 locked; /* Private */ /* info for fast blit mapping to other surfaces */ struct SDL_BlitMap *map; /* Private */ /* format version, bumped at every change to invalidate blit maps */ unsigned int format_version; /* Private */ /* Reference count -- used when freeing surface */ int refcount; /* Read-mostly */ } SDL_Surface;
各項目に関する詳しい説明はを参照してください。(SDL_Surface SDL Documentation wiki)
#include <SDL/SDL.h> #include <SDL/SDL_image.h> int main(){ SDL_Surface *image; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); image = IMG_Load("penguin.png"); SDL_Delay(3000); SDL_Quit(); /* SDL終了 */ return 0; }
SDL_imageライブラリをするときはコンパイル時にそれをリンクしなければなりません。
$ gcc test.c -lSDL -lSDL_image
画像を表示する
画像を表示するには3段階の手順を踏みます。
- ディスプレイサーフェスを取得する。
- ディスプレイサーフェスに画像イメージを複写する。
- flipする
まず、ディスプレイサーフェスを取得します。
SDL_Surface* SDL_GetVideoSurface(void);
次に、ディスプレイサーフェスに画像イメージを複写します。
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
SDL_Rectは次のメンバを持つ構造体です。
typedef struct SDL_Rect { Sint16 x, y; Uint16 w, h; } SDL_Rect;
↑ x座標とy座標、縦横の大きさです。
*srcには複写する画像イメージを指定し、画像側の複写範囲を*srcrectで指定します。*dstにはディスプレイサーフェス(SDL_GetVideoSurfaceで取得したもの)を指定します。*dstrectにはディスプレイサーフェス側の画像セット位置を指定します。
*dstrectはxとyのみ参照され、w,h(縦、横の大きさ)は無視されるようです。
なお、画像の拡大、縮小には、SDL_gfxライブラリが必要となります。
最後にflipをします。
int SDL_Flip(SDL_Surface* screen);
これで、画面に画像が表示されるはずです。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> int main(){ SDL_Surface *image; SDL_Surface *screen; SDL_Rect rect_scr = {0,0,300,300}; SDL_Rect rect_img = {0,0,200,200}; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); image = IMG_Load("penguin.png"); screen = SDL_GetVideoSurface(); SDL_BlitSurface(image, &rect_img, screen, &rect_scr); SDL_Flip(screen); SDL_Delay(3000); SDL_Quit(); /* SDL終了 */ return 0; }
タイトルバーが空白なのは寂しい
ので、SDL_WM_SetCaption()でタイトルバーをつくりましょう。
void SDL_WM_SetCaption(const char *title, const char *icon);
*titleはタイトルバーの文字列、*iconはアイコンのファイル名ではなく、ウインドウリストに表示する文字列をセットします。文字列はUTF-8でエンコードされたものが使用できます。
#include <SDL/SDL.h> #include <SDL/SDL_image.h> int main(){ SDL_Surface *image; SDL_Surface *screen; SDL_Rect rect_scr = {0,0,300,300}; SDL_Rect rect_img = {0,0,200,200}; SDL_Init(SDL_INIT_EVERYTHING); /* SDL起動 */ SDL_WM_SetCaption("ペンギン", "ぺんぎん"); SDL_SetVideoMode(300, 300, 32, SDL_HWSURFACE); image = IMG_Load("penguin.png"); screen = SDL_GetVideoSurface(); SDL_BlitSurface(image, &rect_img, screen, &rect_scr); SDL_Flip(screen); SDL_Delay(3000); SDL_Quit(); /* SDL終了 */ return 0; }
-- 続く --
今日のg++
C++の書き方です。
オーバーロード
オーバードライブとかだと何かの必殺技っぽくてかっこいいのですが、「ドライブ」ではありません。「ロード」です。また、オーバーライドというよく似た言葉もそのうち登場しますが、これもまた別物です。
これは一体何かと言うと、同じ関数で異なる引数を持ったものが作れるというものです。クラスを作るときにはあまり便利さを感じませんが、実際作ったクラスを使ってプログラムを作成する場合は、これはかなり便利になります。
例えば、ファイルを読み込むという関数を作成するとします。ファイルの読み込みはfreadを使って読み込めますので、freadをラップした関数を作成します。引数はファイルポインタと読み込みサイズ、バッファになります。
また、fopen、fread、fcloseの流れが面倒だ。どうせ一回しか読み込まないんだから、ファイル名を指定して読み込められればいい、という場合もありますので、fopen、fread、fcloseを連続して行う関数を作成します。この場合、引数はファイル名、読み込みサイズ、バッファになります。
ここで、両方の関数を仮にfilereadとしておけば、ファイルポインタを使うにしろ、ファイル名を指定するにしろ、どちらの場合もfilereadを使えばよくなり、余分に関数名を覚えなくても済みます。
なお、引数が同じで、返す型のみ異なるというのはだめです。
// myclass.h #include <stdio.h> class myclass{ private: int a; public: myclass(int value); ~myclass(); int func(int value); int fileread(FILE* fp, int size, char* buf); int fileread(char* filename, int size, char* buf); };
// myclass.cpp #include "myclass.h" myclass::myclass(int value){ a = value; } myclass::~myclass(){ a = 0; } int myclass::func(int value){ return a*value; } int myclass::fileread(FILE* fp, int size, char* buf){ return fread(buf, sizeof(char), size, fp); } int myclass::fileread(char* filename, int size, char* buf){ FILE* fp; int ret; fp = fopen(filename, "rb"); if(fp == NULL) { return -1; } ret = fileread(fp, size, buf); // ↑のfilereadを呼び出しています。 fclose(fp); return ret; }
読み込み部分は共通処理(fread)なので、fileread(ファイル名版)の中でfileread(ファイルポインタ版)を呼び出しています。
※コメント、トラックバックはできません。(ブログじゃないから)
Copyright (c) 2008, 2009 greencap