libGDXの基礎15 NinePatchを使う

今回はNinePatch(ナインパッチ)の使い方です。
原理的には難しくなくて、ただ引き延ばす場所を指定するだけです。ナインパッチという名前は知らなくても大昔にHTMLのテーブルでレイアウトして使っていた人は多いのではないでしょうか。

http://qiita.com/shinsan68k/items/5b9c9981fbcdbb49a8af

qiitaで前回から1年以上たってしまいましたが、少しずつでも書いていけたらと。

横線入れると一区切りになるというスライドモードにも章単位で対応してみました。

完全にスライド用にはしていないです。というか文字の大きさ固定とかコード全部載せてるやつなので無理です。
一部分のみではなく、完全なソースコードがあるので従来通り下にスクロールして読む方がいいとは思いますが。

Thymeleaf 3.0を試す その3 ユーティリティを作る

Thymeleaf 3.0を試す
Thymeleaf 3.0を試す その2 エスケープの有無

の続き。

今までパラメータとして文字列しか渡していませんでしたが、もちろん数値も扱えます。

〜
        String template = "[[${a}]] + [[${b}]] = [[${a+b}]]";

〜

        Map<String, Object> params = new HashMap<>();
        params.put("a", 1000);
        params.put("b", 20000);
〜


計算もView側でできるのがわかりますね。
実行結果

1000 + 20000 = 21000

3桁区切り

3ケタごとに区切り文字を入れたいというのはよくあることです。もちろんそれも標準で用意はされてはいます。一応。

〜
        String template = "[[${#numbers.formatInteger(a+b, 1, 'DEFAULT')}]]";
〜


実行結果

21,000

一応と書いたのは、見てわかる通りあほみたいに長いのが原因です。
実行しないとこのミスはわからないしこんなのいちいち書いてられないと思います。書いていたらおかしいと思わないといけませんよね。

オレオレutil

というわけで作ります。まずシンプルに何も考えず現在できる仕組みの中で考えてみましょう。

        //----------------------------------------------------------------------
        //追加したいユーティリティ
        //----------------------------------------------------------------------
        class OreOreUtil {
            public String num(int num){
                NumberFormat nf = NumberFormat.getInstance();
                return nf.format(num);
            }
        }
〜
        String template = "[[${oreore.num(a+b)}]]";
〜
        Map<String, Object> params = new HashMap<>();
        params.put("a", 1000);
        params.put("b", 20000);
        params.put("oreore", new OreOreUtil());
〜


実行結果

21,000

まずはこれで十分だと思います。しいて言えばユーティリティなのかパラメータなのかどうかがわかりにくいです。パラメータとして渡していますので。「#」は予約されていてパラメータの名前として使えないのでこうなります。

が、命名規則でどうにでもなるとは思いますので気になる人だけ次に進むとよいでしょう。

複雑化させる仕組みは必須ではないと思います。

まじめに実装する

dialectという拡張する仕組みがどうやらあるぽいです。全ソースコードを載せます。

import java.text.NumberFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.IContext;
import org.thymeleaf.context.IExpressionContext;
import org.thymeleaf.dialect.IExpressionObjectDialect;
import org.thymeleaf.expression.IExpressionObjectFactory;

public class Thymeleaf3 {

