【プチコン4講座】各シーンのBGMとタイトル画面の実装

プチコン4

プチコン4 シューティングゲーム タイトル画面

こんにちは。継続の錬金術士なおキーヌです。

ブログ毎日更新は220日目になります。

第12回「【プチコン4講座】スコア一定数値で難易度調整」にてスコアに応じて難易度を上昇させるようにしました。

本講座も残りもあと少しです。

現状のままでは少し寂しいので各シーンでBGMを流すようにしてみましょう。

ついでにタイトル画面の実装も行いよりゲームらしく完成の方向にもっていきます。

それではプチコン4でSTG作りその第13回目始めましょう。

  1. BGMを鳴らしてみよう
  2. タイトル用のシーンを実装しよう
  3. シューティングゲーム作り講座第13回まとめ

BGMを鳴らしてみよう

ねぇトモくん。ゲームに音楽って流せないの?

そういえば作るのに夢中でBGMの存在を忘れていたぜ。

作ってる時に流すとプログラムを止めても流れたままで自分でBGMSTOPを打ち込まなきゃ止まらないから今まで使ってなかったんだ。折角だし何かBGMを付けてみようか。

BGMを選ぶ

キーボードの「F9」かJoyConのマイナスボタンを押して「Ctrl」を押してスマイルツール1を起動してね。

効果音の一覧が出てきたぜ。

Rを押すと次の項目へ行けるんだ。1回押したらBGMのリストになるよ。プログラミングには影響が無いからBGMは自分の好きなものを選んでいいよ。ボクは以下のようにしてみたよ。

  • タイトル画面:13
  • Lv0~1:2
  • Lv2~3:31
  • LvMaX:41
  • ゲームオーバー:4

それじゃあまずはゲーム中のBGMを付けてみようか。BGMの再生は1回だけでいいよ。ループの中で再生しちゃうとループごとに曲の最初になって何も聞こえないから注意してね。

こんなのはどうかしら?フラグを1つ用意して、ONの時は処理を実行せず、シーンが切り替わるときにそのフラグをOFFにしてシーンに応じてBGMを再生するの。そしてフラグをONにすればループの中に入れておいても大丈夫じゃない?

いいね。それ採用。マユミちゃん段々とプログラマーらしくなってきたね!

でしょでしょ!

シーンがどれかはシーンフラグで管理してるから分岐はそれを使えば完璧だね。早速コードを書いてみようか。

G_BgmFlag = #FALSE

' ループ開始
loop
  ' コントローラーはどのシーンでも動くようにする
  D_Controller
  ' BGM監視
  D_BgmSelect

  ~~~省略~~~
endloop


' BGMセレクタ
'───────────────────────────────
def D_BgmSelect
  if G_BgmFlag == #FALSE then
    case G_SceneFlag
      when 0
        BGMPLAY 13
      when 1
        if G_PlayerStatus[4] >= 0 && G_PlayerStatus[4] <= 1 then
          BGMPLAY 2
        elseif G_PlayerStatus[4] >= 2 && if G_PlayerStatus[4] <= 3 then
          BGMPLAY 31
        else
          BGMPLAY 41
        endif
      when 2
        BGMSTOP
      when 3
        BGMPLAY 4
    endcase

    G_BgmFlag = #TRUE
  endif
end

#FALSEと#TRUEってなんだこれ?

Bool値っていうんだけど、日本語なら真偽値。機械って0と1しか認識できないから0がOFFで1がON……っていうのは二進数の勉強の時にやったでしょ?そして#が付いているのは定数で中に数字や文字列が入っているんだ。FALSEは0、TRUEは1が入っているよ。

1と0じゃだめなのか?

他のプログラミング言語だとTRUEとFALSEって普通に使えるんだけどプチコンの場合は用意されていないみたいでどうやら定数を使って実装しているみたい。中身は結局「有るか無いか」だから1を有る。0を無いとみ立てているんだ。それに0とか1にしちゃうと必ずしも0がOFF出ない可能性があるんだ。

シーンのフラグなんかがそうよね?0はタイトルシーンであって別に無しってわけじゃないし。

た、たしかに……#FALSEだと0より無しっていう風にとらえやすいかもしれねぇ……

確かに0か1かの方が1文字で済むね。でも他の人が見た時何かわからないから出来る限りパッと見で意味の分かるものが最適なんだ。

後はシーン切り替えの時にBGMのフラグをOFFに出来れば完璧そうね。

