From 15b0b8efc391a10aaaf28febd1d08911a5f96d2c Mon Sep 17 00:00:00 2001 From: Leo Le Bouter Date: Sat, 10 Oct 2020 23:34:01 +0200 Subject: [PATCH] First working version Next we will be looking at implementing multi-controller multiplayer --- .gitignore | 5 + Cargo.toml | 19 ++++ src/main copy.rs_ | 135 +++++++++++++++++++++++ src/main.rs | 269 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs_ | 144 +++++++++++++++++++++++++ 5 files changed, 572 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/main copy.rs_ create mode 100644 src/main.rs create mode 100644 src/main.rs_ diff --git a/.gitignore b/.gitignore index 62bd1a4..29a7654 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,8 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk + + +#Added by cargo + +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..688b661 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "LJ-rust-filters" +version = "0.1.0" +authors = ["Leo Le Bouter "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde_json = "1.0.58" +gilrs = "0.7.4" +clap = "2.33.3" +anyhow = "1.0.33" +chrono = "0.4.19" +rand = "0.7.3" +ncollide2d = "0.25.0" +nphysics2d = "0.17.0" +nalgebra = "0.22.0" +nphysics_testbed2d = "0.10.0" diff --git a/src/main copy.rs_ b/src/main copy.rs_ new file mode 100644 index 0000000..3f768de --- /dev/null +++ b/src/main copy.rs_ @@ -0,0 +1,135 @@ +use anyhow::Result; +use gilrs::{Axis, Button, EventType}; +use io::Write; + +use std::{io, thread, time::Duration}; + +fn main() -> Result<()> { + use gilrs::{Button, Event, Gilrs}; + + let mut gilrs = Gilrs::new().unwrap(); + + // Iterate over all connected gamepads + for (_id, gamepad) in gilrs.gamepads() { + eprintln!("{} is {:?}", gamepad.name(), gamepad.power_info()); + } + + let mut alter_x: f32 = 0.; + let mut alter_y: f32 = 0.; + let mut old_alter_y: f32 = 0.; + let mut last_v: f32 = 0.; + let mut was_x = false; + let mut is_one = false; + let mut is_jump = false; + let mut velocity = 1.0; + + let mut active_gamepad = None; + + loop { + let mut line = String::new(); + io::stdin().read_line(&mut line)?; + + let frame: Vec<(f32, f32, u32)> = serde_json::from_str(&line)?; + + // Examine new events + if let Some(Event { id, event, time }) = gilrs.next_event() { + // eprintln!("{:?} New event from {}: {:?}", time, id, event); + + active_gamepad = Some(id); + + // match event { + // EventType::AxisChanged(axis, v, _code) => { + // if axis == Axis::LeftStickX { + // alter_x -= 1.; + // // was_x = true; + // } else if axis == Axis::LeftStickY { + // alter_y -= 1.; + // // was_x = false; + // } + // } + // _ => {} + // } + } + + // if is_one { + // if was_x { + // alter_x -= 1.0; + // } else { + // alter_y -= 1.0; + // } + // } + if let Some(active_gamepad) = active_gamepad { + let gp = gilrs.gamepad(active_gamepad); + + { + let velocity = 0.5; + + let (sx, sy) = (gp.value(Axis::LeftStickX), gp.value(Axis::LeftStickY)); + + if sx.abs() > 0.5 || sy.abs() > 0.5 { + if sx.abs() > 0.5 { + alter_x -= velocity * sx.signum(); + } + if !is_jump { + if sy.abs() > 0.5 { + alter_y -= velocity * sy.signum(); + } + } + } + } + + if gp.is_pressed(Button::South) && !is_jump { + is_jump = true; + old_alter_y = alter_y; + velocity = 1.0; + } + } + + if is_jump { + if velocity >= -1. { + alter_y -= velocity; + velocity -= 0.05; + } else { + is_jump = false; + alter_y = old_alter_y; + } + + eprintln!("Jump: alter_y: {:?}", alter_y); + } + + let altered_frame: Vec<(f32, f32, u32)> = frame + .iter() + .map(|(x, y, color)| { + let mut new_x = if *x + alter_x * 10. >= 800. { + 800. + } else { + *x + alter_x * 10. + }; + + let mut new_y = if *y + alter_y * 10. >= 800. { + 800. + } else { + *y + alter_y * 10. + }; + + if new_x < 0. { + new_x = 0.; + } + + if new_y < 0. { + new_y = 0.; + } + + (new_x, new_y, *color) + }) + .collect(); + + serde_json::to_writer(io::stdout(), &altered_frame)?; + io::stdout().write(b"\n")?; + io::stdout().flush()?; + + // serde_json::to_writer(io::stderr(), &altered_frame)?; + // io::stderr().write(b"\n")?; + // io::stderr().flush()?; + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..1a4db8c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,269 @@ +use anyhow::Result; +use chrono::offset::Utc; +use gilrs::{Axis, Button, Event, EventType, Gilrs}; +use rand::prelude::*; + +use std::{ + io::{self, Write}, + thread, time, + time::Duration, +}; + +type Segment = [[f32; 2]; 2]; + +#[derive(Default)] +struct Game { + platforms: Vec>, + player: Vec, + joystick_player_delta: [f32; 2], + jump_player_delta: f32, +} + +const COLORS: [u32; 12] = [ + 0xFF0000, 0xFF8000, 0xFFFF00, 0x80FF00, 0x00FF00, 0x00FF80, 0x00FFFF, 0x0080FF, 0x0000FF, + 0x7F00FF, 0xFF00FF, 0xFF007F, +]; + +fn main() -> Result<()> { + let mut gilrs = Gilrs::new().unwrap(); + let mut rng = rand::thread_rng(); + let mut frame_count: u64 = 0; + let mut last_press_frame_count = 0; + let mut is_jump = false; + let mut double_jump = false; + let mut velocity = 1.0; + let mut last_is_colide = false; + let mut x_pressed = 0; + let mut velocity_under_0 = 0; + let mut color = 0xFFFFFF; + let mut colors_iter = COLORS.iter().cycle(); + let mut destroyed_platforms_without_ground = 0; + + let mut game = Game { + player: vec![ + [[600.0, 600.0], [650.0, 600.0]], + [[650.0, 600.0], [650.0, 650.0]], + [[650.0, 650.0], [600.0, 650.0]], // bottom line + [[600.0, 650.0], [600.0, 600.0]], + ], + ..Game::default() + }; + + let mut active_gamepad = None; + + loop { + let mut is_collide = false; + + if let Some(Event { id, event, time }) = gilrs.next_event() { + active_gamepad = Some(id); + } + + if let Some(active_gamepad) = active_gamepad { + let gp = gilrs.gamepad(active_gamepad); + + { + let velocity = 0.5; + + let (sx, sy) = (gp.value(Axis::LeftStickX), gp.value(Axis::LeftStickY)); + + if sx.abs() > 0.5 || sy.abs() > 0.5 { + if sx.abs() > 0.5 { + let x = velocity * sx.signum(); + if game.joystick_player_delta[0] + x >= -50. + && game.joystick_player_delta[0] + x <= 20. + { + game.joystick_player_delta[0] += x; + } + } + // if sy.abs() > 0.5 { + // game.joystick_player_delta[1] -= velocity * sy.signum(); + // } + } + } + + for l in game.platforms.iter_mut() { + if (game.player[2][0][1] + + game.joystick_player_delta[1] * 10. + + game.jump_player_delta + >= l[0][0][1] - 18. + && game.player[2][0][1] + + game.joystick_player_delta[1] * 10. + + game.jump_player_delta + <= l[0][0][1] + 18.) + && (game.player[2][0][0] + game.joystick_player_delta[0] * 7. >= l[0][0][0] + && game.player[2][1][0] + game.joystick_player_delta[0] * 7. <= l[0][1][0]) + { + is_collide = true; + } + + if !is_collide && last_is_colide && !double_jump { + velocity = 0.; + } + + if is_collide && !last_is_colide { + double_jump = false; + if destroyed_platforms_without_ground % 5 == 0 + && destroyed_platforms_without_ground != 0 + { + color = *colors_iter.next().unwrap(); + destroyed_platforms_without_ground += 1; + } + } + } + + if last_press_frame_count + rng.gen_range(100, 4000) <= frame_count { + let height = rng.gen_range(300., 550.); + game.platforms + .push(vec![[[800., height], [rng.gen_range(810., 900.), height]]]); + last_press_frame_count = frame_count; + } + /*if gp.is_pressed(Button::West) && + } else*/ + if gp.is_pressed(Button::South) { + if game.jump_player_delta == 0. { + x_pressed += 1; + is_jump = true; + velocity = 1.0; + } + + if is_collide || (velocity > 0. && !double_jump) { + x_pressed += 1; + velocity = 1.0; + double_jump = true; + } + } + } + + if is_collide + && game.joystick_player_delta[0] >= -49. + && game.joystick_player_delta[0] <= 20. + { + game.joystick_player_delta[0] -= 1. / 7.; + } + + // if is_jump && !is_collide && !double_jump { + + // } else { + // is_jump = false; + // double_jump = false; + // game.jump_player_delta = 0.; + // } + + // //eprintln!("Jump: alter_y: {:?}", game.jump_player_delta); + // } + + if is_jump { + game.jump_player_delta -= velocity * 30.; + is_jump = false; + } + + if (game.player[2][0][1] + game.joystick_player_delta[1] * 10. + game.jump_player_delta) + < 650. + { + if !is_collide || velocity >= 0. { + if velocity >= 0. { + velocity_under_0 += 1; + } + game.jump_player_delta -= velocity * 30.; + velocity -= 0.05; + } + } else { + color = 0xFFFFFF; + destroyed_platforms_without_ground = 0; + colors_iter = COLORS.iter().cycle(); + game.jump_player_delta = 0.; + } + + let mut frame: Vec<(f32, f32, u32)> = vec![]; + + let mut to_remove = vec![]; + for (k, l) in game.platforms.iter_mut().enumerate() { + let mut must_remove = false; + + for (i, p) in l.iter_mut().enumerate() { + frame.push((p[0][0], p[0][1], 0)); + + frame.push((p[0][0], p[0][1], color)); + frame.push((p[1][0], p[1][1], color)); + + frame.push((p[1][0], p[1][1], 0)); + + if p[0][0] >= 50. { + p[0][0] -= 1.; + p[1][0] -= 1.; + } else { + must_remove = true; + } + } + + if must_remove { + to_remove.push(k); + } + } + for i in to_remove { + game.platforms.remove(i); + destroyed_platforms_without_ground += 1; + } + + for p in game.player.iter() { + let p = [ + ( + p[0][0] + game.joystick_player_delta[0] * 7., + p[0][1] + game.joystick_player_delta[1] * 10. + game.jump_player_delta, + ), + ( + p[1][0] + game.joystick_player_delta[0] * 7., + p[1][1] + game.joystick_player_delta[1] * 10. + game.jump_player_delta, + ), + ]; + + frame.push((p[0].0, p[0].1, 0)); + + frame.push((p[0].0, p[0].1, color)); + frame.push((p[1].0, p[1].1, color)); + + frame.push((p[1].0, p[1].1, 0)); + } + + let out = serde_json::to_string(&frame)?; + if !frame.is_empty() { + io::stdout().write_all(out.as_bytes())?; + io::stdout().write(b"\n")?; + io::stdout().flush()?; + } + + eprintln!("score: {:?}", destroyed_platforms_without_ground); + // eprintln!( + // "{}: + // game.player: {:?} + // game.platforms: {:?} + // game.joystick_player_delta: {:?} + // game.jump_player_delta: {:?} + // is_collide: {:?} + // is_jump: {:?} + // double_jump: {:?} + // velocity: {:?} + // x_pressed: {:?} + // velocity_under_0: {:?} + // {:?}", + // Utc::now().time(), + // game.player, + // game.platforms, + // game.joystick_player_delta, + // (game.player[2][0][1] + game.joystick_player_delta[1] * 10. + game.jump_player_delta), + // is_collide, + // is_jump, + // double_jump, + // velocity, + // x_pressed, + // velocity_under_0, + // game.player[2][0][1] + game.joystick_player_delta[1] * 10. + game.jump_player_delta + // ); + + thread::sleep(Duration::from_millis(1000 / 60)); + frame_count += 1; + last_is_colide = is_collide; + } + + Ok(()) +} diff --git a/src/main.rs_ b/src/main.rs_ new file mode 100644 index 0000000..28d8878 --- /dev/null +++ b/src/main.rs_ @@ -0,0 +1,144 @@ +extern crate nalgebra as na; + +use na::{Point2, Point3, RealField, Vector2}; +use ncollide2d::pipeline::CollisionGroups; +use ncollide2d::shape::{Cuboid, ShapeHandle}; +use nphysics2d::force_generator::DefaultForceGeneratorSet; +use nphysics2d::joint::DefaultJointConstraintSet; +use nphysics2d::object::{ + BodyPartHandle, ColliderDesc, DefaultBodySet, DefaultColliderSet, Ground, RigidBodyDesc, +}; +use nphysics2d::world::{DefaultGeometricalWorld, DefaultMechanicalWorld}; +use nphysics_testbed2d::Testbed; + + +macro_rules! r( + ($e: expr) => { + nalgebra::convert::($e) + } +); + +/* + * NOTE: The `r` macro is only here to convert from f64 to the `N` scalar type. + * This simplifies experimentation with various scalar types (f32, fixed-point numbers, etc.) + */ +pub fn init_world(testbed: &mut Testbed) { + /* + * World + */ + let mechanical_world = DefaultMechanicalWorld::new(Vector2::new(r!(0.0), r!(-9.81))); + let geometrical_world = DefaultGeometricalWorld::new(); + let mut bodies = DefaultBodySet::new(); + let mut colliders = DefaultColliderSet::new(); + let joint_constraints = DefaultJointConstraintSet::new(); + let force_generators = DefaultForceGeneratorSet::new(); + + /* + * Setup a static body used as the ground. + */ + let ground_handle = bodies.insert(Ground::new()); + + /* + * Setup groups. + */ + const GREEN_GROUP_ID: usize = 0; + let mut green_group = CollisionGroups::new(); + green_group.set_membership(&[GREEN_GROUP_ID]); + green_group.set_whitelist(&[GREEN_GROUP_ID]); + + const BLUE_GROUP_ID: usize = 1; + let mut blue_group = CollisionGroups::new(); + blue_group.set_membership(&[BLUE_GROUP_ID]); + blue_group.set_whitelist(&[BLUE_GROUP_ID]); + + /* + * A floor that will collide with everything (default behaviour). + */ + let ground_thickness = r!(0.2); + let ground_shape = ShapeHandle::new(Cuboid::new(Vector2::new(r!(3.0), ground_thickness))); + + let main_floor = ColliderDesc::new(ground_shape) + .translation(Vector2::y() * -ground_thickness) + .build(BodyPartHandle(ground_handle, 0)); + colliders.insert(main_floor); + + /* + * A green floor that will collide with the GREEN group only. + */ + let ground_shape = ShapeHandle::new(Cuboid::new(Vector2::new(r!(1.0), r!(0.1)))); + let green_floor = ColliderDesc::new(ground_shape.clone()) + .translation(Vector2::y()) + .collision_groups(green_group) + .build(BodyPartHandle(ground_handle, 0)); + let green_collider_handle = colliders.insert(green_floor); + + testbed.set_collider_color(green_collider_handle, Point3::new(0.0, 1.0, 0.0)); + + /* + * A blue floor that will collide with the BLUE group only. + */ + let blue_floor = ColliderDesc::new(ground_shape) + .translation(Vector2::y() * r!(2.0)) + .collision_groups(blue_group) + .build(BodyPartHandle(ground_handle, 0)); + let blue_collider_handle = colliders.insert(blue_floor); + + testbed.set_collider_color(blue_collider_handle, Point3::new(0.0, 0.0, 1.0)); + + /* + * Create the boxes + */ + let num = 8; + let rad = r!(0.1); + + let cuboid = ShapeHandle::new(Cuboid::new(Vector2::repeat(rad))); + let shift = (rad + ColliderDesc::::default_margin()) * r!(2.0); + let centerx = shift * r!(num as f64) / r!(2.0); + let centery = r!(2.5); + + for k in 0usize..4 { + for i in 0usize..num { + let x = r!(i as f64) * shift - centerx; + let y = r!(k as f64) * shift + centery; + + // Alternate between the GREEN and BLUE groups. + let (group, color) = if k % 2 == 0 { + (green_group, Point3::new(0.0, 1.0, 0.0)) + } else { + (blue_group, Point3::new(0.0, 0.0, 1.0)) + }; + + // Build the rigid body. + let rb = RigidBodyDesc::new().translation(Vector2::new(x, y)).build(); + let rb_handle = bodies.insert(rb); + + // Build the collider. + let co = ColliderDesc::new(cuboid.clone()) + .density(r!(1.0)) + .collision_groups(group) + .build(BodyPartHandle(rb_handle, 0)); + colliders.insert(co); + + testbed.set_body_color(rb_handle, color); + } + } + + /* + * Set up the testbed. + */ + testbed.set_ground_handle(Some(ground_handle)); + testbed.set_world( + mechanical_world, + geometrical_world, + bodies, + colliders, + joint_constraints, + force_generators, + ); + testbed.look_at(Point2::new(0.0, 1.0), 100.0); +} + +fn main() { + let testbed = Testbed::::from_builders(0, vec![("Collision groups", init_world)]); + testbed.run() +}