rust-2048/src/tile.rs

147 lines
4.8 KiB
Rust

use graphics::*;
use piston::*;
use number_renderer::NumberRenderer;
use settings::Settings;
#[deriving(Clone, PartialEq)]
pub enum TileState {
TileStatic,
/// (t, x, y, origin_x, origin_x)
TileMoving(f64, f64, f64, int, int),
/// (t, size)
TileNew(f64, f64),
/// (t, size)
TileCombine(f64, f64),
}
#[deriving(Clone)]
pub struct Tile<'a> {
pub score: int,
pub tile_x: int,
pub tile_y: int,
pub status: TileState,
settings: &'a Settings,
}
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),
settings: settings,
}
}
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),
settings: settings,
}
}
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) = 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) = 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;
},
_ => {},
}
}
pub fn update(&mut self, dt: f64) {
match self.status {
TileMoving(t, x, y, ox, oy) => {
if dt >= t {
self.status = TileStatic;
} else {
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);
}
},
TileNew(t, size) => {
if dt >= t {
self.status = TileStatic;
} else {
let factor = dt / t;
self.status = TileNew(t - dt, size + factor * (self.settings.tile_size - size));
}
},
TileCombine(t, size) => {
if dt >= t {
self.status = TileStatic;
} else {
let factor = dt / t;
self.status = TileCombine(t - dt, size + factor * (self.settings.tile_size - size));
}
},
_ => {},
}
}
pub fn render(&self, number_renderer: &NumberRenderer, c: &Context, gl: &mut Gl) {
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);
},
TileNew(_, s) => {
size = (s, s);
},
TileCombine(_, s) => {
size = (s, s);
},
_ => {},
}
let (x, y) = pos;
let (w, h) = size;
let color = self.get_color();
c.view()
.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], 1.0).draw(gl);
let color = if self.score >= 8 {
self.settings.text_light_color
} else {
self.settings.text_dark_color
};
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, ..3] {
let i = (self.score as f64).log2() as uint;
if i > 0 && i < self.settings.tiles_colors.len() {
*self.settings.tiles_colors.get(i)
} else {
self.settings.tile_unknow_color
}
}
}