作者別: M.W.

Cordovaを使ってみました!

こんにちは。開発担当のマットです。

最近、AndroidとiOSのアプリ開発をしています。
作っているアプリがiOS端末(iPhoneやiPad)とAndroidのネイティブ機能を使うので、iOS版とAndroid版を別々に作成しました。

もちろん、アプリを2つのプラットフォームで作ることは手間が掛かりますが、iOSとAndroidの力を完全に引き出すには必要です。

しかし、単純でウェブサイトのようなアプリケーションを作ろうと思ったら、二つのネイティブなアプリを作るより、簡単な方法が沢山あります。私はその簡単な方法を一つ試してみましたので、ご紹介したいと思います。

開発環境

この記事にて、iOSとAndroidのアプリをビルドします。

・iOSのアプリをビルドするには、XcodeがインストールされているMacが必要です。
・Androidのアプリをビルドするには、Android Studioをインストールする必要があります。Android StudioはWindows、Mac、Linux、全てにインストールすることができます。

Cordova

Wikipediaによりますと、Cordovaは「オープンソース(Apache 2.0 License)のモバイルアプリケーション開発フレームワーク。」

Cordovaの特徴ですが、

モバイルデバイスのカメラ、GPS、加速度センサーなどにアクセスするためのAPIを追加することにより、JavaScript、HTML、CSSといったウェブアプリケーション開発の技術でモバイルアプリケーションを開発することができるのが特徴である。

簡単に言いますと、ウェブサイトのようなものをHTML、Javascript、CSSで作れば、Cordovaはそのウェブサイトをモバイルアプリケーションに変換してくれる。
なお、Javascriptで特別のファンクションを呼び出すと、ネイティブアプリケーションのネイティブ機能(カメラ、GPS、加速度センサー、など)を利用することができます。

 

使ってみよう

まずは、Cordovaをダウンロードしました。
詳細は https://cordova.apache.org/ でも書いてありますが、コマンド実行でインストールします。

なお、Cordova自体をインストールする前に、node.jsをインストールする必要があります。まだインストールされていない場合、https://nodejs.org/ja/からダウンロードして、インストールしてください。


では、コマンドプロンプトから以下のコマンドを実行してください。
npm install -g cordova

