地上の洞窟

どこにも行かず、液晶と「にらめっこ」し続ける人の物語。

オープンソースの理想と現実

とある界隈のお話である。
その界隈は、AIによる研究が盛んで、
その研究を「ぶつけ合う」ようなことが、その人々の間で行われていた。

しかし、その界隈の人間のまるで頂点に立つような人間が零した。
「こういったAI研究のぶつけ合いが出来たのは、そのAIが無償の物であったから」と。

これが開発者の逆鱗に触れてしまったのか。
開発者は「楽しいからタダで作っているわけではない」と。
そしてひとまずの最新AIは、有償のものにしてしまったようだ。

…なぜこうも濁してここに記しているかというと、
同じ何かを無償で提供する人間として、個人的にはとても物申したい事柄ではあるのだが、
そのAI開発者は自分に比べれば、雲の上の存在といえ、とても恐れ多い。
ので、このような僻地でゴミのような文章を打ち捨てることとしたのである。


そのAIはオープンソースソフトウェアであった。
そのAIの内訳は誰でも無償で知ることができるし、それを使うこともできる。
なんともありがたい話だと思うのは誰しもがそうであることだと思う。

しかしそんなんで儲かるのか?と言われれば全くもってそんなハズはなく。

無償で提供し続けることがどれだけ、その人にとっての損失であるか、
作り手にとっては気が気でない事は確かである。それは自分も断言できる。

しかし、だからこそ、どれだけ手間暇をかけて、
どれだけ自信をもってこれは最高の作品であると高らかに主張しようと、
作り手には物理的な見返りというのは一切入ってこないことが、
どれだけの狂気を生むかというのは、自分自身はっきりと理解できる。

誰しもが、いつかは応援や支援を頂けるという邪念と戦いながら物を作っている。
しかし実際にそういうことが起きるかと言われれば、
その「人々」という単位でみても稀だし、その人「個人」で見ても稀な事である。
それが、理想と現実の差なのである。


では、作り手はなぜ無償で提供する道を選ぶのか?
それは第一に、最高の物を作りたいからであると個人的には思う。

世の中、高いお金を払ったからいいものが手に入るというわけでもない。
むしろこの世の中には無償でもかけがえのない素晴らしい物が出回っており
タダでこれだけのものが手に入る、なんて素晴らしいんだと思うことは多々あるだろう。

もっと言えばスーパーに行けば、皆「安くて良い物」を常々求めることであろう。
売り手が「そのものには金銭的価値はない」ということが
買い手には価値があることであり、開発者=売り手である環境では
自分が作った物には(金銭的)価値が無いと言い張る必要がある。
これが絶望的につらい事柄なのである。

金銭的価値があるものが価値のあるものとは限らない様に、
価値があるものに金銭的価値があるとは限らない。
直感に反して受け入れがたいが、意外とそうである。

それでも作り手は、もはや意地で、安くて良い物を作ろうとしているのだ。
きっと。


オープンソースの恩恵は多くの開発者と利用者が居る事であると思う。
誰でも参加できるからこそ、その事柄は急速に発展できる。
その代わりに、提供者である開発者は、利用者から物理的な価値が得られない。
何かをする代わりに何かを得ることが、この世の原理であるハズなのにそれがない。
沢山の人に参加して欲しいという理想のために、ある意味現実離れしている。

しかし作り手はもとより自らこの道を選んだハズである。
作り手は自分の作った最高の作品に価値が無いと言い続ける狂気と
戦い続けなければならない。
作り手は自分が選んだその道に、命を懸けて納得する必要がある。

自分はそれで何を成せたわけでもない。
しかし周りは違う。その開発者は違う。きちんと何かを成している。
オープンソースの理想に住んでいる。スポンサーもいて、支援も得ていて。
誰かからも応援されていて、誰かからの意見も得ることが出来て。
そうして自分と比べてみて、まだ何か文句があるのかと。
それだけやっておいて、今更、理想と現実の差に突然憤りを感じるものかと。
個人的にはそう言いたい。


今回のその一件は、「界隈」のAI利用者からすれば、オープンソースの本質を
外側から語っただけに過ぎないだろうと思う。
それにオープンソースの住人が、理想を見ていた人間が、
ふと現実に追いつかれてしまったのだろうか。
如何に聡明で、何かを成している過去があろうと、突然とそうなるものなのだろうか。
今の自分にはまだ理解が届きそうにない。


なんか精彩に欠け放題な文章となってしまった。申し訳ない。
(平常運転ともいえるが)

【Ruby】Win32APIを使用してキー入力を取得する方法


前置き

