use common::Point2D;
use core::controller::Controller;
use core::controller::ControllerManager;
+use core::level::Level;
use core::render::Renderer;
use point;
use sdl2::event::Event;
use sdl2::joystick::PowerLevel;
+use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use sprites::SpriteManager;
use std::cell::RefCell;
self.world.render(renderer, sprites);
}
- fn handle_event(&mut self, _event: Event) {}
+ fn handle_event(&mut self, event: Event) {
+ match event {
+ Event::KeyDown { keycode: Some(Keycode::Space), .. } => {
+ self.world.level.regenerate();
+ }
+ Event::KeyDown { keycode: Some(Keycode::KpPlus), .. } => {
+ self.world.level.increase_iteration();
+ }
+ Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => {
+ self.world.level.decrease_iteration();
+ }
+ _ => {}
+ }
+ }
}
////////// WORLD ///////////////////////////////////////////////////////////////
impl World {
pub fn new() -> Self {
World {
- level: Level {
- gravity: point!(0.0, 0.1),
- ground: 600.0,
- },
+ level: Level::new(point!(0.0, 0.1), 600.0),
..Default::default()
}
}
}
}
-////////// LEVEL ///////////////////////////////////////////////////////////////
-
-#[derive(Default)]
-pub struct Level {
- gravity: Point2D<f64>,
- ground: f64, // just to have something
-}
-
-impl Level {
- pub fn render(&mut self, renderer: &mut Renderer, _sprites: &SpriteManager) {
- let w = renderer.viewport().0 as i32;
- for i in 1..11 {
- let y = (i * i - 1) as i32 + self.ground as i32;
- renderer.canvas().set_draw_color((255 - i * 20, 255 - i * 20, 0));
- renderer.canvas().draw_line((0, y), (w, y)).unwrap();
- }
- }
-}
-
////////// OBJECT //////////////////////////////////////////////////////////////
type Objects = Vec<Box<dyn Object>>;
}
}
- if self.pos.x <= 0.0 || self.pos.x >= 1280.0 { // only for testing
- self.pos.x = self.pos.x.max(0.0).min(1280.0);
- self.vel.x = -self.vel.x;
- self.bounces = 0;
+ let x = (self.pos.x / lvl.grid.cell_size as f64).min(lvl.grid.width as f64 - 1.0).max(0.0) as usize;
+ let y = (self.pos.y / lvl.grid.cell_size as f64).min(lvl.grid.height as f64 - 1.0).max(0.0) as usize;
+ if lvl.grid.cells[x][y] {
+ if self.bounces == 0 {
+ return Dead
+ }
+ self.vel = -self.vel;
+ self.bounces -= 1;
use rand::distributions::{Distribution, Normal};
let normal = Normal::new(0.5, 0.4);
objects.push(Box::new(Boll {
- vel: self.vel * normal.sample(&mut rand::thread_rng()),
- ..*self
+ vel: self.vel * normal.sample(&mut rand::thread_rng()),
+ ..*self
}));
}
let block = _sprites.get("block");
let size = 4 + self.bounces * 6;
renderer.blit(block, None, Rect::new(self.pos.x as i32 - size as i32 / 2, self.pos.y as i32 - size as i32 / 2, size as u32, size as u32));
- // renderer.set_draw_color((0, self.bounces * 100, 255));
- // renderer.draw_point((self.pos.x as i32, self.pos.y as i32)).unwrap();
+ // renderer.canvas().set_draw_color((0, self.bounces * 100, 255));
+ // renderer.canvas().draw_point((self.pos.x as i32, self.pos.y as i32)).unwrap();
}
}
--- /dev/null
+use common::Point2D;
+use core::render::Renderer;
+use rand::Rng;
+use sprites::SpriteManager;
+
+////////// LEVEL ///////////////////////////////////////////////////////////////
+
+#[derive(Default)]
+pub struct Level {
+ pub gravity: Point2D<f64>,
+ pub ground: f64, // just to have something
+ pub grid: Grid,
+ iterations: u8,
+}
+
+impl Level {
+ pub fn new(gravity: Point2D<f64>, ground: f64) -> Self {
+ Level { gravity, ground, grid: Grid::generate(10), iterations: 10 }
+ }
+
+ pub fn regenerate(&mut self) {
+ self.grid = Grid::generate(self.iterations);
+ }
+
+ pub fn increase_iteration(&mut self) {
+ self.iterations += 1;
+ self.regenerate();
+ println!("iterate {} time(s)", self.iterations);
+ }
+
+ pub fn decrease_iteration(&mut self) {
+ self.iterations -= 1;
+ self.regenerate();
+ println!("iterate {} time(s)", self.iterations);
+ }
+
+ pub fn render(&mut self, renderer: &mut Renderer, _sprites: &SpriteManager) {
+ let w = renderer.viewport().0 as i32;
+
+ renderer.canvas().set_draw_color((64, 64, 64));
+ let size = self.grid.cell_size;
+ for x in 0..self.grid.width {
+ for y in 0..self.grid.height {
+ if self.grid.cells[x][y] {
+ renderer.canvas().fill_rect(sdl2::rect::Rect::new(x as i32 * size as i32, y as i32 * size as i32, size as u32, size as u32)).unwrap();
+ }
+ }
+ }
+
+ for i in 1..11 {
+ let y = (i * i - 1) as i32 + self.ground as i32;
+ renderer.canvas().set_draw_color((255 - i * 20, 255 - i * 20, 0));
+ renderer.canvas().draw_line((0, y), (w, y)).unwrap();
+ }
+ }
+}
+
+////////// GRID ////////////////////////////////////////////////////////////////
+
+#[derive(Default)]
+pub struct Grid {
+ pub width: usize,
+ pub height: usize,
+ pub cell_size: usize,
+ pub cells: Vec<Vec<bool>>,
+}
+
+impl Grid {
+ fn generate(iterations: u8) -> Grid {
+ let cell_size = 10;
+ let (width, height) = (1280 / cell_size, 600 / cell_size);
+ let mut cells = vec!(vec!(true; height); width);
+
+ let mut rng = rand::thread_rng();
+
+ // randomize
+ for x in 1..(width - 1) {
+ for y in 1..(height - 1) {
+ cells[x][y] = rng.gen_range(0, 100) > 55;
+ }
+ }
+
+ // smooth
+ // let mut count = 0;
+ // loop {
+ // count += 1;
+ // println!("iteration {}", count);
+ for _i in 0..iterations {
+ let mut next = vec!(vec!(true; height); width);
+ for x in 1..(width - 1) {
+ for y in 1..(height - 1) {
+ match Grid::neighbours(&cells, x, y) {
+ n if n < 4 => next[x][y] = false,
+ n if n > 4 => next[x][y] = true,
+ _ => next[x][y] = cells[x][y]
+ };
+ }
+ }
+ if cells == next {
+ break;
+ } else {
+ cells = next;
+ }
+ }
+
+ Grid {
+ width,
+ height,
+ cell_size,
+ cells
+ }
+ }
+
+ fn neighbours(grid: &Vec<Vec<bool>>, px: usize, py: usize) -> u8 {
+ let mut count = 0;
+ for x in (px - 1)..=(px + 1) {
+ for y in (py - 1)..=(py + 1) {
+ if !(x == px && y == py) && grid[x][y] {
+ count += 1;
+ }
+ }
+ }
+ count
+ }
+}