diff --git a/src/app.rs b/src/app.rs index 8013042..e2945ce 100644 --- a/src/app.rs +++ b/src/app.rs @@ -4,22 +4,25 @@ use piston::*; use board::Board; use number_renderer::NumberRenderer; +use settings::Settings; -pub struct App { - board: Board, +pub struct App<'a> { + board: Board<'a>, number_renderer: Option, + settings: &'a Settings, } -impl App { - pub fn new() -> App { +impl<'a> App<'a> { + pub fn new(settings: &'a Settings) -> App<'a> { App { - board: Board::new(), + board: Board::new(settings), number_renderer: None, + settings: settings, } } } -impl Game for App { +impl<'a> Game for App<'a> { fn load(&mut self, asset_store: &mut AssetStore) { self.number_renderer = Some(NumberRenderer::new(asset_store)); } @@ -50,7 +53,7 @@ impl Game for App { self.board.merge_from_top_to_bottom(); } if key == keyboard::Space { - self.board = Board::new(); + self.board = Board::new(self.settings); } } diff --git a/src/board.rs b/src/board.rs index dd33497..9ec25b1 100644 --- a/src/board.rs +++ b/src/board.rs @@ -5,24 +5,27 @@ use rand::random; use graphics::*; use piston::*; use number_renderer::NumberRenderer; -use settings; +use settings::Settings; use tile::{ Tile, TileStatic, }; -pub struct Board { - tiles: Vec, +pub struct Board<'a> { + tiles: Vec>, score: int, highest_score: int, + + settings: &'a Settings, } -impl Board { - pub fn new() -> Board { +impl<'a> Board<'a> { + pub fn new(settings: &'a Settings) -> Board<'a> { let mut board = Board { tiles: Vec::::new(), score: 0, highest_score: 0, + settings: settings, }; board.generate_tile(); board.generate_tile(); @@ -30,15 +33,15 @@ impl Board { } pub fn generate_tile(&mut self) { - if self.tiles.len() == (settings::TILE_WIDTH * settings::TILE_HEIGHT) as uint { + if self.tiles.len() == (self.settings.tile_width * self.settings.tile_height) as uint { return; } loop { - let x = (random::() % settings::TILE_WIDTH as uint) as int; - let y = (random::() % settings::TILE_HEIGHT as uint) as int; + let x = (random::() % self.settings.tile_width as uint) as int; + let y = (random::() % self.settings.tile_height as uint) as int; if self.get_tile(x, y).is_none() { - self.tiles.push(Tile::new(2, x, y)); + self.tiles.push(Tile::new(self.settings, 2, x, y)); break; } } @@ -70,7 +73,7 @@ impl Board { tiles_need_removed.insert(i); tiles_need_removed.insert(j); - tiles_need_added.push(Tile::new_combined(tile1.score + tile2.score, tile1.tile_x, tile1.tile_y)); + tiles_need_added.push(Tile::new_combined(self.settings, tile1.score + tile2.score, tile1.tile_x, tile1.tile_y)); score_to_added += tile1.score + tile2.score; break; } @@ -90,27 +93,32 @@ impl Board { pub fn render(&self, number_renderer: &NumberRenderer, c: &Context, gl: &mut Gl) { c.view() - .rect(settings::BEST_RECT[0], - settings::BEST_RECT[1], - settings::BEST_RECT[2], - settings::BEST_RECT[3]) - .rgba(settings::LABEL_COLOR[0], - settings::LABEL_COLOR[1], - settings::LABEL_COLOR[2], - settings::LABEL_COLOR[3]) + .rect(self.settings.best_rect[0], + self.settings.best_rect[1], + self.settings.best_rect[2], + self.settings.best_rect[3]) + .rgba(self.settings.label_color[0], + self.settings.label_color[1], + self.settings.label_color[2], + 1.0) .fill(gl); - number_renderer.render(self.score as u32, settings::BEST_RECT[0] + settings::BEST_RECT[2] / 2.0, settings::BEST_RECT[1] + settings::BEST_RECT[3] / 2.0, settings::BEST_RECT[2], settings::TEXT_LIGHT_COLOR, c, gl); + number_renderer.render( + self.score as u32, + self.settings.best_rect[0] + self.settings.best_rect[2] / 2.0, + self.settings.best_rect[1] + self.settings.best_rect[3] / 2.0, + self.settings.best_rect[2], + self.settings.text_light_color, c, gl); self.render_board(c, gl); self.render_tiles(number_renderer, c, gl); } pub fn merge_from_bottom_to_top(&mut self) { - self.merge_col(0, settings::TILE_HEIGHT, 1); + self.merge_col(0, self.settings.tile_height, 1); } pub fn merge_from_top_to_bottom(&mut self) { - self.merge_col(settings::TILE_HEIGHT - 1, -1, -1); + self.merge_col(self.settings.tile_height - 1, -1, -1); } fn merge_col(&mut self, y_start: int, y_end: int, y_step: int) { @@ -121,7 +129,7 @@ impl Board { let mut need_generate = false; loop { // move all tiles to right place - for col in range(0, settings::TILE_WIDTH) { + for col in range(0, self.settings.tile_width) { for row in range_step(y_start, y_end, y_step) { match self.get_mut_tile(col, row) { None => { @@ -141,7 +149,7 @@ impl Board { } let mut did_merged = false; - for col in range(0, settings::TILE_WIDTH) { + for col in range(0, self.settings.tile_width) { let mut found = false; let mut sx = 0; let mut sy = 0; @@ -189,11 +197,11 @@ impl Board { } pub fn merge_from_left_to_right(&mut self) { - self.merge_row(settings::TILE_WIDTH - 1, -1, -1); + self.merge_row(self.settings.tile_width - 1, -1, -1); } pub fn merge_from_right_to_left(&mut self) { - self.merge_row(0, settings::TILE_WIDTH, 1); + self.merge_row(0, self.settings.tile_width, 1); } fn merge_row(&mut self, x_start: int, x_end: int, x_step: int) { @@ -204,7 +212,7 @@ impl Board { let mut need_generate = false; loop { // move all tiles to right place - for row in range(0, settings::TILE_HEIGHT) { + for row in range(0, self.settings.tile_height) { for col in range_step(x_start, x_end, x_step) { match self.get_mut_tile(col, row) { None => { @@ -224,7 +232,7 @@ impl Board { // merge let mut did_merged = false; - for row in range(0, settings::TILE_HEIGHT) { + for row in range(0, self.settings.tile_height) { let mut found = false; let mut sx = 0; let mut sy = 0; @@ -282,11 +290,11 @@ impl Board { } /// Returns next tile right besides (x, y) - fn get_next_tile<'a>(&'a self, x: int, y: int, step_x: int, step_y: int) -> Option<&'a Tile> { + fn get_next_tile<'b>(&'b self, x: int, y: int, step_x: int, step_y: int) -> Option<&'b Tile<'a>> { let mut x = x + step_x; let mut y = y + step_y; - while x >= 0 && x < settings::TILE_WIDTH - && y >= 0 && y < settings::TILE_HEIGHT { + while x >= 0 && x < self.settings.tile_width + && y >= 0 && y < self.settings.tile_height { let tile = self.get_tile(x, y); if tile.is_some() { return tile; @@ -297,12 +305,12 @@ impl Board { None } - fn get_mut_next_tile<'a>(&'a mut self, x: int, y: int, step_x: int, step_y: int) -> Option<&'a mut Tile> { + fn get_mut_next_tile<'b>(&'b mut self, x: int, y: int, step_x: int, step_y: int) -> Option<&'b mut Tile<'a>> { let mut x = x + step_x; let mut y = y + step_y; let mut found = false; - while x >= 0 && x < settings::TILE_WIDTH - && y >= 0 && y < settings::TILE_HEIGHT { + while x >= 0 && x < self.settings.tile_width + && y >= 0 && y < self.settings.tile_height { let tile = self.get_tile(x, y); if tile.is_some() { found = true; @@ -319,7 +327,7 @@ impl Board { } } - fn get_tile<'a>(&'a self, x: int, y: int) -> Option<&'a Tile> { + fn get_tile<'b>(&'b self, x: int, y: int) -> Option<&'b Tile<'a>> { for tile in self.tiles.iter() { if tile.tile_x == x && tile.tile_y == y { return Some(tile); @@ -328,7 +336,7 @@ impl Board { None } - fn get_mut_tile<'a>(&'a mut self, x: int, y: int) -> Option<&'a mut Tile> { + fn get_mut_tile<'b>(&'b mut self, x: int, y: int) -> Option<&'b mut Tile<'a>> { for tile in self.tiles.mut_iter() { if tile.tile_x == x && tile.tile_y == y { return Some(tile); @@ -349,32 +357,32 @@ impl Board { fn render_board(&self, c: &Context, gl: &mut Gl) { c.view() - .rect(settings::BOARD_PADDING, - settings::BOARD_PADDING + settings::BOARD_OFFSET_Y, - settings::BOARD_SIZE[0], - settings::BOARD_SIZE[1]) - .rgba(settings::TILE_BACKGROUND_COLOR[0], - settings::TILE_BACKGROUND_COLOR[1], - settings::TILE_BACKGROUND_COLOR[2], - settings::TILE_BACKGROUND_COLOR[3]) + .rect(self.settings.board_padding, + self.settings.board_padding + self.settings.board_offset_y, + self.settings.board_size[0], + self.settings.board_size[1]) + .rgba(self.settings.tile_background_color[0], + self.settings.tile_background_color[1], + self.settings.tile_background_color[2], + 1.0) .fill(gl); - let mut x = settings::BOARD_PADDING + settings::TILE_PADDING; - let mut y = settings::BOARD_PADDING + settings::BOARD_OFFSET_Y + settings::TILE_PADDING; - for _ in range(0, settings::TILE_HEIGHT) { - for _ in range(0, settings::TILE_WIDTH) { + let mut x = self.settings.board_padding + self.settings.tile_padding; + let mut y = self.settings.board_padding + self.settings.board_offset_y + self.settings.tile_padding; + for _ in range(0, self.settings.tile_height) { + for _ in range(0, self.settings.tile_width) { c.view() - .rect(x, y, settings::TILE_SIZE, settings::TILE_SIZE) - .rgba(settings::TILES_COLOR[0][0], - settings::TILES_COLOR[0][1], - settings::TILES_COLOR[0][2], - settings::TILES_COLOR[0][3]) + .rect(x, y, self.settings.tile_size, self.settings.tile_size) + .rgba(self.settings.tiles_colors.get(0)[0], + self.settings.tiles_colors.get(0)[1], + self.settings.tiles_colors.get(0)[2], + 1.0) .fill(gl); - x += settings::TILE_PADDING + settings::TILE_SIZE; + x += self.settings.tile_padding + self.settings.tile_size; } - x = settings::BOARD_PADDING + settings::TILE_PADDING; - y += settings::TILE_PADDING + settings::TILE_SIZE; + x = self.settings.board_padding + self.settings.tile_padding; + y += self.settings.tile_padding + self.settings.tile_size; } } diff --git a/src/main.rs b/src/main.rs index 7d22713..64f2718 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,21 +19,24 @@ mod tile; type GameWindowBackEnd = GameWindowSDL2; fn main() { - let settings = settings::SettingsInJson::load(); + let settings = settings::Settings::load(); let mut game_window: GameWindowBackEnd = GameWindow::new( GameWindowSettings::new ( "Rust-2048".to_owned(), - settings::WINDOW_SIZE, + settings.window_size, false, true, - settings::WINDOW_BACKGROUND_COLOR, + [settings.window_background_color[0], + settings.window_background_color[1], + settings.window_background_color[2], + 1.0,], ) ); - let mut asset_store = AssetStore::from_folder(settings::ASSET_FOLDER); + let mut asset_store = AssetStore::from_folder(settings.asset_folder.as_slice()); - let mut app = app::App::new(); + let mut app = app::App::new(&settings); app.run(&mut game_window, &mut asset_store); } diff --git a/src/number_renderer.rs b/src/number_renderer.rs index d3cea52..5972878 100644 --- a/src/number_renderer.rs +++ b/src/number_renderer.rs @@ -20,7 +20,7 @@ impl NumberRenderer { } pub fn render(&self, number: u32, center_x: f64, center_y: f64, max_width: f64, - color: [f32, ..4], c: &Context, gl: &mut Gl) { + color: [f32, ..3], c: &Context, gl: &mut Gl) { let digits = number_to_digits(number); let total_width = DIGITS_WIDTH * digits.len() as f64; let total_width = if total_width > max_width { @@ -38,7 +38,7 @@ impl NumberRenderer { for digit in digits.iter() { image.source_rect[0] = DIGITS_WIDTH as u32 * *digit; c.view().rect(x, y, width, height) - .image(image).rgba(color[0], color[1], color[2], color[3]) + .image(image).rgba(color[0], color[1], color[2], 1.0) .draw(gl); x += width; } diff --git a/src/settings.rs b/src/settings.rs index 1f873ee..8f9a24e 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -8,6 +8,7 @@ use serialize::{ Decodable, }; +/* pub static ASSET_FOLDER: &'static str = "assets"; pub static WINDOW_SIZE: [u32, ..2] = [ @@ -63,7 +64,7 @@ pub static BUTTON_COLOR: [f32, ..4] = [142.0 / 255.0, 122.0 / 255.0, 102.0 / 255 pub static TEXT_DARK_COLOR: [f32, ..4] = [119.0 / 255.0, 110.0 / 255.0, 101.0 / 255.0, 1.0]; pub static TEXT_LIGHT_COLOR: [f32, ..4] = [249.0 / 255.0, 246.0 / 255.0, 242.0 / 255.0, 1.0]; - +*/ static SETTING_FILENAME: &'static str = "settings.json"; @@ -93,10 +94,6 @@ pub struct Settings { } impl Settings { - pub fn default_settings() -> Settings { - Settings::from_settings_in_json(&SettingsInJson::default_settings()) - } - pub fn load() -> Settings { Settings::from_settings_in_json(&SettingsInJson::load()) } @@ -107,16 +104,25 @@ impl Settings { s.tile_size * s.tile_height as f64 + s.tile_padding * (s.tile_height + 1) as f64, ]; + + let mut tiles_colors = Vec::<[f32, ..3]>::new(); + for color in s.tiles_colors.iter() { + tiles_colors.push([ + *color.get(0) / 255.0, + *color.get(1) / 255.0, + *color.get(2) / 255.0, + ]); + } Settings { - asset_folder: s.asset_folder, + asset_folder: s.asset_folder.clone(), window_size: [ (s.board_padding * 2.0 + board_size[0]) as u32, (s.board_padding * 2.0 + board_size[1] + s.board_offset_y) as u32, ], window_background_color: [ - *s.window_background_color.get(0), - *s.window_background_color.get(1), - *s.window_background_color.get(2), + *s.window_background_color.get(0) / 255.0, + *s.window_background_color.get(1) / 255.0, + *s.window_background_color.get(2) / 255.0, ], board_padding: s.board_padding, board_size: board_size, @@ -126,9 +132,50 @@ impl Settings { tile_size: s.tile_size, tile_padding: s.tile_padding, tile_background_color: [ - *s.tile_background_color.get(0), - *s.tile_background_color.get(1), - *s.tile_background_color.get(2), + *s.tile_background_color.get(0) / 255.0, + *s.tile_background_color.get(1) / 255.0, + *s.tile_background_color.get(2) / 255.0, + ], + tiles_colors: tiles_colors, + tile_unknow_color: [ + *s.tile_unknow_color.get(0) / 255.0, + *s.tile_unknow_color.get(1) / 255.0, + *s.tile_unknow_color.get(2) / 255.0, + ], + tile_move_time: s.tile_move_time, + tile_new_time: s.tile_new_time, + tile_combine_time: s.tile_combine_time, + best_rect: [ + *s.best_rect.get(0), + *s.best_rect.get(1), + *s.best_rect.get(2), + *s.best_rect.get(3), + ], + score_rect: [ + *s.score_rect.get(0), + *s.score_rect.get(1), + *s.score_rect.get(2), + *s.score_rect.get(3), + ], + label_color: [ + *s.label_color.get(0) / 255.0, + *s.label_color.get(1) / 255.0, + *s.label_color.get(2) / 255.0, + ], + button_color: [ + *s.button_color.get(0) / 255.0, + *s.button_color.get(1) / 255.0, + *s.button_color.get(2) / 255.0, + ], + text_dark_color: [ + *s.text_dark_color.get(0) / 255.0, + *s.text_dark_color.get(1) / 255.0, + *s.text_dark_color.get(2) / 255.0, + ], + text_light_color: [ + *s.text_light_color.get(0) / 255.0, + *s.text_light_color.get(1) / 255.0, + *s.text_light_color.get(2) / 255.0, ], } } @@ -196,7 +243,7 @@ impl SettingsInJson { tile_width: 4, tile_height: 4, tile_size: 72.0, - tile_padding: 12.0, + tile_padding: 16.0, tile_background_color: vec![187.0, 173.0, 160.0], tiles_colors: tiles_colors, tile_unknow_color: vec![200.0, 0.0, 0.0], @@ -220,7 +267,9 @@ impl SettingsInJson { let exe_path = exe_path.unwrap(); let path = exe_path.join(Path::new(SETTING_FILENAME)); if !path.exists() || !path.is_file() { - return SettingsInJson::default_settings(); + let default = SettingsInJson::default_settings(); + default.save(); + return default; } let file = File::open(&path).unwrap(); let mut reader = BufferedReader::new(file); diff --git a/src/tile.rs b/src/tile.rs index 7217617..64ed3c7 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -2,7 +2,7 @@ use graphics::*; use piston::*; use number_renderer::NumberRenderer; -use settings; +use settings::Settings; #[deriving(Clone, Eq)] pub enum TileState { @@ -16,49 +16,55 @@ pub enum TileState { } #[deriving(Clone)] -pub struct Tile { +pub struct Tile<'a> { pub score: int, pub tile_x: int, pub tile_y: int, pub status: TileState, + + settings: &'a Settings, } -impl Tile { - pub fn new(score: int, tile_x: int, tile_y: int) -> Tile { +impl<'a> Tile<'a> { + pub fn new(settings: &'a Settings, score: int, tile_x: int, tile_y: int) -> Tile<'a> { Tile { score: score, tile_x: tile_x, tile_y: tile_y, - status: TileNew(settings::TILE_NEW_TIME, 0.0), + status: TileNew(settings.tile_new_time, 0.0), + + settings: settings, } } - pub fn new_combined(score: int, tile_x: int, tile_y: int) -> Tile { + pub fn new_combined(settings: &'a Settings, score: int, tile_x: int, tile_y: int) -> Tile<'a> { Tile { score: score, tile_x: tile_x, tile_y: tile_y, - status: TileCombine(settings::TILE_COMBINE_TIME, 1.2 * settings::TILE_SIZE), + status: TileCombine(settings.tile_combine_time, 1.2 * settings.tile_size), + + settings: settings, } } - fn tile_to_pos(tile_x: int, tile_y: int) -> (f64, f64) { - let x = settings::BOARD_PADDING + tile_x as f64 * settings::TILE_SIZE + (tile_x + 1) as f64 * settings::TILE_PADDING; - let y = settings::BOARD_PADDING + settings::BOARD_OFFSET_Y + tile_y as f64 * settings::TILE_SIZE + (tile_y + 1) as f64 * settings::TILE_PADDING; + fn tile_to_pos(&self, tile_x: int, tile_y: int) -> (f64, f64) { + let x = self.settings.board_padding + tile_x as f64 * self.settings.tile_size + (tile_x + 1) as f64 * self.settings.tile_padding; + let y = self.settings.board_padding + self.settings.board_offset_y + tile_y as f64 * self.settings.tile_size + (tile_y + 1) as f64 * self.settings.tile_padding; (x, y) } pub fn start_moving(&mut self, destination_tile_x: int, destination_tile_y: int) { match self.status { TileMoving(_, _, _, ox, oy) => { - let (x, y) = Tile::tile_to_pos(ox, oy); - self.status = TileMoving(settings::TILE_MOVE_TIME, x, y, ox, oy); + let (x, y) = self.tile_to_pos(ox, oy); + self.status = TileMoving(self.settings.tile_move_time, x, y, ox, oy); self.tile_x = destination_tile_x; self.tile_y = destination_tile_y; }, TileStatic => { - let (x, y) = Tile::tile_to_pos(self.tile_x, self.tile_y); - self.status = TileMoving(settings::TILE_MOVE_TIME, x, y, self.tile_x, self.tile_y); + let (x, y) = self.tile_to_pos(self.tile_x, self.tile_y); + self.status = TileMoving(self.settings.tile_move_time, x, y, self.tile_x, self.tile_y); self.tile_x = destination_tile_x; self.tile_y = destination_tile_y; }, @@ -72,7 +78,7 @@ impl Tile { if dt >= t { self.status = TileStatic; } else { - let (dx, dy) = Tile::tile_to_pos(self.tile_x, self.tile_y); + let (dx, dy) = self.tile_to_pos(self.tile_x, self.tile_y); let factor = dt / t; self.status = TileMoving(t - dt, x + factor * (dx - x), y + factor * (dy - y), ox, oy); } @@ -82,7 +88,7 @@ impl Tile { self.status = TileStatic; } else { let factor = dt / t; - self.status = TileNew(t - dt, size + factor * (settings::TILE_SIZE - size)); + self.status = TileNew(t - dt, size + factor * (self.settings.tile_size - size)); } }, TileCombine(t, size) => { @@ -90,7 +96,7 @@ impl Tile { self.status = TileStatic; } else { let factor = dt / t; - self.status = TileCombine(t - dt, size + factor * (settings::TILE_SIZE - size)); + self.status = TileCombine(t - dt, size + factor * (self.settings.tile_size - size)); } }, _ => {}, @@ -98,8 +104,8 @@ impl Tile { } pub fn render(&self, number_renderer: &NumberRenderer, c: &Context, gl: &mut Gl) { - let mut pos = Tile::tile_to_pos(self.tile_x, self.tile_y); - let mut size = (settings::TILE_SIZE, settings::TILE_SIZE); + let mut pos = self.tile_to_pos(self.tile_x, self.tile_y); + let mut size = (self.settings.tile_size, self.settings.tile_size); match self.status { TileMoving(_, x, y, _, _) => { pos = (x, y); @@ -116,25 +122,25 @@ impl Tile { let (w, h) = size; let color = self.get_color(); c.view() - .rect_centered(x + settings::TILE_SIZE / 2.0, - y + settings::TILE_SIZE / 2.0, + .rect_centered(x + self.settings.tile_size / 2.0, + y + self.settings.tile_size / 2.0, w / 2.0, h / 2.0) - .rgba(color[0], color[1], color[2], color[3]).fill(gl); + .rgba(color[0], color[1], color[2], 1.0).fill(gl); let color = if self.score >= 8 { - settings::TEXT_LIGHT_COLOR + self.settings.text_light_color } else { - settings::TEXT_DARK_COLOR + self.settings.text_dark_color }; - number_renderer.render(self.score as u32, x + settings::TILE_SIZE / 2.0, y + settings::TILE_SIZE / 2.0, settings::TILE_SIZE, color, c, gl); + number_renderer.render(self.score as u32, x + self.settings.tile_size / 2.0, y + self.settings.tile_size / 2.0, self.settings.tile_size, color, c, gl); } - fn get_color(&self) -> [f32, ..4] { + fn get_color(&self) -> [f32, ..3] { let i = (self.score as f64).log2() as uint; - if i > 0 && i < settings::TILES_COLOR.len() { - settings::TILES_COLOR[i] + if i > 0 && i < self.settings.tiles_colors.len() { + *self.settings.tiles_colors.get(i) } else { - settings::TILE_UNKNOW_COLOR + self.settings.tile_unknow_color } } }