RGSS3みたいな「ゲーム系のアプリケーションでキー入力を取得したい」
そういう時に使えるかもしれないお話。
※古いRuby1.9ぐらいの話なので、Win32APIみたいなdllの呼び出しは
また新しいバージョンだと話が変わってきたりすると思う。自分は詳しくないけど。

Win32APIの概要

APIとは略さずに言うと "Application Programming Interfaces" と言うらしく、
Win32APIとはなんぞやというのをざっくりとまとめるなら、
Windowsの機能をプログラムから簡単に呼び出すための仕組み」と言える。

Rubyの「Win32API」クラス

Rubyには「Win32API」というクラスがある。
これはその名の通りWin32APIを介してWindowsの機能を呼び出すことができる。
実際には単純にdllファイルの機能を呼び出すことが出来るクラスであるため、
自作したdllをRubyで読み込んで使用するといったことも可能。

Win32APIで出来ること

Windowsのアプリケーションで出来ること、と言ったら
多岐に渡りすぎるので全て紹介することは不可能だが、簡単な所で言うと

  • ウィンドウの作成、移動
  • ファイル・ディレクトリの操作
  • マウス・キーボード入力の取得

などが挙げられる。
他にもなんやかんやと描画したり、IMEに入力された文字を取得したりとか…
挙げてたらキリがないと言えば、その通りである。

Rubyは基本、コンソール上で動かすので、Win32APIと関わることは通常、無い。
RPGツクール「RGSS」みたいにRubyの延長線上でWindowsアプリケーションを動かす」
といった場合に、必要になる技術と言える。

実装

とりあえず簡単に。
キーボードの「A」が押されたら"A"と出力するだけのコード。

# encoding: utf-8
require "win32api"

get_key_state = Win32API.new('user32', 'GetKeyState', 'i', 'i')

while true
  state = get_key_state.call(65)
  if state & 0xFF00 > 0
    puts "A"
  end
  sleep(0.01)
end


解説

とりあえずRubyのWin32APIは組み込みではないのでrequireを忘れずに。
(RGSS3では要らないよ!)

Win32APIクラスの初期化

new時には以下の4つの引数が必要。

引数 説明
dll_name String 機能(関数)を呼び出すdllの名称
func String 呼び出す関数の名前
import String
またはStringの配列
関数に渡す引数の「型」
export String 関数が返す値の「型」

import, exportで指定する型には以下の文字列を使用。

文字
ポインタ 'p'
long 'l'
int 'i'
void 'v'



今回のキーボード入力の取得に使うWin32APIクラスの初期化は以下のようになる。

get_key_state = Win32API.new('user32', 'GetKeyState', 'i', 'i')



キーボード入力の取得にはUser32.dll内のGetKeyState関数を使用する。*1
引数には入力を取得したいキーの「仮想キーコード」を渡す。
仮想キーコードはキーボード上の各キーを識別するための数値である。int型。
例えばEnterキーの入力取得をしたければ13、
アルファベットのAキーを取得したければ65などと細かく決まっている。
仮想キーコード一覧は調べれば出てくる。
返り値は指定したキーの入力状態が返ってくる。

関数の呼び出し

では早速GetKeyState関数を呼び出してみる。
呼び出しには「.call」するだけ。そのまんまだね。

get_key_state.call(65)

引数には取得したいキーの仮想キーコードを指定。
今回はAキーを取得したいので65を指定。

キーの押下判定

取得したキーの状態は16Bitの整数で表されており、
キーが押されている場合は、16Bitの内の上側8Bitが全て立つ。*2
つまり、キーが押下中かどうかを判定するには、ビット演算で上側8Bitを抽出し、
その値が0を超えているかで判定すればいい、ということになる。

state = get_key_state.call(65)
if state & 0xFF00 > 0
  # キーが押されている場合の処理
end

…と、このようにしてキー入力が取得できる。意外と簡単?

まとめ

意外とキー取得は回りくどい!!

まぁRubyWindowsアプリケーションであることを
前提としてない?ので当然といえば当然だが。

余談だがこのdll呼び出しは結構重い。ので、
Rubyで計算するのは遅いから、dll上はC++だしそっちで動かせば速いんじゃね?」
とかいう邪道に手を出そうとして失敗したことがあったりする。
もうそれ、Ruby使ってる意味よ…?

*1:他にもGetAsyncKeyStateだったりGetKeyboardStateだったりがあるが
それぞれで使い方、使い道は異なる。今回は割愛

*2:0b1111_1111_0000_0000の様になる

【RGSS3】ダイナミックスクロール

ダイナミックスクロール
滑らか(?)で簡単なスクロール

