神代クロ のすべての投稿

ゲーム開発14:キャラクタクラス作成

0307a462.jpg「みずほ銀の著作権投資、ゲーム開発にシフト」らしい>挨拶
---

キャラクタクラスCCharaを作るため試行錯誤してたのですが、あれやこれやと色んなモノを詰め込もうとして、訳わからん状態となってしまいました。

これじゃいつまで経っても完成しないという事で、複雑な処理は排除、外部ファイルとして持たせるデータもソースにベタ打ちさせて、とにかく動くもの優先で作ることにしました。

とりあえず以下の値だけ持たせました。

座標mx,my,mz
キャラクタ番号my_no
スプライト番号spr_no
キャラクタ管理クラスへのポインタCCharaManage*

ソースですが、前回のキャラクタ管理クラスCCharaManageからCCharaを継承した自キャラクラスCMyCharaを呼び出します。呼び出し時に即値でスプライトを生成して、spr_noに格納します。今はあまり意味無いけど、CCharaManageへのポインタもCommonInit()の中で格納しています。

Move()ではCInputクラスからキー入力を受け取り、座標mx,myに移動量を加算します。これで移動できます。

最後にDraw()からCommonDraw()を呼び出してスプライト表示させます。今は無駄に見えますが、キャラクタ毎に描画方法は変わりますので、こう書いてます。

一応これで任意の場所にキャラクタを表示し、キーボード等で移動させる事が出来ます。欲張らずに、最初からこうやって組んどけばよかったよ。

次回は当たり判定を行います。

//---------------------------------------------------------
// 初期化
CMyChara::CMyChara(int no, int x, int y, CCharaManage *manage)
{
 RECT workRect;

 my_no=no;
 CommonInit(x, y, 1, manage);

 // スプライト作成
 SetRect(&workRect, 0, 0, 48, 96);
 spr_no[0]=System->Graphics->CreateSprite("data\test.jpg", workRect);
}

//---------------------------------------------------------
// 移動
void CMyChara::Move()
{
 float work_x, work_y;
 KEYCODE key;

 // キーコード取得
 System->Input->PressKey(&key);

 work_x=(float)key.x*6;
 work_y=(float)key.y*6;

 mx+=work_x;
 my+=work_y;
}

//---------------------------------------------------------
// 描画
void CMyChara::Draw()
{
 CommonDraw();
}

//---------------------------------------------------------
// 共通描画
void CChara::CommonDraw()
{
 System->Graphics->DrawSprite(spr_no[0], mx, my, mz, D3DXCOLOR(1,1,1,1), 0, 1, 1);
}

//---------------------------------------------------------
// 共通初期化
void CChara::CommonInit(int x, int y, int type, CCharaManage *manage)
{
 CharaManage=manage;

 mx=(float)x;
 my=(float)y;
 mz=1.0f;
}

ゲーム開発13:キャラクタ管理クラス作成

キャラクタクラスCCharaを作ろうと思いましたが、その前にキャラクタ管理クラスCCharaManageを作成します。

キャラクタ管理クラスとは、CCharaをまとめて処理するクラスといった感じでしょうか。キャラクタの移動や描画はひとつひとつ別個に処理させず、この管理クラスに全部やってもらいます。

キャラクタの最大数MAX_CHARA分だけCCharaポインタを持ち、CreateChara()にて空いているCCharaポインタがあったら、そこに任意のキャラクタを生成します。キャラクタの種類kindを引数に持ち、ベタですがswitch~caseで生成キャラを選択します。ちなみに

Chara[i]= new CMyChara(i, x, y);
Chara[i]= new CEnemy01(i, x, y);

としているのは、CMyCharaCEnemy01がCCharaを継承したクラスだから可能にしている芸当です。キャラクタを増やす際、CEnemy02:public CCharaみたいに継承クラスを作って追加するだけで、中身が敵だろうとアイテムだろうと関係なく、汎用的に使いまわすことができます。

あとはMove()で移動、Draw()で描画を全キャラ分ループで回しています。キャラクタの寿命が来たらDeleteChara()で、これまた中身を気にせずに削除する事ができます。

次回は今度こそキャラクタクラスを作ります。

//-----------------------------------------------------------------------------
// 生成
CCharaManage::CCharaManage()
{
 int  i;

 // キャラクタ初期化(念のため)
 for (i=0; i<MAX_CHARA; i++) {
  Chara[i]=NULL;
 }
}

//-----------------------------------------------------------------------------
// 解放
CCharaManage::~CCharaManage()
{
 int  i;

 // キャラクタ解放
 for (i=0; i<MAX_CHARA; i++) {
  DeleteChara(i);
 }
}

