├── .gitignore ├── _rust-toolchain.toml ├── assets ├── level.progression.yaml ├── xp.png ├── arrow.png ├── shadow.png ├── tileset.png ├── health_bar.png ├── BitPotionExt.ttf ├── health_bar_fill.png ├── health_bar_border.png ├── monogram-extended.ttf ├── entities │ ├── enemies │ │ ├── Mushroom.png │ │ ├── FlyingEye.png │ │ ├── demon_slime.png │ │ ├── mushroom.yaml │ │ ├── flying_eye.yaml │ │ ├── enemy.yaml │ │ ├── bosses.yaml │ │ └── data.yaml │ └── player │ │ ├── GUMDROP.E64.R.PNG │ │ └── player.yaml ├── monster_flesh_eye_sheet.png ├── monster_flesh_teeth_sheet.png ├── floors │ ├── start.yaml.floor │ └── medium.yaml.floor └── domains.yaml ├── src ├── map │ ├── mod.rs │ ├── walkable.rs │ ├── generation.rs │ └── map.rs ├── game_states │ ├── mod.rs │ ├── menu.rs │ ├── loading.rs │ └── ingame.rs ├── movement │ ├── mod.rs │ ├── direction.rs │ ├── movement.rs │ └── easing.rs ├── state.rs ├── sorting.rs ├── effects.rs ├── prototype.rs ├── statistics.rs ├── main.rs ├── animation.rs ├── ui │ ├── boss.rs │ └── player.rs ├── manifest │ ├── floor.rs │ ├── player.rs │ ├── boss.rs │ ├── enemy.rs │ └── mod.rs ├── boss.rs ├── enemy.rs ├── helper.rs ├── ui.rs ├── controller.rs ├── collision.rs ├── enemy │ └── state_machine.rs ├── stats.rs ├── floor.rs ├── player.rs └── attack.rs ├── Cargo.toml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.idea 3 | /.fleet 4 | /.vscode -------------------------------------------------------------------------------- /_rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | -------------------------------------------------------------------------------- /assets/level.progression.yaml: -------------------------------------------------------------------------------- 1 | base_xp: 100 2 | xp_multiplier: 1.5 3 | -------------------------------------------------------------------------------- /src/map/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod generation; 2 | pub mod walkable; 3 | pub mod map; 4 | -------------------------------------------------------------------------------- /src/game_states/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ingame; 2 | pub mod loading; 3 | pub mod menu; 4 | -------------------------------------------------------------------------------- /src/movement/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod direction; 2 | pub mod easing; 3 | pub mod movement; 4 | -------------------------------------------------------------------------------- /assets/xp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/xp.png -------------------------------------------------------------------------------- /assets/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/arrow.png -------------------------------------------------------------------------------- /assets/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/shadow.png -------------------------------------------------------------------------------- /assets/tileset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/tileset.png -------------------------------------------------------------------------------- /assets/health_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/health_bar.png -------------------------------------------------------------------------------- /assets/BitPotionExt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/BitPotionExt.ttf -------------------------------------------------------------------------------- /assets/health_bar_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/health_bar_fill.png -------------------------------------------------------------------------------- /assets/health_bar_border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/health_bar_border.png -------------------------------------------------------------------------------- /assets/monogram-extended.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/monogram-extended.ttf -------------------------------------------------------------------------------- /assets/entities/enemies/Mushroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/entities/enemies/Mushroom.png -------------------------------------------------------------------------------- /assets/monster_flesh_eye_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/monster_flesh_eye_sheet.png -------------------------------------------------------------------------------- /assets/monster_flesh_teeth_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/monster_flesh_teeth_sheet.png -------------------------------------------------------------------------------- /assets/entities/enemies/FlyingEye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/entities/enemies/FlyingEye.png -------------------------------------------------------------------------------- /assets/entities/enemies/demon_slime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/entities/enemies/demon_slime.png -------------------------------------------------------------------------------- /assets/entities/player/GUMDROP.E64.R.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edgarssilva/relentless-revenge/HEAD/assets/entities/player/GUMDROP.E64.R.PNG -------------------------------------------------------------------------------- /assets/floors/start.yaml.floor: -------------------------------------------------------------------------------- 1 | floors: [1, 5] 2 | 3 | rooms: [2, 3] 4 | room_size: [3, 4] 5 | enemies_count: [2, 6] 6 | 7 | enemies: 8 | - path: "../entities/enemies/yaml.enemy" 9 | weight: 4 10 | - path: "../entities/enemies/flying_eye.yaml.enemy" 11 | weight: 1 12 | -------------------------------------------------------------------------------- /assets/floors/medium.yaml.floor: -------------------------------------------------------------------------------- 1 | floors: [6, 20] 2 | 3 | rooms: [3, 6] 4 | room_size: [4, 6] 5 | enemies_count: [6, 24] 6 | 7 | enemies: 8 | - path: "../entities/enemies/yaml.enemy" 9 | weight: 2 10 | - path: "../entities/enemies/flying_eye.yaml.enemy" 11 | weight: 2 12 | - path: "../entities/enemies/mushroom.yaml.enemy" 13 | weight: 1 14 | -------------------------------------------------------------------------------- /assets/entities/enemies/mushroom.yaml: -------------------------------------------------------------------------------- 1 | name: "Mushroom" 2 | 3 | xp: 75 4 | damage: 5 5 | health: 200 6 | speed: 15 7 | cooldown: 7500 8 | 9 | texture: 10 | path: "./Mushroom.png" 11 | tile_size: [150, 150] 12 | rows: 1 13 | columns: 8 14 | frames: [0, 1, 2, 3, 4, 5, 6, 7] 15 | duration: 100 16 | 17 | scale: [1, 1] 18 | hitbox: [25, 40] 19 | 20 | attack: 21 | type: "Melee" 22 | size: [40, 40] 23 | duration: 3.0 24 | knockback: 5.0 25 | 26 | feet_offset: 20 27 | -------------------------------------------------------------------------------- /src/state.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::Component; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Component, Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Copy, Debug)] 5 | pub enum State { 6 | Idle, 7 | Walking, 8 | Attacking(u32), //Index of the attack in a combo 9 | Dashing, 10 | _Dying, 11 | } 12 | 13 | impl State { 14 | pub fn set(&mut self, state: State) { 15 | *self = state; 16 | } 17 | 18 | pub fn equals(&self, other: Self) -> bool { 19 | *self == other 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /assets/entities/enemies/flying_eye.yaml: -------------------------------------------------------------------------------- 1 | name: "Flying Eye" 2 | 3 | xp: 55 4 | damage: 15 5 | health: 60 6 | speed: 30 7 | cooldown: 6500 8 | 9 | texture: 10 | path: "./FlyingEye.png" 11 | tile_size: [150, 150] 12 | rows: 1 13 | columns: 8 14 | frames: [0, 1, 2, 3, 4, 5, 6, 7] 15 | duration: 100 16 | 17 | scale: [1.2, 1.2] 18 | hitbox: [24, 24] 19 | 20 | attack: 21 | type: "Ranged" 22 | size: [100, 20] 23 | velocity: 70 24 | duration: 3.0 25 | texture: 26 | path: "../../arrow.png" 27 | tile_size: [100, 100] 28 | rows: 5 29 | columns: 6 30 | duration: 100 31 | 32 | feet_offset: 20 33 | -------------------------------------------------------------------------------- /assets/entities/enemies/enemy.yaml: -------------------------------------------------------------------------------- 1 | name: "Cool Enemy" 2 | 3 | xp: 50 4 | damage: 10 5 | health: 100 6 | speed: 20 7 | cooldown: 7000 8 | 9 | texture: 10 | path: "../../monster_flesh_eye_sheet.png" 11 | tile_size: [256, 256] 12 | rows: 3 13 | columns: 3 14 | frames: [0, 1, 2, 3, 4, 5, 6, 7] 15 | duration: 250 16 | 17 | scale: [0.25, 0.25] 18 | hitbox: [96, 96] 19 | 20 | attack: 21 | type: "Ranged" 22 | size: [100, 20] 23 | velocity: 70 24 | duration: 3.0 25 | texture: 26 | path: "../../arrow.png" 27 | tile_size: [100, 100] 28 | rows: 5 29 | columns: 6 30 | duration: 100 31 | 32 | feet_offset: 24 33 | -------------------------------------------------------------------------------- /src/sorting.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::{Component, Query, Transform}; 2 | 3 | //pub const MAP_LAYER: f32 = 0.0; 4 | pub const ENTITIES_LAYER: f32 = 100.0; 5 | 6 | const MAX_Y: f32 = 10000.0; 7 | 8 | #[derive(Component)] 9 | pub struct YSort(pub f32); 10 | 11 | #[derive(Component)] 12 | pub struct FeetOffset(pub f32); 13 | 14 | pub fn ysort(mut query: Query<(&YSort, &mut Transform, Option<&FeetOffset>)>) { 15 | for (ysort, mut transform, offset) in query.iter_mut() { 16 | let offset = offset.map(|x| x.0).unwrap_or(0.0); 17 | transform.translation.z = ysort.0 - ((transform.translation.y - offset) / MAX_Y); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/game_states/menu.rs: -------------------------------------------------------------------------------- 1 | use bevy::{ 2 | input::ButtonInput, 3 | prelude::{App, KeyCode, NextState, OnEnter, Plugin, Res, ResMut}, 4 | }; 5 | 6 | use crate::GameState; 7 | 8 | pub struct MainMenuPlugin; 9 | 10 | impl Plugin for MainMenuPlugin { 11 | fn build(&self, app: &mut App) { 12 | app.add_systems(OnEnter(GameState::MainMenu), (setup_menu, skip_menu)); 13 | } 14 | } 15 | 16 | fn setup_menu() {} 17 | 18 | fn skip_menu(keys: Res>, mut state: ResMut>) { 19 | if keys.any_just_pressed([KeyCode::Space, KeyCode::Backslash]) { 20 | state.set(GameState::InGame); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /assets/domains.yaml: -------------------------------------------------------------------------------- 1 | domains: 2 | - name: "Entrance" 3 | floors: [1, 5] 4 | 5 | rooms: [2, 3] 6 | room_size: [3, 4] 7 | enemies_count: [2, 6] 8 | 9 | boss: "Demon Slime" 10 | 11 | enemies: 12 | - [4, "Cool Enemy"] 13 | - [1, "Flying Eye"] 14 | 15 | 16 | - name: "Dungeon" 17 | floors: [6, 20] 18 | 19 | rooms: [3, 6] 20 | room_size: [4, 6] 21 | enemies_count: [6, 24] 22 | 23 | boss: "Demon Slime" 24 | 25 | enemies: 26 | - [2, "Cool Enemy"] 27 | - [2, "Flying Eye"] 28 | - [1, "Mushroom"] 29 | # - name: "Cool Enemy" 30 | # weight: 2 31 | # - name: "Flying Eye" 32 | # weight: 2 33 | # - name: "Mushroom" 34 | # weight: 1 35 | -------------------------------------------------------------------------------- /src/effects.rs: -------------------------------------------------------------------------------- 1 | use crate::{game_states::loading::GameAssets, sorting::FeetOffset}; 2 | use bevy::prelude::*; 3 | 4 | #[derive(Component)] 5 | pub struct Shadow; 6 | 7 | pub fn spawn_shadows( 8 | query: Query<(Entity, Option<&FeetOffset>), Added>, 9 | game_assets: Res, 10 | mut commands: Commands, 11 | ) { 12 | for (entity, offset) in query.iter() { 13 | let offset = offset.map(|x| x.0).unwrap_or(0.0); 14 | commands.entity(entity).with_children(|parent| { 15 | parent.spawn(SpriteBundle { 16 | texture: game_assets.shadow_texture.clone(), 17 | transform: Transform::from_xyz(0., -offset, -0.5), 18 | ..Default::default() 19 | }); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /assets/entities/enemies/bosses.yaml: -------------------------------------------------------------------------------- 1 | bosses: 2 | - name: "Demon Slime" 3 | 4 | xp: 1500 5 | damage: 50 6 | health: 100 7 | speed: 20 8 | 9 | scale: [1, 1] 10 | hitbox: [96, 96] 11 | 12 | feet_offset: 48 13 | 14 | texture: 15 | path: "entities/enemies/demon_slime.png" 16 | tile_size: [288, 160] 17 | rows: 5 18 | columns: 22 19 | 20 | animations: 21 | - name: "idle" 22 | #frames: [0, 1, 2, 3, 4, 5] 23 | frames: [22, 23, 24, 25,26,27,28,29,30,31] 24 | duration: 250 25 | 26 | - name: "jump" 27 | frames: [22, 33] 28 | duration: 250 29 | 30 | - name: "attack" 31 | frames: [44, 58] 32 | duration: 250 33 | 34 | - name: "hit" 35 | frames: [66, 70] 36 | duration: 250 37 | 38 | - name: "death" 39 | frames: [88, 109] 40 | duration: 250 41 | 42 | -------------------------------------------------------------------------------- /src/prototype.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | use crate::player::PlayerBundle; 3 | use bevy::prelude::{Component, FromReflect, Vec2}; 4 | use bevy::reflect::{Reflect, ReflectMut, ReflectOwned, ReflectRef, Typed, TypeInfo}; 5 | use bevy_proto::prelude::{DependenciesBuilder, Schematic, SchematicContext}; 6 | 7 | #[derive(Reflect, FromReflect)] 8 | pub struct StatsProto { 9 | pub health: u32, 10 | pub damage: u32, 11 | pub speed: u32, 12 | pub cooldown: u32, 13 | pub xp: u32, 14 | } 15 | 16 | #[derive(Reflect, FromReflect)] 17 | pub struct PlayerProto { 18 | name: String, 19 | stats: StatsProto, 20 | size: Vec2, 21 | hitbox: Vec2, 22 | } 23 | 24 | impl Schematic for PlayerBundle { 25 | type Input = PlayerProto; 26 | 27 | fn apply(input: &Self::Input, context: &mut SchematicContext) {} 28 | 29 | fn remove(input: &Self::Input, context: &mut SchematicContext) {} 30 | 31 | fn preload_dependencies(input: &mut Self::Input, dependencies: &mut DependenciesBuilder) {} 32 | } 33 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "isometric" 4 | version = "0.1.0" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | bevy = {version = "0.14", features = ["dynamic_linking"] } 10 | bevy_egui = "0.29.0" 11 | bevy_rapier2d = "0.27" 12 | bevy_ecs_tilemap = "0.14" 13 | 14 | #big-brain = "0.16.0" 15 | seldom_state = "0.11" 16 | 17 | leafwing-input-manager = "0.15" 18 | leafwing_manifest = {version = "0.2.0", features = ["yaml"]} 19 | 20 | #bevy_asset_loader = { version = "0.20", features = ["2d"] } 21 | bevy_common_assets = { version = "0.11", features = ["yaml"] } 22 | 23 | turborand = "0.10.0" 24 | dirs = "5.0" 25 | serde = "1.0" 26 | bevy-persistent = { version = "0.6", features = ["all"] } 27 | noisy_bevy = "0.7" 28 | bevy_spritesheet_animation = "0.4.2" 29 | 30 | # Otimizations to speed up compilation in debug mode 31 | # Enable a small amount of optimization in debug mode 32 | [profile.dev] 33 | opt-level = 1 34 | 35 | # Enable high optimizations for dependencies (incl. Bevy), but not for our code: 36 | [profile.dev.package."*"] 37 | opt-level = 3 38 | -------------------------------------------------------------------------------- /src/statistics.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use bevy::time::{Timer, TimerMode}; 3 | use bevy::utils::Duration; 4 | use bevy_persistent::prelude::*; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | use crate::player::Player; 8 | 9 | #[derive(Resource, Serialize, Deserialize, Debug, Clone, Default)] 10 | pub struct Statistics { 11 | pub kills: u32, 12 | pub deaths: u32, 13 | pub dashes: u32, 14 | pub damage_dealt: u32, 15 | pub damage_taken: u32, 16 | pub max_xp: u32, 17 | pub max_level: u32, 18 | pub revenge_time: f32, 19 | pub play_time: f32, 20 | pub game_count: u32, 21 | pub healing: u32, 22 | } 23 | 24 | pub fn auto_save( 25 | time: Res