Browse Source

数学模式代码

haobo wei 3 weeks ago
parent
commit
b21b0df6ab

+ 0 - 1
Assets/GAME/Scripts/Core/Player/PlayerArmyManager.cs

@@ -45,7 +45,6 @@ public class PlayerArmyManager : MonoBehaviour
   {
     _playerArcherCount++;
 
-
     PlayerWarriors.Add(Instantiate(ComponentsManager.BattleManager.PlayerArcherPrefab.GetComponent<Warrior>(),
       ComponentsManager.StagesManager.GetCurrentStageItem.GetPlayerPoint(_counter).position, Quaternion.identity));
 

+ 0 - 4
Assets/GAME/Scripts/Core/Tutorial/Tutorial.cs

@@ -72,14 +72,10 @@ public class Tutorial : MonoBehaviour
     tutorialPointer.gameObject.SetActive(true);
     tutorialPointer.position=Camera.main.WorldToScreenPoint(answer.position);
 
-    AnswerOption.OnAnswerClicked += OnAnswerClicked;
-
   }
   private void OnAnswerClicked()
   {
     Time.timeScale=1f;
     tutorialPointer.gameObject.SetActive(false);
-    AnswerOption.OnAnswerClicked -= OnAnswerClicked;
-
   }
 }

+ 30 - 88
Assets/Scripts/AnswerOption.cs

@@ -6,124 +6,66 @@ public class AnswerOption : MonoBehaviour
     [SerializeField] private TextMeshPro answerText;
     private int answerValue;
     private MathQuizManager quizManager;
-    private float lifeTime;
     private bool isCorrect;
-    private Vector3 startPosition;
-    private Vector3 targetPosition;
-    private bool isFullyShown = false;
-    private bool isDisappearing = false;
-    private float showAnimationTime = 0.8f;    // 显示动画时间
-    private float disappearAnimationTime = 1f; // 消失动画时间
-    private float currentShowTime = 0f;
-    private float currentDisappearTime = 0f;
-    private float floatHeight = 3f;           // 上浮高度
-    public static event Action OnAnswerClicked;
+    private Vector3 startPos, targetPos;
+    private float showTime = 0.8f, disappearTime = 1f, floatHeight = 3f;
+    private float showT = 0f, disappearT = 0f;
+    private bool isShown = false, isDisappearing = false;
 
-    public bool IsCorrect => isCorrect;
+    public static event Action OnAnswerClicked;
 
     void Start()
     {
-        // 如果answerText为空,尝试在子对象中查找
-        if (answerText == null)
-        {
-            answerText = GetComponentInChildren<TextMeshPro>();
-            if (answerText == null)
-            {
-                Debug.LogError("AnswerOption: No TextMeshPro component found! Please add a TextMeshPro component to this object or its children.");
-            }
-        }
-        // 设置初始位置
-        startPosition = transform.position;
-        // 设置目标位置(向上移动)
-        targetPosition = startPosition + Vector3.up * floatHeight;
-        // 设置销毁时间
-        Destroy(gameObject, quizManager.GetAnswerLifeTime() + disappearAnimationTime);
+        if (!answerText) answerText = GetComponentInChildren<TextMeshPro>();
+        startPos = transform.position;
+        targetPos = startPos + Vector3.up * floatHeight;
+        Destroy(gameObject, showTime + disappearTime + 15f);
     }
 
