忍者ブログ

神戸電子専門学校ゲームソフト学科の生徒が運営するGESのブログです。

   
カテゴリー「C++実用」の記事一覧

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

リファレンス

C++のリファレンス
http://www.cppreference.com/wiki/jp/start

C++11 sinceC++11って所が新しく追加された所です。(英語)
http://en.cppreference.com/w/cpp

C++11の日本語ver(C++11の項目がなくあちこちにあるのでC++11をまとまって読みたい方には不向き)
https://sites.google.com/site/cpprefjp/reference

VisualStadio2010からC++11を使えます。
VisualStadio2008は2008にSP1というものを入れれば、
ある程度のものを扱えます。(shared_ptr・正規表現・tupleなどが使えます)
SP1のインストーラの場所↓
http://www.microsoft.com/downloads/ja-jp/details.aspx?FamilyId=FBEE1648-7106-44A7-9649-6D9F6D58056E&displaylang=ja

SP1によって追加されるライブラリ一覧
http://msdn.microsoft.com/ja-jp/library/bb982198.aspx

補足
SP1によってもたらす効果のURLです。C#の予測候補などが早くなるみたいです。
http://www.atmarkit.co.jp/fdotnet/special/vs2008sp1/vs2008sp1_01.html

リファレンスを読むことで見たこと無かった関数とかあったりして面白いです。
関数オブジェクトに足を入れたら、しばらくは抜け出せないです。

byリーダ和田

拍手[1回]

PR

数字→文字、文字→数字、変換、lexical_cast

// 理想1
int num=893;                // これを文字列にしたい!
std::string str;              // 文字列格納先
str=(std::string)(num); // 無理やりキャストなんてことはできない・・・・・
printf("%s",str.c_str() );

// 理想2
std::string str="893";     //  数字にしたい
int num;                          // 数字格納先
num=(int)(str);               // 無理やりキャストなんてことはできない・・・・・
printf("%d",str.c_str() );

あるひとつのフォーマットにしたがって書けば、実現することができます。
今回紹介するのは、lexical_castです。

拍手[0回]

第1回 デザインパターン 『シングルトンパターン』

中原です。

そろそろデザインパターンをしてみようかと…。

カテゴリもC++入門ですが、新しく増やすのもなんですし、そのままいっちゃいます。

では、早速。

第1回 デザインパターン 『シングルトンパターン』

拍手[0回]

反復子を自分で作ってみる

ども・・・・・・・・・・・・和佐田雅史です。
今回はイテレータについてです。

イテレータと言うのは反復子の事で、listやmapコンテナをfor文でポインタによる参照( のようなもの )を行いたい時に使います。

std::list< T >::iterator it = List.begin();

と言う感じですね。
しかし、自分でコンテナを作った時にiteratorはどう作ればよいでしょうか?

基本的には定義したコンテナクラスの中にローカルクラスとして定義するのが一般的です。

template< class T > class Freelist
{
// 実装

// ローカルクラスとして定義
class iterator : public std::iterator<.....>
};

ですが一々コンテナを作る時に定義するのははっきり言ってめんどくさいのでtemplateで作っておくと便利です。


//============================================
// コンテナ作成時の反復子
//
//
//
//============================================

#ifndef _ITERATOR_HPP_
#define _ITERATOR_HPP_

#include <iterator>