//-----------------------------------------------------------------------------
// キャラクタ生成
CChara *CCharaManage::CreateChara(int kind, int x, int y, CChara *parent)
{
 int  i;

 // 空いているキャラクタがあるか検索
 for (i=0; i<MAX_CHARA; i++) {
  if (Chara[i]==NULL) {
   break;
  }
  i++;
 }
 if (i>=MAX_CHARA) {
  return NULL;
 }

 switch (kind) {
 case KIND_MYCHARA: // 自キャラ
  Chara[i]= new CMyChara(i, x, y);
  break;
 case KIND_ENEMY01: // 敵キャラ01
  Chara[i]= new CEnemy01(i, x, y);
  break;
 }

 // 自分の親を設定
 if (parent!=NULL) {
  Chara[i]->SetParent(parent);
 }

 return Chara[i];
}

//-----------------------------------------------------------------------------
// キャラクタ解放
void CCharaManage::DeleteChara(int no)
{
 if (Chara[no]!=NULL) {
  delete Chara[no];
  Chara[no]=NULL;
 }
}

//-----------------------------------------------------------------------------
// 移動
int CCharaManage::Move()
{
 int  i, ret;

 for (i=0; i<MAX_CHARA; i++) {
  if (Chara[i]!=NULL) {
   Chara[i]->Move();
  }
 }

 return ret;
}

//-----------------------------------------------------------------------------
// 描画
void CCharaManage::Draw()
{
 int  i;

 for (i=0; i<MAX_CHARA; i++) {
  if (Chara[i]!=NULL) {
   Chara[i]->Draw();
  }
 }
}

IE6からFirefox3に乗り換える

ブラウザはもう何年もInternet Explorer6(IE6)を使い続けてきましたが、Firefox3に乗り換えることにしました。

IE7が出ててIE8のベータ版?もあるけど、試しにIE7を入れて使った際、なんか使い辛く感じました。だからいっその事別のブラウザに乗り換えようと。まぁ試しに数ヶ月間、Firefoxを仕事パソコンで使ってて問題ないと判断したってのもあるんだけどね。

てゆうか、元々俺はNetscape Navigatorを使ってた人間だから、戻ったと言うべきかな。そういえばメーラーもずっとThunderbird使ってるし。

とりあえずアドオンはPopup ALT Attributes(画像のALT属性をIEみたいにポップアップ表示させる)とUser Agent Switcher(ブラウザを偽装する。携帯サイトを閲覧できるようになる)を入れました。

乗り換えたお陰で、ブラウジングの効率が上がりますね。

コタツを出す

21262d1c.jpg寒くなってきたので、コタツを出しました。まぁ出したっていうか、夏でもテーブル代わりに使ってるので、コタツ布団を買ってきて掛けたって事なんだけど。

ちなみに今まで使ってたコタツ布団は安物だったので、中の綿が千切れまくり、表面も破れてダメになってたので、新しく写真のやつを買いました。

これは掛け布団の四隅が柔らかい別の生地になっていて、あまり広がらないというものです。狭い部屋だと結構場所食うからね、こういうアイデア商品は良いね。

これで冬が越せます。

ゲーム開発12:キャラクタクラスの設計

キャラクタクラスキャラクタクラスCCharaを作るため、あれこれ試行錯誤してました。

キャラクタを構成するのは初期化・移動・描画・解放の処理と、スプライトや位置情報等のデータです。

ゲーム内にはキャラクタがたくさん出てくるので、このキャラクタクラスは生成・解放を頻繁に繰り返し、そのため無駄が出てきます。なので再利用できるデータは再利用して無駄を省きたい。その辺でデータの持ち方を色々と考えてましたよ。

画像の表はとりあえず現時点でのクラス案です。定型部分をパーツクラスCCharaPartsとして分けてみました。

これで大丈夫かな? とりあえず次回から実装に移ります。

ノートパソコン買いました2

この前買ったdynabookで、視野角が狭いと書きましたが、勘違いでしたよ。

画面が明るいと目が疲れるので、暗くして使うのですが、暗くすると画面端が暗くなりすぎて見づらい。この調節はグラフィックのプロパティで行っていたのですが、実は東芝省電力のプロパティから調節するとイイ感じの明るさになるのでした。

バッテリー駆動で使ってたら、バッテリーの減少と共に画面の明るさが変わったので気付いたよ。

画面の明るさも調節できたし、これで仕事用マシンとして外でガンガン使っていけます。寒くなってきたら、NASとこのdynabookで、コタツに居ながら仕事できるねw

ノートパソコン買いました

eab2b2d7.jpg
最近よくライブドアブログが落ちる…>挨拶
---

ノートパソコンを購入しました。今回は東芝です。dynabook SS RX1という、今年の1月に出たものです。今まで使っていたレッツノートCF-W2は良いものなんだけど、如何せん古いので性能的に厳しくなってきてたからね。

購入時に考えたのは、毎日持ち運ぶから軽いもの、どうせなら今より画面解像度が高いもの、やっぱりWindowsXP搭載、あとは性能が少々といったところです。

dynabook SS RX1 TE120E/2W PPR1TE2EPZRUK
Core2Duo 1.2GHz (超低電圧版)
メモリ1Gbyte
HDD80Gbyte
液晶12.1インチ(1280×800)
DVDスーパーマルチドライブ
WindowsXP Pro
重量1.1kg

