ボタンを作る関数とその応用について

投稿者:            mini mosmoss 投稿日:2016/07/12 19:34

cfm_さんのボタンを作る関数を使って
「cpu's box」「Carp swimming」「ひまなビール屋」
を作ってみて覚えたことを書き出しておく
よくわかってないこともあるんだけど応用した例も残しておく

書いてあること

ボタンを作る関数が便利なところ

ボタンを作る関数使用上の注意

ボタンを作る関数のアレンジ

1、ボタンを作る時にボタン画像の回転角度を指定する
2、カーソルがボタン上にある時に画像を変える
3、ボタン情報を利用した当たり判定


ボタンを作る関数が便利なところ


1.ボタン画像、ボタンを作りたい座標、ボタンの大きさを設定するだけでボタンを作れる


2.「ボタン画像をなにも設定しなくても」ボタンが作れる(透明ボタン)


・脱出ゲームなどを作りやすいと思う
・また後述のようにボタン画像をたくさん登録できない&表示ができないときに
 あらかじめ複数のボタンが描かれた基盤絵を一枚用意すれば
 この透明ボタンでなんとかすることができる(Carpの背景色設定基盤はこの方法)
・またボタン画像をアニメーションさせたり、条件に応じて画像を変化させたい時にも
 通常のスプライト画像に重ねて透明ボタンを設置するという方法で実現できる
 (boxの箱を選ぶ時の演出はこの方法)

3.ボタンを押してる時と押してないときで別の画像を表示できる(同じ画像を表示することも)


4.ボタンを作る時にそのボタンのID(index)を「数字で」自由に指定して設定できる


 ボタンを文字列や作成順でなく指定した数字で呼び分けることで
 スクリプト上都合がいいことが多い

5.指定したIDのボタンが押されてるかどうかの判定を短くかける


 if button_get(index)
 #ここにindex番のボタンが押されてる時の処理を書く
 end
 これだけで、そのボタンが押されてる時に何が起るかを設定できる

6.クリックした時に「一度だけ」trueを返す


 メイン処理の中でいちいちフラグ操作をしなくていい


ボタンを作る関数使用上の注意



1.複数のボタン画像を一枚のスプライトで作ることができない


  例:10種類のボタンを作り、全てボタン画像を変え、押離の二枚用意する場合、
  20枚の画像の登録が必要になる(1枚のスプライトで済ませられない)
  →ただこれについては関数の改造でなんとかなるかもしれない

2.透明じゃないボタンを作る場合、安定して一度に表示できる数に限りがある


 例:「Carp swimming」では8枚の蓮ボタンを
    部分ループを使って一度に表示しても障りはなかった
   「ひまなビール屋」では40個のボタンを
    部分ループを使って一度に表示することは安定性に欠けたため
    図鑑機能はひとまずspeak文を使うことになった


3.ボタンを消す関数で消されるのはボタンのスプライト画像のみ


 ボタンの領域はどうやら残るので、delete_button(index)のちに
 画面外にbutton_add(index)してボタンID情報の上書きをするという手当が必要

  これをしないと次にそのIDでボタンをつくるまで、
  なにもないように見えるところをクリックしてもボタンフラグが立つ(透明ボタン化する)

  例:「Carp swimming」で花にさわらずに場面転換したあと
    その花の場所に行くと、花をさわった時の反応がでる
    この見えない花ボタンは次に花ボタンが作成されるまで残る
  例:「cpu's box」でボタンが消えたあとにその場所を押すとボタンが出現し
    以降消えなくなるのはこの癖のため


4.テキストとの併用は注意しながら


 複数のボタン画像を一枚のスプライトですませられないなら、テキストを使えば良いじゃない、
 ボタンの説明をボタンの上に重ねて書いたり、隣に書いたりしたい、という時の注意点をまとめる
 ブラウザや環境のちがいによってフォントの大きさ文字の高さ、スペースの横幅などに影響がでる

 1、テキストボックスは想定する領域の2倍以上縦横に広く作る
 2、テキストの冒頭にスペースで余白を作らない、改行で高さを調節しない
   テキストボックスの位置で表示位置を調整する
   また複数のボタンをひとつのテキストボックスですまさず
   ボタンごとにテキストボックスを作成する(面倒)
 3、これでもずれることがあるので、そもそもフォントのずれが致命的となるように設計しない