インストールが完了されたら、Cordovaのアプリケーションを作成するコマンドを実行しましょう。例として「MyCordovaApp」というアプリケーションを作成する。
なお、アプリケーションの bundle ID (アプリを特定するID)もこの時点で設定しましょう〜。
cordova create MyCordovaApp com.example.myCordovaApp MyCordovaApp
                                  (ディレクトリー名 Bundle ID アプリ名

次は、作ったディレクトリーに移動する(MyCordovaApp)。
今回、iOS版、Android版、ブラウザー版を作ってみます。
cordova platform add browser
cordova platform add ios
cordova platform add android

なお、以下のコマンドを実行すると、対応されているプラットフォームの一覧が表示されます。今回の記事の範囲外となりますが、BlackberryやOSXやWindowsのアプリも作れるようです。
cordova platform

ところで、Cordovaの準備ができました。
さて、簡単に何かを作ってしまおう。

初めてのCordova

アプリケーションディレクトリーの中にwww/index.htmlというファイルがあります。
これがアプリケーションの最初に表示されるページとなります。
空白のページではなく、既に内容が入っています。ちょっと変更してみましょう!

bodyの部分に以下のHTMLが入っている。

以下に変更してみました。

なお、非ASCII文字も入れちゃっているので、headに以下のmetaタグも追加しました。

<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />

そして、ファイルを保存!

各プラットフォームにビルド!

コマンドプロンプトに戻って、以下のコマンドを実行すると、追加されているプラットフォームのファイルが更新されます。
cordova build

XCodeでMyCordovaApp/platforms/ios/を開くとiOSアプリケーションをビルドできます。
Android Studios で MyCordovaApp/platforms/android/を開くとAndroidのアプリケーションをビルドすることができます。
なお、cordova run browser だけでウェブページを確認することができます。

今回、作ってみたものをスクリーンショットで撮ってみました。

まとめ

Cordovaで簡単に多くのプラットフォームに対応できることはとても便利だと思います。
特に、HTML,CSS,Javascriptに経験が深いウェブ系の開発者の場合、Cordovaの利用により、複数のプラットフォームに対応しているアプリを迅速に開発できると思います。

しかし・・・
個人的意見にすぎませんが、Cordovaやこのようなマルチプラットフォームサービスは、開発オプションの中間に位置していると思います。

完全にウェブサイトのようなモバイルアプリを作成したい場合、iOSやAndroidが提供するWebViewを利用する方がいいかもしれません。
その反面、多くのネイティブ機能を使いたい場合、手間は掛かりますが、ネイティブのアプリケーションを作ると、そのプラットフォームにより適している製品を作れると思います。

でも、「あまり手間を掛けずに、ウェブサイトに近くて、カメラやGPSのようなネイティブ機能を利用するが、依存しない複数のプラットフォームに対応したアプリケーション」を作りたいと思う場合は、ぜひ使ってみてください。


ゲーム開発 – 地形生成 アルゴリズム

こんにちは。開発担当のマットです。
 
以前の記事でも言ったことはありますが、ゲームが大好きです。
いろんなのゲームの中でも、とくに街づくりゲームが好きです。
 
街づくりゲームは沢山ありますが、内容はほとんどが似ていて何らかのマップの上で街を作っていきます。
しかし、一度成功すると二度目が面白くないので、毎回違う場所で街づくりをすることがポイントです。
 
そのため、ほとんどの街づくりゲームには、ランダム地形生成の機能が付いています。
なお、街づくりだけではなく、近年は多くのアクション・アドベンチャーゲームにも付くようになりました。
 

おそらく、Minecraftの影響ではないかと思います

 
このランダム地形生成機能に興味を持って調べたので、今回の記事では3つのアルゴリズムを紹介したいと思います。
 
今回紹介します3つのアルゴリズムを使えば、ランダムマップを生成するゲームをより簡単に作ることができると思います。

私のようにゲーム作成に興味をお持ちの方は、ぜひ読んでみてください。

1:フラクタル・アルゴリズム

個人的な意見ですが、フラクタルアルゴリズムは島や海岸の生成に向いているアルゴリズムだと思うので、島を作っていきます。
 
まずはグリッドを想像します。
5×5を使いますが、思いのままに作っても問題ありません。


 
次は、島の大体の形を決めます。
私は、ちょっと丸目の島が欲しいので角のセル(A1,E1,E5,A5)を削ります。


 
各セルの中のランダムな箇所に点(ポイント)を置いて、繋げていきます。


 
少し島の形に近づきましたが、まだ直線が多すぎて不自然です。
次は、各ポイントの間の位置を計算します。(以下で緑の点で表します)

 
それぞれの新しいポイントをランダムに左右上下にずらして、繋げ直すと島がよりギザギザになります。


 
先ほどよりも島の形が見えてきました。
 
このステップを何度か繰り返せば、本当に海岸のような線が出来上がります。
実際に作ったものはこちらです。

2:ダイヤモンド・スクエア・アルゴリズム

ダイヤモンド・スクエア・アルゴリズムはとても簡単で、上記のフラクタル・アルゴリズムのような島づくりには適していると思います。
また、フラクタル・アルゴリズムと違って地形の高度を獲得することができます。
 
前回と同じようにグリッドを作ります。
サイズは 2+1 × 2ⁿ+1 にするのが1番無難なので、このサイズをおススメします。
(つまり、5×5(2²+1 × 2²+1),9×9(2³+1 × 2³+1),1025×1025(2¹⁰+1 × 2¹⁰+1)など)
 
グリッドが出来上がったら、縁のセルの値を全部0にして真ん中のセルの値を1にします。
簡単な5×5のグリッドを例に説明したいと思います。


 
次は真ん中のセルと縁のセルの間のセルの値を計算します。
上記の例では、「真ん中のセルと縁のセルの間のセル」はB3,C2,D3,C4に当てはまります。

もちろん「間」と言ったら、「横縦の間」もありますし、「斜めの間」もあります。
この例では、「縦横の間」を使っていますが、実際に実装するときは両手段を併用するといいと思います。
ちなみに、このアルゴリズムの名前(ダイヤモンド・スクエア)はこの斜め、横縦を因んでいます。

間のセル(B3,C2,D3,C4)に、周囲のセルの数値の中間のランダム数値(もしくは平均値に近いランダム数値)を入れます。
C1が0で、C3が1となっているので、C2は0と1の間のランダム数値となります。

 
そのステップを繰り返し、全てのセルに値が入るまで続けます。
今、B3,C2,D3,C4の値を入れたので、次はB3,C2,D3,C4と縁の間のセルを埋めていきます。(つまりB2,D2,B4,D4)

やり方は色々あります。
例えばB2ですが、C2とA2の間のランダム数値を取ることもできますし、B3とB1の間のランダム数値を取ることもできます。
A2,B1,C2,B3の平均値に近い数値を取ることもできますし、A1,C1,B3,A3の平均値に近い数値を取ることもできます。
実装方法はプログラマーのお好み次第です。


 
最後に、全てのセルが埋まったら、高度の定義を行います。
例えば、0.2以下は海、0.7以上は山、その間は草、など。

 
上記の例はあまり綺麗ではないですが、ちゃんと実装すると以下のような島をランダムで生成できます。

高度値を使って、森林や川も生成することは可能です。

先ほど言った通り、島に適しているアルゴリズムだと思いますが、縁や真ん中の値を0,1ではなくて、ランダムな数値で始めると、山と谷のような結果になります。

3:パーリン・ノイズ・アルゴリズム

ゲームの地形生成では、パーリン・ノイズ・アルゴリズムは1番使用されているかもしれません。

パーリン・ノイズの詳細を説明することは本記事の範囲外となりますが(詳しくはWikipedia)、簡単に説明すると、波の生成アルゴリズムです。

多くのプラットフォームにライブラリーが存在し、使うことによって、ランダム波のノイズを生成することができます。


 
ダイヤモンド・スクエア・アルゴリズムと同じように、海や山の閾値を設定することによって、地形を作成することができます。
以下の地図は上のパーリンノイズをベースにして作成しました。

複数のパーリンノイズマップを重ねると、森林(深緑のエリア)なども生成できます。

まとめ

ゲームを作成するとき、リプレイアビリティ(繰り返し遊べること)は重視すべき要素だと思います。

この記事は街づくりのゲームの前提でアルゴリズムを紹介しましたが、これらのアルゴリズムを使えばRPG用の洞窟や宇宙ゲームの小惑星帯など、多くのエリアを自然に生成することができます。

毎回遊ぶとき、エリアが同じだとリプレイアビリティがなくなりユーザさんは遊ばなくなってしまうので、そうならないように、ぜひ上記の地形アルゴリズムを使って頑張って開発してみてください!


NPCのAIプログラミング

こんにちは。開発担当のマットです。
 
ゲームが大好きです。
パソコンゲームと最初に出会ったのは子供の頃でした。
父親の事務所にあったパソコンにMS-DOSゲームライブラリーというものがあって、楽しく遊んでいたことを覚えています。
 
ライブラリーには色々なゲームがありましたが、その中でもシミュレーションゲームが特に好きでシムシティのようなゲームに何時間も費やしていました。

代表的な街づくりゲーム。シムシティ2000

遊んできたたくさんのゲームの中で、大きな印象があったのが2001年発のBlack&Whiteです。
ちょっと珍しい設定ですが、このゲームは村の神様として遊びます。
雨を降らしたり、火災を起こしたり、雷を落としたり、様々な神秘的な奇跡を起こすことによって崇拝してもらうゲームです。

Black&White の一般的な村

でも、一番面白いと思っていたのはゲームの中の村人達でした。
ゲーム用語で、このようなキャラクターは「直接制御できないキャラクターNPC(ノンプレイヤーキャラクター)」といいます。
このゲームの一番の魅力はこのNPC達のAIでした。

なぜなら他のゲームと違って、ある程度自由に動いたりすることができたからです。
村の婦人達が妊娠したり、子供達が遊んで走り回ったり、皆が怖いことから隠れたりして、見るだけでも十分面白いシミュレーションでした。

AIとは何?

AIはArtificial Intelligenceの省略です。
日本語では、「人工知能」と訳されています。

ゲームのAIは「知能」の意味が曖昧で中々定義しにくいですが、環境に反応して目的を果たそうとするものはAIと言っていいかと思います。

上記で取り上げたBlack&Whiteの例では、村人達の目的は単純に無事に幸せに生きて子供を残すことだけでしたが、そのことでゲームに個性が生まれて楽しく遊ぶことができました。

この記事で紹介するAIの例

この記事では、上記のようなAIプログラムの基本を説明したいと思います。
実際のコードは使いませんが、AIの基盤がわかるとプログラミング言語を1つでも知っていれば、誰でもAIスクリプトを書くことに挑戦できると思います。

上記のゲームと同様で自由勝手に動く人間(NPC)のAIの例で進めたいと思います。
何らかの設定が必要なので、「無人島に流された」という設定を使いたいと思います。

ゲームAIの分解

AIのプログラムは5つの段階に分けることができます。

  1. Sensing – 感知する
  2. Conditions – 条件を生成する
  3. State – 状態を選択する
  4. Schedule – (適切であれば)新たなスケジュールを選択する
  5. Task – タスクを実行する

定期的にスクリプトをコールして、これらの段階を順番に実行していきます。

1. Sensing – 感知する

まず一番最初にするのは「感知」です。
NPCはただの人間で全知の超能力者ではありません。
そのNPCは何を見えるか、何を聞こえるかをリストアップし、もしNPCの近くにココナッツの木やビーチで歩いているカニがいたら、それらをNPCの感知リストに載せる。

逆に島の反対側にいるイノシシは見えないし聞こえないので、感知リストには載せません。

2. Conditions – 条件を生成する

次は感知したものリスト一覧で様々な「条件」を生成する。
例えばカニが見えるので「食物が見えるか」の条件をtrueと定義する。
同じくココナッツが見えるので「水分が見えるか」の条件もtrueと定義できる。
その反面イノシシのような獣は感知していないので「危険な動物がいる」の条件をfalseと定義する。

3. State – 状態を選択する

次はNPCの状態を選択する。
まずは「通常」ですが、もし近くにいる危険な動物を感知したら「危険な動物がいる」という条件がtrueになります。
もちろん危険動物が近くにいると振る舞いが変わるので、NPCの状態(State)が「通常」ではなくて「注意深い」になります。

「注意深い」になっている間は、音を立てずに忍足で歩くなど行動が変わります。

一つの状態の種類だけだと足りないかもしれないので、さらに分けることができます。
例えば「心理の状態」と「健康の状態」など。

4. Schedule – スケジュールを選択する

スケジュールとは一つの目標のことです。
上記で定義した条件と状態の元で決めます。

例えば水分が近くにあって喉が乾いている場合、水分を取りに行くというスケジュールを決定する。

基本的にスケジュールが決定されたら、そのスケジュールを最後までする。*1
つまり水分を取りに行っている途中、お腹が空いてもスケジュールは変更しません。
まず水分を獲得してから食料を取りに行けばいい。*2

しかし「割り込み条件」(Interruption)という特別な条件が成立したら、途中であってもスケジュールを変更する。
例えば蛇に噛まれた場合は水分獲得をやめてケガを治療するスケジュールに切り替えるべき。

*1: これは柔軟なルールです。途中で再検証すべきスケジュールもあると思います。
*2: ただし「餓死しそう」のような「割り込み条件」が成立したらスケジュールを変更すべきです。

5.Task -タスクを実行する

スケジュールは一つか複数のタスクで成り立っています。

例えばココナッツの水分を獲得するのに、以下のタスクがある。

  • 木まで歩く
  • 木を登る
  • ココナッツを取る
  • 木を降りる
  • ココナッツを割る
  • 飲む

「割り込み条件」によってスケジュールが変わらない限り、これらのタスクを1つ1つ順番にやり遂げるだけです。

まとめ

ゲームを開発する際、気の利いたAIが必要で欠かせない場合がたくさんあります。

プログラマーとして「あ!動いた!」の瞬間が一番楽しいと思うので、実際に動き回るバーチャルな人間のようなNPCをコーディングすることはとても楽しいです。
興味がある方は実際にプログラムでも書いてみるのはいかがでしょうか。


最短ルートを探せる”A* パスファインディング”を試してみた

こんにちは。開発担当のマットです。
Sploutでは様々なテクノロジーを使って色々開発していますが、その中でも特にゲーム・プログラミングが1番好きです。
 
日本ではあまり知られていませんが、小さい時からシヴィライゼーションというゲームが大好きでした。

civgame
『シヴィライゼーション 2』のスクリーンショット

ルールは複雑ですが、目的は単純です。
国のリーダーとして、都市を設立して、軍隊を作り、敵を倒し、世界の征服者になることです。
 
プログラムを書けるようになった頃、このようなゲームを作成することをすぐ試してみました。
1人の人間のプレーヤー対複数のコンピュータ・プレーヤーのゲームにするつもりだったので、世界のマップを作って将棋盤のようにそれをマスに分けて(海のマス、森林のマス、野原のマス、山のマス、など)、将棋の駒のような軍隊のピースを設置しました。
歩兵部隊、戦車、軍艦など、いろいろな種類を用意して通過可能と通過不可能のマスも定義しました。
 
歩兵部隊の場合、海と山が通過できない。
戦車の場合、それプラス森林もダメ。
軍艦は海のみ通過できるなど。
 
一マスずつ動かす場合、コードはとてもシンプルでした。
隣のマスはその駒にとって通過可能であれば、通過を許す。
一マスずつしか動かないので、遠い目的地までのルートは頭の中で管理していました。
 
ところがコンピュータの番になると目的地までのルート管理で困りました。
駒と目的地の間に山や海やそのような通過不可能なマスがあったら、その障害を避ける方法を見つけなければなりませんが、実際にどうやってするのでしょう?

「パスファインディング」とは?

名前の通り、「パスファインディング」は「パス(道)ファインディング(探し)」のことです。
つまり、「パスファインディング」は A という出発地から B という目的地までの道を見つける方式のこと。
 
様々なパスファインディング方法がありますが、この記事で紹介するのは1番多く使われている「A* パスファインディング」という方式です。

A* パスファインディング方式の実例

単純に、A*(エイ・スター)とも呼ばれますが、この方式を正しく使うと、必ず1番短い道を見つけることができます。
少し複雑なので、実際の例で説明したいと思います。

*草色は通過可能、青色は通過不可能とします。

 
この実例で、このマップのA出発池からB目的地までの一番短い道を探します。
コーディングを始める前には、以下の基本知識が必要となります。
 
1.パスファインディングの用語で「マス」は「ノード」と言うので、以下では「ノード」と呼ぶ。
 
2.この実例では、1ノード=1m(メートル)。即ち、上下左右を動く場合、距離は 1.0mとなる。
 
3.しかし、斜めに行く場合、「√2.0m」となります。実際にそれを使うと処理が遅くなる上、実例が複雑になりますので、端数を切り捨てて、1.4mとする。
 
4.それぞれのノードは以下の変数を持つ。
>  g (これは「今まで辿ってきた道の距離」を持つ変数)
>  h (これは「直線で目的地までの距離」を持つ変数)
>  p (これは「このノードに着くまでの手前のノード」を指す変数)
 
5.確認できるノードを「open」というリストに保管する。
 
6.既に確認したノードは「closed」というリストに保管される。
>  一旦closedに入ると、openに戻されることはない。
 
7.その時、調べているノードは「current」とされる

A*パスファインディングの手順

1.まず、A出発地を「current」と指定する。
 
2.currentが目的地であれば終了。
 
3.以下の条件を満たす場合、currentに接触しているノードをopenリストに追加する。
〈条件〉
接触しているノードは通過可能である
接触しているノードはclosedリストに含まれていない
 
4.currentに接触しているノードの g と h を計算し以下のルールを従う。
 
ルール①
もし、そのノードのg,h,p値がまだ設定されていない場合、そのノードのgとhを設定しそのノードのpをcurrentと設定する。
 
ルール②
もし、そのノードのg,h,p値が既に設定されている場合、新しく計算したgは既に設定されているgより少ない場合のみ新しく計算したgを設定し、そのノードのpをcurrentに設定する。
 
5.currentをclosedリストに追加する。
 
6.openリストの中で、g+hが一番低いノードをcurrentと設定する。
 
7.ステップ2からステップ7まで繰り返す。

実例

上記の手順だけではわかりにくいので、実際の例で上記の手順を使って一番短い道を見つけましょう。
 
まず、A出発地を「current」と定義する。

黄色=current

 
次、currentと接触しているノードをopenリストに追加する。
a2
薄オレンジ=openリスト

 
次、それぞれの g と h 値を計算し設定する。
なお、それぞれのpはcurrentとなります。
以下の図では、pを矢印で表す。
(それぞれのノードのpノードは差し先です)
a3
g = 来た距離、 h=直線で目的地まで

一旦、図を見てみましょう。
 
例として、C3にあるノードを見てみましょう。
C3のG値は1.4  出発地からC3まで、1.4m分の道を行かなければならないからです。
C3のH値は5.4  C3から目的地まで直線でいけたら、5.4mはまだあるからです。
(4つ右、1つ斜めので、4*1.0m + 1*1.4m = 5.4m)
なお、C3のpはまだ設定されていなかったので、pはcurrentのB4と設定されました。(左下向きの矢印で表している)
 
次はステップ5とステップ6。
current(B4)をclosedに追加し、openリストの中のgとhの合算が一番低いノードは新しいcurrentになります。
今の時点では、それはC4となります。
(C4の gとhの合算(5.0+1.0)は他のopenノードよりも低いため)
a4
次はC4を調べる

 
次はcurrent (C4)に接触しているノードをopenに追加する。
(ご注意:B4はclosedに含まれていて、D3は通過不可能ので、いずれも追加しない)
a5
接触している、且つopenにあるものは紫枠に

 
次、上記の図で紫枠になっているノードの g と hを計算します。
D4とD5は何も入っていないので入れるだけで問題ないですが、既に設定されているものも確認しなければなりません。
 
例として、C5を見てみましょう。
C5がB4から直接来た場合、gは1.4mになりますが、C4から来た場合2.0mになります
(B4→C4の1.om + C4→C5の1.0m)
 
既に設定された1.4mの方が短い道なので、C5のp(手前のノード)は出発地のB4のままでいいです。
なお、gを上書きしません。
計算が全部終わると、このようになります。
a6a
C4の接触ノードを調べ終わった後

 
次はステップ5とステップ6。
確認済みのノードをclosedに追加して、g+hが一番低いノードをcurrentとして設定する。
gとhの合算が一番低いノードはD4です。
a7b
次はD4を調べる

 
次はD4と接触しているノードをopenに追加し、gとhを計算する。
a8
紫色はチェック対象となるノード

 
ご覧の通りE3,E4は設定されていなかったので設定されて、pがcurrentのD4となりました。
しかし、D4経由でC3,D5,C5まで行くとそれぞれのg値がより高くなってしまうので上書きされません。
(例えば、D4からD5に行く場合、gは3.0mになるが、C4からD5に行く場合、gは2.4mので、D5のpはC4のままでいいです)

 

次、各openノードを比較してgとhの合算が一番低いノード(E4)をcurrentにしD4をclosedリストに移す。

a9
一つずつ順番にやっていきます

 
次は、E4と接触しているノードをopenして、gとhを計算する。
(今回、接触ノードは全て通過不可能、または既にopenに追加されているので、openリストに何も追加しなくていいが、E3とD5のE4から辿った場合のgを計算する必要があります。今回、どれも上書きされません。)
 
E4をclosedにし、gとhの合算が一番低いノードをcurrentに切り替える
しかし各openノードのgとhの合算を確認したら、E4もD5もC3もC5も同じ6.8mとなっています。
 
その場合、どちらを選んでも問題ないです。
今回の実例では、h値が一番低いものを優先に調べることにしましょう。
(結果的に、A*は一番短い道を確実に見つけてくれるけど、複数の等しい道がある場合、この「どれを優先に調べる」ルールはその等しい道の中、どの道になるかを影響する。優先順位をランダムで決定することでも問題ありません。)
 
E4、D5、C3、C5の中、
h値が一番低いのはE3ので、それをcurrentにします。
a10
行き止まりであるE3も確認する

 

E3の接触ノードは全て通過不可能、またはclosedに入っている。
残念ながら、行き止まりでした。
g、hを計算できる接触ノードはありませんので、openリストを広げるステップをスキップし、E3をclosedに入れる。
 
まだC3,C5,D5、三つとも、6.8mとなっていますが、h値が低いのはD5ので、
それをcurrentに切り替える
 
そのD5の接触ノードを確認して、gとhの計算をする。
a11
 
この手順を繰り返すと目的地に近づいていきます。
a12
 
a13
 
a14
 
やっと、目的地のH4はopenリストに追加され、gとhが計算されました。
次のステップで目的地がcurrentになります。
 
そうなるとこの手順の繰り返しを完了します。
a15
 
ちなみに目的地に着かずopenリストを尽くしてしまう場合もあります。
その場合「道が存在しない」という意味になるのでコードを書く時は、その可能性も考え対応する必要があります。
 
やっと目的地に辿り着いて一番短い道の距離は7.8mであることがわかりました。
目的地からp値で遡ると道のルートも取得できます。
目的地H4のpはG5.
G5のpはF6.
F6のpはE6.
E6のpはD5.
D5のpはC4.
C4のpは出発地のB4.
a16
 
つまり、行く道はその反対
B4→C4→D5→E6→F6→G5→H4
a17

A* パスファインディングの特徴

上記の実例はとても単純なマップでしたが、複雑な迷路のようなマップでも1番短い道を必ず見つけてくれることが確実です。
a18
 
なおgとhの合算が低いものから調べていくため、他のパスファインディング方式より処理がより速いです。

ウェイティング(重み付け)

なお、ウェイティングをすると、通過可能の障害物もシミュレートできます。
以下のマップを見てみましょう。
a19

 
この実例では人と馬が目的地に行きたいですが、間に森林がある。
このゲームでは人は構いなく森林を通ることができるけど、馬は森林を避ける傾向を持つ(でも、仕方がない場合、通る)。
 
それをシミュレートするには、gを計算するとき何らかの重み付けを使います。
 
つまり、人がまっすぐ森林のノードに移ると+1.0と計算するが、
馬の場合、野原は森林より5倍好ましければ馬がまっすぐ森林のノードに移ると+5.0と計算する。
(hは通常通り、直線距離で計算する)
 
これをすると、人は割りとまっすぐなパスを辿る。
馬はできるだけ分厚い森林を避けようとする。
a20
 
同様に、反対のこともできます。
「障害物」を避けるために重み付けをするだけではなく道路などを優先的に使うよう野原に重み付けをして、道路に重付けをしないこともできる。
a21
 
***ご注意
重み付けをする際、1.0より小さい数字を使うと「必ず一番短い道を見つける」特徴がなくなります。
その反面大きいな数字を使うとあまりにも避けようとしすぎてコードの処理が遅くなります。

まとめ

『もしアップルパイを最初から作りたいと思ったら、まずは宇宙を創造しなければなりません』- Carl Sagan
 
マップ上で駒を動かすのはものすごく単純な行為には見えますが、プログラミングの世界では単純なことは中々ありません。
 
コンピュータにとっては簡単ですが、私は 312198 * 1912 の暗算はできません。
その反面、散歩をするときは自然に目的地まで歩くことができるのに、コンピュータにとっては自然ではないので、A*などの方式でコードを書いて教えなければなりません。
 
今回の記事で紹介しました方式は主に、ゲーム・プログラミングやロボティクスで活用できますが、このような問題を1つ1つ解決していくことがプログラマーの1番の楽しみと思います。
 
自分に挑戦したいと思う方は、ぜひ上記のA*パスファインディング方式を実際に使って簡単なプログラムでも書いてみるのはいかがでしょう。


ウェブサービスまたはスマートフォンアプリの国際対応のススメ

こんにちは。開発担当のマットです。
現在、私はスプラウトで様々な開発をしていますが、開発者になる前は日英翻訳の仕事をしていました。
 
翻訳は面白いものだと思います。
文章を訳すことによって言語の壁を超えることができます。
また、いい翻訳者であれば異なる文化を持つ多くの国の方々に著者の感情と強調まできちんと届けることができます。

小説の翻訳フローはだいたい同じです。
日本語で小説を書いて出版する。
海外から需要がある場合、翻訳会社に委託して翻訳が出来上がったら海外にも出版する。

でも、ソフトウェアの場合、翻訳はそれほど簡単ではありません。
本記事で、一般的なウェブサービスまたはスマートフォンアプリなどの国際化の利点、およびチャレンジについて書きたいと思います。

 

ソフトウェア国際化の利点
「日本語だけでいいんじゃないの?」

市場として、日本は小さくありません。
この記事を書く時点(2016年12月)では、1億2620万人の日本人がいます。
なお、日本のGDPは500兆円を超えています。

けれども、世界の割合として日本人は世界人口の2パーセントにも達していません。
なお、世界GDPの6パーセントです。

ウェブサービスまたはアプリなどを開発する際、日本にいない98%の人間と94%の市場を見過ごしてしまうとすごくもったいないです。

人口の比較。日本は世界人口の2%も占めません。
人口の比較。日本は世界人口の2%も占めません。

世界規模なサービスを開発するにあたってのチャレンジ
「いったいどこから始まる?」

「サービスを国際化する」イコール「サービスを翻訳する」と思いがちですが、それほど簡単ではありません。

サービスの国際対応は大きく3つの段階に分けることができます。

  1. Multilingualization (多言語化)
  2. Localization (現地化)
  3. Internationalization (国際化)

Multilingualization (多言語化)

atoa

国際対応にあたって、多言語化は一番想像しやすい項目だと思います。

「Multilingualization(多言語化)」とは、サービスを他の言語で表示できるようにすることです。

ところが、なんでも簡単に訳すことができません。
特に気にしないといけないのは、動的文言です。
文章の中に変数が入る場合、色々な問題が発生します。

私の経験上で、一番悩んできた問題を以下にまとめます。

 

単数・複数の区別

「このユーザは{X}人の友達がいます」という文章は簡単に見えますが、英語に訳すと、一人の場合は「friend」、一人以上の場合は「friends」になります。
サービスを多言語化する際、翻訳文の管理システムに、単数・複数の区別ができるように作らないといけません。

なお、英語の場合は、1 = 単数、1ではない = 複数、ですが、フランス語の場合、0 も単数扱いという文法ルールが存在します。
なお、ロシア語の場合、21,31,41などが単数扱いで、100,1000,10000などは全く別の「大複数」的な扱いになります。

要するに、言語によって単数・複数の区別は非常に複雑で、翻訳者がその区別を入力できるよう多言語システムを作るべきです。

 

文法的性

日本語に全くない概念ですが、単語に性別が属する言語も存在します。
「お爺さん、お婆さん」を英語に訳すと単純に「the grandfather, the grandmother」になりますが、スペイン語だと、「el abuelo, la abuela」になってしまいます。

なお、性別を持っていそうな「お爺さん、お婆さん」だけではなく、性別を持っていなさそうな単語も同様です。
例えば、「皿」は男性用のelを使う。ギターは女性用のlaを使うそうです。

同じような現象ですが、日本語では性別で区別しないが、生物・非生物の使い分けがあります。
「動物がいる。物がある。」などで見られます。

これは簡単に対応できないですが、なるべく翻訳者がこのような区別を入力できるよう多言語システムを作れたら作るべきです。

(しかし、私の経験上でほとんどの翻訳者はこの問題を回避するよう、文章を上手に書くことができます)

 

UIが言葉の順番に依存すると困ります。

時々出てくる問題ですが、文章の中の単語の順番が変わるとUIが崩れてしまうことがあります。

このようなUIの多言語化作業が非常に大変になってしまいます。
なので、絶対にしてはいけないこととは言えませんが、開発者様はこの事実を考慮しておくと後の悩みを防ぐことができます。

Localization (現地化)

globe_flags

多言語化の段階で言語の壁を超えることができても、国境はまだ超えていません。

「Localization (現地化)」とは、日本と異なる法律や習慣を持つ国に対して、サービスを最適化することです。

現地化はかなり広い意味を持ち、「最適化」をどこまですべきかは客観的な答えはないと思います。

でも、世界規模のサービスを作りたい場合、以下のことを頭の片隅に入れると良いと思います。

 

法律

国境を越えると海外の法律を考慮しなければなりません。
各国の著作権法、成年の年齢、広告の掲載に関する規制などが異なるので、このような法的問題を対応できる余地をサービスを設計する段階で考えるべきだと思います。

 

日付・時間の表示

日本向けのサービスと違って、世界規模のサービスに時間を表示させる場合、世界各時間帯の対応をする必要があります。
なお、日付と時間の表し方も国によって異なります。

例えば、日本では24時間表示が人気ですが、西洋ではAM/PMで時間を表すことが一般的です。

また、2017年1月2日を英語で書くとしたらどちらが正解でしょうか?

a) 1/2/2017
b) 2/1/2017