namespace Alumina
{

// friendの為の仮定義
template< typename Type , typename value_type > class iterator;
template< typename Type , typename value_type > class const_iterator;


//=============================================
// 通常iterator
//
//
//=============================================
template< typename Type , typename value_type > class iterator : public std::iterator<std::bidirectional_iterator_tag, value_type, void>
{
public:
 iterator() : _ptr(0) {}

 iterator(Type* ptr) : _ptr(ptr){}

 // ジェネリック要素へのアクセス
 Type& operator*() const {return *_ptr;}
 Type* operator->() const {return _ptr;}


 // 真偽判定
 bool operator==(const iterator& rhs) const {return _ptr == rhs._ptr;}
 bool operator!=(const iterator& rhs) const {return _ptr != rhs._ptr;}

//=============================================
//
// 演算子によるポインタ演算
//
//=============================================
 iterator& operator++() {_ptr = _ptr->_next; return *this;}
 iterator& operator--() {_ptr = _ptr->_prev; return *this;}
 iterator operator++(int i) { iterator temp = *this; ++*this; return temp; }
 iterator operator--(int i) { iterator temp = *this; --*this; return temp; }

protected:

 // メンバ
 Type* _ptr;

 friend class Type;
 friend class const_iterator;
};

//===============================================
// const_iterator
//
//
//===============================================
template< typename Type , typename value_type > class const_iterator : public std::iterator<std::bidirectional_iterator_tag, value_type, void>
{
public:
 const_iterator() : _ptr(0){}
 const_iterator(const iterator& it) : _ptr(it._ptr) {}
 const_iterator(const Type* ptr) : _ptr(ptr) {}

 const Type& operator*() const {return *_ptr;}
 const Type* operator->() const {return _ptr;}

 bool operator==(const const_iterator& rhs) const {return _ptr == rhs._ptr;}
 bool operator!=(const const_iterator& rhs) const {return _ptr != rhs._ptr;}

 //=============================================
 //
 // 演算子によるポインタ演算
 //
 //=============================================
 
 const_iterator& operator++() {_ptr = _ptr->_next; return *this;}
 const_iterator& operator--() {_ptr = _ptr->_prev; return *this;}
 const_iterator operator++(int i) { const_iterator temp = *this; ++*this; return temp; }
 const_iterator operator--(int i) { const_iterator temp = *this; --*this; return temp; }

protected:
 const Type* _ptr;

 friend class Type;
};


}
#endif


長くなりましたが、使用例を以下に示します。


// LISTNODE 型を管理するリストコンテナ
template < typename LISTNODE , template< class > class Interfase = ListType > class FreeList
{
public:

 // 実装インターフェース設定
 typedef Interfase< LISTNODE > LIST;

 // それに伴った反復子を定義
 typedef Alumina::iterator< LIST , LIST > iterator;
 typedef Alumina::const_iterator< LIST , LIST > const_iterator;

.........................

};

このように定義するだけでiteratorが使えるようになります。
便利ですね。


それではお疲れ様でした。

拍手[0回]

インターフェイス講座

ども、こんばんわ~

目を閉じれば楽園が見えてるZAKIです

発表会はすごい作品が多かったですね~

とってもよく作りこんであったり、アイデアが面白かったりすごいチームばかりでした

僕もがんばってやらなければっ


さて、今回のテーマは「インターフェイス講座」です

C++言語のクラスについての話になるので2年生対象ですね

みなさんはインターフェイスって使ってますか?

これを使ってやると沢山のコードを使いまわせたりするんですよ

拍手[0回]

templateMetaProgramming

ども・・・・・・・・・・・・・・・・・・GES会長の和佐田雅史です。


今日は新世界の技術と呼ばれているtemplateMetaProgrammingについてです。
少し前にGenericProgrammingについて触れましたが、それの応用です。

GenericProgrammingは型引数というものを持ち、型に依存しない素晴らしいプログラムが組めるというものでした。

// ラジアン
  template< typename T > inline T Radian( T Degree )
  {
   return static_cast< T >( PI/180.0f)*Degree;
  }

このようにするとT型へ勝手にラジアン変換してくれる便利なユーティリティの出来上がりです。
float Angle = Radian< float >( 60.0f );
double Angle = Radian< double >( 60.0f );

のように型引数で指定すると勝手に展開されて、その関数を構築してくれます。
※実際はstatic const float Radian = PI/180.0f;と置いて手動で変換する方が遥かに速いですが。


しかしtemplateで渡せるのはclassや、typenameだけではありません。
int、unsigned(  unsigned int  )、long等と言った整数値も型として渡すことが可能です。
( VisualC++ 6.0コンパイラならdouble等も渡せます。 )

これを利用しない手はありません。

これを利用すれば、コンパイル時に型生成だけで数値演算を行うことも可能です。
以下を踏まえて階乗を計算するtemplateを実装してみます。


// 階乗計算templateMeta
  template< unsigned N > struct Fact
  {
   enum { Val = N * Fact< N - 1 >::Val };
  };

  // template特殊化 : 0か1の階乗の場合
  template <> struct Fact< 0 > { enum { Val = 1 }; };
  template <> struct Fact< 1 > { enum { Val = 1 }; };

