スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

JSゲームエンジンMibbuのソースを読む

簡単なアクションゲームを作ろうかと思ったのだが、その前にJavaScriptゲームエンジンについて調べることにした。

ソースが読める程度の小規模エンジンを探して、見つけたのがMibbu
Mibbu, HTML5 javascript game framework, canvas, DOM
圧縮後のファイルサイズは5.59KB。圧縮前でも25.8KB。
作者はポーランドの人みたいだ。

提供している機能は、メインループ、キャラクター画像、背景画像の管理。
HTML5 Canvasを使うか、DOMを使うかを設定できる。DOMを使う場合はCSS3アニメーションをキャラクターに設定できる。
キャラクターの移動のほかに、背景画像の移動も設定できる。
キャラクターの衝突判定機能もある。

小規模アクションゲームとしては十分かなと思ったが、登録したキャラクターの削除はできない。
パラメータを変えて非表示にすればいいだけだが、オブジェクトをうまく再利用する必要がありそう。

ソースコードを読んで参考になったこと
・return this でメソッドチェーンを可能に
・単項プラス演算子で数値変換
  var newTime = +(new Date());
これでDateをNumberに変換している。
・背景画像の360°任意方向へのスクロール
CSSのbackground-positionを算出しているだけだが、自分はやったことが無かったので参考になった。
・CSSアニメーションを動的に設定する方法

ほかにも細かいところでいろいろと参考になった。
他のゲームエンジンも調べてみるかな。
スポンサーサイト

サイコロを改造してチンチロリンで敵と戦うゲームを公開した

久しぶりにゲームを作った。

バトルdeチンチロリン
バトルdeチンチロリン タイトル

チンチロリンで敵と戦うゲーム。
バトルdeチンチロリン 戦闘画面

敵を倒して得たお金でサイコロを改造できる。
バトルdeチンチロリン 改造画面

あの456サイも作れる。
バトルdeチンチロリン サイコロ一覧


今回はボタンもHTML5 Canvasで作った。バインドしたイベントはCanvasのクリックイベントだけ。
レベルデザインと言うか、難易度調整に苦労した。サイコロを改造するとプレイヤーが強くなりすぎるため、高レベルの敵も改造サイコロを使用するようにした。
なるべく説明がなくてもわかる画面にしたかったが、改造画面がどうもわかりにくい気がする。

セーブデータはWeb Storageに保存しているので、IE7以下ではセーブできない。データ量はたいしたことないので、cookieに保存するようにもできるがどうしようか。

JavaScriptゲームエンジンもどきを作ろうとする

前のエントリで「LimeJSを使ってゲームを作ろうかな」と書いたのだが、細かいところ(Canvasの一部だけ更新するなど)で自分のやりたいことと合わなそうだ。
そこで、以前作ったCanvasアニメーション用ライブラリを修正してゲームエンジンもどきを作ることにした。

以前作ったライブラリの機能はこんな感じ
・メインループを管理(ループの開始、停止、fpsの設定など)
・Canvasのプロパティを管理(サイズやcontextなど)
・Canvasに表示するエンティティを管理
ループするたびに各エンティティのdrawメソッドを実行する。
エンティティの実装はライブラリ外で行う。

これに、以下の機能を追加することにした
・Canvasではエンティティではなくシーンを管理
・各シーンごとに、シーンに表示するエンティティを管理
・Canvasで発生したイベント(とりあえずクリックイベントのみ)を、エンティティに振り分ける
ループするたびに、現在のシーン配下のエンティティのdrawメソッドを実行する。
既存ライブラリでは、画面を変えるときはエンティティを入れ替える必要があったが、シーンを切り替えるだけで済む。
Canvas内で表示するボタンなどのイベントも、シーンを切り替えることで対応できる。

細かいテストはまだだが、ボタンを押して画面を切り替える動作確認はできた。
メインループを開始してアニメーションを行うこともできた。
ボタンやテキストのエンティティを作成するクラスもライブラリに組み込んだ。

「いろいろある軽量JavaScriptゲームエンジンの劣化版」という感じだが、とりあえずこの自作ゲームエンジンをブラッシュアップしながらゲームを作ってみよう。
それからほかのゲームエンジンを使ったりソースを読んだりすれば、また別の発見があると思う。

JavaScriptゲームエンジンについて調べてみたが・・・

先日のエントリで書いた囲碁プログラムの修正が一段落したので、HTML5でゲームでも作ろうと思った。
単純なゲームにするつもりだが、フレームワークというかゲームエンジンを使ってみよう。
ゲームエンジンについては半年前にちょっと調べたのだが、改めて調べてみることにした。

検索して見つけたのがこれ
List of JS game engines
このページだと右が切れていて、wikiページでもコメントが切れていたので、markdownファイルをダウンロードしてコメントを読んだ。
読んだのだが・・・多すぎてどれがいいのかわからない。

みんなが知らない 10 Excellent HTML5 coding Toolsにも取り上げられたLimeJSを使ってみようか。以前ちょっとソース読んだし。