ボタンを作る関数のアレンジ


ボタンを作る関数は次の7部からなる

1、キー入力を一行で取得する関数
2、ボタンを作る関数内で使う変数の配列をあらかじめ作っておく関数 button_start()
3、引数の情報をもとにボタンを実際に作る関数 button_add
  この中には2で作っておいた配列に引数で得られるボタン情報を入れるパートと
  引数の情報をもとにボタン画像を描画するパートがある
4、ボタンとカーソルの関係を求めて処理を決める関数 button_get(index)
  キー入力を一行で取得する関数を使い、
  カーソルの位置を求めるパート
  クリックしているかいないかを求めるパート
  クリックしている時に、クリックしている時用の画像に差し替え、返り値にtrueを込めるパート
  クリックをやめた時に、クリックしていない時用の画像に差し替え、返り値にfalseを込めるパートがある
5、ボタン番号が入った配列を取得する関数
6、ボタン番号を指定してボタンを削除する関数
7、ボタンを全て削除する関数

ボタンを作る関数群の中で何か新しい変数や引数を使いたい場合には
2のbutton_start()の中であらかじめ新しい変数を設定しておかなくてはいけない
また3のボタン生成の時に、その変数に何か入れておく必要もある
ボタン描画に関わるアレンジの場合は、3で一回4で二回描画のタイミングがある

4のbutton_get(index)の返り値はtrueかfalseが返るのだが、関数内を見るとreturn b==2となっている
これはgetVariable("btn_push")[index]がtrueだけどクリックしてない、すなわち押下中から
クリックを離した瞬間の一回のみb==2になる、つまりtrueを返す、ということ(なのかも、よくわかってない)
このへんをさわる時には注意

1、ボタンを作る時にボタン画像の回転角度を指定する(Carp swimming)


Carp swimmingでは蓮画像をボタンとして表示しています
蓮の切れ込みの部分がぜんぶ同じ箇所にあると不自然という問題があり
ボタン画像をランダムで回転させています

1、ボタンを作る関数群本編の前に
cfm_さんの「スプライトを中心指定して回転させる関数」を記述
2、button_start()関数の中に1カ所追加
3、button_add()関数の引数をひとつ追加
4、button_add()関数の中に2カ所追加
5、button_get(index)関数の中に2カ所追加

仕組みは、ボタンを描くタイミングでその都度指定した角度に回転させてます
追加した部分にコメントをつけてます
###ボタンを作る関数にボタンの回転角度も追加###

###ボタンを作る関数群の前にキー入力を一行で取得する関数を記述###
###ここでは省きますので使う人は検索してここに貼ってください###

###ボタンを作る関数群の前に中心指定回転関数を記述###

#スプライトを中心を指定して回転させる(画像ID,中心座標X,中心座標Y,画像幅,画像高さ,角度(ラジアン),拡大率X,拡大率Y)
#この関数はsetSpritePositionやsetSpriteScaleの機能を含んでいるので、それらを別に使用はしないでください。
def setSpriteRotation2(img,x,y,w,h,angle,scalex,scaley)
  setSpriteRotation(img,angle)
  w2=w*scalex
  h2=h*scaley
  a=sqrt(w2*w2+h2*h2)/2
  ce=(atan2(h2,w2)+angle)%6.28319
  setSpritePosition(img,x-a*cos(ce),y-a*sin(ce))
  setSpriteScale(img,scalex,scaley)
end

#画面上にボタンを作る関数本編#
#スクリプトの最初に記述が必要。
def button_start()
  setCanvasVisible(true)
  setVariable("btn_ctrl",createArray())
  setVariable("btn_img0",createArray())
  setVariable("btn_img1",createArray())
  setVariable("btn_imgnum0",createArray())
  setVariable("btn_imgnum1",createArray())
  setVariable("btn_x0",createArray())
  setVariable("btn_y0",createArray())
  setVariable("btn_x1",createArray())
  setVariable("btn_y1",createArray())
  setVariable("btn_z",createArray())
  setVariable("btn_r",createArray())   ##追加した部分##
  setVariable("btn_imgw",createArray())
  setVariable("btn_imgh",createArray())
  setVariable("btn_push",createArray())
end

