Hatena::ブログ(Diary)

永字八法 RSSフィード Twitter

 | 

2011-03-31 Thursday

遅延print

NScripterで、任意の画面Aから任意の画面Bへの遷移を行う場合、Aのルーチンが終了する時にAで使われているスプライトを全て始末し、printをせずにBのルーチンを開始して必要スプライトを揃え、そこからはじめてprintを行うのがセオリーと考えられる。
Aが使ったスプライトはAが完全に始末する、以下同様。これを鉄則として守れば、画面間の遷移でスプライトの消し忘れ等による問題は、原理的に発生しえないことになる。
しかしここでもう一つの問題が発生する。すなわち、どのエフェクトでもって画面Bを表示すべきかであるprint 1だけ使っていればそりゃあ問題はないが味気ない。しかし、遷移前の画面Aによっては、Bで使われるエフェクトの種類を変えたいと言うことも有り得る。

具体例

イベント絵のサムネイルが並べられたギャラリーモードを画面Aとする。そして、一つ一つのイベント絵を全体表示するのを画面Bとする。
この時、AからBへの遷移エフェクト特別もので、A→Bは「Aで選択されたサムネイルが拡大されてBになる」とし、B→Aは「Bが縮小してAの一部に収まる」と言う動作であるとする。
この二つの間の遷移関係では、A→Bは使用すべきエフェクトは一意に決定されるが、逆ではそうはならない。と言うのは、ギャラリーモードへは、通常タイトル画面から、あるいはちょっとひねたシステムなら、ゲームからでも遷移できるもの場合が多い。
仮に、タイトル画面をTとするならば、T→AはB→Aとは違うエフェクトを使用することが自然だとわかるだろう。
そこで必要になるのは、TやBのルーチンが終了する時に、Aを表示するのに使われるエフェクト指定する仕組みである

解決策

print_delay命令とprint_resolve命令を考案する。
print_delay命令は、通常のprintと同じ引数を取るが、それはすぐには実行されずにLua領域内変数に保管される。
print_resolve命令はprint_delayによって保管された引数を実行する。実行された変数は消去される。もし、エフェクト番号等が保管されていなかった場合(print_resolveの空撃ち)は、print 1を実行するとする。
後、念のため、print_clearも作成しておこう。

スクリプト

do
	local arg = {}
	NSExec("luasub print_clear")
	function NSCOM_print_clear()
		arg = {}
	end
	NSExec("luasub print_delay")
	function NSCOM_print_delay()
		arg = {} -- 初期化
		arg[1] = NSPopInt()
		if NSCheckComma() then
			NSPopComma()
			arg[2] = NSPopInt()
		end
		if NSCheckComma() then
			NSPopComma()
			arg[3] = NSPopStr() -- 三つ目の引数があるとしたら、それは文字列。
		end
	end
	NSExec("luasub print_resolve")
	function NSCOM_print_resolve()
		if arg[1] then -- 引数がある場合
			local stuck = {} -- 一時退避用
			local exec = "_print "

			-- 第一引数
				stuck[1] = NSGetIntValue(1) -- 退避
				NSSetIntValue(1, arg[1]) -- 保存
				exec = exec .. "%1"
			-- 第二引数
			if arg[2] then
				stuck[2] = NSGetIntValue(2) -- 退避
				NSSetIntValue(2, arg[2]) -- 保存
				exec = exec .. ",%2"
			end
			if arg[3] then
				stuck[3] = NSGetStrValue(3) -- 退避
				NSSetStrValue(3, arg[3]) -- 保存
				exec = exec .. ",$3"
			end
			NSExec(exec) -- 実行
			
			-- 復帰
			if stuck[1] then NSSetIntValue(1, stuck[1]) end
			if stuck[2] then NSSetIntValue(2, stuck[2]) end
			if stuck[3] then NSSetStrValue(3, stuck[3]) end
			
			-- 引数を削除
			arg = {}
		else -- 引数がない場合
			NSUpdate() -- print 1 相当
		end
	end
end

注意点

print_delayによって保管されたprintへの引数は、Lua領域に保管されるため、間にsave&loadを挟んだ場合の動作は保証できない。print_delayからprint_resolveの間にセーブができるようにはしないように心がけること。

2011年03月30日のツイート

遅延print

NScripterで、任意の画面Aから任意の画面Bへの遷移を行う場合、Aのルーチンが終了する時にAで使われているスプライトを全て始末し、printをせずにBのルーチンを開始して必要スプライトを揃え、そこからはじめてprintを行うのがセオリーと考えられる。
Aが使ったスプライトはAが完全に始末する、以下同様。これを鉄則として守れば、画面間の遷移でスプライトの消し忘れ等による問題は、原理的に発生しえないことになる。
しかしここでもう一つの問題が発生する。すなわち、どのエフェクトでもって画面Bを表示すべきかであるprint 1だけ使っていればそりゃあ問題はないが味気ない。しかし、遷移前の画面Aによっては、Bで使われるエフェクトの種類を変えたいと言うことも有り得る。

具体例

イベント絵のサムネイルが並べられたギャラリーモードを画面Aとする。そして、一つ一つのイベント絵を全体表示するのを画面Bとする。
この時、AからBへの遷移エフェクト特別もので、A→Bは「Aで選択されたサムネイルが拡大されてBになる」とし、B→Aは「Bが縮小してAの一部に収まる」と言う動作であるとする。
この二つの間の遷移関係では、A→Bは使用すべきエフェクトは一意に決定されるが、逆ではそうはならない。と言うのは、ギャラリーモードへは、通常タイトル画面から、あるいはちょっとひねたシステムなら、ゲームからでも遷移できるもの場合が多い。
仮に、タイトル画面をTとするならば、T→AはB→Aとは違うエフェクトを使用することが自然だとわかるだろう。
そこで必要になるのは、TやBのルーチンが終了する時に、Aを表示するのに使われるエフェクト指定する仕組みである

解決策

print_delay命令とprint_resolve命令を考案する。
print_delay命令は、通常のprintと同じ引数を取るが、それはすぐには実行されずにLua領域内変数に保管される。
print_resolve命令はprint_delayによって保管された引数を実行する。実行された変数は消去される。もし、エフェクト番号等が保管されていなかった場合(print_resolveの空撃ち)は、print 1を実行するとする。
後、念のため、print_clearも作成しておこう。

