TextMeshPro - ことはじめ的なやーつ!【Unity】

この記事での環境

  • Unity 2017.3.0f3 Personal(64bit)
  • TextMemsh Pro - Beta 0.1.44
  • 導入
    • ~ unity2018の場合 ~
  • UGUIのTextに代わるTextMeshProのUI用Text
  • Font Asset Creator フォントアセットを作る
  • TEXT INPUT BOX
    • Rich Text タグ
  • FONT SETTINGS
    • Color Gradient でグラデーション
    • マテリアルを使う
    • 縁取り
    • スクリプトから縁取りの色を変える
  • 関連
続きを読む

今日のjavaおっかけ(20170929):ラムダ〜streamAPIのざっくり

基本

Runnableインタフェースをラムダの書き方で実装した場合。

            Runnable runnable1 = () ->{
                System.out.println("lambda!");
            };
            runnable1.run();
  • 結果
lambda!

Runnableはご存知の通りrunメソッドしかない。 戻り値と引数もない。

なので、上記のように、runメソッドの処理を特にrunというメソッドを宣言せずに実装できた。

関数型インタフェース 「引数とか戻り値ある場合はどうなる?」

関数型インタフェースという仕組みを使う。

この後のstreamAPIも絡むので、よく使われるであろう3つについてかく。

Function<T,R>

https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Function.html

T は引数の型。R は戻り値の型を指定する。

Function<Integer, String> asterisker = (i) -> { return "*" + i; };
String result = asterisker.apply(10);
System.out.println(result);
  • 結果
*10

上記は10という数字を引数で渡して、アスタリスクの文字列を先頭に足して文字列を返す処理。

引数2つ渡したい!なんて場合は、BiFunctionなんてのもある。

https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/BiFunction.html

BiFunction<Integer, Integer, String> asterisker = (i, i2) -> { return "*" + (i * i2); };
String result = asterisker.apply(10, 2);
System.out.println(result);
  • 結果
*20

Consumer

https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Consumer.html

T は引数の型。Functionの戻り値がない版?

Consumer<String> buyer = (goods) -> {
  System.out.println(goods + "を購入しました");
};
buyer.accept("おにぎり");
  • 結果
おにぎりを購入しました

Predicate

https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Predicate.html

T は引数の型。testメソッドは評価した結果をbooleanで返してくれる。

Predicate<String> buyer = (goods) -> {
  return goods.equals("おにぎり");
};
boolean result = buyer.test("おにぎり");
System.out.println(result);
  • 結果
true

Comparator として使う

関数型インタフェース、そもそもどういう使い方するの?ってところ。。

int[] numbers = {-1, 2, 0, -3, 8};
List<Integer> numbersList = new ArrayList<>();
for(int n : numbers){
  numbersList.add(n);
}

前提

まず数字が入ったリストを適当に用意した。この数字の順番をソートしたい。

Collections#sort の第二引数では、ソートする方法をComparatorで定義することができる。

本題

下記は、Comparatorをラムダで、小さい値→大きい値にソートするように書いた例。

Collections.sort(numbersList, (a, b) -> { return a - b; });

for(Integer n : numbersList) {
  System.out.print(n + ",");
}
  • 結果
-3,-1,0,2,8,

streamAPI

まず、リストなどの大元であるCollectionsstreamというメソッドがjava8から追加された。

Stream<E>を戻り値で返してくれる。

https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html

先ほどと同じように、数値型のリストに適当な値を入れておきました。

int[] numbers = {-1, 2, 0, -3, 8};
List<Integer> numbersList = new ArrayList<>();
for(int n : numbers){
  numbersList.add(n);
}

forEarch

numbersList.stream().forEach((i) -> {
    System.out.print(i + ",");
});
  • 結果
-1,2,0,-3,8,

リストの中身が変数i に入ってくるので、それをsysoutしているだけのプログラム。

forEarchConsumerを受け取るので、 今回の数値の場合だと、Constumer<Integer>を受け取っていることになる。

filter

numbersList.stream().filter((i) -> {
    return i > 0;
}).forEach((i) -> {
    System.out.print(i + ",");
});
  • 結果
2,8,

意味の通り、フィルタリングしてくれる。

filterPredicateを受け取るので、 Predicateの中で評価してbooleanの値を返しtrueのものだけ抜粋する。

map

numbersList.stream()
  .filter((i) -> { return i > 0;})
  .map((i) -> {
    return "*" + i + "*"; })
  .forEach((s) -> {
    System.out.print(s + ","); });
  • 結果
*2*,*8*,

mapFunctionを受け取るので、 Functionの中で受け取った数値を文字列として返している。

Xcode8.3でxvimを使う

この記事は

https://github.com/XVimProject/XVim

