item.rs 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. use ggez::graphics;
  2. use crate::{Point2, SCENE_ITEMS_SPRITE_SHEET_HEIGHT, SCENE_ITEMS_SPRITE_SHEET_WIDTH};
  3. use crate::behavior::ItemBehavior;
  4. use crate::physics::{MetaEvent, util};
  5. use crate::physics::position::GridPosition;
  6. use crate::scene::SpriteType;
  7. pub struct SceneItemSpriteInfo {
  8. pub relative_start_y: f32,
  9. pub relative_tile_width: f32,
  10. pub relative_tile_height: f32,
  11. pub tile_count: u16,
  12. pub tile_width: f32,
  13. pub tile_height: f32,
  14. pub _half_tile_width: f32,
  15. pub _half_tile_height: f32,
  16. }
  17. impl SceneItemSpriteInfo {
  18. // TODO: ask on rust community if this is performant, or how to make it static
  19. pub fn from_type(type_: &SpriteType) -> Self {
  20. let (start_y, tile_width, tile_height, tile_count) = match type_ {
  21. SpriteType::WalkingSoldier => (12.0, 12.0, 12.0, 8),
  22. SpriteType::CrawlingSoldier => (26.0, 26.0, 26.0, 8),
  23. SpriteType::StandingSoldier => (0.0, 12.0, 12.0, 1),
  24. };
  25. Self {
  26. relative_start_y: start_y / SCENE_ITEMS_SPRITE_SHEET_HEIGHT,
  27. relative_tile_width: tile_width / SCENE_ITEMS_SPRITE_SHEET_WIDTH,
  28. relative_tile_height: tile_height / SCENE_ITEMS_SPRITE_SHEET_HEIGHT,
  29. tile_count,
  30. tile_width,
  31. tile_height,
  32. _half_tile_width: tile_width / 2.0,
  33. _half_tile_height: tile_height / 2.0,
  34. }
  35. }
  36. }
  37. pub struct ItemState {
  38. pub current_behavior: ItemBehavior,
  39. }
  40. impl ItemState {
  41. pub fn new(current_behavior: ItemBehavior) -> Self {
  42. Self { current_behavior }
  43. }
  44. }
  45. pub enum SceneItemType {
  46. Soldier,
  47. }
  48. pub struct SceneItem {
  49. pub type_: SceneItemType,
  50. pub position: Point2,
  51. pub grid_position: GridPosition,
  52. pub state: ItemState,
  53. pub meta_events: Vec<MetaEvent>,
  54. pub current_frame: u16,
  55. }
  56. impl SceneItem {
  57. pub fn new(type_: SceneItemType, position: Point2, state: ItemState) -> Self {
  58. Self {
  59. type_,
  60. position: position.clone(),
  61. grid_position: util::grid_position_from_position(&position.clone()),
  62. state,
  63. meta_events: vec![],
  64. current_frame: 0,
  65. }
  66. }
  67. pub fn sprite_info(&self) -> SceneItemSpriteInfo {
  68. SceneItemSpriteInfo::from_type(&self.sprite_type())
  69. }
  70. pub fn tick_sprite(&mut self) {
  71. self.current_frame += 1;
  72. // TODO: good way to have sprite info ? performant ?
  73. if self.current_frame >= self.sprite_info().tile_count {
  74. self.current_frame = 0;
  75. }
  76. }
  77. pub fn as_draw_param(&self, current_frame: f32) -> graphics::DrawParam {
  78. let sprite_info = self.sprite_info();
  79. graphics::DrawParam::new()
  80. .src(graphics::Rect::new(
  81. current_frame as f32 * sprite_info.relative_tile_width,
  82. sprite_info.relative_start_y,
  83. sprite_info.relative_tile_width,
  84. sprite_info.relative_tile_height,
  85. ))
  86. .rotation(90.0f32.to_radians())
  87. .offset(Point2::new(0.5, 0.5))
  88. }
  89. pub fn sprite_type(&self) -> SpriteType {
  90. // Here some logical about state, nature (soldier, tank, ...) and current behavior to
  91. // determine sprite type
  92. match self.state.current_behavior {
  93. ItemBehavior::Crawling => SpriteType::CrawlingSoldier,
  94. ItemBehavior::Walking(_) => SpriteType::WalkingSoldier,
  95. ItemBehavior::Standing(_) => SpriteType::StandingSoldier,
  96. }
  97. }
  98. }