Roman 5a5a0e220b 任务:替换美术素材,实装动画
1.替换一些美术素材
(1.替换炸弹贴图

2.实装一些新动画
(1.制作地藏之手拿钱的时候的动画
(2.制作爱欲品小怪动画
(3.制作伊斯兰小怪动画
(4.制作玩家开始交互和交互中动画
(5.制作镰刀飞行动画
(6.制作男童动画

*.优化和修复
(1.使木马喷射炸弹时,炸弹有扭矩
2021-12-17 23:33:40 +08:00

630 lines
22 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using DG.Tweening;
using Sirenix.OdinInspector;
/// <summary>
/// 玩家类,控制玩家相关的东西
/// </summary>
public class MyPlayer : MonoBehaviour, Boomer.I_CanBeBoomedObj
{
// _____ _ _ _
// | __ \ | | | (_)
// | |__) | _| |__ | |_ ___
// | ___/ | | | '_ \| | |/ __|
// | | | |_| | |_) | | | (__
// |_| \__,_|_.__/|_|_|\___|
[Header("玩家平时地面移动的速度")][FoldoutGroup("属性")]
public float speed = 10f;
[Header("玩家跳跃力度的大小")][FoldoutGroup("属性")]
public float jumpForce = 10f;
[FoldoutGroup("CD")][Header("挥动锤子的CD时长")]
public float hammerCD = 1f;
[FoldoutGroup("CD")][Header("发射镰刀的CD时长")]
public float sickleCD = 10f;
[Header("镰刀游戏物体")][FoldoutGroup("预制体")]
public GameObject sicklePrefab;
public enum AtkMethod{,,};
/// <summary>
/// 生命值上限
/// </summary>
[FoldoutGroup("属性")][Header("生命值上限")]
public float HP;
/// <summary>
/// 被击飞后的飞行方向的调整值
/// </summary>
[Header("被攻击后击飞的力度调整值")][FoldoutGroup("其他",false,0)]
public Vector2 hitToflyParameter;
/// <summary>
/// 攻击方式的倍率列表
/// </summary>
[DictionaryDrawerSettings()][Header("攻击方式的倍率列表")][ShowInInspector][FoldoutGroup("其他",false,0)]
public static Dictionary<AtkMethod,int> atkMethodMagnification;
/// <summary>
/// 记录此时自己是否被爱欲品缠抱
/// </summary>
[Header("被缠抱了吗?")][SerializeField][ReadOnly][FoldoutGroup("状态")]
public bool isCatching = false;
/// <summary>
/// 正抓着玩家的爱欲品
/// </summary>
[HideInInspector]
public AiYuPin catingAiYuPin;
/// <summary>
/// 玩家此时捕捉着的可交互物体
/// </summary>
[Header("玩家此时捕捉着的可交互物体")][FoldoutGroup("状态")][ReadOnly]
public Interactive catching;
/// <summary>
/// 当前身上有多少特殊硬币,用来塞钱的那种
/// </summary>
[FoldoutGroup("状态")][Header("当前身上有多少特殊硬币,用来塞钱的那种")]
public int specialMoneyCount = 0;
/// <summary>
/// 此时是否受着撞钟攻击的影响?
/// </summary>
[Header("此时是否受着撞钟攻击的影响?")][FoldoutGroup("状态")][ReadOnly]
public bool isAnnoying = false;
// _____ _ _
// | __ \ (_) | |
// | |__) | __ ___ ____ _| |_ ___
// | ___/ '__| \ \ / / _` | __/ _ \
// | | | | | |\ V / (_| | || __/
// |_| |_| |_| \_/ \__,_|\__\___|
private Rigidbody2D m_rigidbody;//自身刚体组件
[SerializeField][ReadOnly][FoldoutGroup("状态")]
private int inputDir;//当前输入方向,-1左1右0静止
[SerializeField][ReadOnly][FoldoutGroup("状态")]
private bool isLanding;//记录自己当前是否着地
private DOTweenAnimation wavingAnimation;//锤子挥动动画组件
private SpriteRenderer hammerSprite;//锤子的图片组件
private BoxCollider2D hammerCollider;//锤子的碰撞体
[FoldoutGroup("CD")][Header("挥动锤子的CD还剩多长时间")][SerializeField][ReadOnly]
private float hammerCDLeft = 0f;
[FoldoutGroup("CD")][Header("发射镰刀的CD还剩多长时间")][SerializeField][ReadOnly]
private float sickleCDLeft = 0f;
/// <summary>
/// 面部朝向,-1为左,1为右
/// </summary>
private int faceDir = 1;//面部朝向
private Transform sickleFirePoint;//镰刀发射点的transform
private Transform sickleClearerL;//左边的镰刀清除触发器
private Transform sickleClearerR;//右边的镰刀清除触发器
[FoldoutGroup("状态",false,1)][Header("玩家现在是否处于控制状态下(物理)")][SerializeField][ReadOnly]
private bool inControl = true;
[SerializeField][ReadOnly][ProgressBar(0,10,0.15f,0.47f,0.74f)][FoldoutGroup("状态")]
private float HPLeft;
/// <summary>
/// 自身动画控制器组件
/// </summary>
private Animator m_Animator;
/// <summary>
/// 是否在跳跃状态
/// </summary>
private bool isJumping;
/// <summary>
/// 是否在下落
/// </summary>
private bool isFalling;
/// <summary>
/// 是否在攻击
/// </summary>
private bool isAttacking;
/// <summary>
/// 是否在丢镰刀
/// </summary>
private bool isThrowing;
private VibrationManager vibrationManager;
/// <summary>
///反击侦察器组件
/// </summary>
private CounterScout counterScout;
/// <summary>
/// 此时自己是否正在与物体交互
/// </summary>
[Header("此时自己是否正在与物体交互")][ReadOnly][SerializeField][FoldoutGroup("状态")]
private bool isInteractive = false;
// _____ _ _ ____ _
// / ____| | | | _ \ | |
// | | __ _| | | |_) | __ _ ___| | __
// | | / _` | | | _ < / _` |/ __| |/ /
// | |___| (_| | | | |_) | (_| | (__| <
// \_____\__,_|_|_|____/ \__,_|\___|_|\_\
void Start()
{
Init();//初始化一些参数
}
void Update()
{
CountCD();
ChangeAnimator();
}
void FixedUpdate()
{
Move();//处理水平移动
}
// _ _ _
// | \ | | | |
// | \| | ___ _ __ _ __ ___ __ _| |
// | . ` |/ _ \| '__| '_ ` _ \ / _` | |
// | |\ | (_) | | | | | | | | (_| | |
// |_| \_|\___/|_| |_| |_| |_|\__,_|_|
//初始化函数
private void Init()
{
//找到自己身上的组件和需要的游戏物体
m_rigidbody = GetComponent<Rigidbody2D>();
wavingAnimation = transform.Find("锤子的旋转中心").GetComponent<DOTweenAnimation>();
hammerSprite = transform.Find("锤子的旋转中心").Find("锤子").GetComponent<SpriteRenderer>();
hammerCollider = transform.Find("锤子的旋转中心").Find("锤子").GetComponent<BoxCollider2D>();
sickleFirePoint = transform.Find("镰刀发射点");
sickleClearerL = transform.Find("镰刀飞出消除触发器左");
sickleClearerL.gameObject.AddComponent<SickleClearer>();
sickleClearerR = transform.Find("镰刀飞出消除触发器右");
sickleClearerR.gameObject.AddComponent<SickleClearer>();
m_Animator = GetComponent<Animator>();
vibrationManager = FindObjectOfType<VibrationManager>();
counterScout = gameObject.AddComponent<CounterScout>();
//初始化生命值
HPLeft = HP;
//初始化攻击倍率字典
atkMethodMagnification = new Dictionary<AtkMethod, int>();
atkMethodMagnification.Add(AtkMethod.,1);
atkMethodMagnification.Add(AtkMethod.,1);
atkMethodMagnification.Add(AtkMethod.,2);
}
//移动函数,每帧运行一次,处理水平方向移动
private void Move()
{
//只有不受击\不攻击的情况下可以移动
if(inControl && !isAttacking){
//直接修改刚体速度
m_rigidbody.velocity = new Vector2(inputDir * speed,//水平方向以输入方向乘以预设速度大小
m_rigidbody.velocity.y);//垂直方向不变
}
if(isInteractive){
m_rigidbody.velocity = Vector2.zero;
}
}
//计算CD的函数每帧调用
private void CountCD()
{
if(hammerCDLeft > 0) hammerCDLeft -= Time.deltaTime;
if(sickleCDLeft > 0) sickleCDLeft -= Time.deltaTime;
}
/// <summary>
/// 转身的时候触发
/// </summary>
private void TurnAround()
{
faceDir = inputDir;
transform.localScale = new Vector3( //x乘-1以显示转身
transform.localScale.x * -1,
//y、z不变
transform.localScale.y, transform.localScale.z);
}
/// <summary>
/// 被击飞的时候Call这个
/// </summary>
/// <param name="dir">被击方向</param>
public void BeHitToFly(int dir)
{
m_rigidbody.velocity = Vector2.zero;
m_rigidbody.velocity += new Vector2(
-1 * dir * hitToflyParameter.x,
hitToflyParameter.y
);
}
/// <summary>
/// 每Update调用处理状态机全部放这里
/// </summary>
protected void ChangeAnimator()
{
//移动动画
if (inputDir == 0) m_Animator.SetBool("isWalking", false);
else if(!isInteractive)m_Animator.SetBool("isWalking", true);
//跳跃动画
m_Animator.SetBool("isJumping",isJumping);
//下落动画
if(m_rigidbody.velocity.y < 0 && !isLanding){
m_Animator.SetBool("isFalling",true);
isJumping = false;
}
if(isLanding) {isFalling = false;m_Animator.SetBool("isFalling",isFalling);}
//锤子攻击动画
m_Animator.SetBool("isAttacking",isAttacking);
//记录着地
m_Animator.SetBool("isLanding",isLanding);
//被击飞动画触发
m_Animator.SetBool("isBeHitting",!inControl);
//丢出镰刀动画
m_Animator.SetBool("isThrowing",isThrowing);
//交互动画
m_Animator.SetBool("isInteractive",isInteractive);
}
/// <summary>
/// 被爱欲品抓住时用协程触发
/// </summary>
private void CatchingHarm(){
HPLeft -= FindObjectOfType<AiYuPin>().ATK;
}
/// <summary>
/// 塞钱
/// </summary>
private void GiveMoney(){
specialMoneyCount--;
}
/// <summary>
/// 捡到钱了
/// </summary>
private void IPickedACoin(){
specialMoneyCount++;
}
// _____ _ _ _ _
// / ____| | | (_) (_)
// | | ___ | | |_ ___ _ ___ _ __
// | | / _ \| | | / __| |/ _ \| '_ \
// | |___| (_) | | | \__ \ | (_) | | | |
// \_____\___/|_|_|_|___/_|\___/|_| |_|
private void OnCollisionEnter2D(Collision2D collision)//当有物体碰上
{
if(collision.transform.tag == "地面")
{isLanding = true;//若碰撞物体标签为地面,标记自身着地
if(!isCatching)inControl = true;}
}
private void OnCollisionExit2D(Collision2D collision)//当有碰撞体离开
{
if(collision.transform.tag == "地面" && (isJumping || !inControl))
{isLanding = false;}//若碰撞物体标签为地面,标记自身未着地
}
// 以下为操作监听事件
// _____ _ _____ _
// |_ _| | | / ____| | |
// | | _ __ _ __ _ _| |_| (___ _ _ ___| |_ ___ _ __ ___
// | | | '_ \| '_ \| | | | __|\___ \| | | / __| __/ _ \ '_ ` _ \
// _| |_| | | | |_) | |_| | |_ ____) | |_| \__ \ || __/ | | | | |
// |_____|_| |_| .__/ \__,_|\__|_____/ \__, |___/\__\___|_| |_| |_|
// | | __/ |
// |_| |___/
public void OnMove(InputAction.CallbackContext context)//OnMove事件
{
//决定输入方向inputDir
if(!context.ReadValue<float>().Equals(0))
inputDir = (context.ReadValue<float>() > 0) ? 1 : -1;
else inputDir = 0;
if(faceDir * inputDir < 0){
if(inControl && !isAttacking)TurnAround();
if(isCatching && context.started){
catingAiYuPin.OnBreakFree();
Debug.Log("挣脱");
}
}
}
public void OnJump(InputAction.CallbackContext context)//OnJump事件
{
//当按下跳跃键
if(context.performed)
{
if(isLanding && inControl){//如果当前着地
//给予自身刚体
m_rigidbody.velocity = new Vector2(m_rigidbody.velocity.x,//水平方向速度不变
jumpForce);//垂直方向给予预设跳跃速度
//标记自身正在跳跃
isJumping = true;
vibrationManager.ShakeScream(Vector2.up,0.5f);
StartCoroutine(vibrationManager.ShakePad(0.1f,0.2f,0.2f,VibrationManager.PadShakeitem.));
}
}
}
public void OnWave(InputAction.CallbackContext context)
{
//当执行Wave动作
if (context.performed && hammerCDLeft <= 0)
{
hammerSprite.DOFade(1, 0f);//把锤子显示Debug用后期请删除
hammerCollider.enabled = true;//打开锤子碰撞体
wavingAnimation.DOPlay();//播放挥动锤子动画
hammerCDLeft = hammerCD;//挥动成功重置CD剩余时间
if(!isAttacking)isAttacking = true;
//空挥轻微震动手柄
StartCoroutine(
vibrationManager.ShakePad(0.1f,0.1f,0.2f,VibrationManager.PadShakeitem.)
);
//检查是否有可反击的炸弹
if(counterScout.catchingBoomer != null && faceDir == -1)
{
//有则执行炸弹的反击功能
counterScout.catchingBoomer.Vengeance();
//剧烈震动手柄
StartCoroutine(vibrationManager.ShakePad(0.8f,0.2f,0.2f,VibrationManager.PadShakeitem.));
}
}
}
//检测到 镰刀 按键的时候触发
public void OnSickle(InputAction.CallbackContext context)
{
//按下就触发 CD好了 玩家处于控制状态
if(context.started && sickleCDLeft <= 0 && inControl){
//实例化一个镰刀游戏物体
Sickle sickle = Instantiate(
sicklePrefab,
sickleFirePoint.position,
Quaternion.identity
).GetComponent<Sickle>();
//初始化镰刀
sickle.dir = faceDir;
//开始计算镰刀CD
sickleCDLeft = sickleCD;
//轻微震动手柄
StartCoroutine(
vibrationManager.ShakePad(
0.1f,0.1f,0.2f,VibrationManager.PadShakeitem.
)
);
//轻微震动屏幕
vibrationManager.ShakeScream(Vector2.right,0.2f);
//改变标记表示开始播放丢镰刀动画
isThrowing = true;
}
}
public void OnInteractive(InputAction.CallbackContext context){
//当按下交互键
if(context.performed && catching != null){
//根据所捕获物体的不同,区分一下操作
switch(catching.itemName){
case Interactive.ItemName. :
if(
specialMoneyCount > 0 &&
!FindObjectOfType<MoneyBox>().hasMoney
){
catching.OnCall();
GiveMoney();
}
break;
case Interactive.ItemName. :
IPickedACoin();
catching.OnCall();
break;
case Interactive.ItemName. :
if(catching.RetuenState() == (int)Boy.State.wait){
catching.OnCall();
isInteractive = true;
}
break;
default :
catching.OnCall();
isInteractive = true;
break;
}
}
//当抬起交互键触发OnCallCancle
if(context.canceled && catching != null){
catching.OnCallCancel();
isInteractive = false;
}
}
// ______ _
// | ____| | |
// | |____ _____ _ __ | |_
// | __\ \ / / _ \ '_ \| __|
// | |___\ V / __/ | | | |_
// |______\_/ \___|_| |_|\__|
//当挥动锤子动画结束后触发
public void OnWaveEnd()
{
//为挥动动画倒带
wavingAnimation.DORewind();
//把锤子隐藏Debug用后期请删除
hammerSprite.DOFade(0,0f);
//关闭锤子的碰撞体
hammerCollider.enabled = false;
}
/// <summary>
/// 当玩家被打则Call这个函数
/// </summary>
/// <param name="atk">遭受的攻击力</param>
/// <param name="dir">攻击来源的方向,-1左1右</param>
public void OnBeHit(float atk, int dir)
{
//触发一个击飞
BeHitToFly(dir);
//标记自身不受控制
inControl = false;
//交互中断
isInteractive = false;
if(catching != null)
catching.OnCallCancel();
//掉血
HPLeft -= atk;
//震动屏幕和手柄
StartCoroutine(vibrationManager.ShakePad(0.8f,0.5f,0.2f,VibrationManager.PadShakeitem.));
vibrationManager.ShakeScream(new Vector2(dir,1),1f);
}
/// <summary>
/// 锤子攻击动画结尾Event调用
/// </summary>
public void StopAttacking(){isAttacking = false;
//解决面部朝向的问题
if(faceDir * inputDir < 0){
if(inControl && !isAttacking)TurnAround();
if(isCatching){catingAiYuPin.OnBreakFree();}
}
}
/// <summary>
/// 当玩家被爱欲品抓住后触发这个事件
/// </summary>
/// <param name="aiYuPin">这个爱欲品的爱欲品组件</param>
public void BeCatchedByAiYuPin(AiYuPin aiYuPin){
//标记自身正被抓着
isCatching = true;
//标记自身失去控制
inControl = false;
//每秒掉血,伤害量为爱欲品的攻击力
InvokeRepeating("CatchingHarm",0f,1f);
//去除刚体速度,防止滑行带来的位置偏移问题
m_rigidbody.velocity = Vector2.zero;
//记录正在抓着自己的爱欲品
catingAiYuPin = aiYuPin;
}
/// <summary>
/// 完全挣脱的时候从爱欲品Call过来
/// </summary>
public void BreakFreeCompletely(){
//取消被抓住的标记
isCatching = false;
//恢复移动操控
inControl = true;
//取消掉血协程
CancelInvoke("CatchingHarm");
//去掉记录着的抓住玩家的爱欲品
catingAiYuPin = null;
//消除正在攻击状态以解决Bug
isAttacking = false;
}
//脚着地的时候触发,通过状态机调用
public void OnFootTap(){
StartCoroutine(vibrationManager.ShakePad(0f,0.02f,0.05f,VibrationManager.PadShakeitem.));
}
//镰刀攻击结尾调用,清除镰刀攻击状态防止多次触发动画
public void OnThrowingEnd(){isThrowing = false;}
/// <summary>
/// 被撞钟攻击的开始瞬间触发
/// </summary>
public void OnInAnnoying(){
Debug.Log("我被干扰了");
//标记自身正在被影响
isAnnoying = true;
//减速减益
speed *= 0.5f;
}
/// <summary>
/// 当离开撞钟攻击范围的时候触发一次
/// </summary>
public void OnOutAnnoying(){
Debug.Log("我脱离了干扰");
//标记自身离开影响
isAnnoying = false;
//恢复减速减益
speed *= 2f;
}
/// <summary>
/// 当交互中断,从可交互物体触发
/// </summary>
public void OnInteractiveException(){
Debug.Log("我超!什么玩意");
isInteractive = false;
}
/// <summary>
/// 当有男童被救从男童触发
/// </summary>
/// <param name="boy"></param>
public void OnSave(Boy boy){
isInteractive = false;
}
// _____ _ __
// |_ _| | | / _|
// | | _ __ | |_ ___ _ __| |_ __ _ ___ ___
// | | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \
// _| |_| | | | || __/ | | || (_| | (_| __/
// |_____|_| |_|\__\___|_| |_| \__,_|\___\___|
public void BeBoomed(float atk, int dir, Boomer boomer){
OnBeHit(atk,dir);
}
public Transform ObjTransform(){return transform;}
// _______ _ _____ _
// |__ __| | |/ ____| |
// | | ___ ___ | | | | | __ _ ___ ___
// | |/ _ \ / _ \| | | | |/ _` / __/ __|
// | | (_) | (_) | | |____| | (_| \__ \__ \
// |_|\___/ \___/|_|\_____|_|\__,_|___/___/
private class SickleClearer : MonoBehaviour
{
//一个工具小插件,单独写脚本实在太浪费,所以在这里写一下。
//当触发器检测到有东西进入,会试图获取它身上的镰刀脚本,如果有就说明镰刀到屏幕边缘了,把这个镰刀删除
//没有的话说明是其他物体,不作处理
void OnTriggerEnter2D(Collider2D other)
{
if(other.TryGetComponent<Sickle>(out Sickle temp))
Destroy(temp.gameObject);
}
}
/// <summary>
/// 反击侦察器,玩家的工具类
/// </summary>
private class CounterScout : MonoBehaviour
{
/// <summary>
/// 正捕获着的炸弹
/// </summary>
public Boomer catchingBoomer;
void OnTriggerEnter2D(Collider2D other){
//如果可捕获的炸弹进入捕获范围
if(other.TryGetComponent<Boomer>(out Boomer temp) &&
temp.isThisCanBeReturned){
//则记录下这个炸弹
catchingBoomer = temp;
}
}
void OnTriggerExit2D(Collider2D other){
//如果捕获着的炸弹离开,清空记录
if(other.TryGetComponent<Boomer>(out Boomer temp) &&
temp == catchingBoomer){
catchingBoomer = null;
}
}
}
}