|
@@ -1,5 +1,7 @@
|
1
|
1
|
use std::cmp;
|
2
|
2
|
use std::collections::HashMap;
|
|
3
|
+use std::path::Path;
|
|
4
|
+use std::time::Instant;
|
3
|
5
|
|
4
|
6
|
use ggez::event::MouseButton;
|
5
|
7
|
use ggez::graphics::{DrawMode, MeshBuilder, StrokeOptions};
|
|
@@ -18,16 +20,28 @@ use crate::config::{
|
18
|
20
|
use crate::map::Map;
|
19
|
21
|
use crate::physics::util::scene_point_from_window_point;
|
20
|
22
|
use crate::physics::util::window_point_from_scene_point;
|
21
|
|
-use crate::physics::GridPosition;
|
|
23
|
+use crate::physics::GridPoint;
|
22
|
24
|
use crate::physics::{util, MetaEvent, PhysicEvent};
|
23
|
|
-use crate::scene::item::{apply_scene_item_modifier, ItemState, SceneItem, SceneItemType};
|
|
25
|
+use crate::scene::item::{
|
|
26
|
+ apply_scene_item_modifier, apply_scene_item_modifiers, ItemState, SceneItem, SceneItemModifier,
|
|
27
|
+ SceneItemType,
|
|
28
|
+};
|
24
|
29
|
use crate::ui::vertical_menu::vertical_menu_sprite_info;
|
25
|
30
|
use crate::ui::MenuItem;
|
26
|
31
|
use crate::ui::{SceneItemPrepareOrder, UiComponent, UserEvent};
|
27
|
32
|
use crate::util::velocity_for_behavior;
|
28
|
|
-use crate::{Offset, ScenePoint, WindowPoint};
|
29
|
|
-use std::path::Path;
|
30
|
|
-use std::time::Instant;
|
|
33
|
+use crate::{scene, Message, Offset, SceneItemId, ScenePoint, WindowPoint};
|
|
34
|
+
|
|
35
|
+#[derive(PartialEq)]
|
|
36
|
+enum DebugTerrain {
|
|
37
|
+ None,
|
|
38
|
+ Tiles,
|
|
39
|
+ Opacity,
|
|
40
|
+}
|
|
41
|
+
|
|
42
|
+pub enum MainStateModifier {
|
|
43
|
+ ChangeSceneItemGridPosition(SceneItemId, GridPoint, GridPoint),
|
|
44
|
+}
|
31
|
45
|
|
32
|
46
|
pub struct MainState {
|
33
|
47
|
// time
|
|
@@ -39,16 +53,17 @@ pub struct MainState {
|
39
|
53
|
|
40
|
54
|
// display
|
41
|
55
|
debug: bool,
|
42
|
|
- debug_terrain: bool,
|
|
56
|
+ debug_terrain: DebugTerrain,
|
43
|
57
|
display_offset: Offset,
|
44
|
58
|
sprite_sheet_batch: graphics::spritebatch::SpriteBatch,
|
45
|
59
|
map_batch: graphics::spritebatch::SpriteBatch,
|
46
|
60
|
ui_batch: graphics::spritebatch::SpriteBatch,
|
47
|
|
- terrain_batch: graphics::spritebatch::SpriteBatch,
|
|
61
|
+ debug_terrain_batch: graphics::spritebatch::SpriteBatch,
|
|
62
|
+ debug_terrain_opacity_mesh_builder: MeshBuilder,
|
48
|
63
|
|
49
|
64
|
// scene items
|
50
|
65
|
scene_items: Vec<SceneItem>,
|
51
|
|
- scene_items_by_grid_position: HashMap<GridPosition, Vec<usize>>,
|
|
66
|
+ scene_items_by_grid_position: HashMap<GridPoint, Vec<usize>>,
|
52
|
67
|
|
53
|
68
|
// events
|
54
|
69
|
physics_events: Vec<PhysicEvent>,
|
|
@@ -64,32 +79,6 @@ pub struct MainState {
|
64
|
79
|
scene_item_prepare_order: Option<SceneItemPrepareOrder>,
|
65
|
80
|
}
|
66
|
81
|
|
67
|
|
-fn update_terrain_batch(
|
68
|
|
- mut terrain_batch: graphics::spritebatch::SpriteBatch,
|
69
|
|
- map: &Map,
|
70
|
|
-) -> graphics::spritebatch::SpriteBatch {
|
71
|
|
- terrain_batch.clear();
|
72
|
|
- for ((grid_x, grid_y), tile) in map.tiles.iter() {
|
73
|
|
- // FIXME pre compute these data
|
74
|
|
- let src_x = tile.tile_x as f32 * tile.relative_tile_width;
|
75
|
|
- let src_y = tile.tile_y as f32 * tile.relative_tile_height;
|
76
|
|
- let dest_x = *grid_x as f32 * tile.tile_width as f32;
|
77
|
|
- let dest_y = *grid_y as f32 * tile.tile_height as f32;
|
78
|
|
- terrain_batch.add(
|
79
|
|
- graphics::DrawParam::new()
|
80
|
|
- .src(graphics::Rect::new(
|
81
|
|
- src_x,
|
82
|
|
- src_y,
|
83
|
|
- tile.relative_tile_width,
|
84
|
|
- tile.relative_tile_height,
|
85
|
|
- ))
|
86
|
|
- .dest(ScenePoint::new(dest_x, dest_y)),
|
87
|
|
- );
|
88
|
|
- }
|
89
|
|
-
|
90
|
|
- terrain_batch
|
91
|
|
-}
|
92
|
|
-
|
93
|
82
|
impl MainState {
|
94
|
83
|
pub fn new(ctx: &mut Context) -> GameResult<MainState> {
|
95
|
84
|
let map = Map::new(&Path::new("resources/map1.tmx"))?;
|
|
@@ -107,18 +96,14 @@ impl MainState {
|
107
|
96
|
let ui_batch = graphics::spritebatch::SpriteBatch::new(ui_image);
|
108
|
97
|
|
109
|
98
|
let terrain_image = graphics::Image::new(ctx, format!("/{}", map.terrain_image.source))?;
|
110
|
|
- let mut terrain_batch = graphics::spritebatch::SpriteBatch::new(terrain_image);
|
111
|
|
- terrain_batch = update_terrain_batch(terrain_batch, &map);
|
|
99
|
+ let mut debug_terrain_batch = graphics::spritebatch::SpriteBatch::new(terrain_image);
|
|
100
|
+ debug_terrain_batch = scene::util::update_terrain_batch(debug_terrain_batch, &map);
|
|
101
|
+ let debug_terrain_opacity_mesh_builder =
|
|
102
|
+ scene::util::create_debug_terrain_opacity_mesh_builder(&map)?;
|
112
|
103
|
|
113
|
104
|
let mut scene_items = vec![];
|
114
|
105
|
for x in 0..1 {
|
115
|
106
|
for y in 0..4 {
|
116
|
|
- // let current_behavior = if y % 2 == 0 {
|
117
|
|
- // ItemBehavior::WalkingTo(util::vec_from_angle(90.0))
|
118
|
|
- // } else {
|
119
|
|
- // ItemBehavior::CrawlingTo()
|
120
|
|
- // };
|
121
|
|
-
|
122
|
107
|
scene_items.push(SceneItem::new(
|
123
|
108
|
SceneItemType::Soldier,
|
124
|
109
|
ScenePoint::new((x as f32 * 24.0) + 100.0, (y as f32 * 24.0) + 100.0),
|
|
@@ -128,7 +113,7 @@ impl MainState {
|
128
|
113
|
}
|
129
|
114
|
}
|
130
|
115
|
|
131
|
|
- let mut scene_items_by_grid_position: HashMap<GridPosition, Vec<usize>> = HashMap::new();
|
|
116
|
+ let mut scene_items_by_grid_position: HashMap<GridPoint, Vec<usize>> = HashMap::new();
|
132
|
117
|
for (i, scene_item) in scene_items.iter().enumerate() {
|
133
|
118
|
let grid_position = util::grid_position_from_scene_point(&scene_item.position, &map);
|
134
|
119
|
scene_items_by_grid_position
|
|
@@ -137,17 +122,18 @@ impl MainState {
|
137
|
122
|
.push(i);
|
138
|
123
|
}
|
139
|
124
|
|
140
|
|
- let mut main_state = MainState {
|
|
125
|
+ let main_state = MainState {
|
141
|
126
|
frame_i: 0,
|
142
|
127
|
start: Instant::now(),
|
143
|
128
|
map,
|
144
|
129
|
debug: false,
|
145
|
|
- debug_terrain: false,
|
|
130
|
+ debug_terrain: DebugTerrain::None,
|
146
|
131
|
display_offset: Offset::new(0.0, 0.0),
|
147
|
132
|
sprite_sheet_batch,
|
148
|
133
|
map_batch,
|
149
|
134
|
ui_batch,
|
150
|
|
- terrain_batch,
|
|
135
|
+ debug_terrain_batch,
|
|
136
|
+ debug_terrain_opacity_mesh_builder,
|
151
|
137
|
scene_items,
|
152
|
138
|
scene_items_by_grid_position,
|
153
|
139
|
physics_events: vec![],
|
|
@@ -219,7 +205,11 @@ impl MainState {
|
219
|
205
|
.as_millis()
|
220
|
206
|
> 250
|
221
|
207
|
{
|
222
|
|
- self.debug_terrain = !self.debug_terrain;
|
|
208
|
+ self.debug_terrain = match &self.debug_terrain {
|
|
209
|
+ DebugTerrain::None => DebugTerrain::Tiles,
|
|
210
|
+ DebugTerrain::Tiles => DebugTerrain::Opacity,
|
|
211
|
+ DebugTerrain::Opacity => DebugTerrain::None,
|
|
212
|
+ };
|
223
|
213
|
self.last_key_consumed.insert(KeyCode::F10, Instant::now());
|
224
|
214
|
}
|
225
|
215
|
}
|
|
@@ -330,10 +320,33 @@ impl MainState {
|
330
|
320
|
.extend(self.get_scene_items_for_scene_area(&scene_from, &scene_to));
|
331
|
321
|
}
|
332
|
322
|
|
|
323
|
+ fn change_scene_item_grid_position(
|
|
324
|
+ &mut self,
|
|
325
|
+ scene_item_i: usize,
|
|
326
|
+ from_grid_position: GridPoint,
|
|
327
|
+ to_grid_position: GridPoint,
|
|
328
|
+ ) {
|
|
329
|
+ let grid_position_scene_items = self
|
|
330
|
+ .scene_items_by_grid_position
|
|
331
|
+ .get_mut(&from_grid_position)
|
|
332
|
+ .expect("Scene item should be here !");
|
|
333
|
+ let x = grid_position_scene_items
|
|
334
|
+ .iter()
|
|
335
|
+ .position(|x| *x == scene_item_i)
|
|
336
|
+ .expect("Scene item should be here !");
|
|
337
|
+ grid_position_scene_items.remove(x);
|
|
338
|
+ self.scene_items_by_grid_position
|
|
339
|
+ .entry(to_grid_position)
|
|
340
|
+ .or_default()
|
|
341
|
+ .push(scene_item_i)
|
|
342
|
+ }
|
|
343
|
+
|
333
|
344
|
// TODO: manage errors
|
334
|
345
|
fn physics(&mut self) {
|
|
346
|
+ let mut messages: Vec<Message> = vec![];
|
|
347
|
+
|
335
|
348
|
// Scene items movements
|
336
|
|
- for scene_item in self.scene_items.iter_mut() {
|
|
349
|
+ for (scene_item_i, scene_item) in self.scene_items.iter_mut().enumerate() {
|
337
|
350
|
match scene_item.state.current_behavior {
|
338
|
351
|
ItemBehavior::Standing => {}
|
339
|
352
|
ItemBehavior::MoveTo(move_to_scene_point)
|
|
@@ -343,11 +356,29 @@ impl MainState {
|
343
|
356
|
.expect("must have velocity here");
|
344
|
357
|
let move_vector =
|
345
|
358
|
(move_to_scene_point - scene_item.position).normalize() * velocity;
|
346
|
|
- // TODO ici il faut calculer le déplacement réél (en fonction des ticks, etc ...)
|
347
|
|
- scene_item.position.x += move_vector.x;
|
348
|
|
- scene_item.position.y += move_vector.y;
|
349
|
|
- scene_item.grid_position =
|
|
359
|
+ let new_position = ScenePoint::new(
|
|
360
|
+ scene_item.position.x + move_vector.x,
|
|
361
|
+ scene_item.position.y + move_vector.y,
|
|
362
|
+ );
|
|
363
|
+ messages.push(Message::SceneItemMessage(
|
|
364
|
+ scene_item_i,
|
|
365
|
+ SceneItemModifier::ChangePosition(new_position),
|
|
366
|
+ ));
|
|
367
|
+ let new_grid_position =
|
350
|
368
|
util::grid_position_from_scene_point(&scene_item.position, &self.map);
|
|
369
|
+ if scene_item.grid_position != new_grid_position {
|
|
370
|
+ messages.push(Message::MainStateMessage(
|
|
371
|
+ MainStateModifier::ChangeSceneItemGridPosition(
|
|
372
|
+ scene_item_i,
|
|
373
|
+ scene_item.grid_position.clone(),
|
|
374
|
+ new_grid_position.clone(),
|
|
375
|
+ ),
|
|
376
|
+ ));
|
|
377
|
+ messages.push(Message::SceneItemMessage(
|
|
378
|
+ scene_item_i,
|
|
379
|
+ SceneItemModifier::ChangeGridPosition(new_grid_position.clone()),
|
|
380
|
+ ));
|
|
381
|
+ }
|
351
|
382
|
}
|
352
|
383
|
}
|
353
|
384
|
}
|
|
@@ -356,6 +387,32 @@ impl MainState {
|
356
|
387
|
if self.frame_i % 600 == 0 && self.frame_i != 0 {
|
357
|
388
|
self.physics_events.push(PhysicEvent::Explosion);
|
358
|
389
|
}
|
|
390
|
+
|
|
391
|
+ self.consume_messages(messages);
|
|
392
|
+ }
|
|
393
|
+
|
|
394
|
+ fn consume_messages(&mut self, messages: Vec<Message>) {
|
|
395
|
+ for message in messages.into_iter() {
|
|
396
|
+ match message {
|
|
397
|
+ Message::SceneItemMessage(i, scene_item_modifier) => {
|
|
398
|
+ let scene_item = self.get_scene_item_mut(i);
|
|
399
|
+ apply_scene_item_modifier(scene_item, scene_item_modifier);
|
|
400
|
+ }
|
|
401
|
+ Message::MainStateMessage(main_state_modifier) => match main_state_modifier {
|
|
402
|
+ MainStateModifier::ChangeSceneItemGridPosition(
|
|
403
|
+ scene_item_i,
|
|
404
|
+ from_grid_position,
|
|
405
|
+ to_grid_position,
|
|
406
|
+ ) => {
|
|
407
|
+ self.change_scene_item_grid_position(
|
|
408
|
+ scene_item_i,
|
|
409
|
+ from_grid_position,
|
|
410
|
+ to_grid_position,
|
|
411
|
+ );
|
|
412
|
+ }
|
|
413
|
+ },
|
|
414
|
+ }
|
|
415
|
+ }
|
359
|
416
|
}
|
360
|
417
|
|
361
|
418
|
fn metas(&mut self) {
|
|
@@ -372,9 +429,9 @@ impl MainState {
|
372
|
429
|
|
373
|
430
|
fn animate(&mut self) {
|
374
|
431
|
for (_, scene_item) in self.scene_items.iter_mut().enumerate() {
|
375
|
|
- apply_scene_item_modifier(scene_item, digest_next_order(&scene_item));
|
376
|
|
- apply_scene_item_modifier(scene_item, digest_current_order(&scene_item));
|
377
|
|
- apply_scene_item_modifier(scene_item, digest_current_behavior(&scene_item));
|
|
432
|
+ apply_scene_item_modifiers(scene_item, digest_next_order(&scene_item));
|
|
433
|
+ apply_scene_item_modifiers(scene_item, digest_current_order(&scene_item));
|
|
434
|
+ apply_scene_item_modifiers(scene_item, digest_current_behavior(&scene_item));
|
378
|
435
|
}
|
379
|
436
|
}
|
380
|
437
|
|
|
@@ -640,8 +697,12 @@ impl event::EventHandler for MainState {
|
640
|
697
|
));
|
641
|
698
|
|
642
|
699
|
graphics::draw(ctx, &self.map_batch, window_draw_param)?;
|
643
|
|
- if self.debug_terrain {
|
644
|
|
- graphics::draw(ctx, &self.terrain_batch, window_draw_param)?;
|
|
700
|
+ if self.debug_terrain == DebugTerrain::Tiles {
|
|
701
|
+ graphics::draw(ctx, &self.debug_terrain_batch, window_draw_param)?;
|
|
702
|
+ } else if self.debug_terrain == DebugTerrain::Opacity {
|
|
703
|
+ let debug_terrain_opacity_mesh =
|
|
704
|
+ self.debug_terrain_opacity_mesh_builder.build(ctx).unwrap();
|
|
705
|
+ graphics::draw(ctx, &debug_terrain_opacity_mesh, window_draw_param)?;
|
645
|
706
|
}
|
646
|
707
|
graphics::draw(ctx, &self.sprite_sheet_batch, window_draw_param)?;
|
647
|
708
|
if let Ok(scene_mesh) = scene_mesh_builder.build(ctx) {
|