Can move tiles left/right

This commit is contained in:
Coeuvre 2014-05-21 14:09:51 +08:00
parent 57b9c1d04d
commit 1e9e8ac303
5 changed files with 181 additions and 42 deletions

View file

@ -27,6 +27,8 @@ impl Game for App {
} }
fn load(&mut self, _asset_store: &mut AssetStore) { fn load(&mut self, _asset_store: &mut AssetStore) {
self.board.generate_tile();
self.board.generate_tile();
} }
fn key_press( fn key_press(
@ -35,10 +37,10 @@ impl Game for App {
_asset_store: &mut AssetStore _asset_store: &mut AssetStore
) { ) {
if key == keyboard::Left { if key == keyboard::Left {
self.board.test_tile.start_moving(settings::TILE_MOVE_TIME, 0, 0); self.board.merge_from_right_to_left();
} }
if key == keyboard::Right { if key == keyboard::Right {
self.board.test_tile.start_moving(settings::TILE_MOVE_TIME, 3, 0); self.board.merge_from_left_to_right();
} }
} }

View file

@ -1,37 +1,177 @@
use std::iter::range_step;
use rand::random;
use graphics::*; use graphics::*;
use piston::*; use piston::*;
use settings; use settings;
use tile::Tile; use tile::{
Tile,
TileStatic,
};
pub struct Board { pub struct Board {
center: [f64, ..2], tiles: Vec<Tile>,
tiles: [[Option<Tile>, ..settings::TILE_WIDTH], ..settings::TILE_HEIGHT],
pub test_tile: Tile,
} }
impl Board { impl Board {
pub fn new() -> Board { pub fn new() -> Board {
Board { Board {
center: [0.0, 0.0], tiles: Vec::<Tile>::new(),
tiles: [ }
[None, None, None, None], }
[None, None, None, None],
[None, None, None, None], pub fn generate_tile(&mut self) {
[None, None, None, None], if self.tiles.len() == (settings::TILE_WIDTH * settings::TILE_HEIGHT) as uint {
], return;
test_tile: Tile::new(16, 0, 0), }
'generating: loop {
let x = (random::<uint>() % settings::TILE_WIDTH as uint) as int;
let y = (random::<uint>() % settings::TILE_HEIGHT as uint) as int;
if self.get_tile(x, y).is_none() {
self.tiles.push(Tile::new(2, x, y));
break;
}
} }
} }
pub fn update(&mut self, dt: f64) { pub fn update(&mut self, dt: f64) {
self.test_tile.update(dt); for tile in self.tiles.mut_iter() {
tile.update(dt);
}
} }
pub fn render(&self, c: &Context, gl: &mut Gl) { pub fn render(&self, c: &Context, gl: &mut Gl) {
self.render_board(c, gl); self.render_board(c, gl);
self.render_tiles(c, gl); self.render_tiles(c, gl);
self.test_tile.render(c, gl); }
pub fn can_merge(&self) -> bool {
for row in range(0, settings::TILE_HEIGHT) {
if !self.can_merge_row(row) {
return false;
}
}
true
}
pub fn merge_from_left_to_right(&mut self) {
self.merge_row(settings::TILE_WIDTH - 1, -1, -1);
}
pub fn merge_from_right_to_left(&mut self) {
self.merge_row(0, settings::TILE_WIDTH, 1);
}
fn merge_row(&mut self, x_start: int, x_end: int, x_step: int) {
if self.is_locking() {
return;
}
// move all tiles to right place
for row in range(0, settings::TILE_HEIGHT) {
for col in range_step(x_start, x_end, x_step) {
match self.get_mut_tile(col, row) {
None => {
match self.get_mut_next_tile(col, row, x_step, 0) {
Some(ref mut tile) => {
tile.start_moving(col, row);
},
_ => {},
}
},
_ => {},
}
}
}
// merge
self.generate_tile();
}
fn can_merge_row(&self, row: int) -> bool {
for col in range(0, settings::TILE_WIDTH) {
match self.get_tile(col, row) {
Some(ref tile) => {
match self.get_next_tile(tile.tile_x, tile.tile_y, 1, 0) {
Some(ref s_tile) => {
if tile.score == s_tile.score {
return true;
}
},
_ => {},
}
},
None => {},
}
}
false
}
fn is_locking(&self) -> bool {
for tile in self.tiles.iter() {
if tile.status != TileStatic {
return true;
}
}
false
}
/// 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> {
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 {
let tile = self.get_tile(x, y);
if tile.is_some() {
return tile;
}
x += step_x;
y += step_y;
}
None
}
fn get_mut_next_tile<'a>(&'a mut self, x: int, y: int, step_x: int, step_y: int) -> Option<&'a mut Tile> {
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 {
let tile = self.get_tile(x, y);
if tile.is_some() {
found = true;
break;
}
x += step_x;
y += step_y;
}
if found {
self.get_mut_tile(x, y)
} else {
None
}
}
fn get_tile<'a>(&'a self, x: int, y: int) -> Option<&'a Tile> {
for tile in self.tiles.iter() {
if tile.tile_x == x && tile.tile_y == y {
return Some(tile);
}
}
None
}
fn get_mut_tile<'a>(&'a mut self, x: int, y: int) -> Option<&'a mut Tile> {
for tile in self.tiles.mut_iter() {
if tile.tile_x == x && tile.tile_y == y {
return Some(tile);
}
}
None
} }
fn render_board(&self, c: &Context, gl: &mut Gl) { fn render_board(&self, c: &Context, gl: &mut Gl) {
@ -70,7 +210,7 @@ impl Board {
fn render_tiles(&self, c: &Context, gl: &mut Gl) { fn render_tiles(&self, c: &Context, gl: &mut Gl) {
for row in range(0, settings::TILE_HEIGHT) { for row in range(0, settings::TILE_HEIGHT) {
for col in range(0, settings::TILE_WIDTH) { for col in range(0, settings::TILE_WIDTH) {
match self.tiles[row][col] { match self.get_tile(col, row) {
Some(ref tile) => { Some(ref tile) => {
tile.render(c, gl); tile.render(c, gl);
}, },

View file

@ -1,6 +1,7 @@
#![feature(globs)] #![feature(globs)]
extern crate collections;
extern crate rand; extern crate rand;
extern crate graphics; extern crate graphics;

View file

@ -14,8 +14,8 @@ pub static BOARD_SIZE: [f64, ..2] = [
]; ];
pub static BOARD_OFFSET_Y: f64 = 128.0; pub static BOARD_OFFSET_Y: f64 = 128.0;
pub static TILE_WIDTH: uint = 4; pub static TILE_WIDTH: int = 4;
pub static TILE_HEIGHT: uint = 4; pub static TILE_HEIGHT: int = 4;
pub static TILE_SIZE: f64 = 96.0; pub static TILE_SIZE: f64 = 96.0;
pub static TILE_PADDING: f64 = 16.0; pub static TILE_PADDING: f64 = 16.0;
pub static TILE_BACKGROUND_COLOR: [f32, ..4] = [187.0 / 255.0, 173.0 / 255.0, 160.0 / 255.0, 1.0]; pub static TILE_BACKGROUND_COLOR: [f32, ..4] = [187.0 / 255.0, 173.0 / 255.0, 160.0 / 255.0, 1.0];

View file

@ -3,17 +3,18 @@ use graphics::*;
use piston::*; use piston::*;
use settings; use settings;
enum TileState { #[deriving(Eq)]
pub enum TileState {
TileStatic, TileStatic,
/// (t, x, y, destination_tile_x, destination_tile_y) /// (t, x, y)
TileMoving(f64, f64, f64, int, int), TileMoving(f64, f64, f64),
} }
pub struct Tile { pub struct Tile {
score: int, pub score: int,
tile_x: int, pub tile_x: int,
tile_y: int, pub tile_y: int,
status: TileState, pub status: TileState,
} }
impl Tile { impl Tile {
@ -32,27 +33,22 @@ impl Tile {
(x, y) (x, y)
} }
pub fn start_moving(&mut self, t: f64, destination_tile_x: int, destination_tile_y: int) { pub fn start_moving(&mut self, destination_tile_x: int, destination_tile_y: int) {
match self.status {
TileStatic => {
let (x, y) = Tile::tile_to_pos(self.tile_x, self.tile_y); let (x, y) = Tile::tile_to_pos(self.tile_x, self.tile_y);
self.status = TileMoving(t, x, y, destination_tile_x, destination_tile_y); self.status = TileMoving(settings::TILE_MOVE_TIME, x, y);
}, self.tile_x = destination_tile_x;
_ => {}, self.tile_y = destination_tile_y;
}
} }
pub fn update(&mut self, dt: f64) { pub fn update(&mut self, dt: f64) {
match self.status { match self.status {
TileMoving(t, x, y, dtx, dty) => { TileMoving(t, x, y) => {
if dt >= t { if dt >= t {
self.tile_x = dtx;
self.tile_y = dty;
self.status = TileStatic; self.status = TileStatic;
} else { } else {
let (dx, dy) = Tile::tile_to_pos(dtx, dty); let (dx, dy) = Tile::tile_to_pos(self.tile_x, self.tile_y);
let factor = dt / t; let factor = dt / t;
self.status = TileMoving(t - dt, x + factor * (dx - x), y + factor * (dy - y), dtx, dty); self.status = TileMoving(t - dt, x + factor * (dx - x), y + factor * (dy - y));
} }
}, },
TileStatic => {}, TileStatic => {},
@ -62,12 +58,12 @@ impl Tile {
pub fn render(&self, c: &Context, gl: &mut Gl) { pub fn render(&self, c: &Context, gl: &mut Gl) {
let mut pos = (0.0, 0.0); let mut pos = (0.0, 0.0);
match self.status { match self.status {
TileMoving(_, x, y) => {
pos = (x, y);
},
TileStatic => { TileStatic => {
pos = Tile::tile_to_pos(self.tile_x, self.tile_y); pos = Tile::tile_to_pos(self.tile_x, self.tile_y);
}, },
TileMoving(_, x, y, _, _) => {
pos = (x, y);
}
} }
let (x, y) = pos; let (x, y) = pos;
let color = self.get_color(); let color = self.get_color();