個人ゲーム開発日報|コインでレベルアップの実装

ゲーム開発
スポンサーリンク

前回は、敵のライフの増加を実装します。

個人ゲーム開発日報|敵のライフを増やす
敵のライフを増やす実装をします。

今回は、獲得したコインでタップレベルと味方の精霊の攻撃力が上がる機能を実装します。

ボタンを作成、コードをアタッチ

やることは以下です。

  1. タップレベルと精霊レベルを上げるコードを作成
  2. ボタンを作成する。
  3. そのボタンをインスペクターでアタッチする。

タップダメージと精霊の攻撃力を上げる関数は以下のようにします。

void IncreaseTapDamage()
    {
        if (coinCount >= 10) // 必要なコイン数を設定
        {
            coinCount -= 10; // コインを消費
            tapDamage += 1; // タップダメージを増加
            UpdateCoinCountText(); // UIを更新
            Debug.Log("タップダメージが増加しました。現在のタップダメージ: " + tapDamage);
        }
    }

    void IncreaseSpiritLevel()
    {
        if (coinCount >= 20) // 必要なコイン数を設定
        {
            coinCount -= 20; // コインを消費
            SpiritController spiritController = FindObjectOfType<SpiritController>();
            if (spiritController != null)
            {
                spiritController.IncreaseAttackPower(); // 精霊の攻撃力を増加
            }
            UpdateCoinCountText(); // UIを更新
            Debug.Log("精霊の攻撃力が増加しました。");
        }
    }

SpiritController

    public void IncreaseAttackPower()
    {
        attackPower += 1; // 精霊の攻撃力を増加
    }

アタッチするボタンをインスペクターで登録できるようにし

    public Button increaseTapDamageButton; // タップの威力を上げるボタン
    public Button increaseSpiritLevelButton; // 精霊のレベルを上げるボタン

Startで認識させます。

    void Start()
    {
        // ボタンにイベントリスナーを追加
        increaseTapDamageButton.onClick.AddListener(IncreaseTapDamage);
        increaseSpiritLevelButton.onClick.AddListener(IncreaseSpiritLevel);
    }

これで、ボタンを押したらレベルが上がる機能を実装できました。

全体コード

using UnityEngine;
using DG.Tweening;
using TMPro;
using System.Collections;
using UnityEngine.UI;

public class ClickDamageHandler : MonoBehaviour
{
    public GameObject coinPrefab; // コインのプレハブ
    public GameObject diamondPrefab; // ダイヤのプレハブ
    public Transform coinSpawnPoint; // コインが飛び出す位置
    public TMP_Text coinCountText; // コイン獲得数を表示するTextMeshProUGUI
    public TMP_Text diamondCountText; // ダイヤ獲得数を表示するTextMeshProUGUI
    public Image damageGaugeBackground; // ダメージゲージの背景
    public Image damageGaugeFill; // ダメージゲージのフィル
    public TMP_Text enemyLifeText; // 敵のライフを表示するTextMeshProUGUI
    public Button increaseTapDamageButton; // タップの威力を上げるボタン
    public Button increaseSpiritLevelButton; // 精霊のレベルを上げるボタン

    private int coinCount = 0; // 獲得したコインの数
    private int diamondCount = 0; // 獲得したダイヤの数
    private int damageCount = 0; // ダメージ数のカウント
    private int enemyLife = 10; // 敵のライフ
    private int maxEnemyLife = 10; // 敵の最大ライフ
    private int tapDamage = 1; // タップの威力
    private Vector3 originalPosition; // オブジェクトの元の位置
    private bool isAnimating = false; // アニメーション中かどうかを示すフラグ

    private SpriteRenderer spriteRenderer; // スプライトレンダラー

    void Start()
    {
        // オブジェクトの元の位置を保存
        originalPosition = transform.localPosition;
        spriteRenderer = GetComponent<SpriteRenderer>(); // スプライトレンダラーを取得
        UpdateCoinCountText(); // 初期表示の更新
        UpdateDiamondCountText(); // 初期表示の更新
        UpdateDamageGauge(); // 初期表示の更新
        UpdateEnemyLifeText(); // 敵のライフの表示を更新

        // ボタンにイベントリスナーを追加
        increaseTapDamageButton.onClick.AddListener(IncreaseTapDamage);
        increaseSpiritLevelButton.onClick.AddListener(IncreaseSpiritLevel);
    }

    void OnMouseDown()
    {
        if (!isAnimating)
        {
            ReceiveDamage(tapDamage); // 現在のタップダメージを使用
        }
    }

