item.rs 3.7KB

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