    public static void main(String[] args) {

        //----------------------------------------------------------------------
        //追加したいユーティリティ
        //----------------------------------------------------------------------
        class OreOreUtil {
            public String num(int param){
                NumberFormat nf = NumberFormat.getInstance();
                return nf.format(param);
            }
        }
        
        //----------------------------------------------------------------------
        //「#oreore」という名前でOreOreUtilにアクセスさせるためのしくみ
        //----------------------------------------------------------------------
        class OreOreDialect implements IExpressionObjectDialect{
            
            final static String KEY = "oreore";
            
            final Set<String> names = new HashSet<String>(){
                {add(KEY);}
            };
            
            @Override
            public IExpressionObjectFactory getExpressionObjectFactory() {
                return new IExpressionObjectFactory() {
                    
                    @Override
                    public Set<String> getAllExpressionObjectNames() {
                        return names;
                    }

                    @Override
                    public Object buildObject(IExpressionContext context, String expressionObjectName) {
                        if(KEY.equals(expressionObjectName)){//名前が一致したなら
                            return new OreOreUtil();
                        }
                        return null;
                    }

                    @Override
                    public boolean isCacheable(String expressionObjectName) {
                        return true;
                    }
                };
            }

            @Override
            public String getName() {
                return "OreOreUtilDialect";
            }
        }
        
        //----------------------------------------------------------------------
        //ここから下が実行
        //----------------------------------------------------------------------
        
        
        //準備
        TemplateEngine engine = new TemplateEngine();
        //オレオレ設定追加
        engine.addDialect(new OreOreDialect());


        String template = "[[${#oreore.num(a+b)}]]";


        Map<String, Object> params = new HashMap<>();
        params.put("a", 1000);
        params.put("b", 20000);

        IContext context = new Context(Locale.getDefault(), params);

        //生成
        String result = engine.process(template, context);

        //出力
        System.out.println(result);
    }
}

実行結果は同じです。

21,000

#oreore.num()でアクセスできているのがわかりますね。

Thymeleaf 3.0を試す その2 エスケープの有無

Thymeleaf 3.0を試す
の続き。

前回は以下のようになっていましたね。

        //テンプレート
        String template = "ぼくは[[${hoge}]]ではありません。";

        //パラメータ
        Map<String, Object> params = new HashMap<>();
        params.put("hoge", "変態");


このパラメータを

        params.put("hoge", "<<変態>>");

のようにしてみます。


実行。

ぼくは&lt;&lt;変態&gt;&gt;ではありません。

あ、勝手にエスケープされてますね。エスケープされたくない場合もあるでしょう。その場合はテンプレートを以下のように変えます。

        //テンプレート
        String template = "ぼくは[(${hoge})]ではありません。";

実行。

ぼくは<<変態>>ではありません。

つまり、

[[〜]]

エスケープありで、

[(〜)]

エスケープなしとなります。

Thymeleaf 3.0を試す


長いのかったるいのでシンプルにいきます。面倒な設定もなしです。IDEやビルドシステムすらいらないレベルでさくさくといきます。

ダウンロード

https://bintray.com/thymeleaf/downloads/thymeleaf/view

ここの下のほうにあるthymeleaf-3.0.0.RELEASE-dist.zipとかいうファイルをダウンロードします。

zipの中のlibフォルダにあるjarとdistフォルダにあるthymeleaf-3.0.0.RELEASE.jarをライブラリに追加します。
各自IDEにあわせて設定してください。

コード

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.IContext;

public class Thymeleaf3 {

    public static void main(String[] args) {
        
        //準備
        TemplateEngine engine = new TemplateEngine();
        
        
        //テンプレート
        String template = "ぼくは[[${hoge}]]ではありません。";

        //パラメータ
        Map<String, Object> params = new HashMap<>();
        params.put("hoge", "変態");
        IContext context = new Context(Locale.getDefault(), params);
        
        //生成
        String result = engine.process(template, context);
        
        
        //出力
        System.out.println(result);
    }
    
}

実行結果

ぼくは変態ではありません

おわり。

SFC ファーランドストーリー クリア

概要

1995年発売のスーパーファミコンシミュレーションRPGです。

これはPC-9801用ソフトのファーランドストーリー1作目と2作目を融合させた作品です。
2作目の後半のストーリーが少し変更されていますが、基本的に同じものと考えてよいでしょう。

SFCにはファーランドストーリー2もありますが、こちらはPC98の作品とは何の関係もありません。


1995年発売ということで、1996年のPC-FX版や1997年のPSやWindowsに再移植された四つの封印の大本といえます。

LVは1部(1作目部分)と2部(2作目部分)とでリセットされません。このあたりもPCエンジンイース1/2のようなものですね。


PC98版ももっていますが、キャラ会話が専用の画面に切り替わるのが大きな変更点でしょうか。それ以外はUI的にそれほど差はないと思いますが、この変更だけでもわりと感覚は違ってきます。

