Browse Source

Implement multiples moves

Bastien Sevajol 3 years ago
parent
commit
480e488e2c
9 changed files with 116 additions and 38 deletions
  1. 30 7
      src/behavior/animate.rs
  2. 3 2
      src/behavior/mod.rs
  3. 2 0
      src/behavior/order.rs
  4. 7 1
      src/config.rs
  5. 1 0
      src/main.rs
  6. 18 14
      src/scene/item.rs
  7. 41 13
      src/scene/main.rs
  8. 3 1
      src/ui/mod.rs
  9. 11 0
      src/util.rs

+ 30 - 7
src/behavior/animate.rs View File

@@ -2,6 +2,7 @@ use crate::behavior::order::Order;
2 2
 use crate::behavior::ItemBehavior;
3 3
 use crate::config::MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT;
4 4
 use crate::scene::item::{ItemState, SceneItem, SceneItemModifier};
5
+use crate::util::velocity_for_behavior;
5 6
 use std::f32::consts::FRAC_PI_2;
6 7
 
7 8
 pub fn digest_next_order(scene_item: &SceneItem) -> Vec<SceneItemModifier> {
@@ -11,8 +12,10 @@ pub fn digest_next_order(scene_item: &SceneItem) -> Vec<SceneItemModifier> {
11 12
     if let Some(next_order) = &scene_item.next_order {
12 13
         match next_order {
13 14
             Order::MoveTo(_) => {
14
-                scene_item_modifiers.push(SceneItemModifier::SwitchToCurrentOrder);
15
+                scene_item_modifiers.push(SceneItemModifier::SwitchToNextOrder);
15 16
             }
17
+            Order::MoveFastTo(_) => scene_item_modifiers.push(SceneItemModifier::SwitchToNextOrder),
18
+            Order::HideTo(_) => scene_item_modifiers.push(SceneItemModifier::SwitchToNextOrder),
16 19
         }
17 20
     }
18 21
 
@@ -26,8 +29,21 @@ pub fn digest_current_order(scene_item: &SceneItem) -> Vec<SceneItemModifier> {
26 29
     if let Some(current_order) = &scene_item.current_order {
27 30
         match current_order {
28 31
             Order::MoveTo(move_to_scene_point) => {
32
+                // FIXME BS NOW: Change order only if it is not the current order
29 33
                 scene_item_modifiers.push(SceneItemModifier::ChangeState(ItemState::new(
30
-                    ItemBehavior::WalkingTo(*move_to_scene_point),
34
+                    ItemBehavior::MoveTo(*move_to_scene_point),
35
+                )))
36
+            }
37
+            Order::MoveFastTo(move_to_scene_point) => {
38
+                // FIXME BS NOW: Change order only if it is not the current order
39
+                scene_item_modifiers.push(SceneItemModifier::ChangeState(ItemState::new(
40
+                    ItemBehavior::MoveFastTo(*move_to_scene_point),
41
+                )))
42
+            }
43
+            Order::HideTo(move_to_scene_point) => {
44
+                // FIXME BS NOW: Change order only if it is not the current order
45
+                scene_item_modifiers.push(SceneItemModifier::ChangeState(ItemState::new(
46
+                    ItemBehavior::HideTo(*move_to_scene_point),
31 47
                 )))
32 48
             }
33 49
         }
@@ -41,8 +57,9 @@ pub fn digest_current_behavior(scene_item: &SceneItem) -> Vec<SceneItemModifier>
41 57
 
42 58
     match scene_item.state.current_behavior {
43 59
         ItemBehavior::Standing => {}
44
-        ItemBehavior::WalkingTo(going_to_scene_point)
45
-        | ItemBehavior::CrawlingTo(going_to_scene_point) => {
60
+        ItemBehavior::MoveTo(going_to_scene_point)
61
+        | ItemBehavior::MoveFastTo(going_to_scene_point)
62
+        | ItemBehavior::HideTo(going_to_scene_point) => {
46 63
             // Note: angle computed by adding FRAC_PI_2 because sprites are north oriented
47 64
             scene_item_modifiers.push(SceneItemModifier::ChangeDisplayAngle(
48 65
                 f32::atan2(
@@ -53,15 +70,21 @@ pub fn digest_current_behavior(scene_item: &SceneItem) -> Vec<SceneItemModifier>
53 70
 
54 71
             // Check if scene_point reached
55 72
             let distance = going_to_scene_point.distance(scene_item.position);
56
-            if distance < MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT {
73
+            let velocity = velocity_for_behavior(&scene_item.state.current_behavior)
74
+                .expect("must have velocity here");
75
+            if distance < MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT * velocity {
57 76
                 scene_item_modifiers.push(SceneItemModifier::ChangeState(ItemState::new(
58 77
                     ItemBehavior::Standing,
59 78
                 )));
79
+
80
+                // Test if reached destination is from an order. If it is, switch to next order.
60 81
                 if let Some(current_order) = &scene_item.current_order {
61 82
                     match current_order {
62
-                        Order::MoveTo(move_to_scene_point) => {
83
+                        Order::MoveTo(move_to_scene_point)
84
+                        | Order::MoveFastTo(move_to_scene_point)
85
+                        | Order::HideTo(move_to_scene_point) => {
63 86
                             if *move_to_scene_point == going_to_scene_point {
64
-                                scene_item_modifiers.push(SceneItemModifier::SwitchToCurrentOrder);
87
+                                scene_item_modifiers.push(SceneItemModifier::SwitchToNextOrder);
65 88
                             }
66 89
                         }
67 90
                     }

+ 3 - 2
src/behavior/mod.rs View File

@@ -5,6 +5,7 @@ use crate::ScenePoint;
5 5
 
6 6
 pub enum ItemBehavior {
7 7
     Standing, // since
8
-    CrawlingTo(ScenePoint),
9
-    WalkingTo(ScenePoint),
8
+    HideTo(ScenePoint),
9
+    MoveTo(ScenePoint),
10
+    MoveFastTo(ScenePoint),
10 11
 }

+ 2 - 0
src/behavior/order.rs View File

@@ -3,4 +3,6 @@ use crate::ScenePoint;
3 3
 #[derive(Clone)]
4 4
 pub enum Order {
5 5
     MoveTo(ScenePoint),
6
+    MoveFastTo(ScenePoint),
7
+    HideTo(ScenePoint),
6 8
 }

+ 7 - 1
src/config.rs View File

@@ -35,4 +35,10 @@ pub const SCENE_ITEMS_CHANGE_ERR_MSG: &str = "scene_items content change !";
35 35
 //
36 36
 pub const DEBUG: bool = true;
37 37
 // Distance from move target point to consider reached
38
-pub const MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT: f32 = 1.0;
38
+pub const MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT: f32 = 3.0;
39
+// Velocity of move vector
40
+pub const MOVE_VELOCITY: f32 = 1.0;
41
+// Velocity of move fast vector
42
+pub const MOVE_FAST_VELOCITY: f32 = 2.0;
43
+// Velocity of move hide vector
44
+pub const MOVE_HIDE_VELOCITY: f32 = 0.5;

+ 1 - 0
src/main.rs View File

@@ -11,6 +11,7 @@ mod config;
11 11
 mod physics;
12 12
 mod scene;
13 13
 mod ui;
14
+mod util;
14 15
 
15 16
 type WindowPoint = Vec2;
16 17
 type Offset = Vec2;

+ 18 - 14
src/scene/item.rs View File

@@ -17,15 +17,16 @@ pub struct SceneItemSpriteInfo {
17 17
     pub tile_height: f32,
18 18
     pub _half_tile_width: f32,
19 19
     pub _half_tile_height: f32,
20
+    pub tick_speed: f32,
20 21
 }
21 22
 
22 23
 impl SceneItemSpriteInfo {
23 24
     // TODO: ask on rust community if this is performant, or how to make it static
24 25
     pub fn from_type(type_: &SpriteType) -> Self {
25
-        let (start_y, tile_width, tile_height, tile_count) = match type_ {
26
-            SpriteType::WalkingSoldier => (12.0, 12.0, 12.0, 8),
27
-            SpriteType::CrawlingSoldier => (26.0, 26.0, 26.0, 8),
28
-            SpriteType::StandingSoldier => (0.0, 12.0, 12.0, 1),
26
+        let (start_y, tile_width, tile_height, tile_count, tick_speed) = match type_ {
27
+            SpriteType::WalkingSoldier => (12.0, 12.0, 12.0, 8, 0.5),
28
+            SpriteType::CrawlingSoldier => (26.0, 26.0, 26.0, 8, 1.0),
29
+            SpriteType::StandingSoldier => (0.0, 12.0, 12.0, 1, 0.0),
29 30
         };
30 31
 
31 32
         Self {
@@ -37,6 +38,7 @@ impl SceneItemSpriteInfo {
37 38
             tile_height,
38 39
             _half_tile_width: tile_width / 2.0,
39 40
             _half_tile_height: tile_height / 2.0,
41
+            tick_speed,
40 42
         }
41 43
     }
42 44
 }
@@ -61,7 +63,7 @@ pub struct SceneItem {
61 63
     pub grid_position: GridPosition,
62 64
     pub state: ItemState,
63 65
     pub meta_events: Vec<MetaEvent>,
64
-    pub current_frame: u16,
66
+    pub current_frame: f32,
65 67
     pub current_order: Option<Order>,
66 68
     pub next_order: Option<Order>,
67 69
     pub display_angle: f32,
@@ -75,7 +77,7 @@ impl SceneItem {
75 77
             grid_position: util::grid_position_from_scene_point(&position.clone()),
76 78
             state,
77 79
             meta_events: vec![],
78
-            current_frame: 0,
80
+            current_frame: 0.0,
79 81
             current_order: None,
80 82
             next_order: None,
81 83
             display_angle: 0.0,
@@ -87,10 +89,11 @@ impl SceneItem {
87 89
     }
88 90
 
89 91
     pub fn tick_sprite(&mut self) {
90
-        self.current_frame += 1;
92
+        let sprite_info =self.sprite_info();
93
+        self.current_frame += sprite_info.tick_speed;
91 94
         // TODO: good way to have sprite info ? performant ?
92
-        if self.current_frame >= self.sprite_info().tile_count {
93
-            self.current_frame = 0;
95
+        if self.current_frame as u16 >= sprite_info.tile_count {
96
+            self.current_frame = 0.0;
94 97
         }
95 98
     }
96 99
 
@@ -98,7 +101,7 @@ impl SceneItem {
98 101
         let sprite_info = self.sprite_info();
99 102
         graphics::DrawParam::new()
100 103
             .src(graphics::Rect::new(
101
-                current_frame as f32 * sprite_info.relative_tile_width,
104
+                (current_frame as u16) as f32 * sprite_info.relative_tile_width,
102 105
                 sprite_info.relative_start_y,
103 106
                 sprite_info.relative_tile_width,
104 107
                 sprite_info.relative_tile_height,
@@ -111,15 +114,16 @@ impl SceneItem {
111 114
         // Here some logical about state, nature (soldier, tank, ...) and current behavior to
112 115
         // determine sprite type
113 116
         match self.state.current_behavior {
114
-            ItemBehavior::CrawlingTo(_) => SpriteType::CrawlingSoldier,
115
-            ItemBehavior::WalkingTo(_) => SpriteType::WalkingSoldier,
117
+            ItemBehavior::HideTo(_) => SpriteType::CrawlingSoldier,
118
+            ItemBehavior::MoveTo(_) => SpriteType::WalkingSoldier,
119
+            ItemBehavior::MoveFastTo(_) => SpriteType::WalkingSoldier,
116 120
             ItemBehavior::Standing => SpriteType::StandingSoldier,
117 121
         }
118 122
     }
119 123
 }
120 124
 
121 125
 pub enum SceneItemModifier {
122
-    SwitchToCurrentOrder,
126
+    SwitchToNextOrder,
123 127
     ChangeDisplayAngle(f32),
124 128
     ChangeState(ItemState),
125 129
 }
@@ -127,7 +131,7 @@ pub enum SceneItemModifier {
127 131
 pub fn apply_scene_item_modifier(scene_item: &mut SceneItem, modifiers: Vec<SceneItemModifier>) {
128 132
     for modifier in modifiers {
129 133
         match modifier {
130
-            SceneItemModifier::SwitchToCurrentOrder => {
134
+            SceneItemModifier::SwitchToNextOrder => {
131 135
                 let next_order = scene_item.next_order.clone();
132 136
                 scene_item.current_order = next_order;
133 137
                 scene_item.next_order = None;

+ 41 - 13
src/scene/main.rs View File

@@ -13,9 +13,9 @@ use crate::behavior::order::Order;
13 13
 use crate::behavior::ItemBehavior;
14 14
 use crate::config::{
15 15
     ANIMATE_EACH, DEBUG, DEFAULT_SELECTED_SQUARE_SIDE, DEFAULT_SELECTED_SQUARE_SIDE_HALF,
16
-    DISPLAY_OFFSET_BY, DISPLAY_OFFSET_BY_SPEED, MAX_FRAME_I, META_EACH,
17
-    MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT, PHYSICS_EACH, SCENE_ITEMS_CHANGE_ERR_MSG,
18
-    SPRITE_EACH, TARGET_FPS,
16
+    DISPLAY_OFFSET_BY, DISPLAY_OFFSET_BY_SPEED, MAX_FRAME_I, META_EACH, MOVE_FAST_VELOCITY,
17
+    MOVE_HIDE_VELOCITY, MOVE_TO_REACHED_WHEN_DISTANCE_INFERIOR_AT, MOVE_VELOCITY, PHYSICS_EACH,
18
+    SCENE_ITEMS_CHANGE_ERR_MSG, SPRITE_EACH, TARGET_FPS,
19 19
 };
20 20
 use crate::physics::util::scene_point_from_window_point;
21 21
 use crate::physics::util::window_point_from_scene_point;
@@ -27,6 +27,7 @@ use crate::scene::item::{
27 27
 use crate::ui::vertical_menu::{vertical_menu_sprite_info, VerticalMenuSpriteInfo};
28 28
 use crate::ui::MenuItem;
29 29
 use crate::ui::{SceneItemPrepareOrder, UiComponent, UserEvent};
30
+use crate::util::velocity_for_behavior;
30 31
 use crate::{Offset, ScenePoint, WindowPoint};
31 32
 
32 33
 pub struct MainState {
@@ -174,12 +175,19 @@ impl MainState {
174 175
         }
175 176
 
176 177
         if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
177
-            // TODO: Add order to scene_item
178 178
             match scene_item_prepare_order {
179 179
                 SceneItemPrepareOrder::Move(scene_item_usize) => {
180 180
                     let mut scene_item = self.get_scene_item_mut(*scene_item_usize);
181 181
                     scene_item.next_order = Some(Order::MoveTo(scene_click_point));
182 182
                 }
183
+                SceneItemPrepareOrder::MoveFast(scene_item_usize) => {
184
+                    let mut scene_item = self.get_scene_item_mut(*scene_item_usize);
185
+                    scene_item.next_order = Some(Order::MoveFastTo(scene_click_point));
186
+                }
187
+                SceneItemPrepareOrder::Hide(scene_item_usize) => {
188
+                    let mut scene_item = self.get_scene_item_mut(*scene_item_usize);
189
+                    scene_item.next_order = Some(Order::HideTo(scene_click_point));
190
+                }
183 191
             }
184 192
 
185 193
             self.scene_item_prepare_order = None;
@@ -197,8 +205,16 @@ impl MainState {
197 205
                             Some(SceneItemPrepareOrder::Move(scene_item_usize));
198 206
                         self.scene_item_menu = None;
199 207
                     }
200
-                    MenuItem::MoveFast => {}
201
-                    MenuItem::Hide => {}
208
+                    MenuItem::MoveFast => {
209
+                        self.scene_item_prepare_order =
210
+                            Some(SceneItemPrepareOrder::MoveFast(scene_item_usize));
211
+                        self.scene_item_menu = None;
212
+                    }
213
+                    MenuItem::Hide => {
214
+                        self.scene_item_prepare_order =
215
+                            Some(SceneItemPrepareOrder::Hide(scene_item_usize));
216
+                        self.scene_item_menu = None;
217
+                    }
202 218
                 }
203 219
             };
204 220
             self.scene_item_menu = None;
@@ -241,16 +257,20 @@ impl MainState {
241 257
         // Scene items movements
242 258
         for scene_item in self.scene_items.iter_mut() {
243 259
             match scene_item.state.current_behavior {
244
-                ItemBehavior::WalkingTo(scene_point) => {
245
-                    // FIXME BS NOW: velocity
246
-                    let move_vector = (scene_point - scene_item.position).normalize() * 1.0;
260
+                ItemBehavior::Standing => {}
261
+                ItemBehavior::MoveTo(move_to_scene_point)
262
+                | ItemBehavior::MoveFastTo(move_to_scene_point)
263
+                | ItemBehavior::HideTo(move_to_scene_point) => {
264
+                    let velocity = velocity_for_behavior(&scene_item.state.current_behavior)
265
+                        .expect("must have velocity here");
266
+                    let move_vector =
267
+                        (move_to_scene_point - scene_item.position).normalize() * velocity;
247 268
                     // TODO ici il faut calculer le déplacement réél (en fonction des ticks, etc ...)
248 269
                     scene_item.position.x += move_vector.x;
249 270
                     scene_item.position.y += move_vector.y;
250 271
                     scene_item.grid_position =
251 272
                         util::grid_position_from_scene_point(&scene_item.position);
252 273
                 }
253
-                _ => {}
254 274
             }
255 275
         }
256 276
 
@@ -322,7 +342,7 @@ impl MainState {
322 342
         for scene_item in self.scene_items.iter() {
323 343
             self.sprite_sheet_batch.add(
324 344
                 scene_item
325
-                    .as_draw_param(scene_item.current_frame as f32)
345
+                    .as_draw_param(scene_item.current_frame)
326 346
                     .dest(scene_item.position.clone()),
327 347
             );
328 348
         }
@@ -449,7 +469,15 @@ impl MainState {
449 469
     ) -> GameResult<MeshBuilder> {
450 470
         if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
451 471
             match scene_item_prepare_order {
452
-                SceneItemPrepareOrder::Move(scene_item_usize) => {
472
+                SceneItemPrepareOrder::Move(scene_item_usize)
473
+                | SceneItemPrepareOrder::MoveFast(scene_item_usize)
474
+                | SceneItemPrepareOrder::Hide(scene_item_usize) => {
475
+                    let color = match &scene_item_prepare_order {
476
+                        SceneItemPrepareOrder::Move(_) => graphics::BLUE,
477
+                        SceneItemPrepareOrder::MoveFast(_) => graphics::MAGENTA,
478
+                        SceneItemPrepareOrder::Hide(_) => graphics::YELLOW,
479
+                    };
480
+
453 481
                     let scene_item = self.get_scene_item(*scene_item_usize);
454 482
                     mesh_builder.line(
455 483
                         &vec![
@@ -460,7 +488,7 @@ impl MainState {
460 488
                             ),
461 489
                         ],
462 490
                         2.0,
463
-                        graphics::WHITE,
491
+                        color,
464 492
                     )?;
465 493
                 }
466 494
             }

+ 3 - 1
src/ui/mod.rs View File

@@ -22,7 +22,9 @@ pub enum UserEvent {
22 22
 }
23 23
 
24 24
 pub enum SceneItemPrepareOrder {
25
-    Move(usize), // scene_item usize
25
+    Move(usize),     // scene_item usize
26
+    MoveFast(usize), // scene_item usize
27
+    Hide(usize),     // scene_item usize
26 28
 }
27 29
 
28 30
 #[derive(Clone)]

+ 11 - 0
src/util.rs View File

@@ -0,0 +1,11 @@
1
+use crate::behavior::ItemBehavior;
2
+use crate::config::{MOVE_FAST_VELOCITY, MOVE_HIDE_VELOCITY, MOVE_VELOCITY};
3
+
4
+pub fn velocity_for_behavior(behavior: &ItemBehavior) -> Option<f32> {
5
+    match behavior {
6
+        ItemBehavior::MoveTo(_) => Some(MOVE_VELOCITY),
7
+        ItemBehavior::MoveFastTo(_) => Some(MOVE_FAST_VELOCITY),
8
+        ItemBehavior::HideTo(_) => Some(MOVE_HIDE_VELOCITY),
9
+        _ => None,
10
+    }
11
+}