プログラミング未経験だけどゲームつくる - 6 : タイトル画面をつくる【LOVE2d】

猫は実家で飼ってます。
こんばんは、サトウダイスケです。

今回はタイトル画面を作りたいと思います。

そもそもの話ですが、
一般的にどのようにゲームを作ってるとかそういうことが全くわからないです。

例えば大量のテキストメッセージってどうやって保管して表示してるんだろうとか。どこか専用のファイル作って、そこに保存して、あとは変数の番号で呼び出してるのかなあとか想像の域を超えません。

あと、RPGで言うマップの森とか壁とかのタイルってどうやって配置したり管理しているんだろう...とか。直感的にできないとしたらめちゃくちゃ大変そうだな...

タイトル画面も同様で、今回作っているゲームのタイトル画面用の背景が真っ黒だとしたら、ゲーム本編の画面を覆うような黒いマットを敷いて、STARTボタンを押したら、黒いマットが外れて、後ろ側に隠れてたゲーム本編が出てくるような感じなんですかね。目指す方向としては。

TPOなんだろうけど、今回はその方向を目指します。
※今回ははじめてリアルタイムでnoteを書いてみてます。

その際気をつけなければいけないのは、

・描写するイメージのレイヤーの前後関係
 ※CSSで言うところのz-index
・本編のキー操作を一時的に無効にすること
・本編で時間制限や敵の動きがある場合は一時的にストップしておく

といったところでしょうか。


描写するイメージのレイヤーの前後関係

取り敢えず上のWikiからわかることとしては、LOVE2dの設計思想にはz-index的なものは存在していないということ。

コードの記述順番を後にしたものが前面レイヤーになるようなので、その都度削除して挿入しなおさないといけないようだ。

