rust impl
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

137 wiersze
3.9 KiB

  1. // modules
  2. mod tile;
  3. // namespacing
  4. use crate::{util::*, MainState, Result};
  5. use ggez::{
  6. graphics::{self, DrawParam},
  7. Context,
  8. };
  9. use mint::{Point2, Vector2, Vector3};
  10. use std::{collections::HashMap, path::PathBuf};
  11. use tile::*;
  12. /// represent a whole rendered world
  13. pub struct World {
  14. width: isize,
  15. depth: isize,
  16. height: isize,
  17. data: HashMap<Vector3<isize>, Tile>,
  18. builder: TileBuilder,
  19. offset: Point2<f32>,
  20. zoom: Vector2<f32>,
  21. }
  22. impl World {
  23. /// create a new world instance
  24. pub fn new(
  25. ctx: &mut Context,
  26. tile_config: PathBuf,
  27. width: isize,
  28. depth: isize,
  29. height: isize,
  30. ) -> Result<World> {
  31. let builder = TileBuilder::new(ctx, tile_config)?;
  32. let mut data: HashMap<Vector3<isize>, Tile> = HashMap::new();
  33. let offset: Point2<f32> = [350.0f32, 100.0f32].into();
  34. let zoom: Vector2<f32> = [1.0f32, 1.0f32].into();
  35. for x in 0..width {
  36. for y in 0..depth {
  37. for z in 0..height {
  38. data.insert([x, y, z].into(), builder.build("nothing".to_owned())?);
  39. }
  40. }
  41. }
  42. Ok(World {
  43. width,
  44. height,
  45. depth,
  46. data,
  47. builder: builder,
  48. offset,
  49. zoom,
  50. })
  51. }
  52. /// renders the world to the window
  53. pub fn render(&self, ctx: &mut Context) -> Result<()> {
  54. for x in 0..self.width {
  55. for y in 0..self.depth {
  56. for z in 0..self.height {
  57. let tile = self.data.get(&[x, y, z].into()).unwrap();
  58. let iso_coord: IsometricVector2 = Point2::from([x as f32, y as f32]).into();
  59. let scale = [self.zoom.x, self.zoom.y];
  60. let dest = [
  61. iso_coord.x() * (self.builder.tile_width() / 2.0) * scale[0]
  62. + self.offset.x,
  63. iso_coord.y() * (self.builder.tile_height() / 2.0) * scale[1]
  64. + self.offset.y,
  65. ];
  66. let param = DrawParam::default()
  67. .dest(Point2::from_slice(&dest))
  68. .scale(Point2::from_slice(&scale));
  69. graphics::draw(ctx, tile.texture(), param)?;
  70. }
  71. }
  72. }
  73. Ok(())
  74. }
  75. }
  76. /// action struct for wrapping offsetting input
  77. #[derive(Debug)]
  78. pub struct OffsetAction(Vector2<f32>);
  79. impl OffsetAction {
  80. /// construct a new offset action
  81. pub fn new(offset: Vector2<f32>) -> OffsetAction {
  82. OffsetAction(offset)
  83. }
  84. }
  85. impl crate::Action for OffsetAction {
  86. fn execute(&self, _ctx: &mut Context, state: &mut MainState) -> Result<()> {
  87. state.world.offset.x =
  88. self.0.x * (state.world.builder.tile_width() / 2.0) + state.world.offset.x;
  89. state.world.offset.y =
  90. self.0.y * (state.world.builder.tile_height() / 2.0) + state.world.offset.y;
  91. Ok(())
  92. }
  93. fn undo(&self, _ctx: &mut Context, state: &mut MainState) -> Result<()> {
  94. state.world.offset.x = state.world.offset.x - self.0.x;
  95. state.world.offset.y = state.world.offset.y - self.0.y;
  96. Ok(())
  97. }
  98. }
  99. /// action struct for wrapping zoom input
  100. #[derive(Debug)]
  101. pub struct ZoomAction(Vector2<f32>);
  102. impl ZoomAction {
  103. /// construct a new scale action
  104. pub fn new(scale: Vector2<f32>) -> ZoomAction {
  105. ZoomAction(scale)
  106. }
  107. }
  108. impl crate::Action for ZoomAction {
  109. fn execute(&self, _ctx: &mut Context, state: &mut MainState) -> Result<()> {
  110. state.world.zoom.x = self.0.x + state.world.zoom.x;
  111. state.world.zoom.y = self.0.y + state.world.zoom.y;
  112. Ok(())
  113. }
  114. fn undo(&self, _ctx: &mut Context, state: &mut MainState) -> Result<()> {
  115. state.world.zoom.x = state.world.zoom.x - self.0.x;
  116. state.world.zoom.y = state.world.zoom.y - self.0.y;
  117. Ok(())
  118. }
  119. }