|  | @@ -1,15 +1,31 @@
 | 
	
		
			
			|  | 1 | +use std::cmp;
 | 
	
		
			
			|  | 2 | +use std::collections::HashMap;
 | 
	
		
			
			|  | 3 | +use std::env;
 | 
	
		
			
			|  | 4 | +use std::path;
 | 
	
		
			
			|  | 5 | +
 | 
	
		
			
			| 1 | 6 |  use ggez;
 | 
	
		
			
			|  | 7 | +use ggez::{event, input};
 | 
	
		
			
			|  | 8 | +use ggez::{Context, GameResult};
 | 
	
		
			
			| 2 | 9 |  use ggez::event::{KeyCode, MouseButton};
 | 
	
		
			
			| 3 | 10 |  use ggez::graphics;
 | 
	
		
			
			| 4 | 11 |  use ggez::graphics::{Color, DrawMode, FillOptions, MeshBuilder, StrokeOptions};
 | 
	
		
			
			| 5 | 12 |  use ggez::timer::check_update_time;
 | 
	
		
			
			| 6 |  | -use ggez::{event, input};
 | 
	
		
			
			| 7 |  | -use ggez::{Context, GameResult};
 | 
	
		
			
			| 8 | 13 |  use glam::Vec2;
 | 
	
		
			
			| 9 |  | -use std::cmp;
 | 
	
		
			
			| 10 |  | -use std::collections::HashMap;
 | 
	
		
			
			| 11 |  | -use std::env;
 | 
	
		
			
			| 12 |  | -use std::path;
 | 
	
		
			
			|  | 14 | +
 | 
	
		
			
			|  | 15 | +use behavior::ItemBehavior;
 | 
	
		
			
			|  | 16 | +use physics::{MetaEvent, PhysicEvent, util};
 | 
	
		
			
			|  | 17 | +use scene::item::{ItemState, SceneItem, SceneItemSpriteInfo, SceneItemType};
 | 
	
		
			
			|  | 18 | +use scene::main::MainState;
 | 
	
		
			
			|  | 19 | +use scene::SpriteType;
 | 
	
		
			
			|  | 20 | +use ui::{SceneItemPrepareOrder, UiItem, UiSpriteInfo, UserEvent};
 | 
	
		
			
			|  | 21 | +use ui::scene_item_menu::SceneItemMenuItem;
 | 
	
		
			
			|  | 22 | +
 | 
	
		
			
			|  | 23 | +use crate::physics::position::GridPosition;
 | 
	
		
			
			|  | 24 | +
 | 
	
		
			
			|  | 25 | +mod physics;
 | 
	
		
			
			|  | 26 | +mod ui;
 | 
	
		
			
			|  | 27 | +mod scene;
 | 
	
		
			
			|  | 28 | +mod behavior;
 | 
	
		
			
			| 13 | 29 |  
 | 
	
		
			
			| 14 | 30 |  // TODO: create a ScenePosition and a WindowPosition to be more explicit
 | 
	
		
			
			| 15 | 31 |  type Point2 = Vec2;
 | 
	
	
		
			
			|  | @@ -33,725 +49,6 @@ const DEFAULT_SELECTED_SQUARE_SIDE: f32 = 14.0;
 | 
	
		
			
			| 33 | 49 |  const DEFAULT_SELECTED_SQUARE_SIDE_HALF: f32 = DEFAULT_SELECTED_SQUARE_SIDE / 2.0;
 | 
	
		
			
			| 34 | 50 |  const SCENE_ITEMS_CHANGE_ERR_MSG: &str = "scene_items content change !";
 | 
	
		
			
			| 35 | 51 |  
 | 
	
		
			
			| 36 |  | -#[derive(Eq, PartialEq, Hash)]
 | 
	
		
			
			| 37 |  | -pub struct GridPosition {
 | 
	
		
			
			| 38 |  | -    x: i32,
 | 
	
		
			
			| 39 |  | -    y: i32,
 | 
	
		
			
			| 40 |  | -}
 | 
	
		
			
			| 41 |  | -
 | 
	
		
			
			| 42 |  | -impl GridPosition {
 | 
	
		
			
			| 43 |  | -    pub fn new(x: i32, y: i32) -> Self {
 | 
	
		
			
			| 44 |  | -        Self { x, y }
 | 
	
		
			
			| 45 |  | -    }
 | 
	
		
			
			| 46 |  | -}
 | 
	
		
			
			| 47 |  | -
 | 
	
		
			
			| 48 |  | -fn vec_from_angle(angle: f32) -> Vector2 {
 | 
	
		
			
			| 49 |  | -    let vx = angle.sin();
 | 
	
		
			
			| 50 |  | -    let vy = angle.cos();
 | 
	
		
			
			| 51 |  | -    Vector2::new(vx, vy)
 | 
	
		
			
			| 52 |  | -}
 | 
	
		
			
			| 53 |  | -
 | 
	
		
			
			| 54 |  | -fn grid_position_from_position(position: &Point2) -> GridPosition {
 | 
	
		
			
			| 55 |  | -    GridPosition::new(
 | 
	
		
			
			| 56 |  | -        (position.x / GRID_TILE_WIDTH) as i32,
 | 
	
		
			
			| 57 |  | -        (position.y / GRID_TILE_HEIGHT) as i32,
 | 
	
		
			
			| 58 |  | -    )
 | 
	
		
			
			| 59 |  | -}
 | 
	
		
			
			| 60 |  | -
 | 
	
		
			
			| 61 |  | -enum UiItem {
 | 
	
		
			
			| 62 |  | -    SceneItemMenu,
 | 
	
		
			
			| 63 |  | -}
 | 
	
		
			
			| 64 |  | -
 | 
	
		
			
			| 65 |  | -enum SceneItemMenuItem {
 | 
	
		
			
			| 66 |  | -    Move,
 | 
	
		
			
			| 67 |  | -}
 | 
	
		
			
			| 68 |  | -
 | 
	
		
			
			| 69 |  | -struct UiSpriteInfo {
 | 
	
		
			
			| 70 |  | -    relative_start_x: f32,
 | 
	
		
			
			| 71 |  | -    relative_start_y: f32,
 | 
	
		
			
			| 72 |  | -    relative_width: f32,
 | 
	
		
			
			| 73 |  | -    relative_height: f32,
 | 
	
		
			
			| 74 |  | -    width: f32,
 | 
	
		
			
			| 75 |  | -    height: f32,
 | 
	
		
			
			| 76 |  | -}
 | 
	
		
			
			| 77 |  | -
 | 
	
		
			
			| 78 |  | -impl UiSpriteInfo {
 | 
	
		
			
			| 79 |  | -    pub fn from_type(type_: UiItem) -> Self {
 | 
	
		
			
			| 80 |  | -        match type_ {
 | 
	
		
			
			| 81 |  | -            UiItem::SceneItemMenu => Self {
 | 
	
		
			
			| 82 |  | -                relative_start_x: 0.0,
 | 
	
		
			
			| 83 |  | -                relative_start_y: 0.0,
 | 
	
		
			
			| 84 |  | -                relative_width: 71.0 / UI_SPRITE_SHEET_WIDTH,
 | 
	
		
			
			| 85 |  | -                relative_height: 68.0 / UI_SPRITE_SHEET_HEIGHT,
 | 
	
		
			
			| 86 |  | -                width: 71.0,
 | 
	
		
			
			| 87 |  | -                height: 68.0,
 | 
	
		
			
			| 88 |  | -            },
 | 
	
		
			
			| 89 |  | -        }
 | 
	
		
			
			| 90 |  | -    }
 | 
	
		
			
			| 91 |  | -
 | 
	
		
			
			| 92 |  | -    pub fn as_draw_param(&self) -> graphics::DrawParam {
 | 
	
		
			
			| 93 |  | -        graphics::DrawParam::new().src(graphics::Rect::new(
 | 
	
		
			
			| 94 |  | -            self.relative_start_x,
 | 
	
		
			
			| 95 |  | -            self.relative_start_y,
 | 
	
		
			
			| 96 |  | -            self.relative_width,
 | 
	
		
			
			| 97 |  | -            self.relative_height,
 | 
	
		
			
			| 98 |  | -        ))
 | 
	
		
			
			| 99 |  | -    }
 | 
	
		
			
			| 100 |  | -
 | 
	
		
			
			| 101 |  | -    pub fn which_item_clicked(
 | 
	
		
			
			| 102 |  | -        &self,
 | 
	
		
			
			| 103 |  | -        menu_position: Point2,
 | 
	
		
			
			| 104 |  | -        click_position: Point2,
 | 
	
		
			
			| 105 |  | -        scene_item: &SceneItem,
 | 
	
		
			
			| 106 |  | -    ) -> Option<SceneItemMenuItem> {
 | 
	
		
			
			| 107 |  | -        Some(SceneItemMenuItem::Move)
 | 
	
		
			
			| 108 |  | -    }
 | 
	
		
			
			| 109 |  | -}
 | 
	
		
			
			| 110 |  | -
 | 
	
		
			
			| 111 |  | -struct SpriteInfo {
 | 
	
		
			
			| 112 |  | -    relative_start_y: f32,
 | 
	
		
			
			| 113 |  | -    relative_tile_width: f32,
 | 
	
		
			
			| 114 |  | -    relative_tile_height: f32,
 | 
	
		
			
			| 115 |  | -    tile_count: u16,
 | 
	
		
			
			| 116 |  | -    tile_width: f32,
 | 
	
		
			
			| 117 |  | -    tile_height: f32,
 | 
	
		
			
			| 118 |  | -    _half_tile_width: f32,
 | 
	
		
			
			| 119 |  | -    _half_tile_height: f32,
 | 
	
		
			
			| 120 |  | -}
 | 
	
		
			
			| 121 |  | -
 | 
	
		
			
			| 122 |  | -impl SpriteInfo {
 | 
	
		
			
			| 123 |  | -    // TODO: ask on rust community if this is performant, or how to make it static
 | 
	
		
			
			| 124 |  | -    pub fn from_type(type_: &SpriteType) -> Self {
 | 
	
		
			
			| 125 |  | -        let (start_y, tile_width, tile_height, tile_count) = match type_ {
 | 
	
		
			
			| 126 |  | -            SpriteType::WalkingSoldier => (12.0, 12.0, 12.0, 8),
 | 
	
		
			
			| 127 |  | -            SpriteType::CrawlingSoldier => (26.0, 26.0, 26.0, 8),
 | 
	
		
			
			| 128 |  | -            SpriteType::StandingSoldier => (0.0, 12.0, 12.0, 1),
 | 
	
		
			
			| 129 |  | -        };
 | 
	
		
			
			| 130 |  | -
 | 
	
		
			
			| 131 |  | -        Self {
 | 
	
		
			
			| 132 |  | -            relative_start_y: start_y / SCENE_ITEMS_SPRITE_SHEET_HEIGHT,
 | 
	
		
			
			| 133 |  | -            relative_tile_width: tile_width / SCENE_ITEMS_SPRITE_SHEET_WIDTH,
 | 
	
		
			
			| 134 |  | -            relative_tile_height: tile_height / SCENE_ITEMS_SPRITE_SHEET_HEIGHT,
 | 
	
		
			
			| 135 |  | -            tile_count,
 | 
	
		
			
			| 136 |  | -            tile_width,
 | 
	
		
			
			| 137 |  | -            tile_height,
 | 
	
		
			
			| 138 |  | -            _half_tile_width: tile_width / 2.0,
 | 
	
		
			
			| 139 |  | -            _half_tile_height: tile_height / 2.0,
 | 
	
		
			
			| 140 |  | -        }
 | 
	
		
			
			| 141 |  | -    }
 | 
	
		
			
			| 142 |  | -}
 | 
	
		
			
			| 143 |  | -
 | 
	
		
			
			| 144 |  | -enum SpriteType {
 | 
	
		
			
			| 145 |  | -    WalkingSoldier,
 | 
	
		
			
			| 146 |  | -    CrawlingSoldier,
 | 
	
		
			
			| 147 |  | -    StandingSoldier,
 | 
	
		
			
			| 148 |  | -}
 | 
	
		
			
			| 149 |  | -
 | 
	
		
			
			| 150 |  | -enum ItemBehavior {
 | 
	
		
			
			| 151 |  | -    Standing(u32), // since
 | 
	
		
			
			| 152 |  | -    Crawling,
 | 
	
		
			
			| 153 |  | -    Walking(Vector2),
 | 
	
		
			
			| 154 |  | -}
 | 
	
		
			
			| 155 |  | -
 | 
	
		
			
			| 156 |  | -struct ItemState {
 | 
	
		
			
			| 157 |  | -    current_behavior: ItemBehavior,
 | 
	
		
			
			| 158 |  | -}
 | 
	
		
			
			| 159 |  | -
 | 
	
		
			
			| 160 |  | -enum SceneItemType {
 | 
	
		
			
			| 161 |  | -    Soldier,
 | 
	
		
			
			| 162 |  | -}
 | 
	
		
			
			| 163 |  | -
 | 
	
		
			
			| 164 |  | -impl ItemState {
 | 
	
		
			
			| 165 |  | -    pub fn new(current_behavior: ItemBehavior) -> Self {
 | 
	
		
			
			| 166 |  | -        Self { current_behavior }
 | 
	
		
			
			| 167 |  | -    }
 | 
	
		
			
			| 168 |  | -}
 | 
	
		
			
			| 169 |  | -
 | 
	
		
			
			| 170 |  | -struct SceneItem {
 | 
	
		
			
			| 171 |  | -    type_: SceneItemType,
 | 
	
		
			
			| 172 |  | -    position: Point2,
 | 
	
		
			
			| 173 |  | -    grid_position: GridPosition,
 | 
	
		
			
			| 174 |  | -    state: ItemState,
 | 
	
		
			
			| 175 |  | -    meta_events: Vec<MetaEvent>,
 | 
	
		
			
			| 176 |  | -    current_frame: u16,
 | 
	
		
			
			| 177 |  | -}
 | 
	
		
			
			| 178 |  | -
 | 
	
		
			
			| 179 |  | -impl SceneItem {
 | 
	
		
			
			| 180 |  | -    pub fn new(type_: SceneItemType, position: Point2, state: ItemState) -> Self {
 | 
	
		
			
			| 181 |  | -        Self {
 | 
	
		
			
			| 182 |  | -            type_,
 | 
	
		
			
			| 183 |  | -            position: position.clone(),
 | 
	
		
			
			| 184 |  | -            grid_position: grid_position_from_position(&position.clone()),
 | 
	
		
			
			| 185 |  | -            state,
 | 
	
		
			
			| 186 |  | -            meta_events: vec![],
 | 
	
		
			
			| 187 |  | -            current_frame: 0,
 | 
	
		
			
			| 188 |  | -        }
 | 
	
		
			
			| 189 |  | -    }
 | 
	
		
			
			| 190 |  | -
 | 
	
		
			
			| 191 |  | -    pub fn sprite_info(&self) -> SpriteInfo {
 | 
	
		
			
			| 192 |  | -        SpriteInfo::from_type(&self.sprite_type())
 | 
	
		
			
			| 193 |  | -    }
 | 
	
		
			
			| 194 |  | -
 | 
	
		
			
			| 195 |  | -    pub fn tick_sprite(&mut self) {
 | 
	
		
			
			| 196 |  | -        self.current_frame += 1;
 | 
	
		
			
			| 197 |  | -        // TODO: good way to have sprite info ? performant ?
 | 
	
		
			
			| 198 |  | -        if self.current_frame >= self.sprite_info().tile_count {
 | 
	
		
			
			| 199 |  | -            self.current_frame = 0;
 | 
	
		
			
			| 200 |  | -        }
 | 
	
		
			
			| 201 |  | -    }
 | 
	
		
			
			| 202 |  | -
 | 
	
		
			
			| 203 |  | -    pub fn as_draw_param(&self, current_frame: f32) -> graphics::DrawParam {
 | 
	
		
			
			| 204 |  | -        let sprite_info = self.sprite_info();
 | 
	
		
			
			| 205 |  | -        graphics::DrawParam::new()
 | 
	
		
			
			| 206 |  | -            .src(graphics::Rect::new(
 | 
	
		
			
			| 207 |  | -                current_frame as f32 * sprite_info.relative_tile_width,
 | 
	
		
			
			| 208 |  | -                sprite_info.relative_start_y,
 | 
	
		
			
			| 209 |  | -                sprite_info.relative_tile_width,
 | 
	
		
			
			| 210 |  | -                sprite_info.relative_tile_height,
 | 
	
		
			
			| 211 |  | -            ))
 | 
	
		
			
			| 212 |  | -            .rotation(90.0f32.to_radians())
 | 
	
		
			
			| 213 |  | -            .offset(Point2::new(0.5, 0.5))
 | 
	
		
			
			| 214 |  | -    }
 | 
	
		
			
			| 215 |  | -
 | 
	
		
			
			| 216 |  | -    pub fn sprite_type(&self) -> SpriteType {
 | 
	
		
			
			| 217 |  | -        // Here some logical about state, nature (soldier, tank, ...) and current behavior to
 | 
	
		
			
			| 218 |  | -        // determine sprite type
 | 
	
		
			
			| 219 |  | -        match self.state.current_behavior {
 | 
	
		
			
			| 220 |  | -            ItemBehavior::Crawling => SpriteType::CrawlingSoldier,
 | 
	
		
			
			| 221 |  | -            ItemBehavior::Walking(_) => SpriteType::WalkingSoldier,
 | 
	
		
			
			| 222 |  | -            ItemBehavior::Standing(_) => SpriteType::StandingSoldier,
 | 
	
		
			
			| 223 |  | -        }
 | 
	
		
			
			| 224 |  | -    }
 | 
	
		
			
			| 225 |  | -}
 | 
	
		
			
			| 226 |  | -
 | 
	
		
			
			| 227 |  | -#[derive(Debug)]
 | 
	
		
			
			| 228 |  | -enum PhysicEvent {
 | 
	
		
			
			| 229 |  | -    Explosion,
 | 
	
		
			
			| 230 |  | -}
 | 
	
		
			
			| 231 |  | -
 | 
	
		
			
			| 232 |  | -#[derive(Debug)]
 | 
	
		
			
			| 233 |  | -enum MetaEvent {
 | 
	
		
			
			| 234 |  | -    FearAboutExplosion,
 | 
	
		
			
			| 235 |  | -}
 | 
	
		
			
			| 236 |  | -
 | 
	
		
			
			| 237 |  | -#[derive(Debug)]
 | 
	
		
			
			| 238 |  | -enum UserEvent {
 | 
	
		
			
			| 239 |  | -    Click(Point2),                 // Window coordinates
 | 
	
		
			
			| 240 |  | -    RightClick(Point2),            // Window coordinates
 | 
	
		
			
			| 241 |  | -    AreaSelection(Point2, Point2), // Window coordinates
 | 
	
		
			
			| 242 |  | -}
 | 
	
		
			
			| 243 |  | -
 | 
	
		
			
			| 244 |  | -enum SceneItemPrepareOrder {
 | 
	
		
			
			| 245 |  | -    Move(usize), // scene_item usize
 | 
	
		
			
			| 246 |  | -}
 | 
	
		
			
			| 247 |  | -
 | 
	
		
			
			| 248 |  | -struct MainState {
 | 
	
		
			
			| 249 |  | -    // time
 | 
	
		
			
			| 250 |  | -    frame_i: u32,
 | 
	
		
			
			| 251 |  | -
 | 
	
		
			
			| 252 |  | -    // display
 | 
	
		
			
			| 253 |  | -    display_offset: Point2,
 | 
	
		
			
			| 254 |  | -    sprite_sheet_batch: graphics::spritebatch::SpriteBatch,
 | 
	
		
			
			| 255 |  | -    map_batch: graphics::spritebatch::SpriteBatch,
 | 
	
		
			
			| 256 |  | -    ui_batch: graphics::spritebatch::SpriteBatch,
 | 
	
		
			
			| 257 |  | -
 | 
	
		
			
			| 258 |  | -    // scene items
 | 
	
		
			
			| 259 |  | -    scene_items: Vec<SceneItem>,
 | 
	
		
			
			| 260 |  | -    scene_items_by_grid_position: HashMap<GridPosition, Vec<usize>>,
 | 
	
		
			
			| 261 |  | -
 | 
	
		
			
			| 262 |  | -    // events
 | 
	
		
			
			| 263 |  | -    physics_events: Vec<PhysicEvent>,
 | 
	
		
			
			| 264 |  | -
 | 
	
		
			
			| 265 |  | -    // user interactions
 | 
	
		
			
			| 266 |  | -    left_click_down: Option<Point2>,
 | 
	
		
			
			| 267 |  | -    right_click_down: Option<Point2>,
 | 
	
		
			
			| 268 |  | -    current_cursor_position: Point2,
 | 
	
		
			
			| 269 |  | -    user_events: Vec<UserEvent>,
 | 
	
		
			
			| 270 |  | -    selected_scene_items: Vec<usize>,         // scene_item usize
 | 
	
		
			
			| 271 |  | -    scene_item_menu: Option<(usize, Point2)>, // scene_item usize, display_at
 | 
	
		
			
			| 272 |  | -    scene_item_prepare_order: Option<SceneItemPrepareOrder>,
 | 
	
		
			
			| 273 |  | -}
 | 
	
		
			
			| 274 |  | -
 | 
	
		
			
			| 275 |  | -impl MainState {
 | 
	
		
			
			| 276 |  | -    fn new(ctx: &mut Context) -> GameResult<MainState> {
 | 
	
		
			
			| 277 |  | -        let sprite_sheet = graphics::Image::new(ctx, "/sprite_sheet.png").unwrap();
 | 
	
		
			
			| 278 |  | -        let sprite_sheet_batch = graphics::spritebatch::SpriteBatch::new(sprite_sheet);
 | 
	
		
			
			| 279 |  | -        let map = graphics::Image::new(ctx, "/map1bg.png").unwrap();
 | 
	
		
			
			| 280 |  | -        let map_batch = graphics::spritebatch::SpriteBatch::new(map);
 | 
	
		
			
			| 281 |  | -        let ui = graphics::Image::new(ctx, "/ui.png").unwrap();
 | 
	
		
			
			| 282 |  | -        let ui_batch = graphics::spritebatch::SpriteBatch::new(ui);
 | 
	
		
			
			| 283 |  | -
 | 
	
		
			
			| 284 |  | -        let mut scene_items = vec![];
 | 
	
		
			
			| 285 |  | -        for x in 0..1 {
 | 
	
		
			
			| 286 |  | -            for y in 0..4 {
 | 
	
		
			
			| 287 |  | -                let current_behavior = if y % 2 == 0 {
 | 
	
		
			
			| 288 |  | -                    ItemBehavior::Walking(vec_from_angle(90.0))
 | 
	
		
			
			| 289 |  | -                } else {
 | 
	
		
			
			| 290 |  | -                    ItemBehavior::Crawling
 | 
	
		
			
			| 291 |  | -                };
 | 
	
		
			
			| 292 |  | -
 | 
	
		
			
			| 293 |  | -                scene_items.push(SceneItem::new(
 | 
	
		
			
			| 294 |  | -                    SceneItemType::Soldier,
 | 
	
		
			
			| 295 |  | -                    Point2::new((x as f32 * 24.0) + 100.0, (y as f32 * 24.0) + 100.0),
 | 
	
		
			
			| 296 |  | -                    ItemState::new(current_behavior),
 | 
	
		
			
			| 297 |  | -                ));
 | 
	
		
			
			| 298 |  | -            }
 | 
	
		
			
			| 299 |  | -        }
 | 
	
		
			
			| 300 |  | -
 | 
	
		
			
			| 301 |  | -        let mut main_state = MainState {
 | 
	
		
			
			| 302 |  | -            frame_i: 0,
 | 
	
		
			
			| 303 |  | -            display_offset: Point2::new(0.0, 0.0),
 | 
	
		
			
			| 304 |  | -            sprite_sheet_batch,
 | 
	
		
			
			| 305 |  | -            map_batch,
 | 
	
		
			
			| 306 |  | -            ui_batch,
 | 
	
		
			
			| 307 |  | -            scene_items,
 | 
	
		
			
			| 308 |  | -            scene_items_by_grid_position: HashMap::new(),
 | 
	
		
			
			| 309 |  | -            physics_events: vec![],
 | 
	
		
			
			| 310 |  | -            left_click_down: None,
 | 
	
		
			
			| 311 |  | -            right_click_down: None,
 | 
	
		
			
			| 312 |  | -            current_cursor_position: Point2::new(0.0, 0.0),
 | 
	
		
			
			| 313 |  | -            user_events: vec![],
 | 
	
		
			
			| 314 |  | -            selected_scene_items: vec![],
 | 
	
		
			
			| 315 |  | -            scene_item_menu: None,
 | 
	
		
			
			| 316 |  | -            scene_item_prepare_order: None,
 | 
	
		
			
			| 317 |  | -        };
 | 
	
		
			
			| 318 |  | -
 | 
	
		
			
			| 319 |  | -        for (i, scene_item) in main_state.scene_items.iter().enumerate() {
 | 
	
		
			
			| 320 |  | -            let grid_position = grid_position_from_position(&scene_item.position);
 | 
	
		
			
			| 321 |  | -            main_state
 | 
	
		
			
			| 322 |  | -                .scene_items_by_grid_position
 | 
	
		
			
			| 323 |  | -                .entry(grid_position)
 | 
	
		
			
			| 324 |  | -                .or_default()
 | 
	
		
			
			| 325 |  | -                .push(i);
 | 
	
		
			
			| 326 |  | -        }
 | 
	
		
			
			| 327 |  | -
 | 
	
		
			
			| 328 |  | -        Ok(main_state)
 | 
	
		
			
			| 329 |  | -    }
 | 
	
		
			
			| 330 |  | -
 | 
	
		
			
			| 331 |  | -    fn inputs(&mut self, ctx: &Context) {
 | 
	
		
			
			| 332 |  | -        let display_offset_by =
 | 
	
		
			
			| 333 |  | -            if input::keyboard::is_mod_active(ctx, input::keyboard::KeyMods::SHIFT) {
 | 
	
		
			
			| 334 |  | -                DISPLAY_OFFSET_BY_SPEED
 | 
	
		
			
			| 335 |  | -            } else {
 | 
	
		
			
			| 336 |  | -                DISPLAY_OFFSET_BY
 | 
	
		
			
			| 337 |  | -            };
 | 
	
		
			
			| 338 |  | -
 | 
	
		
			
			| 339 |  | -        if input::keyboard::is_key_pressed(ctx, KeyCode::Left) {
 | 
	
		
			
			| 340 |  | -            self.display_offset.x += display_offset_by;
 | 
	
		
			
			| 341 |  | -        }
 | 
	
		
			
			| 342 |  | -        if input::keyboard::is_key_pressed(ctx, KeyCode::Right) {
 | 
	
		
			
			| 343 |  | -            self.display_offset.x -= display_offset_by;
 | 
	
		
			
			| 344 |  | -        }
 | 
	
		
			
			| 345 |  | -        if input::keyboard::is_key_pressed(ctx, KeyCode::Up) {
 | 
	
		
			
			| 346 |  | -            self.display_offset.y += display_offset_by;
 | 
	
		
			
			| 347 |  | -        }
 | 
	
		
			
			| 348 |  | -        if input::keyboard::is_key_pressed(ctx, KeyCode::Down) {
 | 
	
		
			
			| 349 |  | -            self.display_offset.y -= display_offset_by;
 | 
	
		
			
			| 350 |  | -        }
 | 
	
		
			
			| 351 |  | -
 | 
	
		
			
			| 352 |  | -        while let Some(user_event) = self.user_events.pop() {
 | 
	
		
			
			| 353 |  | -            match user_event {
 | 
	
		
			
			| 354 |  | -                UserEvent::Click(click_position) => {
 | 
	
		
			
			| 355 |  | -                    let scene_position = Point2::new(
 | 
	
		
			
			| 356 |  | -                        click_position.x - self.display_offset.x,
 | 
	
		
			
			| 357 |  | -                        click_position.y - self.display_offset.y,
 | 
	
		
			
			| 358 |  | -                    );
 | 
	
		
			
			| 359 |  | -                    self.selected_scene_items.drain(..);
 | 
	
		
			
			| 360 |  | -                    if let Some(scene_item_usize) =
 | 
	
		
			
			| 361 |  | -                        self.get_first_scene_item_for_position(&scene_position)
 | 
	
		
			
			| 362 |  | -                    {
 | 
	
		
			
			| 363 |  | -                        self.selected_scene_items.push(scene_item_usize);
 | 
	
		
			
			| 364 |  | -                    }
 | 
	
		
			
			| 365 |  | -
 | 
	
		
			
			| 366 |  | -                    if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
 | 
	
		
			
			| 367 |  | -                        // TODO: Add order to scene_item
 | 
	
		
			
			| 368 |  | -                        self.scene_item_prepare_order = None;
 | 
	
		
			
			| 369 |  | -                    }
 | 
	
		
			
			| 370 |  | -
 | 
	
		
			
			| 371 |  | -                    // FIXME BS NOW: interpreter sur quel element du menu on a click ...
 | 
	
		
			
			| 372 |  | -                    if let Some((scene_item_usize, menu_position)) = self.scene_item_menu {
 | 
	
		
			
			| 373 |  | -                        let menu_sprite_info = UiSpriteInfo::from_type(UiItem::SceneItemMenu);
 | 
	
		
			
			| 374 |  | -                        let scene_item = self
 | 
	
		
			
			| 375 |  | -                            .scene_items
 | 
	
		
			
			| 376 |  | -                            .get(scene_item_usize)
 | 
	
		
			
			| 377 |  | -                            .expect(SCENE_ITEMS_CHANGE_ERR_MSG);
 | 
	
		
			
			| 378 |  | -                        if click_position.x >= menu_position.x
 | 
	
		
			
			| 379 |  | -                            && click_position.x <= menu_position.x + menu_sprite_info.width
 | 
	
		
			
			| 380 |  | -                            && click_position.y >= menu_position.y
 | 
	
		
			
			| 381 |  | -                            && click_position.y <= menu_position.y + menu_sprite_info.height
 | 
	
		
			
			| 382 |  | -                        {
 | 
	
		
			
			| 383 |  | -                            if let Some(menu_item) = menu_sprite_info.which_item_clicked(
 | 
	
		
			
			| 384 |  | -                                menu_position,
 | 
	
		
			
			| 385 |  | -                                click_position,
 | 
	
		
			
			| 386 |  | -                                scene_item,
 | 
	
		
			
			| 387 |  | -                            ) {
 | 
	
		
			
			| 388 |  | -                                match menu_item {
 | 
	
		
			
			| 389 |  | -                                    SceneItemMenuItem::Move => {
 | 
	
		
			
			| 390 |  | -                                        self.scene_item_prepare_order =
 | 
	
		
			
			| 391 |  | -                                            Some(SceneItemPrepareOrder::Move(scene_item_usize));
 | 
	
		
			
			| 392 |  | -                                        self.scene_item_menu = None;
 | 
	
		
			
			| 393 |  | -                                    }
 | 
	
		
			
			| 394 |  | -                                }
 | 
	
		
			
			| 395 |  | -                            }
 | 
	
		
			
			| 396 |  | -                        } else {
 | 
	
		
			
			| 397 |  | -                            self.scene_item_menu = None;
 | 
	
		
			
			| 398 |  | -                        }
 | 
	
		
			
			| 399 |  | -                    };
 | 
	
		
			
			| 400 |  | -                }
 | 
	
		
			
			| 401 |  | -                UserEvent::AreaSelection(from, to) => {
 | 
	
		
			
			| 402 |  | -                    let scene_from = Point2::new(
 | 
	
		
			
			| 403 |  | -                        from.x - self.display_offset.x,
 | 
	
		
			
			| 404 |  | -                        from.y - self.display_offset.y,
 | 
	
		
			
			| 405 |  | -                    );
 | 
	
		
			
			| 406 |  | -                    let scene_to =
 | 
	
		
			
			| 407 |  | -                        Point2::new(to.x - self.display_offset.x, to.y - self.display_offset.y);
 | 
	
		
			
			| 408 |  | -                    self.selected_scene_items.drain(..);
 | 
	
		
			
			| 409 |  | -                    self.selected_scene_items
 | 
	
		
			
			| 410 |  | -                        .extend(self.get_scene_items_for_area(&scene_from, &scene_to));
 | 
	
		
			
			| 411 |  | -                }
 | 
	
		
			
			| 412 |  | -                UserEvent::RightClick(position) => {
 | 
	
		
			
			| 413 |  | -                    if let Some(scene_item_usize) =
 | 
	
		
			
			| 414 |  | -                        self.get_first_scene_item_for_position(&position)
 | 
	
		
			
			| 415 |  | -                    {
 | 
	
		
			
			| 416 |  | -                        if self.selected_scene_items.contains(&scene_item_usize) {
 | 
	
		
			
			| 417 |  | -                            let scene_item = self
 | 
	
		
			
			| 418 |  | -                                .scene_items
 | 
	
		
			
			| 419 |  | -                                .get(scene_item_usize)
 | 
	
		
			
			| 420 |  | -                                .expect(SCENE_ITEMS_CHANGE_ERR_MSG);
 | 
	
		
			
			| 421 |  | -                            self.scene_item_menu =
 | 
	
		
			
			| 422 |  | -                                Some((scene_item_usize, scene_item.position.clone()))
 | 
	
		
			
			| 423 |  | -                        }
 | 
	
		
			
			| 424 |  | -                    }
 | 
	
		
			
			| 425 |  | -                }
 | 
	
		
			
			| 426 |  | -            }
 | 
	
		
			
			| 427 |  | -        }
 | 
	
		
			
			| 428 |  | -    }
 | 
	
		
			
			| 429 |  | -
 | 
	
		
			
			| 430 |  | -    // TODO: manage errors
 | 
	
		
			
			| 431 |  | -    fn physics(&mut self) {
 | 
	
		
			
			| 432 |  | -        // Scene items movements
 | 
	
		
			
			| 433 |  | -        for scene_item in self.scene_items.iter_mut() {
 | 
	
		
			
			| 434 |  | -            match scene_item.state.current_behavior {
 | 
	
		
			
			| 435 |  | -                ItemBehavior::Walking(vector) => {
 | 
	
		
			
			| 436 |  | -                    // TODO ici il faut calculer le déplacement réél (en fonction des ticks, etc ...)
 | 
	
		
			
			| 437 |  | -                    scene_item.position.x += 1.0;
 | 
	
		
			
			| 438 |  | -                    scene_item.grid_position = grid_position_from_position(&scene_item.position);
 | 
	
		
			
			| 439 |  | -                }
 | 
	
		
			
			| 440 |  | -                _ => {}
 | 
	
		
			
			| 441 |  | -            }
 | 
	
		
			
			| 442 |  | -        }
 | 
	
		
			
			| 443 |  | -
 | 
	
		
			
			| 444 |  | -        // (FAKE) Drop a bomb to motivate stop move
 | 
	
		
			
			| 445 |  | -        if self.frame_i % 600 == 0 && self.frame_i != 0 {
 | 
	
		
			
			| 446 |  | -            self.physics_events.push(PhysicEvent::Explosion);
 | 
	
		
			
			| 447 |  | -        }
 | 
	
		
			
			| 448 |  | -    }
 | 
	
		
			
			| 449 |  | -
 | 
	
		
			
			| 450 |  | -    fn metas(&mut self) {
 | 
	
		
			
			| 451 |  | -        for physic_event in &self.physics_events {
 | 
	
		
			
			| 452 |  | -            match physic_event {
 | 
	
		
			
			| 453 |  | -                PhysicEvent::Explosion => {
 | 
	
		
			
			| 454 |  | -                    for scene_item in self.scene_items.iter_mut() {
 | 
	
		
			
			| 455 |  | -                        scene_item.meta_events.push(MetaEvent::FearAboutExplosion);
 | 
	
		
			
			| 456 |  | -                    }
 | 
	
		
			
			| 457 |  | -                }
 | 
	
		
			
			| 458 |  | -            }
 | 
	
		
			
			| 459 |  | -        }
 | 
	
		
			
			| 460 |  | -    }
 | 
	
		
			
			| 461 |  | -
 | 
	
		
			
			| 462 |  | -    fn animate(&mut self) {
 | 
	
		
			
			| 463 |  | -        // TODO: ici il faut reflechir a comment organiser les comportements
 | 
	
		
			
			| 464 |  | -
 | 
	
		
			
			| 465 |  | -        for scene_item in self.scene_items.iter_mut() {
 | 
	
		
			
			| 466 |  | -            for meta_event in &scene_item.meta_events {
 | 
	
		
			
			| 467 |  | -                match meta_event {
 | 
	
		
			
			| 468 |  | -                    MetaEvent::FearAboutExplosion => {
 | 
	
		
			
			| 469 |  | -                        scene_item.state = ItemState::new(ItemBehavior::Standing(self.frame_i));
 | 
	
		
			
			| 470 |  | -                    }
 | 
	
		
			
			| 471 |  | -                }
 | 
	
		
			
			| 472 |  | -            }
 | 
	
		
			
			| 473 |  | -
 | 
	
		
			
			| 474 |  | -            match scene_item.state.current_behavior {
 | 
	
		
			
			| 475 |  | -                ItemBehavior::Crawling => {
 | 
	
		
			
			| 476 |  | -                    scene_item.state = ItemState::new(ItemBehavior::Walking(vec_from_angle(90.0)));
 | 
	
		
			
			| 477 |  | -                }
 | 
	
		
			
			| 478 |  | -                ItemBehavior::Walking(_) => {
 | 
	
		
			
			| 479 |  | -                    scene_item.state = ItemState::new(ItemBehavior::Crawling);
 | 
	
		
			
			| 480 |  | -                }
 | 
	
		
			
			| 481 |  | -                ItemBehavior::Standing(since) => {
 | 
	
		
			
			| 482 |  | -                    if self.frame_i - since >= 120 {
 | 
	
		
			
			| 483 |  | -                        scene_item.state =
 | 
	
		
			
			| 484 |  | -                            ItemState::new(ItemBehavior::Walking(vec_from_angle(90.0)));
 | 
	
		
			
			| 485 |  | -                    }
 | 
	
		
			
			| 486 |  | -                }
 | 
	
		
			
			| 487 |  | -            }
 | 
	
		
			
			| 488 |  | -
 | 
	
		
			
			| 489 |  | -            scene_item.meta_events.drain(..);
 | 
	
		
			
			| 490 |  | -        }
 | 
	
		
			
			| 491 |  | -    }
 | 
	
		
			
			| 492 |  | -
 | 
	
		
			
			| 493 |  | -    fn tick_sprites(&mut self) {
 | 
	
		
			
			| 494 |  | -        for scene_item in self.scene_items.iter_mut() {
 | 
	
		
			
			| 495 |  | -            scene_item.tick_sprite();
 | 
	
		
			
			| 496 |  | -        }
 | 
	
		
			
			| 497 |  | -    }
 | 
	
		
			
			| 498 |  | -
 | 
	
		
			
			| 499 |  | -    fn position_with_display_offset(&self, position: &Point2) -> Point2 {
 | 
	
		
			
			| 500 |  | -        Point2::new(
 | 
	
		
			
			| 501 |  | -            position.x + self.display_offset.x,
 | 
	
		
			
			| 502 |  | -            position.y + self.display_offset.y,
 | 
	
		
			
			| 503 |  | -        )
 | 
	
		
			
			| 504 |  | -    }
 | 
	
		
			
			| 505 |  | -
 | 
	
		
			
			| 506 |  | -    fn get_first_scene_item_for_position(&self, position: &Point2) -> Option<usize> {
 | 
	
		
			
			| 507 |  | -        // TODO: if found multiple: select nearest
 | 
	
		
			
			| 508 |  | -        for (i, scene_item) in self.scene_items.iter().enumerate() {
 | 
	
		
			
			| 509 |  | -            let sprite_info = scene_item.sprite_info();
 | 
	
		
			
			| 510 |  | -            if scene_item.position.x >= position.x - sprite_info.tile_width
 | 
	
		
			
			| 511 |  | -                && scene_item.position.x <= position.x + sprite_info.tile_width
 | 
	
		
			
			| 512 |  | -                && scene_item.position.y >= position.y - sprite_info.tile_height
 | 
	
		
			
			| 513 |  | -                && scene_item.position.y <= position.y + sprite_info.tile_height
 | 
	
		
			
			| 514 |  | -            {
 | 
	
		
			
			| 515 |  | -                return Some(i);
 | 
	
		
			
			| 516 |  | -            }
 | 
	
		
			
			| 517 |  | -        }
 | 
	
		
			
			| 518 |  | -
 | 
	
		
			
			| 519 |  | -        None
 | 
	
		
			
			| 520 |  | -    }
 | 
	
		
			
			| 521 |  | -
 | 
	
		
			
			| 522 |  | -    fn get_scene_items_for_area(&self, from: &Point2, to: &Point2) -> Vec<usize> {
 | 
	
		
			
			| 523 |  | -        let mut selection = vec![];
 | 
	
		
			
			| 524 |  | -
 | 
	
		
			
			| 525 |  | -        for (i, scene_item) in self.scene_items.iter().enumerate() {
 | 
	
		
			
			| 526 |  | -            if scene_item.position.x >= from.x
 | 
	
		
			
			| 527 |  | -                && scene_item.position.x <= to.x
 | 
	
		
			
			| 528 |  | -                && scene_item.position.y >= from.y
 | 
	
		
			
			| 529 |  | -                && scene_item.position.y <= to.y
 | 
	
		
			
			| 530 |  | -            {
 | 
	
		
			
			| 531 |  | -                selection.push(i);
 | 
	
		
			
			| 532 |  | -            }
 | 
	
		
			
			| 533 |  | -        }
 | 
	
		
			
			| 534 |  | -
 | 
	
		
			
			| 535 |  | -        selection
 | 
	
		
			
			| 536 |  | -    }
 | 
	
		
			
			| 537 |  | -}
 | 
	
		
			
			| 538 |  | -
 | 
	
		
			
			| 539 |  | -impl event::EventHandler for MainState {
 | 
	
		
			
			| 540 |  | -    fn update(&mut self, ctx: &mut Context) -> GameResult {
 | 
	
		
			
			| 541 |  | -        while check_update_time(ctx, TARGET_FPS) {
 | 
	
		
			
			| 542 |  | -            self.inputs(ctx);
 | 
	
		
			
			| 543 |  | -
 | 
	
		
			
			| 544 |  | -            // TODO: meta: calculer par ex qui voit qui (soldat voit un ennemi: ajouter l'event a vu
 | 
	
		
			
			| 545 |  | -            // ennemi, dans animate il se mettra a tirer)
 | 
	
		
			
			| 546 |  | -            let tick_sprite = self.frame_i % SPRITE_EACH == 0;
 | 
	
		
			
			| 547 |  | -            let tick_animate = self.frame_i % ANIMATE_EACH == 0;
 | 
	
		
			
			| 548 |  | -            let tick_physics = self.frame_i % PHYSICS_EACH == 0;
 | 
	
		
			
			| 549 |  | -            let tick_meta = self.frame_i % META_EACH == 0;
 | 
	
		
			
			| 550 |  | -
 | 
	
		
			
			| 551 |  | -            // Apply moves, explosions, etc
 | 
	
		
			
			| 552 |  | -            if tick_physics {
 | 
	
		
			
			| 553 |  | -                self.physics();
 | 
	
		
			
			| 554 |  | -            }
 | 
	
		
			
			| 555 |  | -
 | 
	
		
			
			| 556 |  | -            // Generate meta events according to physics events and current physic state
 | 
	
		
			
			| 557 |  | -            if tick_meta {
 | 
	
		
			
			| 558 |  | -                self.metas();
 | 
	
		
			
			| 559 |  | -            }
 | 
	
		
			
			| 560 |  | -
 | 
	
		
			
			| 561 |  | -            // Animate scene items according to meta events
 | 
	
		
			
			| 562 |  | -            if tick_animate {
 | 
	
		
			
			| 563 |  | -                self.animate();
 | 
	
		
			
			| 564 |  | -            };
 | 
	
		
			
			| 565 |  | -
 | 
	
		
			
			| 566 |  | -            // Change scene items tiles
 | 
	
		
			
			| 567 |  | -            if tick_sprite {
 | 
	
		
			
			| 568 |  | -                self.tick_sprites();
 | 
	
		
			
			| 569 |  | -            }
 | 
	
		
			
			| 570 |  | -
 | 
	
		
			
			| 571 |  | -            // Increment frame counter
 | 
	
		
			
			| 572 |  | -            self.frame_i += 1;
 | 
	
		
			
			| 573 |  | -            if self.frame_i >= MAX_FRAME_I {
 | 
	
		
			
			| 574 |  | -                self.frame_i = 0;
 | 
	
		
			
			| 575 |  | -            }
 | 
	
		
			
			| 576 |  | -
 | 
	
		
			
			| 577 |  | -            // Empty physics event
 | 
	
		
			
			| 578 |  | -            self.physics_events.drain(..);
 | 
	
		
			
			| 579 |  | -        }
 | 
	
		
			
			| 580 |  | -
 | 
	
		
			
			| 581 |  | -        Ok(())
 | 
	
		
			
			| 582 |  | -    }
 | 
	
		
			
			| 583 |  | -
 | 
	
		
			
			| 584 |  | -    fn draw(&mut self, ctx: &mut Context) -> GameResult {
 | 
	
		
			
			| 585 |  | -        graphics::clear(ctx, graphics::BLACK);
 | 
	
		
			
			| 586 |  | -
 | 
	
		
			
			| 587 |  | -        let mut scene_mesh_builder = MeshBuilder::new();
 | 
	
		
			
			| 588 |  | -
 | 
	
		
			
			| 589 |  | -        for scene_item in self.scene_items.iter() {
 | 
	
		
			
			| 590 |  | -            self.sprite_sheet_batch.add(
 | 
	
		
			
			| 591 |  | -                scene_item
 | 
	
		
			
			| 592 |  | -                    .as_draw_param(scene_item.current_frame as f32)
 | 
	
		
			
			| 593 |  | -                    .dest(scene_item.position.clone()),
 | 
	
		
			
			| 594 |  | -            );
 | 
	
		
			
			| 595 |  | -            scene_mesh_builder.circle(
 | 
	
		
			
			| 596 |  | -                DrawMode::fill(),
 | 
	
		
			
			| 597 |  | -                scene_item.position.clone(),
 | 
	
		
			
			| 598 |  | -                2.0,
 | 
	
		
			
			| 599 |  | -                2.0,
 | 
	
		
			
			| 600 |  | -                graphics::WHITE,
 | 
	
		
			
			| 601 |  | -            )?;
 | 
	
		
			
			| 602 |  | -        }
 | 
	
		
			
			| 603 |  | -
 | 
	
		
			
			| 604 |  | -        for i in &self.selected_scene_items {
 | 
	
		
			
			| 605 |  | -            let selected_scene_item = self.scene_items.get(*i).expect(SCENE_ITEMS_CHANGE_ERR_MSG);
 | 
	
		
			
			| 606 |  | -            scene_mesh_builder.rectangle(
 | 
	
		
			
			| 607 |  | -                DrawMode::Stroke(StrokeOptions::default()),
 | 
	
		
			
			| 608 |  | -                graphics::Rect::new(
 | 
	
		
			
			| 609 |  | -                    selected_scene_item.position.x - DEFAULT_SELECTED_SQUARE_SIDE_HALF,
 | 
	
		
			
			| 610 |  | -                    selected_scene_item.position.y - DEFAULT_SELECTED_SQUARE_SIDE_HALF,
 | 
	
		
			
			| 611 |  | -                    DEFAULT_SELECTED_SQUARE_SIDE,
 | 
	
		
			
			| 612 |  | -                    DEFAULT_SELECTED_SQUARE_SIDE,
 | 
	
		
			
			| 613 |  | -                ),
 | 
	
		
			
			| 614 |  | -                graphics::GREEN,
 | 
	
		
			
			| 615 |  | -            )?;
 | 
	
		
			
			| 616 |  | -        }
 | 
	
		
			
			| 617 |  | -
 | 
	
		
			
			| 618 |  | -        if let Some(left_click_down) = self.left_click_down {
 | 
	
		
			
			| 619 |  | -            if left_click_down != self.current_cursor_position {
 | 
	
		
			
			| 620 |  | -                scene_mesh_builder.rectangle(
 | 
	
		
			
			| 621 |  | -                    DrawMode::fill(),
 | 
	
		
			
			| 622 |  | -                    graphics::Rect::new(
 | 
	
		
			
			| 623 |  | -                        left_click_down.x - self.display_offset.x,
 | 
	
		
			
			| 624 |  | -                        left_click_down.y - self.display_offset.y,
 | 
	
		
			
			| 625 |  | -                        self.current_cursor_position.x - left_click_down.x,
 | 
	
		
			
			| 626 |  | -                        self.current_cursor_position.y - left_click_down.y,
 | 
	
		
			
			| 627 |  | -                    ),
 | 
	
		
			
			| 628 |  | -                    graphics::GREEN,
 | 
	
		
			
			| 629 |  | -                )?;
 | 
	
		
			
			| 630 |  | -            }
 | 
	
		
			
			| 631 |  | -
 | 
	
		
			
			| 632 |  | -            scene_mesh_builder.circle(
 | 
	
		
			
			| 633 |  | -                DrawMode::fill(),
 | 
	
		
			
			| 634 |  | -                left_click_down,
 | 
	
		
			
			| 635 |  | -                2.0,
 | 
	
		
			
			| 636 |  | -                2.0,
 | 
	
		
			
			| 637 |  | -                graphics::YELLOW,
 | 
	
		
			
			| 638 |  | -            )?;
 | 
	
		
			
			| 639 |  | -        }
 | 
	
		
			
			| 640 |  | -
 | 
	
		
			
			| 641 |  | -        if let Some((_, position)) = self.scene_item_menu {
 | 
	
		
			
			| 642 |  | -            self.ui_batch.add(
 | 
	
		
			
			| 643 |  | -                UiSpriteInfo::from_type(UiItem::SceneItemMenu)
 | 
	
		
			
			| 644 |  | -                    .as_draw_param()
 | 
	
		
			
			| 645 |  | -                    .dest(position),
 | 
	
		
			
			| 646 |  | -            );
 | 
	
		
			
			| 647 |  | -        }
 | 
	
		
			
			| 648 |  | -
 | 
	
		
			
			| 649 |  | -        if let Some(scene_item_prepare_order) = &self.scene_item_prepare_order {
 | 
	
		
			
			| 650 |  | -            match scene_item_prepare_order {
 | 
	
		
			
			| 651 |  | -                SceneItemPrepareOrder::Move(scene_item_usize) => {
 | 
	
		
			
			| 652 |  | -                    let scene_item = self
 | 
	
		
			
			| 653 |  | -                        .scene_items
 | 
	
		
			
			| 654 |  | -                        .get(*scene_item_usize)
 | 
	
		
			
			| 655 |  | -                        .expect(SCENE_ITEMS_CHANGE_ERR_MSG);
 | 
	
		
			
			| 656 |  | -                    scene_mesh_builder.line(
 | 
	
		
			
			| 657 |  | -                        &vec![scene_item.position.clone(), self.current_cursor_position],
 | 
	
		
			
			| 658 |  | -                        2.0,
 | 
	
		
			
			| 659 |  | -                        graphics::WHITE,
 | 
	
		
			
			| 660 |  | -                    )?;
 | 
	
		
			
			| 661 |  | -                }
 | 
	
		
			
			| 662 |  | -            }
 | 
	
		
			
			| 663 |  | -        }
 | 
	
		
			
			| 664 |  | -
 | 
	
		
			
			| 665 |  | -        self.map_batch.add(
 | 
	
		
			
			| 666 |  | -            graphics::DrawParam::new()
 | 
	
		
			
			| 667 |  | -                .src(graphics::Rect::new(0.0, 0.0, 1.0, 1.0))
 | 
	
		
			
			| 668 |  | -                .dest(Point2::new(0.0, 0.0)),
 | 
	
		
			
			| 669 |  | -        );
 | 
	
		
			
			| 670 |  | -
 | 
	
		
			
			| 671 |  | -        let scene_mesh = scene_mesh_builder.build(ctx)?;
 | 
	
		
			
			| 672 |  | -        graphics::draw(
 | 
	
		
			
			| 673 |  | -            ctx,
 | 
	
		
			
			| 674 |  | -            &self.map_batch,
 | 
	
		
			
			| 675 |  | -            graphics::DrawParam::new()
 | 
	
		
			
			| 676 |  | -                .dest(self.position_with_display_offset(&Point2::new(0.0, 0.0))),
 | 
	
		
			
			| 677 |  | -        )?;
 | 
	
		
			
			| 678 |  | -        graphics::draw(
 | 
	
		
			
			| 679 |  | -            ctx,
 | 
	
		
			
			| 680 |  | -            &self.sprite_sheet_batch,
 | 
	
		
			
			| 681 |  | -            graphics::DrawParam::new()
 | 
	
		
			
			| 682 |  | -                .dest(self.position_with_display_offset(&Point2::new(0.0, 0.0))),
 | 
	
		
			
			| 683 |  | -        )?;
 | 
	
		
			
			| 684 |  | -        graphics::draw(
 | 
	
		
			
			| 685 |  | -            ctx,
 | 
	
		
			
			| 686 |  | -            &scene_mesh,
 | 
	
		
			
			| 687 |  | -            graphics::DrawParam::new()
 | 
	
		
			
			| 688 |  | -                .dest(self.position_with_display_offset(&Point2::new(0.0, 0.0))),
 | 
	
		
			
			| 689 |  | -        )?;
 | 
	
		
			
			| 690 |  | -        graphics::draw(
 | 
	
		
			
			| 691 |  | -            ctx,
 | 
	
		
			
			| 692 |  | -            &self.ui_batch,
 | 
	
		
			
			| 693 |  | -            graphics::DrawParam::new()
 | 
	
		
			
			| 694 |  | -                .dest(self.position_with_display_offset(&Point2::new(0.0, 0.0))),
 | 
	
		
			
			| 695 |  | -        )?;
 | 
	
		
			
			| 696 |  | -
 | 
	
		
			
			| 697 |  | -        self.sprite_sheet_batch.clear();
 | 
	
		
			
			| 698 |  | -        self.map_batch.clear();
 | 
	
		
			
			| 699 |  | -        self.ui_batch.clear();
 | 
	
		
			
			| 700 |  | -        graphics::present(ctx)?;
 | 
	
		
			
			| 701 |  | -
 | 
	
		
			
			| 702 |  | -        println!("FPS: {}", ggez::timer::fps(ctx));
 | 
	
		
			
			| 703 |  | -        Ok(())
 | 
	
		
			
			| 704 |  | -    }
 | 
	
		
			
			| 705 |  | -
 | 
	
		
			
			| 706 |  | -    fn mouse_button_down_event(&mut self, _ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
 | 
	
		
			
			| 707 |  | -        match button {
 | 
	
		
			
			| 708 |  | -            MouseButton::Left => {
 | 
	
		
			
			| 709 |  | -                self.left_click_down = Some(Point2::new(x, y));
 | 
	
		
			
			| 710 |  | -            }
 | 
	
		
			
			| 711 |  | -            MouseButton::Right => {
 | 
	
		
			
			| 712 |  | -                self.right_click_down = Some(Point2::new(x, y));
 | 
	
		
			
			| 713 |  | -            }
 | 
	
		
			
			| 714 |  | -            MouseButton::Middle => {}
 | 
	
		
			
			| 715 |  | -            MouseButton::Other(_) => {}
 | 
	
		
			
			| 716 |  | -        }
 | 
	
		
			
			| 717 |  | -    }
 | 
	
		
			
			| 718 |  | -
 | 
	
		
			
			| 719 |  | -    fn mouse_button_up_event(&mut self, _ctx: &mut Context, button: MouseButton, x: f32, y: f32) {
 | 
	
		
			
			| 720 |  | -        match button {
 | 
	
		
			
			| 721 |  | -            MouseButton::Left => {
 | 
	
		
			
			| 722 |  | -                if let Some(left_click_down) = self.left_click_down {
 | 
	
		
			
			| 723 |  | -                    if left_click_down == Point2::new(x, y) {
 | 
	
		
			
			| 724 |  | -                        self.user_events.push(UserEvent::Click(left_click_down));
 | 
	
		
			
			| 725 |  | -                    } else {
 | 
	
		
			
			| 726 |  | -                        let from = Point2::new(
 | 
	
		
			
			| 727 |  | -                            cmp::min(left_click_down.x as i32, x as i32) as f32,
 | 
	
		
			
			| 728 |  | -                            cmp::min(left_click_down.y as i32, y as i32) as f32,
 | 
	
		
			
			| 729 |  | -                        );
 | 
	
		
			
			| 730 |  | -                        let to = Point2::new(
 | 
	
		
			
			| 731 |  | -                            cmp::max(left_click_down.x as i32, x as i32) as f32,
 | 
	
		
			
			| 732 |  | -                            cmp::max(left_click_down.y as i32, y as i32) as f32,
 | 
	
		
			
			| 733 |  | -                        );
 | 
	
		
			
			| 734 |  | -                        self.user_events.push(UserEvent::AreaSelection(from, to));
 | 
	
		
			
			| 735 |  | -                    }
 | 
	
		
			
			| 736 |  | -                }
 | 
	
		
			
			| 737 |  | -                self.left_click_down = None;
 | 
	
		
			
			| 738 |  | -            }
 | 
	
		
			
			| 739 |  | -            MouseButton::Right => {
 | 
	
		
			
			| 740 |  | -                if let Some(right_click_down) = self.right_click_down {
 | 
	
		
			
			| 741 |  | -                    self.user_events
 | 
	
		
			
			| 742 |  | -                        .push(UserEvent::RightClick(right_click_down));
 | 
	
		
			
			| 743 |  | -                }
 | 
	
		
			
			| 744 |  | -            }
 | 
	
		
			
			| 745 |  | -            MouseButton::Middle => {}
 | 
	
		
			
			| 746 |  | -            MouseButton::Other(_) => {}
 | 
	
		
			
			| 747 |  | -        }
 | 
	
		
			
			| 748 |  | -    }
 | 
	
		
			
			| 749 |  | -
 | 
	
		
			
			| 750 |  | -    fn mouse_motion_event(&mut self, _ctx: &mut Context, x: f32, y: f32, _dx: f32, _dy: f32) {
 | 
	
		
			
			| 751 |  | -        self.current_cursor_position = Point2::new(x, y);
 | 
	
		
			
			| 752 |  | -    }
 | 
	
		
			
			| 753 |  | -}
 | 
	
		
			
			| 754 |  | -
 | 
	
		
			
			| 755 | 52 |  pub fn main() -> GameResult {
 | 
	
		
			
			| 756 | 53 |      let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
 | 
	
		
			
			| 757 | 54 |          let mut path = path::PathBuf::from(manifest_dir);
 |