Skip to content

Commit 648db4b

Browse files
committed
♻️ refactor code
1 parent 45f3594 commit 648db4b

File tree

4 files changed

+243
-211
lines changed

4 files changed

+243
-211
lines changed

src/game/behavior.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use super::Game;
2+
use super::GameState;
3+
use ggez::event::{EventHandler, KeyCode};
4+
use ggez::graphics::{self, Color, Text};
5+
use ggez::input::keyboard::KeyMods;
6+
use ggez::timer;
7+
use ggez::GameError;
8+
use ggez::{Context, GameResult};
9+
10+
impl EventHandler<GameError> for GameState {
11+
fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
12+
match self.state {
13+
Game::Playing => {
14+
self.bird_velocity += 0.5;
15+
self.bird_pos[1] += self.bird_velocity;
16+
17+
if self.check_collision(ctx) {
18+
self.game_over();
19+
}
20+
21+
self.obstacle_spawn_timer += timer::delta(ctx).as_secs_f32();
22+
if self.obstacle_spawn_timer > 1.5 {
23+
self.obstacle_spawn_timer = 0.0;
24+
self.add_obstacle(ctx);
25+
}
26+
27+
for obstacle in &mut self.obstacles {
28+
obstacle.top.x -= 2.0;
29+
obstacle.bottom.x -= 2.0;
30+
}
31+
32+
self.obstacles
33+
.retain(|obstacle| obstacle.top.x + obstacle.top.w > 0.0);
34+
35+
self.score();
36+
}
37+
_ => {}
38+
}
39+
40+
Ok(())
41+
}
42+
43+
fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
44+
graphics::clear(ctx, Color::WHITE);
45+
46+
let score_text = Text::new(format!("Score: {}", self.score));
47+
let score_pos = [20.0, 20.0];
48+
graphics::draw(ctx, &score_text, (score_pos, 0.0, Color::BLACK))?;
49+
50+
let bird_scale = graphics::DrawParam::default()
51+
.scale([0.15, 0.15])
52+
.dest([self.bird_pos[0], self.bird_pos[1]]);
53+
graphics::draw(ctx, &self.bird_image, bird_scale)?;
54+
55+
for obstacle in &self.obstacles {
56+
let top_rect = graphics::Mesh::new_rectangle(
57+
ctx,
58+
graphics::DrawMode::fill(),
59+
obstacle.top,
60+
Color::GREEN,
61+
)?;
62+
graphics::draw(ctx, &top_rect, graphics::DrawParam::default())?;
63+
64+
let bottom_rect = graphics::Mesh::new_rectangle(
65+
ctx,
66+
graphics::DrawMode::fill(),
67+
obstacle.bottom,
68+
Color::GREEN,
69+
)?;
70+
graphics::draw(ctx, &bottom_rect, graphics::DrawParam::default())?;
71+
}
72+
73+
if self.state == Game::Menu {
74+
let start_text = Text::new("Press Enter to start");
75+
let start_pos = [320.0, 300.0];
76+
graphics::draw(ctx, &start_text, (start_pos, 0.0, Color::BLACK))?;
77+
}
78+
79+
if self.state == Game::GameOver {
80+
let start_text = Text::new("Press R to restart");
81+
let start_pos = [320.0, 300.0];
82+
graphics::draw(ctx, &start_text, (start_pos, 0.0, Color::BLACK))?;
83+
}
84+
85+
graphics::present(ctx)?;
86+
Ok(())
87+
}
88+
89+
fn key_down_event(
90+
&mut self,
91+
_ctx: &mut Context,
92+
keycode: KeyCode,
93+
_keymods: KeyMods,
94+
_repeat: bool,
95+
) {
96+
match self.state {
97+
Game::Menu => {
98+
if keycode == KeyCode::Return {
99+
self.state = Game::Playing;
100+
}
101+
}
102+
Game::Playing => {
103+
if keycode == KeyCode::Space {
104+
self.bird_velocity = -06.0;
105+
}
106+
}
107+
Game::GameOver => {
108+
if keycode == KeyCode::R {
109+
self.restart(_ctx).expect("Falha ao reiniciar o jogo")
110+
}
111+
}
112+
}
113+
}
114+
}

