rsnaker/graphics/sprites/
fruit.rs

1//! # Fruit Management Module
2//!
3//! This module defines the `Fruit` struct, which represents different fruits in the game logic and provides the
4//!  ability to create, position, and render them.
5//!
6//! The `FRUITS_SCORES_PROBABILITIES` constant defines various fruits with their respective scores and spawn probabilities.
7//!
8//! # Example
9//! ```rust
10//! use rsnaker::graphics::sprites::fruit::Fruit;
11//! use rsnaker::graphics::graphic_block::Position;
12//!
13//! let position = Position { x: 5, y: 10 };
14//! let apple = Fruit::new(40, 2,position, "🍎");
15//! assert_eq!(apple.get_score(), 40);
16//! ```
17//!
18
19use crate::graphics::graphic_block::{GraphicBlock, Position};
20use ratatui::buffer::Buffer;
21use ratatui::layout::Rect;
22use ratatui::prelude::Widget;
23use ratatui::style::Style;
24use ratatui::widgets::WidgetRef;
25
26/// Distribution statistics with weighted lottery / pie chart parts.
27/// image, score, probability, size effect
28///
29pub const FRUITS_SCORES_PROBABILITIES: &[(&str, i32, u16, i16)] = &[
30    ("🍇", 5, 5, 0),
31    ("🍉", 10, 15, 0),
32    ("🍋", 15, 10, 10),
33    ("🍌", 20, 15, 10),
34    ("🍐", 30, 10, 10),
35    ("🍎", 40, 10, 15),
36    ("🥝", 50, 10, 15),
37    ("🍓", 60, 5, 15),
38    ("🍒", 70, 5, 20),
39    ("🥥", 0, 5, -20),
40    ("🦞", -10, 5, -100),
41];
42
43/// Represents a fruit on the map.
44/// Fruits have a score value and are displayed as graphical blocks.
45#[derive(PartialEq, Debug, Clone)]
46pub struct Fruit<'a> {
47    score: i32,
48    grow_snake: i16,
49    graphic_block: GraphicBlock<'a>,
50}
51
52impl<'a> Fruit<'a> {
53    /// Creates a new `Fruit` at a given position with an associated score and image.
54    #[must_use]
55    pub fn new(
56        score: i32,
57        grow_snake_by_relative_nb: i16,
58        position: Position,
59        image: &'a str,
60    ) -> Fruit<'a> {
61        Self {
62            score,
63            grow_snake: grow_snake_by_relative_nb,
64            graphic_block: GraphicBlock::new(position, image, Style::default()),
65        }
66    }
67
68    /// Checks if the fruit is at a specific position.
69    #[must_use]
70    pub fn is_at_position(&self, position: &Position) -> bool {
71        self.graphic_block.get_position() == position
72    }
73    /// Checks if the fruit is at a specific position.
74    pub fn set_position(&mut self, position: Position) {
75        self.graphic_block.set_position(position);
76    }
77
78    /// Returns the score of the fruit.
79    #[must_use]
80    pub fn get_score(&self) -> i32 {
81        self.score
82    }
83    #[must_use]
84    pub fn get_grow_snake(&self) -> i16 {
85        self.grow_snake
86    }
87}
88
89/// Enables `Fruit` to be rendered as a widget.
90impl Widget for Fruit<'_> {
91    fn render(self, area: Rect, buf: &mut Buffer) {
92        self.graphic_block.render(area, buf);
93    }
94}
95
96/// Enables `Fruit` to be rendered as a reference widget.
97impl WidgetRef for Fruit<'_> {
98    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
99        self.graphic_block.render_ref(area, buf);
100    }
101}