神代クロ のすべての投稿

コミケ77サークル参加

名称未設定 1今日はコミケにサークル参加してきました。1年ぶりです。

朝8:30くらいに会場に到着。今回は矢絣の風呂敷をテーブルに敷きました。後は簡単な説明の紙を立て掛け、作品を並べてディスプレイ完了。

カイロを2つも装備したのに会場内は物凄く寒く、また徹夜明けで眠かったので、なかなか過酷な感じでした(汗) まあ時間が経つにつれて暖かくはなったけどね。

今回は場所が良かったのか、結構人の流れが多い気がしたな。お陰で手に取ってくれる人や話しかけてくれる人もいつもより多かったよ。そういえば巫女装束の女性「別に巫女なんて興味ないんだからねっ」と言ってウチの作品を買っていってくれましたw

会場でも説明しましたが今回のはまだ未完成品で、しかもバグが残ってます。ギリギリまで粘ったんだけどバグ取れなかったよ。そのうちちゃんと出来たらサイトに差分をアップします。

そんな訳で、来てくれた皆さんありがとうございました。

クリスマス終了のお知らせ

091225_0020322今日はクリスマスイヴなのでケーキを買ってきて、独りで食べました。

そういえば取引先の女子社員に「クリスマスは何か用事があるんですか?」と聞かれたので「今年はクリスマス中止になったらしいよ」と答えておきました。オレ、カッコいいorz

さてケーキだけど、今年もホール単位でしか売ってなかったよ。まぁ年に1回だしいいか。美味しかったけど、食べきれず半分は明日に持ち越しです。

今年もあと1週間か。まだまだやり残した事がたくさんあるから、何とかしないとなぁ。

秋葉原で飲む

今日は秋葉原で飲みました。

秋葉原で飲むのは久しぶりな気がする。クジラ料理が幾つかあったので注文しようとしたら「くじらベーコンしかありません」って言われたよ。まぁ仕方ない。

飲みながらビジネスの話とかしたり。請け仕事は単価が下がる一方だから、やっぱり独立系のビジネス立ち上げなきゃなぁとかそんな。

今年の飲み会はこれで最後かなぁ。

忘年会に参加

今日は取引先の忘年会に参加しました。

飲み屋に行く途中メチャクチャ混んでました。休日前で忘年会シーズンだからなぁ。店の中も順番待ちの人達で溢れかえってたよ。みんな大変だ。

内容はコースメニューのすき焼きでした。すき焼きも久しぶりだなぁ。ただ残念ながら、人数の割に量は少なかった。

帰り。なんかホームで男に声を掛けられたよ。ほろ酔いなその男、雑談を交わしつつも「株に興味ない?」と聞いてくる。胡散臭ぇ(笑) でもいちおうメアド教えといたw どんな素性の男やら。

しかし帰りは終電だったんでこれまた混んでたよ。疲れた。

ゲーム開発32:XAudio2でWaveを再生する2

続きです。今回はWaveファイルを読み込んで解析する処理です。

mmioというマルチメディア入出力関数があるので、それを使って解析すればOKです。

前回のCAudioBaseクラスと今回のCAudioWaveクラスの上にCAudioクラスという緩衝材を入れてますが、ほとんどCAudioBaseと同じなので省略します。

これでようやく音が鳴るようになりました。次はまた当たり判定かなぁ。いい加減当たり判定もFIXしたいところ。

//-----------------------------------------------------------------------------
// 生成
CAudioWave::CAudioWave()
{
 m_pwfx=NULL;
 m_hmmio=NULL;
 m_pResourceBuffer=NULL;
 m_dwSize=0;
}
//-----------------------------------------------------------------------------
// 解放
CAudioWave::~CAudioWave()
{
 Close();

 SAFE_DELETE_ARRAY(m_pwfx);
}
//-----------------------------------------------------------------------------
// オープン
HRESULT CAudioWave::Open(LPSTR strFileName, WAVEFORMATEX* pwfx)
{
 HRESULT hr;

 if (strFileName==NULL) {
  return FALSE;
 }
 SAFE_DELETE_ARRAY(m_pwfx);

 // ファイルオープン
 m_hmmio=mmioOpen(strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ);
 if (FAILED(hr=ReadMMIO())) {
  mmioClose(m_hmmio, 0);
  return FALSE;
 }

 if (FAILED(ResetFile())) {
  return FALSE;
 }

 // ファイルサイズ保持
 m_dwSize=m_ck.cksize;

 return TRUE;
}
//-----------------------------------------------------------------------------
// マルチメディア関数で読み込み
HRESULT CAudioWave::ReadMMIO()
{
 MMCKINFO  ckIn;
 PCMWAVEFORMAT   pcmWaveFormat;

 m_pwfx=NULL;

 if ((0!=mmioDescend(m_hmmio, &m_ckRiff, NULL, 0))) {
  return E_FAIL;
 }

 // Waveファイルかどうか
 if ((m_ckRiff.ckid!=FOURCC_RIFF) || (m_ckRiff.fccType!=mmioFOURCC('W', 'A', 'V', 'E'))) {
  return E_FAIL;
 }

 // FMTチャンク検索
 ckIn.ckid=mmioFOURCC('f', 'm', 't', ' ');
 if (0!=mmioDescend(m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK)) {
  return E_FAIL;
 }

 // pcmWaveFormat取得
 if (mmioRead(m_hmmio, (HPSTR)&pcmWaveFormat, sizeof(pcmWaveFormat))!=sizeof(pcmWaveFormat)) {
  return E_FAIL;
 }

 // 余分なBYTEがある?
 if (pcmWaveFormat.wf.wFormatTag==WAVE_FORMAT_PCM) {
  m_pwfx=(WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX)];
  if (NULL==m_pwfx) {
   return E_FAIL;
  }

  // waveformatexコピー
  memcpy(m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
  m_pwfx->cbSize=0;
 }
 else {
  // 余分なBYTE読み込み
  WORD cbExtraBytes=0L;
  if (mmioRead(m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD))!=sizeof(WORD)) {
   return E_FAIL;
  }

  m_pwfx=(WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX)+cbExtraBytes];
  if (NULL==m_pwfx) {
   return E_FAIL;
  }

  // waveformatexコピー
  memcpy(m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
  m_pwfx->cbSize=cbExtraBytes;

  // 余分なBYTE読み込み
  if (mmioRead(m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), cbExtraBytes )!=cbExtraBytes) {
   SAFE_DELETE(m_pwfx);
   return E_FAIL;
  }
 }

 // FMTチャンクから出る
 if (0!=mmioAscend(m_hmmio, &ckIn, 0)) {
  SAFE_DELETE(m_pwfx);
  return E_FAIL;
 }

 return S_OK;
}
//-----------------------------------------------------------------------------
// サイズ取得
DWORD CAudioWave::GetSize()
{
 return m_dwSize;
}
//-----------------------------------------------------------------------------
// ファイルリセット
HRESULT CAudioWave::ResetFile()
{
 if (m_hmmio==NULL) {
  return CO_E_NOTINITIALIZED;
 }

 // データ検索
 if (-1==mmioSeek(m_hmmio, m_ckRiff.dwDataOffset+sizeof(FOURCC), SEEK_SET)) {
  return E_FAIL;
 }

 // データチャンク検索
 m_ck.ckid=mmioFOURCC('d', 'a', 't', 'a');
 if (0!=mmioDescend(m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK)) {
  return E_FAIL;
 }

 return S_OK;
}
//-----------------------------------------------------------------------------
// ファイルから読み込み
HRESULT CAudioWave::Read(BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead)
{
 MMIOINFO mmioinfoIn;

 if (m_hmmio==NULL) {
  return CO_E_NOTINITIALIZED;
 }
 if (pBuffer==NULL || pdwSizeRead==NULL) {
  return E_INVALIDARG;
 }

 *pdwSizeRead=0;

 if (0!=mmioGetInfo(m_hmmio, &mmioinfoIn, 0)) {
  return E_FAIL;
 }

 UINT cbDataIn=dwSizeToRead;
 if (cbDataIn>m_ck.cksize) {
  cbDataIn=m_ck.cksize;
 }

 m_ck.cksize-=cbDataIn;

 for (DWORD cT=0; cT<cbDataIn; cT++) {
  // BYTEコピー
  if (mmioinfoIn.pchNext==mmioinfoIn.pchEndRead) {
   if (0!=mmioAdvance(m_hmmio, &mmioinfoIn, MMIO_READ)) {
    return E_FAIL;
   }

   if (mmioinfoIn.pchNext==mmioinfoIn.pchEndRead) {
    return E_FAIL;
   }
  }

  // コピー
  *((BYTE*)pBuffer+cT)=*((BYTE*)mmioinfoIn.pchNext);
  mmioinfoIn.pchNext++;
 }

 if (0!=mmioSetInfo(m_hmmio, &mmioinfoIn, 0)) {
  return E_FAIL;
 }

 *pdwSizeRead=cbDataIn;

 return S_OK;
}
//-----------------------------------------------------------------------------
// ファイルを閉じる
HRESULT CAudioWave::Close()
{
 mmioClose(m_hmmio, 0);
 m_hmmio=NULL;
 SAFE_DELETE_ARRAY(m_pResourceBuffer);

 return S_OK;
}