-    public void Initialize(MathQuizManager manager, int value, bool correct)
+    public void Initialize(MathQuizManager mgr, int value, bool correct)
     {
-        quizManager = manager;
+        quizManager = mgr;
         answerValue = value;
         isCorrect = correct;
-        if (answerText != null)
-        {
-            answerText.text = value.ToString();
-            // 使用默认颜色
-            answerText.color = Color.white;
-        }
-        lifeTime = manager.GetAnswerLifeTime();
-
-        // 设置自动销毁
-        Invoke("StartDisappear", lifeTime);
+        if (answerText) answerText.text = value.ToString();
+        Invoke(nameof(StartDisappear), 15f);
     }
 
     void Update()
     {
         if (isDisappearing)
         {
-            // 处理消失动画
-            currentDisappearTime += Time.deltaTime;
-            float disappearProgress = Mathf.Clamp01(currentDisappearTime / disappearAnimationTime);
-            
-            // 同时处理位置和缩放
-            transform.position = Vector3.Lerp(transform.position, transform.position + Vector3.up * floatHeight, disappearProgress);
-            transform.localScale = Vector3.Lerp(Vector3.one, Vector3.zero, disappearProgress);
-            
-            if (disappearProgress >= 1f)
-            {
-                Destroy(gameObject);
-            }
+            disappearT += Time.deltaTime;
+            float t = Mathf.Clamp01(disappearT / disappearTime);
+            transform.position = Vector3.Lerp(transform.position, transform.position + Vector3.up * floatHeight, t);
+            transform.localScale = Vector3.Lerp(Vector3.one, Vector3.zero, t);
+            if (t >= 1f) Destroy(gameObject);
         }
-        else if (!isFullyShown)
+        else if (!isShown)
         {
-            // 处理显示动画
-            currentShowTime += Time.deltaTime;
-            float showProgress = Mathf.Clamp01(currentShowTime / showAnimationTime);
-            
-            // 同时处理位置和缩放
-            transform.position = Vector3.Lerp(startPosition, targetPosition, showProgress);
-            transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, showProgress);
-            
-            if (showProgress >= 1f)
-            {
-                isFullyShown = true;
-            }
+            showT += Time.deltaTime;
+            float t = Mathf.Clamp01(showT / showTime);
+            transform.position = Vector3.Lerp(startPos, targetPos, t);
+            transform.localScale = Vector3.Lerp(Vector3.zero, Vector3.one, t);
+            if (t >= 1f) isShown = true;
         }
         else
         {
-            // 完全显示后的持续移动
-            transform.position = Vector3.Lerp(transform.position, targetPosition, quizManager.GetFloatSpeed() * Time.deltaTime);
+            transform.position = Vector3.Lerp(transform.position, targetPos, 0.3f * Time.deltaTime);
         }
     }
 
-    private void StartDisappear()
-    {
-        isDisappearing = true;
-        currentDisappearTime = 0f;
-    }
+    void StartDisappear() { isDisappearing = true; disappearT = 0f; }
 
     void OnMouseDown()
     {
-        // 只有在完全显示且未开始消失时才能点击
-        if (quizManager != null && isFullyShown && !isDisappearing)
+        if (quizManager != null && isShown && !isDisappearing)
         {
-            bool isCorrect = quizManager.CheckAnswer(this);
-            // 根据答案正确性播放不同的音效
-            if (isCorrect)
-            {
-                // TODO: 播放正确答案音效
-            }
-            else
-            {
-                // TODO: 播放错误答案音效
-            }
+            quizManager.CheckAnswer(this);
             StartDisappear();
+            OnAnswerClicked?.Invoke();
         }
-        OnAnswerClicked?.Invoke();
     }
 
-    public int GetAnswerValue()
-    {
-        return answerValue;
-    }
+    public int GetAnswerValue() => answerValue;
 } 

+ 91 - 206
Assets/Scripts/MathQuizManager.cs

@@ -1,259 +1,144 @@
 using UnityEngine;
 using TMPro;
