├── .gitignore ├── src ├── plugins │ ├── entities │ │ ├── terrain │ │ │ ├── obstacles.rs │ │ │ ├── mod.rs │ │ │ ├── env.rs │ │ │ └── buildings.rs │ │ ├── player │ │ │ ├── plugins │ │ │ │ ├── mod.rs │ │ │ │ ├── score.rs │ │ │ │ └── memory.rs │ │ │ ├── components.rs │ │ │ ├── states.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── background │ │ │ └── mod.rs │ │ ├── camera │ │ │ └── mod.rs │ │ └── bytes │ │ │ └── mod.rs │ ├── mod.rs │ ├── game │ │ ├── states.rs │ │ ├── mod.rs │ │ ├── rpc.rs │ │ ├── ground.rs │ │ ├── menu.rs │ │ ├── dialog.rs │ │ ├── setup.rs │ │ ├── restart.rs │ │ ├── assets.rs │ │ ├── sounds.rs │ │ └── animation.rs │ └── debug.rs ├── main.rs ├── bsod.rs └── lib.rs ├── .cargo └── config.toml.example ├── assets ├── pts.png ├── bytes.png ├── icon │ ├── ico.ico │ ├── ico.png │ └── ico.psd ├── player.png ├── player.psd ├── audio │ ├── jump.ogg │ ├── death.ogg │ ├── ambience.ogg │ └── original.ogg ├── terrain │ ├── board.png │ ├── board.psd │ ├── left.png │ ├── right.png │ ├── side.psd │ ├── cabinet.png │ ├── cabinet.psd │ ├── middle.png │ └── middle.psd ├── fonts │ └── VCR_OSD_MONO.ttf ├── background │ ├── background.psd │ ├── background_scaled.psd │ ├── background_scaled_0004_sky.png │ ├── background_scaled_0001_cloud_1.png │ ├── background_scaled_0003_cloud_0.png │ ├── background_scaled_0000_buildings_1.png │ └── background_scaled_0002_buildings_0.png └── README.md ├── Makefile.toml ├── Cargo.toml ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .cargo/config.toml -------------------------------------------------------------------------------- /src/plugins/entities/terrain/obstacles.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.cargo/config.toml.example: -------------------------------------------------------------------------------- 1 | [env] 2 | DISCORD_APP_ID = "696969696969696969" -------------------------------------------------------------------------------- /src/plugins/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod debug; 2 | pub mod entities; 3 | pub mod game; 4 | -------------------------------------------------------------------------------- /assets/pts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/pts.png -------------------------------------------------------------------------------- /assets/bytes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/bytes.png -------------------------------------------------------------------------------- /assets/icon/ico.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/icon/ico.ico -------------------------------------------------------------------------------- /assets/icon/ico.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/icon/ico.png -------------------------------------------------------------------------------- /assets/icon/ico.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/icon/ico.psd -------------------------------------------------------------------------------- /assets/player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/player.png -------------------------------------------------------------------------------- /assets/player.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/player.psd -------------------------------------------------------------------------------- /assets/audio/jump.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/audio/jump.ogg -------------------------------------------------------------------------------- /assets/audio/death.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/audio/death.ogg -------------------------------------------------------------------------------- /assets/terrain/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/board.png -------------------------------------------------------------------------------- /assets/terrain/board.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/board.psd -------------------------------------------------------------------------------- /assets/terrain/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/left.png -------------------------------------------------------------------------------- /assets/terrain/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/right.png -------------------------------------------------------------------------------- /assets/terrain/side.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/side.psd -------------------------------------------------------------------------------- /assets/audio/ambience.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/audio/ambience.ogg -------------------------------------------------------------------------------- /assets/audio/original.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/audio/original.ogg -------------------------------------------------------------------------------- /assets/terrain/cabinet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/cabinet.png -------------------------------------------------------------------------------- /assets/terrain/cabinet.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/cabinet.psd -------------------------------------------------------------------------------- /assets/terrain/middle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/middle.png -------------------------------------------------------------------------------- /assets/terrain/middle.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/terrain/middle.psd -------------------------------------------------------------------------------- /assets/fonts/VCR_OSD_MONO.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/fonts/VCR_OSD_MONO.ttf -------------------------------------------------------------------------------- /src/plugins/entities/player/plugins/mod.rs: -------------------------------------------------------------------------------- 1 | mod memory; 2 | mod score; 3 | 4 | pub use memory::*; 5 | pub use score::*; 6 | -------------------------------------------------------------------------------- /assets/background/background.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background.psd -------------------------------------------------------------------------------- /assets/background/background_scaled.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background_scaled.psd -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # Assets 2 | all of the assets were hand crafted but these: 3 | - [/audio/ambience.gg](https://youtu.be/v-N5pJ6VFYc?si=WpEi1h83jOpCOH7l) -------------------------------------------------------------------------------- /assets/background/background_scaled_0004_sky.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background_scaled_0004_sky.png -------------------------------------------------------------------------------- /assets/background/background_scaled_0001_cloud_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background_scaled_0001_cloud_1.png -------------------------------------------------------------------------------- /assets/background/background_scaled_0003_cloud_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background_scaled_0003_cloud_0.png -------------------------------------------------------------------------------- /assets/background/background_scaled_0000_buildings_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background_scaled_0000_buildings_1.png -------------------------------------------------------------------------------- /assets/background/background_scaled_0002_buildings_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/theunrealtarik/malformed/HEAD/assets/background/background_scaled_0002_buildings_0.png -------------------------------------------------------------------------------- /src/plugins/entities/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod background; 2 | pub mod bytes; 3 | pub mod camera; 4 | pub mod player; 5 | pub mod terrain; 6 | 7 | pub mod prelude { 8 | pub use super::background::*; 9 | pub use super::bytes::*; 10 | pub use super::camera::*; 11 | pub use super::player::*; 12 | pub use super::terrain::*; 13 | } 14 | -------------------------------------------------------------------------------- /Makefile.toml: -------------------------------------------------------------------------------- 1 | [tasks.build-release] 2 | condition = { profiles = ["production"] } 3 | command = "cargo" 4 | args = ["build", "--release"] 5 | 6 | [tasks.build-debug] 7 | command = "cargo" 8 | args = ["build", "--features", "bevy/dynamic_linking"] 9 | 10 | [tasks.run] 11 | command = "cargo" 12 | args = ["run", "--features", "bevy/dynamic_linking"] 13 | 14 | -------------------------------------------------------------------------------- /src/plugins/game/states.rs: -------------------------------------------------------------------------------- 1 | use crate::plugins::debug::*; 2 | use bevy::prelude::*; 3 | 4 | #[derive(Clone, Copy, Default, Eq, PartialEq, Debug, Hash, States, Reflect)] 5 | #[allow(dead_code)] 6 | pub enum GameState { 7 | #[default] 8 | Paused, 9 | Resumed, 10 | } 11 | 12 | #[derive(Clone, Copy, Default, Eq, PartialEq, Debug, Hash, States, Reflect, InspectorOptions)] 13 | #[reflect(InspectorOptions)] 14 | pub enum GameAssetsState { 15 | #[default] 16 | Pending, 17 | Loaded, 18 | } 19 | -------------------------------------------------------------------------------- /src/plugins/game/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod animation; 2 | pub mod assets; 3 | pub mod dialog; 4 | pub mod ground; 5 | pub mod menu; 6 | pub mod restart; 7 | pub mod rpc; 8 | pub mod setup; 9 | pub mod sounds; 10 | pub mod states; 11 | 12 | pub mod prelude { 13 | use bevy::prelude::*; 14 | 15 | #[derive(Component, Default)] 16 | pub struct Responsive; 17 | 18 | pub use super::animation::*; 19 | pub use super::assets::*; 20 | pub use super::dialog::*; 21 | pub use super::ground::*; 22 | pub use super::menu::*; 23 | pub use super::restart::*; 24 | pub use super::rpc::*; 25 | pub use super::setup::*; 26 | pub use super::sounds::*; 27 | pub use super::states::*; 28 | } 29 | -------------------------------------------------------------------------------- /src/plugins/entities/terrain/mod.rs: -------------------------------------------------------------------------------- 1 | use bevy::{prelude::*, sprite::Anchor}; 2 | use bevy_rapier2d::prelude::*; 3 | 4 | use glib::*; 5 | 6 | #[derive(Component, Reflect, Clone, Copy, Debug, Default)] 7 | pub struct Platform { 8 | pub coords: (f32, f32), 9 | pub width: f32, 10 | } 11 | 12 | #[derive(Component)] 13 | pub struct Scrollable; 14 | 15 | // mod obstacles; 16 | mod buildings; 17 | mod env; 18 | 19 | // pub use obstacles::*; 20 | pub use buildings::*; 21 | pub use env::*; 22 | 23 | pub struct TerrainPlugin; 24 | 25 | impl Plugin for TerrainPlugin { 26 | fn build(&self, app: &mut App) { 27 | app.add_plugins(BuildingsPlugin) 28 | .add_plugins(EnvironmentPlugin); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod plugins; 2 | 3 | use bevy::prelude::*; 4 | use plugins::entities::prelude::*; 5 | use plugins::game::prelude::*; 6 | 7 | fn main() { 8 | App::new() 9 | .add_plugins(GameAssetsPlugin) 10 | .add_plugins(GameEssentialsPlugin) 11 | .add_plugins(GameAnimationPlugin) 12 | .add_plugins(GameCameraPlugin) 13 | .add_plugins(GameSoundTrack) 14 | .add_plugins(GameMenuPlugin) 15 | .add_plugins(GameRestartPlugin) 16 | .add_plugins(BackgroundPlugin) 17 | .add_plugins(TerrainPlugin) 18 | .add_plugins(BytesPlugin) 19 | .add_plugins(PlayerPlugin) 20 | .add_plugins(RPCPlugin) 21 | .add_plugins(DialogPlugin) 22 | .run(); 23 | } 24 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "malformed" 3 | version = "0.1.0" 4 | edition = "2021" 5 | homepage = "https://github.com/theunrealtarik/malformed" 6 | 7 | [lib] 8 | name = "glib" 9 | path = "./src/lib.rs" 10 | 11 | [features] 12 | bsod = [] 13 | 14 | [dependencies] 15 | bevy = { version = "0.13.2", features = ["hdr", "bevy_audio" ] } 16 | bevy_egui = "0.27" 17 | bevy_asset_loader = { version = "0.20.2", features = ["2d"] } 18 | bevy-inspector-egui = "0.24.0" 19 | bevy_rapier2d = { version = "0.26.0" } 20 | bevy_kira_audio = "0.19.0" 21 | bevy_embedded_assets = "0.10.2" 22 | rand = "0.8.5" 23 | bevy_tweening = "0.10.0" 24 | libc = "0.2.155" 25 | winapi = { version = "0.3", features = ["winuser"] } 26 | discord-rich-presence = "0.2.4" 27 | 28 | [build-dependencies] 29 | winres = "0.1.12" 30 | 31 | [profile.dev] 32 | opt-level = 1 33 | 34 | [profile.dev.package."*"] 35 | opt-level = 3 36 | -------------------------------------------------------------------------------- /src/plugins/entities/player/components.rs: -------------------------------------------------------------------------------- 1 | use crate::plugins::debug::*; 2 | use bevy::prelude::*; 3 | 4 | #[derive(Component, Reflect, Default)] 5 | pub struct Jump { 6 | pub coyote: f32, 7 | pub buffering: f32, 8 | pub press: f32, 9 | pub rising: bool, 10 | } 11 | 12 | #[derive(Component, Default)] 13 | pub(crate) struct Player; 14 | 15 | #[derive(Component)] 16 | pub struct PlayerGrounded; 17 | 18 | #[derive(Component, Reflect, Default)] 19 | pub(crate) struct AuxiliaryVelocity { 20 | pub value: Vec2, 21 | } 22 | 23 | #[derive(Component, Reflect, Default)] 24 | pub struct AuxiliaryAcceleration { 25 | pub value: Vec2, 26 | } 27 | 28 | #[derive(Component, Default, Reflect)] 29 | pub struct WalkingTimer(pub Timer); 30 | 31 | #[derive(Component, Default, Reflect)] 32 | pub struct DialogTimer(pub Timer); 33 | 34 | #[derive(Component, Reflect, InspectorOptions, Default)] 35 | #[reflect(InspectorOptions)] 36 | pub struct PlayerAnimationController { 37 | pub curr_animation: super::states::PlayerAnimation, 38 | } 39 | -------------------------------------------------------------------------------- /src/bsod.rs: -------------------------------------------------------------------------------- 1 | use winapi::shared::{ 2 | basetsd::PULONG_PTR, 3 | ntdef::{BOOLEAN, FALSE, LONG, NTSTATUS, PBOOLEAN, PULONG, TRUE, ULONG}, 4 | ntstatus::STATUS_IN_PAGE_ERROR, 5 | }; 6 | 7 | /// https://ntdoc.m417z.com/ntadjustprivilegestoken 8 | /// https://ntdoc.m417z.com/ntraiseharderror 9 | extern "C" { 10 | fn RtlAdjustPrivilege( 11 | Privilege: ULONG, 12 | Enable: BOOLEAN, 13 | CurrThread: BOOLEAN, 14 | StatusPointer: PBOOLEAN, 15 | ) -> NTSTATUS; 16 | 17 | fn NtRaiseHardError( 18 | ErrorStatus: LONG, 19 | Useless1: LONG, 20 | Useless2: LONG, 21 | Useless3: PULONG_PTR, 22 | ValidResponseOption: ULONG, 23 | ResponsePointer: PULONG, 24 | ) -> NTSTATUS; 25 | } 26 | 27 | pub fn bsod() { 28 | unsafe { 29 | let mut privilege_state = false as BOOLEAN; 30 | let mut error_response = 0 as ULONG; 31 | 32 | // 19 is `SE_SHUTDOWN_PRIVILEGE` declared in https://github.com/tpn/winsdk-10/blob/master/Include/10.0.14393.0/km/wdm.h#L5277 33 | RtlAdjustPrivilege(19, TRUE, FALSE, &mut privilege_state); 34 | NtRaiseHardError( 35 | STATUS_IN_PAGE_ERROR, 36 | 0, 37 | 0, 38 | std::ptr::null_mut(), 39 | 6, 40 | &mut error_response, 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/plugins/entities/player/states.rs: -------------------------------------------------------------------------------- 1 | use crate::{plugins::debug::*, Animation, Frame, DEFAULT_CYCLE_DELAY}; 2 | use bevy::prelude::*; 3 | 4 | #[derive(States, Debug, Clone, PartialEq, Eq, Hash, Default, Reflect)] 5 | pub enum MovementType { 6 | Running, 7 | #[default] 8 | Walking, 9 | } 10 | 11 | #[derive(States, Debug, Clone, PartialEq, Eq, Hash, Default, Reflect)] 12 | pub enum Being { 13 | Dead, 14 | #[default] 15 | Alive, 16 | } 17 | 18 | #[derive(Reflect, InspectorOptions, Default, States, Debug, Clone, Copy, PartialEq, Eq, Hash)] 19 | #[reflect(InspectorOptions)] 20 | pub enum PlayerAnimation { 21 | #[default] 22 | Idle, 23 | Walking, 24 | Running, 25 | Rising, 26 | Falling, 27 | } 28 | 29 | impl PlayerAnimation { 30 | pub fn animation(self) -> Animation { 31 | match self { 32 | Self::Idle => Animation::default(Frame::range(0, 9)), 33 | Self::Walking => Animation::default(Frame::range(10, 17)), 34 | Self::Running => Animation::default(Frame::range(20, 27)), 35 | Self::Rising => { 36 | Animation::new(DEFAULT_CYCLE_DELAY, Frame::range(30, 31), TimerMode::Once) 37 | } 38 | Self::Falling => { 39 | Animation::new(DEFAULT_CYCLE_DELAY, Frame::range(32, 32), TimerMode::Once) 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Malformed 2 | 3 | ![malformed banner](https://github.com/theunrealtarik/malformed/assets/58333332/2f277cf7-32a9-4263-b81b-e0302dc5fd8d) 4 | 5 | > [!WARNING] 6 | > This game is a piece of software that will entirely crash your computer whenever you lose which can lead to hardware-level damage and loss of any progress of any ongoing work. 7 | 8 | > [!WARNING] 9 | > I'm not responsible for any mis use of the provided code in this repository. 10 | 11 | ## Download 12 | If you just want to try what the game is all about (nothing new really) please download the **regular** version as it doesn't crash your whole system, instead your player will respawn and restart the level, unlike the **BSoD** version. 13 | > **BSoD**: *"blue screen of death"* 14 | 15 | 16 | ## Controls 17 | - `Space` to jump, the longer you hold the longer your jump gets. 18 | - `R` to restart the level after death. 19 | 20 | ## Development 21 | For starters read [bevy](https://bevyengine.org/learn/quick-start/getting-started/setup/)'s getting started guide and make sure you have [Rust](https://rustup.rs/) installed on your system then install [cargo-make](https://github.com/sagiegurari/cargo-make). (idk why am explaining this LOL) 22 | ```bash 23 | // debug mode with dynamic linking 24 | cargo make build-debug 25 | cargo make run 26 | 27 | // release mode with static linking 28 | cargo make --profile production build-release 29 | ``` 30 | Regarding contributions, yes (please). -------------------------------------------------------------------------------- /src/plugins/game/rpc.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | use discord_rich_presence::{ 3 | activity::{self, Assets, Button}, 4 | DiscordIpc, DiscordIpcClient, 5 | }; 6 | use glib::{ DISCORD_LARGE_IMAGE, DISCORD_STATE}; 7 | 8 | #[derive(Resource)] 9 | pub struct DiscordRPC { 10 | client: DiscordIpcClient, 11 | } 12 | 13 | impl Default for DiscordRPC { 14 | fn default() -> Self { 15 | Self { 16 | client: DiscordIpcClient::new(env!("DISCORD_APP_ID")).unwrap(), 17 | } 18 | } 19 | } 20 | 21 | pub struct RPCPlugin; 22 | 23 | impl Plugin for RPCPlugin { 24 | fn build(&self, app: &mut App) { 25 | app.init_resource::() 26 | .add_systems(PreStartup, Self::setup); 27 | } 28 | } 29 | 30 | impl RPCPlugin { 31 | fn setup(mut rpc: ResMut) { 32 | if rpc.client.connect().is_ok() { 33 | let payload = activity::Activity::new() 34 | .details("Komboter is not dying, not today.") 35 | .assets( 36 | Assets::new() 37 | .large_text(DISCORD_STATE) 38 | .large_image(DISCORD_LARGE_IMAGE), 39 | ) 40 | .buttons(vec![ 41 | Button::new("Play", env!("CARGO_PKG_HOMEPAGE")), 42 | Button::new("BSoD", "https://www.youtube.com/watch?v=njFw1NOAu3s"), 43 | ]); 44 | 45 | rpc.client.set_activity(payload).unwrap(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/plugins/game/ground.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | 3 | use crate::GameState; 4 | use bevy::prelude::*; 5 | use bevy_rapier2d::prelude::*; 6 | 7 | #[derive(Component, Reflect, Default)] 8 | pub struct Ground; 9 | 10 | #[derive(Component, Reflect, PartialEq, Eq)] 11 | pub struct Grounded { 12 | pub value: bool, 13 | } 14 | 15 | impl Grounded { 16 | pub fn new(value: bool) -> Self { 17 | Self { value } 18 | } 19 | } 20 | 21 | #[derive(Default)] 22 | pub struct GameGroundCheckPlugin { 23 | marker: PhantomData, 24 | } 25 | 26 | impl Plugin for GameGroundCheckPlugin 27 | where 28 | G: Component, 29 | { 30 | fn build(&self, app: &mut App) { 31 | app.add_systems( 32 | Update, 33 | Self::check_ground.run_if(in_state(GameState::Resumed)), 34 | ) 35 | .register_type::(); 36 | } 37 | } 38 | 39 | impl GameGroundCheckPlugin 40 | where 41 | G: Component, 42 | { 43 | fn check_ground( 44 | mut checkers: Query<(Entity, &mut Grounded)>, 45 | grounds: Query>, 46 | ctx: Res, 47 | ) { 48 | for (checker, mut state) in checkers.iter_mut() { 49 | for ground in grounds.iter() { 50 | let result = ctx.intersection_pair(ground, checker); 51 | if result == Some(true) { 52 | *state = Grounded::new(true); 53 | return; 54 | } else { 55 | *state = Grounded::new(false); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/plugins/game/menu.rs: -------------------------------------------------------------------------------- 1 | use bevy::prelude::*; 2 | 3 | use crate::{GameAssetsState, GameState, TextureAssets}; 4 | 5 | #[derive(Component)] 6 | struct Menu; 7 | 8 | pub struct GameMenuPlugin; 9 | impl Plugin for GameMenuPlugin { 10 | fn build(&self, app: &mut App) { 11 | app.init_state::() 12 | .add_systems( 13 | Update, 14 | Self::wait 15 | .run_if(in_state(GameState::Paused)) 16 | .run_if(in_state(GameAssetsState::Loaded)), 17 | ) 18 | .add_systems(Update, Self::start.run_if(in_state(GameState::Paused))); 19 | } 20 | } 21 | 22 | impl GameMenuPlugin { 23 | fn wait( 24 | mut commands: Commands, 25 | textures: Res, 26 | query: Query>, 27 | ) { 28 | if query.is_empty() { 29 | commands 30 | .spawn(SpriteBundle { 31 | texture: textures.pts.clone(), 32 | transform: Transform::from_xyz(0.0, 512.0, 0.0), 33 | ..Default::default() 34 | }) 35 | .insert(Menu); 36 | } 37 | } 38 | 39 | fn start( 40 | mut query: Query<&mut Visibility, With>, 41 | mut game_state: ResMut>, 42 | input: Res>, 43 | ) { 44 | if query.is_empty() { 45 | return; 46 | } 47 | 48 | for mut visibility in query.iter_mut() { 49 | if input.just_pressed(KeyCode::Space) { 50 | *visibility = Visibility::Hidden; 51 | game_state.set(GameState::Resumed); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/plugins/game/dialog.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use crate::plugins::debug::*; 4 | use crate::{GameAssetsState, GameState}; 5 | use bevy::prelude::*; 6 | 7 | #[derive(Component, Default, Reflect, Clone, Debug, InspectorOptions)] 8 | pub struct Dialog { 9 | pub index: usize, 10 | pub lines: Vec, 11 | } 12 | 13 | impl Dialog { 14 | pub fn new(lines: Vec) -> Self { 15 | Self { index: 0, lines } 16 | } 17 | } 18 | 19 | #[derive(Default, Reflect, Clone, Debug)] 20 | pub struct Line { 21 | content: String, 22 | timer: Timer, 23 | } 24 | 25 | impl Line { 26 | pub fn new(content: &'static str, duration: Duration) -> Self { 27 | Self { 28 | content: String::from(content), 29 | timer: Timer::new(duration, TimerMode::Once), 30 | } 31 | } 32 | } 33 | 34 | pub struct DialogPlugin; 35 | 36 | impl Plugin for DialogPlugin { 37 | fn build(&self, app: &mut App) { 38 | app.add_systems( 39 | Update, 40 | Self::play_dialogs 41 | .run_if(in_state(GameAssetsState::Loaded)) 42 | .run_if(in_state(GameState::Resumed)), 43 | ) 44 | .register_type::() 45 | .register_type::(); 46 | } 47 | } 48 | 49 | impl DialogPlugin { 50 | fn play_dialogs( 51 | mut commands: Commands, 52 | mut query: Query<(Entity, &mut Dialog, &mut Text)>, 53 | time: Res