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

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

スマートフォン勉強会@関西#14で話をしました (6)

今日のブログで、サウンドとタッチとダイアログのスライド紹介をまとめて行いたいと思います。

サウンド命令について


サウンド命令は7つあります。最初のsound.beep()は、昔のBASICで良くあった「ビー」という音を鳴らす命令です。周波数と鳴らす時間を設定すると音が鳴ります。ただし、多重再生には対応していないので、鳴り終わる前にbeep命令を実行すると前の音は鳴り止みます。余りにこれを続けるとLuaridaが落ちます(^^;。
サンプルにあるように、前の音が完全に鳴り終わるタイミングで、次の音を鳴らしてください。上の図でlen=25となっているのが、25ms音を鳴らすという意味です。tm = system.getSec()+len/800としているのは、単位が秒でlen/800秒待つことになります。本来ならmsなので、len/1000とするところですが、長めに待たせるために、len/800としています。

sound.isPlay()〜sound.stop()までの命令は、サウンドファイル(wavやmp3やogg)を鳴らす命令です。0〜7までのサウンド番号にサウンドを設定して、startで鳴らすことができます。この命令は多重に鳴らすことができます。ただし、1番号の多重再生は4重ねまでです。音源8つでは少ないかもしれませんが、setSoundFileで音データファイルを読み込みながら鳴らしてください。
以下に、sound.beep()を使ったオルガンデモソースを書きます。

------------------------------------------
--organ
------------------------------------------
--関数宣言--------------------------------
main={}            --mainメソッド
workdroiddraw={}   -- ドロイドくんをWorkBMPのx,y座標に描きます
printscrl={}       --スクロールするテキスト表示
soundini={}        --サウンドデータの初期化
beepon={}          --音を鳴らす

--グローバル変数宣言----------------------
Onkai={ x={}, y=0, hz={}, txt={}, fsize=0 }

--画面サイズ取得
Gwide, Gheight = canvas.getviewSize()
LuaridaPath = system.getCardMnt().."/luarida"	--luaファイルを保存しているPath
------------------------------------------
mt={}
mt.__newindex=function(mtt,mtn,mtv)
 dialog( "Error Message", "宣言していない変数 "..mtn.." に値を入れようとしています", 0 )
 toast("画面タッチで実行を続けます", 1)
 touch(3)
end
mt.__index=function(mtt,mtn)
 dialog( "Error Message", "変数 "..mtn.." は宣言されていません", 0 )
 toast("画面タッチで実行を続けます", 1)
 touch(3)
end
setmetatable(_G,mt)
--------以下が実プログラム----------------
------------------------------------------
--スクロールするテキスト表示
------------------------------------------
function printscrl( str, fontsize, fcolor, bcolor )
local sc
 --一度、見えないところにテキストを書いて、改行数を求める
 sc = canvas.drawTextBox( str, 0, Gheight+1, fontsize, fcolor, Gwide )
 --画面の絵をワークエリアに取り込みます
 canvas.getg( 0, fontsize*sc, Gwide-1, Gheight-1, 0, fontsize*sc, Gwide-1, Gheight-1 )
 --取り込んだ画面をスクロールさせて描きます
 canvas.putg( 0, 0, Gwide-1, Gheight-fontsize*sc-1, 0, fontsize*sc, Gwide-1, Gheight-1 )
 --書き出す部分をバックカラーで塗り潰します
 canvas.drawRect(  0, Gheight-fontsize*sc-1, Gwide, Gheight, bcolor, 1 )
 --スクロールしたところにテキストを書きます
 canvas.drawTextBox( str, 0, Gheight-fontsize*sc, fontsize, fcolor, Gwide )
end
------------------------------------------
-- ドロイドくんをWorkBMPのx,y座標に描きます
-- ドロイドくん大きさ 56×65
------------------------------------------
function workdroiddraw( wx, wy )
local dcol = color(164,198,57)
local ecol = color(255,255,255)
local x, y = 0, 0
 --MainBMPを透明色に塗りつぶす
 canvas.putCls()
 --顔を描く
 canvas.putCircle( x+28,y+23,19,dcol, 1 )
 canvas.putCircle( x+20,y+13,1,ecol, 1 )
 canvas.putCircle( x+36,y+13,1,ecol, 1 )
 --角を描く
 canvas.putLine( x+16,y+0,x+19,y+5,dcol)
 canvas.putLine( x+16,y+0,x+20,y+5,dcol)
 canvas.putLine( x+40,y+0,x+35,y+5,dcol)
 canvas.putLine( x+40,y+0,x+34,y+5,dcol)
 --顔をWorkBMPに描画
 canvas.getg( x+10,y+0,x+45,y+19,wx+10,wy+0,wx+45,wy+19 )
 --再びMainBMPを透明色に塗りつぶす
 canvas.putCls()
 --体を描く
 canvas.putCircle( x+15,y+48,4,dcol, 1 )
 canvas.putCircle( x+41,y+48,4,dcol, 1 )
 canvas.putRect( x+10,y+22,x+45,y+48,dcol,1 )
 canvas.putRect( x+15,y+48,x+41,y+51,dcol,1 )
 --足を描く
 canvas.putCircle( x+22,y+61,4,dcol, 1 )
 canvas.putRect( x+18,y+51,x+25,y+61,dcol,1 )
 canvas.putCircle( x+34,y+61,4,dcol, 1 )
 canvas.putRect( x+30,y+51,x+37,y+61,dcol,1 )
 --腕を描く
 canvas.putCircle( x+52,y+24,4,dcol, 1 )
 canvas.putCircle( x+52,y+41,4,dcol, 1 )
 canvas.putRect( x+48,y+25,x+55,y+40,dcol,1 )
 canvas.putCircle( x+4,y+24,4,dcol, 1 )
 canvas.putCircle( x+4,y+41,4,dcol, 1 )
 canvas.putRect( x+0,y+25,x+7,y+40,dcol,1 )
 --体をWorkBMPに取得する
 canvas.getg( x,y+20,x+55,y+64, wx, wy+20, wx+55, wy+64 )
end
------------------------------------------
--サウンドデータの初期化
------------------------------------------
function soundini( n )
local i
 --周波数計算用
 Onkai.hz[1] = 0
 Onkai.hz[2] = 2
 Onkai.hz[3] = 3
 Onkai.hz[4] = 5
 Onkai.hz[5] = 7
 Onkai.hz[6] = 8
 Onkai.hz[7] = 10
 Onkai.hz[8] = 12
 Onkai.hz[9] = 14
 Onkai.hz[10] = 15
 Onkai.hz[11] = 17
 Onkai.hz[12] = 19
 Onkai.hz[13] = 20
 Onkai.hz[14] = 22
 Onkai.hz[15] = 24
 Onkai.hz[16] = 26
 Onkai.hz[17] = 27
 Onkai.hz[18] = 29
 Onkai.txt[1] = "ラ"
 Onkai.txt[2] = "シ"
 Onkai.txt[3] = "ド"
 Onkai.txt[4] = "レ"
 Onkai.txt[5] = "ミ"
 Onkai.txt[6] = "ファ"
 Onkai.txt[7] = "ソ"
 Onkai.txt[8] = "ラ"
 Onkai.txt[9] = "シ"
 Onkai.txt[10] = "ド"
 Onkai.txt[11] = "レ"
 Onkai.txt[12] = "ミ"
 Onkai.txt[13] = "ファ"
 Onkai.txt[14] = "ソ"
 Onkai.txt[15] = "ラ"
 Onkai.txt[16] = "シ"
 Onkai.txt[17] = "ド"
 Onkai.txt[18] = "レ"

 local dd = Gwide/n
 Onkai.fsize = dd/2
 Onkai.y = Gheight*0.7
 for i=1,n+1 do
   Onkai.x[i] = (i-1)*dd
   local p = Onkai.x[i]
   if( Onkai.txt[i]~="ファ" )then
     p = p + Onkai.fsize/2
   end
   canvas.putText( Onkai.txt[i], p+1, Onkai.y, Onkai.fsize, color(0,0,0) )
   canvas.putText( Onkai.txt[i], p, Onkai.y, Onkai.fsize, color(0,0,0) )
 end
 canvas.putflush()
end
------------------------------------------
--音を鳴らす
------------------------------------------
function beepon( a )
local hz = 440*math.pow( 2, a/12 )
local len = 25

 sound.beep( hz, len )
 local tm = system.getSec() + len/800
 while( tm>system.getSec() )do end
end
------------------------------------------
--メインプログラム
------------------------------------------
function main()
local siro = color(255,255,255)
local i
local bx, by = 56, 0
local droidy = Gheight*0.5-65/2

 --ドロイドくんをワーク画面にセットする
 workdroiddraw( 0, 0 )

 --背景を白にする
 canvas.drawCls( siro )

 --サウンドデータの初期化
 soundini( 10 )

 --画面のバックアップ
 canvas.getg(0,0,Gwide-1,Gheight-1, bx,by,bx+Gwide-1,by+Gheight-1)

 while(true)do
   local x,y,s = touch(1)
   for i=1,19 do
     if( Onkai.x[i]>x )then
       --音を鳴らす
       beepon( Onkai.hz[i-1] )
       canvas.putg(0,0,Gwide-1,Gheight-1, bx,by,bx+Gwide-1,by+Gheight-1)
       canvas.putrotg(x,droidy,0, 0,0,55,64)
       canvas.putflush()
       break
     end
   end
   if( y>droidy-65/2 and y<droidy+65/2 )then break end
 end
end
main()
system.exit()

タッチについて


画面タッチの取得には、touch()という命令を使います。詳しくはここ
戻り値は、タッチした(X,Y)座標とタッチの状態です。タッチの状態は上図の下段に書いてある通りです。
また、引数によってタッチの処理が変わります。上図上段にあるように、touch()のときは即座にタッチ座標等が返ってきます。touch(3)とすると画面タッチして指が離れるまで待ちます。
注意点として、取得座標はcanvas.setMainBmp(Wide,Height)で設定した範囲となることです。setMainBmpの初期値は画面サイズなので気にする必要はないですが、変更した場合は気をつけてください。


ダイアログについて


ダイアログの説明もすまべんの時に時間が無くて飛ばしてしまいました。ダイアログには、メッセージボックスのように使えるdialog命令と、一定時間メッセージを表示するtoast命令と、アイテムをセットして選択させるitem.から始まる命令の3タイプがあります。
上図はリストサンプルの例です。下記にそれぞれのサンプルのプログラムを書きます。チェックリストの場合、チェック状態がビットで返ってくるので、ビット処理のところが参考になるかもしれません。詳しくはカテゴリー[item]を見てください。

------------------------------------------
--list
------------------------------------------
--関数宣言--------------------------------
main={}         --mainメソッド
printscrl={}    --スクロールするテキスト表示
listsample={}   --リストサンプル
radiosample={}  --ラジオボタンサンプル
checksample={}  --チェックボタンサンプル

--グローバル変数宣言----------------------
Select = { "みかん","たちうお","うめ","かき","めはりずし","しょうゆ","びんちょうたん","山本商店" }

--画面サイズ取得
Gwide, Gheight = canvas.getviewSize()
LuaridaPath = system.getCardMnt().."/luarida"  --luaファイルを保存しているPath
------------------------------------------
mt={}
mt.__newindex=function(mtt,mtn,mtv)
 dialog( "Error Message", "宣言していない変数 "..mtn.." に値を入れようとしています", 0 )
 toast("画面タッチで実行を続けます", 1)
 touch(3)
end
mt.__index=function(mtt,mtn)
 dialog( "Error Message", "変数 "..mtn.." は宣言されていません", 0 )
 toast("画面タッチで実行を続けます", 1)
 touch(3)
end
setmetatable(_G,mt)
--------以下が実プログラム----------------
------------------------------------------
--スクロールするテキスト表示
------------------------------------------
function printscrl( str, fontsize, fcolor, bcolor )
local sc
 --一度、見えないところにテキストを書いて、改行数を求める
 sc = canvas.drawTextBox( str, 0, Gheight+1, fontsize, fcolor, Gwide )
 --画面の絵をワークエリアに取り込みます
 canvas.getg( 0, fontsize*sc, Gwide-1, Gheight-1, 0, fontsize*sc, Gwide-1, Gheight-1 )
 --取り込んだ画面をスクロールさせて描きます
 canvas.putg( 0, 0, Gwide-1, Gheight-fontsize*sc-1, 0, fontsize*sc, Gwide-1, Gheight-1 )
 --書き出す部分をバックカラーで塗り潰します
 canvas.drawRect(  0, Gheight-fontsize*sc-1, Gwide, Gheight, bcolor, 1 )
 --スクロールしたところにテキストを書きます
 canvas.drawTextBox( str, 0, Gheight-fontsize*sc, fontsize, fcolor, Gwide )
end
------------------------------------------
--チェックボタンサンプル
------------------------------------------
function checksample()
local c1,c2,c3,c4
local g = "あなたは、"
local f = 0
local t
local i
local blue = color(0,0,255)
local red = color(255,0,0)
local green = color(0,255,0)

 item.clear()
 for i=1,#Select-1 do
   item.add( Select[i], 0 )
 end
 item.add( Select[#Select], 1 )

 c1,c2,c3,c4,t = item.check("好きなものにチェックしてください")

 if( t==0 )then
   printscrl( "キャンセルしましたね。", 30, red, color(255,255,255) )
   toast( "画面タッチ待ちです", 0 )
   touch(3)
   return
 elseif( c1==0 )then
   printscrl( "何も好きなものが無いのですね。", 30, red, color(255,255,255) )
   touch(3)
   return
 end
	
 for i=1,15 do
   if( math.fmod(math.floor(c1/math.pow(2,16-i)),2)==1 )then
     if( f==0 )then
       f = 1
     else
       g = g.."と"
     end
     g = g..Select[i]
   end
 end
 printscrl( g.."が好きですね。", 30, color(0,0,0), color(255,255,255) )
 toast( "画面タッチ待ちです", 0 )
 touch(3)
end
------------------------------------------
--ラジオボタンサンプル
------------------------------------------
function radiosample()
local i
local t
local blue = color(0,0,255)
local red = color(255,0,0)

 item.clear()
 for i=1, #Select do
   item.add( Select[i], 0 )
 end
 t = item.radio( "好きなものを選んでください", 1 )

 if( t==0 )then
   printscrl( "好きなものが無かったですか。", 30, red, color(255,255,255) )
 else
   printscrl( "あなたは、"..Select[t].."が好きですね。", 30, blue, color(255,255,255) )
 end
 toast( "画面タッチ待ちです", 0 )
 touch(3)
end
------------------------------------------
--リストサンプル
------------------------------------------
function listsample()
local i
local t
local green = color(0,255,0)
local red = color(255,0,0)

 item.clear()
 for i=1, #Select do
   item.add( Select[i], 0 )
 end
 t = item.list( "好きなものを選んでください" )
	
 if( t==0 )then
   printscrl( "好きなものが無かったですか。", 30, red, color(255,255,255) )
 else
   printscrl( "あなたは、"..Select[t].."が好きですね。", 30, green, color(255,255,255) )
 end
 toast( "画面タッチ待ちです", 0 )
 touch(3)
end
------------------------------------------
--メインプログラム
------------------------------------------
function main()
local siro = color(255,255,255)

 --背景を白にする
 canvas.drawCls( siro )

 while(true)do
   item.clear()
   item.add("リストサンプル", 0 )
   item.add("ラジオボタンサンプル", 0 )
   item.add("チェックリストサンプル", 0 )
   item.add("サンプルデモの終了", 0 )
   local a = item.list( "テストするサンプルを選んでください" )
   if( a==4 )then
     toast( "リストサンプルを終了します", 0 )
     break
   elseif( a==1 )then
     listsample()
   elseif( a==2 )then
     radiosample()
   elseif( a==3 )then
     checksample()
   end
 end
end
main()
system.exit()

以上です。