Edited at

openFrameworksでiOSアプリをつくった所感oF全般編

More than 3 years have passed since last update.


概要

iOSアプリをつくる要件があったが 

swiftとかObjective-C勉強する時間がなく、

openFrameworks(以下oF)ならなんとかできたので

oFをつかってiOSアプリをつくった。

それを通して新しく知ったこと、初めて使ったAddonまとめ。

iOSにかぎらずoF全般的なこととiOSのみのことの2部構成です。

・ openFrameworksでiOSアプリをつくった所感oF全般編(本記事)

・ openFrameworksでiOSアプリをつくった所感iOS限定の機能編


次書こうと思っていたらほとんどこっちに書いていたのでネタがいまいちなかったです(9/2)


tr1/memory エラー


内容

これは本当に困った。

Addon入れた後や作業再開した時になぜか出て困った。

PCのoFでは見たことなかったが調べていたらPCでも出るみたいなので

こちらに書いておく。


対策

https://github.com/openframeworks/openFrameworks/pull/2764

に書いてあるとおり

・ Build Setting->architecturesのBaseSDKとかが他の動くプロジェクトと同じになってるか確認する

・ Build Setting->Apple LLVM 6.1 -Language - C++のC++ Standard LibraryをCompiler Defaultからlibstdc++にする

ということなんだけれどそう設定しても全然対策にならなくて

最初は諦めてもう一回最初からプロジェクトつくってたが、途中で対策を発見した。

ずっとプロジェクトのbuild settingを見ていたのだが

openFrameworksというフォルダの中に「iOS+OFLib.xcodeproj」

というプロジェクトがありこっちのC++ Standard Libraryが

Compiler Defaultになっていた。

libstdc++に直したら無事に消えた。


ofxStateMachine


ofxStateMachineを使用してみた

oFでシーンの切り替えなどができるライブラリ

ofxStateMachine


使用シーン

iOSアプリなので最低限のシーンの切り替えが必要。

さすがにofApp.mmの中だけで出し分けるのはつらそうなので今回はじめて使ってみた。

ちなみにoFでも普通にストーリーボードとか画面推移できるらしいが

その辺調べている時間がなかったのと不慣れなところに突っ込むのは

やめようということで断念。

制作終盤に

/example の中に

iosCustomSizeExample

iosStoryboardExample

を見つけた。悔しい。

でもiosStoryboardExampleはビルド通るけど実行すると止まる。


使い方と注意点

大体の使い方は

田所淳さんのサイト: yoppa.org

によくまとまっています。

これを参考にしましょう。


基本

addon入れて、ofApp.h, ofApp.mmに諸々書いて、新しくC++ファイル(hoge.h, hoge.cpp or hoge.mm)つくって

changeState("hoge")

でシーンがうつります。


シーン間で変数を共有したいとき


sharedData.h

class sharedData{

public:

int hoge = 10;

};


みたいなクラスつくる


ofApp.h

itg::ofxStateMachine<sharedData> stateMachine;


とかく


ofApp.mm

stateMachine.getSharedData().hoge = 100;

int fuge = stateMachine.getSharedData().hoge;

みたいな感じで使う

シーンクラスでは


opening.h

class opening: public itg::ofxState<sharedData>{

void setup();
void update();
void draw();
}

みたいにシーンファイルで継承?する。


opening.mm

getSharedData().hoge = 100;

int fuge = getSharedData().hoge;


使う。


注意点

思い出しながら書いているので漏れてるプロセスとかあるかもしれない。

少し考えれば当たり前なのだがsetup()はシーンが変わるたびに

呼ばれるわけではなく実行時に全部のシーンのsetup()が呼ばれる。

なのでむやみにメモリ使い過ぎるのはよくなさそう。

そういうことなのでシーンが変わる瞬間はどうやって判別しようかという

ことになる。

→update()にフラグつくって管理した。

頭悪い感じになってしまった。

今思えばなにか方法ありそう。

あと切り替わり時にupdate()が呼ばれる前にdraw()から始まること

が最後の方あった。突然起きた現象だったので自分の実装が悪い感じもする。


ofxTween


oFでもjs界隈で人気のTweenMaxみたいなことが手軽にしたい。

こんなのあるらしいです。

ofxTween


使用シーン

もうofVec2f pos(0,0);みたいなのつくって

pos.x++;みたいなので動かすことから卒業したい。

楽にTweenしていい感じのアニメーションにみせる。