https://shinsan.s3.amazonaws.com/diary/2016/0509-01.png

ゲームシステム

シミュレーションRPGということで、基本はファイアーエムブレムのようなものです。

大きな違いは、以下のようになります。
・マップはHEXで移動させにくい
・道具は全キャラで統一されたもの
・アイテムの受け渡し、道具の使用、装備変更ではターン消費せず
・補助系魔法など一切なし
・プリースト系の回復スキルはかならず全快するものを1つだけ
・敵キャラの動きがやる気がない
・移動力が全体的に少ない


最後のところですが、これがなかなか厳しいです。なんせ、平地を歩くときキャラの移動マス数はそのほとんどが3-2マスです。これは異常に足が遅く前キャラを目的地に移動させるのに時間と手間がかかります。

一応主人公には集合メニューがあり、それを使うと簡単に集められるのですが、問題は地形があるとひっかかって主人公によってこないことです。あまりにも適当すぎます。

ゲームバランス

難易度は非常に低いです。やられてしまった味方をアイテムやプリースト系の回復魔法でよみがえらせることができます。回復アイテムの使用もターンを使いません。敵の攻撃を受けた後、自分のターンで回復、攻撃して反撃を受けた後また回復、そしてターン終了、といったことも可能です。アイテムの所持も個人ごとではなく、全体で一つのアイテムセットとなっています。そのため、薬草を大量に持っているとそれだけで十分です。ターンを消費しないことからわかる通り、回復量も一番少ない薬草を複数回使うで最終面まで十分だったりします。

1部はほぼファーランドストーリー1作目そのもののため、移動が異常につらい以外は割と問題ありません。
1部は成長がヘタレた場合を考慮してかパラメータを増やすドーピングアイテムが店売りされていて、どうにでもなります。ドーピングアイテムは使わなくてもクリア可能な万全のバランスです。

問題は2部です。こちらはドーピングアイテムがないのでヘタレると最悪です。特に素早さが足りないキャラがわりと多く、雑魚戦で死にまくるキャラが固定化されます。また、雑魚の強さがよくわからない設定も多く、以前の章より後から追加される敵キャラのほうが弱いといったことがなぜか起こります。また、1部から引き続いて登場する雑魚キャラのほうが強いことも多いなどよくわかりません。

2部最後のラスボスの素早さ設定も異常で、主人公も含めて素早さが育ったキャラも含めてあらゆるキャラが一撃で殺されることがほとんどです。主人公がやられるとゲームオーバーになるため、主人公以外でダメージを与えておいて、最後に主人公でとどめだけをさすというのが必要になります。

LVUP回数が1部と比べて10回ほどは多いため、1部時点では問題になりにくかった素早さの問題が発覚しやすいことなど、ドーピングアイテムが必要なのはむしろ2部の方だったのではないでしょうか。


これだと1部は問題ないように感じますが、実際のところMAPを移動しまくる感じは1部のほうが多く、敵キャラの配置や召喚などを考えても移動をひたすら行う場面が見られます。戦闘バランスは2部では崩壊していても、MAPの敵や町などの配置などは1部より良くなっているということです。

ユニットの特徴

職業ごとに特徴というか隠しパラメータ的なものがあり、画面に表示されるステータスがわりとあてにならないことが多いです。

ウィザードとソーサラーは魔法抵抗があります。ステータスの魔法防御に関係なく魔法に強いです。もちろん、これらのキャラは魔法防御も高いのでさらに魔法に対しては圧倒的な強さを持ちます。同じ魔法系の最初から上級のメイジは魔法防御は高いですが、魔法に強いという特徴はないです。そのため、魔法防御が同じソーサラーなどと比べて受けるダメージが大きいです。

ドワーフ系は魔法にめっぽう弱いです。魔法防御自体も低いのですが、その数値以上に異様にダメージを受けます。

空を飛んでいるセイレーン族は弓に弱いです。これはイメージ通りだと思うのですぐ気が付くかもしれません。