良い方法はありそうだけど、難しそうで躓くことになってしまうので、記述順番で解決して進んでいきます。

  -- タイトル画面の描写

  love.graphics.setColor(0, 0, 0 , 255)
  love.graphics.rectangle("fill", 0, 0, window_w,  window_h)  

  love.graphics.setFont(title_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print("ねこダッシュ", window_w/2, window_h/2)

  love.graphics.setFont(message_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print("はじめる", window_w/2, window_h/2+80)

  love.graphics.setFont(message_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print("せつめい", window_w/2, window_h/2+120)

こんな表示になりました。

	window_w = t.window.width
	window_h = t.window.height

で、画面の横幅と縦幅を取得しています。
なので、黒マットは丁度のサイズで描画されています。

文字の表示位置は、横幅と縦幅の1/2の座標から描写されています。

これだけだと、ズレてしまいますよね。
centerにalignしたい...

x軸方向のcenterはテキストの長さを取得してその半分を差し引けばいけそうです。y軸方向のverticalなalignについては...divでもあるある問題ですね。

ゲーム画面の設定が

	t.window.width = 800
	t.window.height = 500

になっているので、それが固定であれば少しずつズラして、見た目ベースで整列してもいいかもしれないのですが、あとで困りますので、計算式で出したいところ。

「ねこダッシュの上端〜せつめいの下端」までのheightがわかれば、x軸同様にその半分を差し引けばいけそうではあります。つまり、window_h/2が「ねこダッシュの上端」で、window_h/2+120が「せつめいの上端」なので、”せつめい”の文字の縦のheightがわかれば、「ねこダッシュの上端〜せつめいの下端」までのheightがわかりそうです。

求めるべきは、

(window_h/2+120+”せつめい”の文字の縦のheight)-(window_h/2)
=120+”せつめい”の文字の縦のheight

ですね。

そういえば、先日もリンクを貼った、

に日本語文字の大きさの計算の方法がありました。
getWidthを使いたいと思います。

まずは、x軸方向のセンタライズ。

  title = "ねこダッシュ"
  hajimeru = "はじめる"
  setsumei = "せつめい"

  title_width = title_font:getWidth(title) 
  hajimeru_width = message_font:getWidth(hajimeru) 
  setsumei_width = message_font:getWidth(setsumei) 

  love.graphics.setColor(0, 0, 0 , 255)
  love.graphics.rectangle("fill", 0, 0, window_w,  window_h)  

  love.graphics.setFont(title_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print(title, window_w/2-title_width/2, window_h/2)

  love.graphics.setFont(message_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print(hajimeru, window_w/2-hajimeru_width/2, window_h/2+80)

  love.graphics.setFont(message_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print(setsumei, window_w/2-setsumei_width/2, window_h/2+120)

なぜ..."はじめる"と"せつめい"がズレてる気がする。
解せぬ。ダッシュのュの小文字の大きさのせいか。

文字を変えたら合ってた。
とりあえずこっちでいこう。

次はy軸のセンタライズ。

  title = "ねこがはしる"
  hajimeru = "はじめる"
  setsumei = "せつめい"

  title_width = title_font:getWidth(title) 
  hajimeru_width = message_font:getWidth(hajimeru) 
  setsumei_width = message_font:getWidth(setsumei) 

  setsumei_height = message_font:getHeight(setsumei) 

  love.graphics.setColor(0, 0, 0 , 255)
  love.graphics.rectangle("fill", 0, 0, window_w,  window_h)  

  love.graphics.setFont(title_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print(title, window_w/2-title_width/2, window_h/2-(120+setsumei_height)/2)

  love.graphics.setFont(message_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print(hajimeru, window_w/2-hajimeru_width/2, window_h/2+80-(120+setsumei_height)/2)

  love.graphics.setFont(message_font)
  love.graphics.setColor(255, 255, 255)
  love.graphics.print(setsumei, window_w/2-setsumei_width/2, window_h/2+120-(120+setsumei_height)/2)

でけたー!

出来る限りですがコードの簡略化したいと思います。

  title_text={}
  title_text={
              "ねこがはしる",
              "はじめる",
              "せつめい",
              }
  title_text_lineheight = 40 -- 行間サイズ

  love.graphics.setColor(0, 0, 0 , 255)
  love.graphics.rectangle("fill", 0, 0, window_w,  window_h)  

  for i = 1 , #title_text do
    love.graphics.setColor(255, 255, 255)
    if i == 1 then 
      love.graphics.setFont(title_font)
      text_width =  title_font:getWidth(title_text[i]) 
      s = 0
    else 
      love.graphics.setFont(message_font)
      text_width =  message_font:getWidth(title_text[i]) 
      s = 1
    end
    text_height = title_font:getHeight(title_text[i])
    text_x = (window_w-text_width)/2
    text_y = (window_h-(title_text_lineheight*(#title_text)+text_height))/2
    love.graphics.print(title_text[i], text_x , text_y+title_text_lineheight*(i-1)+40*s)
  end

少しだけ綺麗になりました。

メニューの増減も自動で対応できるように。


キー操作でメニューを選べるようにする

続いてはキー操作です。

game_startのtrueとfalseで、
タイトル画面なのかゲーム画面なのかを切り替えます。

  -- タイトル画面
  game_start = false
  title_text={}
  title_text={
              "ねこがはしる",
              "はじめる",
              "せつめい",
              "おぷしょん",
              "らんきんぐ",
              }
  title_text_lineheight = 40 -- 行間サイズ
  active_menu = 2 -- 初期で選択されているメニュー
  menu_wait = false
  wait_time = 0.15
  wait_time_remaining = wait_time


  -- キー操作によるタイトルめ画面のメニューがアクティブな位置の計算

  if menu_wait == false then

    if 2 < active_menu then
      if love.keyboard.isDown("up") then
        love.audio.stop(snd_message)
        love.audio.play(snd_message)
        active_menu = active_menu - 1
        menu_wait = true
      end
    end
      
    if active_menu < (#title_text) then
      if love.keyboard.isDown("down") then
        love.audio.stop(snd_message)
        love.audio.play(snd_message)
        active_menu = active_menu + 1
        menu_wait = true
      end
    end

    if love.keyboard.isDown("return") then
      love.audio.stop(snd_message)
      love.audio.play(snd_message)
      menu_wait = true
      game_start = true
    end

    elseif menu_wait == true then
      wait_time_remaining = wait_time_remaining - dt
      if wait_time_remaining <= 0 then
        menu_wait = false
        wait_time_remaining = wait_time
    end
  end

 
  -- タイトル画面の描写

  if game_start == false then
    love.graphics.setColor(0, 0, 0 , 255)
    love.graphics.rectangle("fill", 0, 0, window_w,  window_h)  

    for i = 1 , #title_text do
      love.graphics.setColor(255, 255, 255)
      if i == 1 then 
        love.graphics.setFont(gametitle_font)
        text_width =  gametitle_font:getWidth(title_text[i]) 
        s = 0
      else 
        love.graphics.setFont(message_font)
        text_width =  message_font:getWidth(title_text[i]) 
        s = 1
      end
      text_height = gametitle_font:getHeight(title_text[i])
      text_x = (window_w-text_width)/2
      text_y = (window_h-(title_text_lineheight*(#title_text)+text_height))/2
      if i == active_menu then
        love.graphics.setColor(255, 0, 0)
       else
        love.graphics.setColor(255, 255, 255)
      end
      love.graphics.print(title_text[i], text_x , text_y+title_text_lineheight*(i-1)+40*s)
    end
  end
    elseif menu_wait == true then
      wait_time_remaining = wait_time_remaining - dt
      if wait_time_remaining <= 0 then
        menu_wait = false
        wait_time_remaining = wait_time
    end

このあたりはもっと改善しようがありそう。

こんな感じでupとdownのキー操作でメニューを選べるようになりました。
「はじめる」「らんきんぐ」でカーソルは止まります。
また、returnでゲーム本編に切り替わります。

ゲームっぽくなってきましたね。
今はデザインが質素ですけど、最後にブラッシュアップしたいと思います。

次回は、

・制限時間を設定する
・スコアやHPを表示できるようにする

に挑戦します〜





この記事が気に入ったらサポートをしてみませんか?