24 个版本 (2 个稳定版)
1.1.0 | 2024年7月10日 |
---|---|
0.10.0 | 2023年11月19日 |
0.9.4 | 2023年2月9日 |
0.9.2 | 2022年11月8日 |
0.2.0 | 2021年2月25日 |
#4 in 游戏
每月111 次下载
用于 simplebeatmapanalyzer
645KB
14K SLoC
rosu-pp
用于计算所有 osu! 游戏模式的难度和表现属性的库。
rosu-pp
的很大一部分是将 osu!lazer 的难度和表现计算移植过来,重点在于将代码精确地翻译为 Rust 以获得最精确的结果,同时提供显著的性能提升。
移植代码的最新提交
- osu!lazer :
7342fb7f51b34533a42bffda89c3d6c569cc69ce
(2022-10-11) - osu!tools :
146d5916937161ef65906aa97f85d367035f3712
(2022-10-08)
最新游戏模式更新新闻
- osu: https://osu.ppy.sh/home/news/2022-09-30-changes-to-osu-sr-and-pp
- taiko: https://osu.ppy.sh/home/news/2022-09-28-changes-to-osu-taiko-sr-and-pp
- catch: https://osu.ppy.sh/home/news/2020-05-14-osucatch-scoring-updates
- mania: https://osu.ppy.sh/home/news/2022-10-09-changes-to-osu-mania-sr-and-pp
使用方法
// Decode the map
let map = rosu_pp::Beatmap::from_path("./resources/2785319.osu").unwrap();
// Calculate difficulty attributes
let diff_attrs = rosu_pp::Difficulty::new()
.mods(8 + 16) // HDHR
.calculate(&map);
let stars = diff_attrs.stars();
// Calculate performance attributes
let perf_attrs = rosu_pp::Performance::new(diff_attrs)
// To speed up the calculation, we used the previous attributes.
// **Note** that this should only be done if the map and all difficulty
// settings stay the same, otherwise the final attributes will be incorrect!
.mods(24) // HDHR, must be the same as before
.combo(789)
.accuracy(99.2)
.misses(2)
.calculate();
let pp = perf_attrs.pp();
// Again, we re-use the previous attributes for maximum efficiency.
let max_pp = perf_attrs.performance()
.mods(24) // Still the same
.calculate()
.pp();
println!("Stars: {stars} | PP: {pp}/{max_pp}");
逐步计算
逐步计算属性提供了一种有效的方法来单独处理每个 hitobject 并仅计算到该点的属性。
对于难度属性,有 GradualDifficulty
实现了 Iterator
,而对于表现属性,有 GradualPerformance
需要当前的分数状态。
use rosu_pp::{Beatmap, GradualPerformance, Difficulty, any::ScoreState};
let map = Beatmap::from_path("./resources/1028484.osu").unwrap();
let mut gradual = Difficulty::new()
.mods(16 + 64) // HRDT
.clock_rate(1.2)
.gradual_performance(&map);
let mut state = ScoreState::new(); // empty state, everything is on 0.
// The first 10 hitresults are 300s
for _ in 0..10 {
state.n300 += 1;
state.max_combo += 1;
let attrs = gradual.next(state.clone()).unwrap();
println!("PP: {}", attrs.pp());
}
// Fast-forward to the end
state.max_combo = ...
state.n300 = ...
state.n_katu = ...
...
let attrs = gradual.last(state).unwrap();
println!("PP: {}", attrs.pp());
准确性
rosu-pp
在多种 mod 组合下与所有当前 beatmap 进行了测试,并提供了与 osu!lazer 完全匹配的值,精确到小数点后最后一位。
然而,有一个小注意事项:只有在调试模式下,值才如此精确。在发布模式下,Rust编译器会进行优化,这可能导致由于浮点数不精确而产生微小的差异,最终可能会放大。考虑到这一点,rosu-pp
在不针对.NET编译器本身的情况下,尽可能精确。实际上,发布模式下的不精确性可以忽略不计。
速度
rosu-pp
的一个重要因素是计算速度。优化和精确翻译并不总是相辅相成。不过,仍然尽可能地进行了性能改进,提供了比原生C#代码显著更快的运行时。
osu!lazer和rosu-pp
的简单基准测试结果
osu!lazer:
Decoding maps: Median: 378.10ms | Mean: 381.47ms
Calculating difficulties: Median: 588.89ms | Mean: 597.11ms
Calculating performances: Median: 315.90µs | Mean: 310.60µs
rosu-pp:
Decoding maps: Median: 46.94ms | Mean: 47.21ms
Calculating difficulties: Median: 72.90ms | Mean: 73.13ms
Calculating performances: Median: 44.13µs | Mean: 45.53µs
特性
标志 | 描述 | 依赖关系 |
---|---|---|
默认 |
启用compact_strains 特性 |
|
compact_strains |
在Plain Vec中存储内部应变值会在恶意长地图上引入内存不足的风险(见/b/3739922)。此特性更紧凑地存储应变,但性能会损失约5%。 | |
sync |
如果启用此特性,一些逐渐的计算类型才能跨线程共享。这会带来性能惩罚,因此只有当真正需要时才启用。 | |
tracing |
在解码beatmap期间遇到的任何错误将通过tracing::error 进行记录。如果此特性未启用,则错误将被忽略。 |
tracing |
绑定
使用除Rust以外的语言使用rosu-pp
- JavaScript:rosu-pp-js
- Python:rosu-pp-py
依赖关系
~1MB
~22K SLoC