ナイトは弓に強いです。


敵専用ユニットですが、サキュバスは男性キャラに対して圧倒的に強いようです。


あと、2部に登場しないキャラもいます。2部は職業が被らないようになっていて、ユニットの外見ですべてキャラ名が判別可能です。1部はないとは3キャラ、バードは2キャラ、プリーストは2キャラになるためキャラのステータスを見ないと判別できません。これはかなり苦痛です。また、2部で使えないのならそいつらを無理に成長させる必要もありません。経験値をその分別のキャラに割り振れば2部は少し楽になったのかなとか思いました。もっとも2部は基本簡単なのですが。

ストーリー

割とどうでもよいお話ですが、ファイアーエムブレムが1作目からこなれていたのに対してこちらのテキストは結構ひどいです。
同人ソフトなら納得する範囲ですが、95年時点で商用でこれはなかなか珍しい部類かもしれません。

サウンド

全体的にひどい完成度ですが、BGMだけはまったく問題ない完成度となっています。
効果音周りが演出含めてあまりやる気がないとは思いますが、BGMはよいのでサウンドは差し引きゼロといったあたりでしょうか。


そのほか気になったキャラ達

飛行をしているので4マスという驚異的な移動力を誇る。4マスが驚異的なのはこの作品だけ。FEだったらアーマー系だよなぁ。
https://shinsan.s3.amazonaws.com/diary/2016/0509-07.png
ワルキューレの専用槍は近接が物理、間接が魔法という直間両方が使えるだけではなく属性も使い分けできるというすぐれもの。ステータス的には可もなく不可もなくといったところか。若干打たれ弱いが、問題はないレベル。専用最強武器は近接物理。1部、2部ともに途中から仲間になるが使いやすいので問題なし。


2部からの途中参加キャラの割に専用のお話とマップが用意されており、初期HPの異様な高さと魔法系唯一敏捷さが伸びるため圧倒的に使いやすかった。
https://shinsan.s3.amazonaws.com/diary/2016/0509-02.png
https://shinsan.s3.amazonaws.com/diary/2016/0509-03.png
顔もおちついた感じで優遇されている感じか。専用最強武器は間接魔法。


主人公の幼馴染の魔法使い。ライアと比べてどれだけ弱いのかがわかる。魔法抵抗もちではあるが、敏捷さがほんとやばい。
https://shinsan.s3.amazonaws.com/diary/2016/0509-08.png
表示バグ。
https://shinsan.s3.amazonaws.com/diary/2016/0509-06.png
ウィザードの最強武器は近接魔法。でも説明のところには間接と書いてある。間接だったら使いやすかったろうに。1部の3章、2部の3章からと早くから使えるのが強みだが、それだけ。


近接物理オンリーですが魔法防御以外の伸びが非常によいので使いやすいです。最強専用武器ももちろん近接物理で使い分けの必要がない。
https://shinsan.s3.amazonaws.com/diary/2016/0509-04.png
ドワーフ族の族長はバーサーカーだったのでまじめなこいつに変わったほうが良いのは間違いないです。
https://shinsan.s3.amazonaws.com/diary/2016/0509-09.png


物理オンリーながらも近接と間接両方扱える投げ斧を使いこなすドワーフの族長はステータス以上に相当使いやすいです。
https://shinsan.s3.amazonaws.com/diary/2016/0509-11.png
ドワーフたちは1部2章、2部は最初から仲間になるため非常に使い勝手が良いです。


主人公の剣の師匠。1部の最初からいます。2分も2章からと使いやすい。らしいですが、ステータスはかなり散々です。最初強ければFEのジェイガンのポジションもあったでしょうが、そういうこともなく。
https://shinsan.s3.amazonaws.com/diary/2016/0509-10.png
ただし、1部の時点ではステータスがこれほど話されていないこと、武器自体は使いやすい近接間接物理の投げやりを使いこなすため、問題にはなりません。問題は2部の後半おいていかれることですね。敏捷さが問題になるのも2部から。