毎回BGMSTOPとシーン切り替えを書くのが面倒だから引数ありの1つの命令にしてしまおうか。

' プレイヤー衝突チェック
'───────────────────────────────
def D_PlayerColCheck
  var isHit = SPHITSP(G_SpvManageNo[0], G_SpvManageNo[3], G_SpvManageNo[4])

  if isHit != -1 && SPVAR(isHit,"IS_HIT") == 0 then
    BEEP 91, -300
    DEC G_PlayerStatus[0]

    ' ライフが0になったら
    if G_PlayerStatus[0] <= 0 then
      ' ゲームオーバーシーンへいく
      D_SceneChange 3
    endif

    SPVAR isHit, "IS_HIT", 1
  endif
end

' スコアの更新
'───────────────────────────────
def D_ScoreUpdate
  D_ScoreAdd 0.1

  ' レベルアップ監視
  if G_PlayerStatus[2] > G_GameLvUp[G_PlayerStatus[4]] then
    INC G_PlayerStatus[4]
    D_SceneChange 1
  endif

  GFILL 300,16,400,32,RGB(0,0,0,0)
  GPUTCHR 300,16, STR$(FLOOR(G_PlayerStatus[2])),8,RGB(255,255,255),1
end

' ゲームリセット
'───────────────────────────────
def D_GameReset
  GCLS
  D_SpriteInitialize
  D_PlayerStatusInitialize
  D_ScoreInitialize
  D_SceneChange 1
end

' シーン切り替え
'───────────────────────────────
def D_SceneChange A_Scene
  BGMSTOP
  G_BgmFlag = #FALSE
  G_SceneFlag = A_Scene
endif

今のところ「ゲームオーバー」「Lvアップ」「リスタート」ぐらいしかシーンの切り替えが無いからそこのシーンフラグチェンジを置き換えたよ。

なるほど、レベルアップした時も呼び出して同じシーンだけどレベルによってBGMを変更しているのか!

タイトル用のシーンを実装しよう

本来はタイトル画面を用意したい所なんだけど絵を用意するのが面倒だったしプログラミングにはあまり関係なくなっちゃうから、プログラムをスタートしてから何かボタンが押されるまではゲームを開始しないようにするシーンを作るよ。

トモカズのそういう正直な所、好きだぜ。

まぁ、即席で絵を描くのは難しいわよね。

多重スクロールとか使って車がかっこよく走っているシーンをタイトル画面にしたかったんだけどまた今度だね。それじゃあタイトルシーンを作るよ。開始シーンを0にしておいてね。

' シーン用変数
G_SceneFlag = 0

' タイトル点滅用フラグ
G_FlashFlag = #FALSE

' ループ開始
loop
  ' コントローラーはどのシーンでも動くようにする
  D_Controller
  ' BGM監視
  D_BgmSelect

  ' フラグで処理を切り分ける
  case G_SceneFlag
    ' タイトルシーン
    when 0
      D_GameTitle
      ~~~省略~~~
  endcase

  ' 垂直同期
  VSYNC
endloop

' タイトルシーン
'───────────────────────────────
def D_GameTitle
  var frame = MAINCNT()

  ' プチコン4を起動してからの経過時間を元に30で割り切れたらフラグを切り替え
  if (frame MOD 30) == 0 then
    G_FlashFlag = !G_FlashFlag
  endif

  ' 文字をフラグの状態により点滅させる
  if G_FlashFlag == #FALSE
    GPUTCHR  40,100,"PLEASE PRESS  BUTTON",16,RGB(255,255,255),1
    GPUTCHR  40+(16*13+8),100,"A",16,RGB(255,0,0),1
  else
    GFILL 40,100,400,116, RGB(0,0,0,0,)
  endif
end

これで起動するとタイトルシーンで文字が点滅するよ。

なんかBGMも入れるとゲームぽさがめちゃくちゃ増したぜ!

後はAボタンを押してゲーム開始の処理を入れたらいいわね。

最後にAボタン処理を作ろうか。

