「Ajaxでエロゲーを作るブログ」[ゲーム][DHTML][XML][ねこみみか](2)/XMLの連結

「Ajaxでエロゲーを作るブログ」[ゲー

 ねこみみか第2話。


ややエロだぞ!


 複数XMLファイルへの対応を行いました。


00000000.xml

<?xml version="1.0" encoding="UTF-8" ?>
<pages>
    <page>
        <character>Lecan03.gif</character>
        <background>BG03.jpg</background>
        <text>ねこみみか (2)</text>
    </page>
<!-- 略 -->
    <page>
        <character>Lecan01.gif</character>
        <text>レカン:わらわの名はレカンじゃ。この名も、そなたの知る女性に似せて付けられたのであろう。心証を悪くするでないぞ。</text>
        <next>00000001.xml</next>
    </page>
</pages>


 「次のXML」を<next>タグで指定。
 これがセットされていたらJavaScriptでこのXMLファイルを読み込むようにしました。


main.js

// ...
    // <next>の中身を取得します。
    if( pageElement.getElementsByTagName( "next" ).length != 0 )
    {
        page.nextXmlUrl
            = pageElement.getElementsByTagName( "next" )[0].childNodes[0].nodeValue;
    }
    else
    {
        page.nextXmlUrl = null;
    }

    // インデックスナンバーを進めます。
    page.nextIndex = index + 1;
    if( page.nextXmlUrl != null )
    {
        page.nextIndex = 0;
    }
    else if( page.nextIndex == ajax.responseXML.documentElement.getElementsByTagName( "page" ).length )
    {
        page.nextIndex = 0;
    }
// ...

// 「読み込むXML」を格納するグローバル変数。
var nextXmlUrl = "00000000.xml";

// ...

                // 次の読み込み先。
                if( page.nextXmlUrl != null )
                {
                    nextXmlUrl = page.nextXmlUrl;
                }


 これで、シーン毎にXMLファイルを分けられるようにしました。
 分岐とかもこの辺で分けられるようにしたいな。
 あともうひとつ、キャラクターの非表示時に、一度透明GIFに置き換えるようにしました。

main.js

                        // offの時は非表示に。
                        characterObj.src = "Opa.gif";
                        characterObj.style.visibility = "hidden";

 そうしないと、次の表示時に前のイメージが出ちゃうんで。


 次はメッセージウィンドウの非表示化だな。
 なんせ、次は一枚絵が出てくるんで……。

(1)/キャラ非表示/キー入力

「Ajaxでエロゲーを作るブログ」[ゲー

 「ねこみみか」というシリーズものを開始しました。


やっとゲームらしくなったね


 技術的には、キャラの非表示と、キー入力に対応しました。

  • キャラクターの非表示


00000000.xml

<?xml version="1.0" encoding="UTF-8" ?>
<pages>
<!-- 略 -->
    <page>
        <character>off</character>
        <background>BG02.jpg</background>
        <text>そして恋歌は家に帰り、俺は誰もいない家に着く。</text>
    </page>
<!-- 略 -->
</pages>


 <character>タグでoffを指定すると、キャラを消せるようにしました。
 これと同時に背景を一枚絵にすると、一枚絵の表示になるとゆー。
 キャラクターの表示・非表示は、対象オブジェクトのstyle.visibilityプロパティにvisible/hiddenをセットすることで行えます。


main.js

                // キャラ。
                if( page.characterUrl != null )
                {
                    // イメージ置き換え先の取得。
                    var characterObj = document.getElementById( characterObjId );
                    if( page.characterUrl.indexOf( "off" ) == 0 )
                    {
                        // offの時は非表示に。
                        characterObj.style.visibility = "hidden";
                    }
                    else
                    {
                        // イメージを置き換えます。
                        characterObj.src = page.characterUrl;
                        characterObj.style.visibility = "visible";
                    }
                }


 つか、JavaScriptって、JavaのString#equals()に当たるメソッドってないんか?(汗)
 indexOf()で比較したけど、前方一致だからちょっと不安だな。うーむ。

  • キー入力すると進むようにする。

 スペースキー、←、→を押すと進むようにしました。
 なんかこれがえらいめんどかった。


main.js

/**
*   キーが押された時に呼び出されるイベントハンドラです。
*/
function onKeyPressNext( e )
{
    var keyCode = null;
    if(document.all)
    {
        // IE6の場合。
        keyCode = event.keyCode;
    }
    else
    {
        // FireFoxの場合。
        keyCode = e.which;
    }

    // スペースキー、←、→の場合に次へとスキップします。
    if( ( keyCode == 32 ) ||
        ( keyCode == 37 ) ||
        ( keyCode == 39 ) )
    {
        next();
        return false;
    }
}

// イベントハンドラとしてセットします。
document.onkeypress = onKeyPressNext;


 まずイベントハンドラのセットは、document.onkeypressプロパティにイベントハンドラとなるメソッドを渡すことで行います。
 そうすると、キー入力時に指定したメソッドが呼ばれます。
 メソッドでは引数ひとつ持たせます……が、この引数というか、キー入力の内容が格納されている変数がIE6とFireFoxとでことなるので、そのあたりを吸収しています。
 よくわからんが、document.allがあるとIE6らしい?
 あと、このイベントハンドラでfalseを返せば、ブラウザ上での処理はされません。普通ならスペースキーを押すと下にスクロールするけど、それもされないです。
 IMEっぽい処理をしてるプログラムは、こういうふうにしてるんかな。


 とりあえずこれでかなりゲームっぽい感じに。
 他にしたいのはこんなとこかな。

  • メッセージウィンドウの表示・非表示切り替え。
  • 分岐まわり。

 分岐まわりは結構大変そうだなぁ。ウィンドウ表示はできるけど、そのあたりをXML側で定義するのが面倒そう。

背景の置き換え。

「Ajaxでエロゲーを作るブログ」[ゲー

 背景も置き換えられるようにしました。


ゲームって便利よね……


00000000.xml

<?xml version="1.0" encoding="UTF-8" ?>
<pages>
    <page>
        <character>g.gif</character>
        <background>BG01.jpg</background>
        <text>恋歌:外……。</text>
    </page>
    <page>
        <text>恋歌:あっという間に……。</text>
    </page>
    <page>
        <character>e.gif</character>
        <background>BG02.jpg</background>
        <text>恋歌:玄関!</text>
    </page>
</pages>


 <character>タグでキャラクターの画像を、<background>タグで背景画像を指定するようにしました。
 これを、キャラの画像と同じ方法で置き換えています。


 つか、今回はCSSでの細かい調整がメイン。

  • クリック用の「トップスクリーン」が、IE6だと機能しない

 クリック用の「トップスクリーン」が、IE6だとちゃんと機能しなかった。
 「何もない」とダメだったみたいで、背景色を指定して、その上で透明度を最大に。


main.css

/** トップスクリーン(クリック用) */
div.topscreen
{
    position: absolute;

    left: 20px;
    top: 0px;

    width: 600px;
    height: 400px;

    filter: alpha( style=0, opacity=00 );
    -moz-opacity: 0.00;
    background: #FFFFFF;

    z-index: 50;
    overflow: visible;
}


 これで、IE6でも、ゲーム画面のどこをクリックしても進むようになりました。

  • メッセージフレームがIE6とFireFoxで大きくずれる。

 IE6がpaddingをwidthに含むのに対して、FireFoxは含まずwidth+paddingが実際の横幅になるんで、paddingを使用せず、内側の実際にテキストを出力する部分にmarginをセット。

  • 背景の出力位置がずれる。

 背景の出力位置の基準がIE6とFireFoxでこれまたずれてた。
 absoluteにするとちゃんとうまくいくんで、横線以下も<div>で囲んで全部absoluteに(爆)。


 ここまでやって、だいぶIE6とFireFoxとで近づきました。
 微妙に違う所もあるけど、まぁこのくらいなら問題ないでしょ。


 当面の課題。

  • キャラクターの画像を消して、背景を一枚絵にできるようにする。
  • キャラクターの画像のサイズを属性として持たせて、それに合わせて出力位置を変えるようにする。

 各画像のサイズ合わせたりとかが思いの外面倒なことに気付き始めた……。

CSSで透明度変更。

[CSS][ゲーム]CSSで透明度変更。

 エロゲーっぽくしてみました。


クリッククリック!

 スタイルシートをいじってエロゲーっぽい構成に。


index.html

<DIV class="background"> </DIV>
<DIV class="caracter">
<IMG ID="character" SRC="e.jpg"><BR>
</DIV>
<DIV class="message_window_background"> </DIV>
<DIV class="message_window_frame">
    <DIV ID="maintext">このへんクリックしてね</DIV><BR>
</DIV>
<DIV class="topscreen" onClick="next( 'character', 'maintext' ); return false;"> </DIV>


 メッセージウィンドウの透明度は、IEFireFoxで違うので両方設定。


main.css

/** メッセージウィンドウ(背景) */
div.message_window_background
{
    position: absolute;

    left: 20px;
    top: 300px;

    width: 600px;
    height: 100px;

    filter: alpha( style=0, opacity=70 );
    -moz-opacity: 0.70;

    z-index: 2;
    overflow: visible;

    background: #FFFFFF;
}


 IEはfilterで、FireFoxは-moz-opacityで設定。


 あと、「ゲーム画面全体のどこでクリックしてもテキストが進む」ように、<DIV class="topscreen">を全体にはっつけました。


main.css

/** トップスクリーン(クリック用) */
div.topscreen
{
    position: absolute;

    left: 0px;
    top: 0px;

    width: 600px;
    height: 400px;

    z-index: 5;
    overflow: visible;
}


 これをonClickにしてるんで、ゲーム画面のどこをクリックしても進みます。将来的にはキーを押した時にも進めるようにしたいな。

スタイルシートで背景とキャラを重ねる。

[CSS]スタイルシートで背景とキャラを


むかつくー!!

 スタイルシートを使って、レイヤーのように背景の上にキャラを重ねてみました。


index.html

<DIV class="background">
<IMG ID="background" SRC="1.jpg" BORDER="0"><BR>
</DIV>
<DIV class="caracter">
<IMG ID="character" SRC="2.gif"><BR>
</DIV>

 背景、キャラ共に<DIV>で囲んであります。
 んでこれをスタイルシートで重ねます。


main.css

/** キャラクター */
div.caracter
{
    position: absolute;

    left: 100px;
    top: 0px;

    z-index: 1;
    overflow: visible;
}

/** 背景 */
div.background
{
    position: relative;

    left: 0px;
    top: 0px;

    z-index: 0;
    overflow: visible;
}

 背景の方はpositionをrelativeでかつz-indexを0に。
 キャラの方はpositionをabsoluteでかつz-indexを1に。
 これで重なります。


 ただ、キャラの画像は透過GIFにしないとまわりを透明にできないです。
 PNGでも試したんだけど、IE6だと透過しないです。FireFoxならちゃんと透過されるんだけど。IE7ではサポートされるみたいだけど、IE7が浸透するまで待つ……のは無理なんで、とりあえずGIFしかないなー。アンチエイリアシングまわりが面倒そうだ……。

XML内にエレメントがない場合の処理。

[JavaScript][XML][ゲーム]XML内にエレ


むかつくー!!

 今回は以下のような修正をしました。

  • XMLの情報を変数として返す。
  • <image>タグがない場合にはこれまでの画像をそのままセットする。

 オブジェクト指向っぽく、と、XML記述を楽にするために、ってことで。
 まず、XMLの方はこんな感じ。


00000000.xml

<?xml version="1.0" encoding="UTF-8" ?>
<pages>
    <page>
        <image>f.jpg</image>
        <text>恋歌:むかつくー!!</text>
    </page>
    <page>
        <text>恋歌:むかつくむかつくむかつくー!!</text>
    </page>
<!-- 略 -->
</pages>


 2番目の<page>タグには、<image>タグがありません。
 こういう「省略記法」ができるように、というのが今回の修正の理由。
 <image>タグがあるかどうかのチェックはこんな感じ。


main.js

function getPage( ajax, index )
{
    var page = new Object();
    
    // <page>を取得します。
    var pageElement
        = ajax.responseXML.documentElement.getElementsByTagName( "page" )[index];

    // <image>の中身を取得します。
    if( pageElement.getElementsByTagName( "image" ).length != 0 )
    {
        page.imageUrl 
            = pageElement.getElementsByTagName( "image" )[0].childNodes[0].nodeValue;
    }
    else
    {
        page.imageUrl = null;
    }

// ...

    return page;
}


 タグがなければgetElementsByTagName()メソッドの戻り値の配列が、要素数0になるんでそれをチェック。
 それにしても、JavaScriptって不思議だなぁ……。
 とりあえず、メソッドなしの構造体みたいなオブジェクトを作る場合は、次のようにするらしい。

  • new Object()してとりあえずオブジェクトを作る。
  • プロパティは宣言の必要なし。アクセスすれば作られる。
  • 別に指定しなくても関数は戻り値を返せる。

 ……うう、「オブジェクト」を「インスタンス」、「プロパティ」を「フィールド」って言いてぇ(汗)。
 まぁとりあえずこれでタグの有無をチェックできることがわかったんで、たとえば<next_page>ってタグを作って00000001.xmlみたいに書いておくと次はそっちを読むとかできるな。
 さらに、背景用タグとか、選択肢用のタグ、画面エフェクト用タグもあとで追加するようにしていきましょう。

トップイメージ更新

「Ajaxでエロゲーを作るブログ」トップ


み、見んなっ!!

 やっとこさちゃんとしたトップイメージを描きました。
 Google Mapとかで速くスクロールすると「画像読み込み中」のパネルが表示されるのを真似てみました。ドラッグしても下は見えません(爆)。
 キャラは看板娘の恋歌。
 ツールはAdobe Photoshop CS1.0。タブレットでがりがり描きました。所要時間3時間。もちっと細かいところまで詰めれば良かったかな……髪の質感がよちょっと良くないな。
 まぁこれまで何もなかったんでとりあえずってことで。なんかエロゲーっぽいし(爆)。