using Unity.VisualScripting;
///
/// BPM组单元,用于储存对应时间组的物件速度变化,与乐曲相关
///
public class BPMGroup
{
/*关于时间组与BPM变换的机制
*BPM变换是一种用来完成适应中间有BPM变换的歌曲的一种机制
*其原理是通过控制当前BPM的基准BPM的比值,使得NoteSpeed得以变化
*当BPM变换到比原定的数值更大时,那么音符的速度将会更快
*当BPM变换到比原定的数值更小时,那么音符的速度将会更慢
*
*但是将这种变换设置为全局的是不合适的,因此我们从数据上为Note划分组别
*使得每一个时间组都可以被单独控制
*我们将在控制器重创建一个列表,统一管理列表中的所有时间组单元
*在每一个物件被实例化时,它将被传递对应的时间组单元的引用
*
*每一个时间组单元通过更新自身存储的NoteSpeed以达到控制Note的效果
*因为每一个被创建的物件实例都会不断的通过NoteSpeed更新自身位置
*
*由于时间组条数通常在100这个数量级以内,选择字典结构去管理是相对合适的
*/
///
/// 当前BPM组的NoteSpeed
///
public float CurrentNoteSpeed
{
get
{
if (CurrentBPM == 0) return 0;
//单位向量*基础速度*音符流速*BPM/基准BPM
return _noteStream * CurrentBPM * _baseSpeed / _baseBPM;
}
}
private float _noteStream;
private float _baseSpeed;
private float _baseBPM;
///
/// 每拍的时间长度(秒)
///
public float Beat
{
get
{
return CurrentBPM > 0 ? 60f / CurrentBPM : 0f;
}
}
///
/// 音符相对当前BPM的抵达下落目标所需时间,单位:ms
///
public float InitializeOffset
{
get
{
if (CurrentNoteSpeed == 0) return 0;
//到达目标点的时间
return TrackLength / CurrentNoteSpeed;
}
}
///
/// 轨道长度,该值应当添加至游戏主控变成玩家偏好设置
///
private float TrackLength;
public float CurrentBPM { set; get; }
public int GroupNum { get; }
public BPMGroup(float currentBPM, int groupNum, float noteStream, float baseSpeed, float baseBPM, float trackLength)
{
CurrentBPM = currentBPM;
GroupNum = groupNum;
_noteStream = noteStream;
_baseSpeed = baseSpeed;
_baseBPM = baseBPM;
TrackLength = trackLength;
}
public void UpdatePlayerSetting(float noteStream, float baseSpeed, float baseBPM, float trackLength)
{
_noteStream = noteStream;
_baseSpeed = baseSpeed;
_baseBPM = baseBPM;
TrackLength = trackLength;
}
public override string ToString()
{
return $"BPMGroup [Group: {GroupNum}]\n" +
$"BPM: {CurrentBPM}\n" +
$"Beat: {Beat:F3}s\n" +
$"NoteSpeed: {CurrentNoteSpeed:F2}\n" +
$"Stream: {_noteStream}\n" +
$"BaseSpeed: {_baseSpeed}\n" +
$"BaseBPM: {_baseBPM}\n" +
$"InitializeOffset:{InitializeOffset}\n"+
$"当前速度:{CurrentNoteSpeed}"
;
}
}