ゲーム開発31:XAudio2でWaveを再生する1

前にXACT3Waveを再生する処理を書きましたが、いちいちWaveファイルを固めるのはメンドくさい。

てな訳で、改めてXAudio2でWaveを再生することにしました。まぁサンプルにそのものずばりな物があるので(XAudio2BasicSound)、それを元にゲームで使える様な物に作り替えます。

基本的な処理の流れは、COMを初期化してXAudio2を使えるようにする。マスターボイスを作ってその中にWaveから取り出したソースボイスを入れる。再生。といった感じです。

今回はXAudio2の部分CAudioBaseクラスだけ記述しました。Waveファイルからデータを取り出す処理は次回。

//--------------------------------------------------------------------------------------
// 生成
CAudioBase::CAudioBase()
{
 for (int i=0; i<MAX_SOUND; i++) {
  pSourceVoice[i]=NULL;
  pXAudioBuffer[i]=NULL;
  pbWaveData[i]=NULL;
 }

 pXAudio2=NULL;
 pMasteringVoice=NULL;
}
//-----------------------------------------------------------------------------
// 解放
CAudioBase::~CAudioBase()
{
 Release();

 // マスターボイス解放
 if (pMasteringVoice!=NULL) {
  pMasteringVoice->DestroyVoice();
  pMasteringVoice=NULL;
 }

 // XAudio解放
 SAFE_RELEASE(pXAudio2);

 // COM解放
 CoUninitialize();
}
//--------------------------------------------------------------------------------------
// 初期化
BOOL CAudioBase::Init()
{
 // COM初期化
 CoInitializeEx(NULL, COINIT_MULTITHREADED);

 // デバッグモードの場合
 UINT32 flags=0;
#ifdef _DEBUG
 flags|=XAUDIO2_DEBUG_ENGINE;
#endif

 // XAudio2生成
 if (FAILED(XAudio2Create(&pXAudio2, flags))) {
  CoUninitialize();
  return E_FAIL;
 }

 // マスターボイス生成
 if (FAILED(pXAudio2->CreateMasteringVoice(&pMasteringVoice))) {
  SAFE_RELEASE(pXAudio2);
  CoUninitialize();
  return E_FAIL;
 }

 return S_OK;
}
//-----------------------------------------------------------------------------
// 解放
void CAudioBase::Release()
{
 // ソースボイス解放
 for (int i=0; i<MAX_SOUND; i++) {
  ReleaseSound(i);
 }
}
//-----------------------------------------------------------------------------
// サウンド解放
void CAudioBase::ReleaseSound(int no)
{
 if (pbWaveData[no]!=NULL) {
  SAFE_DELETE(pbWaveData[no]);
 }
 if (pXAudioBuffer[no]!=NULL) {
  SAFE_DELETE(pXAudioBuffer[no]);
 }
 if (pSourceVoice[no]!=NULL) {
  pSourceVoice[no]->DestroyVoice();
  pSourceVoice[no]=NULL;
 }
}
//--------------------------------------------------------------------------------------
// ファイル読み込み
int CAudioBase::LoadSound(LPSTR szFilename, int loop_flag)
{
 int  i;

 // 空いているWaveがあるか検索
 for (i=0; i<MAX_SOUND; i++) {
  if (pSourceVoice[i]==NULL) {
   break;
  }
 }
 if (i>=MAX_SOUND) {
  return -1;
 }

 // Waveファイル読み込み
 CAudioWave wav;
 if (FAILED(wav.Open(szFilename, NULL))) {
  return -1;
 }

 // Waveファイルのフォーマット取得
 WAVEFORMATEX* pwfx=wav.GetFormat();

 // サイズ計算
 DWORD cbWaveSize=wav.GetSize();

 // メモリにデータを乗せる
 pbWaveData[i]=new BYTE[cbWaveSize];
 if (FAILED(wav.Read(pbWaveData[i], cbWaveSize, &cbWaveSize))) {
  SAFE_DELETE_ARRAY(pbWaveData[i]);
  return -1;
 }

 // ソースボイス生成
 if (FAILED(pXAudio2->CreateSourceVoice(&pSourceVoice[i], pwfx))) {
  SAFE_DELETE_ARRAY(pbWaveData[i]);
  return -1;
 }

 if (loop_flag!=0) {
  loop_flag=XAUDIO2_LOOP_INFINITE;
 }

 // オーディオバッファ設定
 pXAudioBuffer[i]=new XAUDIO2_BUFFER;
 pXAudioBuffer[i]->Flags=XAUDIO2_END_OF_STREAM;
 pXAudioBuffer[i]->AudioBytes=cbWaveSize;
 pXAudioBuffer[i]->pAudioData=pbWaveData[i];
 pXAudioBuffer[i]->PlayBegin=0;
 pXAudioBuffer[i]->PlayLength=0;
 pXAudioBuffer[i]->LoopBegin=0;
 pXAudioBuffer[i]->LoopLength=0;
 pXAudioBuffer[i]->LoopCount=loop_flag;
 if (FAILED(pSourceVoice[i]->SubmitSourceBuffer(pXAudioBuffer[i]))) {
  pSourceVoice[i]->DestroyVoice();
  SAFE_DELETE_ARRAY(pbWaveData[i]);
  return -1;
 }

 return i;
}
//--------------------------------------------------------------------------------------
// サウンド再生
void CAudioBase::PlaySound(int no)
{
 if (no==-1 || pSourceVoice[no]==NULL) {
  return;
 }
 StopSound(no);
 pSourceVoice[no]->FlushSourceBuffers();
 pSourceVoice[no]->SubmitSourceBuffer(pXAudioBuffer[no]);
 HRESULT hr=pSourceVoice[no]->Start(0);
}
//--------------------------------------------------------------------------------------
// サウンド停止
void CAudioBase::StopSound(int no)
{
 if (no==-1 || pSourceVoice[no]==NULL) {
  return;
 }

 pSourceVoice[no]->Stop(0);
}

