Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: note render, hitfx render, rating #472

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ inner.rs
/test
/log*
/build_event_debug.sh
/.idea
31 changes: 30 additions & 1 deletion prpr/src/bin.rs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先不动bin.rs

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::{
},
judge::{HitSound, JudgeStatus},
parse::process_lines,
info::ChartFormat,
};
use anyhow::{bail, Result};
use byteorder::{LittleEndian as LE, ReadBytesExt, WriteBytesExt};
Expand Down Expand Up @@ -154,6 +155,32 @@ impl BinaryData for bool {
}
}

impl BinaryData for ChartFormat {
fn read_binary<R: Read>(r: &mut BinaryReader<R>) -> Result<Self> {
match r.read::<u8>()? {
0 => Ok(ChartFormat::Rpe),
1 => Ok(ChartFormat::Pec),
2 => Ok(ChartFormat::Pgr),
3 => Ok(ChartFormat::Pgr1),
4 => Ok(ChartFormat::Pbc),
_ => bail!("invalid chart format"),
}
}

fn write_binary<W: Write>(&self, w: &mut BinaryWriter<W>) -> Result<()> {
w.write_val(
match self {
ChartFormat::Rpe => 0,
ChartFormat::Pec => 1,
ChartFormat::Pgr => 2,
ChartFormat::Pgr1 => 3,
ChartFormat::Pbc => 4,
}
)?;
Ok(())
}
}