#ボタンを作成(ボタン番号,通常時画像,押下中画像,画像幅,画像高さ,左上X,左上Y,右下X,右下Y,zオーダー,回転角度)
#img0,img1に0を入れると、それぞれ画像を表示しません
#2つの座標によって、自動で画像を拡大縮小します。
#2つの画像の幅と高さは同じにしてください。
#indexは-1以外の数値。
def button_add(index,img0,img1,imgw,imgh,x0,y0,x1,y1,ZOrder,r) ##最後の引数rを追加##
  getVariable("btn_imgw")[index]=imgw
  getVariable("btn_imgh")[index]=imgh
  getVariable("btn_imgnum0")[index]=img0
  getVariable("btn_imgnum1")[index]=img1
  getVariable("btn_x0")[index]=x0
  getVariable("btn_y0")[index]=y0
  getVariable("btn_x1")[index]=x1
  getVariable("btn_y1")[index]=y1
  getVariable("btn_z")[index]=ZOrder
  getVariable("btn_r")[index]=r    ##追加した部分##
  pushArray(getVariable("btn_ctrl"), index)
  if img0==0
    getVariable("btn_img0")[index]=0
  else
    getVariable("btn_img0")[index]=createSprite(img0)
    setSpriteRect(getVariable("btn_img0")[index],0,0,getVariable("btn_imgw")[index],getVariable("btn_imgh")[index],0,0,getVariable("btn_x1")[index]-getVariable("btn_x0")[index]+1,getVariable("btn_y1")[index]-getVariable("btn_y0")[index]+1)
    setSpritePosition(getVariable("btn_img0")[index],getVariable("btn_x0")[index],getVariable("btn_y0")[index])
    setSpriteZOrder(getVariable("btn_img0")[index],getVariable("btn_z")[index])
##追加した部分ここから##
    setSpriteRotation2(getVariable("btn_img0")[index], getVariable("btn_x0")[index] + (getVariable("btn_x1")[index] - getVariable("btn_x0")[index])/2 ,getVariable("btn_y0")[index] + (getVariable("btn_y1")[index] - getVariable("btn_y0")[index])/2,(getVariable("btn_x1")[index] - getVariable("btn_x0")[index]), (getVariable("btn_y1")[index] - getVariable("btn_y0")[index]),  getVariable("btn_r")[index],1.0,1.0)
##追加した部分ここまで##
    drawCanvas()
  end
  getVariable("btn_img1")[index]=0
end
#ボタンがクリックされたらTrueを返す
def button_get(index)
  b=0
  x=input_getmousex()
  if getVariable("btn_x0")[index]<x&&x<getVariable("btn_x1")[index]
    y=input_getmousey()
    if getVariable("btn_y0")[index]<y&&y<getVariable("btn_y1")[index]
      if input_getmouse("HOLD")
        if !getVariable("btn_push")[index]
          if getVariable("btn_img0")[index]!=0
            deleteSprite(getVariable("btn_img0")[index])
            getVariable("btn_img0")[index]=0
          end
          if getVariable("btn_imgnum1")[index]!=0
            getVariable("btn_img1")[index]=createSprite(getVariable("btn_imgnum1")[index])
            setSpriteRect(getVariable("btn_img1")[index],0,0,getVariable("btn_imgw")[index],getVariable("btn_imgh")[index],0,0,getVariable("btn_x1")[index]-getVariable("btn_x0")[index]+1,getVariable("btn_y1")[index]-getVariable("btn_y0")[index]+1)
            setSpritePosition(getVariable("btn_img1")[index],getVariable("btn_x0")[index],getVariable("btn_y0")[index])
            setSpriteZOrder(getVariable("btn_img1")[index],getVariable("btn_z")[index])
##追加した部分ここから##
    setSpriteRotation2(getVariable("btn_img1")[index], getVariable("btn_x0")[index] + (getVariable("btn_x1")[index] - getVariable("btn_x0")[index])/2 ,getVariable("btn_y0")[index] + (getVariable("btn_y1")[index] - getVariable("btn_y0")[index])/2,(getVariable("btn_x1")[index] - getVariable("btn_x0")[index]), (getVariable("btn_y1")[index] - getVariable("btn_y0")[index]),  getVariable("btn_r")[index],1.0,1.0)