    public void ReceiveDamage(int amount)
    {
        damageCount += amount; // ダメージ数を増加
        enemyLife -= amount; // 敵のライフを減少
        LogDamage(); // ダメージ数をコンソールに表示
        ShakeObject(); // オブジェクトを揺らす
        SpawnCoin(); // コインを生成して飛ばす
        UpdateDamageGauge(); // ダメージゲージを更新
        UpdateEnemyLifeText(); // 敵のライフの表示を更新
        if (enemyLife <= 0)
        {
            DropDiamondAndRespawnEnemy(); // ダイヤを生成し、敵をリスポーン
        }
    }

    void LogDamage()
    {
        Debug.Log("Damage: " + damageCount); // コンソールにダメージ数を表示
    }

    void ShakeObject()
    {
        // アニメーション中フラグを設定
        isAnimating = true;

        // 左にもっと動かしてから元の位置に戻す
        transform.DOLocalMoveX(originalPosition.x - 0.2f, 0.05f).SetEase(Ease.OutQuad) // 移動の幅を0.2fに設定
            .OnComplete(() =>
            {
                transform.localPosition = originalPosition;
                isAnimating = false; // アニメーションが終了したらフラグをリセット
            });
    }

    void SpawnCoin()
    {
        // コインを生成
        GameObject coin = Instantiate(coinPrefab, coinSpawnPoint.position, Quaternion.identity);

        // コインを敵キャラクターより上に表示
        coin.GetComponent<SpriteRenderer>().sortingOrder = 10;

        // コインに飛び出すアニメーションを適用
        float dropHeight = Random.Range(-2.0f, -4.0f); // 落下先を2倍に伸ばす
        Vector3 peakPosition = new Vector3(
            coinSpawnPoint.position.x,
            coinSpawnPoint.position.y + 1.0f, // 一度上に上がる
            coinSpawnPoint.position.z
        );
        Vector3 targetPosition = new Vector3(
            coinSpawnPoint.position.x + Random.Range(-1.0f, 1.0f), // 横の範囲を広げる
            coinSpawnPoint.position.y + dropHeight,
            coinSpawnPoint.position.z
        );

        Sequence coinSequence = DOTween.Sequence();
        coinSequence.Append(coin.transform.DOMove(peakPosition, 0.15f).SetEase(Ease.OutQuad)) // 上に上がる動きを2倍速に
                    .Append(coin.transform.DOMove(targetPosition, 0.25f).SetEase(Ease.InQuad)) // 下に落ちる動きを2倍速に
                    .OnComplete(() => StartCoroutine(CoinLifetime(coin))); // アニメーション完了時にコインのライフタイムを開始
    }

    IEnumerator CoinLifetime(GameObject coin)
    {
        float lifetime = 4.0f; // コインが消えるまでの時間
        float timer = 0.0f;

        while (timer < lifetime)
        {
            timer += Time.deltaTime;
            yield return null;

            if (coin == null)
                yield break; // コインが既に消えている場合はコルーチンを終了
        }

        if (coin != null)
        {
            Destroy(coin);
            AddCoin(); // コインを獲得
        }
    }

    public void AddCoin()
    {
        coinCount++; // 獲得したコイン数を増加
        UpdateCoinCountText(); // UIを更新
    }

    public void AddDiamond()
    {
        diamondCount++; // 獲得したダイヤ数を増加
        UpdateDiamondCountText(); // UIを更新
    }

    void UpdateCoinCountText()
    {
        coinCountText.text = "Coins: " + coinCount.ToString(); // コイン数を表示
    }

    void UpdateDiamondCountText()
    {
        diamondCountText.text = "Diamonds: " + diamondCount.ToString(); // ダイヤ数を表示
    }

    void UpdateDamageGauge()
    {
        float fillAmount = (float)enemyLife / maxEnemyLife;
        damageGaugeFill.fillAmount = fillAmount; // ダメージゲージを更新
    }

    void UpdateEnemyLifeText()
    {
        enemyLifeText.text = "Life: " + enemyLife.ToString(); // 敵のライフを表示
    }

    void DropDiamondAndRespawnEnemy()
    {
        // ダイヤを生成
        GameObject diamond = Instantiate(diamondPrefab, coinSpawnPoint.position, Quaternion.identity);

        // ダイヤに飛び出すアニメーションを適用
        float dropHeight = Random.Range(-2.0f, -4.0f); // 落下先を2倍に伸ばす
        Vector3 peakPosition = new Vector3(
            coinSpawnPoint.position.x,
            coinSpawnPoint.position.y + 1.0f, // 一度上に上がる
            coinSpawnPoint.position.z
        );
        Vector3 targetPosition = new Vector3(
            coinSpawnPoint.position.x + Random.Range(-1.0f, 1.0f), // 横の範囲を広げる
            coinSpawnPoint.position.y + dropHeight,
            coinSpawnPoint.position.z
        );

        Sequence diamondSequence = DOTween.Sequence();
        diamondSequence.Append(diamond.transform.DOMove(peakPosition, 0.15f).SetEase(Ease.OutQuad)) // 上に上がる動きを2倍速に
                       .Append(diamond.transform.DOMove(targetPosition, 0.25f).SetEase(Ease.InQuad)) // 下に落ちる動きを2倍速に
                       .OnComplete(() => StartCoroutine(DiamondLifetime(diamond))); // アニメーション完了時にダイヤのライフタイムを開始

        // 敵のライフを増加させる
        maxEnemyLife += 10; // ライフの増加量を設定
        enemyLife = maxEnemyLife;

        // 敵を一瞬消して再び現れる演出を追加
        StartCoroutine(RespawnEnemy());
    }