impl BinaryData for f32 {
fn read_binary<R: Read>(r: &mut BinaryReader<R>) -> Result<Self> {
Ok(r.0.read_f32::<LE>()?)
Expand Down Expand Up @@ -322,6 +349,7 @@ impl BinaryData for Note {
1 => NoteKind::Hold {
end_time: r.read()?,
end_height: r.read()?,
end_speed: if r.read()? { r.read::<f32>()? } else { 1. },
},
2 => NoteKind::Flick,
3 => NoteKind::Drag,
Expand All @@ -348,10 +376,11 @@ impl BinaryData for Note {
NoteKind::Click => {
w.write_val(0_u8)?;
}
NoteKind::Hold { end_time, end_height } => {
NoteKind::Hold { end_time, end_height, end_speed } => {
w.write_val(1_u8)?;
w.write_val(end_time)?;
w.write_val(end_height)?;
w.write_val(end_speed)?;
}
NoteKind::Flick => w.write_val(2_u8)?,
NoteKind::Drag => w.write_val(3_u8)?,
Expand Down
22 changes: 22 additions & 0 deletions prpr/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ impl BpmList {
BpmList { elements, cursor: 0 }
}

pub fn new_time(ranges: Vec<(f32, f32)>) -> Self {
let mut elements = Vec::new();
for (time, bpm) in ranges {
elements.push((time, time, bpm));
}
BpmList { elements, cursor: 0 }
}

/// Get the time in seconds for a given beats
pub fn time_beats(&mut self, beats: f32) -> f32 {
while let Some(kf) = self.elements.get(self.cursor + 1) {
Expand Down Expand Up @@ -157,4 +165,18 @@ impl BpmList {
let (beats, start_time, bpm) = &self.elements[self.cursor];
beats + (time - start_time) / (60. / bpm)
}

pub fn now_bpm(&mut self, time: f32) -> f32 {
while let Some(kf) = self.elements.get(self.cursor + 1) {
if kf.1 > time {
break;
}
self.cursor += 1;
}
while self.cursor != 0 && self.elements[self.cursor].1 > time {
self.cursor -= 1;
}
let (_, _, bpm) = &self.elements[self.cursor];
*bpm
}
}
6 changes: 4 additions & 2 deletions prpr/src/core/chart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ impl Chart {
}
// TODO optimize
let trs = self.lines.iter().map(|it| it.now_transform(res, &self.lines)).collect::<Vec<_>>();
for (line, tr) in self.lines.iter_mut().zip(trs) {
line.update(res, tr);
let mut guard = self.bpm_list.borrow_mut();
for (index, (line, tr)) in self.lines.iter_mut().zip(trs).enumerate() {
line.update(res, tr, &mut guard, index);
}
drop(guard);
for effect in &mut self.extra.effects {
effect.update(res);
}
Expand Down
21 changes: 19 additions & 2 deletions prpr/src/core/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::{
ext::{draw_text_aligned, get_viewport, NotNanExt, SafeTexture},
judge::{JudgeStatus, LIMIT_BAD},
ui::Ui,
info::ChartFormat,
};
use macroquad::prelude::*;
use miniquad::{RenderPass, Texture, TextureParams, TextureWrap};
Expand Down Expand Up @@ -157,15 +158,15 @@ pub struct JudgeLine {
}

impl JudgeLine {
pub fn update(&mut self, res: &mut Resource, tr: Matrix) {
pub fn update(&mut self, res: &mut Resource, tr: Matrix, bpm_list: &mut BpmList, index: usize) {
// self.object.set_time(res.time); // this is done by chart, chart has to calculate transform for us
let rot = self.object.rotation.now();
self.height.set_time(res.time);
let line_height = self.height.now();
let mut ctrl_obj = self.ctrl_obj.borrow_mut();
self.cache.update_order.retain(|id| {
let note = &mut self.notes[*id as usize];
note.update(res, rot, &tr, &mut ctrl_obj, line_height);
note.update(res, rot, &tr, &mut ctrl_obj, line_height, bpm_list, index);
!note.dead()
});
drop(ctrl_obj);
Expand Down Expand Up @@ -381,6 +382,14 @@ impl JudgeLine {
let height_below = -p[0].y.min(p[1].y.min(p[2].y.min(p[3].y))) * res.aspect_ratio;
let agg = res.config.aggressive;
for note in self.notes.iter().take(self.cache.not_plain_count).filter(|it| it.above) {
let line_height = {
let mut height = self.height.clone();
height.set_time(note.time.min(res.time));
height.now()
};
if agg && note.height - line_height + note.object.translation.1.now() > height_above / note.speed && matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Rpe) {
break;
}
note.render(res, &mut config, bpm_list);
}
for index in &self.cache.above_indices {
Expand All @@ -398,6 +407,14 @@ impl JudgeLine {
}
res.with_model(Matrix::identity().append_nonuniform_scaling(&Vector::new(1.0, -1.0)), |res| {
for note in self.notes.iter().take(self.cache.not_plain_count).filter(|it| !it.above) {
let line_height = {
let mut height = self.height.clone();
height.set_time(note.time.min(res.time));
height.now()
};
if agg && note.height - line_height + note.object.translation.1.now() > height_below / note.speed && matches!(res.chart_format, ChartFormat::Pgr | ChartFormat::Rpe) {
break;
}
note.render(res, &mut config, bpm_list);
}
for index in &self.cache.below_indices {
Expand Down
37 changes: 26 additions & 11 deletions prpr/src/core/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ use super::{chart::ChartSettings, BpmList, CtrlObject, JudgeLine, Matrix, Object
pub use crate::{
judge::{HitSound, JudgeStatus},
parse::RPE_HEIGHT,
core::HEIGHT_RATIO,
info::ChartFormat,
};
use macroquad::prelude::*;

const HOLD_PARTICLE_INTERVAL: f32 = 0.15;
//const HOLD_PARTICLE_INTERVAL: f32 = 0.15;
const FADEOUT_TIME: f32 = 0.16;
const BAD_TIME: f32 = 0.5;

#[derive(Clone, Debug)]
pub enum NoteKind {
Click,
Hold { end_time: f32, end_height: f32 },
Hold { end_time: f32, end_height: f32, end_speed: f32 },
Flick,
Drag,
}
Expand Down Expand Up @@ -134,11 +136,14 @@ impl Note {
// && self.ctrl_obj.is_default()
}

pub fn update(&mut self, res: &mut Resource, parent_rot: f32, parent_tr: &Matrix, ctrl_obj: &mut CtrlObject, line_height: f32) {
pub fn update(&mut self, res: &mut Resource, parent_rot: f32, parent_tr: &Matrix, ctrl_obj: &mut CtrlObject, line_height: f32, bpm_list: &mut BpmList, index: usize) {
self.object.set_time(res.time);
if let Some(color) = if let JudgeStatus::Hold(perfect, at, ..) = &mut self.judge {
if res.time > *at {
*at += HOLD_PARTICLE_INTERVAL / res.config.speed;
if let Some(color) = if let JudgeStatus::Hold(perfect, ref mut at, ..) = &mut self.judge {
if res.time >= *at {
let beat = 30. / bpm_list.now_bpm(
if matches!(res.chart_format, ChartFormat::Pgr) { index as f32 } else { self.time }
);
*at = res.time + beat / res.config.speed;
Some(if *perfect {
res.res_pack.info.fx_perfect()
} else {
Expand Down Expand Up @@ -207,7 +212,7 @@ impl Note {

let base = height - line_height;
if !config.draw_below
&& ((res.time - FADEOUT_TIME >= self.time) || (self.fake && res.time >= self.time) || (self.time > res.time && base <= -1e-5))
&& ((res.time - FADEOUT_TIME >= self.time) || (self.fake && res.time >= self.time) || (self.time > res.time && base <= -0.001))
&& !matches!(self.kind, NoteKind::Hold { .. })
{
return;
Expand All @@ -231,7 +236,7 @@ impl Note {
NoteKind::Click => {
draw(res, *style.click);
}
NoteKind::Hold { end_time, end_height } => {
NoteKind::Hold { end_time, end_height, end_speed } => {
res.with_model(self.now_transform(res, ctrl_obj, 0., 0.), |res| {
let style = if res.config.double_hint && self.multiple_hint {
&res.res_pack.note_style_mh
Expand All @@ -251,14 +256,24 @@ impl Note {

let h = if self.time <= res.time { line_height } else { height };
let bottom = h - line_height;
let top = end_height - line_height;
if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover {
let top = if matches!(res.chart_format, ChartFormat::Pgr) {
let end_spd = end_speed * ctrl_obj.y.now_opt().unwrap_or(1.);
if end_spd == 0. {
return;
}
let time = if res.time >= self.time {res.time} else {self.time};
let hold_height = end_height - height;
let hold_line_height = (time - self.time) * end_spd / res.aspect_ratio / HEIGHT_RATIO;
bottom + hold_height - hold_line_height
} else {
end_height - line_height
};
if res.time < self.time && bottom < -1e-6 && !config.settings.hold_partial_cover && !matches!(res.chart_format, ChartFormat::Pgr) {
return;
}
let tex = &style.hold;
let ratio = style.hold_ratio();
// body
// TODO (end_height - height) is not always total height
draw_tex(
res,
**(if res.res_pack.info.hold_repeat {
Expand Down
4 changes: 4 additions & 0 deletions prpr/src/core/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::{
path::Path,
sync::atomic::AtomicU32,
};
use crate::info::ChartFormat;

pub const MAX_SIZE: usize = 64; // needs tweaking
pub static DPI_VALUE: AtomicU32 = AtomicU32::new(250);
Expand Down Expand Up @@ -344,6 +345,7 @@ pub type SfxMap = HashMap<String, Sfx>;

pub struct Resource {
pub config: Config,
pub chart_format: ChartFormat,
pub info: ChartInfo,
pub aspect_ratio: f32,
pub dpi: u32,
Expand Down Expand Up @@ -411,6 +413,7 @@ impl Resource {

pub async fn new(
config: Config,
chart_format: ChartFormat,
info: ChartInfo,
mut fs: Box<dyn FileSystem>,
player: Option<SafeTexture>,
Expand Down Expand Up @@ -451,6 +454,7 @@ impl Resource {
macroquad::window::gl_set_drawcall_buffer_capacity(MAX_SIZE * 4, MAX_SIZE * 6);
Ok(Self {
config,
chart_format,
info,
aspect_ratio,
dpi: DPI_VALUE.load(std::sync::atomic::Ordering::SeqCst),
Expand Down
1 change: 1 addition & 0 deletions prpr/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub enum ChartFormat {
Rpe = 0,
Pec,
Pgr,
Pgr1,
Pbc,
}

Expand Down
14 changes: 8 additions & 6 deletions prpr/src/judge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,6 @@ impl Judge {
}
}
for (line_id, id) in judgements.into_iter() {
self.commit(t, Judgement::Perfect, line_id as _, id, 0.);
let (note_transform, note_hitsound) = {
let line = &mut chart.lines[line_id];
let note = &mut line.notes[id as usize];
Expand All @@ -863,11 +862,14 @@ impl Judge {
(note.object.now(res), note.hitsound.clone())
};
let line = &chart.lines[line_id];
res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| {
res.emit_at_origin(line.notes[id as usize].rotation(&line), res.res_pack.info.fx_perfect())
});
if !matches!(chart.lines[line_id].notes[id as usize].kind, NoteKind::Hold { .. }) {
self.commit(t, Judgement::Perfect, line_id as _, id, 0.);
res.with_model(line.now_transform(res, &chart.lines) * note_transform, |res| {
res.emit_at_origin(line.notes[id as usize].rotation(line), res.res_pack.info.fx_perfect())
});
note_hitsound.play(res);
} else {
self.commit(t, Judgement::Perfect, line_id as _, id, 0.);
}
}
}
Expand Down Expand Up @@ -968,13 +970,13 @@ pub struct PlayResult {

pub fn icon_index(score: u32, full_combo: bool) -> usize {
match (score, full_combo) {
(1000000, _) => 7,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

combo数太大这里有点问题吧,是不是该改1000000, true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本家中实测无论什么情况,只要分数是1000000就是AP,所以我改成了这样(
那我改一下吧

(_, true) => 6,
(x, _) if x < 700000 => 0,
(x, _) if x < 820000 => 1,
(x, _) if x < 880000 => 2,
(x, _) if x < 920000 => 3,
(x, _) if x < 960000 => 4,
(1000000, _) => 7,
(_, false) => 5,
(_, true) => 6,
}
}
2 changes: 1 addition & 1 deletion prpr/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod pec;
pub use pec::parse_pec;

mod pgr;
pub use pgr::parse_phigros;
pub use pgr::{parse_phigros, parse_phigros_fv1};

mod rpe;
pub use rpe::{parse_rpe, RPE_HEIGHT, RPE_WIDTH};
Expand Down
3 changes: 2 additions & 1 deletion prpr/src/parse/pec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ fn parse_judge_line(mut pec: PECJudgeLine, id: usize, max_time: f32) -> Result<J
for note in notes {
height.set_time(note.time);
note.height = height.now();
if let NoteKind::Hold { end_time, end_height } = &mut note.kind {
if let NoteKind::Hold { end_time, end_height,end_speed: _ } = &mut note.kind {
height.set_time(*end_time);
*end_height = height.now();
}
Expand Down Expand Up @@ -244,6 +244,7 @@ pub fn parse_pec(source: &str, extra: ChartExtra) -> Result<Chart> {
'2' => NoteKind::Hold {
end_time: it.take_time(r)?,
end_height: 0.0,
end_speed: 1.0,
},
'3' => NoteKind::Flick,
'4' => NoteKind::Drag,
Expand Down
Loading