スクリプト

do
	local arg = {}
	NSExec("luasub print_clear")
	function NSCOM_print_clear()
		arg = {}
	end
	NSExec("luasub print_delay")
	function NSCOM_print_delay()
		arg = {} -- 初期化
		arg[1] = NSPopInt()
		if NSCheckComma() then
			NSPopComma()
			arg[2] = NSPopInt()
		end
		if NSCheckComma() then
			NSPopComma()
			arg[3] = NSPopStr() -- 三つ目の引数があるとしたら、それは文字列。
		end
	end
	NSExec("luasub print_resolve")
	function NSCOM_print_resolve()
		if arg[1] then -- 引数がある場合
			local stuck = {} -- 一時退避用
			local exec = "_print "

			-- 第一引数
				stuck[1] = NSGetIntValue(1) -- 退避
				NSSetIntValue(1, arg[1]) -- 保存
				exec = exec .. "%1"
			-- 第二引数
			if arg[2] then
				stuck[2] = NSGetIntValue(2) -- 退避
				NSSetIntValue(2, arg[2]) -- 保存
				exec = exec .. ",%2"
			end
			if arg[3] then
				stuck[3] = NSGetStrValue(3) -- 退避
				NSSetStrValue(3, arg[3]) -- 保存
				exec = exec .. ",$3"
			end
			NSExec(exec) -- 実行
			
			-- 復帰
			if stuck[1] then NSSetIntValue(1, stuck[1]) end
			if stuck[2] then NSSetIntValue(2, stuck[2]) end
			if stuck[3] then NSSetStrValue(3, stuck[3]) end
			
			-- 引数を削除
			arg = {}
		else -- 引数がない場合
			NSUpdate() -- print 1 相当
		end
	end
end

注意点

print_delayによって保管されたprintへの引数は、Lua領域に保管されるため、間にsave&loadを挟んだ場合の動作は保証できない。print_delayからprint_resolveの間にセーブができるようにはしないように心がけること。

2011年03月30日のツイート

遅延print

NScripterで、任意の画面Aから任意の画面Bへの遷移を行う場合、Aのルーチンが終了する時にAで使われているスプライトを全て始末し、printをせずにBのルーチンを開始して必要スプライトを揃え、そこからはじめてprintを行うのがセオリーと考えられる。
Aが使ったスプライトはAが完全に始末する、以下同様。これを鉄則として守れば、画面間の遷移でスプライトの消し忘れ等による問題は、原理的に発生しえないことになる。
しかしここでもう一つの問題が発生する。すなわち、どのエフェクトでもって画面Bを表示すべきかであるprint 1だけ使っていればそりゃあ問題はないが味気ない。しかし、遷移前の画面Aによっては、Bで使われるエフェクトの種類を変えたいと言うことも有り得る。

具体例

イベント絵のサムネイルが並べられたギャラリーモードを画面Aとする。そして、一つ一つのイベント絵を全体表示するのを画面Bとする。
この時、AからBへの遷移エフェクト特別もので、A→Bは「Aで選択されたサムネイルが拡大されてBになる」とし、B→Aは「Bが縮小してAの一部に収まる」と言う動作であるとする。
この二つの間の遷移関係では、A→Bは使用すべきエフェクトは一意に決定されるが、逆ではそうはならない。と言うのは、ギャラリーモードへは、通常タイトル画面から、あるいはちょっとひねたシステムなら、ゲームからでも遷移できるもの場合が多い。
仮に、タイトル画面をTとするならば、T→AはB→Aとは違うエフェクトを使用することが自然だとわかるだろう。
そこで必要になるのは、TやBのルーチンが終了する時に、Aを表示するのに使われるエフェクト指定する仕組みである

解決策

print_delay命令とprint_resolve命令を考案する。
print_delay命令は、通常のprintと同じ引数を取るが、それはすぐには実行されずにLua領域内変数に保管される。
print_resolve命令はprint_delayによって保管された引数を実行する。実行された変数は消去される。もし、エフェクト番号等が保管されていなかった場合(print_resolveの空撃ち)は、print 1を実行するとする。
後、念のため、print_clearも作成しておこう。

スクリプト

do
	local arg = {}
	NSExec("luasub print_clear")
	function NSCOM_print_clear()
		arg = {}
	end
	NSExec("luasub print_delay")
	function NSCOM_print_delay()
		arg = {} -- 初期化
		arg[1] = NSPopInt()
		if NSCheckComma() then
			NSPopComma()
			arg[2] = NSPopInt()
		end
		if NSCheckComma() then
			NSPopComma()
			arg[3] = NSPopStr() -- 三つ目の引数があるとしたら、それは文字列。
		end
	end
	NSExec("luasub print_resolve")
	function NSCOM_print_resolve()
		if arg[1] then -- 引数がある場合
			local stuck = {} -- 一時退避用
			local exec = "_print "

			-- 第一引数
				stuck[1] = NSGetIntValue(1) -- 退避
				NSSetIntValue(1, arg[1]) -- 保存
				exec = exec .. "%1"
			-- 第二引数
			if arg[2] then
				stuck[2] = NSGetIntValue(2) -- 退避
				NSSetIntValue(2, arg[2]) -- 保存
				exec = exec .. ",%2"
			end
			if arg[3] then
				stuck[3] = NSGetStrValue(3) -- 退避
				NSSetStrValue(3, arg[3]) -- 保存
				exec = exec .. ",$3"
			end
			NSExec(exec) -- 実行
			
			-- 復帰
			if stuck[1] then NSSetIntValue(1, stuck[1]) end
			if stuck[2] then NSSetIntValue(2, stuck[2]) end
			if stuck[3] then NSSetStrValue(3, stuck[3]) end
			
			-- 引数を削除
			arg = {}
		else -- 引数がない場合
			NSUpdate() -- print 1 相当
		end
	end
end

注意点

print_delayによって保管されたprintへの引数は、Lua領域に保管されるため、間にsave&loadを挟んだ場合の動作は保証できない。print_delayからprint_resolveの間にセーブができるようにはしないように心がけること。

2011年03月30日のツイート

2011-03-30 Wednesday

2011年03月29日のツイート

2011年03月29日のツイート

2011年03月29日のツイート