そして2部に登場しないキャラのエンディングはこれくらい適当な扱い。
https://shinsan.s3.amazonaws.com/diary/2016/0509-05.png

ボリューム

ファーランドストーリー1作目から14話全部。
ファーランドストーリー2作目全14話のうち直接的に関係のない外伝3話を除いた11話を収録。
合計25話。ボリューム的に14話だと短いと感じるのでちょうどよい。ただ、第2部はひたすら追いかけるだけなのでお話が適当過ぎ。1部の幼馴染を救う、敵から大切な封印アイテムを守るといったところがあまりない。
この25話というのはちょうどファイアエムブレム初代のボリュームなのでよい塩梅だとは思う。

移動が遅いので時間はかかりやすいもののリセットはまずないので思ったよりは時間はかからないだろう。集合をうまく使えばよい。また、いつでもどこでもセーブができるのでそこの地点からのやり直しもできる。ボス前などやばい時や調子が良い時は3カ所まで好きにセーブできるのでそれを使いこなせば冒険もしやすい。

評価

いつもの5段階評価。おすすめかかどうかは総合評価を見てもらえれば。

  評価
システム ★★−−−
シナリオ ★★−−−
サウンド ★★★−−
グラフィック ★★★−−
総合評価 ★★−−−

とにかく移動が苦痛。それさえ我慢できれば入門的には問題ないかもしれません。

ですが、これやるくらいならファイアーエムブレムシリーズをやるほうが何倍も満足度が高く、そちらのほうがおすすめです。

際物好きならよいですが、スクリーンショットのきれいさだけをみてプレイすると結構苦痛だと思います。

デジゲー博 2015 いってきた

2015/11/15デジゲー博なるものがあったので去年に引き続き行ってみた。これは同人、インディーの即売会。まぁソフケとかMI68とかそういうものと同じ。

かなり久しぶりの秋葉原駅。男子トイレがすさまじく臭いのだが、換気扇ぶっ壊れてる感じかね、これ。もともと1カ所しか換気するところなさそうにみえたけど。あと、男子トイレではおなじみの大のほうは相変わらず並んでる。

同じ同人ソフト即売会でMI68との違いがどうたらとかTwitterでつぶやいてしまったので比較しないわけにはいかないだろう。

会場の雰囲気

前回までのMI68と比較するとやはり若い人が多い。20代もかなりいると思われる。MI68はレトロゲーイベントではないのだが、レトロゲー率がやはり高いので、ここは仕方がない所だろう。次回のMI68も多分年齢層は高めだろう。講演内容もあるかもしれない。そういやデジゲー博には講演はないな。そこが差別化か。

逆に若い人はMI68などのイベントで30年前のパソコンを一度は目にしてみたほうがいいかもしれない。クロック周波数が今のスマホの1/500とか、メインメモリがKBやMB単位で、数千分の一とかそういうので動かすわけだ。ハードディスクもない場合も多く、そもそもフロッピーディスクドライブすらない場合もある。

おっと、話がそれた。

会場の雰囲気は前回のイケイケなリア充のウェーイな雰囲気から一変して、いたってごく普通の即売会寄りになったと感じた。VR系や東方を前面に押し出してメディアや外人などが目立った去年と比べると明らかに違う。

また、完成してないものや遊べない、遊びにくいものがおおあった去年と違い、今年は感覚的なもので申し訳ないが、ちゃんと体験版を100円など有料配布していた。もちろん、無料配布しているところもあるが。

2D系も多めに感じたし、ちゃんとドット絵が多く感じられた。のっぺり系の絵や2Dではあっても物理演算でいかにもUnity等でこねくりまわしてつくった、3Dものとかそういうのもあるが、前回よりは2Dのゲームのほうが目立つ感じはあったと思う。これも感覚的なものでもうしわけないが、スマホ系はだいぶ減った感じもあった。

展示について

一般参加側から見てふと思ったことを。

スマホ用、DL専用はいい内容のものでもきつい

出店しているソフトはパソコン向けのほかにはやはりスマホタブレット向けのものも前回同様そこそこある。