src/game/controls.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use super::Game;
2+
use super::GameState;
3+
use super::ObstaclePair;
4+
use ggez::graphics;
5+
use ggez::graphics::Rect;
6+
use ggez::{Context, GameResult};
7+
use rand::Rng;
8+
9+
impl GameState {
10+
pub fn add_obstacle(&mut self, _ctx: &mut Context) {
11+
let mut rng = rand::thread_rng();
12+
let gap_y = rng.gen_range(200.0..400.0);
13+
let gap_height = 150.0;
14+
15+
let top_height = gap_y - gap_height / 2.0;
16+
let bottom_y = gap_y + gap_height / 2.0;
17+
let bottom_height = 600.0 - bottom_y;
18+
19+
self.obstacles.push(ObstaclePair {
20+
top: Rect::new(800.0, 0.0, 50.0, top_height),
21+
bottom: Rect::new(800.0, bottom_y, 50.0, bottom_height),
22+
passed: false,
23+
});
24+
}
25+
26+
pub fn check_collision(&self, ctx: &Context) -> bool {
27+
let bird_scale = 0.15;
28+
let bird_width = self.bird_image.width() as f32 * bird_scale;
29+
let bird_height = self.bird_image.height() as f32 * bird_scale;
30+
31+
let bird_rect = Rect::new(self.bird_pos[0], self.bird_pos[1], bird_width, bird_height);
32+
33+
for obstacle in &self.obstacles {
34+
let top_rect = Rect::new(
35+
obstacle.top.x,
36+
obstacle.top.y,
37+
obstacle.top.w,
38+
obstacle.top.h,
39+
);
40+
let bottom_rect = Rect::new(
41+
obstacle.bottom.x,
42+
obstacle.bottom.y,
43+
obstacle.bottom.w,
44+
obstacle.bottom.h,
45+
);
46+
47+
if bird_rect.overlaps(&top_rect) || bird_rect.overlaps(&bottom_rect) {
48+
return true;
49+
}
50+
}
51+
52+
if bird_rect.top() < 0.0 || bird_rect.bottom() > graphics::drawable_size(ctx).1 {
53+
return true;
54+
}
55+
56+
false
57+
}
58+
59+
pub fn game_over(&mut self) {
60+
self.state = Game::GameOver;
61+
}
62+
63+
pub fn score(&mut self) {
64+
let bird_x = self.bird_pos[0] + (self.bird_image.width() as f32 * 0.15);
65+
for obstacle in &mut self.obstacles {
66+
if !obstacle.passed && bird_x > obstacle.top.x + obstacle.top.w {
67+
obstacle.passed = true;
68+
self.score += 1;
69+
}
70+
}
71+
}
72+
73+
pub fn restart(&mut self, _ctx: &mut Context) -> GameResult<()> {
74+
self.state = Game::Playing;
75+
self.bird_pos = [50.0, 50.0];
76+
self.bird_velocity = 0.0;
77+
self.obstacles.clear();
78+
self.obstacle_spawn_timer = 0.0;
79+
self.score = 0;
80+
Ok(())
81+
}
82+
}

src/game/mod.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
mod behavior;
2+
mod controls;
3+
4+
use ggez::graphics::{Image, Rect};
5+
use ggez::{Context, GameResult};
6+
7+
pub struct GameState {
8+
state: Game,
9+
bird_image: Image,
10+
bird_pos: [f32; 2],
11+
bird_velocity: f32,
12+
obstacles: Vec<ObstaclePair>,
13+
obstacle_spawn_timer: f32,
14+
score: i32,
15+
}
16+
17+
impl GameState {
18+
pub fn new(ctx: &mut Context) -> GameResult<GameState> {
19+
let bird_image = Image::new(ctx, "/bird.png")?;
20+
Ok(GameState {
21+
state: Game::Menu,
22+
bird_image,
23+
bird_pos: [50.0, 50.0],
24+
bird_velocity: 0.0,
25+
obstacles: Vec::new(),
26+
obstacle_spawn_timer: 0.0,
27+
score: 0,
28+
})
29+
}
30+
}
31+
32+
#[derive(PartialEq)]
33+
enum Game {
34+
Menu,
35+
Playing,
36+
GameOver,
37+
}
38+
39+
struct ObstaclePair {
40+
top: Rect,
41+
bottom: Rect,
42+
passed: bool,
43+
}

0 commit comments

Comments
 (0)