##追加した部分ここまで##
          end
          drawCanvas()
          getVariable("btn_push")[index]=true
        end
      elsif getVariable("btn_push")[index]#離されたとき
        b=2
      end
    elsif getVariable("btn_push")[index]
      b=1
    end
  elsif getVariable("btn_push")[index]
    b=1
  end
  if b==1||b==2
    if getVariable("btn_img1")[index]!=0
      deleteSprite(getVariable("btn_img1")[index])
      getVariable("btn_img1")[index]=0
    end
    if getVariable("btn_imgnum0")[index]!=0
      getVariable("btn_img0")[index]=createSprite(getVariable("btn_imgnum0")[index])
      setSpriteRect(getVariable("btn_img0")[index],0,0,getVariable("btn_imgw")[index],getVariable("btn_imgh")[index],0,0,getVariable("btn_x1")[index]-getVariable("btn_x0")[index]+1,getVariable("btn_y1")[index]-getVariable("btn_y0")[index]+1)
      setSpritePosition(getVariable("btn_img0")[index],getVariable("btn_x0")[index],getVariable("btn_y0")[index])
      setSpriteZOrder(getVariable("btn_img0")[index],getVariable("btn_z")[index])
##追加した部分ここから##
    setSpriteRotation2(getVariable("btn_img0")[index], getVariable("btn_x0")[index] + (getVariable("btn_x1")[index] - getVariable("btn_x0")[index])/2 ,getVariable("btn_y0")[index] + (getVariable("btn_y1")[index] - getVariable("btn_y0")[index])/2,(getVariable("btn_x1")[index] - getVariable("btn_x0")[index]), (getVariable("btn_y1")[index] - getVariable("btn_y0")[index]),  getVariable("btn_r")[index],1.0,1.0)
##追加した部分ここまで##
    end
    drawCanvas()
    getVariable("btn_push")[index]=false
  end
  return b==2
end
#すべてのボタンの番号が入った配列を取得
def button_getarray()
  a=createArray()
  len=getArrayLength(getVariable("btn_ctrl"))
  j=0
  i=0
  while i<len
    if getVariable("btn_ctrl")[i]!=-1
      a[j]=getVariable("btn_ctrl")[i]
      j=j+1
    end
    i=i+1
  end
  return a
end
def button_delete(index)
  i=getArrayLength(getVariable("btn_ctrl"))-1
  while -1<i
    if getVariable("btn_ctrl")[i]==index
      if getVariable("btn_img0")[index]!=0
        deleteSprite(getVariable("btn_img0")[index])
      elsif getVariable("btn_img1")[index]!=0
        deleteSprite(getVariable("btn_img1")[index])
      end
      drawCanvas()
      getVariable("btn_ctrl")[i]=-1
      return true
    end
    i=i-1
  end
  return false
end
def button_alldelete()
  i=getArrayLength(getVariable("btn_ctrl"))-1
  while -1<i
    if getVariable("btn_ctrl")[i]!=-1
      if getVariable("btn_img0")[getVariable("btn_ctrl")[i]]!=0
        deleteSprite(getVariable("btn_img0")[getVariable("btn_ctrl")[i]])
      elsif getVariable("btn_img1")[getVariable("btn_ctrl")[i]]!=0
        deleteSprite(getVariable("btn_img1")[getVariable("btn_ctrl")[i]])
      end
      getVariable("btn_ctrl")[i]=-1
    end
    i=i-1
  end
  drawCanvas()
end


2、ボタンを押した時ではなく、カーソルがボタン上にある時に画像を変える(ひまなビール屋)


ボタンを回転させるやつよりも、「何カ所追加した」と数えにくいので、
コメントが追加されてるあたりに変更箇所があると思ってください

コメントの内容について
通常時=ボタン灰色=img0
カーソルがボタンの上にある時=ボタン白色=img1
という設定です

仕組みはhoverという変数を作って今ボタンがhover中なのかちがうのかを管理
(カーソルがボタンの上にある時だけhover中)
状態に合わせた画像を表示しています

###ボタンを作る関数でカーソルがボタンの上にある時にボタン画像を変えるアレンジ###

###ボタンを作る関数群の前にキー入力を一行で取得する関数を記述###
###ここでは省きますので使う人は検索してここに貼ってください###