' コントローラー
'───────────────────────────────
def D_Controller
  ' 0番目のコントローラー(つまり1コン)の押されているボタンを取得
  VAR B = BUTTON(0)

  ~~~ 省略 ~~~

  ' Aボタン処理
  if (B AND 1 << #B_LRIGHT) != 0 then
    ' ボタンカウント命令に#B_RLEFTを渡す
    D_BtnPressCount #B_LRIGHT
    ' Aボタンのカウントが1であれば
    if G_BtnPressCount[0] == 1 then
    endif
  else
    ' ボタンが離されたらカウントが1以上の時
    if G_BtnPressCount[0] >= 1 then
      ' ボタンカウントを0にする
      G_BtnPressCount[0] = 0
    endif
  endif

  ~~~ 省略 ~~~
end

' ボタンカウント関数
'───────────────────────────────
def D_BtnPressCount A_Button
  ' ボタンカウント分岐
  case A_Button
    ' 渡されたボタンが#B_RRIGHTだったら
    when #B_RRIGHT
      ' ボタンカウント配列の数が256未満かどうか調べる
      if G_BtnPressCount[0] < 256 then 
        ' 条件に一致したら+1する
        INC G_BtnPressCount[0]
      endif
    ~~~ 省略 ~~~

  endcase
end



' タイトルシーン
'───────────────────────────────
def D_GameTitle
  var frame = MAINCNT()

  ' プチコン4を起動してからの経過時間を元に30で割り切れたらフラグを切り替え
  if (frame MOD 30) == 0 then
    G_FlashFlag = !G_FlashFlag
  endif

  ' 文字をフラグの状態により点滅させる
  if G_FlashFlag == #FALSE
    GPUTCHR  40,100,"PLEASE PRESS  BUTTON",16,RGB(255,255,255),1
    GPUTCHR  40+(16*13+8),100,"A",16,RGB(255,0,0),1
  else
    GFILL 40,100,400,116, RGB(0,0,0,0,)
  endif

  if G_BtnPressCount[0] == 1 then
    GFILL 40,100,400,116, RGB(0,0,0,0,)
    D_SceneChange 1
  endif
end

これでゲームとしてはほぼ完璧だね!……ただタイトル画面で十ボタンを押すとプレイヤーの初期値が移動してしまってるバグがあるんだ。Aボタンを押したときにプレイヤーの座標を修正するか、ボタンの制御を行ってみると良いよ。改良点として自分で直せるか試してみてよ!

トモカズは意外と面倒くさがり屋だからな。

そういえば、面倒くさがりはプログラマに向いてるって聞いたことがあるわ。

そうだね……プログラミングを覚えたきっかけの1つでもあるかな。っと、最後にデバッグとしてレベルアップ点数を下げて確認してみようね。

あちゃー……配列の要素数越えちゃったね。まぁ次直そうか。

シューティングゲーム作り講座第13回まとめ

微妙にバグが潜んでいますが、自力で見つけてみて修正してみてください。

私も完全に忘れてた部分もあるのでデバッグしてみてココ直した方がいいんじゃないか?
って点を見つけたら自分で修正してみるとプログラミング力がアップしますよ。

それでは。

' ゲーム初期化
ACLS
' ループ用変数
var G_I
' シーン用変数
G_SceneFlag = 1
' ボタンカウント配列
DIM G_BtnPressCount[4]

' スプライト管理番号まとめ変数
DIM G_SpvManageNo[] = [0,10,14,20,30]

' プレイヤー用状態変数
'   0=> HP, 1=>能力, 2=>現在スコア, 3=>ハイスコア, 4=>ゲームLv
DIM G_PlayerStatus[5] = [2,0,0,0,0]

' レベルアップ基準値
DIM G_GameLvUp[5] = [5000, 15000, 30000, 50000, 100000 ]

' タイトル点滅用フラグ
G_FlashFlag = #FALSE



' ゲームの初期化
D_Initialize


' ループ開始
loop
  ' コントローラーはどのシーンでも動くようにする
  D_Controller
  ' BGM監視
  D_BgmSelect

  ' フラグで処理を切り分ける
  case G_SceneFlag
    ' タイトルシーン
    when 0
      D_GameTitle
    ' メインシーン
    when 1
      D_PlayerMove
      D_PlayerColCheck
      D_PlayerShotMove
      D_ObstacleMove
      D_ScoreUpdate
      D_PlayerLifeUpdate
    ' ポーズ中
    when2
    ' ゲームオーバー
    when3
      D_GameOver

    ' リザルト画面
    when4
  endcase

  ' 垂直同期
  VSYNC
endloop


' ゲーム初期化
'───────────────────────────────
def D_Initialize

  ' マップ描写
  D_MapDraw

  ' スプライト初期化
  D_SpriteInitialize
end

' コントローラー
'───────────────────────────────
def D_Controller
  ' 0番目のコントローラー(つまり1コン)の押されているボタンを取得
  VAR B = BUTTON(0)

  ' 押されているボタンの情報を表示
  if (B AND 1 << #B_LUP) != 0 then
    ' 上を押されたらY座標を減算
    SPVAR 0,"Y", SPVAR(0,"Y")-1
  elseif (B AND 1 << #B_LDOWN) != 0 then
    ' 下を押されたらY座標を加算
    SPVAR 0,"Y", SPVAR(0,"Y")+1
  endif
  if (B AND 1 << #B_LLEFT) != 0 then
    ' 左を押されたらX座標を減算
    SPVAR 0,"X", SPVAR(0,"X")-1
  elseif (B AND 1 << #B_LRIGHT) != 0 then
    ' 右を押されたらX座標を加算
    SPVAR 0,"X", SPVAR(0,"X")+1
  endif

  ' Aボタン処理
  if (B AND 1 << #B_LRIGHT) != 0 then
    ' ボタンカウント命令に#B_RLEFTを渡す
    D_BtnPressCount #B_LRIGHT
    ' Aボタンのカウントが1であれば
    if G_BtnPressCount[0] == 1 then
    endif
  else
    ' ボタンが離されたらカウントが1以上の時
    if G_BtnPressCount[0] >= 1 then
      ' ボタンカウントを0にする
      G_BtnPressCount[0] = 0
    endif
  endif

  ' Yボタン処理
  if (B AND 1 << #B_LREFT) != 0 then
    ' ボタンカウント命令に#B_RLEFTを渡す
    D_BtnPressCount #B_RLEFT
    ' Yボタンのカウントが1であれば
    if G_BtnPressCount[2] == 1 then
      D_PlayerShot
    endif
  else
    ' ボタンが離されたらカウントが1以上の時
    if G_BtnPressCount[2] >= 1 then
      ' ボタンカウントを0にする
      G_BtnPressCount[2] = 0
    endif
  endif

  ' L1ボタン処理
  if (B AND 1 << #B_L1) != 0 then
    ' ボタンカウント命令に#B_L1を渡す
    D_BtnPressCount #B_L1
    ' L1ボタンのカウントが1であれば
    if G_BtnPressCount[3] == 1 then
      if G_SceneFlag == 3 then
        D_GameReset
      endif
    endif
  else
    ' ボタンが離されたらカウントが1以上の時
    if G_BtnPressCount[3] >= 1 then
      ' ボタンカウントを0にする
      G_BtnPressCount[3] = 0
    endif
  endif
end

' ボタンカウント関数
'───────────────────────────────
def D_BtnPressCount A_Button
  ' ボタンカウント分岐
  case A_Button
    ' 渡されたボタンが#B_RRIGHTだったら
    when #B_RRIGHT
      ' ボタンカウント配列の数が256未満かどうか調べる
      if G_BtnPressCount[0] < 256 then 
        ' 条件に一致したら+1する
        INC G_BtnPressCount[0]
      endif
    ' 渡されたボタンが#B_RLEFTだったら
    when #B_RLEFT
      ' ボタンカウント配列の数が256未満かどうか調べる
      if G_BtnPressCount[2] < 256 then 
        ' 条件に一致したら+1する
        INC G_BtnPressCount[2]
      endif
    when #B_L1
      ' ボタンカウント配列の数が256未満かどうか調べる
      if G_BtnPressCount[3] < 256 then 
        ' 条件に一致したら+1する
        INC G_BtnPressCount[3]
      endif
  endcase
end


' スプライトの初期化
'───────────────────────────────
def D_SpriteInitialize
  ' スプライトを定義
  var PID = G_SpvManageNo[0]
  SPSET PID, 352 ' プレイヤー
  SPVAR PID, "X", 0
  SPVAR PID, "Y", 0
  SPCOL PID

  ' ループさせて弾を生成
  for G_I = G_SpvManageNo[1] to G_SpvManageNo[2]
    SPSET G_I, 1322,0 ' 弾は最初からHIDE状態
    D_ShotPosSettings G_I
    SPCOL G_I
  next

  ' ループさせて障害物を生成
  for G_I = G_SpvManageNo[3] to G_SpvManageNo[4]
    SPSET G_I, 262 ' 岩
    D_ObstacleRndPosSettings G_I
    SPCOL G_I, 1
  next
end

' スプライト(プレイヤー)の移動
'───────────────────────────────
def D_PlayerMove
  ' プレイヤーの移動
  SPOPS 0, SPVAR(0,"X"), SPVAR(0,"Y")
end

' マップの描写
'───────────────────────────────
' マップの塗りつぶし描写
def D_MapDraw
  ' 所属レイヤー変更
  TLAYER 0,7
  ' 背景の色味を変更
  TCOLOR 0, &Hdddddd00
  ' 背景の塗りつぶし
  TFILL 0,0,0,24,14,CHR$(&HE8D8)
end

' プレイヤーショット処理
'───────────────────────────────
def D_PlayerShot
  for G_I=G_SpvManageNo[1], to G_SpvManageNo[2]
    ' 弾にショットフラグが立っていなければ
    if SPVAR(G_I,"SHOT_FLAG") == 0 then
      BEEP 10
      ' 表示フラグをONにする
      SPSHOW G_I
      ' 出現フラグをONにする
      SPVAR G_I,"SHOT_FLAG", 1
      ' 弾の座標をプレイヤーの前方に設定する
      SPVAR G_I, "X", SPVAR(0,"X") + 8
      SPVAR G_I, "Y", SPVAR(0,"Y") + 4
      ' ショット命令が1回動いたら無条件でループを抜ける
      break
  next
end

' プレイヤーの弾の移動処理
'───────────────────────────────
def D_PlayerShotMove
  for G_I=G_SpvManageNo[1], to G_SpvManageNo[2]
    ' 弾にショットフラグが立っていれば
    if SPVAR(G_I,"SHOT_FLAG") == 1 then
      ' 弾のX座標を加算
      SPVAR G_I, "X", SPVAR(G_I,"X") + 8
      ' 弾を移動させる
      SPOFS G_I, SPVAR(G_I,"X"), SPVAR(G_I,"Y")
      ' 移動した後に衝突判定
      if D_ShotColCheck(G_I) == -1 then
        ' 弾の座標が400を越えたら
        if G_I, SPVAR(G_I,"X") > 400 then
          ' 画面外に行くのでショットフラグを0にして非表示にする
          SPVAR G_I,"SHOT_FLAG",0
          SPHIDE G_I
        endif
      endif
    endif
  next
end

' 岩の移動処理
'───────────────────────────────
def D_ObstacleMove
  var lpNum = G_SpvManageNo[4]

  ' ループ最大値調整
  case G_PlayerStatus[4]
    when 0
      DEC lpNum, 69
    when 1
      DEC lpNum, 59
    when 2
      DEC lpNum, 49
    when 3
      DEC lpNum, 29
  endcase 


  for G_I=G_SpvManageNo[3], to lpNum
    ' 完全に画面左外でなければ
    if SPVAR(G_I,"X") > -16 then
      ' 岩のX座標を加算
      SPVAR G_I, "X", SPVAR(G_I,"X") - 5
      ' 岩を移動させる
      SPOFS G_I, SPVAR(G_I,"X"), SPVAR(G_I,"Y")
    else
      ' 画面左外に行ったら右画面外にランダム再配置する
      D_ObstacleRndPosSettings G_I
    endif
  next
end

' 障害物再配置
'───────────────────────────────
def D_ObstacleRndPosSettings A_I
  VAR X = 400 + RND(400)
  VAR Y = RND(225)
  SPVAR A_I, "X", X
  SPVAR A_I, "Y", Y
  SPVAR A_I, "IS_HIT", 0
  SPOFS A_I, SPVAR(A_I,"X"), SPVAR(A_I,"Y")
  SPSHOW A_I
end

' プレイヤー衝突チェック
'───────────────────────────────
def D_PlayerColCheck
  var isHit = SPHITSP(G_SpvManageNo[0], G_SpvManageNo[3], G_SpvManageNo[4])

  if isHit != -1 && SPVAR(isHit,"IS_HIT") == 0 then
    BEEP 91, -300
    DEC G_PlayerStatus[0]

    ' ライフが0になったら
    if G_PlayerStatus[0] <= 0 then
      ' ゲームオーバーシーンへいく
      D_SceneChange 3
    endif

    SPVAR isHit, "IS_HIT", 1
  endif
end

' 弾衝突チェック
'───────────────────────────────
def D_ShotColCheck(A_I)

  var isHit = SPHITSP(A_I, G_SpvManageNo[3], G_SpvManageNo[4])

  if isHit != -1 && SPVAR(isHit,"IS_HIT") == 0 then
    BEEP 120
    ' ショットスコアの加算
    D_ScoreAdd 100
    SPVAR isHit, "IS_HIT", 1
    D_ShotPosSettings A_I
    SPHIDE isHit
    return 0
  else
    return -1
  endif
end

' 弾リセット処理
'───────────────────────────────
def D_ShotPosSettings A_I
  SPOFS A_I, -16, -16
  SPVAR A_I, "X", 0
  SPVAR A_I, "Y", 0
  SPVAR A_I, "SHOT_FLAG", 0
end

' 現在スコアの初期化
'───────────────────────────────
def D_ScoreInitialize
  G_PlayerStatus[2] = 0
end 

' スコアの加算
'───────────────────────────────
def D_ScoreAdd A_AddScore
  ' スコア加算
  INC G_PlayerStatus[2], A_AddScore
  ' ハイスコア更新チェック
  if G_PlayerStatus[2] > G_PlayerStatus[3] then
    G_PlayerStatus[3] = G_PlayerStatus[2]
  endif
end

' スコアの更新
'───────────────────────────────
def D_ScoreUpdate
  D_ScoreAdd 0.1

  ' レベルアップ監視
  if G_PlayerStatus[2] > G_GameLvUp[G_PlayerStatus[4]] then
    BEEP 45
    INC G_PlayerStatus[4]
  endif

  GFILL 300,16,400,32,RGB(0,0,0,0)
  GPUTCHR 300,16, STR$(FLOOR(G_PlayerStatus[2])),8,RGB(255,255,255),1
end

' プレイヤーステータスを初期化
'───────────────────────────────
def D_PlayerStatusInitialize
  G_PlayerStatus[0] = 2
  G_PlayerStatus[1] = 0
  G_PlayerStatus[4] = 0
end 

' プレイヤーライフの加算
'───────────────────────────────
def D_PlayerLifeAdd
  ' ライフ加算
  INC G_PlayerStatus[0]
end

' プレイヤーライフの更新
'───────────────────────────────
def D_PlayerLifeUpdate
  GFILL 16,16,100,32,RGB(0,0,0,0)
  GPUTCHR 16,16, "LIFE:"+STR$(G_PlayerStatus[2]),8,RGB(255,255,125),1
end

' ゲームオーバーシーン
'──────────────────────────
def D_GameOver
  GPUTCHR  72,100,"GAME OVER",16,RGB(255,255,255),1
end

' ゲームリセット
'───────────────────────────────
def D_GameReset
  GCLS
  D_SpriteInitialize
  D_PlayerStatusInitialize
  D_ScoreInitialize
  D_SceneChange 1
end

' BGMセレクタ
'───────────────────────────────
def D_BgmSelect
  if G_BgmFlag == #FALSE then
    case G_SceneFlag
      when 0
        BGMPLAY 13
      when 1
        if G_PlayerStatus[4] >= 0 && G_PlayerStatus[4] <= 1 then
          BGMPLAY 2
        elseif G_PlayerStatus[4] >= 2 && if G_PlayerStatus[4] <= 3 then
          BGMPLAY 31
        else
          BGMPLAY 41
        endif
      when 2
        BGMSTOP
      when 3
        BGMPLAY 4
    endcase

    G_BgmFlag = #TRUE
  endif
end

' シーン切り替え
'───────────────────────────────
def D_SceneChange A_Scene
  BGMSTOP
  G_BgmFlag = #FALSE
  G_SceneFlag = A_Scene
endif

' タイトルシーン
'───────────────────────────────
def D_GameTitle
  var frame = MAINCNT()

  ' プチコン4を起動してからの経過時間を元に30で割り切れたらフラグを切り替え
  if (frame MOD 30) == 0 then
    G_FlashFlag = !G_FlashFlag
  endif

  ' 文字をフラグの状態により点滅させる
  if G_FlashFlag == #FALSE
    GPUTCHR  40,100,"PLEASE PRESS  BUTTON",16,RGB(255,255,255),1
    GPUTCHR  40+(16*13+8),100,"A",16,RGB(255,0,0),1
  else
    GFILL 40,100,400,116, RGB(0,0,0,0,)
  endif

  if G_BtnPressCount[0] == 1 then
    GFILL 40,100,400,116, RGB(0,0,0,0,)
    D_SceneChange 1
  endif
end