main.rs 4.4 KB

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