#ボタンを作る関数
#スクリプトの最初に記述が必要。
def button_start()
  setCanvasVisible(true)
  setVariable("btn_ctrl",createArray())
  setVariable("btn_img0",createArray())
  setVariable("btn_img1",createArray())
  setVariable("btn_imgnum0",createArray())
  setVariable("btn_imgnum1",createArray())
  setVariable("btn_x0",createArray())
  setVariable("btn_y0",createArray())
  setVariable("btn_x1",createArray())
  setVariable("btn_y1",createArray())
  setVariable("btn_z",createArray())
  setVariable("hover",createArray()) ##追加分
  setVariable("btn_imgw",createArray())
  setVariable("btn_imgh",createArray())
  setVariable("btn_push",createArray())
end

#ボタンを作成(ボタン番号,通常時画像,選択中画像,画像幅,画像高さ,左上X,左上Y,右下X,右下Y)
#img0,img1に0を入れると、それぞれ画像を表示しません
#2つの座標によって、自動で画像を拡大縮小します。
#2つの画像の幅と高さは同じにしてください。
#indexは-1以外の数値。
def button_add(index,img0,img1,imgw,imgh,x0,y0,x1,y1,ZOrder)
  getVariable("btn_imgw")[index]=imgw
  getVariable("btn_imgh")[index]=imgh
  getVariable("btn_imgnum0")[index]=img0
  getVariable("btn_imgnum1")[index]=img1
  getVariable("btn_x0")[index]=x0
  getVariable("btn_y0")[index]=y0
  getVariable("btn_x1")[index]=x1
  getVariable("btn_y1")[index]=y1
  getVariable("btn_z")[index]=ZOrder
  getVariable("hover")[index]=false ##追加分
  pushArray(getVariable("btn_ctrl"), index)
  if img0==0
    getVariable("btn_img0")[index]=0
  else
    getVariable("btn_img0")[index]=createSprite(img0)
    setSpriteRect(getVariable("btn_img0")[index],0,0,getVariable("btn_imgw")[index],getVariable("btn_imgh")[index],0,0,getVariable("btn_x1")[index]-getVariable("btn_x0")[index]+1,getVariable("btn_y1")[index]-getVariable("btn_y0")[index]+1)
    setSpritePosition(getVariable("btn_img0")[index],getVariable("btn_x0")[index],getVariable("btn_y0")[index])
    setSpriteZOrder(getVariable("btn_img0")[index],getVariable("btn_z")[index])
    drawCanvas()
  end
  getVariable("btn_img1")[index]=0
end
#ボタンがクリックされたらTrueを返す
def button_get(index)
  b=0
  x=input_getmousex()
  if getVariable("btn_x0")[index]<x&&x<getVariable("btn_x1")[index]
    y=input_getmousey()
    if getVariable("btn_y0")[index]<y&&y<getVariable("btn_y1")[index]     
    #カーソルがボタンの上にあるとき
       if !getVariable("hover")[index] #ボタン画像が白でない(灰色の)とき
          if getVariable("btn_img0")[index]!=0
            deleteSprite(getVariable("btn_img0")[index])
            getVariable("btn_img0")[index]=0
          end
          if getVariable("btn_imgnum1")[index]!=0
            getVariable("btn_img1")[index]=createSprite(getVariable("btn_imgnum1")[index])
            setSpriteRect(getVariable("btn_img1")[index],0,0,getVariable("btn_imgw")[index],getVariable("btn_imgh")[index],0,0,getVariable("btn_x1")[index]-getVariable("btn_x0")[index]+1,getVariable("btn_y1")[index]-getVariable("btn_y0")[index]+1)
            setSpritePosition(getVariable("btn_img1")[index],getVariable("btn_x0")[index],getVariable("btn_y0")[index])
            setSpriteZOrder(getVariable("btn_img1")[index],getVariable("btn_z")[index])
          end #スプライト設定のエンド
          drawCanvas()
      getVariable("hover")[index] =true #ボタン画像が白になってる状態
      else
      end #!getVariable("hover")[index]のend

      if input_getmouse("HOLD")
        if !getVariable("btn_push")[index]
          #押下中の処理
          getVariable("btn_push")[index]=true
        end #!getVariable("btn_push")[index]のエンド
      elsif getVariable("btn_push")[index]#離されたとき
        b=2
      end #input_getmouse("HOLD")のエンド
      else
      b=1
    end #yのエンド
    else
    b=1
  end  #xのエンド
  if b==1||b==2 #カーソルがボタンの上にないとき、または押下中の状態から押下をやめた瞬間

    if getVariable("hover")[index] #ボタン画像が白になってる場合
    if getVariable("btn_img1")[index]!=0
      deleteSprite(getVariable("btn_img1")[index])
      getVariable("btn_img1")[index]=0
    end
    if getVariable("btn_imgnum0")[index]!=0
      getVariable("btn_img0")[index]=createSprite(getVariable("btn_imgnum0")[index])
      setSpriteRect(getVariable("btn_img0")[index],0,0,getVariable("btn_imgw")[index],getVariable("btn_imgh")[index],0,0,getVariable("btn_x1")[index]-getVariable("btn_x0")[index]+1,getVariable("btn_y1")[index]-getVariable("btn_y0")[index]+1)
      setSpritePosition(getVariable("btn_img0")[index],getVariable("btn_x0")[index],getVariable("btn_y0")[index])
      setSpriteZOrder(getVariable("btn_img0")[index],getVariable("btn_z")[index])
    end
       getVariable("hover")[index]=false #ボタン画像を灰色にした状態
    end #getVariable("hover")[index] のend
    drawCanvas()
    getVariable("btn_push")[index]=false
  end
  return b==2