    IEnumerator DiamondLifetime(GameObject diamond)
    {
        float lifetime = 4.0f; // ダイヤが消えるまでの時間
        float timer = 0.0f;

        while (timer < lifetime)
        {
            timer += Time.deltaTime;
            yield return null;

            if (diamond == null)
                yield break; // ダイヤが既に消えている場合はコルーチンを終了
        }

        if (diamond != null)
        {
            Destroy(diamond);
            AddDiamond(); // ダイヤを獲得
        }
    }

    IEnumerator RespawnEnemy()
    {
        // 敵を一瞬消す
        spriteRenderer.DOFade(0, 0.5f);
        yield return new WaitForSeconds(0.5f);

        // 敵を再び現す
        spriteRenderer.DOFade(1, 0.5f);
        UpdateDamageGauge(); // ダメージゲージをリセット
        UpdateEnemyLifeText(); // 敵のライフの表示を更新
    }

    void IncreaseTapDamage()
    {
        if (coinCount >= 10) // 必要なコイン数を設定
        {
            coinCount -= 10; // コインを消費
            tapDamage += 1; // タップダメージを増加
            UpdateCoinCountText(); // UIを更新
            Debug.Log("タップダメージが増加しました。現在のタップダメージ: " + tapDamage);
        }
    }

    void IncreaseSpiritLevel()
    {
        if (coinCount >= 20) // 必要なコイン数を設定
        {
            coinCount -= 20; // コインを消費
            SpiritController spiritController = FindObjectOfType<SpiritController>();
            if (spiritController != null)
            {
                spiritController.IncreaseAttackPower(); // 精霊の攻撃力を増加
            }
            UpdateCoinCountText(); // UIを更新
            Debug.Log("精霊の攻撃力が増加しました。");
        }
    }
}
using UnityEngine;
using System.Collections;
using DG.Tweening;

public class SpiritController : MonoBehaviour
{
    public GameObject targetEnemy; // 攻撃対象の敵
    public int attackPower = 1; // 攻撃力
    public float attackInterval = 4.0f; // 攻撃間隔
    public float attackMoveDistance = 0.5f; // 攻撃時に移動する距離
    public float attackMoveDuration = 0.2f; // 攻撃時に移動する時間

    private ClickDamageHandler enemyHandler; // 敵のダメージハンドラー
    private Vector3 originalPosition; // 精霊の元の位置

    void Start()
    {
        // 初期設定
        if (targetEnemy != null)
        {
            enemyHandler = targetEnemy.GetComponent<ClickDamageHandler>();
        }

        originalPosition = transform.localPosition;

        // 攻撃コルーチンを開始
        StartCoroutine(AttackCoroutine());
    }

    IEnumerator AttackCoroutine()
    {
        while (true)
        {
            yield return new WaitForSeconds(attackInterval);
            Attack();
        }
    }

    void Attack()
    {
        if (enemyHandler != null)
        {
            // 精霊の攻撃アニメーション
            Sequence attackSequence = DOTween.Sequence();
            attackSequence.Append(transform.DOLocalMoveX(originalPosition.x + attackMoveDistance, attackMoveDuration).SetEase(Ease.OutQuad))
                          .Append(transform.DOLocalMoveX(originalPosition.x, attackMoveDuration).SetEase(Ease.InQuad))
                          .OnComplete(() => enemyHandler.ReceiveDamage(attackPower)); // 攻撃のダメージを与える
        }
    }

    public void IncreaseAttackPower()
    {
        attackPower += 1; // 精霊の攻撃力を増加
    }
}

今回はここまで。

<過去の記事>

個人ゲーム開発日報|ライフバー(HPバー)の実装
今回は、敵のライフバー(HPバー)を実装します。
個人ゲーム開発日報|味方の作成、攻撃と攻撃アニメーションの実装
前回は、敵のライフバー(HPバー)を実装しました。今回は、味方の精霊を作り、その精霊も敵にダメージを与える機能とアニメーションを実装します。決まった間隔で攻撃、敵にダメージを与えるやりたいことは、タップ...
個人ゲーム開発日報|ハーフモーダルの実装
今回は、ハーフモーダル機能を実装します。
個人ゲーム開発日報|敵のライフを増やす
敵のライフを増やす実装をします。
タイトルとURLをコピーしました