xvimとはxcodevimが使えるようにするプラグインのことです。

今回はこれをxcode8.3に入れます。

xcodeをバージョンアップしたらxvimが使えなくなってしまったので、それの解消方法をまとめときます。

この記事は以下の記事から今回自分が必要だった部分だけ抜粋させていただきました。感謝。

www.ie-kau.net

qiita.com

試した環境

macOS sierra  Xcode8.3.2(8E2002)

本題

まず古いのが残っている場合は消します。

cd ~/XVim  // Xvimを置いてるディレクトリへ移動。このディレクトリは適宜変更してください。
make uninstall
rm -r ~/XVim

証明書を作って、それを登録します。

https://github.com/XVimProject/XVim/blob/master/INSTALL_Xcode8.md

証明書を作る手順は上の通り。

ここでは上の手順の通りに XcodeSigner という名前で作ったので、それを登録します。違う名前で作った人は XcodeSignerの部分を変えてください。

sudo codesign -f -s XcodeSigner /Applications/Xcode.app  

keith さんのコードを使う

xcodeを8.3にした時点で何度かインストールをしてみたのですが、make自体が通らなくなってしまいました。

issueに上がっていたみたいですでに対応してくれた人がいるらしいのでそちらのソースでコンパイルすることにします。

github.com

git clone https://github.com/keith/XVim.git
git fetch origin xcode-8.3-release
git checkout xcode-8.3-release
make

これでmakeが通るようになりました。

UUIDを登録する

github.com

手動でやってもいいんですが、一括でやってくれる上のツールをインストールします。

gem install update_xcode_plugins
update_xcode_plugins

自分の場合、これでうまく行かなかったので以下をしたところ、無事xvimが有効になりました。

update_xcode_plugins --unsign

Execution failed for task ':android:compileReleaseJavaWithJavac'. compileSdkVersion 'android-24' requires JDK 1.8 or later to compile.

apkファイル作ろうとした際に以下のエラー発生。

Execution failed for task ':android:compileReleaseJavaWithJavac'.compileSdkVersion 'android-24' requires JDK 1.8 or later to compile.

この直前に targetSdkVersionを24にあげてました。

エラーメッセージにある通り、API24 から?(おそらく。23では大丈夫だったため) JDK1.8 が必要になったらしいです。

javaのバージョン確認

インストールしてあるjdkのバージョンを確認。

java -version

または

javac -version

知らなかったけど、コンパイラのバージョンを見るときは, java じゃなくて javac でみたほうがいいらしい。

jdk7をアンインストール → これでとりあえず解決したよーー

確認した結果versionは1.8でした。なのにこのエラーが出る。

javaが複数いるっぽい気がしたので、/Library/Java/JavaVirtualMachinesディレクトリを見てみると、jdk7と8がいる。#Mac OSX Yosemite でやってました。

なんとなくjdk7のほうが使われているようなので、jdk7をアンインストールしてみます。

JDK 7 Mac Install

oracleの↑のページの通りにやればいい。ディレクトリごと消すだけ。権限がないときは、sudo は必要でした。

rm -rf jdk1.7.0_06.jdk

これはjdk7の手順みたいです。jdk6以前は違うみたいなので注意。

これでとりあえずいくようになりました。

直接android studio 使っている人とかは、android studio の設定で使うjdk決めれたりするみたいだし、 jdkのバージョン複数持ってないといけない人もいると思うので、古いバージョンは削除してもOK! な環境な人しかダメなんで、とりあえずってかんじです…

libgdxでscaleするの起点位置の指定の仕方

ふと、scaleする起点?中心?の位置が画像の左下とか真ん中とかしかやったことなくって、

= Actor#setOrigin (int alignment)

画像内の好きな位置にしたかったんだけど、わかんなかったからしょぼいけどメモ。

public class MyGdxGame extends ApplicationAdapter {
    SpriteBatch batch;
    Image img;
    Stage stage;
    
    @Override
    public void create () {
        stage = new Stage(  );
        batch = new SpriteBatch();

        img = new Image(new Texture("badlogic.jpg"));
        stage.addActor(img);
        //img.setOrigin( Align.center ); //真ん中
        //img.setOrigin( img.getWidth()/2, img.getHeight()/2 ); //これも真ん中
        img.setOrigin( img.getWidth() / 2, 0 );  //
        img.addAction( Actions.scaleTo(0.0f, 0.0f, 2f) );

    }

    @Override
    public void render () {
        Gdx.gl.glClearColor( 1, 0, 0, 1 );
        Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
        batch.begin();
        stage.draw();
        batch.end();
        stage.act( Gdx.graphics.getDeltaTime() );
    }
    
