AUJ2XCCYHCUBG3IZCLD4WGBINY56S4QWGJDLUQJVUGMJOESXYGIQC
QMQSIKACOMY55Y3FCVCPCBIM5KODNE6GAKRRGORSMNZQT2ONPDDQC
OFSXWOK6YNCYCKXRPOLAQQOYANOMDOL3ZDUXMDM65UTKVOA4LAXAC
57S64Z47SHSHO23K7VPUFBJETNVYBPK47BSIHJCW572KIUVF52HQC
6YIJ6ZQ6EOSZCK4K422ZUDXSMXKBEAWNA2MKCDS6B7NR2BGB3M2AC
ZTXU3KDWJAP47BPTRDJGQSR3C2YNKJE5NKFBYZKXR7N6LWGJWC7QC
D5PGHFSZDX3WUCLIJXRKCYH4MXULSP7JILSBY5QZ4WG6HX5YZHPQC
use std::time::{Duration, Instant};
use bevy::prelude::*;
use bevy_xpbd_2d::components::{AngularVelocity, LinearVelocity};
pub struct UndertakerPlugin;
impl Plugin for UndertakerPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<UndertakerConfig>()
.add_event::<Undertaken>()
.add_systems(Update, (undertaker_debug_line, update_mortals));
}
}
/// Event that occurs when something is undertaken
#[derive(Event)]
pub struct Undertaken {
position: Vec3,
}
#[derive(Resource)]
pub struct UndertakerConfig {
pub under_y: f32,
pub max_time_under: Duration,
}
impl Default for UndertakerConfig {
fn default() -> Self {
Self {
under_y: 0.0,
max_time_under: Duration::from_secs(1),
}
}
}
#[derive(Component, Default)]
pub struct Mortal {
// Z might have info, so allow it to be controlled
/// If [`None`], entity is destroyed. Otherwise
/// move the entity to a valid location close to the
/// given point, and zero any velocity.
pub respawn: Option<Vec3>,
instant_under: Option<Instant>,
}
impl Mortal {
pub fn respawnable(respawn: Vec3) -> Self {
Self {
respawn: Some(respawn),
..default()
}
}
}
#[allow(clippy::type_complexity)]
fn update_mortals(
mut query: Query<(
Entity,
&mut Mortal,
&mut Transform,
&GlobalTransform,
Option<&mut LinearVelocity>,
Option<&mut AngularVelocity>,
)>,
config: Res<UndertakerConfig>,
mut commands: Commands,
mut writer: EventWriter<Undertaken>,
) {
for (entity, mut mortality, mut transform, global_transform, lin_vel, ang_vel) in
query.iter_mut()
{
if global_transform.translation().y >= config.under_y {
mortality.instant_under = None;
} else {
let mortal_instant = mortality.instant_under.unwrap_or(Instant::now());
if mortal_instant.elapsed() > config.max_time_under {
if let Some(declared_respawn) = mortality.respawn {
let respawn_point = Vec3::new(
declared_respawn.x,
declared_respawn.y.max(config.under_y),
declared_respawn.z,
);
transform.translation = respawn_point;
if let Some(mut linear) = lin_vel {
linear.0 = Vec2::ZERO;
}
if let Some(mut angular) = ang_vel {
angular.0 = 0.;
}
writer.send(Undertaken {
position: global_transform.translation(),
});
mortality.instant_under = None;
} else {
commands.entity(entity).despawn_recursive();
}
} else {
mortality.instant_under = Some(mortal_instant);
}
}
}
}
fn undertaker_debug_line(mut gizmos: Gizmos, config: Res<UndertakerConfig>) {
gizmos.primitive_2d(
Plane2d::new(Vec2::Y),
Vec2::Y * config.under_y,
0.,
Color::ORANGE_RED,
);
}
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bulle".to_string(),
resolution: WindowResolution::new(LOGICAL_WIDTH as f32, LOGICAL_HEIGHT as f32),
DefaultPlugins
.set(WindowPlugin {
primary_window: Some(Window {
title: "Bulle".to_string(),
resolution: WindowResolution::new(
LOGICAL_WIDTH as f32,
LOGICAL_HEIGHT as f32,
),
..default()
}),
}
mod layered {
use bevy::prelude::*;
use bevy_xpbd_2d::{components::CollisionLayers, prelude::*};
pub struct LayeredPlugin;
#[derive(SystemSet, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LayeredPluginSet {
PreUpdate,
Update,
}
impl Plugin for LayeredPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
Update,
update_collision_layers.in_set(LayeredPluginSet::Update),
)
.configure_sets(
Update,
(LayeredPluginSet::PreUpdate, LayeredPluginSet::Update).chain(),
);
}
}
#[derive(PhysicsLayer, Clone, Copy)]
pub enum GameLayer {
Ground,
LayerA,
LayerB,
ProjectileA,
ProjectileB,
}
impl GameLayer {
/// Switch layers into the proper projectile layer
///
/// `Ground` is a special-case value meaning both A and B
pub fn into_projectile(self) -> Self {
match self {
Self::Ground => Self::Ground,
Self::LayerA | Self::ProjectileA => Self::ProjectileA,
Self::LayerB | Self::ProjectileB => Self::ProjectileB,
}
}
}
#[derive(Component, Clone, Copy, Debug)]
pub enum Layered {
Ground,
A,
B,
}
impl Layered {
/// Get the layer-swapped version of this [`Layered`]
pub fn swapped(self) -> Self {
match self {
Self::Ground => Self::Ground,
Self::A => Self::B,
Self::B => Self::A,
}
}
/// Get the corresponding [`GameLayer`]
pub fn layer(self) -> GameLayer {
match self {
Self::Ground => GameLayer::Ground,
Self::A => GameLayer::LayerA,
Self::B => GameLayer::LayerB,
}
}
}
fn layer_a_collision_layers() -> CollisionLayers {
CollisionLayers::new(
[GameLayer::LayerA],
[GameLayer::LayerA, GameLayer::ProjectileA, GameLayer::Ground],
)
}
// NOTE Projectiles (generally) do not interact with each other
fn layer_a_projectile_collision_layers(self_interact: bool) -> CollisionLayers {
CollisionLayers::new(
GameLayer::ProjectileA,
if !self_interact {
Into::<LayerMask>::into([GameLayer::Ground, GameLayer::LayerA])
} else {
[GameLayer::Ground, GameLayer::LayerA, GameLayer::ProjectileA].into()
},
)
}
fn layer_b_collision_layers() -> CollisionLayers {
CollisionLayers::new(
[GameLayer::LayerB],
[GameLayer::LayerB, GameLayer::ProjectileB, GameLayer::Ground],
)
}
fn layer_b_projectile_collision_layers(self_interact: bool) -> CollisionLayers {
CollisionLayers::new(
GameLayer::ProjectileB,
if !self_interact {
Into::<LayerMask>::into([GameLayer::Ground, GameLayer::LayerB])
} else {
[GameLayer::Ground, GameLayer::LayerB, GameLayer::ProjectileB].into()
},
)
}
fn ground_collision_layers() -> CollisionLayers {
CollisionLayers::new(GameLayer::Ground, LayerMask::ALL)
}
fn wide_projectile_collision_layers(self_interact: bool) -> CollisionLayers {
CollisionLayers::new(
[GameLayer::ProjectileA, GameLayer::ProjectileB],
if !self_interact {
Into::<LayerMask>::into([GameLayer::Ground, GameLayer::LayerA, GameLayer::LayerB])
} else {
[
GameLayer::Ground,
GameLayer::LayerA,
GameLayer::LayerB,
GameLayer::ProjectileA,
GameLayer::ProjectileB,
]
.into()
},
)
}
fn update_collision_layers(query: Query<(Entity, Ref<Layered>)>, mut commands: Commands) {
for (entity, layered) in query.iter() {
match &*layered {
Layered::A => {
commands
.entity(entity)
.try_insert(layer_a_collision_layers());
}
Layered::B => {
commands
.entity(entity)
.try_insert(layer_b_collision_layers());
}
Layered::Ground => {
commands
.entity(entity)
.try_insert(ground_collision_layers());
}
}
}
}
Collider::capsule(32.0, 32.0),
Restitution::new(1.0),
TnuaConfig {
max_speed: 5000.,
air_actions: 2,
walk: TnuaBuiltinWalk {
acceleration: 2000.,
air_acceleration: 1500.,
float_height: 64.0,
..default()
},
jump: TnuaBuiltinJump {
height: 128.,
reschedule_cooldown: Some(0.1),
// Defaults x 10
upslope_extra_gravity: 300.0,
// takeoff_extra_gravity: 300.0,
// takeoff_above_velocity: 64.0,
fall_extra_gravity: 200.0,
shorten_extra_gravity: 600.0,
peak_prevention_at_upward_velocity: 10.0,
peak_prevention_extra_gravity: 200.0,
..default()
},
},
TnuaControllerBundle::default(),
// TnuaXpbd2dSensorShape(Collider::circle(32.0)),
TnuaSimpleAirActionsCounter::default(),
Collider::capsule(64.0, 48.0),
layered::Layered::A,
undertaker::Mortal::respawnable(Vec3::new(320.0, 640.0, 0.0)),
struct AiContext {
desired_movement: Vec2,
commands.spawn((
camera::CameraTarget(1),
layered::Layered::B,
RigidBody::Dynamic,
Collider::capsule(32.0, 32.0),
undertaker::Mortal::default(),
MaterialMesh2dBundle {
mesh: Mesh2dHandle(meshes.add(Capsule2d::new(32.0, 32.0))),
material: materials.add(Color::hsl(5., 0.6, 0.75)),
transform: Transform::from_xyz(320.0, 960.0, 0.0),
..default()
},
));
struct Behaved {
runner: simple_bt::BehaviorRunner<AiContext>,
}
struct LayerTextureSwap(Handle<ColorMaterial>);
#[allow(clippy::type_complexity)]
fn action_state_swap_layers(
mut query: Query<(
Entity,
&ActionState<PlayerMovement>,
&GlobalTransform,
&mut layered::Layered,
Option<&mut LayerTextureSwap>,
Option<&mut Handle<ColorMaterial>>,
)>,
spatial_query: SpatialQuery,
) {
for (ent, action_state, gtransform, mut layer, mut maybe_lts, mut maybe_mat) in query.iter_mut()
{
if action_state.just_pressed(&PlayerMovement::Swap) {
// Attempt to swap layers
let blocker_collider = Collider::circle(32. * 2.);
let blockers = spatial_query.shape_intersections(
&blocker_collider,
gtransform.translation().truncate(),
0.,
SpatialQueryFilter::from_mask(layer.swapped().layer()),
);
fn input_behaved(mut query: Query<(&mut Behaved,), Without<Player>>) {
for (mut behaved,) in query.iter_mut() {
let mut context = AiContext {
desired_movement: Vec2::ZERO,
};
behaved.runner.proceed(&mut context);
let x_movement = context.desired_movement.x;
if x_movement > 0.001 {
// action_state.press(&PlayerMovement::Walk);
if blockers.is_empty() {
*layer = layer.swapped();
if let Some(mut lts) = maybe_lts {
let new_mat = lts.0.clone();
if let Some(mat) = maybe_mat.as_mut() {
lts.0 = mat.clone();
*mat.as_mut() = new_mat;
}
}
}
//! Lua scripts to attach behavior trees to things.
//!
//! We use piccolo cuz I wanna get an idea of how to use it
//! and be able to contribute to it.
#import "@preview/gentle-clues:0.7.1": *
#set par(justify: true)
#set document(
title: "IO: Game Design Document",
author: {"Jengamon"},
)
#show "IO": name => box[
#box(image("important.jpg", height: 0.7em)) #name
]
#align(center)[
= IO
== #smallcaps[Game Design Document]
_#smallcaps[by jengamon]_
]
#line(length: 100%)
In this report, we will explore the various factors
that influence _fluid dynamics_ in glaciers and how they
contribute to the formation and behavior of these natural structures.
The most important structure is shown in @skibi_miku.
+ The climate
- Temperature
+ Fahrenheit
+ Celsius
- Precipitation
+ The topography
+ The geology
#info[ This is an info!
#figure(
image("important.jpg", width: 70%),
caption: [
_Skibidi Miku_ is a paragon of virtue.
]
) <skibi_miku>
]
#tip(title: "Best title evah...")[Check this out\~]
If/when I need math, the equation $Q = rho A v + C$ looks pretty cool...
It can also look like: $ Q = rho A v + C $ or
$ Q = rho A v + "time offset" $
Some environmental science:
$ 7.32 beta + sum_(i=0)^nabla Q_i / 2 $
A cool vector: $ v := vec(x_1, x_2, x_3) in cal(S) $
Some variants: $ a arrow.squiggly b $
gdd:
typst watch notes/gdd.typ
bevy = { version = "0.13" }
bevy = { version = "0.13", default-features = false, features = [
"animation",
"bevy_asset",
"bevy_gilrs",
"bevy_scene",
"bevy_winit",
"bevy_core_pipeline",
"bevy_pbr",
"bevy_gltf",
"bevy_render",
"bevy_sprite",
"bevy_text",
"bevy_ui",
"multi-threaded",
"png",
"hdr",
"x11",
"bevy_gizmos",
"tonemapping_luts",
"default_font",
"webgl2",
"bevy_debug_stepping",
]}
bevy_kira_audio = { version = "0.19" }
]
[[package]]
name = "bevy_audio"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0f12495e230cd5cf59c6051cdd820c97d7fe4f0597d4d9c3240c62e9c65b485"
dependencies = [
"bevy_app",
"bevy_asset",
"bevy_derive",
"bevy_ecs",
"bevy_math",
"bevy_reflect",
"bevy_transform",
"bevy_utils",
"cpal",
"rodio",
name = "bevy_kira_audio"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf58fed4b6fd13df35e77002821cf459948131de4ac262c3b6a175d8fe28fd3"
dependencies = [
"anyhow",
"bevy",
"kira",
"parking_lot",
"ron",
"serde",
"thiserror",
"uuid",
]
[[package]]
]
[[package]]
name = "darling"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 2.0.59",
[[package]]
name = "derive_builder"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.59",
]
[[package]]
name = "derive_builder_macro"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
dependencies = [
"derive_builder_core",
"syn 2.0.59",
]
]
[[package]]
name = "gc-arena"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b2e43b3fc51b9900cc9ced1c4630dcbfae1859573102a84d2231ac744c1208"
dependencies = [
"allocator-api2",
"gc-arena-derive",
"hashbrown",
"sptr",
]
[[package]]
name = "gc-arena-derive"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96f3c487d429eaa928334f7f2ca7b14734f1c2f4020d2b08c1f0b4d9c70e4f17"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.59",
"synstructure",
name = "kira"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8968f1eda49cdf4f6406fd5ffe590c3ca2778a1b0e50b5684974b138a99dfb2f"
dependencies = [
"atomic-arena",
"cpal",
"glam",
"mint",
"ringbuf",
"send_wrapper",
"serde",
"symphonia",
]
[[package]]
]
[[package]]
name = "piccolo"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93dd1815b42446904bb2689d1c5d7680e8c68113d5b15a5a3297ba6c7a5f84af"
dependencies = [
"ahash",
"allocator-api2",
"anyhow",
"gc-arena",
"hashbrown",
"rand",
"thiserror",
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "symphonia"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9"
dependencies = [
"lazy_static",
"symphonia-bundle-flac",
"symphonia-codec-vorbis",
"symphonia-core",
"symphonia-format-ogg",
"symphonia-metadata",
]
[[package]]
name = "symphonia-bundle-flac"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97"
dependencies = [
"log",
"symphonia-core",
"symphonia-metadata",
"symphonia-utils-xiph",
]
[[package]]
name = "symphonia-codec-vorbis"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30"
dependencies = [
"log",
"symphonia-core",
"symphonia-utils-xiph",
]
[[package]]
name = "symphonia-core"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "798306779e3dc7d5231bd5691f5a813496dc79d3f56bf82e25789f2094e022c3"
dependencies = [
"arrayvec",
"bitflags 1.3.2",
"bytemuck",
"lazy_static",
"log",
]
[[package]]
name = "symphonia-format-ogg"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931"
dependencies = [
"log",
"symphonia-core",
"symphonia-metadata",
"symphonia-utils-xiph",
]
name = "symphonia-metadata"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc622b9841a10089c5b18e99eb904f4341615d5aa55bbf4eedde1be721a4023c"
dependencies = [
"encoding_rs",
"lazy_static",
"log",
"symphonia-core",
]
[[package]]
name = "symphonia-utils-xiph"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe"
dependencies = [
"symphonia-core",
"symphonia-metadata",
]
[[package]]