2011-03-29 Tuesday

2011年03月28日のツイート

2011年03月28日のツイート

2011年03月28日のツイート

2011-03-28 Monday

NScripterのシステムカスタマイズにおける問題点の洗い出しと対策の模索

define節にてtextgosubを実行する。すると、start節で表示文中に@ないし\があった場合、通常の処理をせずにtextgosubで指定したラベルにgosubする。
システムカスタマイズとは、要約するとこれだけのことである
よって、textgosubで指定されたラベルで始まるルーチンには、最低限以下の機能要求される。

  • returnで終了すること。
  • クリック待ちをすること。
  • 終了時直前、@の場合は改行を、\の場合は改ページ(表示内容の消去)をすること。

ただし、現在のノベルゲームシステムに対するユーザー要求を勘案すると、上記条件は低機能すぎると言わざるを得ない。

これくらいはなければ、今のユーザーからは「システムが○○」よばわりは避けられないのではないだろうか。
これらの仕様を現状のNScripter実装するとなると、大部分はbexec命令によって解決できる。bexecは、ボタン化したスプライトクリックも、キー入力も取得できるからだ。
何が入力されたのかがわかれば、そこから分岐する実装特に難しいものではない。
bexec命令で若干問題になるのは、スプライトクリックは、ボタンダウンボタンアップがセットで検出されるのに対し、キー入力ボタンダウンだけで反応してしまうことだ。これは、CTRLキーによる強制スキップを見越しての実装だろうが、bexecを上書きしてCTRLキー以外ではボタンアップまで含めて判定するのが望ましい。
また、オートモードも、btime命令による時間制限を設けることで実装が可能になる。
唯一、bexec命令にできないことは、既読スキップモードの検出だけである。ただし、この問題が大きいためにtextbtnwaitを捨てられないと言う向きもあるのではないか。
そこで対案として考えたのは、「両方を採用する」と言う遣り方である
define節でkidokuskip命令を実行すると、既読スキップ有効になる。systemcall skipを実行することで、textbtnwait命令既読かどうかの判定を行い、既読であればすぐに処理を返すようになる。
これを使って、iskidoku命令実装できる。

; %iskidokuは、既読スキップかどうかのフラグを格納する固定変数とする。
; 他で使われる予定はないとする。
; %bwaitは、同様に入力を検出しその結果を保存する専用の変数とする。
*iskidoku
	btndef clear
	btntime 1 ; 数値は要調整
	btnwait %bwait ; 既読行なら%bwaitに0が入り、そうでないならタイムアウトの-2/-5のどちらかが入る。
	mov %iskidoku,1/(1-%bwait) ; %bwaitが0の時1が、それ以外の時0が代入される。
return
; この命令は、CTRLの押しっぱなしを考慮していないので、押しっぱなしを検出した後で行われるのが望ましい。
; systemcall skipを実行しておかなければ、この命令は常に0を返す。

これで、bexecによるリッチ入力を実現しながら、既読スキップ実装できる。

2011年03月27日のツイート

NScripterのシステムカスタマイズにおける問題点の洗い出しと対策の模索

define節にてtextgosubを実行する。すると、start節で表示文中に@ないし\があった場合、通常の処理をせずにtextgosubで指定したラベルにgosubする。
システムカスタマイズとは、要約するとこれだけのことである
よって、textgosubで指定されたラベルで始まるルーチンには、最低限以下の機能要求される。

  • returnで終了すること。
  • クリック待ちをすること。
  • 終了時直前、@の場合は改行を、\の場合は改ページ(表示内容の消去)をすること。

ただし、現在のノベルゲームシステムに対するユーザー要求を勘案すると、上記条件は低機能すぎると言わざるを得ない。

これくらいはなければ、今のユーザーからは「システムが○○」よばわりは避けられないのではないだろうか。
これらの仕様を現状のNScripter実装するとなると、大部分はbexec命令によって解決できる。bexecは、ボタン化したスプライトクリックも、キー入力も取得できるからだ。
何が入力されたのかがわかれば、そこから分岐する実装特に難しいものではない。
bexec命令で若干問題になるのは、スプライトクリックは、ボタンダウンボタンアップがセットで検出されるのに対し、キー入力ボタンダウンだけで反応してしまうことだ。これは、CTRLキーによる強制スキップを見越しての実装だろうが、bexecを上書きしてCTRLキー以外ではボタンアップまで含めて判定するのが望ましい。
また、オートモードも、btime命令による時間制限を設けることで実装が可能になる。
唯一、bexec命令にできないことは、既読スキップモードの検出だけである。ただし、この問題が大きいためにtextbtnwaitを捨てられないと言う向きもあるのではないか。
そこで対案として考えたのは、「両方を採用する」と言う遣り方である
define節でkidokuskip命令を実行すると、既読スキップ有効になる。systemcall skipを実行することで、textbtnwait命令既読かどうかの判定を行い、既読であればすぐに処理を返すようになる。
これを使って、iskidoku命令実装できる。

; %iskidokuは、既読スキップかどうかのフラグを格納する固定変数とする。
; 他で使われる予定はないとする。
; %bwaitは、同様に入力を検出しその結果を保存する専用の変数とする。
*iskidoku
	btndef clear
	btntime 1 ; 数値は要調整
	btnwait %bwait ; 既読行なら%bwaitに0が入り、そうでないならタイムアウトの-2/-5のどちらかが入る。
	mov %iskidoku,1/(1-%bwait) ; %bwaitが0の時1が、それ以外の時0が代入される。
return
; この命令は、CTRLの押しっぱなしを考慮していないので、押しっぱなしを検出した後で行われるのが望ましい。
; systemcall skipを実行しておかなければ、この命令は常に0を返す。

これで、bexecによるリッチ入力を実現しながら、既読スキップ実装できる。

2011年03月27日のツイート

NScripterのシステムカスタマイズにおける問題点の洗い出しと対策の模索

define節にてtextgosubを実行する。すると、start節で表示文中に@ないし\があった場合、通常の処理をせずにtextgosubで指定したラベルにgosubする。
システムカスタマイズとは、要約するとこれだけのことである
よって、textgosubで指定されたラベルで始まるルーチンには、最低限以下の機能要求される。

  • returnで終了すること。
  • クリック待ちをすること。
  • 終了時直前、@の場合は改行を、\の場合は改ページ(表示内容の消去)をすること。