使い方と注意点

こちらのブログに大変良くまとまっています。

ありがとうございます。


基本


ofApp.h

#include "ofxTween.h"

()
ofxEasingCirc easing_circ;
ofxTween tween;


ofApp.mm

void ofApp::setup(){

tween.setParameters(0, easing_circ, ofxTween::easeOut,0, 500, 1000, 500);

}

void ofApp::update(){
tween.update();
}

void ofApp::draw(){
ofBackgounr(255);
ofSetColor(0);
ofCircle(0, 0, tween.getTarget(0));
}


こんな感じ。


tween終了時にコールバックも欲しい


ofApp.h

#include "ofxTween.h"

()
ofxEasingCirc easing_circ;
ofxTween tween;
void callback(int &e);


ofApp.mm

void ofApp::setup(){

tween.setParameters(0, easing_circ, ofxTween::easeOut,0, 500, 1000, 500);
ofAddListener(tween.end_E, this, &ofApp::callback);

}

void ofApp::update(){
tween.update();
}

void ofApp::draw(){
ofBackgounr(255);
ofSetColor(0);
ofCircle(0, 0, tween.getTarget(0));
}

void ofApp::callback(int &e){
switch (e) {
case 0:
~
break;
case 1:
~
break;
default:
break;
}
}


こういう感じに書く。

callback関数内でswitchで切り替える

この時の引数eはsetParametersの第一引数。


ofApp.mm

case 0:

setParameters(1, .....);

とかけばこれが終了時にeは1になる(はず)


注意点

注意点というか、とても便利なんだけれど色んなところに

色んなことを書くの結構めんどくさいです。

ofxTweenたくさんつくってそれぞれコールバックとるのとか

イヤだなー

たくさん使うときは

vector <ofxTween> twn;

みたいな感じにしてみた。


ofxJSON


oFでjsonファイルつかいたい

こんなのあるらしいです。

ofxJSON


使用シーン

あらかじめ決まってるデータとかをプログラム側に配列として

格納していくのは結構めんどくさいし増えた時の管理もしづらいと思ったとき

今回は違うけどcsvデータで来たなにかをビジュアライズ的な感じで使うとき

JSONで返ってくるAPI叩くとき


使い方と注意点


読み込む


data.json



{
"aaa": {
"x": 698,
"y": 234
},
"bbb": {
"x": 664,
"y": 86
},
"ccc": {
"x": 482,
"y": 224
},
"ddd": {
"x": 648,
"y": 366
},
"eee": {
"x": 554,
"y": 352
}
}

例えばこういうjsonファイルを用意した時


ofApp.h


#include "ofxJSON.h"

ofxJSONElement json;


インポートして宣言する


ofApp.mm


void ofApp::setup(){
json.open("data.json");
for (int i=0; i<json.getMemberNames().size(); i++) {
string name = json.getMemberNames()[i];
int x = json[name]["x"].asInt();
int y = json[name]["y"].asInt();

cout << name << " :( " << x << ", " << y << ")" << endl;

}

}


みたいな感じに使えて簡単です。

json.openでdata/内のディレクトリいあるファイルにアクセス

json.getMemberNames()[n]でn番目のjsonデータの名前が取得できる。

全部並べたいのでまずjson.getMemberNames().size()で取得し、for文で回す

→とりあえずログに出力


書き出す

すみません、使ってないのでわかんないです。

でもさくっと出来ると思います。

sampleとか見て下さい。


ofDirectory


oFでディレクト内のファイルの情報を得る

そういえばoFでディレクト内のファイル名とかとってくるときとか

どうするんだろうとおもった。

こんなクラスが装備されていた。

ofDirectory


使用シーン

画像ファイルをたくさんつかうアプリケーションなどの場合、

ファイル名をいちいち頭で管理できないしdataディレクトリのなか見て

わざわざ確認した後に

img.loadImage("hogehoge.png");

みたいなのもういやだと感じたとき


使い方と注意点

ファイル名を一覧


ofApp.mm


void ofApp::setup(){
ofDirectory dir("images/");

dir.allowExt("png");
dir.listDir();

for(int i = 0; i < dir.numFiles(); i++){
cout << dir.getName(i) << endl;
}

}


という感じ

ディレクトリの指定はbin/data/以下

もっとたくさん便利メソッドとかありそうだったので

深く使う時にまた調べようと思った。


感想

Qiitaに限らず

投稿するのってすごく体力がいりますね。