正解は・・・どちらも。
米国であれば、b が正式ですが、英連邦の国々(イギリス・オーストラリア・南アフリカ・ニュージーランドなど)では a が正しいです。

 

色と記号

一部のサービスにしか関係ありませんが、文化によって色と記号の意味が異なります。
日本ではチームを分けたら「紅白」、正解がマル印、不正解がバツ印という文化が染み込んでいますが、海外ではチームを分けたら「赤・青」、正解がチェック、不正解がバツ印という国も存在します。

なお、「春=桜色」なども、日本独特の文化によるものです。
もちろん、現地化をする際、日本で使われる色や記号を決して使ってはいけないわけではないですが、このようなことを常に考慮しなければなりません。

Internationalization (国際化)

world_map

上記の多言語化と現地化が終われば、初めて全世界向けにサービスを公開できる状態になります。

しかし、そのままサービスを公開してしまうと多くの問題が発生します。
例えば、サービスに「人気コンテンツ」のページ等があると、多くの国のコンテンツが表示されてしまうことが考えられます。
逆に、ユーザ層がある国に偏ってしまうと、「人気コンテンツ」ページの内容がその国のコンテンツに占められてしまいます。

「Internationalization(国際化)」とは、国際規模のコミュニティを仲良く混じり合い衝突させないことです。

サービスの仕様によっては違いますが、「このサービスは海外向け」と思われないように設計することが国際化の目的です。

ガラパゴスからとびだそう

日本は多くの面白いサービスを開発する国です。
小さい企業から、大きい企業まで、様々なアイディアを活かしてサービスとして提供できることは日本の特長だと思います。

けれども、多くのサービスが日本語のみ、日本人向けにしか提供されていません。
他方、アメリカで開発されるサービスは全世界向けに提供されることが多いです。

アメリカのIT会社が世界にサービスを提供する。
日本のIT会社が日本にサービスを提供する。

個人意見に過ぎないかもしれませんが、この状況は本当にもったいないと思います。
今後、ウェブサイトやゲームやその他のアプリケーションを開発される際、是非是非、国際対応をご検討ください。

参考URL
https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_population
https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(nominal)
https://en.wikipedia.org/wiki/Date_format_by_country
 
\\インターネットに関することは何でもご相談ください//
ウェブサイトやスマートフォンアプリの国際化に関心ございませんか?
弊社までお気軽にご相談ください!
お問い合わせはこちらから。