指定の座標に向かって、加減速を交えた滑らかなスクロールを実行します。
中の計算式は超適当とか言えない ← ちゃんと修正したよ!

スクリプトコマンド一覧

DynamicScroll.scroll(x, y)

マップ座標 x, y が画面の中心になるようにダイナミックスクロールを実行します。

DynamicScroll.scroll_player

プレイヤーが画面の中心になるようにダイナミックスクロールを実行します。

DynamicScroll.scroll_event(event_id)

指定したidのイベントが画面の中心になるようにダイナミックスクロールを実行します。

更新履歴 バージョン 内容
2024/03/02 v2.1.0 スクロール時のキャラクターの表示のズレを
抑制する機構の追加
2024/01/23 v2.0.2 DynamicScroll.scroll_event(event_id)の使用時に
クラッシュする不具合の修正
2023/12/31 v2.0.1 移動速度が移動距離を上回ってしまった場合
計算がおかしくなる不具合の修正
2023/12/31 v2.0.0 計算式を正確なものに修正
2023/11/22 v1.0.0 初版

→スクリプト一覧へ

続きを読む

「力むこと」はきっと罪深い

自分は不安定な人間だ。

ある時はその道を極めたプロのように、神がかり的な能力を発揮するが、
ある時は見るに堪えないような、素人かよと嘆きたくなるような最悪な状態が続いたりする。

こういう不安定さがあるから、「自分は強い」と言い切ることはできない。
いや、実際にはそう言う時もあるが、それはその時だけの話であって、
絶対的といった感じではない。

「レーティング」という概念がある。
複数の人が戦い合って、勝った方はレートという点数を得て、負けた方は失う。
そうすることによって、その人の強さ・評価を数値化して知ることができる。

こういった例で分かりやすいのは、将棋の「藤井聡太」であろう。
将棋の中の「タイトル戦」、所謂大会のようなものを、8つある内の7つを制覇し、
あと1つも制覇寸前という所であり、現在、最強の棋士であることは確実だ。

彼の強さはレーティングにもはっきりと表れている。
プロ棋士は普通の人からみれば、圧倒的に将棋が強い人だが、
プロ同士を比較した場合、強い弱いという差は確実に出てしまう。

藤井聡太はそのプロの中でも強い方の棋士に対して、
圧倒的な勝率を誇り、レートでもぶっちぎりの差を付けている。
強い人に安定して勝ち続ける、あらゆる局面でミスしないからこその「数字に表れる強さ」だ。

それに対して自分はどうだろう。いや比べることさえおこがましい事だろうが。
自分はどれだけ勝ち確定な局面であっても、平然とミスして当たり前のように負ける。
いやそんなの普通だよ、と言われそうだが、勝負の世界では、尋常であってはならないのだ。

自分は下手だ。はっきり言って弱い。素人だ。
せいぜい「数字に表れない強さがある」とかいって強がることぐらいしかできない。

一体何が?何がそんなに下手で悩み嘆いているのか?といわれると全部である。
自分は何をやっても不安定だし、真に強いと言える領域には辿り着けていない。
給与があるなしとか、有名であるかそうでないかとか差し置いて、
真にプロフェッショナルである、という領域にはたどり着いていない。

その理由はごまんとあるだろうが、
今回は自分が「力み過ぎ」ということについて語ろうと思う。(前置きなげぇよ)

自分は緊張する場面で力み過ぎる。
力み過ぎて手が震える。その割には、意志は行動に反映されず、
結果的に何もせず何も成せなかったように見える、ということがある。

それはなぜか?そもそも緊張して硬直している状態は、
精神的圧力に敗北しかけている状態だと個人的には思う。
そんな状態で勝ちが見える訳がないと言われたら、まぁその通りですはいという感じだ。

そしてもう一つ、自分の中で「力が入っている」という状態は、
「実際に何かを動かせる状態じゃない」ということだ。

例えば腕に力を入れて、力こぶを作ったとする。その状態は物凄く力を入れていると思う。
しかし、その状態自体で何かを成せるだろうか?その力に見合う結果が得られるだろうか?
実際には何も起こらないし、ただ、腕がプルプルしながら固定された状態、になると思う。

要はそれは、「緊張して硬直している状態」と大体同じだ。
裏を返せば、緊張して硬直してしまった場合、
敵の目の前で力こぶを作って見せつけるとかいう、意味不明な状況と大して変わらない。

こういう自分自身に力が入っているという状態は、
実際には体を動かさずに安定させようとする力、と言えると思う。
物を運んでいる時の腕とかは、力が入っていて固定され、安定していると思う。

