コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

くだものしょうぶ (2) パラメータの保存と読み込み

くだものしょうぶのv0.44から駒のサイズを変更できるようにしました。パラメータの保存と読み込みのところを説明していませんでしたので、以下に書きたいと思います。

パラメータの宣言

保存するパラメータは、現在、サウンドの有無とBGMの有無、そして、駒のサイズとなっています。それぞれ、以下のように宣言しました。メッセージエリアの設定値は、盤面の基本パラメータから決まります。後で説明します。

BanDraw={ ox, oy, cx, cy, ex, ey, ksize, sukima, pitch } --盤面の基本パラメータ
Msg={ x0 , y0, x1, y1, font, col, bgc }          --メッセージエリアの設定値
BanDraw.ksize = 52                               --駒の大きさ
SoundOnOff = 1                                   --サウンドの設定: 0:なし, 1:あり
BGMOnOff = 0                                     --BGMの設定: 0:なし, 1:あり

保存形式

保存データ形式は単純にCSVにしました。以下のように保存されます。

SoundOnOff,1
BGMOnOff,0
BanSize,52

パラメータの保存・読み込みプログラム

パラメータの読み込みは、メインプログラム開始時に走ります。、

------------------------------------------
--メインプログラム
------------------------------------------
function main()
local x,y
local winner, wstr
local a
local filename
local ret
 --背景色
 canvas.drawCls( BGColor )
 -- 設定を読み込む
 iniFileSetup( "r" )
 ・
 ・
 ・

パラメータの読み込みと書き出しは、1つのプログラムにまとめました。書き出しは、単純にCSVデータにして書き込んでいるだけです。

------------------------------------------
--初期化ファイルの操作
-- opt:w 書き込み, r:読み込み
------------------------------------------
function iniFileSetup( opt )
local fp
 if( opt=="w" )then
   --パラメータの書き込み
   fp = io.open(LuaridaPath.."/"..Doubutsu.IniFilename,"w+")
     if( not(fp) )then
       dialog( LuaridaPath.."/"..Doubutsu.IniFilename.."がオープンできません","プログラムを終了して下さい", 0 )
     else
       fp:write( "SoundOnOff,"..tostring(SoundOnOff).."\n" )
       fp:write( "BGMOnOff,"..tostring(BGMOnOff).."\n" )
       fp:write( "BanSize,"..tostring(BanDraw.ksize).."\n" )
       io.flush()
       io.close(fp)
     end
 elseif( opt=="r" )then
   --パラメータの読み込み
   fp = io.open( LuaridaPath.."/"..Doubutsu.IniFilename, "r")
   if( not(fp) )then
     --読み込めなければファイルを生成します
     iniFileSetup( "w" )
   else
     --パラメータ(CSV)データを読み込みます
     while(true)do
       local str = fp:read("*l")        --1行読み込み
       if( str==nil )then break end     --読込むデータが無ければ終了
       str = string.gsub( str,"\r","" ) --改行コードを外す
       local t={}
       t = split( str, "," )            --CSVをt[1]とt[2]に読み込む
       if( t[1]=="SoundOnOff" )then SoundOnOff = tonumber(t[2]) end
       if( t[1]=="BGMOnOff" )then BGMOnOff = tonumber(t[2]) end
       if( t[1]=="BanSize" )then
         BanDraw.ksize = tonumber(t[2])
         local cy = ViewHeight/2
         local sukima = math.floor(BanDraw.ksize*3/52)
         --駒サイズから計算した盤サイズが画面よりも大きくなりそうだったら、52に初期化する
         if( cy + sukima + BanDraw.ksize*1.5>ViewHeight-25 )then
           BanDraw.ksize = 52
         end
       end
     end
     io.close(fp)
   end
 end
end

読み込みの部分は、1行読み込んでは処理をするループになっています。データが少ないので、単純なプログラムにしました。駒のサイズはBanDraw.ksizeに読み込みます。読み込んだ駒の値を使って将棋盤を作成したときに、縦方向に画面からはみ出してしまう場合は、52に初期化するようにしています。

パラメータの入力

パラメータの入力は、最初の対戦メニュの下に追加しました。editText()命令によって入力された文字が正しい数字のとき、BanDraw.ksizeに値を設定し、パラメータを保存して、駒画像を変更サイズに読み直して、BanDrawパラーメータを再計算します。入力値が数値で無い場合は変更せず、また、入力値が画面に対して大きな場合は、52に初期化します。

------------------------------------------
-- 対戦を決める
------------------------------------------
function selectTaisen()
local ret = 0
local c1,c2,c3,c4
 while(true)do
   item.clear()
   item.add( "ひとのたいせん", 0 )
   item.add( "せんてがひと、ごでがコンピュータ", 0 )
   item.add( "せんてがコンピュータ、ごでがひと", 0 )
   item.add( "おしまい", 0 )
   item.add( "駒の大きさ変更", 0 )
   item.add( "設定変更", 0 )
   ret = item.list("たいせんをえらんでね")
   if( ret<1 or ret==4 )then ret = 0 end   --プログラム終了
   if( ret == 5 )then
     local moji,s = editText("駒の大きさを入力してください")
     if( s==nil or moji==nil or moji=="" or tonumber(moji)==nil )then
       --BanDraw.ksize = 52     --とりあえず、変更なし
     elseif( s==1 )then
       BanDraw.ksize = tonumber( moji )
       local cy = ViewHeight/2
       local sukima = math.floor(BanDraw.ksize*3/52)
       --駒サイズから計算した盤サイズが画面よりも大きくなりそうだったら、52に初期化する
       if( cy + sukima + BanDraw.ksize*1.5>ViewHeight-25 )then
         BanDraw.ksize = 52
       end
       iniFileSetup( "w" )      --パラメータの保存
       --駒データを読み直す(ワークエリアにくだものしょうぶ画像を再読み込みます)
       initPicture()
       -- BanDrawデータとMsgパラメータを再設定します
       initBanDraw()
     else
       --BanDraw.ksize = 52     --とりあえず、変更なし
     end
   elseif( ret == 6 )then
     item.clear()
     item.add( "サウンド有り", SoundOnOff )
     item.add( "BGM有り", BGMOnOff )
     c1,c2,c3,c4,ret = item.check("オプション設定")
     if( ret==1 )then
       SoundOnOff = math.fmod(math.floor(c1/math.pow(2,15)),2)
       BGMOnOff = math.fmod(math.floor(c1/math.pow(2,14)),2)
       iniFileSetup( "w" )      --パラメータの保存
       if( SoundOnOff==1 )then
         if( BGMOnOff==1 )then
           --BGMを開始させます
           sound.start( 7, 1 )  --ループフラグを立てる
         else
           --BGMの停止
           sound.stop( 7 )
         end
       else
         --BGMの停止
         sound.stop( 7 )
       end
     end
   else
     break
   end
 end
 return ret
