地上の洞窟

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

サイト案内

このブログでは、地上に住まう地底人のようなものが
RGSS3の素材を配布してたり、プログラムの話をしたりしています


このブログについて 「地上の洞窟」についてもう少し深く語っています。
RGSS3素材 RPGツクールVXAce」で使えるRGSS3の素材を配布しています。


更新履歴

2024/05/19
2024/03/02
2024/01/23

【RGSS3】トラベルポイント

トラベルポイントUI
知ってる場所へテレポートができる(ルーラ!

登録された場所へテレポートする画面を追加します。
(動作には「CraftLib」スクリプトが必要です)

スクリプトコマンド一覧

TravelPoint.set(map_id, x, y, name = nil)

マップID、X座標、Y座標、登録名(任意)を指定して、テレポート先を登録します。

TravelPoint.set(6, 21, 33)
TravelPoint.set_player(name = nil)

プレイヤーが現在いる位置をテレポート先として登録します。

TravelPoint.set_player("現在地")
TravelPoint.set_player_target_direction(direction, name = nil)

現在プレイヤーがいる位置から、一歩進んだ地点より、
direction方向に進んだ場所をテレポート先として登録します。

TravelPoint.set_player_target_direction(2)
TravelPoint.delete(map_id, x, y, name)

指定したテレポート先の登録を削除します。
nilを指定した場合、その項目は検索対象にしません。

TravelPoint.delete(5, nil, nil, nil) # マップID:5の登録を全て削除
SceneManager.call(TravelPoint::Scene_TravelPoint)

テレポート先の表示・指定を行うシーンへと遷移します。

SceneManager.call(TravelPoint::Scene_TravelPoint)


更新履歴 バージョン 内容
2024/05/19 v1.0.0 初版

→スクリプト一覧へ

続きを読む

【Minecraft】AE2 - 無限倉庫

久々に上げるものがスクリプト素材でもなくアルゴリズム解説でもなく
MinecraftApplied Energistics 2というMODの話である。
いわゆる工業MODの類で、こういうものを駆使してコンパクトな高機能な
生産ラインや倉庫などの物流システムを作ったりするのが、自分は好きだ。

今回はその備忘録。
実質1チャンネルでアイテムを無限に収納できる仕組みを考えた。

前提

無限倉庫を作る上では
ME InterfaceとME Storage Busの仕組みを知っておくと分かりやすい。

ME Interfaceは、通常、自動クラフティングで機械へ素材を供給し
加工したものを倉庫へ送る、中継装置として使われることが多いと思われる。

この機能を転じて使えば、別の倉庫のアイテムへアクセスできる。
元の倉庫から別の倉庫のアイテムを取り寄せたり、アイテムを収納することが可能。

チェストなどの外部ストレージを、倉庫自身のストレージとして扱える
ME Storage Busと組み合わせれば、複数の倉庫を一つのネットワークで管理できる。

ME InterfaceとME Storage Bus
倉庫の一元管理

作成

そうしてできたものがこれ。

無限倉庫_1
無限倉庫_2

表面のチェストの裏にはME Storage Busが敷き詰められていて
これがこの倉庫の収納となる。

一見、ひとかたまりの倉庫に見えるが
横幅一マスの独立した倉庫を、ME Storage BusとME Interfaceで繋ぎ合わせている。
連結元の親倉庫ほど収納優先度が高く、連結先の子倉庫は優先度を低く設定する必要がある。

無限倉庫_3
一列の内訳

ゴミ箱なども付けておけば溢れ対策にもなる。以上!

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

とある界隈のお話である。
その界隈は、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つも制覇寸前という所であり、現在、最強の棋士であることは確実だ。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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