main.rs 29KB

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