Thunderbird3のIMAPでGmailを使ってみる

Thunderbird3Thunderbirdがバージョン3.0になりました。見たらIMAPの高速化とかGmailとの連携強化とか書かれてたので、利用してみる事にしました。

ちなみにIMAPが何なのかはよくわかってませんw POPと違い、サーバー上のメールを直接操作出来るって事でいいのかな?

ThunderbirdでGmailのアカウントを設定すると、自動でIMAPのサーバに接続します。しかしGmailには16000通くらいメールがあったので、ダウンロード完了するまで30分くらいかかったよ。

で、未読既読がごちゃごちゃしてたので、全部既読にしようと全選択してから既読を選んだら…なんか完了するまで2時間くらいかかったよ(汗)

これは最初だけなのかな。その後は受信トレイとかクリックすると微妙に固まるけど、まぁ問題ないレベルでした。

Thunderbirdでメール送信したらGmailの送信済みメールに入るし、既読やアーカイブを指定したらそれも反映されるし、良いね。今まではいちいちGmailサイトに行ってやってたからなぁ。

複数のPCで全く同じ環境になるのは良いです。二重ダウンロードとか未読のまま忘れてしまうなんて事がなくなるし。

ただ、いちいちサーバに見に行ってるため、やっぱり重いのは気になるかな。

