备份CatanBuilding瘦身独立工程

This commit is contained in:
JSD\13999
2026-05-26 16:15:54 +08:00
commit 2d0e6a61b7
12001 changed files with 2431925 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Calculate : MonoBehaviour
{
public float Height = 1;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// 按下tab键计算掉落用时
if (Input.GetKey(KeyCode.Tab))
{
float g = Mathf.Abs(Physics2D.gravity.y);
float t2 = 2 * Height / g;
float t = Mathf.Sqrt(t2);
Debug.Log("从高度 " + Height + " 米掉落,耗时 " + t + "s");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7cc79bb8cfbcf4d4cbd3902fa93772fc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(SpriteRenderer))]
public class MeasureSpriteRendererSize : MonoBehaviour
{
void Update()
{
// 按下空格键测量精灵的大小
if (Input.GetKey(KeyCode.M))
{
var spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
float boundX = spriteRenderer.bounds.size.x;
Debug.Log("Sprite " + this.gameObject.name + " size: " + spriteRenderer.bounds.size.ToString("F2"));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 987a607c41d3ecb43b2dfb3f2fe85bbb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c01c52b71f8ce8743bb4747e93435737
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
[RequireComponent(typeof(ParticleSystem))]
public class ParticleLayerController : MonoBehaviour
{
[Header("Renderer")]
[SerializeField] private Renderer m_ParentRenderer;
[SerializeField] private int m_SortingOrder = 100;
private Renderer m_Renderer;
// Start is called before the first frame update
void Start()
{
// 获取或添加粒子系统
var particleSystem = GetComponent<ParticleSystem>();
var m_Renderer = particleSystem.GetComponent<Renderer>();
// 设置排序层级
m_Renderer.sortingLayerName = m_ParentRenderer.sortingLayerName;
m_Renderer.renderingLayerMask = m_ParentRenderer.renderingLayerMask;
m_Renderer.sortingOrder = m_SortingOrder;
}
// Update is called once per frame
void Update()
{
if (m_Renderer != null)
{
m_Renderer.sortingOrder = m_SortingOrder;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5428880f000d05a44a0c833790098c15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,38 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class PinballCircularProgress : MonoBehaviour
{
#region progress
private float m_Progress = 0f;
public void SetProgress(float progress)
{
m_Progress = progress;
}
#endregion
#region
private Material m_Material;
// Start is called before the first frame update
void Start()
{
var renderer = GetComponent<SpriteRenderer>();
m_Material = renderer.material;
m_Progress = 0f;
}
// Update is called once per frame
void Update()
{
if (m_Material != null)
{
m_Material.SetFloat("_Progress", m_Progress);
}
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c0e650905608528419f710d539fa88b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,428 @@
using asap.core;
using Game;
using GameCore;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace game
{
public class PinballFiringPin : MonoBehaviour
{
[SerializeField] private Collider2D m_Collider2D;
[SerializeField] private PinballPellet m_PelletBase;
private EventPinballDataManager m_DataManager;
private PinballPellet m_Pellet;
private void CreateNewPellet()
{
if (m_PelletBase.gameObject.activeSelf == true)
{
m_PelletBase.gameObject.SetActive(false);
}
if (m_Pellet != null)
{
GameObject tmp = m_Pellet.gameObject;
tmp.SetActive(false);
GameObject.Destroy(tmp);
m_Pellet = null;
}
GameObject gameObject = Instantiate(m_PelletBase.gameObject, m_PelletBase.transform.position, m_PelletBase.transform.rotation, m_PelletBase.transform.parent);
m_Pellet = gameObject.GetComponent<PinballPellet>();
m_Pellet.gameObject.SetActive(true);
m_Pellet.InitPellet(m_RecordTimes);
FishingPinballAct.Publish(new EventPinballSetDummyPelletData()
{
Pellet = m_Pellet
});
}
#region
[Header("声音设置")]
[SerializeField] private AudioClip m_FiringPinPullAudioClip;
[SerializeField] private AssetReferenceT<AudioClip> m_FiringPinSpringAudioClip;
private Sound m_FiringPinPullSound;
public void PlayPullSound()
{
if (m_FiringPinPullSound != null)
{
m_FiringPinPullSound.audioSource.Play();
}
}
public void PlaySpringSound()
{
if (m_FiringPinPullSound != null)
{
m_FiringPinPullSound.audioSource.Stop();
}
GContext.Publish(new AssetReferenceAudioClip(m_FiringPinSpringAudioClip, time: 0f));
}
#endregion
#region
[Header("开关设置")]
[SerializeField] private Transform m_InitialTransform;
[SerializeField] private Transform m_FarthestTransform;
[SerializeField] private float m_ReturnSpeed = 50f; // 回弹速度
[SerializeField] private float m_DeferTime = 0.1f;
[SerializeField] private float m_ProtectedRatio = 0.1f;
//#if UNITY_EDITOR
[Header("物理设置/模拟数据设置")]
[SerializeField] private float m_MinForce = 7f;
[SerializeField] private float m_ForceStep = 0.0001f;
//#endif
private float m_MaxDragDistance = 0f; // 最大拖动距离
private float m_MaxDragDistancePositive = 0f; // 最大拖动距离
private Vector3 m_InitialPosition; // 初始位置
private Vector3 m_FarthestPosition; // 最远位置
private bool isDragging = false; // 拖动状态
private float m_LastTouchDownTime = -1f;
private Camera mainCamera; // 主摄像机
private void OnMouseDown()
{
isDragging = true;
m_LastTouchDownTime = Time.time;
PlayPullSound();
}
private void OnMouseDrag()
{
if (!isDragging) return;
// 将屏幕坐标转为世界坐标
Vector3 touchPos = mainCamera.ScreenToWorldPoint(Input.mousePosition);
touchPos.x = m_InitialPosition.x;
touchPos.z = m_InitialPosition.z; // 保持Z轴不变
// 计算允许移动的位置
Vector3 targetPos = m_InitialPosition;
float deltaY = Mathf.Clamp(
touchPos.y - m_InitialPosition.y,
m_MaxDragDistance,
0f
);
targetPos.y = m_InitialPosition.y + deltaY;
transform.position = targetPos;
float ratio = GetDragRatio();
FishingPinballAct.Publish(new EventPinballEnergyArrowData()
{
Energy = ratio
});
FishingPinballAct.Publish<EventPinballSpringUpdateData>(new EventPinballSpringUpdateData()
{
Ratio = 1.0f - ratio
});
}
private void OnMouseUp()
{
if (isDragging == false)
{
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
return;
}
isDragging = false;
StartCoroutine(BounceBack());
}
public float GetDragRatio()
{
Vector3 startPos = transform.position;
float deadzone = m_MaxDragDistancePositive * m_ProtectedRatio;
float distance = Mathf.Abs(startPos.y - m_InitialPosition.y) - deadzone;
if (distance <= 0f) return 0f;
float totalDistance = m_MaxDragDistancePositive - deadzone;
if (totalDistance <= 0f) return 0f;
return distance / totalDistance;
}
private void ShowChainPack()
{
if (GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData.IsChainPackDepleted)
{
ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_103"));
}
GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData.ShowChainPack();
}
IEnumerator BounceBack()
{
float elapsed = 0f;
Vector3 startPos = transform.position;
float ratio = GetDragRatio();
while (elapsed < 1f)
{
elapsed += m_ReturnSpeed * Time.deltaTime;
// 使用缓动函数实现弹性
transform.position = Vector3.Lerp(
startPos,
m_InitialPosition,
Mathf.SmoothStep(0, 1, elapsed)
);
float tmpRatio = GetDragRatio();
FishingPinballAct.Publish<EventPinballSpringUpdateData>(new EventPinballSpringUpdateData()
{
Ratio = 1.0f - tmpRatio
});
yield return null;
}
float tmpLastTouchDownTime = m_LastTouchDownTime;
m_LastTouchDownTime = -1f;
if (ratio <= 0f)
{
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
yield break;
}
if (tmpLastTouchDownTime < 0f)
{
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
yield break;
}
if (Time.time - tmpLastTouchDownTime < m_DeferTime)
{
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
yield break;
}
PlaySpringSound();
if (m_IsPelletRunning)
{
yield break;
}
var dataManager = GContext.container.Resolve<EventPinballDataManager>();
//dataManager.InitGameRound();
if (!dataManager.ConsumeTemporaryTokensDefault())
{
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
ShowChainPack();
yield break;
}
if (m_DataManager != null)
{
m_DataManager.IsSimulatorMode = m_IsSimulatorMode;
}
//CreateNewPellet();
//float force = Mathf.Lerp(m_MinForce, m_MaxForce, ratio);
float force = dataManager.GetRandomForce(ratio);
m_Pellet.LaunchPellet(force, m_RecordTimes);
FishingPinballAct.Publish(new EventPinballEnergyArrowRestoreData());
//#if AGG
// using (var e = GEvent.GameEvent("event_pinball"))
// {
// e.AddContent("force", force)
// .AddContent("item_consume", m_DataManager.TemporaryConsumedToken);
// }
//#endif
}
bool IsTouchingSwitch(Vector2 screenPos)
{
RaycastHit2D hit = Physics2D.Raycast(
mainCamera.ScreenToWorldPoint(screenPos),
Vector2.zero
);
return hit.collider != null && hit.collider.gameObject == gameObject;
}
#endregion
#region (/)
[SerializeField] private bool m_IsSimulatorMode = false;
[SerializeField] private bool m_IsProcessingSimulatedData = false;
private int m_RecordTimes = 0;
#endregion
#region
private void InitEvent()
{
FishingPinballAct.Subscribe<EventPinballResetPelletStatusData>(ResetPelletInFiringPin);
FishingPinballAct.Subscribe<EventPinballLaunchPelletStatusData>(LaunchPelletInFiringPin);
FishingPinballAct.Subscribe<EventPinballResumePelletData>(ResumePellet);
FishingPinballAct.Subscribe<EventPinballLaunchPelletData>(OnLaunchPelletDataEvent);
}
public void ResumePellet(EventPinballResumePelletData data)
{
CreateNewPellet();
float force = m_MinForce + m_ForceStep * m_RecordTimes;
m_Pellet.ResumePellet(force, m_RecordTimes);
if (m_IsProcessingSimulatedData)
{
m_RecordTimes++;
}
}
public void OnLaunchPelletDataEvent(EventPinballLaunchPelletData data)
{
if (data == null) return;
if (m_Pellet != null)
{
m_Pellet.LaunchPellet(data.Force, m_RecordTimes);
}
}
private bool m_IsPelletRunning = false;
public void LaunchPelletInFiringPin(EventPinballLaunchPelletStatusData data)
{
m_IsPelletRunning = true;
}
public void ResetPelletInFiringPin(EventPinballResetPelletStatusData data)
{
m_IsPelletRunning = false;
}
#endregion
#region
// Start is called before the first frame update
void Start()
{
m_DataManager = GContext.container.Resolve<EventPinballDataManager>();
m_InitialPosition = m_InitialTransform.position;
m_FarthestPosition = m_FarthestTransform.position;
m_MaxDragDistance = m_FarthestTransform.position.y - m_InitialPosition.y;
m_MaxDragDistancePositive = Mathf.Abs(m_MaxDragDistance);
mainCamera = Camera.main;
m_LastTouchDownTime = -1f;
m_FiringPinPullSound = GContext.container.Resolve<ISoundService>().GetNewUISound(m_FiringPinPullAudioClip);
m_IsSimulatorMode = false;
m_IsPelletRunning = false;
InitEvent();
CreateNewPellet();
}
// Update is called once per frame
void Update()
{
if (m_Collider2D == null) return;
bool isTriggered = false, isDown = false, isDrag = false, isUp = false;
Vector2 screenPosition = Vector2.zero;
#if UNITY_EDITOR
if (Input.GetKeyUp(KeyCode.F1))
{
if (m_DataManager != null)
{
m_DataManager.IsSimulatorMode = m_IsSimulatorMode;
}
//CreateNewPellet();
m_Pellet.InitPellet(m_RecordTimes);
//m_Pellet.ResetPellet();
m_Pellet.SetState(EventPinballState.Prepare);
m_Pellet.LaunchPellet(m_MinForce, m_RecordTimes);
return;
}
else if (Input.GetKeyUp(KeyCode.F2))
{
FishingPinballAct.Publish(new EventPinballResumePelletData());
return;
}
isDown = Input.GetMouseButtonDown(0);
isDrag = Input.GetMouseButton(0);
isUp = Input.GetMouseButtonUp(0);
screenPosition = Input.mousePosition;
isTriggered = isDown || isDrag || isUp;
#elif UNITY_IOS || UNITY_ANDROID
isTriggered = Input.touchCount > 0;
if (isTriggered)
{
Touch touch = Input.GetTouch(0);
screenPosition = touch.position;
switch (touch.phase)
{
case TouchPhase.Began:
{
isDown = true;
}
break;
case TouchPhase.Moved:
{
isDrag = true;
}
break;
case TouchPhase.Ended:
{
isUp = true;
}
break;
}
}
#endif
if (isTriggered && IsTouchingSwitch(screenPosition))
{
if (isDown)
{
OnMouseDown();
}
else if (isUp)
{
OnMouseUp();
}
else if (isDrag)
{
OnMouseDrag();
}
}
else
{
OnMouseUp();
}
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4292a8fbe68596a44b853f6ee9bc8d5a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,690 @@
using asap.core;
using Game;
using GameCore;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace game
{
[RequireComponent(typeof(Rigidbody2D))]
public class PinballPellet : MonoBehaviour
{
[Header("物理设置")]
public float Gravity = 9.81f;
public Rigidbody2D m_Rigidbody2D;
[Header("操作设置")]
[SerializeField] private List<PinballScoringWidgetBase> m_BonusList = new List<PinballScoringWidgetBase>();
[SerializeField] private List<PinballScoringWidgetBase> m_ExitList = new List<PinballScoringWidgetBase>();
#region
[Header("声音设置")]
[SerializeField] private List<AssetReferenceT<AudioClip>> m_BonusSoundList = new List<AssetReferenceT<AudioClip>>();
[SerializeField] private AssetReferenceT<AudioClip> m_CollisionSound;
[SerializeField] private List<GameObject> m_CollisionSoundBlacklist = new List<GameObject>();
private int m_BonusSoundIndex = 0;
public void PlayBonusSound()
{
int count = m_BonusSoundList.Count;
if (m_BonusSoundIndex >= 0 && m_BonusSoundIndex < count)
{
AssetReferenceT<AudioClip> bonusSound = m_BonusSoundList[m_BonusSoundIndex];
GContext.Publish(new AssetReferenceAudioClip(bonusSound, time: 0f));
}
m_BonusSoundIndex++;
}
public void PlayCollisionSound()
{
GContext.Publish(new AssetReferenceAudioClip(m_CollisionSound, time: 0f));
}
#endregion
#region
public void AddScore(PinballScoringWidgetBase scoringWidget, ContactPoint2D contactPoint, bool isCumulativeResponseNumber = true)
{
if (scoringWidget == null) return;
if (isCumulativeResponseNumber)
{
GetDataManager().CumulativeResponseNumber++;
}
// 弹出文本
string tip = scoringWidget.GetTip();
EventPinballBonusType bonusType = scoringWidget.BonusType;
int number = scoringWidget.Number;
FloatingText floatingText = null;
if (bonusType == EventPinballBonusType.TypeScore)
{
floatingText = FloatingTextPool.Instance.GetFloatingScoreText();
GetDataManager().AddTemporaryScore(number);
floatingText.Initialize(tip, contactPoint.point);
}
else if (bonusType == EventPinballBonusType.TypeMultiple)
{
//floatingText = FloatingTextPool.Instance.GetFloatingMultipleText();
GetDataManager().MultiplyTemporaryScore(number);
//floatingText.Initialize(tip, contactPoint.point);
}
//m_PelletTrackInfo.RoutePointList.
//string routes = string.Join("-", m_PelletTrackInfo.RoutePointList);
//Debug.LogError("--- 类型:" + bonusType + ", times:" + m_RecordTimes + ", name:" + scoringWidget.gameObject.name + ", 增加分数:" + number + ", 当前分数:" + m_Score + ", tip:" + tip + ", count:" + m_PelletTrackInfo.RoutePointList.Count + ", routes:"+ routes);
}
#endregion
#region
private EventPinballDataManager m_DataManager;
public EventPinballDataManager GetDataManager()
{
if (m_DataManager == null)
{
m_DataManager = GContext.container.Resolve<EventPinballDataManager>();
}
return m_DataManager;
}
private EventPinballState m_State = EventPinballState.Prepare;
public void SetState(EventPinballState state)
{
if (m_State != state)
{
m_State = state;
}
}
public void SetBonusListToInvalid()
{
foreach (var item in m_BonusList)
{
item.SetInvalidMaterial();
}
}
public void ResetBonusListToValid()
{
foreach (var item in m_BonusList)
{
item.ResetValidMaterial();
}
}
public void ResetExitListToValid()
{
foreach (var item in m_ExitList)
{
item.ResetValidMaterial();
}
}
#endregion
//#if UNITY_EDITOR
#region CSV记录
[Header("数据存储设置")]
[SerializeField] private float m_MaxTime = 15f;
[SerializeField] private List<string> m_WhiteNamePrefixList = new List<string>();
[SerializeField] private bool m_IsProcessingSimulatedData = false;
[SerializeField] private bool m_IsSaveTrackInfoData = false;
private int m_RecordTimes = 0;
private PinballPelletTrackInfo m_PelletTrackInfo = new PinballPelletTrackInfo();
private float m_Force = 10f;
private float m_CumulativeTime = 0f;
private static readonly object trackInfoLock = new object();
public void ClearPelletTrackInfo(int recordTimes)
{
if (!m_IsSaveTrackInfoData) return;
if (m_Rigidbody2D == null) return;
m_PelletTrackInfo.ID = recordTimes;
m_PelletTrackInfo.Name = this.gameObject.name;
m_PelletTrackInfo.Force = m_Force;
m_PelletTrackInfo.Gravity = Gravity;
m_PelletTrackInfo.Clear();
}
public void SavePelletTrackInfo()
{
if (!m_IsSaveTrackInfoData) return;
m_PelletTrackInfo.Score = GetDataManager().TemporaryScore;
SavePelletTrackInfoToCsv(EventPinballConfig.CSVFileName);
}
public void RecordTrackInfo(List<ContactPoint2D> list, EventPinballTrackType trackType, Collision2D collision)
{
if (!m_IsSaveTrackInfoData) return;
lock (trackInfoLock)
{
if (m_Rigidbody2D == null || list == null) return;
var trackNode = new PinballPelletTrackNode()
{
TrackType = trackType,
ContactName = collision.gameObject.name,
MaterialName = collision.rigidbody?.sharedMaterial?.name
};
m_PelletTrackInfo.TrackNodeList.Add(trackNode);
foreach (var item in list)
{
TrackNodeContactPoint2D contactPoint2D = new TrackNodeContactPoint2D()
{
Velocity = item.relativeVelocity,
Position = item.point
};
trackNode.ContactPoint2DList.Add(contactPoint2D);
}
}
}
public void RecordEnter(Collision2D collision, List<ContactPoint2D> contactPointList)
{
if (!m_IsSaveTrackInfoData) return;
if (m_Rigidbody2D == null || collision == null) return;
if (CheckNeedRecord(collision))
{
m_PelletTrackInfo.RoutePointList.Add(collision.gameObject.name);
}
RecordTrackInfo(contactPointList, EventPinballTrackType.TypeEnter, collision);
}
public void RecordExit(Collision2D collision)
{
if (!m_IsSaveTrackInfoData) return;
if (m_Rigidbody2D == null || collision == null) return;
List<ContactPoint2D> list = new List<ContactPoint2D>();
collision.GetContacts(list);
RecordTrackInfo(list, EventPinballTrackType.TypeExit, collision);
}
public bool CheckNeedRecord(Collision2D collision)
{
if (collision == null) return false;
foreach (var item in m_WhiteNamePrefixList)
{
if (collision.gameObject.name.StartsWith(item))
{
return true;
}
}
return false;
}
public IEnumerator PrepareToSavePelletTrackInfo(float force, int recordTimes)
{
//StaticBall();
yield return new WaitForSeconds(0.2f);
//m_PelletTrackInfo.Score = GetDataManager().TemporaryScore;
//SavePelletTrackInfo();
//StaticBall();
yield return new WaitForSeconds(1f);
//StaticBall();
yield return new WaitForSeconds(2f);
ResetPellet();
SetState(EventPinballState.Prepare);
FishingPinballAct.Publish(new EventPinballResetPelletStatusData());
//float force = m_MinForce + m_ForceStep * m_RecordTimes;
LaunchPellet(force, recordTimes);
}
#endregion
//#endif
#region
private List<PinballPelletTrackInfo> m_PelletTrackInfoList = new List<PinballPelletTrackInfo>();
public void ClearPelletTrackInfoList()
{
if (!m_IsSaveTrackInfoData) return;
foreach (var item in m_PelletTrackInfoList)
{
item.Clear();
}
m_PelletTrackInfoList.Clear();
}
public void AddPelletTrackInfo(PinballPelletTrackInfo pelletTrackInfo)
{
if (!m_IsSaveTrackInfoData) return;
m_PelletTrackInfoList.Add(pelletTrackInfo);
}
public string GetPelletTrackInfoCsvHeader()
{
List<string> list = new List<string>();
list.Add("id");
list.Add("Name");
list.Add("Force");
list.Add("Count");
list.Add("Multiple");
list.Add("Score");
list.Add("TrackInfo");
string header = string.Join(",", list);
return header;
}
public void CreatePelletTrackInfoCsv(string filename)
{
if (!m_IsSaveTrackInfoData) return;
string filapath = GetDataManager().GetSaveFilepath(filename);
Debug.LogWarning("--- filepath:" + filapath);
if (!File.Exists(filapath))
{
List<string> list = new List<string>();
list.Add(GetPelletTrackInfoCsvHeader());
PinballUtils.ExportToCSV(list, filapath);
}
}
public void SavePelletTrackInfoToCsv(string filename)
{
if (!m_IsSaveTrackInfoData) return;
string filapath = GetDataManager().GetSaveFilepath(filename);
Debug.LogWarning("--- filepath:" + filapath);
List<string> list = new List<string>();
foreach (var trackInfo in m_PelletTrackInfoList)
{
list.Add(trackInfo.ToString());
}
PinballUtils.ExportToCSV(list, filapath);
}
#endregion
#region
private bool m_ReadyToLaunch = false;
public void PrepareToResetPellet()
{
//StaticBall();
//yield return new WaitForSeconds(2f);
ResetPellet();
SetState(EventPinballState.Prepare);
FishingPinballAct.Publish(new EventPinballResetPelletStatusData());
}
public void LaunchPellet(float force, int recordTimes)
{
if (m_State != EventPinballState.Prepare) return;
SetState(EventPinballState.Running);
m_CumulativeTime = 0f;
//#if UNITY_EDITOR
m_Force = force;
GetDataManager().PinballData.Force = force;
ClearPelletTrackInfo(recordTimes);
ClearPelletTrackInfoList();
AddPelletTrackInfo(this.m_PelletTrackInfo);
//m_RecordTimes++;
//#endif
//Debug.LogWarning("--- LaunchPellet force:" + force + ", m_Force:" + m_Force);
Physics2D.gravity = new Vector2(0f, -Mathf.Abs(Gravity));
//var dir = new Vector2(0f, 1f);
//m_Rigidbody2D.AddForce(dir * force, ForceMode2D.Impulse);
m_ReadyToLaunch = true;
FishingPinballAct.Publish(new EventPinballLaunchPelletStatusData());
}
public void ResetPellet()
{
GetDataManager().GetNextPinballData();
FishingPinballAct.Publish(new EventPinballSwitcherOpen());
FishingPinballAct.Publish(new EventPinballStopArrowBreathAnimData());
FishingPinballAct.Publish(new EventPinballHideWidgetMultipleEffectData());
FishingPinballAct.Publish(new EventPinballHideCircularRotationalAnim());
FishingPinballAct.Publish(new EventPinballBasicScoreShowData());
GetDataManager().InitGameRound();
m_BonusSoundIndex = 0;
ResetBonusListToValid();
ResetExitListToValid();
ShowRenderer();
//StaticBall();
//this.transform.position = m_OriginalPosition;
//this.transform.rotation = m_OriginalQuaternion;
FishingPinballAct.Publish(new EventPinballResetMagnification());
}
public void CheckIfTriggeredBonusOver()
{
if (!GetDataManager().IsAddScoreValid())
{
FishingPinballAct.Publish(new EventPinballShowWidgetScoreEffect2Data());
FishingPinballAct.Publish(new EventPinballPlayArrowBreathAnimData());
FishingPinballAct.Publish(new EventPinballShowCircularRotationalAnim());
FishingPinballAct.Publish(new EventPinballBasicScoreHideData());
}
}
public bool HavePelletTriggeredBonus(Collision2D collision, List<ContactPoint2D> contactPointList, bool isAddScore)
{
if (collision == null || contactPointList == null || contactPointList.Count < 1) return false;
if (this.m_State == EventPinballState.Running)
{
ContactPoint2D contactPoint = contactPointList[0];
foreach (var item in m_BonusList)
{
if (item.gameObject == collision.gameObject)
{
GetDataManager().AccumulatedTriggerCount++;
if (isAddScore)
{
(item as PinballScoringWidgetScore)?.ShowEffect1();
AddScore(item, contactPoint);
FishingPinballAct.Publish(new EventPinballShowPopupData()
{
Scores = GetDataManager().TemporaryScore,
BonusType = item.BonusType,
IsMultipleMax = false
});
CheckIfTriggeredBonusOver();
PlayBonusSound();
}
//else
//{
// FishingPinballAct.Publish(new EventPinballShowWidgetScoreEffect2Data());
//}
return true;
}
}
}
return false;
}
public void CheckIfMultipleMax(int multiple)
{
if (multiple == EventPinballConfig.MultipleMax)
{
GetDataManager().IsMultipleMax = true;
FishingPinballAct.Publish<EventPinballPlayLightOnAnimData>(new EventPinballPlayLightOnAnimData());
}
else
{
GetDataManager().IsMultipleMax = false;
}
}
public void HavePelletTriggeredExit(Collision2D collision, List<ContactPoint2D> contactPointList)
{
if (collision == null || contactPointList == null || contactPointList.Count < 1) return;
if (this.m_State == EventPinballState.Running)
{
ContactPoint2D contactPoint = contactPointList[0];
foreach (var item in m_ExitList)
{
if (item.gameObject == collision.gameObject)
{
GetDataManager().PinballData.Multiple = item.Number;
(item as PinballScoringWidgetMultiple)?.ShowEffect();
(item as PinballScoringWidgetMultiple)?.PlaySound();
AddScore(item, contactPoint, false);
SetState(EventPinballState.Ended);
CheckIfMultipleMax(item.Number);
//#if UNITY_EDITOR
m_PelletTrackInfo.Multiple = item.Number;
SavePelletTrackInfo();
//#endif
FishingPinballAct.Publish(new EventPinballHideCircularRotationalAnim());
FishingPinballAct.Publish(new EventPinballShowMultipleTextData()
{
BonusType = item.BonusType,
Position = contactPoint.point,
Tips = item.GetTip(),
Scores = GetDataManager().TemporaryScore,
IsMultipleMax = item.Number == EventPinballConfig.MultipleMax
});
HideRenderer();
//StaticBall();
//#if AGG
// using (var e = GEvent.GameEvent("event_pinball_result"))
// {
// e.AddContent("count", GetDataManager().AccumulatedTriggerCount)
// .AddContent("Multiple", item.Number)
// .AddContent("point_count", GetDataManager().TemporaryScore);
// }
//#endif
//TerminatePellet(item.Number == EventPinballConfig.MultipleMax);
return;
}
}
}
}
//public void StaticBall()
//{
// m_Rigidbody2D.bodyType = RigidbodyType2D.Kinematic;
// m_Rigidbody2D.isKinematic = true;
// m_Rigidbody2D.Sleep();
// // 重置运动状态
// m_Rigidbody2D.velocity = Vector2.zero;
// m_Rigidbody2D.angularVelocity = 0f;
// // 重置约束
// m_Rigidbody2D.freezeRotation = false; // 解除旋转锁定
// m_Rigidbody2D.constraints = RigidbodyConstraints2D.None; // 解除所有约束
// // 重置碰撞检测
// m_Rigidbody2D.simulated = true; // 确保启用物理模拟
// m_Rigidbody2D.interpolation = RigidbodyInterpolation2D.None; // 重置插值
// // 重置休眠状态
// m_Rigidbody2D.WakeUp(); // 强制唤醒刚体
// this.transform.position = m_OriginalPosition;
// this.transform.rotation = m_OriginalQuaternion;
//}
public void ResumePellet(float force, int recordTimes)
{
//StaticBall();
//this.transform.position = m_OriginalPosition;
//this.transform.rotation = m_OriginalQuaternion;
if (m_IsProcessingSimulatedData)
{
this.StartCoroutine(PrepareToSavePelletTrackInfo(force, recordTimes));
}
else
{
//this.StartCoroutine(PrepareToResetPellet());
PrepareToResetPellet();
}
}
#endregion
#region Collider2D
protected virtual void OnCollisionEnter2D(Collision2D collision)
{
List<ContactPoint2D> contactPointList = new List<ContactPoint2D>();
collision.GetContacts(contactPointList);
//#if UNITY_EDITOR
RecordEnter(collision, contactPointList);
//#endif
bool isTriggered = HavePelletTriggeredBonus(collision, contactPointList, GetDataManager().IsAddScoreValid());
if (!isTriggered)
{
bool isInBlacklist = false;
foreach (var item in m_CollisionSoundBlacklist)
{
if (collision.gameObject == item)
{
isInBlacklist = true;
break;
}
}
if (!isInBlacklist)
{
PlayCollisionSound();
}
}
HavePelletTriggeredExit(collision, contactPointList);
}
protected virtual void OnCollisionExit2D(Collision2D collision)
{
//#if UNITY_EDITOR
RecordExit(collision);
//#endif
if (!GetDataManager().IsAddScoreValid())
{
SetBonusListToInvalid();
}
}
#endregion
#region
[SerializeField] private SpriteRenderer m_SpriteRenderer;
[SerializeField] private GameObject m_Trail;
public void HideRenderer()
{
if (m_SpriteRenderer != null)
{
m_SpriteRenderer.enabled = false;
}
if (m_Trail != null)
{
m_Trail.SetActive(false);
}
}
public void ShowRenderer()
{
if (m_SpriteRenderer != null)
{
m_SpriteRenderer.enabled = true;
}
if (m_Trail != null)
{
m_Trail.SetActive(true);
}
}
#endregion
#region
public void InitEvent()
{
//FishingPinballAct.Subscribe<EventPinballResumePelletData>(ResumePellet);
//FishingPinballAct.Subscribe<EventPinballLaunchPelletData>(OnLaunchPelletDataEvent);
}
//public void OnLaunchPelletDataEvent(EventPinballLaunchPelletData data)
//{
// if (data == null) return;
// LaunchPellet(data.Force);
//}
#endregion
#region
private Vector3 m_OriginalPosition;
private Quaternion m_OriginalQuaternion;
// Start is called before the first frame update
public void InitPellet(int recordTimes)
{
m_OriginalPosition = transform.position;
m_OriginalQuaternion = transform.rotation;
m_ReadyToLaunch = false;
InitEvent();
//#if UNITY_EDITOR
ClearPelletTrackInfo(recordTimes);
CreatePelletTrackInfoCsv(EventPinballConfig.CSVFileName);
//#endif
SetState(EventPinballState.Prepare);
ResetPellet();
//GetDataManager().InitGameRound();
//m_Text.text = GContext.container.Resolve<EventPinballDataManager>().GetSaveFilepath(EventPinballConfig.CSVFileName);
}
// Update is called once per frame
void Update()
{
//#if UNITY_EDITOR
if (m_State == EventPinballState.Running)
{
if (m_Rigidbody2D.IsSleeping())
{
m_CumulativeTime += Time.deltaTime;
}
else
{
m_CumulativeTime = 0;
}
if (m_CumulativeTime > 0.1f)
{
GetDataManager().ReturnConsumedToken();
ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_104"));
HideRenderer();
//StaticBall();
SetState(EventPinballState.Ended);
FishingPinballAct.Publish(new EventPinballResumePelletData());
}
}
//#endif
}
private void FixedUpdate()
{
if (m_ReadyToLaunch)
{
m_Rigidbody2D.bodyType = RigidbodyType2D.Dynamic;
m_Rigidbody2D.isKinematic = false;
var dir = new Vector2(0f, 1f);
m_Rigidbody2D.AddForce(dir * m_Force, ForceMode2D.Impulse);
m_ReadyToLaunch = false;
}
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3637ebbbedeaa94ab5626b04ae4ac18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,132 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
namespace game
{
public class PinballPelletTrackInfo
{
public int ID { get; set; }
public string Name { get; set; }
public float Force { get; set; }
public float Gravity { get; set; }
public int Score { get; set; }
public int Multiple { get; set; }
public List<PinballPelletTrackNode> TrackNodeList = new List<PinballPelletTrackNode>();
public List<string> RoutePointList = new List<string>();
public override string ToString()
{
StringBuilder str = new StringBuilder("");
str.Append(ID + ",");
str.Append(Name + ",");
str.Append(Force + ",");
int count = RoutePointList.Count;
str.Append(count + ",");
str.Append(Multiple + ",");
str.Append(Score + ",");
//if (count > 0)
//{
// str.Append(RoutePointList[0]);
//}
//for (int i = 1; i < count; ++i)
//{
// str.Append("_" + RoutePointList[i]);
//}
//str.Append(",");
////str.Append("total_" + count);
//if (count > 0)
//{
// Dictionary<string, int> temp = new Dictionary<string, int>();
// foreach (var item in RoutePointList)
// {
// if (temp.ContainsKey(item))
// {
// int value = temp[item];
// value++;
// temp[item] = value;
// }
// else
// {
// temp.Add(item, 1);
// }
// }
// foreach (var item in temp)
// {
// str.Append("-" + item.Key + "_" + item.Value);
// }
//}
//str.Append(",");
//foreach (var item in TrackNodeList)
//{
// str.Append(item.ToString());
//}
return str.ToString();
}
public void Clear()
{
foreach (var item in TrackNodeList)
{
item.Clear();
}
TrackNodeList.Clear();
RoutePointList.Clear();
}
}
public class PinballPelletTrackNode
{
public EventPinballTrackType TrackType { get; set; }
public string ContactName { get; set; }
public string MaterialName { get; set; }
public List<TrackNodeContactPoint2D> ContactPoint2DList = new List<TrackNodeContactPoint2D>();
public override string ToString()
{
int count = ContactPoint2DList.Count;
StringBuilder str = new StringBuilder("");
str.Append(TrackType + "-");
if (count > 0)
{
str.Append(ContactName + "_" + MaterialName + "-");
}
else
{
str.Append(ContactName + "_" + MaterialName + "|");
}
foreach (var item in ContactPoint2DList)
{
str.Append(item.ToString());
}
return str.ToString();
}
public void Clear()
{
ContactPoint2DList.Clear();
}
}
public class TrackNodeContactPoint2D
{
public Vector2 Velocity { get; set; }
public Vector2 Position { get; set; }
public override string ToString()
{
StringBuilder str = new StringBuilder("");
str.Append("V(" + Velocity.x + "_" + Velocity.y + ")-");
str.Append("P(" + Position.x + "_" + Position.y + ")|");
return str.ToString();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e5b954b96638cf49b16bc3d6d42193c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class PinballRendererSortSettings : MonoBehaviour
{
public int OrderInLayer = 3;
// Start is called before the first frame update
void Start()
{
var renderer = GetComponent<Renderer>();
renderer.sortingOrder = OrderInLayer;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f3371b033e934c04c9ae2f36c1d38b04
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,252 @@
using asap.core;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class PinballSceneController : MonoBehaviour
{
#region
private EventPinballDataManager m_DataManager;
#endregion
#region
[Header("新手相关设置")]
[SerializeField] public SpriteRenderer FiringPin;
private void HideFiringPin(EventPinballHideFiringPinData data)
{
if (FiringPin != null)
{
if (FiringPin.gameObject.activeSelf == true)
{
FiringPin.gameObject.SetActive(false);
}
}
}
private void ShowFiringPin(EventPinballShowFiringPinData data)
{
if (FiringPin != null)
{
if (FiringPin.gameObject.activeSelf == false)
{
FiringPin.gameObject.SetActive(true);
}
}
}
#endregion
#region
public Transform IconPinball;
[Header("动画相关设置")]
[SerializeField] private Animation m_ArrowBreathAnim;
[SerializeField] private List<GameObject> m_HideArrowGameObjectList = new List<GameObject>();
public void PlayArrowBreathAnim(EventPinballPlayArrowBreathAnimData data)
{
m_ArrowBreathAnim.Play();
}
public void HideArrowGameObjectList(EventPinballStopArrowBreathAnimData data)
{
m_ArrowBreathAnim.Stop();
foreach (var item in m_HideArrowGameObjectList)
{
item.SetActive(false);
}
}
[SerializeField] private string m_LightOnAnimName;
[SerializeField] private float m_LightOnAnimTime;
[SerializeField] private Animator m_LightOnAnim;
public void PlayLightOnAnim(EventPinballPlayLightOnAnimData data)
{
m_LightOnAnim.gameObject.SetActive(true);
m_LightOnAnim.Play(m_LightOnAnimName);
this.StartCoroutine(StopLightOnAnim());
}
private IEnumerator StopLightOnAnim()
{
yield return new WaitForSeconds(m_LightOnAnimTime);
m_LightOnAnim.gameObject.SetActive(false);
//FishingPinballAct.Publish(new EventPinballRewardUpdateData()
//{
// Scores = m_DataManager.TemporaryScore
//});
//FishingPinballAct.Publish<EventPinballStopLightOnAnimData>(new EventPinballStopLightOnAnimData());
}
#endregion
#region
[SerializeField] private List<SpriteRenderer> m_EnergyArrowList = new List<SpriteRenderer>();
[SerializeField] private Color m_EnergyArrowColorBright = Color.white;
[SerializeField] private Color m_EnergyArrowColorDark = Color.black;
private float m_RestoreIntervalTime = 0.1f;
public void UpdateEnergyArrowList(EventPinballEnergyArrowData data)
{
if (data == null) return;
int count = m_EnergyArrowList.Count;
float step = 1.0f / count;
int index = (int)Mathf.Ceil(data.Energy / step);
for (int i = 0; i < count; ++i)
{
SpriteRenderer spriteRenderer = m_EnergyArrowList[i];
if (i < index)
{
spriteRenderer.color = m_EnergyArrowColorBright;
}
else
{
spriteRenderer.color = m_EnergyArrowColorDark;
}
}
}
public void RestoreEnergyArrowList(EventPinballEnergyArrowRestoreData data)
{
if (data == null) return;
this.StartCoroutine(RestoreEnergyArrowListToDark());
}
public IEnumerator RestoreEnergyArrowListToDark()
{
int count = m_EnergyArrowList.Count;
int brightIndex = -1;
for (int i = 0; i < count; i++)
{
SpriteRenderer spriteRenderer = m_EnergyArrowList[i];
if (spriteRenderer.color == m_EnergyArrowColorBright)
{
brightIndex = i;
}
}
if (brightIndex >= 0)
{
for (int i = brightIndex; i >= 0; i--)
{
yield return new WaitForSeconds(m_RestoreIntervalTime);
SpriteRenderer spriteRenderer = m_EnergyArrowList[i];
spriteRenderer.color = m_EnergyArrowColorDark;
}
}
}
#endregion
#region
[Header("奖励圆盘特效&动画相关设置")]
[SerializeField] private int m_ResponseNumber = 10; // 相应次数
public List<PinballCircularProgress> m_CircularProgressList = new List<PinballCircularProgress>();
public void UpdateBonusCircularProgress(EventPinballUpdateBonusCircularProgress data)
{
if (m_DataManager == null) return;
float progress = m_DataManager.GetBonusResponseRatio();
foreach (var item in m_CircularProgressList)
{
item.SetProgress(progress);
}
}
public List<Transform> m_CircularAnimList = new List<Transform>();
public float m_CircularAnimRotationalSpeed = -180f;
public void UpdateCircularRotationalAnim()
{
if (m_CircularAnimList.Count > 0)
{
var firstItem = m_CircularAnimList[0];
Vector3 eulerAngles = firstItem.eulerAngles;
eulerAngles += new Vector3(0f, 0f, 1f) * m_CircularAnimRotationalSpeed * Time.deltaTime;
if (eulerAngles.z > 360f)
{
eulerAngles.z -= 360f;
}
else if (eulerAngles.z < -360f)
{
eulerAngles.z += 360f;
}
foreach (var item in m_CircularAnimList)
{
item.eulerAngles = eulerAngles;
}
}
}
private bool m_IsShowCircularRotationalAnim = false;
public void ShowCircularRotationalAnim(EventPinballShowCircularRotationalAnim data)
{
foreach (var item in m_CircularProgressList)
{
item.gameObject.SetActive(false);
}
foreach (var item in m_CircularAnimList)
{
item.gameObject.SetActive(true);
item.eulerAngles = Vector3.zero;
}
m_IsShowCircularRotationalAnim = true;
}
public void HideCircularRotationalAnim(EventPinballHideCircularRotationalAnim data)
{
m_IsShowCircularRotationalAnim = false;
foreach (var item in m_CircularProgressList)
{
item.gameObject.SetActive(true);
}
foreach (var item in m_CircularAnimList)
{
item.gameObject.SetActive(false);
}
}
#endregion
#region
public void InitEvent()
{
FishingPinballAct.Subscribe<EventPinballEnergyArrowData>(UpdateEnergyArrowList);
FishingPinballAct.Subscribe<EventPinballEnergyArrowRestoreData>(RestoreEnergyArrowList);
FishingPinballAct.Subscribe<EventPinballUpdateBonusCircularProgress>(UpdateBonusCircularProgress);
FishingPinballAct.Subscribe<EventPinballPlayArrowBreathAnimData>(PlayArrowBreathAnim);
FishingPinballAct.Subscribe<EventPinballStopArrowBreathAnimData>(HideArrowGameObjectList);
FishingPinballAct.Subscribe<EventPinballPlayLightOnAnimData>(PlayLightOnAnim);
FishingPinballAct.Subscribe<EventPinballShowFiringPinData>(ShowFiringPin);
FishingPinballAct.Subscribe<EventPinballHideFiringPinData>(HideFiringPin);
FishingPinballAct.Subscribe<EventPinballShowCircularRotationalAnim>(ShowCircularRotationalAnim);
FishingPinballAct.Subscribe<EventPinballHideCircularRotationalAnim>(HideCircularRotationalAnim);
}
#endregion
#region
// Start is called before the first frame update
void Start()
{
m_DataManager = GContext.container.Resolve<EventPinballDataManager>();
m_DataManager.BonusResponseNumber = m_ResponseNumber;
InitEvent();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyUp(KeyCode.Escape))
{
// 关闭当前Act
GContext.Publish(new UnloadActToNextAct());
}
if (m_IsShowCircularRotationalAnim)
{
UpdateCircularRotationalAnim();
}
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 74d285fcdf9ab914cbe0d5af5ce05a34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class PinballScoringWidgetBase : MonoBehaviour
{
#region
public int Number = 5; // 分数
public Rigidbody2D Rigidbody2D; // 2D刚体
public PhysicsMaterial2D ValidMaterial; // 有效材质
public PhysicsMaterial2D InvalidMaterial; // 无效材质
protected EventPinballBonusType m_BonusType = EventPinballBonusType.TypeScore;
public EventPinballBonusType BonusType { get => m_BonusType; }
public virtual string GetTip()
{
return "";
}
public void ResetValidMaterial()
{
if (Rigidbody2D != null && ValidMaterial != null)
{
Rigidbody2D.sharedMaterial = ValidMaterial;
}
}
public void SetInvalidMaterial()
{
if (Rigidbody2D != null && InvalidMaterial != null)
{
Rigidbody2D.sharedMaterial = InvalidMaterial;
}
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 209889935e9999f43939f9be5591e9e9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
using asap.core;
using Game;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
namespace game
{
public class PinballScoringWidgetMultiple : PinballScoringWidgetBase
{
#region
[Header("声音设置")]
[SerializeField] private AssetReferenceT<AudioClip> m_Sound;
public void PlaySound()
{
GContext.Publish(new AssetReferenceAudioClip(m_Sound, time: 0f));
}
#endregion
#region
[Header("特效设置")]
[SerializeField] public GameObject m_Effect;
[SerializeField] public float m_EffectDuration = 0.6f;
public void ShowEffect()
{
if (m_Effect != null)
{
if (m_Effect.activeSelf == false)
{
m_Effect.SetActive(true);
}
StartCoroutine(AutoHideEffect());
}
}
private IEnumerator AutoHideEffect()
{
yield return new WaitForSeconds(m_EffectDuration);
HideEffect(null);
}
public void HideEffect(EventPinballHideWidgetMultipleEffectData data)
{
if (m_Effect != null)
{
if (m_Effect.activeSelf == true)
{
m_Effect.SetActive(false);
}
}
}
#endregion
#region
public override string GetTip()
{
return "x" + Number;
}
#endregion
#region
// Start is called before the first frame update
void Start()
{
m_BonusType = EventPinballBonusType.TypeMultiple;
HideEffect(null);
FishingPinballAct.Subscribe<EventPinballHideWidgetMultipleEffectData>(HideEffect);
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 762a90a003e57774c96d02202561b4cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,144 @@
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
namespace game
{
public class PinballScoringWidgetScore : PinballScoringWidgetBase
{
[SerializeField] private TextMeshPro m_TextMesh;
#region
[Header("特效设置")]
[SerializeField] public GameObject m_Effect1;
[SerializeField] public GameObject m_Effect2;
[SerializeField] public float m_Effect1Duration = 0.3f;
[SerializeField] public float m_Effect2Duration = 0.3f;
private float m_Effect1_CumulativeTime = 0f;
public void ShowEffect1()
{
m_Effect1_CumulativeTime = 0f;
}
private void UpdateEffect1()
{
if (m_Effect1 != null)
{
if (m_Effect1_CumulativeTime < m_Effect1Duration)
{
if (m_Effect1.activeSelf == false)
{
m_Effect1.SetActive(true);
}
}
else
{
if (m_Effect1.activeSelf == true)
{
m_Effect1.SetActive(false);
}
}
m_Effect1_CumulativeTime += Time.deltaTime;
if (m_Effect1_CumulativeTime > float.MaxValue)
{
m_Effect1_CumulativeTime = m_Effect1Duration + 1f;
}
}
}
private float m_Effect2_CumulativeTime = 0f;
public void ShowEffect2(EventPinballShowWidgetScoreEffect2Data data)
{
m_Effect2_CumulativeTime = 0f;
}
private void UpdateEffect2()
{
if (m_Effect2 != null)
{
if (m_Effect2_CumulativeTime < m_Effect2Duration)
{
if (m_Effect2.activeSelf == false)
{
m_Effect2.SetActive(true);
}
}
else
{
if (m_Effect2.activeSelf == true)
{
m_Effect2.SetActive(false);
}
}
m_Effect2_CumulativeTime += Time.deltaTime;
if (m_Effect2_CumulativeTime > float.MaxValue)
{
m_Effect2_CumulativeTime = m_Effect2Duration + 1f;
}
}
}
#endregion
#region
public override string GetTip()
{
return "+" + Number;
}
#endregion
#region
private void InitEvent()
{
FishingPinballAct.Subscribe<EventPinballBasicScore>(UpdateScore);
FishingPinballAct.Subscribe<EventPinballBasicScoreHideData>(HideScore);
FishingPinballAct.Subscribe<EventPinballBasicScoreShowData>(ShowScore);
FishingPinballAct.Subscribe<EventPinballShowWidgetScoreEffect2Data>(ShowEffect2);
}
private void UpdateScore(EventPinballBasicScore data)
{
if (data == null) return;
Number = data.Score;
if (m_TextMesh != null)
{
m_TextMesh.text = "" + Number;
}
}
private void HideScore(EventPinballBasicScoreHideData data)
{
if (m_TextMesh != null)
{
m_TextMesh.gameObject.SetActive(false);
}
}
private void ShowScore(EventPinballBasicScoreShowData data)
{
if (m_TextMesh != null)
{
m_TextMesh.gameObject.SetActive(true);
}
}
#endregion
#region
// Start is called before the first frame update
void Start()
{
m_BonusType = EventPinballBonusType.TypeScore;
InitEvent();
m_Effect1_CumulativeTime = m_Effect1Duration + 1f;
m_Effect2_CumulativeTime = m_Effect2Duration + 1f;
}
// Update is called once per frame
void Update()
{
UpdateEffect1();
UpdateEffect2();
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 12c87ee671752054eba9a85d63c2ccb1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class PinballSpring : MonoBehaviour
{
[SerializeField] private Transform m_BottomPosition;
[SerializeField] private SpriteRenderer m_SpriteRenderer;
[SerializeField] private float m_MaxRatio = 0.5f;
#region
public void InitEvent()
{
FishingPinballAct.Subscribe<EventPinballSpringUpdateData>(UpdateSpring);
}
public void UpdateSpring(EventPinballSpringUpdateData data)
{
var spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
float boundX = spriteRenderer.bounds.size.x;
float reservedRatio = 1.0f - m_MaxRatio;
float validRatio = m_MaxRatio * data.Ratio;
float scaleY = reservedRatio + validRatio;
m_SpriteRenderer.transform.localScale = new Vector3(m_SpriteRenderer.transform.localScale.x, scaleY, m_SpriteRenderer.transform.localScale.z);
float height = m_SpriteRenderer.bounds.size.y;
float y = m_BottomPosition.position.y + height / 2;
transform.position = new Vector3(transform.position.x, y, transform.position.z);
}
#endregion
#region
// Start is called before the first frame update
void Start()
{
InitEvent();
}
// Update is called once per frame
void Update()
{
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7ef39d92bc3420647b49d3cf46a4e0bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class PinballSwitcher : MonoBehaviour
{
public Animator m_Animator;
public string m_OpenAnimation;
public string m_CloseAnimation;
public GameObject m_Collider;
#region
private EventPinballSwitcherState m_State;
public bool IsOpen()
{
return m_State == EventPinballSwitcherState.Open;
}
#endregion
#region
public void OpenSwitcher(EventPinballSwitcherOpen data)
{
if (m_Animator != null && !string.IsNullOrEmpty(m_OpenAnimation))
{
m_Animator.Play(m_OpenAnimation);
m_State = EventPinballSwitcherState.Open;
}
if (m_Collider != null)
{
m_Collider.SetActive(false);
}
}
public void CloseSwitcher(EventPinballSwitcherClose data)
{
if (m_Animator != null && !string.IsNullOrEmpty(m_CloseAnimation))
{
m_Animator.Play(m_CloseAnimation);
m_State = EventPinballSwitcherState.Close;
}
if (m_Collider != null)
{
m_Collider.SetActive(true);
}
}
#endregion
#region
public void InitEvent()
{
FishingPinballAct.Subscribe<EventPinballSwitcherOpen>(OpenSwitcher);
FishingPinballAct.Subscribe<EventPinballSwitcherClose>(CloseSwitcher);
}
#endregion
#region
// Start is called before the first frame update
void Start()
{
InitEvent();
FishingPinballAct.Publish(new EventPinballSwitcherOpen());
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d8f250885ca25fa44b8952e0988ea983
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(Collider2D))]
public class PinballSwitcherCloseDetection : MonoBehaviour
{
public PinballPellet m_Pellet;
public PinballSwitcher m_Switcher;
public int m_WaitFrames = 3;
#region Switcher
public IEnumerator CloseSwitcher()
{
int index = 0;
while (index < m_WaitFrames)
{
yield return null;
index++;
}
FishingPinballAct.Publish(new EventPinballSwitcherClose());
}
#endregion
#region Collider2D
private void OnCollisionExit2D(Collision2D collision)
{
if (m_Pellet != null && m_Switcher != null && m_Switcher.IsOpen() && collision.gameObject == m_Pellet.gameObject)
{
StartCoroutine(CloseSwitcher());
}
}
#endregion
#region
public void InitEvent()
{
FishingPinballAct.Subscribe<EventPinballSetDummyPelletData>(SetData);
}
public void SetData(EventPinballSetDummyPelletData data)
{
if (data == null) return;
m_Pellet = data.Pellet;
}
#endregion
#region
private void Awake()
{
InitEvent();
}
#endregion
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8efb55e062aa1b847b95e6eae6097c4e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using UnityEngine;
namespace game
{
public static class PinballUtils
{
public static void ExportToCSV(List<string> list, string filePath)
{
if (list == null || list.Count == 0)
{
Debug.LogWarning("数据为空,无法导出 CSV 文件。");
return;
}
using (StreamWriter sw = new StreamWriter(filePath, true))
{
foreach (var item in list)
{
sw.WriteLine(item);
}
}
Debug.Log($"CSV 文件已保存到: {filePath}");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14cdafaf6baebae4bb2d657dd5e65e10
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c98f51c606786774a8c16d32b227928a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,87 @@
Shader "Bamboo/CircularProgress"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Progress ("Progress", Range(0, 1)) = 0
_Color ("Color", Color) = (1,1,1,1)
_BackgroundColor ("Background Color", Color) = (0,0,0,0)
}
SubShader
{
Tags
{
"Queue"="Transparent"
"RenderType"="Transparent"
}
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Progress;
fixed4 _Color;
fixed4 _BackgroundColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// 获取UV坐标相对于中心的位置
float2 center = float2(0.5, 0.5);
float2 dir = i.uv - center;
// 计算当前点到圆心的距离
float dist = length(dir);
// 计算当前点的角度(从上方开始顺时针方向)
// atan2返回[-π, π],我们转换为[0, 1]范围
float angle = atan2(dir.x, dir.y) / (2.0 * 3.14159265359);
angle = angle < 0 ? angle + 1.0 : angle;
// 采样纹理
fixed4 col = tex2D(_MainTex, i.uv);
// 根据进度决定是否显示
float visible = (dist <= 0.5) && (angle <= _Progress);
// 混合颜色
col.rgb = col.rgb * _Color.rgb;
col.a = col.a * _Color.a * visible;
// 如果不可见,使用背景色
return lerp(_BackgroundColor, col, visible);
}
ENDCG
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: a1423250c4744a04596fc60f2ce062b6
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 80bba6e2f0550644abc6d29a27f6c9be
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
namespace game
{
[RequireComponent(typeof(TextMeshPro))]
public class FloatingText : MonoBehaviour
{
[Header("Type")]
public EventPinballBonusType FloatingTextType;
[Header("Movement Settings")]
public float moveSpeed = 1f;
public float fadeDuration = 1f;
[Header("Renderer")]
public int OrderInLayer = 3;
private TextMeshPro textMesh;
private float currentAlpha = 1f;
private float timer = 0f;
private Vector3 moveDirection = Vector3.up;
private void Awake()
{
textMesh = GetComponent<TextMeshPro>();
var renderer = GetComponent<Renderer>();
renderer.sortingOrder = OrderInLayer;
}
public void Initialize(string text, Vector3 position)
{
transform.position = position;
textMesh.text = text;
currentAlpha = 1f;
timer = 0f;
gameObject.SetActive(true);
}
private void Update()
{
// 移动
transform.position += moveDirection * moveSpeed * Time.deltaTime;
// 淡出
timer += Time.deltaTime;
if (timer >= fadeDuration)
{
if (FloatingTextType == EventPinballBonusType.TypeScore)
{
FloatingTextPool.Instance.ReturnToScorePool(this);
}
else if (FloatingTextType == EventPinballBonusType.TypeMultiple)
{
FloatingTextPool.Instance.ReturnToMultiplePool(this);
}
return;
}
currentAlpha = Mathf.Lerp(1f, 0f, timer / fadeDuration);
var color = textMesh.color;
color.a = currentAlpha;
textMesh.color = color;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fce2a3c44f5cc2d4ead5a2ced75e2732
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace game
{
public class FloatingTextPool : MonoBehaviour
{
public static FloatingTextPool Instance { get; private set; }
[SerializeField] private GameObject floatingScoreTextPrefab;
[SerializeField] private GameObject floatingMultipleTextPrefab;
[SerializeField] private int initialScorePoolSize = 12;
[SerializeField] private int initialMultiplePoolSize = 2;
private Queue<FloatingText> m_ScorePool = new Queue<FloatingText>();
private Queue<FloatingText> m_MultiplePool = new Queue<FloatingText>();
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
InitializePool();
}
private void OnDestroy()
{
m_ScorePool.Clear();
m_ScorePool = null;
m_MultiplePool.Clear();
m_MultiplePool = null;
Instance = null;
}
private void InitializePool()
{
for (int i = 0; i < initialScorePoolSize; i++)
{
CreateNewScoreTextObject();
}
for (int i = 0; i < initialMultiplePoolSize; i++)
{
CreateNewMultipleTextObject();
}
}
private void CreateNewScoreTextObject()
{
var obj = Instantiate(floatingScoreTextPrefab, transform);
var floatingText = obj.GetComponent<FloatingText>();
floatingText.gameObject.SetActive(false);
m_ScorePool.Enqueue(floatingText);
}
private void CreateNewMultipleTextObject()
{
var obj = Instantiate(floatingMultipleTextPrefab, transform);
var floatingText = obj.GetComponent<FloatingText>();
floatingText.gameObject.SetActive(false);
m_MultiplePool.Enqueue(floatingText);
}
public FloatingText GetFloatingScoreText()
{
if (m_ScorePool.Count == 0)
{
CreateNewScoreTextObject();
}
var text = m_ScorePool.Dequeue();
text.gameObject.SetActive(true);
return text;
}
public FloatingText GetFloatingMultipleText()
{
if (m_ScorePool.Count == 0)
{
CreateNewMultipleTextObject();
}
var text = m_MultiplePool.Dequeue();
text.gameObject.SetActive(true);
return text;
}
public void ReturnToScorePool(FloatingText text)
{
text.gameObject.SetActive(false);
m_ScorePool.Enqueue(text);
}
public void ReturnToMultiplePool(FloatingText text)
{
text.gameObject.SetActive(false);
m_MultiplePool.Enqueue(text);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 333a4cb1ba0446646b7439ef7923e586
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: