PDAのひとりごと

黄昏時、携帯情報端末は薄闇の向こうに何を見るのか

ラジェンダ版アロウス

2004-08-30 23:40:27 | PDA
前々から話だけで形のなかったカシオペア・ラジェンダ版、ようやく動くようになったので、とりあえずβ版公開です。

http://tshibuki.hp.infoseek.co.jp/sample/arrousBE500b1.zip

画面サイズを大きくして、ラジェンダの本体で音がなるようにしてあります。
本体とヘッドフォンとで鳴る音が違うため、片方ずつON/OFFできるようにしてあります。

PPC版もこれと同じ画面構成にしていますが、その為、同じ実行ファイルをHPCで動作させた場合の画面構成がおかしくなっています。この辺を修正することと、白黒画面対応が当面の目標かな?

CEとPC

2004-08-24 23:29:50 | PDA
CEのプログラムは、少しの変更でPCのプログラムとして動作させられるはず・・・ということで、ちょっと土日にトライしてみたのですが、結構引っかかりました。

CEの方はUNICODEなので、文字列操作関数はそれを前提に作っていますが、PCの方ではそうとも限らないので、とりあえず両方で使える文字列関数を使うようにしているのですが、意外と両方で使えるというのがなく、結局そこは書き換えてしまいました。

また、sndSoundPlayがXpで使えないようだったので、これもPlaySoundに変更しました。そして、画面は240x480の校正では小さすぎるため、結局この変更に1日かかってしまいました。

このソースから逆にラジェンダ版とPPC版の画面構成を考えようと思っています。

夜の訪問者

2004-08-18 23:59:12 | Weblog
今夜は網戸にコガネムシが来た。
ということで、撮影しようとしたら逃げられそうになったので、部屋へご招待。

色からするとドウガネブイブイかな?
検索をかけると、どうも害虫として有名らしい。

写真撮影が済んだら、お帰りいただいた。

ラジェンダとサウンド

2004-08-18 00:15:48 | PDA
BE500で音が鳴らないというのが懸案事項でしたが、SDKのヘルプを見ると『ラジェンダにはスピーカーがないので音は鳴らない』のだそうです。
では、内蔵ソフトのあの音は何かというと、どうやらあれはスピーカーの音ではなくブザー音のようです。

WAVファイルは、本体では鳴らなくても、ヘッドホンをつなぐと聞こえます。

そこで、選択肢は2つ、ヘッドフォンでサウンドは聞けるのでこのままでラジェンダ対応と謳ってしまう、もしくは、本体だけでも鳴るようにする、です。

実は、本体はブザー音、ヘッドホンからはサウンドが鳴るものを作ってしまいました。ヘッドホンとブザー別々にON/OFFできるようにもしています。

ただ、その後、どうせ手を加えるのならということで、画面サイズをあわせようとして、現在はまり中です。単純に1.3倍に拡大するとモアレが出て画面が汚くなるので、キャラクタそのものを大きくする予定です。

あと、モノクロ版も作りたいな。

本日、CASSIOPEIA for DoCoMo (MIPS/CE2.11/PsPC)と
HITACHI PERSONA HPW-200JC (SH3/CE2.0/HPC)にて動作確認しました。

ほとんどのCE機で動作するようです。

CE用落ち物ゲーム「アロウス」更新

2004-08-15 18:20:01 | PDA
今日は1日涼しかったので、アロウスの修正を行いました。

シグマリオン3で、遅すぎてゲームにならないという不具合があったのですが、今回修正しました。
これは、機種毎にサイズを調整して画面表示していたのですが、どうもその部分が遅かったらしく、サイズ調整を実数演算から整数値に変更したところ充分実用的な速度とすることができました。

オフの時、みっきゅんが提案してくれた、キー入力のリピート設定をオプションとして実装しました。連続入力にするか単発入力にするかが、キー毎に設定できます。

カシオペア・ラジェンダで音が鳴らないのは、どうも仕様のようで、SDKには専用のAPIがあるのを見つけました。しかし、使い方が良く分からないため、要望があるまで保留とします。

アロウスv1.01

セミと野鳥

