1
1
use image:: GenericImageView ;
2
2
use minifb:: { Key , Window , WindowOptions } ;
3
3
use rand:: Rng ;
4
- use std:: time:: Instant ;
4
+ use std:: time:: { Duration , Instant } ;
5
5
6
6
use image_utils:: { convert_to_mono, draw_raindrop, draw_square, is_collision} ;
7
7
use image_utils:: { get_background_for_score, load_background_data} ;
@@ -11,8 +11,9 @@ mod image_utils;
11
11
const DROP_SIZE : u32 = 6 ;
12
12
const NUM_DROPS : usize = 8 ;
13
13
const DROP_DELAY : f32 = 0.5 ; // Delay in seconds for staggered start of each drop
14
- const DROP_SPEED : f32 = 0.0001 ; // Time-based speed (larger values make drops fall slower)
14
+ const DROP_SPEED : f32 = 200.0 ; // Speed in pixels per second
15
15
const WINNING_SCORE : i32 = 30 ; // Score required to win
16
+ const TARGET_FPS : f32 = 60.0 ;
16
17
17
18
struct Raindrop {
18
19
x : u32 ,
@@ -64,12 +65,16 @@ fn main() {
64
65
. map ( |i| Raindrop {
65
66
x : rand:: thread_rng ( ) . gen_range ( 0 ..width - DROP_SIZE ) ,
66
67
y : 0 ,
67
- start_time : Instant :: now ( ) + std :: time :: Duration :: from_secs_f32 ( i as f32 * DROP_DELAY ) ,
68
+ start_time : Instant :: now ( ) + Duration :: from_secs_f32 ( i as f32 * DROP_DELAY ) ,
68
69
last_update : Instant :: now ( ) ,
69
70
} )
70
71
. collect ( ) ;
71
72
73
+ let frame_duration = Duration :: from_secs_f32 ( 1.0 / TARGET_FPS ) ;
74
+
72
75
while window. is_open ( ) && !window. is_key_down ( Key :: Escape ) {
76
+ let frame_start = Instant :: now ( ) ;
77
+
73
78
if score >= WINNING_SCORE {
74
79
println ! ( "You win! Final Score: {}" , score) ;
75
80
@@ -96,16 +101,16 @@ fn main() {
96
101
97
102
// Cursor movement
98
103
if window. is_key_down ( Key :: Up ) && cursor_y > 0 {
99
- cursor_y -= 1 ;
104
+ cursor_y = cursor_y . saturating_sub ( 5 ) ;
100
105
}
101
106
if window. is_key_down ( Key :: Down ) && cursor_y + square_size < height {
102
- cursor_y += 1 ;
107
+ cursor_y = cursor_y . saturating_add ( 5 ) ;
103
108
}
104
109
if window. is_key_down ( Key :: Left ) && cursor_x > 0 {
105
- cursor_x -= 1 ;
110
+ cursor_x = cursor_x . saturating_sub ( 5 ) ;
106
111
}
107
112
if window. is_key_down ( Key :: Right ) && cursor_x + square_size < width {
108
- cursor_x += 1 ;
113
+ cursor_x = cursor_x . saturating_add ( 5 ) ;
109
114
}
110
115
111
116
let cat_rect = ( cat_x, cat_y, cat_width, square_size) ;
@@ -115,12 +120,13 @@ fn main() {
115
120
// Update raindrops
116
121
for drop in raindrops. iter_mut ( ) {
117
122
if drop. start_time . elapsed ( ) . as_secs_f32 ( ) > 0.0 {
118
- if drop. y < height - DROP_SIZE
119
- && drop. last_update . elapsed ( ) . as_secs_f32 ( ) > DROP_SPEED
120
- {
121
- drop. y += 1 ;
123
+ let elapsed = drop. last_update . elapsed ( ) . as_secs_f32 ( ) ;
124
+ let pixels_to_move = ( elapsed * DROP_SPEED ) . round ( ) as u32 ;
125
+
126
+ if drop. y < height - DROP_SIZE {
127
+ drop. y += pixels_to_move;
122
128
drop. last_update = Instant :: now ( ) ;
123
- } else if drop . y >= height - DROP_SIZE {
129
+ } else {
124
130
drop. y = 0 ;
125
131
drop. x = rand:: thread_rng ( ) . gen_range ( 0 ..width - DROP_SIZE ) ;
126
132
}
@@ -155,7 +161,10 @@ fn main() {
155
161
. update_with_buffer ( & buffer, width as usize , height as usize )
156
162
. expect ( "Failed to update window buffer" ) ;
157
163
158
- print ! ( "\x1B [2J\x1B [1;1H" ) ;
159
- println ! ( "Score: {}" , score) ;
164
+ // Cap FPS
165
+ let elapsed = frame_start. elapsed ( ) ;
166
+ if elapsed < frame_duration {
167
+ std:: thread:: sleep ( frame_duration - elapsed) ;
168
+ }
160
169
}
161
170
}
0 commit comments