end
#すべてのボタンの番号が入った配列を取得
def button_getarray()
  a=createArray()
  len=getArrayLength(getVariable("btn_ctrl"))
  j=0
  i=0
  while i<len
    if getVariable("btn_ctrl")[i]!=-1
      a[j]=getVariable("btn_ctrl")[i]
      j=j+1
    end
    i=i+1
  end
  return a
end
def button_delete(index)
  i=getArrayLength(getVariable("btn_ctrl"))-1
  while -1<i
    if getVariable("btn_ctrl")[i]==index
      if getVariable("btn_img0")[index]!=0
        deleteSprite(getVariable("btn_img0")[index])
      elsif getVariable("btn_img1")[index]!=0
        deleteSprite(getVariable("btn_img1")[index])
      end
      drawCanvas()
      getVariable("btn_ctrl")[i]=-1
      return true
    end
    i=i-1
  end
  return false
end
def button_alldelete()
  i=getArrayLength(getVariable("btn_ctrl"))-1
  while -1<i
    if getVariable("btn_ctrl")[i]!=-1
      if getVariable("btn_img0")[getVariable("btn_ctrl")[i]]!=0
        deleteSprite(getVariable("btn_img0")[getVariable("btn_ctrl")[i]])
      elsif getVariable("btn_img1")[getVariable("btn_ctrl")[i]]!=0
        deleteSprite(getVariable("btn_img1")[getVariable("btn_ctrl")[i]])
      end
      getVariable("btn_ctrl")[i]=-1
    end
    i=i-1
  end
  drawCanvas()
end


3、ボタン情報を利用した当たり判定


Carpswimmingでは蓮画像をボタンとして作っています
ボタンを作る時に設定した画像の矩形情報を、そのまま当たり判定に使おうという趣旨です

準備として、上の二例と同じ要領で、変数btn_atariをあらかじめ用意しておきます
これは、当たったら一度だけ得点を返す、という処理のために使います
#ボタンに当たったら、初めて当たった時だけ得点を返す(btn_atariがtrueに)
#第一引数は対象のボタンID,第二・第三引数はボタン領域内にあるか調べる座標点
def button_atari(index, x, y)
  if getVariable("btn_x0")[index]<x&&x<getVariable("btn_x1")[index] &&              getVariable("btn_y0")[index]<y&&y<getVariable("btn_y1")[index] &&           getVariable("btn_atari")[index]==false
          getVariable("btn_atari")[index]=true
           if index < 4
           point = 10  #ボタンID0~3に当たってる場合は10点を返す
           else
           point = 1  #ボタンID0~3以外に当たってる場合は1点を返す
           end
    return point
 else
 end
end

Carpswimmingでは、調べる座標点を鯉の画像の中心点にしています
画像回転によるぶれがないことと、蓮の下をくぐったら得点という演出のためです

コメントする

コメントするには、ログインする必要があります。

コメント一覧

コメントはありません。