トップページgamedev
1001コメント337KB

NScripter Ver.18.00

■ このスレッドは過去ログ倉庫に格納されています
0001名前は開発中のものです。2011/07/29(金) 13:42:31.89ID:eqalPxic
商業流通でなければフリーで利用可能な
ゲームエンジンNScripterについて語るスレです。

・本家
ttp://www.nscripter.com/

・うpろだ
ttp://nscuploader.pa.land.to/
0291名前は開発中のものです。2011/11/03(木) 09:03:15.09ID:I5e3eJcR
禁則処理は行で分けるんじゃなくて、最初は文字で分けるべきな。

local text = "なんか適当な、サンプル文章。" -- 表示したい文章

表示文に2バイト文字しか入らないことが保証されているなら、分割部分は簡単にできるな。

local letters = {} -- 分割した文字を入れるテーブル
-- 2バイト文字専用分割
for i=1, text:len()-1, 2 do
letters[#letters+1] = text:gsub(i, i+1)
end

半角文字も混じるようなら、文字コード調べるところからになるなあ。

function letter_length(letter) -- 文字を与えたら、その文字の長さを0か1で返す関数。半角なら0、全角なら1を返す。
local num = letter:byte() -- 先頭の文字の文字コードを取得。
if num < 127 then return 0 end
if num < 161 then return 1 end
if num < 224 then return 0 end
return 1
end
-- この関数はShift-JIS専用

local letters = {}
local cursor = 1
while cursor < text:len()+1 do
letters[#letters+1] = text:gsub(cursor, cursor+letter_length(text:gsub(cursor, cursor))
cursor = cursor + letters[#letters]:len()
end

どっちか使えば、文字列の分割は完了。
次は肝の禁則処理。
0292名前は開発中のものです。2011/11/03(木) 09:25:32.86ID:I5e3eJcR
禁則処理は、
1.行頭禁則(行頭に来てはならない)と、
2.行末禁則(行末に来てはならない)と、
3.分離禁則(途中で改行してはならない)
の三種類がある。

句読点「。」とか「、」は1に相当する。
「ゃゅょ」とかの拗音促音も1になる。
カッコ類「(」「)」は、前が2になり、後が1になる。
英単語などの半角文字は、半角スペースを除いて全て3になる。
ちなみに一種類の文字が複数の属性を持つことはない。だいたい。

まあ、そういうのは思いついたのをどんどん追加していけばいい。

local no_head = {} -- 行頭禁則文字を定義するテーブル。
no_head["。"] = true
no_head["、"] = true
-- こんな感じでどんどん増やす。

local no_tail = {} -- 行末禁則文字を定義するテーブル。
no_tail["("] = true
no_head[")"] = true
-- 同じく増やす。

で、さっき分割した一文字ずつを今度は結合していく。
結合チェックは、3を最初に、それから1と2(こっちは順番はどうでもいい)の順でチェックする。

おっと、書きこむスペースがなくなった。
0293名前は開発中のものです。2011/11/03(木) 09:44:21.23ID:I5e3eJcR
-- 3.の分離禁則を実現するルーチン
-- チェック1:頭から舐めていって、分離禁則文字が見つかったら、チェック2を開始する。
-- チェック2:次の文字からチェックしていく。分離禁則文字が連続する限り、それをチェック1の文字の末尾につけていく。
local cursor = 1 -- さっきも作ったから、localは要らないかも。
local letter1
local letter2

function is_no_purge(letter) -- 文字を与えると、それが分離禁則文字かどうかを返す関数
if letter:len()>1 then return false end -- 半角文字でなければ分離禁則文字ではない。
if letter == " " then return false end -- 半角スペースは分離禁則文字ではない。
return true
end

while cursor < #letters do
letter1 = letters[cursor]
-- チェック1
if is_no_purge(letter1) then -- 分離禁則文字であればチェック2開始
while true do
letter2 = letters[cursor+1]
if type(letter2)=="nil" then break end -- 終了条件
if is_no_purge(letter2) then
letter1 = letter1 .. letter2 -- 結合
table.remove(letters, cursor+1) -- 結合した文字を削除
else
break -- 終了
end
end
end
lettes[cursor] = letter1 -- 再登録。
cursor = cursor + 1
end
0294名前は開発中のものです。2011/11/03(木) 09:54:35.36ID:I5e3eJcR
-- 行頭禁則処理
-- 行頭禁則文字は、前の文字にくっつく性質を持つ。

cursor = 1
while cursor < #letters do
letter1 = letters[cursor+1] -- 文字を一つ取得。
if no_head[letter1] then -- それが行頭禁則文字だったら
letters[cursor] = letters[cursor]..letter1
table.remove(letters, cursor+1)
else
cursor = cursor + 1
end
end

-- 行末禁則処理
-- 行末禁則文字は、後の文字にくっつく性質を持つ。
cursor = 1
while cursor < #letters do
letter1 = letters[cursor] -- 文字を一つ取得。
if no_tail(letter1) then -- それが行末禁則文字だったら
letter1 = letter1..table.remove(letters, cursor+1)
letters[cursor] = letter1
end
cursor = cursor + 1
end

これでやっと禁則処理ができた。
次は、表示する際の処理。
0295名前は開発中のものです。2011/11/03(木) 10:08:05.81ID:I5e3eJcR
local width_max = 40 -- テキストウィンドウの幅(単位:文字数)ただし、半角で。
function next_line(letters) -- 次の一行を返す。引数にはlettersを与える。
if #letters<1 then return nil end -- 表示する内容がない場合はnilを返す。
local text = ""
if letters[1]==" " then
table.remove(letters, 1) -- 先頭が半角スペースなら表示しない。
else
if width_max < text:len()+letters[1]:len() then
-- 現在の内容と次に来る文字の長さの合計が、最大幅を超える場合、終了。
return text
else
text = text .. table.remove(letters, 1)
end
end
end

local all_text = "" -- 現在のテキストウィンドウの内容
while true do
local line = next_line() -- 次の一行を取得。
if line then
if all_text:len()>0 then -- 既に何か表示していれば
NSExec("_br") -- 改行
all_text = all_text.."\\"
end
NSExec("_puttext \""..line.."/\"")
all_text = all_text..line
else
-- 表示内容がないなら、終了
break
end
end
■ このスレッドは過去ログ倉庫に格納されています