@@ -428,6 +428,98 @@ impl Player {
428
428
self . beep . play ( Some ( 0 ) , 0 ) ;
429
429
}
430
430
431
+ /// Returns true if the given lane is previously pressed and now unpressed.
432
+ /// When the virtual input is mapped to multiple actual inputs
433
+ /// it can update the internal state but still return false.
434
+ pub fn is_unpressed ( & mut self , lane : Lane , continuous : bool , state : InputState ) -> bool {
435
+ let lane = lane. to_uint ( ) ;
436
+ if state == Neutral || ( continuous && self . joystate [ lane] != state) {
437
+ if continuous {
438
+ self . joystate [ lane] = state;
439
+ true
440
+ } else {
441
+ if self . keymultiplicity [ lane] > 0 {
442
+ self . keymultiplicity [ lane] -= 1 ;
443
+ }
444
+ ( self . keymultiplicity [ lane] == 0 )
445
+ }
446
+ } else {
447
+ false
448
+ }
449
+ }
450
+
451
+ /// Returns true if the given lane is previously unpressed and now pressed.
452
+ /// When the virtual input is mapped to multiple actual inputs
453
+ /// it can update the internal state but still return false.
454
+ pub fn is_pressed ( & mut self , lane : Lane , continuous : bool , state : InputState ) -> bool {
455
+ let lane = lane. to_uint ( ) ;
456
+ if state != Neutral {
457
+ if continuous {
458
+ self . joystate [ lane] = state;
459
+ true
460
+ } else {
461
+ self . keymultiplicity [ lane] += 1 ;
462
+ ( self . keymultiplicity [ lane] == 1 )
463
+ }
464
+ } else {
465
+ false
466
+ }
467
+ }
468
+
469
+ /// Processes the unpress event at given lane:
470
+ /// checks if we need to issue a MISS grade.
471
+ pub fn process_unpress ( & mut self , lane : Lane ) {
472
+ // if LN grading is in progress and it is not within the threshold then
473
+ // MISS grade is issued
474
+ let nextlndone =
475
+ self . thru [ lane. to_uint ( ) ] . as_ref ( ) . and_then ( |thru| {
476
+ thru. find_next_of_type ( |obj| {
477
+ obj. object_lane ( ) == Some ( lane) &&
478
+ obj. is_lndone ( )
479
+ } )
480
+ } ) ;
481
+ for p in nextlndone. iter ( ) {
482
+ let delta = ( p. loc . vtime - self . cur . loc . vtime ) * self . gradefactor ;
483
+ if num:: abs ( delta) < BAD_CUTOFF {
484
+ self . nograding [ p. index ] = true ;
485
+ } else {
486
+ self . update_grade_to_miss ( ) ;
487
+ }
488
+ }
489
+ self . thru [ lane. to_uint ( ) ] = None ;
490
+ }
491
+
492
+ /// Processes the press event at given lane:
493
+ /// plays the closest key sound if any, and grades the closest gradable object if possible.
494
+ pub fn process_press ( & mut self , lane : Lane ) {
495
+ // plays the closest key sound
496
+ let soundable =
497
+ self . cur . find_closest_of_type ( VirtualTime , |obj| {
498
+ obj. object_lane ( ) == Some ( lane) && obj. is_soundable ( )
499
+ } ) ;
500
+ for p in soundable. iter ( ) {
501
+ for & sref in p. sounds ( ) . iter ( ) {
502
+ self . play_sound ( sref, false ) ;
503
+ }
504
+ }
505
+
506
+ // tries to grade the closest gradable object in the grading area
507
+ let gradable =
508
+ self . cur . find_closest_of_type ( VirtualTime , |obj| {
509
+ obj. object_lane ( ) == Some ( lane) && obj. is_gradable ( )
510
+ } ) ;
511
+ for p in gradable. iter ( ) {
512
+ if p. index >= self . checked . index && !self . nograding [ p. index ] && !p. is_lndone ( ) {
513
+ let dist = ( p. loc . vtime - self . cur . loc . vtime ) * self . gradefactor ;
514
+ if num:: abs ( dist) < BAD_CUTOFF {
515
+ if p. is_lnstart ( ) { self . thru [ lane. to_uint ( ) ] = Some ( p. clone ( ) ) ; }
516
+ self . nograding [ p. index ] = true ;
517
+ self . update_grade_from_distance ( dist) ;
518
+ }
519
+ }
520
+ }
521
+ }
522
+
431
523
/// Updates the player state. Returns `true` if the caller should keep calling `tick`.
432
524
pub fn tick ( & mut self ) -> bool {
433
525
let opts_ = self . opts . clone ( ) ;
@@ -446,21 +538,19 @@ impl Player {
446
538
}
447
539
448
540
self . now = get_ticks ( ) ;
449
- let mut cur = self . cur . clone ( ) ;
450
- let mut checked = self . checked . clone ( ) ;
451
- let mut thru = self . thru . clone ( ) ;
452
541
let prev = self . cur . clone ( ) ;
453
542
454
543
let curtime = ( self . now - self . origintime ) as f64 / 1000.0 + self . origin . loc . time ;
455
544
match self . reverse {
456
545
Some ( ref reverse) => {
457
546
assert ! ( self . bpm. to_f64( ) < 0.0 && curtime >= reverse. loc. time) ;
458
547
let newpos = reverse. loc . pos + self . bpm . sec_to_measure ( curtime - reverse. loc . time ) ;
459
- cur. seek ( ActualPos , newpos - cur. loc . pos ) ;
548
+ self . cur . seek ( ActualPos , newpos - self . cur . loc . pos ) ;
460
549
}
461
550
None => {
462
551
// apply object-like effects while advancing `self.cur`
463
- for p in cur. mut_until ( ActualTime , curtime - cur. loc . time ) {
552
+ let mut cur = self . cur . clone ( ) ;
553
+ for p in cur. mut_until ( ActualTime , curtime - self . cur . loc . time ) {
464
554
match p. data ( ) {
465
555
BGM ( sref) => {
466
556
self . play_sound_if_nonzero ( sref, true ) ;
@@ -487,30 +577,33 @@ impl Player {
487
577
_ => { }
488
578
}
489
579
}
580
+ self . cur = cur;
490
581
}
491
582
}
492
583
493
584
// grade objects that have escaped the grading area
494
585
if !opts. is_autoplay ( ) {
495
- for p in checked. mut_upto ( & cur) {
496
- let dist = ( cur. loc . vtime - p. loc . vtime ) * self . gradefactor ;
586
+ let mut checked = self . checked . clone ( ) ;
587
+ for p in checked. mut_upto ( & self . cur ) {
588
+ let dist = ( self . cur . loc . vtime - p. loc . vtime ) * self . gradefactor ;
497
589
if dist < BAD_CUTOFF { break ; }
498
590
499
591
if !self . nograding [ p. index ] {
500
592
for & Lane ( lane) in p. object_lane ( ) . iter ( ) {
501
593
let missable =
502
594
match p. data ( ) {
503
595
Visible ( ..) | LNStart ( ..) => true ,
504
- LNDone ( ..) => thru[ lane] . is_some ( ) ,
596
+ LNDone ( ..) => self . thru [ lane] . is_some ( ) ,
505
597
_ => false ,
506
598
} ;
507
599
if missable {
508
600
self . update_grade_to_miss ( ) ;
509
- thru[ lane] = None ;
601
+ self . thru [ lane] = None ;
510
602
}
511
603
}
512
604
}
513
605
}
606
+ self . checked = checked;
514
607
}
515
608
516
609
// process inputs
@@ -537,91 +630,6 @@ impl Player {
537
630
538
631
if opts. is_exclusive ( ) { continue ; }
539
632
540
- // Returns true if the given lane is previously pressed and now unpressed.
541
- // When the virtual input is mapped to multiple actual inputs it can update
542
- // the internal state but still return false.
543
- let is_unpressed = |lane : Lane , continuous : bool , state : InputState | {
544
- let lane = lane. to_uint ( ) ;
545
- if state == Neutral || ( continuous && self . joystate [ lane] != state) {
546
- if continuous {
547
- self . joystate [ lane] = state; true
548
- } else {
549
- if self . keymultiplicity [ lane] > 0 {
550
- self . keymultiplicity [ lane] -= 1 ;
551
- }
552
- ( self . keymultiplicity [ lane] == 0 )
553
- }
554
- } else {
555
- false
556
- }
557
- } ;
558
-
559
- // Returns true if the given lane is previously unpressed and now pressed.
560
- // When the virtual input is mapped to multiple actual inputs it can update
561
- // the internal state but still return false.
562
- let is_pressed = |lane : Lane , continuous : bool , state : InputState | {
563
- let lane = lane. to_uint ( ) ;
564
- if state != Neutral {
565
- if continuous {
566
- self . joystate [ lane] = state; true
567
- } else {
568
- self . keymultiplicity [ lane] += 1 ;
569
- ( self . keymultiplicity [ lane] == 1 )
570
- }
571
- } else {
572
- false
573
- }
574
- } ;
575
-
576
- let process_unpress = |lane : Lane | {
577
- // if LN grading is in progress and it is not within the threshold then
578
- // MISS grade is issued
579
- for thru in thru[ lane. to_uint ( ) ] . iter ( ) {
580
- let nextlndone = thru. find_next_of_type ( |obj| {
581
- obj. object_lane ( ) == Some ( lane) && obj. is_lndone ( )
582
- } ) ;
583
- for p in nextlndone. iter ( ) {
584
- let delta = ( p. loc . vtime - cur. loc . vtime ) * self . gradefactor ;
585
- if num:: abs ( delta) < BAD_CUTOFF {
586
- self . nograding [ p. index ] = true ;
587
- } else {
588
- self . update_grade_to_miss ( ) ;
589
- }
590
- }
591
- }
592
- thru[ lane. to_uint ( ) ] = None ;
593
- } ;
594
-
595
- let process_press = |lane : Lane | {
596
- // plays the closest key sound
597
- let soundable =
598
- cur. find_closest_of_type ( VirtualTime , |obj| {
599
- obj. object_lane ( ) == Some ( lane) && obj. is_soundable ( )
600
- } ) ;
601
- for p in soundable. iter ( ) {
602
- for & sref in p. sounds ( ) . iter ( ) {
603
- self . play_sound ( sref, false ) ;
604
- }
605
- }
606
-
607
- // tries to grade the closest gradable object in the grading area
608
- let gradable =
609
- cur. find_closest_of_type ( VirtualTime , |obj| {
610
- obj. object_lane ( ) == Some ( lane) && obj. is_gradable ( )
611
- } ) ;
612
- for p in gradable. iter ( ) {
613
- if p. index >= checked. index && !self . nograding [ p. index ] && !p. is_lndone ( ) {
614
- let dist = ( p. loc . vtime - cur. loc . vtime ) * self . gradefactor ;
615
- if num:: abs ( dist) < BAD_CUTOFF {
616
- if p. is_lnstart ( ) { thru[ lane. to_uint ( ) ] = Some ( p. clone ( ) ) ; }
617
- self . nograding [ p. index ] = true ;
618
- self . update_grade_from_distance ( dist) ;
619
- }
620
- }
621
- }
622
- true
623
- } ;
624
-
625
633
match ( vkey, state) {
626
634
( SpeedDownInput , Positive ) | ( SpeedDownInput , Negative ) => {
627
635
let current = self . targetspeed . unwrap_or ( self . playspeed ) ;
@@ -639,11 +647,11 @@ impl Player {
639
647
}
640
648
( LaneInput ( lane) , state) => {
641
649
if !opts. is_autoplay ( ) {
642
- if is_unpressed ( lane, continuous, state) {
643
- process_unpress ( lane) ;
650
+ if self . is_unpressed ( lane, continuous, state) {
651
+ self . process_unpress ( lane) ;
644
652
}
645
- if is_pressed ( lane, continuous, state) {
646
- process_press ( lane) ;
653
+ if self . is_pressed ( lane, continuous, state) {
654
+ self . process_press ( lane) ;
647
655
}
648
656
}
649
657
}
@@ -654,17 +662,17 @@ impl Player {
654
662
655
663
// process bombs
656
664
if !opts. is_autoplay ( ) {
657
- for p in prev. upto ( & cur) {
665
+ for p in prev. upto ( & self . cur ) {
658
666
match p. data ( ) {
659
667
Bomb ( lane, sref, damage) if self . key_pressed ( lane) => {
660
668
// ongoing long note is not graded twice
661
- thru[ lane. to_uint ( ) ] = None ;
669
+ self . thru [ lane. to_uint ( ) ] = None ;
662
670
for & sref in sref. iter ( ) {
663
671
self . play_sound ( sref, false ) ;
664
672
}
665
673
if !self . update_grade_from_damage ( damage) {
666
674
// instant death
667
- self . cur = cur. find_end ( ) ;
675
+ self . cur = self . cur . find_end ( ) ;
668
676
return false ;
669
677
}
670
678
}
@@ -673,10 +681,6 @@ impl Player {
673
681
}
674
682
}
675
683
676
- self . cur = cur;
677
- self . checked = checked;
678
- self . thru = thru;
679
-
680
684
// determines if we should keep playing
681
685
if self . cur . index == self . timeline . borrow ( ) . objs . len ( ) {
682
686
if opts. is_autoplay ( ) {
0 commit comments