とにかくしばらく使ってみよう。

※機能を見直してたら「○日分のメッセージをローカルに同期する」って設定があるね。これで最近のだけ受け取れば良かったのか。

※これも後から知ったけど、Shift+Cで一括で既読にできます。ちゃんとマニュアル読まないとダメだね。

エコポイントをEdyで受け取る

9月に地デジテレビを買った際に付いてたエコポイントが、ようやく交換できました。

エコポイント登録サイトでEdyを選択。数週間後にメールが来たので、Edyに投げる用の携帯メールアドレス等の登録をしました。

それから数週間後、EdyギフトIDが届きました。しかしよく考えてみたら、Edyを持っていない事に気づきw 知人のアドバイスを元にANAマイレージクラブのEdy付きを申し込む。

それからさらに数週間後、ANAからカードが送られてきたので、それを使っておサイフケータイのEdyを登録、ようやくエコポイントをゲットできました。

長かった。Edyはコンビニで使えるから、たぶん効率が良いね。

…あれ? EdyはJCBのクレジットカードが登録できないぞorz

ゲーム開発30:坂道との当たり判定

坂道との当たり判定だいぶ間があいたけど、いくつかの処理を追加しました。

マップチップをシンプルに
ドット絵をあれこれいじくり回してたけど、結局シンプルな形にしてしまいました。地味だけど仕方ない。そのうちマップチップを増やして、奥行きを表現したいです。

縦スクロール対応
今までは横スクロールしかしませんでしたが、マップエディタ導入を機にマップサイズを可変にし、縦にもスクロール出来るようにしました。横と違い、staticな変数を持って、ゆっくりスクロールするようにしてます。縦が激しいと酔う。

坂道に対応
坂道を上り降り出来るようになりました。方法は線分の交差判定を使ってます。キャラクタの足元を横一直線の線分とし、坂道の線分との重なりで当たり判定を取っています。この方法なら複雑な地形も簡単に作れるなぁ。実装はネット上にあったコードを参考に組んでます。

処理落ち(汗)
大した事してないはずなのに処理落ち(フレームスキップ)が起きてました。ちなみに50fpsだと大丈夫なのに、60fpsだと処理落ち。もしかしたら単にフレームレートの計算ミスの可能性もあるけど、何にしても原因を特定しなきゃなぁ。

引き続き坂道の処理を作ります。実はまだちょっと挙動がおかしい。

//-----------------------------------------------------------------------------
// 交差判定
BOOL CField::CrossLine(POINT p1, POINT p2, POINT q1, POINT q2)
{
 float A, B, C, D;
 BOOL ret=TRUE;

 A=(float)(p2.y-p1.y);
 B=(float)(p1.x-p2.x);
 C=-(A*p1.x+B*p1.y);
 D=(A*q1.x+B*q1.y+C)*(A*q2.x+B*q2.y+C);

 if (D>0) {
  ret=FALSE;
 }
 else {
  A=(float)(q2.y-q1.y);
  B=(float)(q1.x-q2.x);
  C=-(A*q1.x+B*q1.y);
  D=(A*p1.x+B*p1.y+C)*(A*p2.x+B*p2.y+C);

  if (D>0) {
   ret=FALSE;
  }
 }
 return ret;
}