end

サウンドのパラメータはitem.check()命令を用いているので、ビット単位のフラグとなっています。戻り値のc1の値から、先頭ビットと二番目のビットの値をフラグとして取り出しています。

駒データを読み込む

駒データは、駒サイズに合わせてワークエリアに読み込みます。canvas.loadBmp()を用いて読み込むのですが、ここで、Luaridav1.42Betaで追加した nパラメータを使っています。n=4とすることで、きれいな縮小画像を取り込むことができます。背景用画像は、背景色に塗りつぶしたメイン画面から駒サイズの大きさを取り込んでいます。これらの画像データはワークエリアの上部に並んで保存されます。

------------------------------------------
-- ワークエリアにくだものしょうぶ画像を読み込みます
------------------------------------------
function initPicture()
local filename
local size = BanDraw.ksize - 1
 --ワークエリア画面をクリアします
 canvas.workCls()
 --すいか画像の読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[1]
 if( canvas.loadBmp( filename, 0, 0, size, size, 4 )==-1)then return -1, filename end
 --メロン画像の読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[2]
 if( canvas.loadBmp( filename, size*1 + 1, 0, size*2 + 1, size, 4 )==-1)then return -1, filename end
 --バナナ画像の読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[3]
 if( canvas.loadBmp( filename, size*2 + 2, 0, size*3 + 2, size, 4 )==-1)then return -1, filename end
 --ぶどう画像の読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[4]
 if( canvas.loadBmp( filename, size*3 + 3, 0, size*4 + 3, size, 4 )==-1)then return -1, filename end
 --みかん画像の読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[5]
 if( canvas.loadBmp( filename, size*4 + 4, 0, size*5 + 4, size, 4 )==-1)then return -1, filename end
 --相手エリアマス画像の読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[6]
 if( canvas.loadBmp( filename, size*5 + 5, 0, size*6 + 5, size )==-1)then return -1, filename end
 --対戦エリアマスの読み込み
 filename = LuaridaPath.."/"..Doubutsu.Gazo[7]
 if( canvas.loadBmp( filename, size*6 + 6, 0, size*7 + 6, size )==-1)then return -1, filename end
 --背景用画像の生成
 canvas.getg( 0, 0, size, size, size*7 + 7, 0, size*8 + 7, size )
end

画面構成パラメータの初期化

駒のサイズ(BanDraw.ksize)と画面センタを元に、将棋盤やメッセージエリアの基本座標を計算します。このパラメータを用いて、すべての画像配置を計算します。

------------------------------------------
-- BanDrawデータとMsgパラメータの初期化をします
------------------------------------------
function initBanDraw()
 BanDraw.cx = ViewWide/2                          --画面中心X座標
 BanDraw.cy = ViewHeight/2                        --画面中心Y座標
 BanDraw.sukima = math.floor(BanDraw.ksize*3/52)  --盤のマスとマスの隙間
 BanDraw.pitch = BanDraw.ksize + BanDraw.sukima   --マスのピッチ
 BanDraw.ox = BanDraw.cx - ( BanDraw.sukima*1.5 + BanDraw.ksize*2 ) + 1  --盤の描き始めX座標
 BanDraw.oy = BanDraw.cy - ( BanDraw.sukima + BanDraw.ksize*1.5 ) + 1    --盤の描き始めY座標
 BanDraw.ex = BanDraw.ox + BanDraw.sukima*3 + BanDraw.ksize*4 - 1        --盤の描き終わりX座標
 BanDraw.ey = BanDraw.oy + BanDraw.sukima*2 + BanDraw.ksize*3 - 1        --盤の描き終わりY座標
 Msg.x0 = BanDraw.ox                                            --メッセージエリア開始X座標
 Msg.y0 = BanDraw.ey + BanDraw.sukima + 1                       --メッセージエリア開始Y座標
 Msg.x1 = BanDraw.ox + BanDraw.sukima*2 + BanDraw.ksize*3 - 1   --メッセージエリア終了X座標
 Msg.y1 = ViewHeight - 1                                        --メッセージエリア終了Y座標
 Msg.font = 14                                                  --メッセージフォントサイズ
 Msg.col = color(255,255,255)                                   --メッセージフォント色
 Msg.bgc = color( 61,111,203)                                   --メッセージ背景色
end

この説明を書いていて思ったことは、メイン画面データをフラッシュするときに、画面データをn倍してフラッシュするようなコマンドを設ければ、画面サイズに合わせてプログラムを書き換えなくても、簡単に画面サイズに合わせたプログラムが作れることに、気が付きました。
Luaridaのcanvas.putflush()コマンドに拡大率オプションを追加することを考えよう。