Scratch で Generative Art

f:id:hrt1ro:20190829090250p:plain

お盆前に 『[普及版]ジェネラティブ・アート―Processingによる実践ガイド』マット・ピアソン(著) を買って読んでたのだけど、やる気が出てきたのでいくつか作ってみた。 ProcessingだとSampleコードからのただのコピペになってしまうので、Scratchでやってみることにした。 結果とても苦労した。お勧めはしない。

Chapter 3 線を引く間違った方法

ゆらゆらするやつ

「水平な線を描くときに垂直方向にランダムさを加える」というやつ。 波っぽいアニメーションができれば良いなあと思ってやってみた。 なんとなく動きは狙ったようなものができたのだけど、 波と呼ぶには曲線がカクカクしすぎなのとグラデーション部のマッハバンドが強すぎて滑らかさに欠ける。

Chapter 4 円を描く間違った方法

Wave Clock

本章の最後にある「Wave Clock」を作ってみた。 これは作ってみて分かったのだけど、Processingで書くよりも、Scratchで作ったほうが簡潔に書ける(ことがある)。 たぶんProcessingでスプライトみたいなことをやっているものは Scratchのスプライトでやったほうが早いかも、ということなのだろう。

Chapter 5 次元を加える

こういう分野でPerlinノイズは基本らしい。 ということでPerlinノイズをScratchで描いてみた。けっこう大変。 でも作ってみるとたしかに「使える」感じがすごくあるので作ってよかった。

Perlin ノイズ

3次元ノイズ空間の2次元断面。 ノイズ値をスプライトの明るさに割り当てたもの。

画面をスプライトのタイルで埋め尽くしたい。 Scratchには「スプライトのクローン数は1プロジェクトにつき最大300」という制限がある。 よって300個以下で画面を埋め尽くせる最小サイズを求めると、(24×24)なら(20×15)タイルでステージを埋め尽くせる。

うねうねするやつ

3次元ノイズ空間の2次元断面。 ノイズ値をスプライトの基準からのX軸方向Y軸方向のずれに割り当てたもの。 ついでに1アニメーションフレームごとにスタンプして残像を残している。 これはちょっと想像していたより気持ち悪いものができたのでよかった。

Chapter 6 創発

蔵本モデル

パプアニューギニア 蛍の木」でぐぐると出てくるアレのシミュレーション。 本章で群集アルゴリズムに触れられている(アルゴリズム自体は掲載されてない)のを見て 蛍の点滅が同期するやつがあったなあと思い出した。 前の章で作った20×15タイルを再利用してわりと簡単に完成。

Emergence (circles)

本章でオブジェクト指向とか言い出して僕の欲しい方向性とは違うのでどうしようかと思ったけど、 これはやってみると発見があった。 「予測可能な動き」に「単純な生成ルール」を組み合わせると「ちょっと予測不能な動き」が生まれる。 なるほどこれが創発というものか!という発見が興味深かった。

Chapter 7 自律性

セル・オートマトンといえばライフゲームGoogleで「ライフゲーム」を検索するとライフゲームが始まる。

Game of Life (20×15)

いちど (20×15)タイルのプログラムを作ったら何度も使いまわしてしまう。これが再利用性の高いプログラムというものである。

Game of Life (40×30)

1タイル(24×24)を(2×2)の4個に分割して(40×30)セルにしてみた。 1タイルは4ビットなので24=16状態ある。 16状態を16個のコスチューム着替えで実現している。 やってみると…すごく遅い。 たぶんビット演算を四則演算で実現しているところが遅いのではと推測されるのだけど、 なんかパフォーマンスチューニングはあまりやる気が出ないのでたぶん改善はしない。

Autonomy (wave/averaging)

本章にある「波(平均化)」を実装した。 (20×15)でも意外に波っぽく見えるものである。

Chapter 8 フラクタル

宇宙のゼンマイ時計

これってフラクタルなのだろうか。 実装はスプライトをネストしたかのように振る舞うものを目指してみた。 だいたい狙ったとおりにできて、動きも元のサンプルにだいぶ近づいたので、 ちょっとうまくいったと思う。