ただし、現在のノベルゲームシステムに対するユーザー要求を勘案すると、上記条件は低機能すぎると言わざるを得ない。

これくらいはなければ、今のユーザーからは「システムが○○」よばわりは避けられないのではないだろうか。
これらの仕様を現状のNScripter実装するとなると、大部分はbexec命令によって解決できる。bexecは、ボタン化したスプライトクリックも、キー入力も取得できるからだ。
何が入力されたのかがわかれば、そこから分岐する実装特に難しいものではない。
bexec命令で若干問題になるのは、スプライトクリックは、ボタンダウンボタンアップがセットで検出されるのに対し、キー入力ボタンダウンだけで反応してしまうことだ。これは、CTRLキーによる強制スキップを見越しての実装だろうが、bexecを上書きしてCTRLキー以外ではボタンアップまで含めて判定するのが望ましい。
また、オートモードも、btime命令による時間制限を設けることで実装が可能になる。
唯一、bexec命令にできないことは、既読スキップモードの検出だけである。ただし、この問題が大きいためにtextbtnwaitを捨てられないと言う向きもあるのではないか。
そこで対案として考えたのは、「両方を採用する」と言う遣り方である
define節でkidokuskip命令を実行すると、既読スキップ有効になる。systemcall skipを実行することで、textbtnwait命令既読かどうかの判定を行い、既読であればすぐに処理を返すようになる。
これを使って、iskidoku命令実装できる。

; %iskidokuは、既読スキップかどうかのフラグを格納する固定変数とする。
; 他で使われる予定はないとする。
; %bwaitは、同様に入力を検出しその結果を保存する専用の変数とする。
*iskidoku
	btndef clear
	btntime 1 ; 数値は要調整
	btnwait %bwait ; 既読行なら%bwaitに0が入り、そうでないならタイムアウトの-2/-5のどちらかが入る。
	mov %iskidoku,1/(1-%bwait) ; %bwaitが0の時1が、それ以外の時0が代入される。
return
; この命令は、CTRLの押しっぱなしを考慮していないので、押しっぱなしを検出した後で行われるのが望ましい。
; systemcall skipを実行しておかなければ、この命令は常に0を返す。

これで、bexecによるリッチ入力を実現しながら、既読スキップ実装できる。

2011年03月27日のツイート

2011-03-27 Sunday

2011年03月26日のツイート

2011年03月26日のツイート

2011年03月26日のツイート

2011-03-26 Saturday

2011年03月25日のツイート

2011年03月25日のツイート

2011年03月25日のツイート

2011-03-25 Friday

2011年03月24日のツイート

2011年03月24日のツイート

2011年03月24日のツイート

2011-03-24 Thursday

2011年03月23日のツイート

2011年03月23日のツイート

2011年03月23日のツイート

2011-03-23 Wednesday

いやいくらなんでも抹消はまずいよ抹消は。Amazon八分反対

はてな仕様が変わってp要素で囲まずにbr要素で区切るようにできるようになったので、やってみて過去自分書き込みちょっと確認してみた。
TSUTAYAにいったこと - 永字八法の続き。
404 Not Found書誌データAmazonから抹消されてる。Amazonこえー。

2011年03月22日のツイート

いやいくらなんでも抹消はまずいよ抹消は。Amazon八分反対

はてな仕様が変わってp要素で囲まずにbr要素で区切るようにできるようになったので、やってみて過去自分書き込みちょっと確認してみた。
TSUTAYAにいったこと - 永字八法の続き。
404 Not Found書誌データAmazonから抹消されてる。Amazonこえー。

2011年03月22日のツイート

いやいくらなんでも抹消はまずいよ抹消は。Amazon八分反対

はてな仕様が変わってp要素で囲まずにbr要素で区切るようにできるようになったので、やってみて過去自分書き込みちょっと確認してみた。
TSUTAYAにいったこと - 永字八法の続き。
404 Not Found書誌データAmazonから抹消されてる。Amazonこえー。

2011年03月22日のツイート

2011-03-22 Tuesday

2011年03月21日のツイート

2011年03月21日のツイート

2011年03月21日のツイート

2011-03-21 Monday

2011年03月20日のツイート

2011年03月20日のツイート

2011年03月20日のツイート

2011-03-20 Sunday

仕様考察・イベント絵の未読既読判定とCGモード

まず、NScripterで用意されている命令確認してみる。
define節で、filelog命令を実行しておくと、(NScripterでの)グローバル変数的ににbg命令で読み込んだ画像ファイル名が記録されるようになる。
そして、ある画像ファイルを読み込んだことがあるかどうかは、fchk演算子を使って判別できる。

filelog
(中略)
bg "event01.png",1 ; イベント画像を読み込んで表示する。
(中略)
   if fchk "event01.png" mesbox "表示したことがある。","fchk"
notif fchk "event01.png" mesbox "表示したことがない。","fchk"

CGモードを作るのにこれがあるとかなり簡単になる。

              mov $thumbnail,":c;not_viewed.png"      ; デフォルトの未読画像
if fchk $file mov $thumbnail,":a;/2,0,3;thumb_"+$file ; 読み込んだことがあるなら、それぞれの既読画像に変更
lsp %thumb_sp,$thumbnail,$thumbx,$thumby              ; スプライトとして表示
cellcheckspbtn %thumb_sp,%thumb_sp                    ; スプライトが複数のセルを持っていれば、ボタン化
; 上記工程を画像の数だけ繰り返す。
; 数が多いなら、ページに分割するなどの作業が入る。

聞くだけなら、全く問題はない。しかし、「差分」の概念が加わるとまた話は変わってくる。

差分が加わるとどうなるか。

念のために確認するが、差分とは、ほぼ同じ内容だがちょっと違う一連のグラフィックのことと今回は定義する。立ち絵は広義では差分だが、通常は「表情」と呼ぶべきで、ここではイベント絵に限定する。
多少性的な例示になるが、エロゲーを作る場合、同じポーズで着衣・半裸・全裸イベント絵の数を稼ぐ、と言うようなことはよく行われているだろう。これはグラフィッカーの都合もある。フォトショップなどで背景と人物と下着と着衣をレイヤーに分割して、イベント絵量産の省力化をするなど当たり前のように誰でもが思いつく技法である
これら差分を別々のイベント絵とカウントして並べれば、うん、数だけはそろってきてプレイヤーも満足してくれるかも知れない。
しかし、プレイヤー要求は年々高まるばかりである