[HTML5]ダウンロードデータのキャッシュとしてWeb Storageを使う

囲碁定石トレーニングを、「ダウンロードした定石データをWeb Storageに格納する」ように修正した。

目次
1. localStorageかsessionStorageか
2. Web Storageを使用可能かチェック
3. Web Storageにデータが存在するかチェック
4. Web Storageにデータを登録する

1. localStorageかsessionStorageか
Web StorageにはlocalStorageとsessionStorageがある。
有効期限が無いlocalStorageの方が、無駄なダウンロードをより削減することができる。
ただし、定石データの変更があった場合にデータの同期を取る必要がある。
今はそこまでしてダウンロードを減らす必要が無いので、タブを開いているときだけ有効なsessionStorageを使うことにした。
Web Storageを使用できない環境では、今まで通りキャッシュ用オブジェクトに格納するようにした。

2. Web Storageを使用可能かチェック
コードは以下のようになった。
  mijoseki.act.isStorage = false;
  try {
    if (typeof sessionStorage != 'undefined' && typeof JSON != 'undefined') {
      sessionStorage.setItem('test000', 'check if storage is available');
      mijoseki.act.isStorage = true;
    }
  } catch(e) {
    mijoseki.act.isStorage = false;
  }
Web Storageが使用可能ならmijoseki.act.isStorageフラグをオンにするだけの処理。
cookieをブロックしていたりすると例外が発生するので、try catchで例外対応をしている。(詳細は[HTML5]Web Storageについて調べるを参照)
例外を発生させるためにダミーデータをsetItemしている。
JSONオブジェクトは、オブジェクト⇔文字列 の変換に使用するためチェックしている。

3. Web Storageにデータが存在するかチェック
コードは以下のようになった。
  /**
   * 問題データキャッシュチェック
   * @param {string} probkey 問題のkey値
   * @return {Object} this.setprob() でセットする問題データ。
   * 該当するキャッシュが無い場合はnull。
   */
  mijoseki.Action_.prototype.chkpCache = function(probkey) {
    var pdata = null;
    if (this.isStorage) {
      pdata = sessionStorage.getItem(probkey);
      if (pdata) {
        pdata = JSON.parse(pdata);
      }
    } else{
      // sessionStorageが使用できない環境での処理
      if (this.pdatacache[probkey]) {
        pdata = this.pdatacache[probkey];
      }
    }
    return pdata;
  };
キー値に該当するデータがあったら、JSON.parse()でオブジェクトに変換してreturnするだけ。

4. Web Storageにデータを登録する
コードは以下のようになった。
  /**
   * 問題データキャッシュセット
   * @param {string} probkey 問題のkey値
   * @param {Object} pdata セットする問題データ
   */
  mijoseki.Action_.prototype.setpCache = function(probkey, pdata) {
    if (this.isStorage) {
      var setdata = JSON.stringify(pdata);
      try {
        sessionStorage.setItem(probkey, setdata);
      } catch(e) {
        // 保存容量オーバーなどでStorage使用不可の場合
        mijoseki.act.isStorage = false;
      }
    } else{
      // sessionStorageが使用できない環境での処理
      if (!this.pdatacache[probkey]) {
        if (this.pdatacname.length >= mijoseki.con.num.climit) {
         // キャッシュ数が上限のため、古いキャッシュを削除
         var delval = this.pdatacname.shift();
         delete this.pdatacache[delval];
        }
        this.pdatacname.push(probkey);
      }
      // pdataをshallow copyしてキャッシュに格納
      var pdatacp = {};
      for (var prop in pdata) {
        pdatacp[prop] = pdata[prop];
      }
      this.pdatacache[probkey] = pdatacp;
    }
  };
Web Storageには(今現在では)オブジェクトを登録できないので、JSON.stringify()で文字列に変換している。
setItemで例外が発生した場合は、キャッシュを登録せずにフラグをオフにする。次にダウンロードしたときに、キャッシュオブジェクトに登録される。
キャッシュオブジェクトでは上限を設定しているが、今の定石データは合計25KB以下なのでsessionStorageでは上限チェックをしていない。

以上。難しいことは何も無かった。
各ブラウザでcookieをブロックしたり許可したりしてテストするのが面倒だったぐらい。

[HTML5]Web Storageについて調べる

cookieよりも大容量のデータを保存できるWeb Storageについてちょっと調べた。

概要から使い方まで、たいていのことは以下の記事を読めばわかる。
ブラウザでストレージ? Web Storageを使いこなそう - @IT

Web Storage仕様書の日本語訳は
W3C - 『Web Storage』日本語訳 - HTML5.JP
にある。