サトクリフの五角形

これはフラクタルだよねえ。 1本の線を1つのスプライトで表す実装にしてみた。 5角形を6分割を2段階やっただけでもう線の数が300個近いのでこれで限界となった。 particle飛ばしまくってぐるんぐるん回るはず…というもくろみだったのだけど、 非力なマシンだともう動きがカクカクしていけない。 やっぱりパフォマンスチューニングにはやる気が出ないので多分これ以上良くはならない。


以上で夏休みの自由研究「書籍Generative Artを読んでScratchで書いてみる」は終わり。 けっこう面白かったので、また何かScratchで作るかもしれない。

Apple Pencilを使ってみる

ねんがんの iPad mini (第5世代) を手に入れたぞ。 ついでに Apple Pencil (第1世代) も買った。 えらい出費である。

よくあるiPad miniのこじゃれたレビューとかはしない。

Apple Pencilのプログラミング的な使い方はSDKサンプルの Leveraging Touch Input for Drawing Apps をDownloadして見てだいたいわかった。

指のタッチのときと同じく touchesBegan(_:with) の仲間で受け取ればいいけど、 推定値が含まれていることがあるので(PencilはiOS実機とは別デバイスだから)、 touchesEstimatedPropertiesUpdated(_:) で更新すればよいということらしい。

やってみたのが下の図

f:id:hrt1ro:20190515100105p:plain

タッチイベントでやってくるすべての点を折れ線で描いただけ、 なのにPencilのほうはすごく精緻。点の数が多い。 点の数は 60Hz : 240Hz 比、というわけでもないっぽい。 なんとなく1:2くらいのようす。

touchesなんとかは UIResponder のメソッドなので UIView でoverrideするのが ふつうかと思いこんでいたけどSDKサンプルは UIGestureRecognizer でやってる。 「そういうのもあるのか」 UIGestureRecognizer には allowedTouchTypes があるので 「Pencilだけに反応するやつ」などと簡単に指定できるのでこいつがぼくのほしいやつに違いない。

Core Text で縦書き(3)

前回 Core Text で縦書き(2) - 錯綜 のコメント欄で90度回転しなくていいやつを教えてもらえた。 こんな誰も読んでないようなブログでも親切な人が教えてくれたりするものである。 ありがたいことである。

というわけでやってみた。 まず普通に CTFrame を使って横書き。

        …
        let astr = NSAttributedString(string: string)
        let setter = CTFramesetterCreateWithAttributedString(astr)
        let path = CGPath(rect: rect, transform: nil)
        let frame = CTFramesetterCreateFrame(setter, CFRange(), path, nil)
        …

f:id:hrt1ro:20190307144126p:plain
横書き

次に文字列のアトリビュートに縦書きグリフを、 フレームのアトリビュートに進行方向右から左を、指定する。

        …
        let stringAttrs: [NSAttributedString.Key : Any] = [
            .verticalGlyphForm: true,
        ]
        let astr = NSAttributedString(string: string, attributes: stringAttrs)
        let setter = CTFramesetterCreateWithAttributedString(astr)
        let path = CGPath(rect: rect, transform: nil)
        let frameAttrs = [
            kCTFrameProgressionAttributeName: CTFrameProgression.rightToLeft.rawValue,
        ]
        let frame = CTFramesetterCreateFrame(setter, CFRange(), path, frameAttrs as CFDictionary)
        …

f:id:hrt1ro:20190307144205p:plain
縦書き

最初 CFDictionary に CTFrameProgression.rightToLeft を入れていて動かなくて困った。 rawValueがキモだった。分かってみれば当然だけど。

縦書きはたぶんこれで決まりだ。

Scratchからmicro:bitにつないでみた

2か月くらい前にmicro:bitを購入してから ちょくちょく遊んでいるのだけど これがけっこう楽しくて 久しぶりに LEDを買ってきたり はんだごてを買ってきたり している。 けどやっぱりぼくはソフトウエアな人なので電子工作よりもプログラムを組むのが楽しいようだ。