「おい、なんで勝手靴下脱がしてんだ。常識的に考えて残すだろうここは」

こういう要求もあるかも知れない。かくして、グラフィッカーは様々なバージョン作成することになる。ブラの有無、パンツの有無、靴下の有無、これで一連の素材から8枚のイベント絵が生成された。うん、悪くない。大丈夫だ問題ない

問題おおありだっつーの。何度も何度も同じルート通らせるな。こちとら作業したいんじゃねえんだよ」

やばいCGモードの進捗率がなかなか上がらずプレイヤー様がお怒りになっておられる。なんとかすべえ。
そこで考えられるのがグループ化である。一連の素材から生成されるイベント絵を一つのグループとみなすことで、進捗率はグループ内のどれか一つでも既読にすれば上昇し、CGモードで実際に見る時はサブギャラリーを開いて既読の物のみを見せるようにすればよい。

要求仕様の変更

グループ全体の既読未読判定と、個々の画像既読未読判定を別々に管理記録しなければならない。
そこで考えられるのが、グループ判定用のダミー画像を作っておく方式である

event01base.png
これがダミー画像。1ドット×1ドットの何か適当な奴。これが読み込んであれば、CGモードの進捗率は上がる。
event01xxx.png
差分xxx
event01yyy.png
差分yyy

イベント絵の命名規則をこのようにしておき、イベント絵を表示する専用命令、eventを定義してみよう。

defsub event

*event
getparam %event_group,$event_ext ; イベントのグループ番号と差分コードを取得。
itoa $event_group,%event_group ; 数値を文字列に変換
if %envent_group<10 mov $event_group,"0"+$event_group ; 桁揃え
mov $event_group,"event"+$event_group ; ファイル名っぽく
notif fchk $event_group+"base.png" bg $event_group+"base.png",0 ; グループ判定画像を読み込んでいなければ、読み込み、既読フラグを立てておく。
bg $event_group+"_"+$event_ext+".png",0 ; 読み込むが表示はしないでおく。他にあるかも知れないので。
return

差分の応用

かつて、マイクロキャビンは「マリオネット・カンパニー」と言う超素敵なゲームを出した。KISSは、現在でも「カスタム隷奴」シリーズを出し続けている。
共通点は、ヒロイン容姿プレイヤー意思により変更可能であり、なおかつその変更がイベント絵全てに反映されることである。「理想の異性」を求める一面は否定できず、なればこそ「好みの容姿(や性格)」を与えられるこれらのゲームは、ある種究極のコンセプトであると言える。(コンセプトはそのままで3DグラフィックにしたTEATIMEやテックアーツ3D社も現在では存在する)
このようなシステムであった場合イベント絵はヒロイン容姿違いも差分として吸収すべきで、差分をサブギャラリーに表示するこの方式有効作用するだろう。

defsub event

*event
getparam %event_group,$event_ext ; イベントのグループ番号と差分コードを取得。
itoa $event_group,%event_group ; 数値を文字列に変換
if %envent_group<10 mov $event_group,"0"+$event_group ; 桁揃え
mov $event_group,"event"+$event_group ; ファイル名っぽく
notif fchk $event_group+"base.png" bg $event_group+"base.png",0 ; グループ判定画像を読み込んでいなければ、読み込み、既読フラグを立てておく。

; この部分で、グループ番号と与えられた$event_extでイベント絵を生成する。
; グローバル変数の一つに、使った$event_extを追加しておく。これはCGモードで使われる。

return

メモ

で、自分がこれを完成させるとするならば、サムネイル画像も読み込んだ瞬間作成した方がいいなーと。
そうすれば、サムネイル画像の有無で既読未読判定もできるしね。

2011年03月19日のツイート

仕様考察・イベント絵の未読既読判定とCGモード

まず、NScripterで用意されている命令確認してみる。
define節で、filelog命令を実行しておくと、(NScripterでの)グローバル変数的ににbg命令で読み込んだ画像ファイル名が記録されるようになる。
そして、ある画像ファイルを読み込んだことがあるかどうかは、fchk演算子を使って判別できる。

filelog
(中略)
bg "event01.png",1 ; イベント画像を読み込んで表示する。
(中略)
   if fchk "event01.png" mesbox "表示したことがある。","fchk"
notif fchk "event01.png" mesbox "表示したことがない。","fchk"

CGモードを作るのにこれがあるとかなり簡単になる。

              mov $thumbnail,":c;not_viewed.png"      ; デフォルトの未読画像
if fchk $file mov $thumbnail,":a;/2,0,3;thumb_"+$file ; 読み込んだことがあるなら、それぞれの既読画像に変更
lsp %thumb_sp,$thumbnail,$thumbx,$thumby              ; スプライトとして表示
cellcheckspbtn %thumb_sp,%thumb_sp                    ; スプライトが複数のセルを持っていれば、ボタン化
; 上記工程を画像の数だけ繰り返す。
; 数が多いなら、ページに分割するなどの作業が入る。

聞くだけなら、全く問題はない。しかし、「差分」の概念が加わるとまた話は変わってくる。

差分が加わるとどうなるか。

念のために確認するが、差分とは、ほぼ同じ内容だがちょっと違う一連のグラフィックのことと今回は定義する。立ち絵は広義では差分だが、通常は「表情」と呼ぶべきで、ここではイベント絵に限定する。
多少性的な例示になるが、エロゲーを作る場合、同じポーズで着衣・半裸・全裸イベント絵の数を稼ぐ、と言うようなことはよく行われているだろう。これはグラフィッカーの都合もある。フォトショップなどで背景と人物と下着と着衣をレイヤーに分割して、イベント絵量産の省力化をするなど当たり前のように誰でもが思いつく技法である
これら差分を別々のイベント絵とカウントして並べれば、うん、数だけはそろってきてプレイヤーも満足してくれるかも知れない。
しかし、プレイヤー要求は年々高まるばかりである

「おい、なんで勝手靴下脱がしてんだ。常識的に考えて残すだろうここは」

