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///Yet pear, or strawberry ("🍓", 60, 5, 15),
29/// In order: Symbol, score effect, probability, size effect
30pub const FRUITS_SCORES_PROBABILITIES: &[(&str, i32, u16, i16)] = &[
31    ("🦞", -50, 5, -150),
32    ("🥥", -10, 5, -40),
33    ("🍇", 5, 4, 0),
34    ("🍐", 10, 10, 5),
35    ("🥝", 20, 10, 8),
36    ("🍋", 30, 15, 10),
37    ("🍌", 40, 15, 15),
38    ("🍉", 50, 15, 15),
39    ("🍎", 75, 15, 15),
40    ("🍓", 100, 5, 20),
41    ("🍒", 200, 1, 25),
42];
43
44/// Represents a fruit on the map.
45/// Fruits have a score value and are displayed as graphical blocks.
46#[derive(PartialEq, Debug, Clone)]
47pub struct Fruit<'a> {
48    score: i32,
49    grow_snake: i16,
50    graphic_block: GraphicBlock<'a>,
51}
52
53impl<'a> Fruit<'a> {
54    /// Creates a new `Fruit` at a given position with an associated score and image.
55    #[must_use]
56    pub fn new(
57        score: i32,
58        grow_snake_by_relative_nb: i16,
59        position: Position,
60        image: &'a str,
61    ) -> Fruit<'a> {
62        Self {
63            score,
64            grow_snake: grow_snake_by_relative_nb,
65            graphic_block: GraphicBlock::new(position, image, Style::default()),
66        }
67    }
68
69    /// Checks if the fruit is at a specific position.
70    #[must_use]
71    pub fn is_at_position(&self, position: &Position) -> bool {
72        self.graphic_block.get_position() == position
73    }
74    /// Checks if the fruit is at a specific position.
75    pub fn set_position(&mut self, position: Position) {
76        self.graphic_block.set_position(position);
77    }
78
79    /// Returns the score of the fruit.
80    #[must_use]
81    pub fn get_score(&self) -> i32 {
82        self.score
83    }
84    #[must_use]
85    pub fn get_grow_snake(&self) -> i16 {
86        self.grow_snake
87    }
88}
89
90/// Enables `Fruit` to be rendered as a widget.
91impl Widget for Fruit<'_> {
92    fn render(self, area: Rect, buf: &mut Buffer) {
93        self.graphic_block.render(area, buf);
94    }
95}
96
97/// Enables `Fruit` to be rendered as a reference widget.
98impl WidgetRef for Fruit<'_> {
99    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
100        self.graphic_block.render_ref(area, buf);
101    }
102}