    @Override
    public void dispose () {
        batch.dispose();
    }

cocos 2dx メモ(整理するまでcppのないようも含んでると思う

xcodeで作ったクラスをandroid用にビルドする時には、Android.mkにクラス名を追加

HelloCocos/proj.android-studio/Android.mk

android-studioでビルドしているのでこのディレクトリは以下のAndroid.mkを編集する

LOCAL_SRC_FILESにcpp名を追加する

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../../Classes/AppDelegate.cpp \
                   ../../../Classes/HelloWorldScene.cpp \
                   ../../../Classes/LogoScene.cpp \
                   ../../../Classes/MainMenuScene.cpp \
                   ../../../Classes/HighScoreScene.cpp

android用にビルド

cocos2d-x-3.10//tools/cocos2d-console/bin/cocos run -s ~/snk_cocos/snk -p android --android-studio

毎フレ呼ばれるupdateメソッドを使う

事前にinitとかで以下のcocos2d::Node#scheduleUpdateを呼んでおく必要がある

this->scheduleUpdate();

updateメソッドがマイフレ使える

void update(float dt);

リファレンスカウンタ

snoopopo.hatenablog.com

インクルードガード、宣言と定義

・メンバがポインタの場合は、宣言でいい。定義はいらない=ヘッダをincludeしてクラスの定義を読み込む必要がない。

・引数、戻り値も宣言でいい。

・メンバが実態の場合は、定義を持つ必要がある。

・意識せずにヘッダを2回includeしててclassが二重定義になってエラった → インクルードガードすればOK。

⇒基本的に全部のヘッダはインクルードガードする!

#ifndefマクロは、xxが定義されてなければ #endifまでで囲った処理を実行する、という意味なので、 これで、クラスの定義が1度しか呼ばれないことになる。

#ifndef  _PART_H_
#define  _PART_H_ //1回目のみ呼ばれる

namespace cocos2d {
    class Vec2; //cocos2d::Vec2というクラスがあるよ、という宣言。Vec2はポインタで持っているので定義はいらない
}

class Part : public cocos2d::Node
{
    
public:
    Part(cocos2d::Vec2* pos);
    ~Part();
    Part* getPos();
    void setPos(Part* pos);
private:
    cocos2d::Vec2* _pos;
};

#endif // _PART_H_

rand()

cppでランダムな数値を取得するにはrand()が使える

rand() % 3;

上記の例は、0〜2までの値を取得できる。ランダムな数値を3で割った割った余は、0〜2の数字だからだ。

Action

cocos2dxにもlibgdxと同じでActionの概念がある。

・NodeにrunActionメソッドを持っているのでそれに登録してあげればいい。

//3秒で180度回転。単位は「度」でOK
runAction(RotateBy::create(3, 180));

・上記のままだと等速で処理を行うのでだんだんはやくしたりとかしたい場合はイージングを設定する

runAction(EaseIn::create(RotateBy::create(3, 180), 2));

・単純にxxの処理をしたい、という場合はCallFuncNを使う

    auto print = CallFuncN::create([this](Node* node){
        printf("aaaaaa");
    });

・シーケンス 順次実行 Sequence

auto rotate = EaseIn::create(RotateBy::create(3, 180), 2);
auto scale = EaseIn::create(ScaleBy::create(1, 0.5f), 3);
auto action = Sequence::create(rotate, scale, NULL); //最後は必ずNULLを設定しないとダメ
    
runAction(action);

reference count should be greater than 0

リファレンスカウンタ周りのエラー。

基本的にcocos2d-xのクラスはRefクラスを継承していて、リファレンスカウンタの仕組みを使用している。

Node#createインスタンスを生成する((newはスコープで制限されてるので呼べない))とRef#autorelease状態のインスタンスを取得できるが

クラスのメンバ変数は、自分でreleaseさせたいので、自分でリファレンスカウンタを意識する必要がある。

これがちゃんとなっていない所為で上記のエラーメッセージが出てたのでメモ。

とはいえ、カウンタを操作するRef#retainRef#releaseは、自分で呼びたくないので、マクロを使います。

//Part.h

class Part : public cocos2d::Node
{
public:    
    CC_SYNTHESIZE_RETAIN(cocos2d::Sprite*, _sprite, Sprite);
};
}

CC_SYNTHESIZE_RETAIN で宣言すると、内部的にRef#retainを呼んでくれる。setter,getterも自動で作られる。

//Part.cpp

Part::Part(Vec2* pos) : _pos(pos), _sprite(NULL) //まずnullを初期設定
{
 //画像をセット。テクスチャアトラスからとってきてます。
    this->setSprite(Sprite::createWithSpriteFrameName("snake_down.png"));
}

Part::~Part()
{
    CC_SAFE_RELEASE_NULL(_sprite);
}

・デストラクタでCC_SAFE_RELEASE_NULL呼んで、Ref#releaseする。