-using System.Collections.Generic; 
+using System.Collections.Generic;
 using System.Linq;
 
 public class MathQuizManager : MonoBehaviour
 {
-    [Header("UI References")]
-    [SerializeField] private TextMeshProUGUI questionText;    // 显示题目的文本
-    [SerializeField] private TextMeshProUGUI coinText;        // 显示金币的文本
-    [SerializeField] private GameObject answerPrefab;         // 答案选项预制体
-
-    [Header("Game Settings")]
-    [SerializeField] private float wrongAnswerPenalty = 0.1f; // 错误答案的攻击力减弱比例
-    [SerializeField] private int correctAnswerReward = 10;    // 正确答案的金币奖励
-    [SerializeField] private float answerLifeTime = 15f;      // 答案选项存在时间
-    [SerializeField] private float floatSpeed = 0.3f;         // 答案选项上浮速度
-    [SerializeField] private float correctAnswerBoost = 0.2f; // 正确答案的攻击力加强比例
-    [SerializeField] private float boostDuration = 5f;        // 攻击力加强持续时间
-    [SerializeField] private float answerSpawnRadius = 3f;    // 答案生成半径
-    [SerializeField] private float minAnswerDistance = 1.5f;  // 答案最小生成距离
-    [SerializeField] private int maxAnswersOnScreen =  6;      // 屏幕上最多显示的答案数量
-    [SerializeField] private float correctAnswerChance = 0.3f;// 正确答案生成概率
-
-    // 公共方法用于获取配置值
-    public float GetAnswerLifeTime() => answerLifeTime;
-    public float GetFloatSpeed() => floatSpeed;
-    public float GetCorrectAnswerBoost() => correctAnswerBoost;
-    public float GetBoostDuration() => boostDuration;
-
-    // 私有变量
-    private int currentAnswer;              // 当前题目的正确答案
-    private int coins;                      // 玩家的金币数量
-    private readonly List<Warrior> penalizedWarriors = new List<Warrior>(); // 受到惩罚的战士
-    private readonly List<AnswerOption> activeAnswers = new List<AnswerOption>(); // 当前活动的答案选项
-    private Vector3 lastEnemyDeathPosition; // 存储最后一个敌人死亡的位置
-    private int enemyDeathCount = 0;        // 敌人死亡计数
-
-    private void Start()
-    {
-        InitializeGame();
-    }
-
-    private void InitializeGame()
-    {
-        GenerateNewProblem();
-        UpdateCoinDisplay();
-    }
-
-    // 生成新的数学题目
-    public void GenerateNewProblem()
-    {
-        int num1, num2;
-        int operationType = Random.Range(0, 2); // 0:加法, 1:减法
-
-        switch (operationType)
-        {
-            case 0: // 加法
-                num1 = Random.Range(1, 11);  // 1-10
-                num2 = Random.Range(1, 11);  // 1-10
-                currentAnswer = num1 + num2;
-                questionText.text = $"{num1} + {num2} = ?";
-                break;
-
-            case 1: // 减法
-                num1 = Random.Range(1, 11);  // 1-10
-                num2 = Random.Range(1, num1 + 1); // 确保结果为正数
-                currentAnswer = num1 - num2;
-                questionText.text = $"{num1} - {num2} = ?";
-                break;
-        }
-    }
-
-    // 检查答案
-    public bool CheckAnswer(AnswerOption answerOption)
-    {
-        bool isCorrect = answerOption.GetAnswerValue() == currentAnswer;
-        
-        if (isCorrect)
+    [Header("UI")]
+    [SerializeField] private TextMeshProUGUI questionText;
+    [SerializeField] private TextMeshProUGUI coinText;
+    [SerializeField] private GameObject answerPrefab;
+
+    [Header("参数")]
+    [SerializeField] private float wrongPenalty = 0.1f;
+    [SerializeField] private int correctReward = 10;
+    [SerializeField] private float answerLife = 15f;
+    [SerializeField] private float floatSpeed = 0.3f;
+    [SerializeField] private float correctBoost = 0.2f;
+    [SerializeField] private float boostTime = 5f;
+    [SerializeField] private float spawnRadius = 3f;
+    [SerializeField] private float minSpawnDist = 1.5f;
+    [SerializeField] private int maxAnswers = 6;
+    [SerializeField] private float correctChance = 0.3f;
+
+    private int currentAnswer;
+    private int coins;
+    private List<Warrior> penalized = new();
+    private List<AnswerOption> answers = new();
+    private Vector3 lastEnemyPos;
+    private int deathCount = 0;
+
+    void Start() { NewProblem(); UpdateCoin(); }
+
+    void NewProblem()
+    {
+        int a = Random.Range(1, 11), b = Random.Range(1, 11);
+        if (Random.value < 0.5f) // 加法
         {
-            HandleCorrectAnswer();
+            currentAnswer = a + b;
+            questionText.text = $"{a} + {b} = ?";
         }
-        else
+        else // 减法
         {
-            HandleWrongAnswer(answerOption);
+            if (b > a) (a, b) = (b, a);
+            currentAnswer = a - b;
+            questionText.text = $"{a} - {b} = ?";
         }
-        
-        return isCorrect;
     }
 
-    private void HandleCorrectAnswer()
+    public bool CheckAnswer(AnswerOption opt)
     {
-        AddCoins(correctAnswerReward);
-        ResetAllWarriorsPenalties();
-        ClearAllAnswers();
-        GenerateNewProblem();
+        bool correct = opt.GetAnswerValue() == currentAnswer;
+        if (correct) OnCorrect();
+        else OnWrong(opt);
+        return correct;
     }
 
-    private void HandleWrongAnswer(AnswerOption answerOption)
+    void OnCorrect()
     {
-        ApplyPenaltyToAllWarriors();
-        RemoveAnswer(answerOption);
-        Destroy(answerOption.gameObject);
+        coins += correctReward;
+        UpdateCoin();
+        ResetPenalties();
+        ClearAnswers();
+        NewProblem();
     }
 
-    // 清除所有答案选项
-    private void ClearAllAnswers()
+    void OnWrong(AnswerOption opt)
     {
-        foreach (AnswerOption answer in activeAnswers.ToList())
-        {
-            if (answer != null)
-            {
-                Destroy(answer.gameObject);
-            }
-        }
-        activeAnswers.Clear();
+        ApplyPenalty();
+        RemoveAnswer(opt);
+        Destroy(opt.gameObject);
     }
 
-    // 从活动答案列表中移除答案
-    public void RemoveAnswer(AnswerOption answer)
+    void ClearAnswers()
     {
-        activeAnswers.Remove(answer);
+        foreach (var a in answers) if (a) Destroy(a.gameObject);
+        answers.Clear();
     }
 
-    // 添加金币
-    private void AddCoins(int amount)
-    {
-        coins += amount;
-        UpdateCoinDisplay();
-    }
+    public void RemoveAnswer(AnswerOption a) => answers.Remove(a);
 
-    // 更新金币显示
-    private void UpdateCoinDisplay()
-    {
-        if (coinText != null)
-        {
-            coinText.text = $" {coins}";
-        }
-    }
+    void UpdateCoin() => coinText.text = coins.ToString();
 
-    // 对所有我方战士施加攻击力减弱效果
-    private void ApplyPenaltyToAllWarriors()
+    void ApplyPenalty()
     {
-        var warriors = FindObjectsOfType<Warrior>();
-        foreach (Warrior warrior in warriors)
-        {
-            if (!warrior.IsEnemy && !penalizedWarriors.Contains(warrior))
+        foreach (var w in FindObjectsOfType<Warrior>())
+            if (!w.IsEnemy && !penalized.Contains(w))
             {
-                warrior.ApplyDamagePenalty(wrongAnswerPenalty);
-                penalizedWarriors.Add(warrior);
+                w.ApplyDamagePenalty(wrongPenalty);
+                penalized.Add(w);
             }
-        }
     }
 
-    // 重置所有战士的攻击力
-    private void ResetAllWarriorsPenalties()
+    void ResetPenalties()
     {
-        foreach (Warrior warrior in penalizedWarriors.ToList())
-        {
-            if (warrior != null)
-            {
-                warrior.ResetDamagePenalty();
-            }
-        }
-        penalizedWarriors.Clear();
+        foreach (var w in penalized) if (w) w.ResetDamagePenalty();
+        penalized.Clear();
     }
 
-    // 当敌人死亡时调用
-    public void OnEnemyDeath(Vector3 position, int enemyValue)
+    public void OnEnemyDeath(Vector3 pos, int _)
     {
-        lastEnemyDeathPosition = position;
-        enemyDeathCount++;
-
-        // 每死两个敌人生成一个答案
-        if (enemyDeathCount >= 2)
+        lastEnemyPos = pos;
+        if (++deathCount >= 2)
         {
-            GenerateAnswerOption();
-            enemyDeathCount = 0; // 重置计数
+            SpawnAnswer();
+            deathCount = 0;
         }
     }
 
-    // 生成单个答案选项
-    private void GenerateAnswerOption()
+    void SpawnAnswer()
     {
-        // 如果场上答案数量超过限制,移除最旧的答案
-        if (activeAnswers.Count >= maxAnswersOnScreen)
+        if (answers.Count >= maxAnswers) RemoveOldest();
+        int val = Random.value < correctChance ? currentAnswer : Mathf.Clamp(currentAnswer + Random.Range(-3, 4), 1, 20);
+        Vector3 p = lastEnemyPos + Quaternion.Euler(0, Random.Range(0, 360f), 0) * (Vector3.forward * Random.Range(minSpawnDist, spawnRadius));
+        var obj = Instantiate(answerPrefab, p, Quaternion.identity);
+        var opt = obj.GetComponent<AnswerOption>();
+        if (opt)
         {
-            RemoveOldestAnswer();
+            opt.Initialize(this, val, val == currentAnswer);
+            answers.Add(opt);
         }
-
-        // 生成答案值
-        int answerValue = GenerateAnswerValue();
-        
-        // 计算生成位置
-        Vector3 spawnPosition = CalculateSpawnPosition();
-
-        // 生成答案选项
-        SpawnAnswerOption(answerValue, spawnPosition);
-        if (!PlayerPrefs.HasKey("FirstQuizTutorial"))
-        {
-            PlayerPrefs.SetInt("FirstQuizTutorial", 1);
-            var Tutorial =FindObjectOfType<Tutorial>();
-            Tutorial.ShowQuizTutorial(answerPrefab.transform);
-        }
-    }
-
-    private void RemoveOldestAnswer()
-    {
-        if (activeAnswers.Count > 0)
+        else
         {
-            AnswerOption oldestAnswer = activeAnswers[0];
-            activeAnswers.RemoveAt(0);
-            if (oldestAnswer != null)
-            {
-                Destroy(oldestAnswer.gameObject);
-            }
+            Destroy(obj);
         }
-    }
-
-    private int GenerateAnswerValue()
-    {
-        bool isCorrect = Random.value < correctAnswerChance;
-        if (isCorrect)
+        // 新手引导
+        if (!PlayerPrefs.HasKey("FirstQuizTutorial"))
         {
-            return currentAnswer;
+            PlayerPrefs.SetInt("FirstQuizTutorial", 1);
+            var tut = FindObjectOfType<Tutorial>();
+            if (tut) tut.ShowQuizTutorial(answerPrefab.transform);
         }
-
-        int difference = Random.Range(-3, 4);
-        int wrongAnswer = currentAnswer + difference;
-        return Mathf.Clamp(wrongAnswer, 1, 20);
-    }
-
-    private Vector3 CalculateSpawnPosition()
-    {
-        float randomAngle = Random.Range(0f, 360f);
-        float randomRadius = Random.Range(minAnswerDistance, answerSpawnRadius);
-        float x = Mathf.Cos(randomAngle * Mathf.Deg2Rad) * randomRadius;
-        float z = Mathf.Sin(randomAngle * Mathf.Deg2Rad) * randomRadius;
-        return lastEnemyDeathPosition + new Vector3(x, 0f, z);
     }
 
-    private void SpawnAnswerOption(int answerValue, Vector3 position)
+    void RemoveOldest()
     {
-        GameObject answerObj = Instantiate(answerPrefab, position, Quaternion.identity);
-        AnswerOption answerOption = answerObj.GetComponent<AnswerOption>();
-        
-        if (answerOption != null)
-        {
-            bool isCorrect = answerValue == currentAnswer;
-            answerOption.Initialize(this, answerValue, isCorrect);
-            activeAnswers.Add(answerOption);
-        }
-        else
+        if (answers.Count > 0)
         {
-            Debug.LogError("MathQuizManager: AnswerOption component not found on prefab!");
-            Destroy(answerObj);
+            var oldest = answers[0];
+            answers.RemoveAt(0);
+            if (oldest) Destroy(oldest.gameObject);
         }
     }
 } 

+ 6 - 28
Assets/Scripts/SoldierManager.cs

@@ -1,42 +1,20 @@
 using UnityEngine;
-using System.Collections.Generic;
-
 public class SoldierManager : MonoBehaviour
 {
-    private float baseAttackPower = 100f;    // 基础攻击力
-    private float currentAttackPower;        // 当前攻击力
-    public GameObject answerPrefab;          // 答案选项预制体
+    private float baseAttackPower = 100f;
+    private float currentAttackPower;
 
-    void Start()
-    {
-        currentAttackPower = baseAttackPower;
-    }
+    void Start() { currentAttackPower = baseAttackPower; }
 
-    // 应用攻击力减弱
-    public void ApplyAttackPenalty(float penaltyPercentage)
+    public void ApplyAttackPenalty(float percent)
     {
-        currentAttackPower = baseAttackPower * (1f - penaltyPercentage);
+        currentAttackPower = baseAttackPower * (1f - percent);
     }
 
-    // 重置攻击力
     public void ResetAttackPower()
     {
         currentAttackPower = baseAttackPower;
     }
 
-    // 获取当前攻击力
-    public float GetCurrentAttackPower()
-    {
-        return currentAttackPower;
-    }
-
-    // 当敌人被击杀时生成答案选项
-    public void OnEnemyKilled(Vector3 position)
-    {
-        if (answerPrefab != null)
-        {
-            // 在敌人死亡位置生成答案选项
-            Instantiate(answerPrefab, position, Quaternion.identity);
-        }
-    }
+    public float GetCurrentAttackPower() => currentAttackPower;
 }