Web Storageを使うにあたっての注意点は以下のとおり。
1. cookieをブロックしている場合、例外が発生する。
cookieをブロックしているときの各ブラウザの挙動は以下のようになった。
・Firefox7.0 : 'security error'発生。
・Google Chrome15 : 'QUOTA_EXCEEDED_ERR'発生。
・Internet Explorer8 : 例外が発生せず、Storageに登録可能
Firefox, Google Chromeともに、Storageのメソッドを使用するところで例外が発生するが、
Firefoxでは
if(typeof localStorage == 'undefined')
でも例外が発生した。
なお、
if(typeof sessionStorage == 'undefined')
では発生しなかった。

try catch を使用して例外発生時の対応を記述する必要あり。
IEでも容量オーバーの場合は例外が発生するので、例外対応の必要あり。

2. localStorage は、「ドメイン:ポート番号」単位で管理される。
同一ドメインであれば、異なるディレクトリで登録したデータも参照できる。
注意が必要なのは、localStorage .clear()を使用するとき。「他のディレクトリでの登録データも消える」ことを考慮する必要あり。


なお、localStorageのデータはcookieを削除すると消える
Google Chromeではcookieだけ消してlocalStorageを残すこともできるが、普通に閲覧履歴データの削除からcookieを消すとlocalStorageも消える。
ただし、Internet Explorer8ではcookieを削除してもlocalStorageのデータは消えない。履歴の削除から全てのデータを消してもlocalStorageは消えなかった。

<関連エントリ>
[HTML5]ダウンロードデータのキャッシュとしてWeb Storageを使う

囲碁プログラムの手を戻す機能を修正

囲碁定石トレーニングの修正版をアップした。
前のバージョンに比べて、入力した手を戻す機能が向上した。

<修正前>
・直前の分岐に戻るだけ。それより前の分岐には戻れない。
・戻れるのは黒の分岐のみ。

<修正後>
・ボタンを連続で押すことで、分岐をさかのぼることができる。
・白の分岐にも戻れる。白の分岐を含むかは選択可能。

修正前は、「戻る用のスナップショットをひとつだけ取得し、戻るボタンを押したらそれを反映させる」という実装だった。
スナップショットをたくさん取得すれば分岐をさかのぼることができるが、それだとリソースの負荷が大きくなる。

参考のため棋譜再生プログラムのソースを調べたところ、「入力履歴を作成し、戻ったときは初手から入力して盤面を再現する」という実装だった。
100手目から99手目に戻った場合、プログラムは1手目から99手目までを入力して盤面を再現することになる。
(「100手目を盤面から消すだけでいい」と思うかも知れないが、それだと取られた石を再現できないし、コウ判定もできない)

自分のプログラムも、同じ方式で戻る機能を実装することにした。
定石用データなので、手数はそれほど多く無い。
初手からの再現も、盤面表示せずにデータをいじるだけなので大した負荷にはならない。

以下の点を考慮する必要があったので、少し複雑な実装になった
・「前の手」ではなく、「前の分岐」に戻るため、分岐データも含める必要がある
・白の分岐時の入力は、プログラムによるランダム選択と、ユーザーによる選択の2通りある
特に白の分岐時の履歴作成では苦労した。

これで使い勝手が良くなったと思うが、実際にトレーニングを続けてみないとわからないな。

碁盤に座標を描く実装でちょっと悩む

引き続き、囲碁定石トレーニングの修正をしている。

今日は碁盤に座標を描くことにした。
実装方式について少し考えた。

(1)座標を含めて碁盤を画像にする
画像さえ作ってしまえば実装は簡単。
ただし、
・碁盤の交点のCSS座標が取得できない。
・13路盤など、サイズが異なる碁盤は別の画像を用意する必要がある。
という問題がある。
拡大縮小で画像の交点とCSS座標がズレるようなことは無いと思うが、できれば位置情報を正確に取得したい。

(2)Canvasで座標を描画する
現在の碁盤は HTML5 Canvas で実装しているので、context.fillText() で座標を描いてしまえばいい。
碁盤の線を引くために計算した情報を使えば、fillText用のxy座標を求めるのは難しくない。
ただし、
・Canvasを再描画する際、座標も再描画する必要がある。
という問題がある。
マウスポインタの位置に半透明碁石を表示しているとき、12fpsで碁盤を再描画している。
12fpsで座標を描いても大した負荷にはならないと思うが、無駄な処理は減らしたい。

結局、次の実装方式にした。
(3)DOMを使って座標文字用divを作成する
碁盤を描いたときに計算した情報を取得し、divのCSS座標を計算する。
同じフォントとフォントサイズでもブラウザによって表示が微妙に異なるため、divは表示位置ごとに作成した。19路盤だと19×2=38個。
石と重なっても座標が下に来るように、z-indexを 碁盤の背景色 < 碁盤の座標 < 碁盤のCanvas となるようにした。

できた碁盤は以下のとおり。(これはキャプチャ画像です)
座標つき碁盤
IE(FlashCanvas), firefox, Google Chromeでちゃんと表示されることを確認した。
プロフィール

himax64

Author: 南西
30代後半の無職です。
就活もせずダラダラ生きてます。
作ったもの

最新記事
人気記事
検索フォーム
カテゴリ
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
QRコード
QRコード
カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。