main.rs 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. use std::cmp;
  2. use std::collections::HashMap;
  3. use ggez::event::MouseButton;
  4. use ggez::graphics::{DrawMode, MeshBuilder, StrokeOptions};
  5. use ggez::input::keyboard::KeyCode;
  6. use ggez::timer::check_update_time;
  7. use ggez::{event, graphics, input, Context, GameResult};
  8. use crate::behavior::animate::{digest_current_behavior, digest_current_order, digest_next_order};
  9. use crate::behavior::order::Order;
  10. use crate::behavior::ItemBehavior;
  11. use crate::config::{
  12. ANIMATE_EACH, DEFAULT_SELECTED_SQUARE_SIDE, DEFAULT_SELECTED_SQUARE_SIDE_HALF,
  13. DISPLAY_OFFSET_BY, DISPLAY_OFFSET_BY_SPEED, MAX_FRAME_I, META_EACH, PHYSICS_EACH,
  14. SCENE_ITEMS_CHANGE_ERR_MSG, SPRITE_EACH, TARGET_FPS,
  15. };
  16. use crate::map::Map;
  17. use crate::physics::util::scene_point_from_window_point;
  18. use crate::physics::util::window_point_from_scene_point;
  19. use crate::physics::GridPosition;
  20. use crate::physics::{util, MetaEvent, PhysicEvent};
  21. use crate::scene::item::{apply_scene_item_modifier, ItemState, SceneItem, SceneItemType};
  22. use crate::ui::vertical_menu::vertical_menu_sprite_info;
  23. use crate::ui::MenuItem;
  24. use crate::ui::{SceneItemPrepareOrder, UiComponent, UserEvent};
  25. use crate::util::velocity_for_behavior;
  26. use crate::{Offset, ScenePoint, WindowPoint};
  27. use std::path::Path;
  28. use std::time::Instant;
  29. pub struct MainState {
  30. // time
  31. frame_i: u32,
  32. start: Instant,
  33. // map
  34. map: Map,
  35. // display
  36. debug: bool,
  37. debug_terrain: bool,
  38. display_offset: Offset,
  39. sprite_sheet_batch: graphics::spritebatch::SpriteBatch,
  40. map_batch: graphics::spritebatch::SpriteBatch,
  41. ui_batch: graphics::spritebatch::SpriteBatch,
  42. terrain_batch: graphics::spritebatch::SpriteBatch,
  43. // scene items
  44. scene_items: Vec<SceneItem>,
  45. scene_items_by_grid_position: HashMap<GridPosition, Vec<usize>>,
  46. // events
  47. physics_events: Vec<PhysicEvent>,
  48. // user interactions
  49. last_key_consumed: HashMap<KeyCode, Instant>,
  50. left_click_down: Option<WindowPoint>,
  51. right_click_down: Option<WindowPoint>,
  52. current_cursor_position: WindowPoint,
  53. user_events: Vec<UserEvent>,
  54. selected_scene_items: Vec<usize>, // scene_item usize
  55. scene_item_menu: Option<(usize, ScenePoint)>, // scene_item usize, display_at
  56. scene_item_prepare_order: Option<SceneItemPrepareOrder>,
  57. }
  58. fn update_terrain_batch(
  59. mut terrain_batch: graphics::spritebatch::SpriteBatch,
  60. map: &Map,
  61. ) -> graphics::spritebatch::SpriteBatch {
  62. terrain_batch.clear();
  63. for ((grid_x, grid_y), tile) in map.tiles.iter() {
  64. // FIXME pre compute these data
  65. let src_x = tile.tile_x as f32 * tile.relative_tile_width;
  66. let src_y = tile.tile_y as f32 * tile.relative_tile_height;
  67. let dest_x = *grid_x as f32 * tile.tile_width as f32;
  68. let dest_y = *grid_y as f32 * tile.tile_height as f32;
  69. terrain_batch.add(
  70. graphics::DrawParam::new()
  71. .src(graphics::Rect::new(
  72. src_x,
  73. src_y,
  74. tile.relative_tile_width,
  75. tile.relative_tile_height,
  76. ))
  77. .dest(ScenePoint::new(dest_x, dest_y)),
  78. );
  79. }
  80. terrain_batch
  81. }
  82. impl MainState {
  83. pub fn new(ctx: &mut Context) -> GameResult<MainState> {
  84. let map = Map::new(&Path::new("resources/map1.tmx"))?;
  85. let sprite_sheet_image = graphics::Image::new(ctx, "/sprite_sheet.png")?;
  86. let sprite_sheet_batch = graphics::spritebatch::SpriteBatch::new(sprite_sheet_image);
  87. let map_image = graphics::Image::new(
  88. ctx,
  89. &Path::new(&format!("/{}", &map.background_image.source)),
  90. )?;
  91. let map_batch = graphics::spritebatch::SpriteBatch::new(map_image);
  92. let ui_image = graphics::Image::new(ctx, "/ui.png")?;
  93. let ui_batch = graphics::spritebatch::SpriteBatch::new(ui_image);
  94. let terrain_image = graphics::Image::new(ctx, format!("/{}", map.terrain_image.source))?;
  95. let mut terrain_batch = graphics::spritebatch::SpriteBatch::new(terrain_image);
  96. terrain_batch = update_terrain_batch(terrain_batch, &map);
  97. let mut scene_items = vec![];
  98. for x in 0..1 {
  99. for y in 0..4 {
  100. // let current_behavior = if y % 2 == 0 {
  101. // ItemBehavior::WalkingTo(util::vec_from_angle(90.0))
  102. // } else {
  103. // ItemBehavior::CrawlingTo()
  104. // };
  105. scene_items.push(SceneItem::new(
  106. SceneItemType::Soldier,
  107. ScenePoint::new((x as f32 * 24.0) + 100.0, (y as f32 * 24.0) + 100.0),
  108. ItemState::new(ItemBehavior::Standing),
  109. &map,
  110. ));
  111. }
  112. }
  113. let mut scene_items_by_grid_position: HashMap<GridPosition, Vec<usize>> = HashMap::new();
  114. for (i, scene_item) in scene_items.iter().enumerate() {
  115. let grid_position = util::grid_position_from_scene_point(&scene_item.position, &map);
  116. scene_items_by_grid_position
  117. .entry(grid_position)
  118. .or_default()
  119. .push(i);
  120. }
  121. let mut main_state = MainState {
  122. frame_i: 0,
  123. start: Instant::now(),
  124. map,
  125. debug: false,
  126. debug_terrain: false,
  127. display_offset: Offset::new(0.0, 0.0),
  128. sprite_sheet_batch,
  129. map_batch,
  130. ui_batch,
  131. terrain_batch,
  132. scene_items,
  133. scene_items_by_grid_position,
  134. physics_events: vec![],
  135. last_key_consumed: HashMap::new(),
  136. left_click_down: None,
  137. right_click_down: None,
  138. current_cursor_position: WindowPoint::new(0.0, 0.0),
  139. user_events: vec![],
  140. selected_scene_items: vec![],
  141. scene_item_menu: None,
  142. scene_item_prepare_order: None,
  143. };
  144. Ok(main_state)
  145. }
  146. fn get_scene_item(&self, index: usize) -> &SceneItem {
  147. self.scene_items
  148. .get(index)
  149. .expect(SCENE_ITEMS_CHANGE_ERR_MSG)
  150. }
  151. fn get_scene_item_mut(&mut self, index: usize) -> &mut SceneItem {
  152. self.scene_items
  153. .get_mut(index)
  154. .expect(SCENE_ITEMS_CHANGE_ERR_MSG)
  155. }
  156. fn inputs(&mut self, ctx: &Context) {
  157. let display_offset_by =
  158. if input::keyboard::is_mod_active(ctx, input::keyboard::KeyMods::SHIFT) {
  159. DISPLAY_OFFSET_BY_SPEED
  160. } else {
  161. DISPLAY_OFFSET_BY
  162. };
  163. if input::keyboard::is_key_pressed(ctx, KeyCode::Left) {
  164. self.display_offset.x += display_offset_by;
  165. }
  166. if input::keyboard::is_key_pressed(ctx, KeyCode::Right) {
  167. self.display_offset.x -= display_offset_by;
  168. }
  169. if input::keyboard::is_key_pressed(ctx, KeyCode::Up) {
  170. self.display_offset.y += display_offset_by;
  171. }
  172. if input::keyboard::is_key_pressed(ctx, KeyCode::Down) {
  173. self.display_offset.y -= display_offset_by;
  174. }
  175. if input::keyboard::is_key_pressed(ctx, KeyCode::F12) {
  176. if self
  177. .last_key_consumed
  178. .get(&KeyCode::F12)
  179. .unwrap_or(&self.start)
  180. .elapsed()
  181. .as_millis()
  182. > 250
  183. {
  184. self.debug = !self.debug;
  185. self.last_key_consumed.insert(KeyCode::F12, Instant::now());
  186. }
  187. }
  188. if input::keyboard::is_key_pressed(ctx, KeyCode::F10) {
  189. if self
  190. .last_key_consumed
  191. .get(&KeyCode::F10)
  192. .unwrap_or(&self.start)
  193. .elapsed()
  194. .as_millis()
  195. > 250
  196. {
  197. self.debug_terrain = !self.debug_terrain;
  198. self.last_key_consumed.insert(KeyCode::F10, Instant::now());
  199. }
  200. }
  201. while let Some(user_event) = self.user_events.pop() {
  202. match user_event {
  203. UserEvent::Click(window_click_point) => self.digest_click(window_click_point),
  204. UserEvent::AreaSelection(window_from, window_to) => {
  205. self.digest_area_selection(window_from, window_to)
  206. }
  207. UserEvent::RightClick(window_right_click_point) => {
  208. self.digest_right_click(window_right_click_point)
  209. }
  210. }
  211. }
  212. }
  213. fn digest_click(&mut self, window_click_point: WindowPoint) {
  214. let scene_click_point =
  215. scene_point_from_window_point(&window_click_point, &self.display_offset);
  216. let mut scene_item_selected = false;
  217. let mut scene_item_menu_clicked = false;
  218. let mut prepare_order_clicked = false;
  219. if let Some(scene_item_usize) =
  220. self.get_first_scene_item_for_scene_point(&scene_click_point)
  221. {
  222. self.selected_scene_items.drain(..);
  223. self.selected_scene_items.push(scene_item_usize);
  224. scene_item_selected = true;
  225. }
  226. if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
  227. match scene_item_prepare_order {
  228. SceneItemPrepareOrder::Move(scene_item_usize) => {
  229. let mut scene_item = self.get_scene_item_mut(*scene_item_usize);
  230. scene_item.next_order = Some(Order::MoveTo(scene_click_point));
  231. }
  232. SceneItemPrepareOrder::MoveFast(scene_item_usize) => {
  233. let mut scene_item = self.get_scene_item_mut(*scene_item_usize);
  234. scene_item.next_order = Some(Order::MoveFastTo(scene_click_point));
  235. }
  236. SceneItemPrepareOrder::Hide(scene_item_usize) => {
  237. let mut scene_item = self.get_scene_item_mut(*scene_item_usize);
  238. scene_item.next_order = Some(Order::HideTo(scene_click_point));
  239. }
  240. }
  241. self.scene_item_prepare_order = None;
  242. prepare_order_clicked = true;
  243. }
  244. if let Some((scene_item_usize, scene_menu_point)) = self.scene_item_menu {
  245. let menu_sprite_info = vertical_menu_sprite_info(UiComponent::SceneItemMenu);
  246. if let Some(menu_item) =
  247. menu_sprite_info.item_clicked(&scene_menu_point, &scene_click_point)
  248. {
  249. match menu_item {
  250. MenuItem::Move => {
  251. self.scene_item_prepare_order =
  252. Some(SceneItemPrepareOrder::Move(scene_item_usize));
  253. self.scene_item_menu = None;
  254. }
  255. MenuItem::MoveFast => {
  256. self.scene_item_prepare_order =
  257. Some(SceneItemPrepareOrder::MoveFast(scene_item_usize));
  258. self.scene_item_menu = None;
  259. }
  260. MenuItem::Hide => {
  261. self.scene_item_prepare_order =
  262. Some(SceneItemPrepareOrder::Hide(scene_item_usize));
  263. self.scene_item_menu = None;
  264. }
  265. }
  266. };
  267. self.scene_item_menu = None;
  268. scene_item_menu_clicked = true;
  269. };
  270. if !prepare_order_clicked && !scene_item_menu_clicked && !scene_item_selected {
  271. self.selected_scene_items.drain(..);
  272. }
  273. }
  274. fn digest_right_click(&mut self, window_right_click_point: WindowPoint) {
  275. let scene_right_click_point =
  276. scene_point_from_window_point(&window_right_click_point, &self.display_offset);
  277. // TODO: aucune selection et right click sur un item: scene_item_menu sur un item
  278. // TODO: selection et right click sur un item de la selection: scene_item_menu sur un TOUS les item de la selection
  279. // TODO: selection et right click sur un item PAS dans la selection: scene_item_menu sur un item
  280. if let Some(scene_item_usize) =
  281. self.get_first_scene_item_for_scene_point(&scene_right_click_point)
  282. {
  283. if self.selected_scene_items.contains(&scene_item_usize) {
  284. let scene_item = self.get_scene_item(scene_item_usize);
  285. self.scene_item_menu = Some((scene_item_usize, scene_item.position))
  286. }
  287. }
  288. }
  289. fn digest_area_selection(&mut self, window_from: WindowPoint, window_to: WindowPoint) {
  290. let scene_from = scene_point_from_window_point(&window_from, &self.display_offset);
  291. let scene_to = scene_point_from_window_point(&window_to, &self.display_offset);
  292. self.selected_scene_items.drain(..);
  293. self.selected_scene_items
  294. .extend(self.get_scene_items_for_scene_area(&scene_from, &scene_to));
  295. }
  296. // TODO: manage errors
  297. fn physics(&mut self) {
  298. // Scene items movements
  299. for scene_item in self.scene_items.iter_mut() {
  300. match scene_item.state.current_behavior {
  301. ItemBehavior::Standing => {}
  302. ItemBehavior::MoveTo(move_to_scene_point)
  303. | ItemBehavior::MoveFastTo(move_to_scene_point)
  304. | ItemBehavior::HideTo(move_to_scene_point) => {
  305. let velocity = velocity_for_behavior(&scene_item.state.current_behavior)
  306. .expect("must have velocity here");
  307. let move_vector =
  308. (move_to_scene_point - scene_item.position).normalize() * velocity;
  309. // TODO ici il faut calculer le déplacement réél (en fonction des ticks, etc ...)
  310. scene_item.position.x += move_vector.x;
  311. scene_item.position.y += move_vector.y;
  312. scene_item.grid_position =
  313. util::grid_position_from_scene_point(&scene_item.position, &self.map);
  314. }
  315. }
  316. }
  317. // (FAKE) Drop a bomb to motivate stop move
  318. if self.frame_i % 600 == 0 && self.frame_i != 0 {
  319. self.physics_events.push(PhysicEvent::Explosion);
  320. }
  321. }
  322. fn metas(&mut self) {
  323. for physic_event in &self.physics_events {
  324. match physic_event {
  325. PhysicEvent::Explosion => {
  326. for scene_item in self.scene_items.iter_mut() {
  327. scene_item.meta_events.push(MetaEvent::FeelExplosion);
  328. }
  329. }
  330. }
  331. }
  332. }
  333. fn animate(&mut self) {
  334. for (_, scene_item) in self.scene_items.iter_mut().enumerate() {
  335. apply_scene_item_modifier(scene_item, digest_next_order(&scene_item));
  336. apply_scene_item_modifier(scene_item, digest_current_order(&scene_item));
  337. apply_scene_item_modifier(scene_item, digest_current_behavior(&scene_item));
  338. }
  339. }
  340. fn tick_sprites(&mut self) {
  341. for scene_item in self.scene_items.iter_mut() {
  342. scene_item.tick_sprite();
  343. }
  344. }
  345. fn get_first_scene_item_for_scene_point(&self, scene_position: &ScenePoint) -> Option<usize> {
  346. // TODO: if found multiple: select nearest
  347. for (i, scene_item) in self.scene_items.iter().enumerate() {
  348. let sprite_info = scene_item.sprite_info();
  349. if scene_item.position.x >= scene_position.x - sprite_info.tile_width
  350. && scene_item.position.x <= scene_position.x + sprite_info.tile_width
  351. && scene_item.position.y >= scene_position.y - sprite_info.tile_height
  352. && scene_item.position.y <= scene_position.y + sprite_info.tile_height
  353. {
  354. return Some(i);
  355. }
  356. }
  357. None
  358. }
  359. fn get_scene_items_for_scene_area(&self, from: &ScenePoint, to: &ScenePoint) -> Vec<usize> {
  360. let mut selection = vec![];
  361. for (i, scene_item) in self.scene_items.iter().enumerate() {
  362. if scene_item.position.x >= from.x
  363. && scene_item.position.x <= to.x
  364. && scene_item.position.y >= from.y
  365. && scene_item.position.y <= to.y
  366. {
  367. selection.push(i);
  368. }
  369. }
  370. selection
  371. }
  372. fn generate_scene_item_sprites(&mut self) -> GameResult {
  373. for scene_item in self.scene_items.iter() {
  374. self.sprite_sheet_batch.add(
  375. scene_item
  376. .as_draw_param(scene_item.current_frame)
  377. .dest(scene_item.position.clone()),
  378. );
  379. }
  380. Ok(())
  381. }
  382. fn generate_scene_item_menu_sprites(&mut self) -> GameResult {
  383. if let Some((_, scene_point)) = self.scene_item_menu {
  384. for draw_param in vertical_menu_sprite_info(UiComponent::SceneItemMenu)
  385. .as_draw_params(&scene_point, &self.current_cursor_position)
  386. {
  387. self.ui_batch.add(draw_param);
  388. }
  389. }
  390. Ok(())
  391. }
  392. fn generate_map_sprites(&mut self) -> GameResult {
  393. self.map_batch.add(
  394. graphics::DrawParam::new()
  395. .src(graphics::Rect::new(0.0, 0.0, 1.0, 1.0))
  396. .dest(ScenePoint::new(0.0, 0.0)),
  397. );
  398. Ok(())
  399. }
  400. fn update_mesh_builder_with_debug(
  401. &self,
  402. mut mesh_builder: MeshBuilder,
  403. ) -> GameResult<MeshBuilder> {
  404. if self.debug {
  405. // Draw circle on each scene item position
  406. for scene_item in self.scene_items.iter() {
  407. mesh_builder.circle(
  408. DrawMode::fill(),
  409. scene_item.position.clone(),
  410. 2.0,
  411. 2.0,
  412. graphics::WHITE,
  413. )?;
  414. }
  415. // Draw circle where left click down
  416. if let Some(window_left_click_down_point) = self.left_click_down {
  417. let scene_left_click_down_point = scene_point_from_window_point(
  418. &window_left_click_down_point,
  419. &self.display_offset,
  420. );
  421. mesh_builder.circle(
  422. DrawMode::fill(),
  423. scene_left_click_down_point,
  424. 2.0,
  425. 2.0,
  426. graphics::YELLOW,
  427. )?;
  428. }
  429. // Draw circle at cursor position
  430. mesh_builder.circle(
  431. DrawMode::fill(),
  432. scene_point_from_window_point(&self.current_cursor_position, &self.display_offset),
  433. 2.0,
  434. 2.0,
  435. graphics::BLUE,
  436. )?;
  437. }
  438. GameResult::Ok(mesh_builder)
  439. }
  440. fn update_mesh_builder_with_selected_items(
  441. &self,
  442. mut mesh_builder: MeshBuilder,
  443. ) -> GameResult<MeshBuilder> {
  444. for i in &self.selected_scene_items {
  445. let selected_scene_item = self.get_scene_item(*i);
  446. mesh_builder.rectangle(
  447. DrawMode::Stroke(StrokeOptions::default()),
  448. graphics::Rect::new(
  449. selected_scene_item.position.x - DEFAULT_SELECTED_SQUARE_SIDE_HALF,
  450. selected_scene_item.position.y - DEFAULT_SELECTED_SQUARE_SIDE_HALF,
  451. DEFAULT_SELECTED_SQUARE_SIDE,
  452. DEFAULT_SELECTED_SQUARE_SIDE,
  453. ),
  454. graphics::GREEN,
  455. )?;
  456. }
  457. GameResult::Ok(mesh_builder)
  458. }
  459. fn update_mesh_builder_with_selection_area(
  460. &self,
  461. mut mesh_builder: MeshBuilder,
  462. ) -> GameResult<MeshBuilder> {
  463. if let Some(window_left_click_down_point) = self.left_click_down {
  464. let scene_left_click_down_point =
  465. scene_point_from_window_point(&window_left_click_down_point, &self.display_offset);
  466. let scene_current_cursor_position =
  467. scene_point_from_window_point(&self.current_cursor_position, &self.display_offset);
  468. if scene_left_click_down_point != scene_current_cursor_position {
  469. mesh_builder.rectangle(
  470. DrawMode::stroke(1.0),
  471. graphics::Rect::new(
  472. scene_left_click_down_point.x,
  473. scene_left_click_down_point.y,
  474. scene_current_cursor_position.x - scene_left_click_down_point.x,
  475. scene_current_cursor_position.y - scene_left_click_down_point.y,
  476. ),
  477. graphics::GREEN,
  478. )?;
  479. }
  480. }
  481. GameResult::Ok(mesh_builder)
  482. }
  483. fn update_mesh_builder_with_prepare_order(
  484. &self,
  485. mut mesh_builder: MeshBuilder,
  486. ) -> GameResult<MeshBuilder> {
  487. if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
  488. match scene_item_prepare_order {
  489. SceneItemPrepareOrder::Move(scene_item_usize)
  490. | SceneItemPrepareOrder::MoveFast(scene_item_usize)
  491. | SceneItemPrepareOrder::Hide(scene_item_usize) => {
  492. let color = match &scene_item_prepare_order {
  493. SceneItemPrepareOrder::Move(_) => graphics::BLUE,
  494. SceneItemPrepareOrder::MoveFast(_) => graphics::MAGENTA,
  495. SceneItemPrepareOrder::Hide(_) => graphics::YELLOW,
  496. };
  497. let scene_item = self.get_scene_item(*scene_item_usize);
  498. mesh_builder.line(
  499. &vec![
  500. scene_item.position.clone(),
  501. scene_point_from_window_point(
  502. &self.current_cursor_position,
  503. &self.display_offset,
  504. ),
  505. ],
  506. 2.0,
  507. color,
  508. )?;
  509. }
  510. }
  511. }
  512. GameResult::Ok(mesh_builder)
  513. }
  514. }
  515. impl event::EventHandler for MainState {
  516. fn update(&mut self, ctx: &mut Context) -> GameResult {
  517. while check_update_time(ctx, TARGET_FPS) {
  518. self.inputs(ctx);
  519. // TODO: meta: calculer par ex qui voit qui (soldat voit un ennemi: ajouter l'event a vu
  520. // ennemi, dans animate il se mettra a tirer)
  521. let tick_sprite = self.frame_i % SPRITE_EACH == 0;
  522. let tick_animate = self.frame_i % ANIMATE_EACH == 0;
  523. let tick_physics = self.frame_i % PHYSICS_EACH == 0;
  524. let tick_meta = self.frame_i % META_EACH == 0;
  525. // Apply moves, explosions, etc
  526. if tick_physics {
  527. self.physics();
  528. }
  529. // Generate meta events according to physics events and current physic state
  530. if tick_meta {
  531. self.metas();
  532. }
  533. // Animate scene items according to meta events
  534. if tick_animate {
  535. self.animate();
  536. };
  537. // Change scene items tiles
  538. if tick_sprite {
  539. self.tick_sprites();
  540. }
  541. // Increment frame counter
  542. self.frame_i += 1;
  543. if self.frame_i >= MAX_FRAME_I {
  544. self.frame_i = 0;
  545. }
  546. // Empty physics event
  547. self.physics_events.drain(..);
  548. }
  549. Ok(())
  550. }
  551. fn draw(&mut self, ctx: &mut Context) -> GameResult {
  552. graphics::clear(ctx, graphics::BLACK);
  553. let mut scene_mesh_builder = MeshBuilder::new();
  554. self.generate_scene_item_sprites()?;
  555. self.generate_scene_item_menu_sprites()?;
  556. self.generate_map_sprites()?;
  557. scene_mesh_builder = self.update_mesh_builder_with_debug(scene_mesh_builder)?;
  558. scene_mesh_builder = self.update_mesh_builder_with_selected_items(scene_mesh_builder)?;
  559. scene_mesh_builder = self.update_mesh_builder_with_selection_area(scene_mesh_builder)?;
  560. scene_mesh_builder = self.update_mesh_builder_with_prepare_order(scene_mesh_builder)?;
  561. let window_draw_param = graphics::DrawParam::new().dest(window_point_from_scene_point(
  562. &ScenePoint::new(0.0, 0.0),
  563. &self.display_offset,
  564. ));
  565. graphics::draw(ctx, &self.map_batch, window_draw_param)?;
  566. if self.debug_terrain {
  567. graphics::draw(ctx, &self.terrain_batch, window_draw_param)?;
  568. }
  569. graphics::draw(ctx, &self.sprite_sheet_batch, window_draw_param)?;
  570. if let Ok(scene_mesh) = scene_mesh_builder.build(ctx) {
  571. graphics::draw(ctx, &scene_mesh, window_draw_param)?;
  572. }
  573. graphics::draw(ctx, &self.ui_batch, window_draw_param)?;
  574. self.sprite_sheet_batch.clear();
  575. self.map_batch.clear();
  576. self.ui_batch.clear();
  577. graphics::present(ctx)?;
  578. // println!("FPS: {}", ggez::timer::fps(ctx));
  579. Ok(())
  580. }
  581. fn mouse_button_down_event(&mut self, _ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
  582. match button {
  583. MouseButton::Left => {
  584. self.left_click_down = Some(WindowPoint::new(x, y));
  585. }
  586. MouseButton::Right => {
  587. self.right_click_down = Some(WindowPoint::new(x, y));
  588. }
  589. MouseButton::Middle => {}
  590. MouseButton::Other(_) => {}
  591. }
  592. }
  593. fn mouse_button_up_event(&mut self, _ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
  594. match button {
  595. MouseButton::Left => {
  596. if let Some(left_click_down) = self.left_click_down {
  597. if left_click_down == WindowPoint::new(x, y) {
  598. self.user_events.push(UserEvent::Click(left_click_down));
  599. } else {
  600. let from = WindowPoint::new(
  601. cmp::min(left_click_down.x as i32, x as i32) as f32,
  602. cmp::min(left_click_down.y as i32, y as i32) as f32,
  603. );
  604. let to = WindowPoint::new(
  605. cmp::max(left_click_down.x as i32, x as i32) as f32,
  606. cmp::max(left_click_down.y as i32, y as i32) as f32,
  607. );
  608. self.user_events.push(UserEvent::AreaSelection(from, to));
  609. }
  610. }
  611. self.left_click_down = None;
  612. }
  613. MouseButton::Right => {
  614. if let Some(right_click_down) = self.right_click_down {
  615. self.user_events
  616. .push(UserEvent::RightClick(right_click_down));
  617. }
  618. }
  619. MouseButton::Middle => {}
  620. MouseButton::Other(_) => {}
  621. }
  622. }
  623. fn mouse_motion_event(&mut self, _ctx: &mut Context, x: f32, y: f32, _dx: f32, _dy: f32) {
  624. self.current_cursor_position = WindowPoint::new(x, y);
  625. }
  626. }