こういう要求もあるかも知れない。かくして、グラフィッカーは様々なバージョン作成することになる。ブラの有無、パンツの有無、靴下の有無、これで一連の素材から8枚のイベント絵が生成された。うん、悪くない。大丈夫だ問題ない

問題おおありだっつーの。何度も何度も同じルート通らせるな。こちとら作業したいんじゃねえんだよ」

やばいCGモードの進捗率がなかなか上がらずプレイヤー様がお怒りになっておられる。なんとかすべえ。
そこで考えられるのがグループ化である。一連の素材から生成されるイベント絵を一つのグループとみなすことで、進捗率はグループ内のどれか一つでも既読にすれば上昇し、CGモードで実際に見る時はサブギャラリーを開いて既読の物のみを見せるようにすればよい。

要求仕様の変更

グループ全体の既読未読判定と、個々の画像既読未読判定を別々に管理記録しなければならない。
そこで考えられるのが、グループ判定用のダミー画像を作っておく方式である

event01base.png
これがダミー画像。1ドット×1ドットの何か適当な奴。これが読み込んであれば、CGモードの進捗率は上がる。
event01xxx.png
差分xxx
event01yyy.png
差分yyy

イベント絵の命名規則をこのようにしておき、イベント絵を表示する専用命令、eventを定義してみよう。

defsub event

*event
getparam %event_group,$event_ext ; イベントのグループ番号と差分コードを取得。
itoa $event_group,%event_group ; 数値を文字列に変換
if %envent_group<10 mov $event_group,"0"+$event_group ; 桁揃え
mov $event_group,"event"+$event_group ; ファイル名っぽく
notif fchk $event_group+"base.png" bg $event_group+"base.png",0 ; グループ判定画像を読み込んでいなければ、読み込み、既読フラグを立てておく。
bg $event_group+"_"+$event_ext+".png",0 ; 読み込むが表示はしないでおく。他にあるかも知れないので。
return

差分の応用

かつて、マイクロキャビンは「マリオネット・カンパニー」と言う超素敵なゲームを出した。KISSは、現在でも「カスタム隷奴」シリーズを出し続けている。
共通点は、ヒロイン容姿プレイヤー意思により変更可能であり、なおかつその変更がイベント絵全てに反映されることである。「理想の異性」を求める一面は否定できず、なればこそ「好みの容姿(や性格)」を与えられるこれらのゲームは、ある種究極のコンセプトであると言える。(コンセプトはそのままで3DグラフィックにしたTEATIMEやテックアーツ3D社も現在では存在する)
このようなシステムであった場合イベント絵はヒロイン容姿違いも差分として吸収すべきで、差分をサブギャラリーに表示するこの方式有効作用するだろう。

defsub event

*event
getparam %event_group,$event_ext ; イベントのグループ番号と差分コードを取得。
itoa $event_group,%event_group ; 数値を文字列に変換
if %envent_group<10 mov $event_group,"0"+$event_group ; 桁揃え
mov $event_group,"event"+$event_group ; ファイル名っぽく
notif fchk $event_group+"base.png" bg $event_group+"base.png",0 ; グループ判定画像を読み込んでいなければ、読み込み、既読フラグを立てておく。

; この部分で、グループ番号と与えられた$event_extでイベント絵を生成する。
; グローバル変数の一つに、使った$event_extを追加しておく。これはCGモードで使われる。

return

メモ

で、自分がこれを完成させるとするならば、サムネイル画像も読み込んだ瞬間作成した方がいいなーと。
そうすれば、サムネイル画像の有無で既読未読判定もできるしね。

2011年03月19日のツイート

仕様考察・イベント絵の未読既読判定とCGモード

まず、NScripterで用意されている命令確認してみる。
define節で、filelog命令を実行しておくと、(NScripterでの)グローバル変数的ににbg命令で読み込んだ画像ファイル名が記録されるようになる。
そして、ある画像ファイルを読み込んだことがあるかどうかは、fchk演算子を使って判別できる。

filelog
(中略)
bg "event01.png",1 ; イベント画像を読み込んで表示する。
(中略)
   if fchk "event01.png" mesbox "表示したことがある。","fchk"
notif fchk "event01.png" mesbox "表示したことがない。","fchk"

CGモードを作るのにこれがあるとかなり簡単になる。

              mov $thumbnail,":c;not_viewed.png"      ; デフォルトの未読画像
if fchk $file mov $thumbnail,":a;/2,0,3;thumb_"+$file ; 読み込んだことがあるなら、それぞれの既読画像に変更
lsp %thumb_sp,$thumbnail,$thumbx,$thumby              ; スプライトとして表示
cellcheckspbtn %thumb_sp,%thumb_sp                    ; スプライトが複数のセルを持っていれば、ボタン化
; 上記工程を画像の数だけ繰り返す。
; 数が多いなら、ページに分割するなどの作業が入る。

聞くだけなら、全く問題はない。しかし、「差分」の概念が加わるとまた話は変わってくる。

差分が加わるとどうなるか。

念のために確認するが、差分とは、ほぼ同じ内容だがちょっと違う一連のグラフィックのことと今回は定義する。立ち絵は広義では差分だが、通常は「表情」と呼ぶべきで、ここではイベント絵に限定する。
多少性的な例示になるが、エロゲーを作る場合、同じポーズで着衣・半裸・全裸イベント絵の数を稼ぐ、と言うようなことはよく行われているだろう。これはグラフィッカーの都合もある。フォトショップなどで背景と人物と下着と着衣をレイヤーに分割して、イベント絵量産の省力化をするなど当たり前のように誰でもが思いつく技法である
これら差分を別々のイベント絵とカウントして並べれば、うん、数だけはそろってきてプレイヤーも満足してくれるかも知れない。
しかし、プレイヤー要求は年々高まるばかりである

「おい、なんで勝手靴下脱がしてんだ。常識的に考えて残すだろうここは」

こういう要求もあるかも知れない。かくして、グラフィッカーは様々なバージョン作成することになる。ブラの有無、パンツの有無、靴下の有無、これで一連の素材から8枚のイベント絵が生成された。うん、悪くない。大丈夫だ問題ない

問題おおありだっつーの。何度も何度も同じルート通らせるな。こちとら作業したいんじゃねえんだよ」