一方で、単に動かすだけであれば力は意外と入らない。
入れない方が、結果的には対象に対して大きな力が入る。
力むことが、自分の行動を安定させようと、止めようとする力だから。

要するに、緊張して力んでいる状態では、意志は反映されないし結果は出せない。
出来るだけ力を抜いた状態で体を動かす。それでいて精密で無駄な動きが無いことが
「洗練されている」ということなのだろうというのが、今の自分の仮説だ。

安定して結果を出そうと思っているのに、
力んだら動きが固定され「安定し過ぎて」結果が出ないなんて、皮肉だ…

巷で話題の将棋マナー

とりあえず雑記。どちらかというと役に立たない文章を
ネット上に掲載するのは初かもしれない?いや、いつも役に立たない文しか書いてないか。

まあそれはさておき、最近は将棋を指す上でのマナーが話題だったりするらしい。

チェス然り将棋然り、王様を取られたら負けのゲームな訳だが、
将棋はよく見ると、王様を表す駒は「玉将」と「王将」の二つが用意されている。
(ギョクショウとオウショウね)

文化的には、二人の対局者の間で「強い方」が「王将」を持つべきというしきたりがあるようで、
そういうことを気にしない人が「王将ウェーーーイwww」って持って行ったことについて腹が立つ
というのが話題の発端のようだ。

自分は単純に「後手番が王将を持てばいい」と思う。
その方が周りが見たときに、どちらが先手・後手なのかが一目で分かるし、
将棋のソフトなどを見ても、大抵は自動的に先手が玉、後手が王で配置されている。
私的には見慣れた光景だ。

将棋は先手番・後手番とでは、
「先手の方が勝ちやすく、逆に後手で勝つことは難しい」と言われている。
先手は当然相手より先に攻めることができるし、序盤から選べる作戦の幅も広い。
プロ同士の対局であっても、若干先手番の方が勝率が高く(53%くらい?)
人間より強い「将棋AI」を用いて初期配置を検討しても、僅かに先手番持ちである。

将棋の駒落ちなど、ハンデのある戦いでは、
不利な方、つまりは上手側が分かりやすく王将を持っている。
駒を落としてなくても、後手番を持つと最初から決めて対局することが
ハンデであると日本将棋連盟のそれに書いてあったり。

まああとは、先手が「玉将」、後手が「王将」と誰かに教わったような気がする。
(なお、パッと調べてもそんなソースは無い模様)

タイトル戦などで挑戦者・保持者みたいな構図がはっきりと決まっているなら
上位者が王将を持つルールはふさわしいとは思うが、
それ以外の対局であれば、振り駒で決まった先後であっても、
手合割のように、後手番が王将を持つことが一番分かりやすいと、個人的には思う。
(後手番が不憫という問題に対して、多少の手向けにはなるような気がするし)

まぁ大体そんな感じ。自分が将棋初心者の友人と対局するときは、
勝ちやすく作戦も選べる先手番を譲り、後手番を積極的に選んでいる。
(なお、勝ちは譲らない模様)

参考

book.mynavi.jp
www.shogi.or.jp
ja.wikipedia.org
ja.wikipedia.org

【FFmpeg】とにかく簡単にmp4→gif変換

mp4→gif変換
mp4 → gif変換

※画面は開発中のものです。とか言っとけ定期


前置き

ブログ上でイメージを示したいが、それが動画だったとき。
本来であればvideoタグとか使って動画を埋め込みたいところだが、
はてなブログ君では動画のアップロードが出来なかったりする。

多分TwitterYouTubeに上げた動画を埋め込むのが一番なのだが、
自分はTwitterはROMりたいし、YouTubeになんでもかんでも上げるのはちょっちね。

てなわけで考えられるのが昔ながらの.gifアニメーション
最近は.webpみたいな規格もあるようだが、
はてなブログ君では.webpは取り扱えなかったりする(またかよー!)

というわけで、動画ファイルを.gifに変換する方法を紹介しやす。

準備

動画を.gifに変換する方法は色々ありますが、今回はFFmpegを使用します。

ダウンロード先は色々あるけど、
FFmpeg公式ページ
→ Download
→ Get packages & executable files
Windows EXE Files
Windows builds by BtbN

からでいいと思う。手間だろうからリンク先貼っときます。

github.com

ここのLatest Auto-Build → Assetsから
ffmpeg-master-latest-win64-gpl-shared.zip」をダウンロードして、
.zipファイルなので解凍して、どっか分かる場所に置いとく。

バッチファイル作成