// 分りにくい人の為にマクロで呼びさせるに定義
#define FactT( n ) Fact< n >::Val

0の階乗や1の階乗は1なので予めtemplateの特殊化をしておきます。
templateの特殊化とは、この型の場合はこういう動きをするというものを定義する機能です。

Fact( 3 );

とすると3の階乗をコンパイル時に型として生成し、実行時には既に求まっているものとなります。



必ずしも必要な技術では無いですが、学生にして神の領域に挑みたい方はどうぞ。

templateMetaに関しては、boostやLokiというライブラリを解析すれば結構勉強になります。
最もそれらが理解出来るのならば学校に来る必要等無いですが・・・・・・・・・・・・。

それではお疲れ様でした。

拍手[0回]

const使ってる?

ども、こんばんわ~

割とふらふらしてきたZAKIです

製作実習が終盤に近づいてきました

最初からクライマックスなチームもいるかもしれませんが、体には…気をつけて


さて、今回のテーマは「const」です。

プログラムで意外と使われていないconst修飾子

constを付けるとその変数、構造体に値を代入できなくなります

そんなのどこで使うんだ?と思われるかもしれませんが、意外と役に立つんですよ?

今回はその使い道をざっと紹介

拍手[0回]

スマートポインタ

ども・・・・・・・・・・会長の和佐田雅史です。
今日はスマートポインタについて講義します。


皆さんはnewやdeleteを知っているでしょうか?
動的に変数の領域を確保する時に

Character Chara = new Character;

とすると変数CharaにCharacter型の領域を作成する事が出来ます。
ようするにcで言うmallocを使っているとお考え下さい。

しかし、newで確保したものは解放しないとメモリリークを起こしてしまいます。
mallocで確保したメモリはfree関数で解放しないといけませんよね?

それと同じ事です。

しかし・・・・プログラマと言えど人間ですのでもしかすると解放処理を忘れてしまうかもしれません。

ですのでスマートポインタ( STLではオートポインタ )という物を使います。

std::auto_ptr< 型引数 > ptrObject;

とすると、参照がなくなった時点で勝手に解放してくれます。
javaのガーベージコレクションとまでは行きませんが便利ですよね?

ただ、中には自分でスマートポインタを作りたいという人が居るかもしれません。
なので一応簡易版をここに乗せておきます。

使いたい人はどうぞ。
※1.動的に確保したObjectのみに適用するようにして下さい
※2.ネームスペース( Wasadaとかptrとか )は自由に書き換えてもらって結構です。

使用例は


Wasada::ptr::auto_ptr< Character > Chara();

Chara->m_hp = 1;


等です。

それではお疲れ様でした。


namespace Wasada
{

namespace ptr
{

// オートポインタ定義
template< typename Type > class auto_ptr
{
private:
 Type* _ptr;
 friend class Type;
 
public:
 // ptrアクセッサ
 Type& operator*() const {return *_ptr;}
 Type* operator->() const {return _ptr;}

 
 // コンストラクタ
 auto_ptr(const Type* ptr)
 {
//  this->_ptr = NULL;
  this->_ptr = ptr;
 }

 auto_ptr()
 {
  this->_ptr = NULL;
  this->_ptr = new Type;
 }


 // デストラクタで勝手に解放
 virtual ~auto_ptr()
 {
  if( this->_ptr )
  {
   delete _ptr;
  }
 }
};

}
}

拍手[0回]

FPS制御 ~プログラム編~

ども~こんにちわ~

ZAKIでっす

更新に間が空いてしまってすいませんっ

部屋探しに追われている毎日で不動産回りまくってます


さて、今回は「FPS制御~プログラム編~」です。

やっと。って感じですね

前回にも載せましたが、サンプルとドキュメントはこちら

一部表示されないページがあったようなので、修正しました。

申し訳ありませんでした

さて、プログラムの手順は以下の通りです。

  1. 1フレームにかける時間の計算
  2. 現在時間の取得
  3. 処理後の時間の取得
  4. 1フレームの時間との差分を計算
  5. 4の差分次のフレームまで待つ

