Compare commits
No commits in common. "b70396ab720422b6f9f7ab5be2e63ebd4bf3d7c2" and "eabc979fe9d186fde6b891c030f89ba79e30b12b" have entirely different histories.
b70396ab72
...
eabc979fe9
11 changed files with 159 additions and 254 deletions
41
Cargo.lock
generated
41
Cargo.lock
generated
|
@ -923,6 +923,26 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevyjam"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bevy-inspector-egui",
|
||||
"bevy_common_assets",
|
||||
"bevy_mod_picking",
|
||||
"bevy_rapier2d",
|
||||
"cpal 0.14.0",
|
||||
"crossbeam-channel",
|
||||
"hexodsp",
|
||||
"rand",
|
||||
"rand_distr",
|
||||
"rapier2d",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"ticktock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.59.2"
|
||||
|
@ -1313,7 +1333,6 @@ dependencies = [
|
|||
"parking_lot 0.12.1",
|
||||
"stdweb",
|
||||
"thiserror",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
"windows",
|
||||
]
|
||||
|
@ -2227,26 +2246,6 @@ dependencies = [
|
|||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lux-synthese"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy",
|
||||
"bevy-inspector-egui",
|
||||
"bevy_common_assets",
|
||||
"bevy_mod_picking",
|
||||
"bevy_rapier2d",
|
||||
"cpal 0.14.0",
|
||||
"crossbeam-channel",
|
||||
"hexodsp",
|
||||
"rand",
|
||||
"rand_distr",
|
||||
"rapier2d",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"ticktock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
version = "0.3.2"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "lux-synthese"
|
||||
name = "bevyjam"
|
||||
version = "0.1.0"
|
||||
authors = ["tuxmain <tuxmain@zettascript.org>"]
|
||||
license = "AGPL-3.0-only"
|
||||
|
@ -24,7 +24,6 @@ serde_json = "1.0.85"
|
|||
ticktock = "0.8.0"
|
||||
|
||||
[target."cfg(target_arch = \"wasm32\")".dependencies]
|
||||
cpal = { version = "0.14.0", features = ["wasm-bindgen"] }
|
||||
|
||||
[profile.dev.package."*"]
|
||||
opt-level = 3
|
||||
|
|
11
README.md
11
README.md
|
@ -1,4 +1,4 @@
|
|||
# Lux synthesĕ
|
||||
# Bevyjam
|
||||
|
||||
## Controls
|
||||
|
||||
|
@ -9,14 +9,17 @@
|
|||
|
||||
## TODO
|
||||
|
||||
* name
|
||||
* more filters
|
||||
* despawn black characters
|
||||
* despawn character when too far
|
||||
* more levels
|
||||
* (?) multiplayer
|
||||
* more audio
|
||||
* "jumpable" component to avoid jumping on sensors
|
||||
* bug: in level2, move the blue character to win, then reset. The characters are lighter than expected. (also level 4)
|
||||
* redshift warning
|
||||
* itchio test
|
||||
|
||||
## Build
|
||||
|
||||
|
@ -63,6 +66,6 @@ Edit the level `N: u32` with the command `bevyjam <N> e`.
|
|||
|
||||
GNU AGPL v3, CopyLeft 2022 Pascal Engélibert, Nixon Cheng
|
||||
|
||||
_Lux synthesĕ_ is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
|
||||
_Lux synthesĕ_ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License along with _Lux synthesĕ_. If not, see https://www.gnu.org/licenses/.
|
||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
||||
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
sh build-wasm.sh || exit 1
|
||||
|
||||
mkdir -p target/itchio/wasm/target
|
||||
mkdir -p target/itchio/wasm/assets
|
||||
|
||||
cp assets/* target/itchio/wasm/assets/
|
||||
cp index.html target/itchio/wasm/
|
||||
cp target/lux-synthese.js target/itchio/wasm/target/
|
||||
cp target/lux-synthese_bg.wasm target/itchio/wasm/target/
|
||||
|
||||
cd target/itchio/wasm
|
||||
zip -r ../wasm.zip .
|
|
@ -1,3 +1,3 @@
|
|||
cargo build --release --target wasm32-unknown-unknown || exit 1
|
||||
echo "==> wasm-bindgen..."
|
||||
wasm-bindgen --out-name lux-synthese --out-dir target --target web target/wasm32-unknown-unknown/release/lux-synthese.wasm || exit 1
|
||||
wasm-bindgen --out-name bevyjam --out-dir target --target web target/wasm32-unknown-unknown/release/bevyjam.wasm || exit 1
|
||||
|
|
BIN
cover.png
BIN
cover.png
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
BIN
cover.xcf
BIN
cover.xcf
Binary file not shown.
25
index.html
25
index.html
|
@ -2,35 +2,12 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Lux synthesĕ</title>
|
||||
<title>Bevyjam</title>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
import init from './target/bevyjam.js'
|
||||
init()
|
||||
</script>
|
||||
<div>
|
||||
<h1>Lux synthesĕ</h1>
|
||||
<p>
|
||||
<strong>Note</strong>: audio does not work in the WASM build.
|
||||
</p>
|
||||
<h2>Controls</h2>
|
||||
<ul>
|
||||
<li><strong>Move</strong>: Arrows</li>
|
||||
<li><strong>Switch</strong>: Tab</li>
|
||||
<li><strong>Level up</strong>: Enter</li>
|
||||
<li><strong>Reset</strong>: R</li>
|
||||
</ul>
|
||||
<h2>Source</h2>
|
||||
<p>
|
||||
The source code of this free software is available in our <a href="https://git.txmn.tk/tuxmain/bevyjam/">Git repository</a>.
|
||||
</p>
|
||||
<p>
|
||||
GNU AGPL v3: CopyLeft 2022 Pascal Engélibert, Nixon Cheng<br/>
|
||||
<em>Lux synthesĕ</em> is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License.<br/>
|
||||
<em>Lux synthesĕ</em> is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.<br/>
|
||||
You should have received a copy of the GNU Affero General Public License along with <em>Lux synthesĕ</em>. If not, see <a href="https://www.gnu.org/licenses/">https://www.gnu.org/licenses/</a>.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
170
src/game.rs
170
src/game.rs
|
@ -57,13 +57,7 @@ impl Plugin for GamePlugin {
|
|||
.with_system(character_particle_effect_system)
|
||||
.with_system(move_win_text_system),
|
||||
)
|
||||
.add_system_to_stage(CoreStage::PostUpdate, char_char_collision_event_system)
|
||||
.add_system_to_stage(CoreStage::PostUpdate, char_platform_collision_event_system)
|
||||
// collision event system might remove items, therefore, we should detect platforms first before removing them
|
||||
.add_system_to_stage(
|
||||
CoreStage::PostUpdate,
|
||||
collision_event_system.after(char_platform_collision_event_system),
|
||||
);
|
||||
.add_system_to_stage(CoreStage::PostUpdate, collision_event_system);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,28 +102,7 @@ pub struct CharacterColor(pub Color);
|
|||
pub struct Player;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Platform;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct PlatformCount(usize);
|
||||
|
||||
impl PlatformCount {
|
||||
fn increment(&mut self) {
|
||||
self.0 += 1;
|
||||
}
|
||||
|
||||
fn decrement(&mut self) {
|
||||
self.0 = self.0.saturating_sub(1);
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.0 = 0;
|
||||
}
|
||||
|
||||
fn is_landed(&self) -> bool {
|
||||
self.0 != 0
|
||||
}
|
||||
}
|
||||
pub struct CollisionCount(usize);
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Melty(pub Color);
|
||||
|
@ -217,7 +190,7 @@ pub fn spawn_character(
|
|||
.insert(Sensor)
|
||||
.insert(Collider::cuboid(30., 0.5))
|
||||
.insert(ActiveEvents::COLLISION_EVENTS)
|
||||
.insert(PlatformCount(0));
|
||||
.insert(CollisionCount(0));
|
||||
});
|
||||
|
||||
character_list.0.insert(entity_commands.id());
|
||||
|
@ -258,8 +231,7 @@ pub fn spawn_platform(
|
|||
..default()
|
||||
})
|
||||
.insert(Collider::cuboid(size.x / 2., size.y / 2.))
|
||||
.insert(Level)
|
||||
.insert(Platform);
|
||||
.insert(Level);
|
||||
}
|
||||
|
||||
pub fn spawn_melty_platform(
|
||||
|
@ -286,7 +258,6 @@ pub fn spawn_melty_platform(
|
|||
.insert(Collider::cuboid(48., 8.))
|
||||
.insert(Melty(color))
|
||||
.insert(Level)
|
||||
.insert(Platform)
|
||||
.with_children(|c| {
|
||||
c.spawn_bundle(SpriteBundle {
|
||||
texture: asset_server.get_handle("melty.png"),
|
||||
|
@ -296,27 +267,31 @@ pub fn spawn_melty_platform(
|
|||
});
|
||||
}
|
||||
|
||||
fn char_char_collision_event_system(
|
||||
fn collision_event_system(
|
||||
mut commands: Commands,
|
||||
|
||||
character_meshes: Res<CharacterMeshes>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
character_query: Query<(
|
||||
&CharacterColor,
|
||||
mut character_query: Query<(
|
||||
&mut CharacterColor,
|
||||
&Transform,
|
||||
&mut Handle<ColorMaterial>,
|
||||
Option<&Player>,
|
||||
)>,
|
||||
|
||||
mut character_list: ResMut<CharacterList>,
|
||||
pass_through_filter_query: Query<&PassThroughFilter>,
|
||||
melty_query: Query<&Melty>,
|
||||
mut collision_counter_query: Query<&mut CollisionCount>,
|
||||
mut app_state: ResMut<State<AppState>>,
|
||||
character_meshes: Res<CharacterMeshes>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut character_list: ResMut<CharacterList>,
|
||||
) {
|
||||
for collision_event in collision_events.iter() {
|
||||
if let CollisionEvent::Started(e1, e2, _flags) = collision_event {
|
||||
match collision_event {
|
||||
CollisionEvent::Started(e1, e2, flags) => {
|
||||
if flags.is_empty() {
|
||||
if let (
|
||||
Ok((c1_color, c1_transform, c1_player)),
|
||||
Ok((c2_color, c2_transform, c2_player)),
|
||||
Ok((c1_color, c1_transform, _c1_material, c1_player)),
|
||||
Ok((c2_color, c2_transform, _c2_material, c2_player)),
|
||||
) = (character_query.get(*e1), character_query.get(*e2))
|
||||
{
|
||||
character_list.0.remove(e1);
|
||||
|
@ -324,11 +299,12 @@ fn char_char_collision_event_system(
|
|||
commands.entity(*e1).despawn_recursive();
|
||||
commands.entity(*e2).despawn_recursive();
|
||||
|
||||
let new_color =
|
||||
(Vec4::from(c1_color.0) + Vec4::from(c2_color.0)).clamp(Vec4::ZERO, Vec4::ONE);
|
||||
let new_color = (Vec4::from(c1_color.0) + Vec4::from(c2_color.0))
|
||||
.clamp(Vec4::ZERO, Vec4::ONE);
|
||||
|
||||
// If color approximately white
|
||||
if app_state.current() == &AppState::Game && new_color.min_element() >= 0.9 {
|
||||
if app_state.current() == &AppState::Game && new_color.min_element() >= 0.9
|
||||
{
|
||||
app_state.replace(AppState::Win).ok();
|
||||
}
|
||||
|
||||
|
@ -345,7 +321,7 @@ fn char_char_collision_event_system(
|
|||
*c2_transform
|
||||
} else {
|
||||
Transform::identity().with_translation(
|
||||
(c1_transform.translation + c2_transform.translation) * 0.5,
|
||||
(c1_transform.translation + c2_transform.translation) / 2.,
|
||||
)
|
||||
},
|
||||
new_color.into(),
|
||||
|
@ -353,68 +329,7 @@ fn char_char_collision_event_system(
|
|||
);
|
||||
|
||||
audio.send(AudioMsg::Fusion).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn char_platform_collision_event_system(
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
mut platform_count_query: Query<&mut PlatformCount>,
|
||||
platform_query: Query<&Platform>,
|
||||
) {
|
||||
// detect platform + player collisions only
|
||||
for collision_event in collision_events.iter() {
|
||||
match collision_event {
|
||||
CollisionEvent::Started(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut platform_count), Ok(_)) =
|
||||
(platform_count_query.get_mut(*e1), platform_query.get(*e2))
|
||||
{
|
||||
platform_count.increment();
|
||||
} else if let (Ok(mut platform_count), Ok(_)) =
|
||||
(platform_count_query.get_mut(*e2), platform_query.get(*e1))
|
||||
{
|
||||
platform_count.increment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CollisionEvent::Stopped(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut platform_count), Ok(_)) =
|
||||
(platform_count_query.get_mut(*e1), platform_query.get(*e2))
|
||||
{
|
||||
platform_count.decrement();
|
||||
} else if let (Ok(mut platform_count), Ok(_)) =
|
||||
(platform_count_query.get_mut(*e2), platform_query.get(*e1))
|
||||
{
|
||||
platform_count.decrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collision_event_system(
|
||||
mut commands: Commands,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
mut character_query: Query<(
|
||||
&mut CharacterColor,
|
||||
&Transform,
|
||||
&mut Handle<ColorMaterial>,
|
||||
Option<&Player>,
|
||||
)>,
|
||||
pass_through_filter_query: Query<&PassThroughFilter>,
|
||||
melty_query: Query<&Melty>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
for collision_event in collision_events.iter() {
|
||||
if let CollisionEvent::Started(e1, e2, flags) = collision_event {
|
||||
if flags.is_empty() {
|
||||
if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) =
|
||||
} else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) =
|
||||
(character_query.get_mut(*e1), melty_query.get(*e2))
|
||||
{
|
||||
if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. {
|
||||
|
@ -465,6 +380,32 @@ fn collision_event_system(
|
|||
.ok();
|
||||
audio.send(AudioMsg::Switch).ok();
|
||||
}
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e1),
|
||||
character_query.get_mut(*e2),
|
||||
) {
|
||||
collision_count.0 += 1;
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e2),
|
||||
character_query.get_mut(*e1),
|
||||
) {
|
||||
collision_count.0 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
CollisionEvent::Stopped(e1, e2, flags) => {
|
||||
if *flags == CollisionEventFlags::SENSOR {
|
||||
if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e1),
|
||||
character_query.get_mut(*e2),
|
||||
) {
|
||||
collision_count.0 = collision_count.0.saturating_sub(1);
|
||||
} else if let (Ok(mut collision_count), Err(_)) = (
|
||||
collision_counter_query.get_mut(*e2),
|
||||
character_query.get_mut(*e1),
|
||||
) {
|
||||
collision_count.0 = collision_count.0.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +450,7 @@ fn change_character_system(
|
|||
fn player_movement_system(
|
||||
keyboard_input: Res<Input<KeyCode>>,
|
||||
mut characters: Query<(&mut Velocity, &Children), With<Player>>,
|
||||
mut platform_count_query: Query<&mut PlatformCount>,
|
||||
collision_counter_query: Query<&CollisionCount>,
|
||||
audio: Res<crossbeam_channel::Sender<AudioMsg>>,
|
||||
) {
|
||||
let right_pressed: bool =
|
||||
|
@ -520,12 +461,11 @@ fn player_movement_system(
|
|||
for (mut velocity, children) in characters.iter_mut() {
|
||||
velocity.linvel.x = 200. * (right_pressed as i8 - left_pressed as i8) as f32;
|
||||
|
||||
let mut platform_count: Mut<PlatformCount> =
|
||||
platform_count_query.get_mut(children[0]).unwrap();
|
||||
if keyboard_input.just_pressed(KeyCode::Space) && platform_count.is_landed() {
|
||||
if keyboard_input.just_pressed(KeyCode::Space)
|
||||
&& collision_counter_query.get(children[0]).unwrap().0 != 0
|
||||
{
|
||||
audio.send(AudioMsg::Jump).ok();
|
||||
velocity.linvel.y = 700.;
|
||||
platform_count.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
commands
|
||||
.spawn_bundle(Text2dBundle {
|
||||
text: Text::from_section(
|
||||
"Lux synthesĕ",
|
||||
"BEVYJAM",
|
||||
TextStyle {
|
||||
font: font.clone(),
|
||||
font_size: 96.0,
|
||||
|
|
|
@ -143,6 +143,5 @@ fn particle_effect_system(
|
|||
/ particle_effect.radius_squared,
|
||||
);
|
||||
}
|
||||
transform.translation.z = 0.005;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue