-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f552f20
commit 11426e1
Showing
8 changed files
with
496 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,100 @@ | ||
use std::marker::PhantomData; | ||
|
||
use bevy::{ecs::system::IntoObserverSystem, prelude::*}; | ||
|
||
/// Marker component for observer hooks added by a specific component. | ||
#[derive(Component, Copy, Clone, Default, Debug)] | ||
pub struct ObserverFor<C: Component>(PhantomData<C>); | ||
|
||
impl<C: Component> ObserverFor<C> { | ||
pub fn new() -> Self { | ||
ObserverFor(PhantomData) | ||
} | ||
|
||
pub fn despawn_for( | ||
In(id): In<Entity>, | ||
q: Query<&Children, With<Self>>, | ||
mut commands: Commands, | ||
) { | ||
for observer in q.iter_descendants(id) { | ||
commands.entity(observer).despawn(); | ||
} | ||
} | ||
} | ||
|
||
pub struct EntityCommandsOf<'a, 'w: 'a, C: Component> { | ||
entity: &'a mut EntityCommands<'w>, | ||
_ph: PhantomData<C>, | ||
} | ||
impl<'a, 'w: 'a, C: Component> EntityCommandsOf<'a, 'w, C> { | ||
pub fn new(entity: &'a mut EntityCommands<'w>) -> Self { | ||
Self { | ||
entity, | ||
_ph: PhantomData, | ||
} | ||
} | ||
} | ||
impl<'a, 'w: 'a, C: Component> From<&'a mut EntityCommands<'w>> for EntityCommandsOf<'a, 'w, C> { | ||
fn from(entity: &'a mut EntityCommands<'w>) -> Self { | ||
Self::new(entity) | ||
} | ||
} | ||
|
||
pub trait EntityExtsOf<'w, C: Component> { | ||
fn observe<E, B, M>( | ||
&mut self, | ||
system: impl IntoObserverSystem<E, B, M>, | ||
) -> &mut EntityCommands<'w> | ||
where | ||
E: Event, | ||
B: Bundle; | ||
|
||
fn despawn_observers(&mut self) -> &mut Self; | ||
} | ||
|
||
impl<'w, C: Component> EntityExtsOf<'w, C> for EntityCommandsOf<'_, 'w, C> { | ||
fn observe<E, B, M>( | ||
&mut self, | ||
system: impl IntoObserverSystem<E, B, M>, | ||
) -> &mut EntityCommands<'w> | ||
where | ||
E: Event, | ||
B: Bundle, | ||
{ | ||
self.entity.observe(system) | ||
} | ||
|
||
fn despawn_observers(&mut self) -> &mut Self { | ||
let id = self.entity.id(); | ||
self.entity | ||
.commands() | ||
.run_system_cached_with(ObserverFor::<C>::despawn_for, id); | ||
self | ||
} | ||
} | ||
|
||
pub trait EntityExts<'w> { | ||
type Of<'a, C: Component> | ||
where | ||
Self: 'a, | ||
'w: 'a; | ||
|
||
fn of<'a, C: Component>(&'a mut self) -> Self::Of<'a, C> | ||
where | ||
'w: 'a; | ||
} | ||
|
||
impl<'w> EntityExts<'w> for EntityCommands<'w> { | ||
type Of<'a, C: Component> | ||
= EntityCommandsOf<'a, 'w, C> | ||
where | ||
Self: 'a, | ||
'w: 'a; | ||
|
||
fn of<'a, C: Component>(&'a mut self) -> Self::Of<'a, C> | ||
where | ||
'w: 'a, | ||
{ | ||
Self::Of::from(self) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
use bevy::prelude::*; | ||
|
||
#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] | ||
#[derive(Reflect)] | ||
pub enum Job { | ||
// Tanks | ||
Paladin, | ||
Warrior, | ||
DarkKnight, | ||
Gunbreaker, | ||
|
||
// Pure healers | ||
WhiteMage, | ||
Astrologian, | ||
|
||
// Barrier healers | ||
Scholar, | ||
Sage, | ||
|
||
// Melee DPS | ||
Monk, | ||
Dragoon, | ||
Ninja, | ||
Samurai, | ||
Reaper, | ||
Viper, | ||
|
||
// Physical ranged DPS | ||
Bard, | ||
Machinist, | ||
Dancer, | ||
|
||
// Magical ranged DPS | ||
BlackMage, | ||
Summoner, | ||
RedMage, | ||
Pictomancer, | ||
Fisher, | ||
|
||
// Limited jobs | ||
BlueMage, | ||
Beastmaster, | ||
} | ||
|
||
impl Job { | ||
pub fn abbrev(self) -> &'static str { | ||
use Job::*; | ||
match self { | ||
Paladin => "PLD", | ||
Warrior => "WAR", | ||
DarkKnight => "DRK", | ||
Gunbreaker => "GNB", | ||
WhiteMage => "WHM", | ||
Astrologian => "AST", | ||
Scholar => "SCH", | ||
Sage => "SGE", | ||
Monk => "MNK", | ||
Dragoon => "DRG", | ||
Ninja => "NIN", | ||
Samurai => "SAM", | ||
Reaper => "RPR", | ||
Viper => "VPR", | ||
Bard => "BRD", | ||
Machinist => "MCH", | ||
Dancer => "DNC", | ||
BlackMage => "BLM", | ||
Summoner => "SMN", | ||
RedMage => "RDM", | ||
Pictomancer => "PCT", | ||
Fisher => "FSH", | ||
BlueMage => "BLU", | ||
Beastmaster => "BSM", | ||
} | ||
} | ||
|
||
pub fn icon_asset_path(self) -> &'static str { | ||
use Job::*; | ||
match self { | ||
Paladin => "sprites/jobs/pld.png", | ||
Warrior => "sprites/jobs/war.png", | ||
DarkKnight => "sprites/jobs/drk.png", | ||
Gunbreaker => "sprites/jobs/gnb.png", | ||
WhiteMage => "sprites/jobs/whm.png", | ||
Astrologian => "sprites/jobs/ast.png", | ||
Scholar => "sprites/jobs/sch.png", | ||
Sage => "sprites/jobs/sge.png", | ||
Monk => "sprites/jobs/mnk.png", | ||
Dragoon => "sprites/jobs/drg.png", | ||
Ninja => "sprites/jobs/nin.png", | ||
Samurai => "sprites/jobs/sam.png", | ||
Reaper => "sprites/jobs/rpr.png", | ||
Viper => "sprites/jobs/vpr.png", | ||
Bard => "sprites/jobs/brd.png", | ||
Machinist => "sprites/jobs/mch.png", | ||
Dancer => "sprites/jobs/dnc.png", | ||
BlackMage => "sprites/jobs/blm.png", | ||
Summoner => "sprites/jobs/smn.png", | ||
RedMage => "sprites/jobs/rdm.png", | ||
Pictomancer => "sprites/jobs/pct.png", | ||
Fisher => "sprites/jobs/fsh.png", | ||
BlueMage => "sprites/jobs/blu.png", | ||
Beastmaster => Self::none_asset_path(), | ||
} | ||
} | ||
|
||
pub fn none_asset_path() -> &'static str { | ||
"sprites/jobs/none.png" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
use avian2d::prelude::Collider; | ||
use bevy::prelude::*; | ||
use job::Job; | ||
|
||
use crate::{drag::Draggable, spawner::Spawnable}; | ||
|
||
pub mod job; | ||
pub mod window; | ||
|
||
/// The size of a player icon. | ||
const PLAYER_SPRITE_SIZE: f32 = 2.0; | ||
|
||
const PLAYER_COLLIDER_SIZE: f32 = 0.001; | ||
|
||
#[derive(Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd, Component, Reflect)] | ||
#[require(Draggable)] | ||
#[require(Collider(|| Collider::circle(PLAYER_COLLIDER_SIZE)))] | ||
#[require(PlayerSprite)] | ||
pub struct Player {} | ||
|
||
impl Player {} | ||
|
||
#[derive(Copy, Default, Clone, Hash, PartialEq, Eq, Ord, PartialOrd, Debug)] | ||
#[derive(Component, Reflect)] | ||
#[require(Sprite(||Sprite{custom_size: Some(Vec2::splat(PLAYER_SPRITE_SIZE)), ..default()}))] | ||
pub struct PlayerSprite { | ||
pub job: Option<Job>, | ||
} | ||
|
||
impl PlayerSprite { | ||
pub fn update_sprites( | ||
mut q: Query<(&PlayerSprite, &mut Sprite), Changed<PlayerSprite>>, | ||
asset_server: Res<AssetServer>, | ||
) { | ||
for (player_sprite, mut sprite) in &mut q { | ||
sprite.image = asset_server.load(player_sprite.asset_path()); | ||
sprite.custom_size = Some(Vec2::splat(PLAYER_SPRITE_SIZE)); | ||
} | ||
} | ||
|
||
pub fn asset_path(self) -> &'static str { | ||
self.job | ||
.map_or(Job::none_asset_path(), Job::icon_asset_path) | ||
} | ||
} | ||
|
||
impl Spawnable for PlayerSprite { | ||
const UNIQUE: bool = true; | ||
|
||
fn spawner_name(&self) -> std::borrow::Cow<'static, str> { | ||
format!("{:#?} Spawner", self.job).into() | ||
} | ||
|
||
fn texture_handle(&self, asset_server: &AssetServer) -> Handle<Image> { | ||
asset_server.load(self.asset_path()) | ||
} | ||
|
||
fn insert(&self, entity: &mut EntityCommands) { | ||
entity.insert((Player {}, *self)); | ||
} | ||
} | ||
|
||
pub struct PlayerPlugin; | ||
|
||
impl Plugin for PlayerPlugin { | ||
fn build(&self, app: &mut App) { | ||
app.add_systems(PostUpdate, PlayerSprite::update_sprites); | ||
} | ||
} | ||
|
||
pub fn plugin() -> PlayerPlugin { | ||
PlayerPlugin | ||
} |
Oops, something went wrong.