First working version

Next we will be looking at implementing multi-controller multiplayer
This commit is contained in:
Leo Le Bouter 2020-10-10 23:34:01 +02:00
parent 0b15908469
commit 15b0b8efc3
5 changed files with 572 additions and 0 deletions

5
.gitignore vendored
View File

@ -10,3 +10,8 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
#Added by cargo
/target

19
Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "LJ-rust-filters"
version = "0.1.0"
authors = ["Leo Le Bouter <lle-bout@zaclys.net>"]
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"

135
src/main copy.rs_ Normal file
View File

@ -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()?;
}
}

269
src/main.rs Normal file
View File

@ -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<Vec<Segment>>,
player: Vec<Segment>,
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(())
}

144
src/main.rs_ Normal file
View File

@ -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::<f64, N>($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<N: RealField>(testbed: &mut Testbed<N>) {
/*
* 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::<N>::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::<f32>::from_builders(0, vec![("Collision groups", init_world)]);
testbed.run()
}