Skip to content
This repository has been archived by the owner on Sep 19, 2022. It is now read-only.

Micro Input Milestone 1 implementation #49

Merged
merged 29 commits into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4db5255
added gamemode resource. It should be used to activate/deactivate rel…
Feb 6, 2021
c292627
Render cursor, and game mode can be toggled by pressing "i"
Feb 9, 2021
83b4ffc
SelectedUnits resource, very simple unit_selection system, some addit…
Feb 9, 2021
db7f8de
added orderqueue component
Feb 12, 2021
0857409
M move order and order check system
Feb 14, 2021
d350c3d
Merge branch 'master' into micro_input_m1
Winsalot Mar 5, 2021
bd2af62
very ugly implementation of M-Move
Winsalot Mar 5, 2021
2ad516e
Added input state
Winsalot Mar 9, 2021
d3eb6b6
M-move now needs explicitly set Input State (since engine doesn;t sup…
Winsalot Mar 9, 2021
782021d
Added deselect
Winsalot Mar 11, 2021
e523046
Implement Hold Position order
Winsalot Mar 11, 2021
10e5075
Idle order system
Winsalot Mar 13, 2021
bf04b07
Spawn units with preexisting hold position order. Also did cargo update
Winsalot Mar 15, 2021
f699143
Stop order and idle state. Works :)
Winsalot Mar 15, 2021
bede7a4
Implement A-move
Winsalot Mar 15, 2021
1d0cdd8
small mouse event refactor for micro-input
Winsalot Mar 15, 2021
0319ab1
Implement fllow order
Winsalot Mar 15, 2021
d5acc33
auto control groups
Winsalot Mar 15, 2021
e513a07
auto control group selects summons
Winsalot Mar 15, 2021
ac96a5f
unselect dead units
Winsalot Mar 23, 2021
9b83eb9
delet commented out code
Winsalot Mar 23, 2021
acf1a0e
aggro range moved to data files
Winsalot Mar 25, 2021
a6bb5d6
added anti-stacking when idle
Winsalot Mar 25, 2021
243aebf
Merge branch 'master'
Apr 4, 2021
a85deaa
keybind list skips auto-control groups to leave more space
Apr 8, 2021
3b1cad2
replace Vec with VecDeque in OrderQueue component
Apr 12, 2021
120f147
Fix things pointed out in review
Apr 12, 2021
440c16a
delete outdated comment line
Apr 12, 2021
26be725
Merge branch 'master' of https://github.com/amethyst/shotcaller into …
Apr 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/target
/dev_notes.txt
/target
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ console_error_panic_hook = { version = "0.1.6", optional = true }
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8.14"
rand = "0.7.3"
oorandom = "11.1.3" # Just read the description at https://crates.io/crates/oorandom to see why I prefer to use this one
lazy_static = "1.4.0"
27 changes: 23 additions & 4 deletions assets/keymap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,35 @@
104: MenuWest
106: MenuSouth
107: MenuNorth
49:
113:
Teleport: 1
50:
119:
Teleport: 2
51:
101:
Teleport: 3
108: MenuEast
113: MenuCancel
13: MenuSelect
115: SpeedToggle
120: SpeedToggle
105: GameModeToggle
# 77: MMove
109: MMove
97: AMove
# 72: HoldPos
104: HoldPos
# 83: StopOrder
115: StopOrder
27: ResetInputState
49:
AutoSelect: 0
50:
AutoSelect: 1
51:
AutoSelect: 2
52:
AutoSelect: 3
53:
AutoSelect: 4
72: CameraWest
74: CameraSouth
75: CameraNorth
Expand Down
8 changes: 8 additions & 0 deletions assets/stat_defs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,11 @@ defs:
min_value: 0.0
max_value: 20.0
icon_path: ~
AggroRange:
key: AggroRange
name: aggrorange
friendly_name: Aggro
default_value: 7.0
min_value: 1.0
max_value: ~
icon_path: ~
16 changes: 16 additions & 0 deletions src/components.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::*;
pub use std::collections::VecDeque;

/// Tags this entity as a `Tower`.
pub struct Tower;
Expand All @@ -20,6 +21,7 @@ pub enum Companion {
/// A elephant companion
Elephant(Entity),
}

/// Tags a tower projectile.
pub struct TowerProjectile;
/// Tags a core.
Expand Down Expand Up @@ -80,6 +82,20 @@ pub struct LineOfSight {
pub range: i32,
}

/// Order queue component for micro-control (and maybe bots)
pub struct OrderQueue {
/// List of orders for a unit.
pub orders: VecDeque<UnitOrder>,
}

impl OrderQueue {
/// Better to wrap a component creation in a function
pub fn new(orders: Vec<UnitOrder>) -> Self {
OrderQueue {
orders: VecDeque::from(orders),
}
}
}
/// Items available to buy
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub struct ShelfItem(pub Items, pub i32);
24 changes: 23 additions & 1 deletion src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,26 @@ pub enum InputEvent {
MenuCancel,
SpeedToggle,
ZoomToggle,
GameModeToggle,
CameraNorth,
CameraSouth,
CameraEast,
CameraWest,
Teleport(u8),

/// Auto control group:
AutoSelect(u8),

/// Key to reset input state to default (default key Esc)
ResetInputState,
/// Key (default M) responsibe for M-move order was pressed
MMove,
/// A move order. (Defaut key A)
AMove,
/// Key (default M) responsibe for HoldPosition order was pressed
HoldPos,
/// Clear unit's order Queue. Default key S
StopOrder,
}

/// Events generated by the game's runtime.
Expand Down Expand Up @@ -46,12 +61,19 @@ pub enum GameEvent {
}

/// Events generated by mouse interaction.
#[derive(PartialEq, Copy, Clone, Debug)]
#[derive(PartialEq, Clone, Debug)]
pub enum MouseEvent {
/// A selectable entity was selected.
EntitySelected(Entity),
/// A clicable entity was clicked anywhere in the game.
EntityClicked(Entity),
/// A hoverable entity was hovered anywhere in the game.
EntityHovered(Entity),
/// A point on a map was clicked. Contains all entity ID's on that point.
PositionClicked {
/// Position of the click
pos: Point,
/// Does that position contain entity (or is it an empty point)
entities: Option<Vec<Entity>>,
},
}
1 change: 1 addition & 0 deletions src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub enum Stats {
Health,
Defense,
Attack,
AggroRange,
Mana,
AttackSpeed,
EnemiesAround,
Expand Down
16 changes: 16 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ mod render_map;
mod resources;
mod states;
mod systems;
mod unit_orders;
mod utils;
pub use self::components::*;
pub use self::events::*;
Expand All @@ -76,6 +77,7 @@ pub use self::render_map::*;
pub use self::resources::*;
pub use self::states::*;
pub use self::systems::*;
pub use self::unit_orders::*;
pub use self::utils::*;

// Bridge between bracket-lib and minigene
Expand Down Expand Up @@ -133,13 +135,22 @@ fn main() -> BError {
combine_collision_system,
input_driver::<InputEvent>,
update_mouse_events_system,
order_generation_system,
unit_selection_system,
control_group_system,
update_input_state_system, // should run before all other input systems
update_collision_resource_system,
handle_action_points_system,
creep_spawner_system,
idle_order_system,
mmove_order_system,
amove_order_system,
holdpos_order_system,
simple_destination_system,
ai_pathing_system,
movement_system,
toggle_game_speed_system,
toggle_game_mode_system,
win_condition_system,
//leader1_simple_movement_system, // TODO re-enable & rewrite like simple_destination_system
//leader2_simple_movement_system, // TODO re-enable & rewrite like simple_destination_system
Expand Down Expand Up @@ -181,6 +192,7 @@ fn main() -> BError {
spawn_creep_system,
spawn_leader_system,
game_stats_updater_system,
order_completion_check_system,
event_retrigger_system::<InputEvent, MoveCameraEvent>,
move_camera_system,
);
Expand Down Expand Up @@ -219,6 +231,10 @@ fn main() -> BError {
world.initialize::<Components<Core>>();
world.initialize::<Viewshed>();
world.initialize::<TeamLeaders>();
world.initialize::<GameMode>();
world.initialize::<SelectedUnits>();
world.initialize::<InputState>();
world.initialize::<RandomNG>();

*world.get_mut::<Option<CollisionResource>>().unwrap() = Some(CollisionResource::new(
CollisionMap::new(MAP_SIZE_X, MAP_SIZE_Y),
Expand Down
36 changes: 33 additions & 3 deletions src/render_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,41 @@ pub fn render_ui(world: &mut World, ctx: &mut BTerm) {
let hm = world.get::<HashMap<char, InputEvent>>().unwrap();
let mut keybinds = hm.iter().collect::<Vec<_>>();
keybinds.sort_by(|t1, t2| format!("{:?}", t1.1).cmp(&format!("{:?}", t2.1)));
let mut offset = 0;
for (idx, (k, v)) in keybinds.iter().enumerate() {
match v {
InputEvent::AutoSelect(..) => {
offset += 1;
continue;
}
_ => {}
}
if **k as u32 == 13 {
ctx.print(PLAY_WIDTH + 1, 18 + idx, format!("Enter:{:?}", v));
ctx.print(PLAY_WIDTH + 1, 18 + idx - offset, format!("Enter:{:?}", v));
} else if **k as u32 == 27 {
ctx.print(PLAY_WIDTH + 1, 18 + idx, format!("Esc:{:?}", v));
ctx.print(PLAY_WIDTH + 1, 18 + idx - offset, format!("Esc:{:?}", v));
} else {
ctx.print(PLAY_WIDTH + 1, 18 + idx, format!("{}:{:?}", k, v));
ctx.print(PLAY_WIDTH + 1, 18 + idx - offset, format!("{}:{:?}", k, v));
}
}

let selected_units = world.get::<SelectedUnits>().unwrap();
ctx.print(PLAY_WIDTH + 1, SCREEN_HEIGHT - 9, "Selected Units");
ctx.print(
PLAY_WIDTH + 1,
SCREEN_HEIGHT - 8,
format!("{:.2}", selected_units.units.len()),
);

let input_state = world.get::<InputState>().unwrap();
let is_txt = match *input_state {
InputState::Default => "Default",
InputState::MMove => "Move",
InputState::AMove => "Attack",
};
ctx.print(PLAY_WIDTH + 1, SCREEN_HEIGHT - 11, "InputState: ");
ctx.print(PLAY_WIDTH + 1, SCREEN_HEIGHT - 10, format!("{:.2}", is_txt));

let game_stats = world.get::<GameStats>().unwrap();
ctx.print(PLAY_WIDTH + 1, SCREEN_HEIGHT - 7, "Total Damage");
ctx.print(
Expand All @@ -110,3 +135,8 @@ pub fn render_ui(world: &mut World, ctx: &mut BTerm) {
);
}
}
/// Renders a cursor at mouse position
pub fn render_cursor(world: &mut World, ctx: &mut BTerm) {
let mouse = world.get::<Mouse>().unwrap();
ctx.print(mouse.pos.0, mouse.pos.1, format!(">"));
}
62 changes: 62 additions & 0 deletions src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,66 @@ pub struct Mouse {
pub pos: (i32, i32),
/// The left button was clicked
pub left_click: bool,
// /// The right button was clicked
// pub right_click: bool,
}

/// Current game mode. Used to disable/enable specific systems
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum GameMode {
/// Default game mode
Shotcaller,
/// Game mode where player directly controls individual units (aka. traditional RTS controls).
MircoInput,
Winsalot marked this conversation as resolved.
Show resolved Hide resolved
}

impl Default for GameMode {
fn default() -> Self {
GameMode::Shotcaller
}
}

/// State of UI for micro-input
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
pub enum InputState {
/// Default state
Default,
/// State when next input is to be considered M-Move target
MMove,
/// State when next input is to be considered A-Move target
AMove,
}

impl Default for InputState {
fn default() -> Self {
InputState::Default
}
}

/// Stores units that were selected by the player
#[derive(Clone, Debug, new)]
pub struct SelectedUnits {
/// Vector of all selected Entities
pub units: Vec<Entity>,
}

impl Default for SelectedUnits {
fn default() -> Self {
SelectedUnits { units: vec![] }
}
}

/// Random number generator to be used in this game
#[derive(Clone, Debug, new)]
pub struct RandomNG {
/// rng
pub rng: oorandom::Rand32,
}

impl Default for RandomNG {
fn default() -> Self {
RandomNG {
rng: oorandom::Rand32::new(1),
}
}
}
4 changes: 4 additions & 0 deletions src/states/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ impl minigene::State for DefaultState {
}
ctx.set_active_console(0);
render_ui(world, ctx);
// TODO: Mouse cursor should be on top of all other sprites
render_cursor(world, ctx);
}

// Update mouse info
{
if let Ok(mut m) = world.get_mut::<Mouse>() {
m.pos = ctx.mouse_pos();
m.left_click = ctx.left_click;
// TODO: there is no variable ctx.right_click. Use rltk::Input::is_mouse_button_pressed(2)
//m.right_click = ctx.right_click;
}
}

Expand Down
Loading