やばいCGモードの進捗率がなかなか上がらずプレイヤー様がお怒りになっておられる。なんとかすべえ。
そこで考えられるのがグループ化である。一連の素材から生成されるイベント絵を一つのグループとみなすことで、進捗率はグループ内のどれか一つでも既読にすれば上昇し、CGモードで実際に見る時はサブギャラリーを開いて既読の物のみを見せるようにすればよい。

要求仕様の変更

グループ全体の既読未読判定と、個々の画像既読未読判定を別々に管理記録しなければならない。
そこで考えられるのが、グループ判定用のダミー画像を作っておく方式である

event01base.png
これがダミー画像。1ドット×1ドットの何か適当な奴。これが読み込んであれば、CGモードの進捗率は上がる。
event01xxx.png
差分xxx
event01yyy.png
差分yyy

イベント絵の命名規則をこのようにしておき、イベント絵を表示する専用命令、eventを定義してみよう。

defsub event

*event
getparam %event_group,$event_ext ; イベントのグループ番号と差分コードを取得。
itoa $event_group,%event_group ; 数値を文字列に変換
if %envent_group<10 mov $event_group,"0"+$event_group ; 桁揃え
mov $event_group,"event"+$event_group ; ファイル名っぽく
notif fchk $event_group+"base.png" bg $event_group+"base.png",0 ; グループ判定画像を読み込んでいなければ、読み込み、既読フラグを立てておく。
bg $event_group+"_"+$event_ext+".png",0 ; 読み込むが表示はしないでおく。他にあるかも知れないので。
return

差分の応用

かつて、マイクロキャビンは「マリオネット・カンパニー」と言う超素敵なゲームを出した。KISSは、現在でも「カスタム隷奴」シリーズを出し続けている。
共通点は、ヒロイン容姿プレイヤー意思により変更可能であり、なおかつその変更がイベント絵全てに反映されることである。「理想の異性」を求める一面は否定できず、なればこそ「好みの容姿(や性格)」を与えられるこれらのゲームは、ある種究極のコンセプトであると言える。(コンセプトはそのままで3DグラフィックにしたTEATIMEやテックアーツ3D社も現在では存在する)
このようなシステムであった場合イベント絵はヒロイン容姿違いも差分として吸収すべきで、差分をサブギャラリーに表示するこの方式有効作用するだろう。

defsub event

*event
getparam %event_group,$event_ext ; イベントのグループ番号と差分コードを取得。
itoa $event_group,%event_group ; 数値を文字列に変換
if %envent_group<10 mov $event_group,"0"+$event_group ; 桁揃え
mov $event_group,"event"+$event_group ; ファイル名っぽく
notif fchk $event_group+"base.png" bg $event_group+"base.png",0 ; グループ判定画像を読み込んでいなければ、読み込み、既読フラグを立てておく。

; この部分で、グループ番号と与えられた$event_extでイベント絵を生成する。
; グローバル変数の一つに、使った$event_extを追加しておく。これはCGモードで使われる。

return

メモ

で、自分がこれを完成させるとするならば、サムネイル画像も読み込んだ瞬間作成した方がいいなーと。
そうすれば、サムネイル画像の有無で既読未読判定もできるしね。

2011年03月19日のツイート

2011-03-19 Saturday

失敗の記録

00.txt

*define
deletemenu
labellog
game
*start
sample
   if lchk *sample_label mesbox "通りました。","lchk"
notif lchk *sample_label mesbox "通ってません。","lchk"
end

system.lua


NSExec("luasub sample")
function NSCOM_sample()
	NSExec("\*sample_label")
end

結論

エラーになる。
nsluaの方から、ラベルの宣言はできない。
ので、nsluaから、lchkの動作を操作することはできない。

ラベルの通過チェック命令と画像の読み込みチェック命令

タイトル通りのものは既にlchkやfchkがあるが、これはif(やnotif)の条件式としての扱いしかできない。
なので、変数に落としこむ何かを作ってみる。

define節game以上

labellog ; 必須
filelog  ; 必須
numalias chk_arg,(適当な数値)
defsub label_check
defsub file_check

game以下start以上

*label_check
getparam i%chk_arg,$chk_arg
                 mov %%chk_arg,0
if lchk $chk_arg mov %%chk_arg,1
return

*file_check
getparam i%chk_arg,$chk_arg
                 mov %%chk_arg,0
if fchk $chk_arg mov %%chk_arg,1
return

解説

特殊命令だったのをわざわざ使いにくい通常命令のレベルまで落としてしまって何か意味があるのかと考えないでもないが、きっと既読未読情報配列とかに格納するのに使えるさきっときっときっと。

2011年03月18日のツイート

失敗の記録

00.txt

*define
deletemenu
labellog
game
*start
sample
   if lchk *sample_label mesbox "通りました。","lchk"
notif lchk *sample_label mesbox "通ってません。","lchk"
end

system.lua


NSExec("luasub sample")
function NSCOM_sample()
	NSExec("\*sample_label")
end

結論

エラーになる。
nsluaの方から、ラベルの宣言はできない。
ので、nsluaから、lchkの動作を操作することはできない。

ラベルの通過チェック命令と画像の読み込みチェック命令

タイトル通りのものは既にlchkやfchkがあるが、これはif(やnotif)の条件式としての扱いしかできない。
なので、変数に落としこむ何かを作ってみる。

define節game以上

labellog ; 必須
filelog  ; 必須
numalias chk_arg,(適当な数値)
defsub label_check
defsub file_check

game以下start以上

*label_check
getparam i%chk_arg,$chk_arg
                 mov %%chk_arg,0
if lchk $chk_arg mov %%chk_arg,1
return

*file_check
getparam i%chk_arg,$chk_arg
                 mov %%chk_arg,0
if fchk $chk_arg mov %%chk_arg,1
return

解説

特殊命令だったのをわざわざ使いにくい通常命令のレベルまで落としてしまって何か意味があるのかと考えないでもないが、きっと既読未読情報配列とかに格納するのに使えるさきっときっときっと。

2011年03月18日のツイート

失敗の記録

00.txt

*define
deletemenu
labellog
game
*start
sample
   if lchk *sample_label mesbox "通りました。","lchk"
notif lchk *sample_label mesbox "通ってません。","lchk"
end

system.lua


NSExec("luasub sample")
function NSCOM_sample()
	NSExec("\*sample_label")
