promenade.rs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #[macro_use]
  2. extern crate specs_derive;
  3. #[macro_use]
  4. extern crate specs_system_macro;
  5. use ggez::graphics::Drawable;
  6. use specs::prelude::*;
  7. use specs::world::WorldExt;
  8. mod input;
  9. pub mod messages;
  10. pub mod util;
  11. const WIDTH: f32 = 600.0;
  12. const HEIGHT: f32 = 400.0;
  13. struct Game {
  14. pub world: specs::World,
  15. }
  16. impl Game {
  17. fn setup(conn: messages::Connection) -> Game {
  18. let mut world = specs::World::new();
  19. world.register::<Pos>();
  20. world.register::<Vel>();
  21. world.register::<Solid>();
  22. world.register::<Controlled>();
  23. world.insert(input::Input::new());
  24. world.insert(conn);
  25. world
  26. .create_entity()
  27. .with(Pos { x: 200.0, y: 200.0 })
  28. .with(Vel { dx: 0.0, dy: 0.0 })
  29. .with(Controlled)
  30. .with(Solid)
  31. .build();
  32. Game { world }
  33. }
  34. }
  35. //
  36. #[derive(Component, Copy, Clone, Debug)]
  37. pub struct Pos {
  38. x: f32,
  39. y: f32,
  40. }
  41. #[derive(Component, Debug)]
  42. pub struct Vel {
  43. dx: f32,
  44. dy: f32,
  45. }
  46. #[derive(Component)]
  47. pub struct Controlled;
  48. #[derive(Component)]
  49. pub struct Solid;
  50. system! {
  51. Transmit(resource conn: messages::Connection, _c: Controlled, p: Pos) {
  52. conn.update(p.x, p.y);
  53. }
  54. }
  55. system! {
  56. Control(resource inp: input::Input, _c: Controlled, mut v: Vel) {
  57. const ACCEL: f32 = 0.5;
  58. v.dx = util::clamp(v.dx + inp.right * ACCEL, -20.0, 20.0);
  59. v.dy = util::clamp(v.dy + inp.up * ACCEL, -20.0, 20.0);
  60. }
  61. }
  62. system! {
  63. Slowdown(mut v: Vel, _c: Controlled) {
  64. const ROUNDING: f32 = 0.01;
  65. const FRICTION: f32 = 0.95;
  66. if v.dx.abs() < ROUNDING {
  67. v.dx = 0.0;
  68. } else {
  69. v.dx *= FRICTION;
  70. }
  71. if v.dy.abs() < ROUNDING {
  72. v.dy = 0.0;
  73. } else {
  74. v.dy *= FRICTION;
  75. }
  76. }
  77. }
  78. system! {
  79. Physics(mut pos: Pos, mut v: Vel, _s: Solid) {
  80. if pos.x < 0.0 {
  81. pos.x = 0.0;
  82. v.dx = v.dx.abs() * 0.5;
  83. } else if pos.x > WIDTH {
  84. pos.x = WIDTH;
  85. v.dx = -v.dx.abs() * 0.5;
  86. }
  87. if pos.y < 0.0 {
  88. v.dy = v.dy.abs();
  89. } else if pos.y > HEIGHT {
  90. v.dy = -v.dy.abs();
  91. }
  92. }
  93. }
  94. system! {
  95. Move(mut pos: Pos, v: Vel) {
  96. pos.x += v.dx;
  97. pos.y += v.dy;
  98. }
  99. }
  100. //
  101. struct Draw<'t> {
  102. pub ctx: &'t mut ggez::Context,
  103. }
  104. impl<'a, 't> specs::System<'a> for Draw<'t> {
  105. type SystemData = (specs::ReadStorage<'a, Pos>,);
  106. fn run(&mut self, (pos,): Self::SystemData) {
  107. for (p,) in (&pos,).join() {
  108. let param = ggez::graphics::DrawParam {
  109. dest: [p.x, p.y].into(),
  110. ..ggez::graphics::DrawParam::default()
  111. };
  112. let mesh = ggez::graphics::Mesh::new_circle(
  113. self.ctx,
  114. ggez::graphics::DrawMode::fill(),
  115. [0.0, 0.0],
  116. 10.0,
  117. 0.1,
  118. ggez::graphics::WHITE,
  119. );
  120. mesh.unwrap().draw(self.ctx, param).unwrap();
  121. }
  122. }
  123. }
  124. impl ggez::event::EventHandler for Game {
  125. fn draw(&mut self, ctx: &mut ggez::Context) -> ggez::GameResult<()> {
  126. ggez::graphics::clear(ctx, ggez::graphics::BLACK);
  127. Draw { ctx }.run_now(&self.world);
  128. ggez::graphics::present(ctx).unwrap();
  129. Ok(())
  130. }
  131. fn update(&mut self, _ctx: &mut ggez::Context) -> ggez::GameResult<()> {
  132. Control.run_now(&self.world);
  133. Physics.run_now(&self.world);
  134. Slowdown.run_now(&self.world);
  135. Move.run_now(&self.world);
  136. Transmit.run_now(&self.world);
  137. Ok(())
  138. }
  139. // to handle events, we modify the stored KeyState resource
  140. fn key_down_event(
  141. &mut self,
  142. ctx: &mut ggez::Context,
  143. keycode: winit::VirtualKeyCode,
  144. _keymod: ggez::event::KeyMods,
  145. _repeat: bool,
  146. ) {
  147. if keycode == winit::VirtualKeyCode::Escape {
  148. self.world.read_resource::<messages::Connection>().goodbye();
  149. ggez::event::quit(ctx);
  150. }
  151. input::Input::handle_down(&mut self.world.write_resource(), keycode);
  152. }
  153. fn key_up_event(
  154. &mut self,
  155. _ctx: &mut ggez::Context,
  156. keycode: winit::VirtualKeyCode,
  157. _keymod: ggez::event::KeyMods,
  158. ) {
  159. input::Input::handle_up(&mut self.world.write_resource(), keycode);
  160. }
  161. }
  162. fn main() -> ggez::GameResult<()> {
  163. let connection = messages::Connection::new("foo", "192.168.0.3", 9991);
  164. let (mut ctx, mut evloop) = ggez::ContextBuilder::new("game", "me")
  165. .window_mode(ggez::conf::WindowMode {
  166. width: WIDTH,
  167. height: HEIGHT,
  168. ..ggez::conf::WindowMode::default()
  169. })
  170. .build()?;
  171. let mut game = Game::setup(connection);
  172. let res = ggez::event::run(&mut ctx, &mut evloop, &mut game);
  173. res
  174. }