diff options
-rw-r--r-- | assets/shaders/enemy_material.wgsl | 15 | ||||
-rw-r--r-- | design.md | 47 | ||||
-rw-r--r-- | plan.md | 39 | ||||
-rw-r--r-- | src/main.rs | 46 |
4 files changed, 135 insertions, 12 deletions
diff --git a/assets/shaders/enemy_material.wgsl b/assets/shaders/enemy_material.wgsl new file mode 100644 index 0000000..4b20d19 --- /dev/null +++ b/assets/shaders/enemy_material.wgsl @@ -0,0 +1,15 @@ +struct EnemyMaterial { + color: vec4<f32>, +}; + +@group(1) @binding(0) +var<uniform> material: EnemyMaterial; + +struct FragmentInput { + #import bevy_pbr::mesh_vertex_output +} + +@fragment +fn fragment(in: FragmentInput) -> @location(0) vec4<f32> { + return material.color * vec4<f32>(in.world_normal, 1.0); +} @@ -1,12 +1,47 @@ -terrorhedron -+ conway polyhedral notation -+ editable voxel map -+ deterministic multiplayer +# terrorhedron, but +- conway polyhedral notation leading to different enemy/turret design and balance +- editable voxel map +- deterministic multiplayer -enemies are shapes: -[ ] generate a table with all shapes generated from T (tetrahedron) +## enemies are shapes: +- [x] generate a table with all shapes generated from T (tetrahedron) with at most 5 operators between s (snub), k (kis), a (ambo), d (dual) in canonical form. provide the vertex number, time needed to see if it's viable to generate them on the fly. + +-> it's not viable to generate on the fly any shape using the topological operators. +they act only on the topology, which leaves some degrees of freedom. + +- [x] evaluate pregenerated options + - use the 5 platonic, 13 archimedean and their dual the 13 catalans -> 31 shapes. + - precalc all variations of "skad" up to depth n=3: 84, n=4: 340, n=5: 1364. + +-> i'll stick to the 31 for now + +## reference of the 31=(13+13+5) shapes. +T, kT, dkT, +aT, kaT, dkaT, aaT, daaT, kdaaT, dkdaaT, aaaT, daaaT, daT, kdaT, dkdaT, saT, dsaT +sT, ksT, dksT, asT, dasT, kdasT, dkdasT, aasT, daasT, dsT, kdsT, dkdsT, ssT, dssT + +### properties of all available shapes up to depth n +contain duplicates, dddT = ddT = dT = T or saT = sdaT +contain canonicalization artifacts + +- [ ] shape shader + - used to indicate both the topology and a variant + - used only to indicate the topology + +shader variants: striped, dotted, translucient, negative, burning, wireframe + +## enemies +### operator effects + +they stack multiplicativly. + +- T: no effect +- k: +20% speed +- a: +3 life, 2x damage +- d: -2 life, duplicates on death (only when losing the d) +- s: multiplies life by 3, speed -20% @@ -0,0 +1,39 @@ +# plan +list of tasks to get to the prototype. + +## camera +the camera should be first person flying and transition to orbital on click seamlessly. +it must support being focused on a point (turret, attach, enemy). + +## level geometry +voxels +- occlusions (normal blocks + decorative) +- attachment points +- path(s) +decorative blocks and lights. + +## level editor +ui for action/block selection. +actions: +- edit level geometry +- edit path +- edit attachments +- edit lights +- edit waves + +## enemy shader +default +hit effect + +## path line shader + +## multiplayer + +## turrets +### placement +### upgrade +### shooting + +## wave spawning + +## waves balance diff --git a/src/main.rs b/src/main.rs index 24b706f..9e43468 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,11 @@ use std::collections::HashMap; use itertools::Itertools; -use bevy::prelude::*; +use bevy::{ + prelude::*, + reflect::TypeUuid, + render::render_resource::{AsBindGroup, ShaderRef}, +}; use polyhedron_ops as p_ops; use smooth_bevy_cameras::{ controllers::orbit::{OrbitCameraBundle, OrbitCameraController, OrbitCameraPlugin}, @@ -17,6 +21,7 @@ fn main() { .add_plugin(OrbitCameraPlugin::default()) .add_startup_system(setup) .add_system(bevy::window::close_on_esc) + .add_plugin(MaterialPlugin::<EnemyMaterial>::default()) .run(); } @@ -30,7 +35,6 @@ impl ShapeMap { let mut sm = ShapeMap { shapes: HashMap::new(), }; - for var in (1..=depth as usize).flat_map(|n| { std::iter::repeat(ops.chars()) .take(n) @@ -50,18 +54,22 @@ impl ShapeMap { fn setup( mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, - mut materials: ResMut<Assets<StandardMaterial>>, + mut base_materials: ResMut<Assets<StandardMaterial>>, + mut enemy_materials: ResMut<Assets<EnemyMaterial>>, ) { let depth = 1; - let sm = ShapeMap::new("T", "asdk", depth); + let sm = ShapeMap::new("T", "skad", depth); let mut x = 0; let mut y = 0; for (_, s) in sm.shapes.iter() { let pos = Vec3::new(0.0, x as f32 * 2.0, y as f32 * 2.0); - commands.spawn(PbrBundle { + commands.spawn(MaterialMeshBundle { mesh: meshes.add(Mesh::from(s.clone())), - material: materials.add(Color::rgb(0.4, 0.35, 0.3).into()), + material: enemy_materials.add(EnemyMaterial { + color: Color::rgba(1.0, 1.0, 1.0, 1.0), + alpha_mode: AlphaMode::Opaque, + }), transform: Transform::from_translation(pos), ..default() }); @@ -72,6 +80,14 @@ fn setup( } } + // reference cube + commands.spawn(MaterialMeshBundle { + mesh: meshes.add(Mesh::from(shape::Cube::default())), + material: base_materials.add(Color::BLUE.into()), + transform: Transform::from_translation(Vec3::new(-2.0, 0.0, 0.0)), + ..default() + }); + commands // light .spawn(DirectionalLightBundle { @@ -93,3 +109,21 @@ fn setup( Vec3::new(0., -1., 0.), )); } + +impl Material for EnemyMaterial { + fn fragment_shader() -> ShaderRef { + "shaders/enemy_material.wgsl".into() + } + + fn alpha_mode(&self) -> AlphaMode { + self.alpha_mode + } +} + +#[derive(AsBindGroup, TypeUuid, Debug, Clone)] +#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] +pub struct EnemyMaterial { + #[uniform(0)] + color: Color, + alpha_mode: AlphaMode, +} |