スマホタブレット向けのものはどうしても一般のマーケットを通るため、ダウンロード専売になってしまうのでその場で購入とはなりにくい。残虐表現などきわどい描写も難しいだろう。

また、どうしても画面は小さく目立たない状態。
それに他人のタブレットスマホにタッチするというのもそこそこ躊躇しやすい。即売会ではやっぱりスマホ系の展示は終わっているというのは変わらない。かえるのは難しいだろう。

とはいうものの、食っていくためのプラットフォームとしてはここ以外現状無理といってよいのでこの即売会との相性の悪さは何とかしないと未来はない。

すでに何らかのソフトで成功していて、黙っていても客が群がる状態ならこの限りではないだろうが。

液晶品質大事

ディスプレイの種類は展示で重要な要素の一つ。テカテカ液晶はやはり圧倒的に目立つ。開発時は気に入らないとしても展示するならテカテカ液晶で13インチ以上はぜひともほしいところだ。これだけで印象が大きく変わる。同人でならともかく、インディーとして食っていくなら必須の装備といってよいだろう。

対応機種書いてないところ多すぎ

これは本当に困った。対応機種を書いてないところがものすごく多かった。これでは買いたくても買えない人も多いだろう。

インスト必要

一般参加者に触ってほしい、そう考えるなら口で説明するのではなく、紙に書いておいておくとよいと思う。
それだけでコントローラを手に持つ人は一気に増えるだろう。

基本操作が想像しやすい格闘であっても、コマンド表は必要だろうし、STGは大抵どこかかならず特殊な仕組みをみんなぶっこんでいるはずだ。
マニュアルがいらないと考えるのは作った本人だけ。なんでも仕組みを知り尽くしている本人はこのへん意外と気が付かないもの。

かわいいは正義

room6さんところはとにかくかわいいを前面に押し出していて雰囲気が良く、ここだけ別次元のように感じた。同人ソフトの即売会ではないが、ゲームレジェンドではこういう感じのブースがたくさんあるのでそういうのが好きな人はいってみるとよいだろう。

音楽の良さはアピールできない

聞いてもらわないといけないため会場のうるささ、隣のブースへの配慮などもあって音楽のアピールは向かない。ゲームという一つのジャンルであり、音楽専用のエリアなどに分けられているものでもないため、わざわざヘッドホンをするというのは手間であり、人が多ければ多いほど流れを止めてしまいやすくつらい。

戦利品

買ったのは今年も1つだけ。去年は体験版を買ったんだったかな。

OSENBEI

早寝早起き腹八分さんの横スクロールSTG。モノクロでゲームボーイを意識している感じだ。
プレイしていてやはりSTGはいい、作りたい!と、STGの全盛期をふと思い出すなどした。武装の法則性が全然わからないのでそこだけ聞きたいところ。

宣伝動画があるのでこれ見たほうが早い。
Windows版のほかMac版も収録されているのが珍しい所か。

CSCD 21.5

クリエイティブスタッフさんところのゲーム詰め合わせ。
無料。

大学のゲーム製作サークルらしい。うらやましい。自分も学生時代にそういうのやってみたかった。

次回は

次回があるかどうかはわからないが、今回の方向なら次回も参加してよいと思った。会場の雰囲気がよいほうに変わったと感じた。

新規開発ならAndroid 4.0系は切ってよさそう

http://shinsan.s3.amazonaws.com/diary/2015/1112-01.png

http://developer.android.com/intl/ja/about/dashboards/index.html

現時点で新規開発なら4.1以上でOK。

4.0と4.1では安定度が別次元。OSのほかにハード的にも2.3からのアップグレード組があるから4.0サポートは割とつらい。



4.3までを切ることができればOSの安定性やチップの速度などからかなりよくなるはず。

そこまでいかなくとも4.1と4.2でもGCの動き結構違うので4.2以上ができるとかなりよい。


5.0以上は結構伸びてるぽい。日本だとやっと夏から出た感じだけど、買い替えサイクル的に一気に4.2以下は消えていくと思われる。


OpenGL ES3 専用は…しばらく無理そう。