ホントはEeePCみたいなネットブックを買おうと思ってたんだけど、いつまで待ってもインテルとゲイツの縛りが緩和されず、全然性能が上がらなかったから諦めました。今使ってるPCより性能が下じゃ買う意味ないしね。

ちなみに価格表見ると37万円って書いてあるけど、新品なのにその1/3くらいで買えたよ。

しかしこのdynabookの液晶は視野角狭すぎる。普通に見てても画面の下の方が暗くなってるし。値引率が高いだけあるのか。でもまぁ、慣れるでしょう。(東芝省電力のプロパティで解決しました)

写真の左側が今回買ったdynabookで、右側がレッツノート、後ろにちょっと見えてるのがNEC LaVie Gです。

統一感ないなぁw

ゲーム開発11:方向性を決める

前回までに、基底・グラフィック・入力のクラスが完成しました。今回はどんなゲームにするかを決めます。

まずは基本システムを考えてみました。

・横スクロールアクションゲーム
・敵を倒したり、障害物を乗り越えていく
・ステージクリア型でボスを倒したらクリア
・自キャラは左右移動、ジャンプ、近接および遠距離攻撃

ありがちなシステムですね。そしてやってみたい事を列挙します。

・ある条件でパワーアップさせる
・フィールドに高低差を付ける
・スピード感を出す
・自キャラの他にサブキャラを出す
・敵の頭に乗れるようにする
・演出に凝ってみる

どこまで出来るかわかりませんが、とりあえずこんな方向性で行ってみます。あと、このままだと地味なので、他と差別化するアイデアを引き続き考えてみますか。

次回はキャラクタークラスを作ります。いちばん難しく、かつ何度も作り直すことになるであろうクラスです。

ニコニコ動画のマイリストRSS取り込み

いつからなのかは知らないけど、ニコニコ動画RSSに対応していました。

なので今までIFRAMEで表示させていたマイリストをRSSで取得し、それっぽく並べてみます。RSSはニコニコ動画のURLの後ろに「?rss=2.0」みたいな引数を付ければ取れます。

巫女さんのマイリストは頻繁に更新しないので、キャッシュとして自サーバ保存しておきます。で、取り出して表示させたのが以下ページです。

巫女さん関連のニコニコ動画

画像やタイトルをクリックすると詳細ページに飛びます。詳細ページではニコニコ動画の外部プレイヤーを使ってページ内で表示させようと思ったのですが、どうも許可されたドメインからしか再生できないみたいです。仕方ないので、IFRAMEにしました。

結局IFRAMEか! あんま意味ないなぁ。外部プレイヤーが使えるようになるか、せめてRSSが検索結果に対応してくれればいいのに。

気が向いたらYouTubeからも取り込んでみよう。

ゲーム開発10:スプライト処理修正

以前作ったスプライト処理ですが、間違いを見つけました。今のままだとZ方向の移動が出来ず、奥行きが実現できません。

そんな訳でまず、CGraphicsBase::InitD3D()に以下のパラメータを追加します。これは奥行きを使うための宣言です。

d3dpp.EnableAutoDepthStencil=TRUE;
d3dpp.AutoDepthStencilFormat=D3DFMT_D16;

D3Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

次にCGraphicsBase::DrawSpriteBase()の中の計算とかを変更します。これでZ方向にも移動できるようになりました。

なぜ2Dなのに奥行きが必要かというと、背景の手前にキャラクタを表示し、キャラクタの手前に文字や設定画面を表示させたいからです。前のままでも、描画の順番を奥から順に並べれば同じ事はできます。でも、描画命令はあっちこっちのクラスから投げられてくるので、管理がややこしくなりそうです。そのため、今のうちに厳密に設定させるという訳です。

//---------------------------------------------------------
// スプライト描画
void CGraphicsBase::DrawSpriteBase(int tex_no, RECT drawRect, float x, float y, float z, DWORD color, float angle, float scale_x, float scale_y)
{
 D3DXMATRIX mat, mat1, mat2, mat3;
 float  center_x, center_y;
 D3DXVECTOR3 Trans, Center;

 // マトリクス初期化
 D3DXMatrixIdentity(&mat1);
 D3DXMatrixIdentity(&mat2);
 D3DXMatrixIdentity(&mat3);

 // マトリクスで拡大縮小回転移動
 D3DXMatrixScaling(&mat1, scale_x, scale_y, 1);
 D3DXMatrixRotationZ(&mat2, D3DXToRadian(angle));
 D3DXMatrixTranslation(&mat3, x, y, 0);
 mat=mat1*mat2*mat3;
 D3Sprite->SetTransform(&mat);

 // 移動
 Trans=D3DXVECTOR3(0, 0, z);

 // 画像の中心
 center_x=(float)(drawRect.right-drawRect.left)/2;
 center_y=(float)(drawRect.bottom-drawRect.top)/2;
 Center=D3DXVECTOR3(center_x, center_y, 0);

 // 描画
 D3Sprite->Draw(Texture[tex_no]->Tex, &drawRect, &Center, &Trans, color);
}