Godotで放置ゲームを作る④:Timerで発電パネルを自動生産させる

初心者向け実践開発

※本記事にはアフィリエイト広告(Udemy)を含みます。

前回のおさらい

前回③では、Signalを使って「発電する」ボタンとGameManagerをつなぎ、クリックするたびに電力が増える仕組みを作りました。ただ、これだけだと放置ゲームとしては物足りません。今回は、クリックしなくても電力が自動で増えていく仕組みを追加します。

今回のゴール

今回作るのは「発電パネル」という設備です。電力を使って発電パネルを購入すると、以後は何もしなくても毎秒電力が増えていきます。

STATION OPSでは今回はじめて「購入」という概念が登場します。何かを購入すると、その分だけ次回の購入コストが上がっていく、という放置ゲームによくある仕組みも、あわせて実装します。

GameManagerに発電パネルの状態を追加する

GameManager.gdに、以下の変数を追加します。

var power_panel_count: int = 0
var power_panel_cost: float = 10.0

const POWER_PANEL_COST_RATE: float = 1.15
const POWER_PANEL_PRODUCTION: float = 1.0
  • power_panel_count:現在所持している発電パネルの数
  • power_panel_cost:次に1基購入するときのコスト
  • POWER_PANEL_COST_RATE:購入するたびにコストが何倍になるか
  • POWER_PANEL_PRODUCTION:発電パネル1基あたりの毎秒の生産量

なぜコストが購入するたびに上がっていくのか

もしコストが常に一定なら、電力さえ貯めれば発電パネルを無限に増やせてしまい、ゲームとしての駆け引きがなくなってしまいます。購入するたびにコストを1.15倍にすることで、「次の1基を買うために、また電力を貯める」という遊びのリズムが生まれます。この数値は今回10→11.5→13.2…のように上昇していきますが、ちょうどよい上昇率は実際に遊びながら調整していく部分です。

発電パネルを購入する処理を書く

func buy_power_panel() -> bool:
    if power < power_panel_cost:
        return false
    power -= power_panel_cost
    power_panel_count += 1
    power_panel_cost *= POWER_PANEL_COST_RATE
    resources_changed.emit()
    return true

if power < power_panel_cost: return falseの行で、電力が足りない場合は何もせずに処理を終えるようにしています。こうすることで、電力がマイナスになってしまう不具合を防いでいます。

Timerで自動生産を実装する

Timerノードとは

Timerとは、指定した時間が経過するたびにtimeoutというSignalを発信してくれるノードです。「1秒ごとに何かをする」といった、時間を基準にした繰り返し処理を作りたいときに使います。

シーンに置かず、コードからTimerを生成する

今回のTimerは、シーンエディタ上でドラッグ&ドロップするのではなく、GameManager.gdの中でコードから生成します。

var _production_timer: Timer

func _ready() -> void:
    _production_timer = Timer.new()
    _production_timer.wait_time = 1.0
    _production_timer.autostart = true
    _production_timer.timeout.connect(_on_production_tick)
    add_child(_production_timer)

GameManagerはシーンファイルを持たないオートロードなので、シーンエディタで直接ノードを配置できません。そのため、_ready()の中でTimer.new()を呼び出してノードを作り、add_child()で自分の子として追加しています。wait_time = 1.0が「1秒ごと」、autostart = trueが「起動と同時に自動でカウントを始める」設定です。

毎秒、発電パネルの数だけ電力を増やす

func _on_production_tick() -> void:
    if power_panel_count > 0:
        power += power_panel_count * POWER_PANEL_PRODUCTION
        resources_changed.emit()

TimerのtimeoutSignalが発信されるたびにこの関数が呼ばれ、所持している発電パネルの数だけ電力を加算します。

購入ボタンをUIに追加する

①②で用意した「UpgradeList」の中に、発電パネルの購入行を追加します。

  1. UpgradeListの子として「HBoxContainer」を追加する
  2. その子として「Label」を追加し、所持数とコストを表示する
  3. 同じく子として「Button」を追加し、テキストを「購入」にする

Main.gd側では、次のように接続します。

@onready var power_panel_info: Label = $Margin/VBoxContainer/UpgradeList/PowerPanelRow/PowerPanelInfo
@onready var power_panel_buy_button: Button = $Margin/VBoxContainer/UpgradeList/PowerPanelRow/PowerPanelBuyButton

func _ready() -> void:
    # (③で書いた接続に加えて)
    power_panel_buy_button.pressed.connect(_on_power_panel_buy_pressed)

func _on_power_panel_buy_pressed() -> void:
    GameManager.buy_power_panel()

func _update_display() -> void:
    power_label.text = "電力: %d" % int(GameManager.power)
    power_panel_info.text = "発電パネル (%d基) - 次: %d" % [
        GameManager.power_panel_count,
        int(GameManager.power_panel_cost)
    ]
    power_panel_buy_button.disabled = GameManager.power < GameManager.power_panel_cost

最後の行のdisabled = GameManager.power < GameManager.power_panel_costが、電力が足りないときにボタンを押せなくする処理です。ボタンが押せない状態になっていれば、プレイヤーは一目で「まだ買えない」と分かります。

動作確認

「発電する」ボタンでコスト分の電力を貯め、発電パネルを1基購入してみてください。購入後は、ボタンを押さなくても1秒ごとに電力が増えていけば成功です。

次回予告

次回⑤では、酸素・部品という新しい資源を追加し、電力→酸素→部品という連鎖構造を作ります。

Godot学習におすすめのオンライン講座

Timerとオートロードを組み合わせた設計は、放置ゲームに限らずいろいろな場面で応用できます。基礎から体系的に学びたい方はこちらもどうぞ。

Godotのコースを見る

参考リンク


コメント

タイトルとURLをコピーしました