You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. use sdl2::pixels::Color;
  2. use sdl2::event::Event;
  3. use sdl2::keyboard::Keycode;
  4. use sdl2::render::{WindowCanvas, Texture};
  5. use sdl2::image::{self, LoadTexture, InitFlag};
  6. use sdl2::rect::{Point, Rect};
  7. use specs::prelude::*;
  8. use specs_derive::Component;
  9. use std::time::Duration;
  10. const PLAYER_MOVEMENT_SPEED: i32 = 5;
  11. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  12. enum Direction {
  13. Up,
  14. Down,
  15. Left,
  16. Right,
  17. }
  18. #[derive(Component, Debug)]
  19. #[storage(VecStorage)]
  20. struct Position(Point);
  21. #[derive(Component, Debug)]
  22. #[storage(VecStorage)]
  23. struct Velocity {
  24. speed: i32,
  25. direction: Direction,
  26. }
  27. #[derive(Component, Debug)]
  28. #[storage(VecStorage)]
  29. struct Sprite {
  30. spritesheet: usize,
  31. region: Rect,
  32. }
  33. #[derive(Component, Debug)]
  34. #[storage(VecStorage)]
  35. struct MovementAnimation {
  36. current_frame: usize,
  37. up_frames: Vec<Sprite>,
  38. down_frames: Vec<Sprite>,
  39. left_frames: Vec<Sprite>,
  40. right_frames: Vec<Sprite>,
  41. }
  42. #[derive(Debug)]
  43. struct Player {
  44. position: Point,
  45. sprite: Rect,
  46. speed: i32,
  47. direction: Direction,
  48. current_frame: i32,
  49. }
  50. fn direction_spritesheet_row(direction: Direction) -> i32 {
  51. use self::Direction::*;
  52. match direction {
  53. Up => 3,
  54. Down => 0,
  55. Left => 1,
  56. Right => 2,
  57. }
  58. }
  59. fn render(
  60. canvas: &mut WindowCanvas,
  61. color: Color,
  62. texture: &Texture,
  63. player: &Player
  64. ) -> Result<(), String> {
  65. canvas.set_draw_color(color);
  66. canvas.clear();
  67. let (width, height) = canvas.output_size()?;
  68. let (frame_width, frame_height) = player.sprite.size();
  69. let current_frame = Rect::new(
  70. player.sprite.x() + frame_width as i32 * player.current_frame,
  71. player.sprite.y() + frame_height as i32 * direction_spritesheet_row(player.direction),
  72. frame_width,
  73. frame_height,
  74. );
  75. let screen_position = player.position + Point::new(width as i32 / 2, height as i32 / 2);
  76. let screen_rect = Rect::from_center(screen_position, frame_width, frame_height);
  77. canvas.copy(texture, current_frame, screen_rect)?;
  78. canvas.present();
  79. Ok(())
  80. }
  81. fn update_player(player: &mut Player) {
  82. use self::Direction::*;
  83. match player.direction {
  84. Left => {
  85. player.position = player.position.offset(-player.speed, 0);
  86. },
  87. Right => {
  88. player.position = player.position.offset(player.speed, 0);
  89. },
  90. Up => {
  91. player.position = player.position.offset(0, -player.speed);
  92. },
  93. Down => {
  94. player.position = player.position.offset(0, player.speed);
  95. },
  96. }
  97. if player.speed != 0 {
  98. player.current_frame = (player.current_frame + 1) % 3;
  99. }
  100. }
  101. fn main() -> Result<(), String> {
  102. let sdl_context = sdl2::init()?;
  103. let video_subsystem = sdl_context.video()?;
  104. let _image_context = image::init(InitFlag::PNG | InitFlag::JPG)?;
  105. let window = video_subsystem.window("game tutorial", 800, 600)
  106. .position_centered()
  107. .build()
  108. .expect("could not initialize video subsystem");
  109. let mut canvas = window.into_canvas().build()
  110. .expect("could not make a canvas");
  111. let texture_creator = canvas.texture_creator();
  112. let texture = texture_creator.load_texture("assets/bardo.png")?;
  113. let mut player = Player {
  114. position: Point::new(0,0),
  115. sprite: Rect::new(0, 0, 26, 36),
  116. speed: 0,
  117. direction: Direction::Right,
  118. current_frame: 0,
  119. };
  120. let mut event_pump = sdl_context.event_pump()?;
  121. let mut i = 0;
  122. 'running: loop {
  123. for event in event_pump.poll_iter() {
  124. match event {
  125. Event::Quit {..} |
  126. Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
  127. break 'running;
  128. },
  129. Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
  130. player.speed = PLAYER_MOVEMENT_SPEED;
  131. player.direction = Direction::Left;
  132. },
  133. Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
  134. player.speed = PLAYER_MOVEMENT_SPEED;
  135. player.direction = Direction::Right;
  136. },
  137. Event::KeyDown { keycode: Some(Keycode::Up), .. } => {
  138. player.speed = PLAYER_MOVEMENT_SPEED;
  139. player.direction = Direction::Up;
  140. },
  141. Event::KeyDown { keycode: Some(Keycode::Down), .. } => {
  142. player.speed = PLAYER_MOVEMENT_SPEED;
  143. player.direction = Direction::Down;
  144. },
  145. Event::KeyUp { keycode: Some(Keycode::Left), repeat: false, .. } |
  146. Event::KeyUp { keycode: Some(Keycode::Right), repeat: false, .. } |
  147. Event::KeyUp { keycode: Some(Keycode::Up), repeat: false, .. } |
  148. Event::KeyUp { keycode: Some(Keycode::Down), repeat: false, .. } => {
  149. player.speed = 0;
  150. },
  151. _ => {}
  152. }
  153. }
  154. i = (i + 1) % 255;
  155. update_player(&mut player);
  156. render(&mut canvas, Color::RGB(i, 64, 255-i), &texture, &player)?;
  157. ::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
  158. }
  159. Ok(())
  160. }