rust impl
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

171 lignes
4.7 KiB

  1. #![allow(unused_imports)]
  2. // mods
  3. mod util;
  4. mod world;
  5. // namespacing
  6. use ggez::{
  7. conf::{WindowMode, WindowSetup},
  8. event::{self, EventHandler, KeyCode, KeyMods},
  9. graphics, Context, ContextBuilder, GameResult,
  10. };
  11. use std::collections::VecDeque;
  12. use world::World;
  13. /// lazy result type
  14. pub type Result<T> = std::result::Result<T, Error>;
  15. // error types
  16. #[derive(Debug, thiserror::Error)]
  17. pub enum Error {
  18. // external errors
  19. #[error(transparent)]
  20. Stdio(#[from] std::io::Error),
  21. #[error(transparent)]
  22. Toml(#[from] toml::de::Error),
  23. #[error(transparent)]
  24. Ggez(#[from] ggez::error::GameError),
  25. // internal errors
  26. #[error("could not find {expected} MasterTile on TileBuilder")]
  27. NoMasterTile { expected: String },
  28. }
  29. // primary game state
  30. pub struct MainState {
  31. world: World,
  32. action_buffer: Vec<Box<dyn Action>>,
  33. action_history: VecDeque<Box<dyn Action>>,
  34. action_history_max_length: usize,
  35. }
  36. impl MainState {
  37. // create a new gamestate
  38. pub fn new(ctx: &mut Context) -> Result<MainState> {
  39. let world = World::new(ctx, "/data/tile_conf.toml".into(), 20, 20, 1)?;
  40. Ok(MainState {
  41. world,
  42. action_history_max_length: 100,
  43. action_history: VecDeque::new(),
  44. action_buffer: Vec::new(),
  45. })
  46. }
  47. }
  48. impl EventHandler for MainState {
  49. fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
  50. // check through the input buffer
  51. while let Some(action) = self.action_buffer.pop() {
  52. action.execute(ctx, self).expect("failed to execute action");
  53. if self.action_history.len() < self.action_history_max_length {
  54. self.action_history.push_back(action);
  55. } else {
  56. self.action_history.pop_front();
  57. self.action_history.push_back(action);
  58. }
  59. }
  60. Ok(())
  61. }
  62. fn key_down_event(
  63. &mut self,
  64. _ctx: &mut Context,
  65. key_code: KeyCode,
  66. _keymods: KeyMods,
  67. repeat: bool,
  68. ) {
  69. use world::{OffsetAction, ZoomAction};
  70. if !repeat {
  71. let action_maybe: Option<Box<dyn Action>> = match key_code {
  72. // movement key codes
  73. KeyCode::Up => Some(Box::new(OffsetAction::new([0.0, 1.0].into()))),
  74. KeyCode::Down => Some(Box::new(OffsetAction::new([0.0, -1.0].into()))),
  75. KeyCode::Left => Some(Box::new(OffsetAction::new([1.0, 0.0].into()))),
  76. KeyCode::Right => Some(Box::new(OffsetAction::new([-1.0, 0.0].into()))),
  77. // zoom key codes
  78. KeyCode::Equals => Some(Box::new(ZoomAction::new([0.1, 0.1].into()))),
  79. KeyCode::Minus => Some(Box::new(ZoomAction::new([-0.1, -0.1].into()))),
  80. // if escape, quit program (for now)
  81. // !! isabelle please remove this eventually
  82. KeyCode::Escape => Some(Box::new(QuitAction::new())),
  83. // ignore all other key codes
  84. _ => None,
  85. };
  86. if let Some(action) = action_maybe {
  87. self.action_buffer.push(action);
  88. }
  89. }
  90. }
  91. fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
  92. // clear the screen
  93. graphics::clear(ctx, graphics::BLACK);
  94. self.world.render(ctx).expect("failed to render");
  95. // render the context
  96. graphics::present(ctx)
  97. }
  98. }
  99. trait Action: std::fmt::Debug {
  100. fn execute(&self, ctx: &mut Context, state: &mut MainState) -> Result<()>;
  101. fn undo(&self, ctx: &mut Context, state: &mut MainState) -> Result<()>;
  102. }
  103. /// struct to wrap quitting the game
  104. #[derive(Debug)]
  105. struct QuitAction;
  106. impl QuitAction {
  107. fn new() -> QuitAction {
  108. QuitAction
  109. }
  110. }
  111. impl Action for QuitAction {
  112. fn execute(&self, ctx: &mut Context, _state: &mut MainState) -> Result<()> {
  113. event::quit(ctx);
  114. Ok(())
  115. }
  116. fn undo(&self, _ctx: &mut Context, _state: &mut MainState) -> Result<()> {
  117. unreachable!()
  118. }
  119. }
  120. fn main_wrapper() -> Result<()> {
  121. let win_mode = WindowMode {
  122. width: 1024.0,
  123. height: 768.0,
  124. ..Default::default()
  125. };
  126. let win_setup = WindowSetup {
  127. title: "unnamed game thinger".to_owned(),
  128. ..Default::default()
  129. };
  130. let cb = ContextBuilder::new("unnamed", "Isabelle L.")
  131. .add_resource_path("./")
  132. .window_mode(win_mode)
  133. .window_setup(win_setup);
  134. let (mut ctx, mut event_loop) = cb.build()?;
  135. let mut state = MainState::new(&mut ctx)?;
  136. event::run(&mut ctx, &mut event_loop, &mut state)?;
  137. Ok(())
  138. }
  139. fn main() {
  140. if let Err(err) = main_wrapper() {
  141. panic!("err occured: {:?}", err);
  142. }
  143. }