1についてはFPSを操作したい場合以外なら、プログラムの始めに一度行えばいいでしょう

サンプルではFrameInit()の中でSetFpsValue()で設定しています

中身は1000ミリ秒を60で割っているだけですね

さて、残りはFrameDraw()の中ですね

まず処理関数Proc()を呼ぶ前にSetBeforTime()現在の時間をセットします。

SetBeforTime()の中のtimeGetTime()現在時間をミリ秒単位で取得してきます。

その後Proc()で処理をしてSetNowTime()処理後の時間をセットします。

そして、GetElapsedTime()ウェイト時間を取得します

GetElapsedTime()中にあるassert()は中の式が真なら、処理を中断してエラーを出します

コンパイルモードがDebugでのみ有効なのでReleaseにすればコンパイルされません。(たしか

最後のGetFpsValue()は現在のFPS値を引数に入れて返します

関数を通るたびに回数をカウントして、前の更新から1秒間経てばFPS値を引数に入れます。

この関数を使うにはSetNowTime()を使っている必要があります


大体はこんな感じでしょうか

大体の説明はソース読みつつコメントを読めばわかるかなぁと思います

わかりにくければ、気軽に質問してくださいね

一応DirectX版も作ってありますが、

DirectXではデバイスを作る際の構造体(D3DPRESENT_PARAMETERS)の

PresentationIntervalメンバにD3DPRESENT_INTERVAL_DEFAULT入れれば勝手にやってくれます

なので、まぁ、GetFpsValue()でも使って、「あ、FPS減った」とか見て楽しんで(?)ください

DirectXを使うにはDrawMain.hのマクロ、__NOT_USE_DIRECT__OUTPUT_DOXYGENXのコメントをはずせば動くはずです

DirectX等の初期化のところもコメントを書いていますが、大体入れる値は変わりません

1年生でやりたいと思う人はとりあえず、自分で打って写してみるとわかりよいので、おすすめです

詳しくは本、ネット、最寄の先輩などに突撃してみましょう

それも勉強のうちです

ちなみに今回の記事は赤色の文字がFPS関連の自作関数青色がゲーム処理関係の自作関数

緑色がDirectXなどのAPI等の関数、構造体になっています。

FPS制御はこの記事で終了です。

お疲れ様でした

それでは今回はこの辺りで、

あでゅーノシ

拍手[0回]

FPS制御 ~概要編2~

ども、こんにちわ~

いよいよ寒くなってきましたね~

今年二度目のにわか風邪を引いているZAKIです

何やら連続記事投稿記録が伸びているようですね

記録を伸ばすためにも、みんながんがん投稿しちゃってください


さて、今回のテーマは「FPS制御 ~概要編2~」です

2(ツー)です2(ツー)。

前回はFPSの動機について話しましたが、今回は仕組みについてです

そんなもんいいから、ソースみせれ!って人はこちらへどうぞ

さて、それではどうやったら1秒間のフレーム数を固定にできるのか

答えは簡単、1フレームにかける時間を一定にすればいいんです

1秒間に60フレーム(FPS:60)処理するとしましょう

そうすると、1フレームにかける時間は

1秒 ÷ 60回 = 0.0166666......秒

ミリ秒単位に直すと約16秒。

1フレームは最大約16ミリ秒かかればいいのです

じゃあ、16ミリ秒まてばいいかというと、そうでもないんです

ゲームでキャラを動かしたり、描画したりする時間も含めないと、

? ミリ秒(描画などの処理時間) + 16ミリ秒(待ち時間) = 16 +? ミリ秒

という感じで待ちすぎてしまいます

なので、処理した時間を測って、その分引いてやる必要があるんです

処理時間を計るにはどうすればいいでしょう

普通、時間を計る時には前の時刻と今の時刻を引き算しますよね?

プログラムでも同じで処理開始時間と処理終了時間を引き算してやればいいのです

開始時間が90で終了時間が100だとすると

16ミリ秒(待ち時間) - {100(終了時間) - 90(開始時間)} = 16ミリ秒 - 10ミリ秒(処理時間)

                                         = 6ミリ秒

となり、この場合は次のフレームまで6ミリ秒待ってやればいいのです

この処理を毎回行うことで1秒間のフレーム数を固定することが出来ます

もし、答えがマイナスになったときは、

処理時間のみで1フレームの最大時間を越えたことになるので、

待つ必要がありません

ただ、その時の対処法が二つありまして、(僕が知る限りなのですが
  • そのまますぐに次のフレームの処理を始める場合
  • 描画処理の部分を飛ばして次のフレームの処理を始める場合
の二つがあります。

前者の場合は1フレームの時間が増えて、処理する回数が減るため、スローモーションのような状態になります

これを「処理落ち」と言います

後者の場合は描画を処理する負担が減るので、ほとんどの場合で1フレームの時間内に次のフレームに移れますが、

描画回数が減るので、画面には瞬間移動のように映ります

これを「コマ落ち」といいます。

格闘ゲームなど見た目のタイミング等が重要な場合は前者が向いているでしょうし、

3Dゲームなど描画部分に強い負担がかかる場合には後者が向いているんじゃないでしょうか

どちらがよいかはゲーム内容によって変わるので、一概には言えないですね


長々と説明してきましたが、これが一連の処理の流れになります

ほんとになっがいww

文章のデコレーションで死に掛けました

次回はいよいよプログラムの解説へはいっていきたいと思います

それでは今回はこの辺で。

あでゅーノシ

 

拍手[0回]

FPS制御 ~概要編~

こんにちわ~

ども、ZAKIです

学園祭が間近ですね~

出し物をする人は忙しく動いていることでしょう

当日までがんばっていきましょー

GESでもゲームブースを出すので一度見に来てください


さて、今回のテーマは「FPS制御 ~概要編~」です。

ところでFPSとは何ぞや?

FPSはFramePerSecond(フレームパーセカンド)の略です

以上です。

……や、やだなぁ。冗談ですよ~

ゲームで一回の処理(計算と描画)をフレームと言います

そのフレームを1秒間に何回行うかを管理することをFPS制御というんですね~

たまに画面の端っこなどに「FPS 60」とか書いてあるのを見たことがありませんか?

あれは一秒間に60回処理をしているよ~という表記なのです。

なぜFPS制御をするのか?

例えば、

ゲームを作っているパソコンとゲームを行うパソコンが違う場合、

開発側のパソコンは1秒間に5回処理できます

プレイヤー側のパソコンは1秒間に10回処理できます

キャラクターが1回の処理で5進むとすると、

開発側のパソコンでは1秒間に25進みますが、プレイヤー側のパソコンでは50進みます

同じゲームなのに開発側とプレイヤー側とでキャラクターのスピードが違います。

開発側はキャラクターは1回の処理に5進むのが丁度いいと思っていても、

プレイヤー側にとってはスピードが速過ぎるということになります

これを1秒間に行う処理回数(FPS)を制御をして、どちらのパソコンでも1秒間に5回処理するようにすればいいわけです

さらに!

FPSをわざと下げてやれば、スローモーションを表現できたりも!?

と、いろいろと便利なので、是非やっておくべきだと思います。

特にデジタルワークスに出たいと思っている人は必要だと思います

デジタルワークスではゲームラボのパソコンを使うので、学生のノートパソコンとでは性能が段違いです

ラボでwait数値を手打ちで調整するよりもFPS制御をしておいたほうが断然楽ですし、発表前はバグとりなどで忙しいので、

今のうちからやっておいたほうがいいんじゃないでしょうか


次の機会には実際にやり方を解説しようと思います

この部分がわからない!

解説がおかしい!

など、コメントなどで指摘してくもらえれば、

修正、解説したいと思うのでよろしくお願いします

では、この辺で。

あでゅーノシ

拍手[0回]

stlを利用したlistコンテナ

ども・・・・・・GES会長の和佐田雅史です。
一年生からリストコンテナを使いたいという要望があったので乗せておきます。


STLのリストコンテナを利用したプログラム

STLはスタンダードテンプレートライブラリと言い、C++に標準で入っているライブラリで、開発効率をかなり上げることが出来ます。

 

STLを利用する事によって変数の型に依存せずにプログラム組めるようになります。

例で言うとint型のリストchar型のリストが違うだけでアルゴリズムは同じです。そのアルゴリズムの部分だけを組んでおいて後から使用する変数の型を指定するプログラムの組み方がSTLの組み方になります。

             

今回はリストコンテナと言うものを利用したプログラムを解説します。

<>左のような括弧の中にで指定したリスト構造を勝手に作ってくれる便利なものをしようすることで一々手動でリスト構造を設計すること無く、自動生成をしてくれるものです。

 

ではまず宣言の仕方から説明します。

: 宣言の仕方

// int型のリスト構造を作成するプログラム

#include <conio.h>

#include <list>

 

// 名前空間stdを使用する

using namespace std;

 

int main()

{

        // 定義

list< int > intList;

 

              // 以下STLによるプログラム

 

return 0;
}
 

※作成するリストの型はintは勿論構造体やクラス等の型も指定できるのでリストクラス等を作成する場合などには便利です。

                  

 

格納の仕方

値を格納するにはpushbackメソッドを使用します。リストの末尾に要素を追加する事が出来ます。



 

//----------------------------------------------------

// 010までの値を格納する

//----------------------------------------------------

for( int i=0 ; i<=10 ; i++ )

{

    // pushbackメソッドで値を格納

    intList.push_back( i );

}
※同様にpopbackというメソッドを使用するとリストの末尾の要素を消す事が出来ます。
 

これで宣言が完了しました。

では次に値を参照するにはどうすればよいのでしょう?
通常ではリストを参照するには基本的にHeadからTailまでをポインタで参照しながら処理します。


ではここでリストの先頭と末尾を取得するメソッドを紹介しましょう。



 

// int型のリストコンテナの要素を参照する物

list< int >::iterator i_IntIterator;

 

// リストの先頭を取得します

i_IntIterator = intList.begin();

 

// リストの末尾を取得します

i_IntIterator = intList.end();

 

 

格納した値を参照するには?

格納した値を参照する時はiterator( イテレータ )と言うものを使います。

イテレータとは反復子と呼ばれ、ポインタのような動きをします。

 

宣言は以下のようにします。

list< int >::iterator 変数名;

 

// イテレータを宣言する : ポインタみたいなもの

list< int >::iterator i_IntIterator;


以上の事を踏まえると、以下のようなループになると思います。

 

// イテレータの参照が先頭から末尾で無いときイテレータは次を参照続ける

for( i_IntIterator = intList.begin() ; i_IntIterator != intList.end() ; i_IntIterator++ )

{

        printf("%d\n" , ( *i_IntIterator ) );

}
 

 

 

     ( *i_IntIterator )とはどういうことなのか?

ポインタが参照している値を弄るには*p = 10のようにアスタリスクを付けます。

同じように、( *i_IntIterator ) = 10とすると、

 

int型のイテレータが参照しているものの中身に10という値を代入する

 

という事になります。

因みにですが、変数のアドレスがほしい場合は

 

&( *i_IntIterator )

 

のような記述の仕方になります。

イテレータはポインタと同じような動きはしますが、ポインタではない(正確にはメンバでint型のポインタオブジェクトを保持している)ので直接アクセスする事が出来ません。

 

なので、

 

イテレータの中に格納されている変数の中身のアドレス

 

と言うように記述してやらないと、構文エラーになります。

 

以上でlistコンテナの説明は終わりです。
他のvectorやmapコンテナ等も同じようにiteratorを利用する事が多いので触る予定の人は今のうちに慣れておいたほうが良いでしょう。

 

因みにですが、これが使えるプログラマと使えないプログラマでは開発における効率の差が100倍近くあります。

業界でC++が必須の技術となっているので必ず使えるようになっておきましょう。

それでは今日の
 講義はここまでとします。お疲れ様でした。

 

拍手[1回]

ブログ内検索

最新コメント

[01/29 人面犬]
[10/01 8ch]
[09/12 uncle]
[09/10 某卒業生]
[06/07 uncle]

カレンダー

03 2024/04 05
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

テスト

Copyright ©  -- GESブログ --  All Rights Reserved
Design by CriCri / Photo by Geralt / powered by NINJA TOOLS / 忍者ブログ / [PR]