end

結論

エラーになる。
nsluaの方から、ラベルの宣言はできない。
ので、nsluaから、lchkの動作を操作することはできない。

ラベルの通過チェック命令と画像の読み込みチェック命令

タイトル通りのものは既にlchkやfchkがあるが、これはif(やnotif)の条件式としての扱いしかできない。
なので、変数に落としこむ何かを作ってみる。

define節game以上

labellog ; 必須
filelog  ; 必須
numalias chk_arg,(適当な数値)
defsub label_check
defsub file_check

game以下start以上

*label_check
getparam i%chk_arg,$chk_arg
                 mov %%chk_arg,0
if lchk $chk_arg mov %%chk_arg,1
return

*file_check
getparam i%chk_arg,$chk_arg
                 mov %%chk_arg,0
if fchk $chk_arg mov %%chk_arg,1
return

解説

特殊命令だったのをわざわざ使いにくい通常命令のレベルまで落としてしまって何か意味があるのかと考えないでもないが、きっと既読未読情報配列とかに格納するのに使えるさきっときっときっと。

2011年03月18日のツイート

2011-03-18 Friday

2011年03月17日のツイート

2011年03月17日のツイート

2011年03月17日のツイート

2011-03-17 Thursday

exist_goto / exist_gosub / exist_return

引数指定したラベル存在したら、そのラベルに飛ぶ何かを作ってみる。

解説

つの命令を作る。

  • exist_goto
  • exist_gosub
  • exist_return

基本的機能は同じ。引数にラベル指定する。(正確には、ラベル判断される文字列文字列変数の集合)
そのラベル存在するならば、そのラベルgotoする/gosubする/returnする。

命令ベル存在した場合ベル存在しない場合
exist_gotoそっちに飛んで返ってこない何もせず次の行へ
exist_gosubそっちの処理を済ませてから次の行へ何もせず次の行へ
exist_returnそっちにreturnする。スタックに注意何もせず次の行へ

前二者はそれなりに使い道は考えつくけれど、exist_returnは難しいかなあ。

define節game以上

numalais labelexist,(適当な数値)
defsub exist_goto
defsub exist_gosub
defsub exist_return

game以下*start以上

*exist_goto
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 return $labelexist
return

*exist_gosub
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 goto $labelexist
return

*exist_return
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 return *exist_return_main
return
*exist_return_main
return $labelexist

使い方

これを説明しておかなければならなかった。
オブジェクト指向プログラミングにおけるメソッドのオーバーライドに似た効果が得られる。

*work
getparam $mode
exist_gosub "*"+$mode+"_work"
default_work
return

こういうスクリプトがあったとする。
work命令に与える引数と、それに合わせたサブルーチン作ることによって、work命令に動作を追加したりしなかったりができる。
共通部分の多い一連の処理の中で、ちょっとだけ違う処理を加えるのに便利。

2011年03月16日のツイート

exist_goto / exist_gosub / exist_return

引数指定したラベル存在したら、そのラベルに飛ぶ何かを作ってみる。

解説

つの命令を作る。

  • exist_goto
  • exist_gosub
  • exist_return

基本的機能は同じ。引数にラベル指定する。(正確には、ラベル判断される文字列文字列変数の集合)
そのラベル存在するならば、そのラベルgotoする/gosubする/returnする。

命令ベル存在した場合ベル存在しない場合
exist_gotoそっちに飛んで返ってこない何もせず次の行へ
exist_gosubそっちの処理を済ませてから次の行へ何もせず次の行へ
exist_returnそっちにreturnする。スタックに注意何もせず次の行へ

前二者はそれなりに使い道は考えつくけれど、exist_returnは難しいかなあ。

define節game以上

numalais labelexist,(適当な数値)
defsub exist_goto
defsub exist_gosub
defsub exist_return

game以下*start以上

*exist_goto
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 return $labelexist
return

*exist_gosub
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 goto $labelexist
return

*exist_return
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 return *exist_return_main
return
*exist_return_main
return $labelexist

使い方

これを説明しておかなければならなかった。
オブジェクト指向プログラミングにおけるメソッドのオーバーライドに似た効果が得られる。

*work
getparam $mode
exist_gosub "*"+$mode+"_work"
default_work
return

こういうスクリプトがあったとする。
work命令に与える引数と、それに合わせたサブルーチン作ることによって、work命令に動作を追加したりしなかったりができる。
共通部分の多い一連の処理の中で、ちょっとだけ違う処理を加えるのに便利。

2011年03月16日のツイート

exist_goto / exist_gosub / exist_return

引数指定したラベル存在したら、そのラベルに飛ぶ何かを作ってみる。

解説

つの命令を作る。

  • exist_goto
  • exist_gosub
  • exist_return

基本的機能は同じ。引数にラベル指定する。(正確には、ラベル判断される文字列文字列変数の集合)
そのラベル存在するならば、そのラベルgotoする/gosubする/returnする。

命令ベル存在した場合ベル存在しない場合
exist_gotoそっちに飛んで返ってこない何もせず次の行へ
exist_gosubそっちの処理を済ませてから次の行へ何もせず次の行へ
exist_returnそっちにreturnする。スタックに注意何もせず次の行へ

前二者はそれなりに使い道は考えつくけれど、exist_returnは難しいかなあ。

define節game以上

numalais labelexist,(適当な数値)
defsub exist_goto
defsub exist_gosub
defsub exist_return

game以下*start以上

*exist_goto
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 return $labelexist
return

*exist_gosub
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 goto $labelexist
return

*exist_return
getparam $labelexist
labelexist %labelexist,$labelexist
if %labelexist=1 return *exist_return_main
return
*exist_return_main
return $labelexist

使い方

これを説明しておかなければならなかった。
オブジェクト指向プログラミングにおけるメソッドのオーバーライドに似た効果が得られる。

*work
getparam $mode
exist_gosub "*"+$mode+"_work"
default_work
return

こういうスクリプトがあったとする。
work命令に与える引数と、それに合わせたサブルーチン作ることによって、work命令に動作を追加したりしなかったりができる。
共通部分の多い一連の処理の中で、ちょっとだけ違う処理を加えるのに便利。

2011年03月16日のツイート

2011-03-16 Wednesday

2011年03月15日のツイート

2011年03月15日のツイート