解凍したフォルダの中にある bin\ffmpeg.exe を動かしていくのだが、
コイツを動かすにはコマンドプロンプト(cmd.exe)から
コマンドを入力して動かしてやる必要がある。

ただし、毎回毎回手入力するのも大変だし、場所指定が面倒だったりと色々あるので、
バッチファイル*1を作成して手軽に動かしてあげようという算段。

ffmpeg.exeと同じフォルダ内に適当な.batファイルを作成して、以下の内容を書き込む。

@echo off

set ffmpeg_path="ffmpeg.exe"

if "%~1"=="" (
  echo Please drag and drop target file.
  pause
  exit /b
)

%ffmpeg_path% -i %~1 -filter_complex "fps=24,split[a][b];[a]palettegen[pal];[b][pal]paletteuse=dither=none:diff_mode=rectangle" -y %~n1.gif

pause

このバッチファイルに動画ファイルをドラッグ&ドロップすれば、
同じ場所に同じ名前でgifファイルが生成される。
(既に同名のgifファイルが存在する場合は上書きされるので、注意)

バッチファイルの作り方は普通にテキストファイルを作成して、
拡張子を.batにするだけでおk。あとは↑をコピペするだけ。


バッチファイルの説明

各項を説明していく。

@echo off

これを書いておくと、バッチファイル内で実行されたコマンドが
コマンドプロンプト内に表示されなくなる。

set ffmpeg_path="ffmpeg.exe"

ffmpeg_pathという変数にffmpeg.exeまでのフルパスを代入して使用する。
""内を、各自ダウンロードした ffmpeg.exeまでのフルパス に書き換えて使用してください。

if "%~1"=="" ( ~~~ )

"%~1" というのは、このバッチファイルに対して
ドラッグ&ドロップされたファイルのフルパスを表す。
これがもし空ならば、変換する対象のファイルが無いとみなし処理を終了する。

%ffmpeg_path% -i %~1 ~~~

%ffmpeg_path% -i %~1 -filter_complex "fps=24,split[a][b];[a]palettegen[pal];[b][pal]paletteuse=dither=none:diff_mode=rectangle" -y %~n1.gif

実際にffmpegを実行するための一行。
-filter_complex の後の""内で、.gifアニメのfps*2を設定している。

この値を大きくすれば動きが滑らかになるが、ファイルサイズがクソデカになるので注意。
また、fpsの他にもサイズ指定などができる。

"fps=24,scale=320:-1,split[a][b];[a]palettegen[pal];[b][pal]paletteuse=dither=none:diff_mode=rectangle"

fps=24 の後に scale=320:-1 を追加している。
横幅を320pxに、縦幅は-1、これは指定した横幅320pxに対して、
元の画像の縦横比を崩さないように縦幅を自動計算して、拡大縮小する。

そのあとのごちゃごちゃした項では、動画からパレットを生成して
減色する工程を行ってたりするが、ややこしいのでここでは割愛。

後ろの方についてる -y は、同名のファイルが存在する場合に上書きするオプション。
%~n1 はドラッグ&ドロップされたファイルの名前(フォルダや拡張子を含まない)。


pause

これを書いておくと、バッチファイルの処理が終わった際に、
コマンドプロンプトが自動終了しないようになる。

まとめ

バッチファイルを作成して、ドラッグ&ドロップでmp4をgifに変換する方法でした。
まぁ、それでも面倒っちゃ面倒だよね。特に出力設定変えるのにバッチファイル編集するのが。
なんか動画→gif変換できる簡単なソフトとか作ろうかな?いや、そんな暇は実際ないんだけど。

今回の方法は変換する動画によっては色合いが褪せちゃうことがあります。
その場合は手間ですが、変換する動画に色調補正をかけて、彩度を上げておくとよいです。
(冒頭の画像もそうだったりする)

しかし、.gifファイルは圧縮が悪いのか、
.mp4から比べると画質が悪くなる上に、ファイルサイズが爆増してしまいます。
できることなら動画を直張りした方がいいですね、マジで。


おまけ

動画→アニメーションwebpを出力するコマンド。主に-qscale:v 80の所で画質が変わる

%ffmpeg_path% -i %~1 -vcodec libwebp -filter:v fps=fps=30 -lossless 0 -qscale:v 80 -loop 0 -preset default -an -vsync 0 -compression_level 6 -y %~n1.webp



パレットを使用せず.gifを出力するコマンド。画質は悪いがサイズは小さい

%ffmpeg_path% -i %~1 -r 30 -y %~n1.gif


*1:.batファイル。実行するコマンドを一まとめにして、簡単なプログラムのように扱える

*2:frame per second、一秒あたりのフレーム数