diff --git a/Assets/Scenes/test.unity b/Assets/Scenes/test.unity index 7288358..c3b912a 100644 --- a/Assets/Scenes/test.unity +++ b/Assets/Scenes/test.unity @@ -463,7 +463,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 326335321} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -0.9, y: -0.8, z: 0} + m_LocalPosition: {x: -8.16, y: -0.8, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 321454206} @@ -629,7 +629,7 @@ MonoBehaviour: speed: 10 jumpForce: 20 hammerCD: 1 - sickleCD: 10 + sickleCD: 0 sicklePrefab: {fileID: 8280362330273855463, guid: 2e2fb120ae20d5e4faaad5a2a2fcca30, type: 3} HP: 10 hitToflyParameter: {x: 10, y: 10} @@ -1107,7 +1107,7 @@ MonoBehaviour: m_PersistentCalls: m_Calls: [] delay: 0 - duration: 3 + duration: 8 easeType: 1 easeCurve: serializedVersion: 2 @@ -1143,7 +1143,7 @@ MonoBehaviour: autoPlay: 1 autoKill: 0 relative: 0 - isLocal: 0 + isLocal: 1 isClosedPath: 1 pathResolution: 10 pathMode: 3 @@ -1153,28 +1153,58 @@ MonoBehaviour: upDirection: {x: 0, y: 1, z: 0} tweenRigidbody: 0 wps: - - {x: 8.32342, y: -1.0342596, z: 0} + - {x: 1.410517, y: -1.0342596, z: 0} fullWps: [] path: wpLengths: - 0 - - 3.503422 - - 3.503422 + - 4.030519 + - 4.030519 wps: - - {x: 4.82, y: -1.03, z: 0} - - {x: 8.32342, y: -1.0342596, z: 0} - - {x: 4.82, y: -1.03, z: 0} + - {x: -2.62, y: -1.03, z: 0} + - {x: 1.410517, y: -1.0342596, z: 0} + - {x: -2.62, y: -1.03, z: 0} type: 0 subdivisionsXSegment: 10 subdivisions: 30 controlPoints: [] - length: 7.006844 + length: 8.061038 isFinalized: 1 timesTable: - 0 - 0.5 - 1 - lengthsTable: [] + lengthsTable: + - 0.044636283 + - 0.17024052 + - 0.36435583 + - 0.6145263 + - 0.9082949 + - 1.2332048 + - 1.5767996 + - 1.9266229 + - 2.2702177 + - 2.5951276 + - 2.8888958 + - 3.1390667 + - 3.3331816 + - 3.4587862 + - 3.503422 + - 3.5480578 + - 3.6736624 + - 3.8677778 + - 4.117948 + - 4.411716 + - 4.7366266 + - 5.0802217 + - 5.430045 + - 5.77364 + - 6.09855 + - 6.3923187 + - 6.642488 + - 6.8366036 + - 6.9622073 + - 7.0068436 inspectorMode: 0 pathType: 0 handlesType: 0 @@ -1182,9 +1212,9 @@ MonoBehaviour: handlesDrawMode: 0 perspectiveHandleSize: 0.5 showIndexes: 1 - showWpLength: 0 + showWpLength: 1 pathColor: {r: 1, g: 1, b: 1, a: 0.5} - lastSrcPosition: {x: 4.82, y: -1.03, z: 0} + lastSrcPosition: {x: -2.62, y: -1.03, z: 0} lastSrcRotation: {x: 0, y: 0, z: 0, w: 1} wpsDropdown: 1 dropToFloorOffset: 0 @@ -1200,11 +1230,16 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2127494698a58b642b7d3ec5f92f8974, type: 3} m_Name: m_EditorClassIdentifier: - HP: 0 + HP: 3 ATK: 1 + speed: 1 coin: 0 HPLeft: 0 state: 0 + hitToflyParameter: {x: 3, y: 3} + deadRotationRangeMax: 500 + deadRotationRangeMin: 500 + inPath: 1 --- !u!4 &1478051114 Transform: m_ObjectHideFlags: 0 @@ -1213,7 +1248,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1478051109} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 4.82, y: -1.03, z: 0} + m_LocalPosition: {x: -2.62, y: -1.03, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 0} diff --git a/Assets/Scripts/Enemy.cs b/Assets/Scripts/Enemy.cs index f41904f..36953de 100644 --- a/Assets/Scripts/Enemy.cs +++ b/Assets/Scripts/Enemy.cs @@ -19,25 +19,24 @@ public class Enemy : MonoBehaviour /// /// 生命值上限 /// - [BoxGroup("属性")][Header("生命值上限")] + [FoldoutGroup("属性")][Header("生命值上限")] public float HP; /// /// 攻击力 /// - [BoxGroup("属性")][Header("攻击力")] + [FoldoutGroup("属性")][Header("攻击力")] public float ATK; /// /// 速度 /// - [BoxGroup("属性")] - public float speed{get{return speed;} set{speed = value;}} - + [FoldoutGroup("属性")][Header("移动速度")] + public float speed; /// /// 打死后掉多少金币 /// - [BoxGroup("属性")][Header("掉落金币数")] + [FoldoutGroup("属性")][Header("掉落金币数")] public int coin; /// @@ -55,13 +54,13 @@ public class Enemy : MonoBehaviour /// /// 当前生命值 /// - [ReadOnly][SerializeField][ProgressBar(0,10,0.15f,0.47f,0.74f)][BoxGroup("状态")] + [ReadOnly][SerializeField][ProgressBar(0,10,0.15f,0.47f,0.74f)][FoldoutGroup("状态")] protected float HPLeft; /// /// 当前状态 /// - [EnumPaging][SerializeField][ReadOnly][Header("当前状态")][BoxGroup("状态")] + [EnumPaging][SerializeField][ReadOnly][Header("当前状态")][FoldoutGroup("状态")] protected State state; // ______ _ @@ -74,7 +73,7 @@ public class Enemy : MonoBehaviour /// /// 当怪物死的时候Call这个函数 /// - protected void OnDead(){} + protected virtual void OnDead(){} /// /// 当怪物触碰到玩家的时候Call这个 @@ -86,12 +85,28 @@ public class Enemy : MonoBehaviour /// /// 攻击方式,枚举类型,具体看MyPlayer /// 受击方向,-1左,1右 - protected void OnBeHit(MyPlayer.AtkMethod hitMethod,int hitDir){} + protected virtual void OnBeHit(MyPlayer.AtkMethod hitMethod,int hitDir){} /// /// 当怪物发现玩家的时候Call这个 /// protected void OnFindThePlayer(){} + /// + /// 当怪物着地的时候触发一次 + /// + protected virtual void OnRetouchedTheGround(){} + + // _ _ _ + // | \ | | | | + // | \| | ___ _ __ _ __ ___ __ _| | + // | . ` |/ _ \| '__| '_ ` _ \ / _` | | + // | |\ | (_) | | | | | | | | (_| | | + // |_| \_|\___/|_| |_| |_| |_|\__,_|_| + + /// + /// 看看死了没 + /// + protected bool CheckDead(){return !(HPLeft > 0);} // _____ _ _ _ _ @@ -104,6 +119,19 @@ public class Enemy : MonoBehaviour { if(other.gameObject.TryGetComponent(out MyPlayer player)) {OnTouchThePlayer(player);}//如果创到的是玩家,则Call事件 + //如果被镰刀创到,Call一下OnBeHit事件,传入攻击方式和攻击来袭方向 + else if(other.gameObject.TryGetComponent(out Sickle sickle)) + {OnBeHit(MyPlayer.AtkMethod.镰刀, + (transform.position.x - + sickle.transform.position.x > 0) ? -1 : 1); + Destroy(sickle.gameObject);} + //如果被锤子锤到,和上面一样 + else if(other.gameObject.TryGetComponent(out Hammer hammer)) + {OnBeHit(MyPlayer.AtkMethod.锤子, + (transform.position.x - + hammer.transform.position.x > 0) ? -1 : 1);} + else if(other.gameObject.tag == "地面") + {OnRetouchedTheGround();} } protected void OnTriggerEnter2D(Collider2D other) { diff --git a/Assets/Scripts/Hammer.cs b/Assets/Scripts/Hammer.cs new file mode 100644 index 0000000..13823f7 --- /dev/null +++ b/Assets/Scripts/Hammer.cs @@ -0,0 +1,8 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Hammer : MonoBehaviour +{ + +} diff --git a/Assets/Scripts/Hammer.cs.meta b/Assets/Scripts/Hammer.cs.meta new file mode 100644 index 0000000..8bb11ec --- /dev/null +++ b/Assets/Scripts/Hammer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8542bc5f7711d44d8c471ae7ca4eb87 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/MyPlayer.cs b/Assets/Scripts/MyPlayer.cs index ccb3aca..f696c6a 100644 --- a/Assets/Scripts/MyPlayer.cs +++ b/Assets/Scripts/MyPlayer.cs @@ -30,11 +30,11 @@ public class MyPlayer : MonoBehaviour public float speed = 10f; [Header("玩家跳跃力度的大小")][FoldoutGroup("Info")] public float jumpForce = 10f; - [BoxGroup("CD")][Header("挥动锤子的CD时长")] + [FoldoutGroup("CD")][Header("挥动锤子的CD时长")] public float hammerCD = 1f; - [BoxGroup("CD")][Header("发射镰刀的CD时长")] + [FoldoutGroup("CD")][Header("发射镰刀的CD时长")] public float sickleCD = 10f; - [Header("镰刀游戏物体")][BoxGroup("预制体")] + [Header("镰刀游戏物体")][FoldoutGroup("预制体")] public GameObject sicklePrefab; public enum AtkMethod{镰刀,锤子,反弹炸弹}; /// @@ -47,6 +47,11 @@ public class MyPlayer : MonoBehaviour /// [Header("被攻击后击飞的力度调整值")][FoldoutGroup("其他",false,0)] public Vector2 hitToflyParameter; + /// + /// 攻击方式的倍率列表 + /// + [DictionaryDrawerSettings()][Header("攻击方式的倍率列表")][ShowInInspector][FoldoutGroup("其他",false,0)] + public static Dictionary atkMethodMagnification; // _____ _ _ // | __ \ (_) | | @@ -63,9 +68,9 @@ public class MyPlayer : MonoBehaviour private DOTweenAnimation wavingAnimation;//锤子挥动动画组件 private SpriteRenderer hammerSprite;//锤子的图片组件 private BoxCollider2D hammerCollider;//锤子的碰撞体 - [BoxGroup("CD")][Header("挥动锤子的CD还剩多长时间")][SerializeField][ReadOnly] + [FoldoutGroup("CD")][Header("挥动锤子的CD还剩多长时间")][SerializeField][ReadOnly] private float hammerCDLeft = 0f; - [BoxGroup("CD")][Header("发射镰刀的CD还剩多长时间")][SerializeField][ReadOnly] + [FoldoutGroup("CD")][Header("发射镰刀的CD还剩多长时间")][SerializeField][ReadOnly] private float sickleCDLeft = 0f; private int faceDir = 1;//面部朝向 private Transform sickleFirePoint;//镰刀发射点的transform @@ -73,7 +78,7 @@ public class MyPlayer : MonoBehaviour private Transform sickleClearerR;//右边的镰刀清除触发器 [FoldoutGroup("其他",false,1)][Header("玩家现在是否处于控制状态下(物理)")][SerializeField][ReadOnly] private bool inControl = true; - [SerializeField][ReadOnly][ProgressBar(0,10,0.15f,0.47f,0.74f)] + [SerializeField][ReadOnly][ProgressBar(0,10,0.15f,0.47f,0.74f)][FoldoutGroup("Info")] private float HPLeft; // _____ _ _ ____ _ @@ -117,6 +122,10 @@ public class MyPlayer : MonoBehaviour sickleClearerR = transform.Find("镰刀飞出消除触发器右"); sickleClearerR.gameObject.AddComponent(); HPLeft = HP; + atkMethodMagnification = new Dictionary(); + atkMethodMagnification.Add(AtkMethod.镰刀,1); + atkMethodMagnification.Add(AtkMethod.锤子,1); + atkMethodMagnification.Add(AtkMethod.反弹炸弹,2); } //移动函数,处理水平方向移动 diff --git a/Assets/Scripts/NormalEnemy.cs b/Assets/Scripts/NormalEnemy.cs index f23c11a..6391d7e 100644 --- a/Assets/Scripts/NormalEnemy.cs +++ b/Assets/Scripts/NormalEnemy.cs @@ -1,14 +1,158 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +using DG.Tweening; +using Sirenix.OdinInspector; +/// +/// 普通怪物类,三关都有的那个 +/// public class NormalEnemy : Enemy { - protected override void OnTouchThePlayer(MyPlayer player) - { + // _____ _ _ _ + // | __ \ | | | (_) + // | |__) | _| |__ | |_ ___ + // | ___/ | | | '_ \| | |/ __| + // | | | |_| | |_) | | | (__ + // |_| \__,_|_.__/|_|_|\___| + + [Header("被攻击后击飞的力度调整值")][FoldoutGroup("其他",false,0)] + public Vector2 hitToflyParameter; + [FoldoutGroup("其他",false,0)][Header("怪物死后旋转速度的随机区间")] + public float deadRotationRangeMax; + [FoldoutGroup("其他",false,0)] + public float deadRotationRangeMin; + + // _____ _ _ + // | __ \ (_) | | + // | |__) | __ ___ ____ _| |_ ___ + // | ___/ '__| \ \ / / _` | __/ _ \ + // | | | | | |\ V / (_| | || __/ + // |_| |_| |_| \_/ \__,_|\__\___| + + protected Rigidbody2D m_rigidbody; + /// + /// 死的时候的受击朝向 + /// + protected int deadDir; + /// + /// 记录一下游戏开始时怪物的位置,方便被击飞后怪物重新回到巡逻起点 + /// + protected Vector3 sourcePosition; + protected DOTweenPath doTweenPath; + [SerializeField][ReadOnly][FoldoutGroup("状态")] + protected bool inPath = true; + /// + /// 现在正在执行的动画,在受击中断的时候用 + /// + private Tween tweenNow; + + // _____ _ _ ____ _ + // / ____| | | | _ \ | | + // | | __ _| | | |_) | __ _ ___| | __ + // | | / _` | | | _ < / _` |/ __| |/ / + // | |___| (_| | | | |_) | (_| | (__| < + // \_____\__,_|_|_|____/ \__,_|\___|_|\_\ + void Start(){Init();} + + // _ _ _ + // | \ | | | | + // | \| | ___ _ __ _ __ ___ __ _| | + // | . ` |/ _ \| '__| '_ ` _ \ / _` | | + // | |\ | (_) | | | | | | | | (_| | | + // |_| \_|\___/|_| |_| |_| |_|\__,_|_| + protected void Init(){ + //生命值初始化为满 + HPLeft = HP; + //Get插件 + doTweenPath = GetComponent(); + m_rigidbody = GetComponent(); + sourcePosition = transform.position; + //初始话目前播放的Tween动画为巡逻 + tweenNow = doTweenPath.tween; + } + + /// + /// 协程用,删除自己这个游戏物体 + /// + protected void Dead(){Destroy(gameObject);} + + /// + /// 被击飞的击飞效果处理 + /// + /// 被击方向 + public void BeHitToFly(int dir){ + m_rigidbody.velocity += new Vector2( //给予自身一个 + -1 * dir * hitToflyParameter.x,//X方向为力度系数乘以受击方向 + hitToflyParameter.y//Y方向为力度系数 + //的绝对的速度 + ); + } + + // ______ _ + // | ____| | | + // | |____ _____ _ __ | |_ + // | __\ \ / / _ \ '_ \| __| + // | |___\ V / __/ | | | |_ + // |______\_/ \___|_| |_|\__| + protected override void OnTouchThePlayer(MyPlayer player){ + //告诉玩家,你被攻击了 player.OnBeHit(ATK, ((transform.position.x - player.transform.position.x) - > 0) ? 1 : -1); + > 0) ? 1 : -1);//通过自身位置和玩家位置的比较来返回玩家本次的受击方向 + } + + protected override void OnBeHit(MyPlayer.AtkMethod hitMethod, int hitDir){ + //结束当前动画 + tweenNow.Pause(); + //让自己被击飞 + BeHitToFly(hitDir); + //修改标志表示自己当前不在Path中 + inPath = false; + //结算生命值 + HPLeft -= MyPlayer.atkMethodMagnification[hitMethod]; + //看下死了没 + //死了就记录下死亡时候的面部朝向,用来做死亡翻滚效果,然后再Call一下死亡事件 + if(CheckDead()) {deadDir = hitDir;OnDead();} + } + + protected override void OnRetouchedTheGround(){ + if(!inPath){//如果此时怪物没在巡逻且着地了,说明时被击飞然后着地了 + //新建一个动画,让怪物回到初始记录位置 + Tween tween = transform.DOMove(sourcePosition, + Mathf.Abs(sourcePosition.x - transform.position.x) / speed, + false); + //设置该动画插值方式为线性 + tween.SetEase(Ease.Linear); + //更改记录的此时正在执行的动画 + tweenNow = tween; + //写一个委托,插入这个新动画的结束事件 + TweenCallback myCallBack = () => + //结束说明回到了初始点,此时让怪物重新开始巡逻,同时更改记录中的正在执行的动画为巡逻 + {doTweenPath.DORestart(); tweenNow = doTweenPath.tween;}; + //插入写的委托 + tween.OnComplete(myCallBack); + //标记自身重新回到巡逻动画 + inPath = true; + //矫正一下faceDir的问题 + transform.rotation = Quaternion. + Euler + (transform.rotation.x, + ((sourcePosition.x - transform.position.x > 0) ? 0:-180), + transform.rotation.z); + } + } + + protected override void OnDead() + { + //标记当前状态为死亡 + state = State.dead; + //加一个扭矩,营造死亡的效果 + m_rigidbody.AddTorque(Random.Range(deadRotationRangeMin,deadRotationRangeMax) * deadDir); + //关掉自己的碰撞体 + GetComponent().enabled = false; + //两秒后自己毁灭 + Invoke("Dead",2f); } }