2004-08-14 10:53:13 | Weblog
今朝はミンミンゼミの鳴き声で目が覚めました。
時計を見て6時半だと思い起きたのですが、その実5時半でした。

早起きは3文の得と言いますが、おかげで可愛らしい緑色の鳥を見ることができました。
最初はメジロかと思ったのですが、目の周りの白い部分がありません。
調べてみると、センダイムシクイという鳥が似ているような気がするのですがどうでしょうか?

デジカメの3倍ズームではこの程度しか撮れませんでした。

ミニオフ

2004-08-14 10:01:42 | Weblog
昨日はアキバでミニオフでした。
待ち合わせ前に本を買ってしまい、その後、DVD-Rを20枚買ったため、かばんが重くて仕方がありませんでした。(汗

アキバついたときに、黒クマ(黒塗りのポポペ)を使っている方を見かけたのですが、あの黒クマ、某サイトでプレゼントされたものではないでしょうか?

後になって声をかけなかったことを後悔しました。
いえ、それを確認したからどうということもないのですが・・・最近ポポペ使いも見かけなくなってしまったので、お友達になりたいなと。(゜゜;)\(--;)オイオイ

だいたい、黒クマに目が行ってて、オーナーがどんな人物だったかも見ていないというこのバカさ加減、自分でもあきれます。

ポポペのプロ~10.得点をつけよう

2004-08-13 07:04:27 | Lesson
 ゲームなのだからスコアぐらい欲しいものですよね。最初からそのつもりで数字の絵も用意してあるのですから、早速スコアを付けましょう。
 まず変数です。スコアを保持するためにグローバル変数として iScore を作りましょう。

int iScore;


 変数は初期化しなくてはなりません。例によって初期化はWM_CREATEが通知されたときの処理 DoCreateMain 関数の中になります。また、この時にスコアも表示してしまいます。スコア表示は少し手間がかかるので、関数にまとめてしまいましょう。GmDispScore関数がそれです。

iScore = 0;             // スコア初期化
GmDispScore();          // スコア表示


 スコアは、インベーダーを撃墜したときに増やします。つまり、砲台の弾の移動処理であるGmMoveTamaHou関数の中の当たり判定の中でカウントアップする事になります。

        if ((posTamaHou.x == posInv.x) && (posTamaHou.y == posInv.y)) {
	    PatBlt( hdcScreen,          // 対象のHDC
	        posTamaHou.x,           // 表示位置 X座標
	        posTamaHou.y,           // 表示位置 Y座標
	        32,                     // 表示サイズ 幅
	        24,                     // 表示サイズ 高さ
	        WHITENESS );            // 白で塗りつぶす
            posInv.x = 320 - 32;
            posInv.y = 24;
            posTamaHou.x = -1;          // 表示終了
            iScore++;                   // スコア+1
            GmDispScore();              // スコア表示
        }


 今回は、これ以外に得点追加となるものがないため、後は表示処理だけです。スコアは、下2桁だけ表示します。

void GmDispScore(void)
{
    int a, b;

    a = iScore / 100;        // 1234 / 100 = 12
    b = iScore - a * 100;    // 1234 - 12*100 = 34
    a = b / 10;              // 34 / 10 = 3
    b -= a * 10;             // 34 - 3*10 = 2

    BitBlt( hdcScreen,       // 転送先HDC
        104,                 // 表示位置 X座標
        0,                   // 表示位置 Y座標
        16,                  // 表示サイズ 幅
        24,                  // 表示サイズ 高さ
        hdcBmp,              // 転送元HDC
        a*16,                // 転送元 X座標
        0,                   // 転送元 Y座標
        SRCCOPY );           // そのまま転送
    BitBlt( hdcScreen,       // 転送先HDC
        104+16,              // 表示位置 X座標
        0,                   // 表示位置 Y座標
        16,                  // 表示サイズ 幅
        24,                  // 表示サイズ 高さ
        hdcBmp,              // 転送元HDC
        b*16,                // 転送元 X座標
        0,                   // 転送元 Y座標
        SRCCOPY );           // そのまま転送
}


 これでスコアは表示されるのですが、今のままではコマンドバーに隠れて見えません。そこで、コマンドバーを表示しないようにしてしまいます。
 まずは、DoWmCreateの最初の部分にある3行がコマンドバーを作成している部分なので、これをコメントアウトします。

//    hwndCB = CommandBar_Create(hInst, hWnd, 1);
//    CommandBar_InsertMenubar(hwndCB, hInst, IDM_MENU, 0);
//    CommandBar_AddAdornments(hwndCB, 0, 0);


 次に、InitInstanceの最後の部分に、コマンドバーを表示する部分があるのでこれもコメントアウトします。

//    if (hwndCB)
//        CommandBar_Show(hwndCB, TRUE);


 最後に、WndProcのWM_DESTROY通知の処理の中にコマンドバーを破棄する処理があるので、これを消して終わりです。

//            CommandBar_Destroy(hwndCB);


 さて、これでコマンドバーが消えたのですが、今度はコマンドバーにあった「アプリケーションの終了」がなくなってしまいました。そこで、ESCキー(ポポペの「もどる」キー)で終了するように処理を追加します。

 WndProcのWM_KEYDOWNの処理の中で、ESCキーを判定してプログラムを終了するようにします。

        case WM_KEYDOWN:
            wKey = wParam;
            if (wParam == VK_ESCAPE) {
                DestroyWindow(hWnd);
            }
            break;


 これでようやくスコア表示できるようになりました。スコアが表示されるとずいぶんゲームらしくなりますね。

ポポペのプロ~9.当たり

2004-08-12 10:45:47 | Lesson
 弾がインベーダーに当たれば得点となるのがこのゲームのルールです。ということで、当たるようにしましょう。
 まずは変数を用意します。

int iStateHou;                          // 砲台表示状態


 砲台の弾の移動処理の中で当たったかどうかの判定を入れます。
void GmMoveTamaHou(void)
{
    if (posTamaHou.x == -1) {           // 表示中ではない
        return;
    }

    PatBlt( hdcScreen,                  // 対象のHDC
        posTamaHou.x,                   // 表示位置 X座標
        posTamaHou.y,                   // 表示位置 Y座標
        32,                             // 表示サイズ 幅
        24,                             // 表示サイズ 高さ
        WHITENESS );                    // 白で塗りつぶす

    posTamaHou.y -= 24;                 // 上へ昇る

    if (posTamaHou.y <= 0) {            // 上端を越えた時
        posTamaHou.x = -1;              // 表示終了
    } else {
        BitBlt( hdcScreen,              // 転送先HDC
            posTamaHou.x,               // 表示位置 X座標
            posTamaHou.y,               // 表示位置 Y座標
            32,                         // 表示サイズ 幅
            24,                         // 表示サイズ 高さ
            hdcBmp,                     // 転送元HDC
            0,                          // 転送元 X座標
            0,                          // 転送元 Y座標
            SRCCOPY );                  // そのまま転送
        if ((posTamaHou.x == posInv.x) && (posTamaHou.y == posInv.y)) {
	    PatBlt( hdcScreen,          // 対象のHDC
	        posTamaHou.x,           // 表示位置 X座標
	        posTamaHou.y,           // 表示位置 Y座標
	        32,                     // 表示サイズ 幅
	        24,                     // 表示サイズ 高さ
	        WHITENESS );            // 白で塗りつぶす
            posInv.x = 320 - 32;
            posInv.y = 24;
        }
    }
}


 弾とインベーダーの大きさが異なる場合や、移動量が異なる場合、当たり判定はもっと複雑になりますが、今回はキャラクタのサイズを規定して、移動量もそれにあわせているため、弾の座標値とインベーダーの座標値が一致しているかどうかで当たりの判定が行えます。
 次に、インベーダーの弾の移動処理の中に砲台との当たり判定を入れます。こちらも同様に、弾の座標値と砲台の座標値との比較で当たったかどうかの判定を行います。

void GmMoveTamaInv(void)
{
    PatBlt( hdcScreen,          // 対象のHDC
        posTamaInv.x,           // 表示位置 X座標
        posTamaInv.y,           // 表示位置 Y座標
        32,                     // 表示サイズ 幅
        24,                     // 表示サイズ 高さ
        WHITENESS );            // 白で塗りつぶす

    posTamaInv.y += 24;         // 下へ落ちる

    if ((posTamaInv.x == posHou.x) && (posTamaInv.y == posHou.y)) {
        iStateHou = 1;
        posTamaInv.x = posInv.x;        // 表示終了
        posTamaInv.y = posInv.y + 24;
    }

    if (posTamaInv.y >= 240-24) {       // 下端を越えた時
        posTamaInv.x = posInv.x;        // 表示終了
        posTamaInv.y = posInv.y + 24;
    }

    BitBlt( hdcScreen,          // 転送先HDC
        posTamaInv.x,           // 表示位置 X座標
        posTamaInv.y,           // 表示位置 Y座標
        32,                     // 表示サイズ 幅
        24,                     // 表示サイズ 高さ
        hdcBmp,                 // 転送元HDC
        0,                      // 転送元 X座標
        0,                      // 転送元 Y座標
        SRCCOPY );              // そのまま転送
}


 インベーダーの方は、弾が当たってもゲームが継続するので特別な処理は不要ですが、砲台は3台破壊されると終わりなので、その処理が必要となります。そこで、弾が砲台に当たったときにステータスを変更し、後でそのステータスを判定して砲台が破壊されたときの処理を行うようにします。
 WM_TIMERが通知されたときに弾とインベーダーが動いています、砲台が爆発している間はこれらを一時的に止めてしまいます。

case WM_TIMER:
    switch (iStateHou) {
    case 0:                     // ゲーム中
        GmMoveInv();
        GmMoveTamaInv();
        GmMoveTamaHou();
        GmMoveHou();
        break;
    case 1:                     // 破壊
        GmDestroyHou();
        break;
    }
    InvalidateRect(hWnd, NULL, FALSE);
    break;


 砲台が破壊されたときは、少しだけ爆発を表現してみます。二つの絵を交互に表示するとそれらしく見えることでしょう。枚数を増やせばもっと違った爆発も表現できますが、それは各自考えてみてください。

void GmDestroyHou(void)
{
    static int iInvTime = 0;

    iInvTime++;

    if (iInvTime % 2) {

        if (iInvTime > 10) {
            iInvTime = 0;
            posHou.x = 0;       // 表示位置 X座標
            iStateHou = 0;      // 元の処理へ戻す
        }

        BitBlt( hdcScreen,      // 転送先HDC
                posHou.x,       // 表示位置 X座標
                posHou.y,       // 表示位置 Y座標
                32,             // 表示サイズ 幅
                24,             // 表示サイズ 高さ
                hdcBmp,         // 転送元HDC
                64,             // 転送元 X座標
                24,             // 転送元 Y座標
                SRCCOPY );      // そのまま転送
    } else {
        PatBlt( hdcScreen,      // 対象のHDC
            posHou.x,           // 表示位置 X座標
            posHou.y,           // 表示位置 Y座標
            32,                 // 表示サイズ 幅
            24,                 // 表示サイズ 高さ
            WHITENESS );        // 白で塗りつぶす
    }
}


 さて、ここまで変更したらビルドしてみましょう。
 さきほど、砲台が3台破壊されるとゲームが終わると言いましたが、実は、まだ終わりの処理が入っていません。砲台の数も設定していないし、残機数の表示もしていないからです。それらは、もう少し先で実装します。その前に、次回は得点の表示を追加しましょう。


CE用落ち物ゲーム「アロウス」正式リリース

2004-08-11 10:59:58 | PDA
今日は曇ってて涼しかったので、プログラムがはかどりました。
という訳で、機種毎の画面サイズも調節し、画像もボカシを
入れて(苦笑)正式版としました。

カシオペア・ラジェンダで音が鳴らないのと、
シグマリオン3で動作が遅くなる症状は原因不明ですが、
SDKを使っていないのでまだ何ともいえません。

ラジェンダはともかく、シグ3はSDKを持っているので、
後ほどEVT4を使ってビルドしなおしてみます。

ダウンロードはこちらから→アロウスv1