micro:bitのプログラミングは ふつうはMakeCode Editorで作ったプログラムをmicro:bitに転送するのだけど いちいちUSBケーブルを外したり繋いだりするのがちょっとめんどい。 まあ繋ぎっぱなしにすりゃいいのだけれども。 このめんどくささが、プログラム書く→試すサイクルを止めるくらい嫌になることもある。

BLEで転送する方法もあるようだけど、 これによると Scratch から制御できると知った。

www.watch.impress.co.jp

この構成では自分が作ったプログラムは Scratch 側で動いていて micro:bit 側ではScratchと通信するプログラムがずっと動いている、 ので micro:bitをScratch の入出力装置として使える。

手順はこれの通りなのだけど

sanuki-tech.net

これはWindows,ChromeでやってるけどmacOS,Safariでもやってみたらできたというだけの話。

で、やってみたけど、これがすごく面白い。 micro:bitを傾けた方向にスプライトが動くだけのプログラムだけ、なのだけど、 これでAボタン押したら弾が出るようにして…などといろいろアイデアが出てくるところが、 そういうところが創造的で面白がるポイントだと思った。

f:id:hrt1ro:20181206140629j:plain

入出力装置として、と書いたけど 入力は振ったとき、傾けたとき、ボタンを押したとき、端子に触れたとき…と充分な気がする。 出力はLEDに表示するくらいしかないので せめてmicro:bitにつないだスピーカーの音を鳴らすくらいはできるようになってほしい。

まだβ なのでそのうちできるようになるといいなあ。

Swiftでファミコンエミュレータを書いた(3)

githubに上げた。

github.com

わかっている問題

  • 音は出ない
  • 遅い
  • iOS実機で動作確認してない
  • 対応している mapper は NROM だけ

遅い問題

Debug build だと 7 fpsくらいしか出ない。 (MacBook 2017, iOS Simulator)

Release build だと 40 fps くらい出るので optimize は非常によく効いている。 逆に言うと optimize に頼りすぎな書き方をしているかもしれない。

iOS 実機では試してないのでどのくらいの性能がでるのかわからない。 iOS 実機を持ってないので。

Instruments で見てみると PPU の rendering がほぼ 90% 以上、までは分かるのだけど どこがボトルネックなのかはよくわからない。 Instruments の見方がよくわからない。

音が出ない問題

APUを作ってないので。 たぶん iOS 実機を手に入れたらつくる、かもしれない。

ふりかえり

  1. CPU は nestest.nes をパスさせるのが大変だった。
  2. PPU は vblank と sprite 0 hit の実装が breakthrough だった

Swift製NESエミュレータその2

遅々として進まず。

nestest はまだたくさん失敗している。

f:id:hrt1ro:20181102195412p:plain

「テスト失敗」の結果を得るまでが大変だった。 実装のミスではなく、仕様を読み違えている。 6502 の CMP のキャリーフラグの仕様変だよね。 思い込みはバグのもと。

color_test はちょっと動いている様子。

f:id:hrt1ro:20181102195431p:plain

palette は画面が崩れまくっている。

f:id:hrt1ro:20181102195444p:plain

まだまだ先は長い。

Swiftでファミコンのエミュレータを書いてみる

先週読んだこのブログエントリ Kotlinでファミコンのエミュレータを書いた - ゆいきノート に刺激を受けたので自分でも書いてみることにした。 Swift4.2, iOS12.0, Xcode10.0で。

なるべく他人の書いたソースコードは読まないようにして、 できるだけ文書や記事だけ読んで実装してみた。 これってプログラムを書く能力よりも 仕様書を読み取る能力のほうが大事だと思った。

ようやくHELLO WORLD!が表示できたので記念にスクリーンショットを貼っておく。

macOS上のiPhoneシミュレータ上で動いているNESエミュレータの図

f:id:hrt1ro:20181025174428p:plain

ソースはそのうちGitHubあたりに公開するかもしれない。 だいぶ飽きてきたのでいつになるかわからない。