aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml3
-rw-r--r--TODO13
-rw-r--r--backgroundxcf.xcfbin0 -> 93892 bytes
-rw-r--r--src/assets/background.pngbin0 -> 2037 bytes
-rw-r--r--src/assets/bit.pngbin0 -> 144 bytes
-rw-r--r--src/bit.xcfbin0 -> 955 bytes
-rw-r--r--src/display.rs21
-rw-r--r--src/input.rs6
-rw-r--r--src/lib.rs171
-rw-r--r--src/main.rs6
10 files changed, 154 insertions, 66 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0428edd..12ffc9c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,4 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.5" \ No newline at end of file
+rand = "0.8.5"
+sfml = "0.17.0" \ No newline at end of file
diff --git a/TODO b/TODO
index 03bf292..6f87946 100644
--- a/TODO
+++ b/TODO
@@ -1,9 +1,12 @@
-SFML input
-SFML graphics
-Select between debug(cli) and gui display
Next piece in gui
Add sounds (mostly for losing, winning and clearing a row)
-Pause on lose focus
Also add a pause
Have a menu
-Add to score on line clear \ No newline at end of file
+Add to score on line clear
+
+redo input system. It feels like junk
+Implement win condition
+
+Import pieces from files to make it data driven
+Refactor getting 2d array from piece area
+ Make it a pointer to the values in the area \ No newline at end of file
diff --git a/backgroundxcf.xcf b/backgroundxcf.xcf
new file mode 100644
index 0000000..66c61c7
--- /dev/null
+++ b/backgroundxcf.xcf
Binary files differ
diff --git a/src/assets/background.png b/src/assets/background.png
new file mode 100644
index 0000000..fe234aa
--- /dev/null
+++ b/src/assets/background.png
Binary files differ
diff --git a/src/assets/bit.png b/src/assets/bit.png
new file mode 100644
index 0000000..32fb054
--- /dev/null
+++ b/src/assets/bit.png
Binary files differ
diff --git a/src/bit.xcf b/src/bit.xcf
new file mode 100644
index 0000000..95e0b34
--- /dev/null
+++ b/src/bit.xcf
Binary files differ
diff --git a/src/display.rs b/src/display.rs
deleted file mode 100644
index b57f68f..0000000
--- a/src/display.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use crate::tetris::piece::{Piece, Pos};
-
-pub fn display(grid: &Vec<Vec<i8>>, piece: &Piece) {
- let piece_pos_vec = piece.get_bits_pos();
-
- let mut yc = 0;
- for y in grid {
- let mut xc = 0;
- for mut x in y {
- for bit in &piece_pos_vec {
- if bit == &Pos(yc, xc) {
- x = &1;
- }
- }
- xc += 1;
- print!("{} ", x);
- }
- print!("\n");
- yc += 1;
- }
-} \ No newline at end of file
diff --git a/src/input.rs b/src/input.rs
deleted file mode 100644
index 23d0040..0000000
--- a/src/input.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-pub struct Input {}
-impl Input {
- pub fn new() -> Input {
- Input{}
- }
-} \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 5b4bbb0..6d7cd75 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,56 +1,169 @@
-pub mod input;
mod tetris;
-mod display;
use crate::tetris::piece;
-use std::io::stdin;
-use crate::input::Input;
+
+use std::time::{Instant, Duration};
+
+// SFML
+use sfml::window::{Style, Event, ContextSettings, Key};
+use sfml::graphics::{self, *};
+use sfml::system::{Vector2f, Vector2u};
pub struct Game {
- tickrate: u8, // How many times things are checked a second
- maxfps: u8, // Between 1 and 240
- gamespeed: u8, // How quickly r#move(down) is called in ms
+ tickrate: Duration, // How many times things are checked a second
+ maxfps: u64,
+ window_geometry: (u32, u32),
+ window: RenderWindow,
}
impl Game {
pub fn new() -> Game {
+ let maxfps = 30;
+ let geometry = (480, 480);
+
+ // Window setup
+ let mut context_settings: ContextSettings = Default::default();
+ context_settings.antialiasing_level = 0;
+
+ let mut window = graphics::RenderWindow::new(
+ geometry,
+ "Test",
+ Style::DEFAULT,
+ &context_settings);
+
+ window.set_framerate_limit(maxfps);
+ window.clear(Color::rgb(250, 250, 250));
+
+ // View
+ let view_geometry = (geometry.0 as f32, geometry.1 as f32);
+ let view = View::new(
+ Vector2f::from(view_geometry) / 2.0,
+ Vector2f::from(view_geometry));
+ window.set_view(&view);
+
Game{
- tickrate: 20,
+ tickrate: Duration::from_secs(1),
maxfps: 30,
- gamespeed: 250,
+ window_geometry: geometry,
+ window: window,
}
}
+ pub fn set_geometry(&mut self, geometry: (u32, u32)) {
+ self.window_geometry = geometry;
+ self.window.set_size(Vector2u::from(geometry));
+ }
+
+ fn pause(&mut self) {
+ println!("paused");
+ loop {
+ match self.window.wait_event() {
+ Some(Event::GainedFocus) => break,
+ _ => ()
+ }
+ }
+ println!("resumed");
+ }
+
// The actual game loop
- pub fn game_loop(&self, input: &Input) {
+ pub fn game_loop(&mut self) {
+
+ // Textures
+ let background = Texture::from_file("assets/background.png").expect("Cannot load texture");
+ let bit = Texture::from_file("assets/bit.png").expect("Cannot load texture");
+
+ // Objects
+ let mut background = RectangleShape::with_texture(&background);
+ background.set_size(Vector2f::new(480.0, 480.0));
+
+ let mut bit = RectangleShape::with_texture(&bit);
+ bit.set_size(Vector2f::new(24.0, 24.0));
+
+ // Initialize the background
+ self.window.draw(&background);
+
+ // Timing
+ let mut tick = Instant::now();
+ let mut fpscap = Instant::now();
+
+ // Game setup
let mut tetris = tetris::Tetris::new();
- let mut piece = piece::Piece::random(piece::Pos(0,0));
+ let mut piece = piece::Piece::random(piece::Pos(-2,3));
loop {
- tetris.check_lines();
- piece.r#move(piece::Dir::Down, &tetris);
+ // Process events
+ let mut key: Option<Key> = None;
+ match self.window.poll_event() {
+ Some(n) => match n {
+ Event::Closed => break,
+ Event::Resized {width: w, height: h} => self.set_geometry((w, h)),
+ Event::LostFocus => self.pause(),
+ Event::KeyPressed {code: c, ctrl: _, alt: _, shift: _, system: _} => key = Some(c),
+ Event::KeyReleased {code: _, ctrl: _, alt: _, shift: _, system: _} => key = None,
+ _ => (),
+ },
+ None => (),
+ }
+
+ // Process keys
+ use tetris::piece::{Dir, Rotate};
+ match key {
+ Some(Key::A) => piece.r#move(Dir::Left, &tetris),
+ Some(Key::S) => piece.r#move(Dir::Down, &tetris),
+ Some(Key::D) => piece.r#move(Dir::Right, &tetris),
+ Some(Key::Q) => piece.rotate(Rotate::Left, &tetris),
+ Some(Key::E) => piece.rotate(Rotate::Right, &tetris),
+ _ => ()
+ }
// Check if piece is dead
if piece.is_alive() == false {
piece.apply_to_grid(&mut tetris);
- piece = piece::Piece::random(piece::Pos(0,0));
+ piece = piece::Piece::random(piece::Pos(-2,3));
// piece = piece::Piece::new(piece::Pieces::Cube, piece::Pos(0,0));
}
-
- let grid = tetris.return_grid();
- display::display(&grid, &piece);
-
- let mut input = String::new();
-
- stdin().read_line(&mut input).expect("Could not read line");
- let input = input.get(0..1).expect("Nothing to get");
- match input {
- "a" => piece.r#move(piece::Dir::Left, &tetris),
- "d" => piece.r#move(piece::Dir::Right, &tetris),
- "e" => piece.rotate(piece::Rotate::Right, &tetris),
- "q" => piece.rotate(piece::Rotate::Left, &tetris),
- " " => break,
- _ => (),
+
+ // Check if there are full lines
+ tetris.check_lines();
+
+ // Execute on tick
+ if tick.elapsed() >= self.tickrate {
+ // Reset the clock
+ tick = Instant::now();
+
+ // Timed logic
+ piece.r#move(piece::Dir::Down, &tetris)
+ }
+
+ if fpscap.elapsed() >= Duration::from_millis(1 / self.maxfps) {
+ // Reset the clock
+ fpscap = Instant::now();
+
+ // Draw the background
+ self.window.draw(&background);
+
+ // Start drawing everything
+ let grid = tetris.return_grid();
+
+ // Draw all the bits
+ for y in (0..grid.len()).rev() {
+ for x in 0..grid.len() {
+ if *grid.get(y).unwrap_or(&vec![0]).get(x).unwrap_or(&0) == 1 {
+ bit.set_position(((x * 24) as f32, (y * 24) as f32));
+ self.window.draw(&bit);
+ }
+ }
+ }
+ for piece_bit in piece.get_bits_pos() {
+ if !(piece_bit.0 < 0 || piece_bit.1 < 0) {
+ bit.set_position(((piece_bit.1 as f32) * 24.0, (piece_bit.0 as f32) * 24.0));
+ self.window.draw(&bit);
+ }
+ }
+
+ self.window.display();
}
}
+
+ self.window.close();
}
}
diff --git a/src/main.rs b/src/main.rs
index aba1e8f..153019b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,6 @@
use tetris::Game;
-use tetris::input::Input;
fn main() {
- let input = Input::new();
- let game = Game::new();
- game.game_loop(&input)
+ let mut game = Game::new();
+ game.game_loop()
} \ No newline at end of file