fc2ブログ

jQuery Mobile を触ってみる

スマートフォン向けのサイトを作ろうと思って少し調べてみた。
jQuery Mobileを使えば手軽に作れそうだ。

入門記事はないかと探して、西畑一馬のjQuery Mobileデザイン入門をザザっと読んでみた。
「デザイン入門」なので、マークアップとCSSが中心でJavaScriptについてはあまり触れていない。
結局、リファレンスをひと通り読むことにした。

ページ遷移はjQuery Mobileがやってくれるので、リンクを貼るだけでいい。
遷移後のonloadや$(document).ready()に該当するものがわかりづらいが、data-role="page" のdivのpageinitイベントにバインドすればいいとわかった。
ただし、
$('#id').bind('pageinit', function(event){...
だとバインドされなかった。
$('#id').live('pageinit', function(event){...
だとバインドされた。意味が分からない。

とりあえず、
・メニューのリストから"ベジェ曲線を使ってみた"をタップすると、ベジェ曲線を使ってみたのCanvasが表示される。
・画面をタップするとボールが動く。もう一度タップすると止まる。
という動きをするMulti-pageを作ってみた。

作ってみたのだが、確認しようにもスマートフォンを持っていない
パソコンからスマホ用サイトの表示をチェックできるMobilizerをインストールしてみたが、CPU負荷が100%に張り付いて動かない。
スマートフォンよりも開発用PCを買うのが先だな。
結局、Safariをインストールして、開発メニューからUser-AgentをiPhoneにして一応動くことを確認した。(HTTPヘッダのUser-Agentを変えているだけなら意味が無さそう)

ページイベント周りがよくわからないから、あとで整理したい。
スポンサーサイト



キートップをはずしてキーボードの掃除をする

珍しくプログラミング以外のことを書く。

年末気分でノートPCキーボードの掃除をしようと思い、初めてキートップを外した本格的な掃除をした。
掃除後
これは掃除後。
掃除前はダニアレルギーになりそうなぐらいひどかったので写真は載せない。

キートップはドライバーではずした。
ドライバーなど
白い柄のドライバーが重宝した。
毛抜きは髪の毛を取るのに使った。

キーによってドライバーを入れる方向が異なる。
ドライバーを入れる方向
ホームポジションのFとJは縦にドライバーを入れる必要があった。
数字キーも1だけは縦だった。

ドライバーに力を入れすぎると、キーを引っ掛ける部分がはずれる。
引っ掛ける部分が外れたキー
慣れれば簡単に元の位置にハメ込めるのだが、最初は戻すのに苦労した。
ハメ込むときにちょっと沈みこませるのがコツ。

spaceやEnterのような大きなキーには針金がついていた。
enterキーなど
この針金でキーボードに固定しているのだが、Enterには縦横に2本の針金がついているため、キーを外すのも付けるのも苦労した。

ホコリを取るのに役に立ったのが綿棒。
綿棒
何年も前に買ったのに全然減っていないが、今回の掃除だけで5本使った。
こびりついた汚れをゴシゴシこすって取った。

エアダスターが無いのでドライヤーでホコリを飛ばそうと思ったが、うちのドライヤーは冷風の強風ができないので使い物にならなかった。

仕上げにこのブラシを軽くかけたが、ゴム周りのホコリが少し残った。
ブラシ

全てのキーを少し湿らせたティッシュと綿棒で拭いたので、キーボード掃除に3時間ぐらいかかった。
次回はもっと効率良くやりたいが、何年後のことになるやら。

Numberの整数化タイミングについて考える

JavaScript囲碁ライブラリを修正した。
左が修正前、右が修正後
囲碁ライブラリ修正前
囲碁ライブラリ修正後
線の間隔を等間隔にしていたが、Canvasサイズによっては余白が大きくなる。
そのため、線の間隔を算出する部分を修正した。

<修正前>
線の間隔を求めた際に整数化

<修正後>
線の座標をセットする際に整数化
  var sepx = (this.cvwidth_ - coormarg) / (rownum - 1 + this.banmarg_); // 線の間隔
  this.xArr_ = []; // x座標格納配列
  this.xArr_[0] = banmarg + coormarg;
  for (var i = 1; i < rownum; i++) {
    this.xArr_[i] = Math.round(this.xArr_[0] + sep * i);
  }


負荷を減らすため、Canvasに設定する座標やサイズを整数にしている。
整数化するタイミングや方法がバラバラなので整理することにした。

・整数が期待される引数
ローカル変数にセットする際に~~で整数化。
/**
 * 何路盤かセット
 * @param {number} inrownum 何路盤か。5以上19以下の整数を設定
 */
migolib.Goban.prototype.setrownum = function(inrownum) {
  var rownum = ~~inrownum;

・算出頻度が低く、他の計算に使用されない値
セットする際にMath.round()で整数化。切り捨てが必要な場合のみ~~で整数化。
  /* canvas中心座標 */
  this.centpos = [Math.round(this.cvwidth_ / 2), Math.round(this.cvheight_ / 2)];

・算出頻度が高く、他の計算に使用されない値
セットする際に~~で整数化。

・間隔の長さなど、他の計算に使用される値
整数化しない。
クラスのプロパティなどに値を保持する場合は、コメントに整数でない旨明記。
  /**
   * 碁盤の目の間隔(px)。not integer
   * @type {number}
   * @private
   */
  this.eyesep_ = 0;

ループで加算する際など、他の計算に使用されることを見過ごして誤差を積み上げてしまうことがあるので注意。
  for (var i = 1; i < rownum; i++) {
    // this.xArr_[i - 1]は整数化されているため、丸め誤差が含まれる
    this.xArr_[i] = Math.round(this.xArr_[i - 1] + sep);
  }

とりあえずこんな感じでやってみるか。

<関連エントリ>
[JavaScript]小数を整数に変換する望ましい方法は?

昔作ったゲームを作り直そうか

このごろJavaScriptばかりやっているので、そろそろサーバサイドのプログラミングもしたい。
だが、以前作った戦車ゲームを作り直したい気分になっている。
やりたいことは以下
・地形を画像にする
・エンジン部分を、自作のライブラリに置き換える
・当たり判定まわりなど、負荷が高そうな部分を見直す
見かけはさほど変わらないので、自己満足のための作業だと思うが、サクっとやってしまいたい。

アクションシューティングゲームを公開した

久しぶりにアクションゲームを作った。

Jump Jump Shooting
Jump Jump Shooting TOP
使用した画像はTOP画面と背景画像のみ。
プレイヤー、敵、障害物は全てHTML5 Canvasで描画している。

ヘルプ画面も作ってみた。
Jump Jump Shooting HELP
ヘルプ画面でも画像は一切使っていない。
文字列もfillText()を使っているので、選択してコピーができない。

当初は空中ジャンプして障害物を避けるだけのつもりだったが、いつの間にかシューティングゲームになっていた。
ジャンプだけだと制御が難しかったので、ダッシュ機能もつけた。
深く考えていなかったが、ダッシュのおかげでゲームらしくなったと思う。

レベルデザインにあまり時間をかけなかったので、難易度がレベルに比例していない気がする。
でも最終面が一番難しいのは確実だからいいか。

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

引き続き、読めそうなサイズのJavaScriptゲームエンジンを探して読んでいる。
Canvasを使っているエンジンを探して見つけたのがPropulsionJS
ファイルは propulsion.jsのみ。非圧縮で36KB。

ドキュメントを見ると、アクションゲームに必要な機能がそろっているのがわかる。
<機能について気づいたこと>
・PP.Alarmで「指定したフレーム数経過後に指定した関数を起動」を設定できる。
・シーン管理機能は無いが、PP.loop.roomに関数をセットすることで画面を切り替えることができる。オブジェクトの入れ替えなどを行う関数をユーザーが作成する必要がある。
・レイヤー管理機能は無い。PP.draw.depthでオブジェクトごとに管理。
・CSS Spriteには対応していない。同一オブジェクトのアクション画像だけは、等幅画像を横一列につなげて1枚の画像ファイルを作成する必要がある。

ソースを読んでわかったことは以下のとおり。
1.衝突判定がかなり気合入っている
・任意の多角形同士の衝突判定ができる。ただし、デフォルトではキャラクター画像サイズの長方形で判定。
・衝突した結果跳ね返った位置を算出できる。衝突した2つのオブジェクトに対して、跳ね返りの割合をパラメータで設定できる。
・衝突位置を算出できる。
SATアルゴリズムで判定しているとソースのコメントにある。
各多角形の辺と、それぞれの垂直ベクトルとの内積を使っているが、何でそれで衝突判定できるのかわからない。
後でちゃんと調べてみるかな。

2.accessor propertyを活用
ECMAScript 5th editionで導入されたaccessor propertyを使いこなしている。
accessor propertyとは、「プロパティに対してgetやsetが発生したときに呼び出す関数を設定できる」プロパティ。
PropulsionJSでは、次の3種類のやり方で実装している。
get演算子set演算子を使用
 日本語のリファレンスは見つけられなかった。
・Object.definePropertyメソッドを使用
 definePropertyメソッドについては ECMA-262 5th edition で導入された Object.defineProperty を使い、属性を指定してプロパティを定義する に詳しい解説がある。
Object.watchメソッドを使用
 setしか設定できない。PropulsionJSでは、watchメソッドがサポートされていない環境用に、Object.definePropertyで実装したwatchメソッドを提供している。

accessor propertyの利用方法に興味がある人には、PropulsionJSのソースを見る価値があると思う。
代入文を記述するだけで関数が実行されるため、コードがすっきりする。
ただし、コードの一部を読んだだけでは関数が実行されていることに気づかない。


ゲームエンジンよりも、accessor propertyについて勉強になった。
accessor property関連はIE8以前では全く動かないが、そもそもCanvasが動かないからPropulsionJSでは考慮していないのだろう。

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

ingenioJSは、JavaScriptで記述されたRPGエンジン。
ingenioはスペイン語らしいが、作者はドイツ人のようだ。

ingenioJSはフィールド画面とメッセージの表示機能を提供している。
戦闘画面は提供していないが、フィールドで戦闘するタイプのRPGならエンジンの機能だけでできそうだ。
なお、ajaxを使用しているためサンプルゲームもjsdocもWEBサーバ経由でないと表示できない。
また、getElementsByClassName()などを使っているので、IEでは動かない。

ソースファイルは14ファイルで、非圧縮で計80.6KB。(ただしAudioEngineは含まず)
今のところRPGを作る予定は無いのだが、十分読めるサイズなのでソースコードを読むことにした。

キャラクターデータ、マップデータ、クエストデータをjsonファイルとして作成すると、エンジンが読み込んでゲーム画面を生成する。
マップデータには、プレイヤーから攻撃されたり話しかけられたりした際のアクションも含まれる。
jsonファイルは、ブラウザからajaxで読み込まれる。
マップデータのjsonファイルを作成するエディタも提供されている。
ingenioJSeditor

キャラクターの表示はDOMのCSSで制御している。Canvasは使用していない。
メインループはingenioJS.rendererのコンストラクタでwindow.setInterval()で実装している。
だが、clearIntervalしているところが見当たらない。ループを止めるためのidも取得していない。

メインループをingenioJS.engineで行っていないところは疑問だが、クラスの役割分担が綺麗だと思った。
外部ファイルを読み込んで画面を生成する部分は参考になるかなと思うが、自分にとってはマップ生成エディタのソースが一番参考になりそうな気がする。

ライツアウト亜種の攻略法を考える

ライツアウト(lights out)とは、全てのマスのライトをつけるパズルゲーム。
クリックすると上下左右のマスのオン/オフが切り替わる。
Tacoyaki+ - Flash game は、ブラウザでできるライツアウトのひとつ。

ライツアウトの解法は検索すればすぐに見つかる。
点灯パズル自動解答(ライツアウト) のような、とても便利なページもある。

このライツアウトの亜種で、クリックすると斜め45度のマスが全て切り替わるパズルゲームがある。
Tacoyaki - Flash game
この解法は、ネットで調べても見つけられなかった。

しょうがないので攻略法を考えるべく、シミュレートするプログラムを作った。
以下はシミュレート結果の例
○○○○○
☆○●○○
○○○●○
○○○○☆
○○○★○
○●○○○
●○☆○○
○☆○●○
○○●○●
○○○●○
○○★○○
○●○●○
○○○○○
○●○●○
○○★○○
○○○○○
○○★○○
○★○★○
○○★○○
○○○○○
初期状態はすべて白で、星がクリックしたマス。
ゲームページ下のTipsにも書いてあるが、
「斜め45度の辺からなる任意の四角形の頂点4つを全てクリックすると、頂点のオン/オフだけ切り替わる」
という法則がある。これがわかるだけで解くのがかなり楽になる。
シミュレートで見つけたパターンと運に助けられて、7×7マスのステージをクリアできた。

JavaScriptで作ったシミュレートクラスのプログラムを載せておく。
Array.indexOf()をサポートしていないブラウザでは動かないので注意。
/**
 * @namespace
 */
var mitako1 = {};

/**
 * Takoyakiクラス
 * @param {number} num 一辺のマスの数
 * @constructor
 */
mitako1.Tako = function(num) {
  /**
   * 一辺のマスの数
   * @type {number}
   */
  this.num = num;
  /**
   * 各マスのオン・オフ状態。オンなら1,オフなら-1
   * 座標(x, y)のマスはboxst[x][y]になる
   * @type {Array.<Array.<number>>}
   */
  this.boxst = [];
  /**
   * 移動方向配列
   * [x軸方向,y軸方向]
   * @type {Array.<Array.<number>>}
   * @private
   */
  this.dirc_ = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
};
/**
 * 初期化
 */
mitako1.Tako.prototype.init = function() {
  this.boxst = [], num = this.num;
  for (var i = 0; i < num; i++) {
    this.boxst.push([]);
    for (var j = 0; j < num; j++) {
      this.boxst[i][j] = -1;
    }
  }
};
/**
 * マスをクリックする
 * @param {number} x マスのX座標。左端を0とする
 * @param {number} y マスのY座標。上端を0とする
 */
mitako1.Tako.prototype.click = function(x, y) {
  this.boxst[x][y] *= -1;
  var tx, ty, num = this.num;
  for (var i = 0; i < this.dirc_.length; i++) {
    tx = x;
    ty = y;
    dx = this.dirc_[i][0];
    dy = this.dirc_[i][1];
    tx += dx;
    ty += dy;
    while (tx >= 0 && tx < num && ty >= 0 && ty < num) {
      this.boxst[tx][ty] *= -1;
      tx += dx;
      ty += dy;
    }
  }
};
/**
 * マスの状態を表示する
 * @param {Array.<Array.<number>>=} star 星型にする座標配列
 * @return {string} 出力結果。オンが黒、オフが白
 */
mitako1.Tako.prototype.disp = function(star) {
  var outstr = '', num = this.num;
  var sxy = [];
  if (star) {
    for (var i = 0; i < star.length; i++) {
      sxy.push(star[i][0] * num + star[i][1]);
   }
  }
  for (var i = 0; i < num; i++) {
    for (var j = 0; j < num; j++) {
      if (this.boxst[j][i] > 0) {
        if (sxy.indexOf(j * num + i) >= 0) {
         outstr += '★';
        } else {
         outstr += '●';
        }
      } else {
        if (sxy.indexOf(j * num + i) >= 0) {
         outstr += '☆';
        } else {
         outstr += '○';
        }
      }
    }
    outstr += '<br>';
  }
  return outstr;
};

もっと時間をかければ、ちゃんとした攻略法を見つけられそうな気がするがどうしようか。
プロフィール

himax64

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

最新記事
人気記事
検索フォーム
カテゴリ
月別アーカイブ
最新コメント
最新トラックバック
RSSリンクの表示
QRコード
QRコード
カウンター