当前位置: 首页 > news >正文

株洲seo网站优化瓷砖网站模板

株洲seo网站优化,瓷砖网站模板,长安网站建设哪家好,南阳网站怎么推广tetris-demo A Tetris example written in Rust using Piston in under 500 lines of code 项目地址: https://gitcode.com/gh_mirrors/te/tetris-demo 项目介绍 Tetris Example in Rust, v2 是一个用Rust语言编写的俄罗斯方块游戏示例。这个项目不仅是一个简单… tetris-demo A Tetris example written in Rust using Piston in under 500 lines of code 项目地址: https://gitcode.com/gh_mirrors/te/tetris-demo 项目介绍 Tetris Example in Rust, v2 是一个用Rust语言编写的俄罗斯方块游戏示例。这个项目不仅是一个简单的游戏实现更是一个展示Rust编程基础的绝佳范例。通过414行代码开发者可以深入了解Rust的基本语法和编程思想。此外项目还提供了一个清晰的Git历史记录展示了功能的逐步迭代过程非常适合初学者和有经验的开发者学习参考。 完整代码 use piston_window::{WindowSettings, PistonWindow, Event, RenderEvent, PressEvent}; use piston_window::{Rectangle, DrawState, Context, Graphics}; use piston_window::{Button, Key};use rand::Rng;use std::time::{Duration, Instant}; use std::collections::HashMap;enum DrawEffecta {None,Darker,Flash(a Veci8), }#[derive(Copy, Clone)] enum Color {Red, Green, Blue, Magenta, Cyan, Yellow, Orange, }#[derive(Default, Clone)] struct Board(HashMap(i8, i8), Color);impl Board {fn new(v: [(i8, i8)], color: Color) - Self {Board(v.iter().cloned().map(|(x, y)| ((x, y), color)).collect())}fn modifiedF(self, f: F) - Selfwhere F: Fn((i8, i8)) - (i8, i8){Board(self.0.iter().map(|((x, y), color)| (f((*x, *y)), *color)).collect())}fn modified_filterF(self, f: F) - Selfwhere F: Fn((i8, i8)) - Option(i8, i8){Board(self.0.iter().filter_map(|((x, y), color)| f((*x, *y)).map(|p| (p, *color))).collect())}fn transposed(self) - Self {self.modified(|(ox, oy)| (oy, ox))}fn mirrored_y(self) - Self {self.modified(|(ox, oy)| (ox, -oy))}fn rotated(self) - Self {self.mirrored_y().transposed()}fn rotated_counter(self) - Self {self.rotated().rotated().rotated()}fn negative_shift(self) - (i8, i8) {use std::cmp::min;self.0.keys().into_iter().cloned().fold((0, 0), |(mx, my), (ox, oy)| (min(mx, ox), min(my, oy)))}fn shifted(self, (x, y): (i8, i8)) - Self {self.modified(|(ox, oy)| (ox x, oy y))}fn merged(self, other: Board) - OptionSelf {let mut hashmap HashMap::new();hashmap.extend(other.0.iter());hashmap.extend(self.0.iter());if hashmap.len() ! self.0.len() other.0.len() {return None;}Some(Self(hashmap))}fn contained(self, x: i8, y: i8) - bool {self.0.keys().into_iter().cloned().fold(true, |b, (ox, oy)| b ox x oy y ox 0 oy 0)}fn whole_lines(self, x: i8, y: i8) - Veci8 {let mut idxs vec![];for oy in 0 .. y {if (0 .. x).filter_map(|ox| self.0.get((ox, oy))).count() x as usize {idxs.push(oy)}}idxs}fn kill_line(self, y: i8) - Self {self.modified_filter(|(ox, oy)|if oy y {Some((ox, oy))} else if oy y {None} else {Some((ox, oy 1))})}fn rendera, G(self,metrics: Metrics,c: Context,g: mut G,draw_effect: DrawEffecta,)where G: Graphics{let mut draw |color, rect: [f64; 4]| {Rectangle::new(color).draw(rect, DrawState::default(), c.transform, g);};for x in 0 .. metrics.board_x {for y in 0 .. metrics.board_y {let block_pixels metrics.block_pixels as f64;let border_size block_pixels / 20.0;let outer [block_pixels * (x as f64), block_pixels * (y as f64), block_pixels, block_pixels];let inner [outer[0] border_size, outer[1] border_size,outer[2] - border_size * 2.0, outer[3] - border_size * 2.0];draw([0.2, 0.2, 0.2, 1.0], outer);draw([0.1, 0.1, 0.1, 1.0], inner);if let Some(color) self.0.get((x as i8, y as i8)) {let code match color {Color::Red [1.0, 0.0, 0.0, 1.0],Color::Green [0.0, 1.0, 0.0, 1.0],Color::Blue [0.5, 0.5, 1.0, 1.0],Color::Magenta [1.0, 0.0, 1.0, 1.0],Color::Cyan [0.0, 1.0, 1.0, 1.0],Color::Yellow [1.0, 1.0, 0.0, 1.0],Color::Orange [1.0, 0.5, 0.0, 1.0],};draw(code, outer);let code [code[0]*0.8, code[1]*0.8, code[2]*0.8, code[3]];draw(code, inner);}match draw_effect {DrawEffect::None {},DrawEffect::Flash(lines) {if lines.contains((y as i8)) {draw([1.0, 1.0, 1.0, 0.5], outer);}}DrawEffect::Darker {draw([0.0, 0.0, 0.0, 0.9], outer);}}}}} }#[derive(Default)] struct Metrics {block_pixels: usize,board_x: usize,board_y: usize, }impl Metrics {fn resolution(self) - [u32; 2] {[(self.board_x * self.block_pixels) as u32,(self.board_y * self.block_pixels) as u32]} }enum State {Flashing(isize, Instant, Veci8),Falling(Board),GameOver, }struct Game {board: Board,metrics: Metrics,state: State,shift: (i8, i8),possible_pieces: VecBoard,time_since_fall: Instant, }impl Game {fn new(metrics: Metrics) - Self {Self {metrics,board: Default::default(),state: State::Falling(Default::default()),time_since_fall: Instant::now(),shift: (0, 0),possible_pieces: vec![Board::new([(0, 0), (0, 1), (1, 0), (1, 1), ][..], Color::Red),Board::new([(0, 0), (1, 0), (1, 1), (2, 0), ][..], Color::Green),Board::new([(0, 0), (1, 0), (2, 0), (3, 0), ][..], Color::Blue),Board::new([(0, 0), (1, 0), (2, 0), (0, 1), ][..], Color::Orange),Board::new([(0, 0), (1, 0), (2, 0), (2, 1), ][..], Color::Yellow),Board::new([(0, 0), (1, 0), (1, 1), (2, 1), ][..], Color::Cyan),Board::new([(1, 0), (2, 0), (0, 1), (1, 1), ][..], Color::Magenta),]}}fn new_falling(mut self) {let mut rng rand::thread_rng();let idx rng.gen_range(0, self.possible_pieces.len());self.state State::Falling(self.possible_pieces[idx].clone());self.shift (0, 0);if self.board.merged(self.falling_shifted()).is_none() {self.state State::GameOver;} else {for _ in 0 .. rng.gen_range(0, 4usize) {self.rotate(false)}}}fn render(self, window: mut PistonWindow, event: Event) {window.draw_2d(event, |c, g, _| {let (board, draw_effect) match self.state {State::Flashing(stage, _, lines) {let draw_effect if *stage % 2 0 {DrawEffect::None} else {DrawEffect::Flash(lines)};(self.board.clone(), draw_effect)}State::GameOver (self.board.clone(), DrawEffect::Darker),State::Falling(_) (self.board.merged(self.falling_shifted()).unwrap(), DrawEffect::None),};board.render(self.metrics, c, g, draw_effect);});}fn falling_shifted(self) - Board {match self.state {State::Falling(state_falling) {state_falling.shifted(self.shift)}State::GameOver { .. } panic!(),State::Flashing { .. } panic!(),}}fn progress(mut self) {match mut self.state {State::Falling(_) {if self.time_since_fall.elapsed() Duration::from_millis(700) {return;}self.move_falling(0, 1);self.time_since_fall Instant::now();}State::Flashing(stage, last_stage_switch, lines) {if last_stage_switch.elapsed() Duration::from_millis(50) {return;}if *stage 18 {*stage 1;*last_stage_switch Instant::now();return;} else {for idx in lines {self.board self.board.kill_line(*idx);}self.new_falling()}}State::GameOver { } {},}}fn move_falling(mut self, x: i8, y: i8) {let falling self.falling_shifted().shifted((x, y));let merged self.board.merged(falling);let contained falling.contained(self.metrics.board_x as i8,self.metrics.board_y as i8);if merged.is_some() contained {// Allow the movementself.shift.0 x;self.shift.1 y;return}if let (0, 1) (x, y) {self.board self.board.merged(self.falling_shifted()).unwrap();let completed self.board.whole_lines(self.metrics.board_x as i8,self.metrics.board_y as i8);if completed.is_empty() {self.new_falling();} else {self.state State::Flashing(0, Instant::now(), completed);}}}fn on_press(mut self, args: Button) {match args {Button::Keyboard(key) { self.on_key(key); }_ {},}}fn on_key(mut self, key: Key) {match mut self.state {State::Flashing {..} {},State::Falling {..} {let movement match key {Key::Right Some((1, 0)),Key::Left Some((-1, 0)),Key::Down Some((0, 1)),_ None,};if let Some(movement) movement {self.move_falling(movement.0, movement.1);return;}match key {Key::Up self.rotate(false),Key::NumPad5 self.rotate(true),_ return,}}State::GameOver { } {match key {Key::Return {self.board.0.clear();self.new_falling();},_ return,}},}}fn rotate(mut self, counter: bool) {match mut self.state {State::Falling(state_falling) {let rotated if counter {state_falling.rotated()} else {state_falling.rotated_counter()};let (x, y) rotated.negative_shift();let falling rotated.shifted((-x, -y));for d in [(0, 0), (-1, 0)] {let mut shift self.shift;shift.0 d.0;shift.1 d.1;if let Some(merged) self.board.merged(falling.shifted(shift)) {if merged.contained(self.metrics.board_x as i8,self.metrics.board_y as i8){// Allow the rotation*state_falling falling;self.shift shift;return}}}}State::GameOver {..} panic!(),State::Flashing {..} panic!(),}} }fn main() {let metrics Metrics {block_pixels: 20,board_x: 8,board_y: 20,};let mut window: PistonWindow WindowSettings::new(Tetris, metrics.resolution()).exit_on_esc(true).build().unwrap();let mut game Game::new(metrics);game.new_falling();while let Some(e) window.next() {game.progress();if let Some(_) e.render_args() {game.render(mut window, e);}if let Some(args) e.press_args() {game.on_press(args);}} }以下是将上述代码拆分为几段并分别给出注释的内容 1. 导入相关库和模块 rust // 导入 piston_window 库中的相关模块用于创建游戏窗口、处理事件、图形绘制等功能 use piston_window::{WindowSettings, PistonWindow, Event, RenderEvent, PressEvent}; use piston_window::{Rectangle, DrawState, Context, Graphics}; use piston_window::{Button, Key};// 导入 rand 库用于生成随机数 use rand::Rng;// 导入标准库中用于处理时间的模块 use std::time::{Duration, Instant}; // 导入标准库中用于处理哈希表数据结构的模块 use std::collections::HashMap;这段代码主要是导入了实现俄罗斯方块游戏所需的各种库和模块。piston_window相关模块用于创建游戏窗口、处理窗口事件以及进行图形绘制等操作。rand库用于生成随机数以便在游戏中随机生成方块形状等。std::time中的Duration和Instant用于处理时间相关的操作比如控制方块下落的时间间隔等。HashMap则用于存储游戏板上方块的位置和颜色等信息。 2. 定义绘制效果和颜色枚举 rust // DrawEffect 枚举定义了绘制方块时可能的效果 // a 是生命周期参数用于确保引用的有效性 enum DrawEffecta {// 无特殊绘制效果None,// 使方块颜色变深的绘制效果Darker,// 使指定行的方块闪烁的绘制效果接受一个 i8 类型向量的引用Flash(a Veci8), }// Color 枚举定义了方块可能的颜色 #[derive(Copy, Clone)] enum Color {Red, Green, Blue, Magenta, Cyan, Yellow, Orange, }这里定义了两个枚举类型。DrawEffect枚举用于指定在绘制游戏板上的方块时可能采用的不同效果比如无效果、颜色变深或者使某些行的方块闪烁等。Color枚举则明确了方块可能出现的各种颜色以便在游戏中区分不同的方块形状或状态。 3. 定义游戏板结构体及相关方法 rust // Board 结构体用于表示游戏板的状态 // 它包含一个 HashMap用于存储游戏板上每个方块的位置以 (i8, i8) 坐标表示和对应的颜色 #[derive(Default, Clone)] struct Board(HashMap(i8, i8), Color);// Board 结构体的实现块包含了一系列处理游戏板相关操作的方法 impl Board {// new 方法用于创建一个新的 Board 实例// 接受一个坐标切片 v 和一个颜色 color将每个坐标位置设置为指定的颜色fn new(v: [(i8, i8)], color: Color) - Self {Board(v.iter().cloned().map(|(x, y)| ((x, y), color)).collect())}// modified 方法根据传入的函数 f 对游戏板上的每个方块位置进行变换// f 函数接受一个坐标并返回一个新的坐标用于修改方块在游戏板上的位置fn modifiedF(self, f: F) - Selfwhere F: Fn((i8, i8)) - (i8, i8){Board(self.0.iter().map(|((x, y), color)| (f((*x, *y)), *color)).collect())}// modified_filter 方法根据传入的函数 f 对游戏板上的方块位置进行过滤和变换// f 函数接受一个坐标并返回一个可选的新坐标如果返回 Some则保留该方块并应用变换如果返回 None则移除该方块fn modified_filterF(self, f: F) - Selfwhere F: Fn((i8, i8)) - Option(i8, i8){Board(self.0.iter().filter_map(|((x, y), color)| f((*x, y)).map(|p| (p, *color))).collect())}// transposed 方法用于对游戏板进行转置操作即将 x 与 y 坐标互换fn transposed(self) - Self {self.modified(|(ox, oy)| (oy, ox))}// mirrored_y 方法用于对游戏板在 y 轴上进行镜像翻转操作即将 y 坐标取反fn mirrored_y(self) - Self {self.modified(|(ox, oy)| (ox, -oy))}// rotated 方法用于对游戏板进行顺时针旋转操作// 先在 y 轴上镜像翻转然后再进行转置操作来实现旋转效果fn rotated(self) - Self {self.mirrored_y().transposed()}// rotated_counter 方法用于对游戏板进行逆时针旋转操作// 通过连续三次调用 rotated 方法来实现逆时针旋转效果fn rotated_counter(self) - Self {self.rotated().rotated().rotated()}// negative_shift 方法用于获取游戏板上所有方块位置的最小 x 和 y 坐标值// 返回一个 (i8, i8) 类型的元组表示最小的偏移量fn negative_shift(self) - (i8, i8) {use std::cmp::min;self.0.keys().into_iter().cloned().fold((0, 0), |(mx, my), (ox, oy)| (min(mx, ox), min(my, oy)))}// shifted 方法用于根据传入的偏移量 (x, y) 对游戏板上的所有方块位置进行平移操作fn shifted(self, (x, y): (i8, y)) - Self {self.modified(|(ox, oy)| (ox x, oy y))}// merged 方法用于将当前游戏板与另一个游戏板 other 进行合并操作// 如果合并后的哈希表长度不等于两个游戏板原来哈希表长度之和说明有位置冲突返回 None否则返回合并后的新游戏板 Some(Self)fn merged(self, other: Board) - OptionSelf {let mut hashmap HashMap::new();hashmap.extend(other.0.iter());hashmap.extend(self.0.iter());if hashmap.len()! self.0.len() other.0.len() {return None;}Some(Self(hashmap))}// contained 方法用于检查给定的坐标 (x, y) 是否在游戏板的有效范围内// 如果所有方块的坐标都满足小于 x 且小于 y且大于等于 0则返回 true否则返回 falsefn contained(self, x: i8, y: i8) - bool {self.0.keys().into_iter().cloned().fold(true, |b, (ox, oy)| b ox x oy y ox 0 oy 0)}// whole_lines 方法用于查找游戏板上给定范围内完整的行// 遍历 y 坐标从 0 到 y - 1 的行对于每一行如果该行在 x 坐标从 0 到 x - 1 的范围内所有方块都存在通过 filter_map 和 count 来判断则将该行的 y 坐标添加到结果向量中fn whole_lines(self, x: i8, y: i8) - Veci8 {let mut idxs vec![];for oy in 0.. y {if (0.. x).filter_map(|ox| self.0.get((ox, oy))).count() x as usize {idxs.push(oy)}}idxs}// kill_line 方法用于清除游戏板上指定的行 y// 通过 modified_filter 方法根据条件对游戏板上的方块位置进行过滤保留不在指定行 y 的方块并将在指定行上方的方块 y 坐标加 1从而实现清除行的效果fn kill_line(self, y: i8) - Self {self.modified_filter(|(ox, oy)|if oy y {Some((ox, oy))} else if oy y {None} else {Some((ox, oy 1))})}// render 方法用于在给定的图形上下文 c 和图形绘制对象 g 下根据指定的绘制效果 draw_effect 绘制游戏板// 遍历游戏板的每个方块位置根据是否有方块以及方块的颜色按照不同的绘制效果进行绘制操作fn rendera, G(self,metrics: Metrics,c: Context,g: mut G,draw_effect: DrawEffecta,)where G: Graphics{let mut draw |color, rect: [f64; 4]| {Rectangle::new(color).draw(rect, DrawState::default(), c.transform, g);};for x in 0.. metrics.board_x {for y in 0.. metrics.board_y {let block_pixels metrics.block_pixels as f64;let border_size block_pixels / 20.0;let outer [block_pixels * (x as f64), block_pixels * (y as f64), block_pixels, block_pixels];let inner [outer[0] border_size, outer[1] border_size,outer[2] - border_size * 2.0, outer[3] - border_size * 2.0];draw([0.2, 0.2, 0.2, 1.0], outer);draw([0.1, 0.1, 0.1, 1.0], inner);if let Some(color) self.0.get((x as i8, y as i8)) {let code match color {Color::Red [1.0, 0.0, 0.0, 1.0],Color::Green [0.0, 1.0, 0.0, 1.0],Color::Blue [0.5, 0.5, 1.0, 1.0],Color::Magenta [1.0, 0.0, 1.0, 1.0],Color::Cyan [0.0, 1.0, 1.0, 1.0],Color::Yellow [1.0, 1.0, 0.0, 1.0],Color::Orange [1.0, 0.5, 0.0, 1.0],};draw(code, outer);let code [code[0]*0.8, code[1]*0.8, code[2]*0.8, code[3]];draw(code, inner);}match draw_effect {DrawEffect::None {},DrawEffect::Flash(lines) {if lines.contains((y as i8)) {draw([1.0, 1.0, 1.0, 0.5], outer);}}DrawEffect::Darker {draw([0.0, 0.0, 0.0, 0.9], outer);}}}}} }这部分代码定义了Board结构体来表示游戏板的状态其中使用HashMap存储每个方块在游戏板上的位置和对应的颜色。同时为Board结构体实现了一系列方法用于对游戏板进行各种操作比如创建新的游戏板实例、对游戏板上的方块位置进行变换平移、旋转、翻转等、合并两个游戏板、检查坐标是否在游戏板范围内、查找完整的行以及清除指定行等并且还实现了绘制游戏板的方法根据不同的绘制效果和方块颜色进行绘制。 4. 定义游戏度量结构体及相关方法 rust // Metrics 结构体用于存储游戏的一些度量信息如每个方块的像素大小、游戏板的行数和列数等 #[derive(Default)] struct Metrics {block_pixels: usize,board_x: usize,board_y: usize, }// Metrics 结构体的实现块包含了一个用于计算游戏窗口分辨率的方法 impl Metrics {// resolution 方法根据游戏板的行数、列数和每个方块的像素大小计算并返回游戏窗口的分辨率以 [u32; 2] 类型的数组表示分别为宽度和高度fn resolution(self) - [u32; 2] {[(self.board_x * self.block_pixels) as u32,(self.board_y * self.block_pixels) as u32]} }这里定义了Metrics结构体用于存储游戏相关的度量信息比如每个方块在屏幕上显示的像素大小、游戏板的行数和列数等。并且为该结构体实现了resolution方法用于根据存储的度量信息计算并返回游戏窗口的分辨率以便后续创建合适大小的游戏窗口。 5. 定义游戏状态枚举和游戏结构体及相关方法 rust // State 枚举用于表示游戏的不同状态 enum State {// 闪烁状态用于处理满行消除时的闪烁效果// 包含当前闪烁阶段isize 类型、上次阶段切换的时间点Instant 类型以及需要闪烁的行索引向量Veci8 类型Flashing(isize, Instant, Veci8),// 方块下落状态包含当前正在下落的方块信息Board 类型Falling(Board),// 游戏结束状态GameOver, }// Game 结构体用于表示整个游戏的状态和逻辑 struct Game {// 游戏板对象用于存储游戏板的当前状态board: Board,// 游戏度量信息对象用于存储游戏的相关度量参数metrics: Metrics,// 当前游戏状态使用 State 枚举表示state: State,// 方块在游戏板上的偏移量以 (i8, i8) 坐标表示shift: (i8, i8),// 可能出现的方块形状列表每个元素都是一个 Board 类型表示不同形状的方块possible_pieces: VecBoard,// 记录上次方块下落的时间点用于控制方块下落的速度time_since_fall: Instant, }// Game 结构体的实现块包含了一系列处理游戏逻辑的方法 impl Game {// new 方法用于创建一个新的 Game 实例// 接受一个 Metrics 类型的参数用于初始化游戏的度量信息并设置游戏板、状态、偏移量等初始值fn new(metrics: Metrics) - Self {Self {metrics,board: Default::default(),state: State::Falling(Default::default()),time_since_fall: Instant::now(),shift: (0, 0),possible_pieces: vec![Board::new([(0, 0), (0, 1), (1, 0), (1, 1), ][..], Color::Red),Board::new([(0, 0), (1, 0), (1, 1), (2, 0), ][..], Color::Green),Board::new([(0, 0), (1, 0), (2, 0), (3, 0), ][..], Color::Blue),Board::new([(0, 0), (1, 0), (2, 0), (0, 1), ][..], Color::Orange),Board::new([(0, 0), (1, 0), (2, 0), (2, 1), ][..], Color::Yellow),Board::new([(0, 0), (1, 0), (1, 1), (2, 1), ][..], Color::Cyan),Board::new([(1, 0), (2, 0), (0, 1), (1, 1), ][..], Color::Magenta),]}}// new_falling 方法用于生成一个新的下落方块// 通过随机数生成器选择一个可能的方块形状并设置为当前下落状态// 如果当前游戏6. Game结构体相关方法 rust // falling_shifted 方法用于获取当前下落状态下经过偏移后的方块信息 // 根据当前游戏状态中的下落方块和偏移量返回偏移后的方块 // 如果当前状态不是下落状态则触发 panic!表示程序出现错误情况 fn falling_shifted(self) - Board {match self.state {State::Falling(state_falling) {state_falling.shifted(self.shift)}State::GameOver {.. } panic!(),State::Flashing {.. } panic!(),} }作用 此方法的目的是根据游戏当前状态获取经过偏移后的正在下落的方块信息。它通过匹配当前游戏状态如果处于Falling状态就利用Board结构体的shifted方法对下落方块按照当前的偏移量self.shift进行偏移操作从而得到准确位置的下落方块。若当前状态不是Falling状态如GameOver或Flashing状态则触发panic!这是因为该方法假设只有在方块处于下落状态时才会被调用以获取正确偏移后的方块其他状态下调用此方法是不符合预期逻辑的所以通过panic!来提示程序出现了错误情况。 rust // progress 方法用于推进游戏的进程根据当前游戏状态执行不同的操作 fn progress(mut self) {match mut self.state {State::Falling(_) {if self.time_since_fall.elapsed() Duration::from_millis(700) {return;}self.move_falling(0, 1);self.time_since_fall Instant::now();}State::Flashing(stage, last_stage_switch, lines) {if last_stage_switch.elapsed() Duration::from_millis(50) {return;}if *stage 18 {*stage 1;*last_stage_switch Instant::now();return;} else {for idx in lines {self.board self.board.kill_line(*idx);}self.new_falling();}}State::GameOver { } {},} }作用 该方法是游戏逻辑的核心部分之一用于根据游戏当前所处的不同状态来推进游戏进程。当游戏处于Falling状态时它首先检查从上一次方块下落至今所经过的时间是否小于等于 700 毫秒如果是则直接返回不进行任何操作这是为了控制方块下落的速度避免下落过快。若时间超过了限制就调用move_falling方法让方块向下移动一格传入参数(0, 1)表示在x方向移动 0 格在y方向移动 1 格然后更新time_since_fall为当前时间以便下一次准确计算方块下落间隔时间。当游戏处于Flashing状态时它先检查从上一次阶段切换至今所经过的时间是否小于等于 50 毫秒如果是则返回。若超过了限制并且当前闪烁阶段*stage小于 18就将闪烁阶段加 1并更新last_stage_switch为当前时间继续进行闪烁效果的展示。而当闪烁阶段达到 18 时意味着闪烁效果结束此时会遍历需要闪烁的行索引lines通过调用board的kill_line方法清除这些行然后调用new_falling方法生成一个新的下落方块继续游戏流程。当游戏处于GameOver状态时此方法不执行任何操作因为游戏已经结束无需再进行其他逻辑处理。 rust // move_falling 方法用于移动正在下落的方块 fn move_falling(mut self, x: i8, y: i8) {let falling self.falling_shifted().shifted((x, y));let merged self.board.merged(falling);let contained falling.contained(self.metrics.board_x as i8,self.metrics.board_y as i8);if merged.is_some() contained {// Allow the movementself.shift.0 x;self.shift.1 y;return}if let (0, 1) (x, y) {self.board self.board.merged(self.falling_shifted()).unwrap();let completed self.board.whole_lines(self.metrics.board_x as i8,self.metrics.board_y as i8);if completed.is_empty() {self.new_falling();} else {self.state State::Flashing(0, Instant::now(), completed);}} }作用 此方法用于处理正在下落的方块的移动操作。首先它通过falling_shifted方法获取当前经过偏移的下落方块然后再根据传入的参数(x, y)对该方块进行进一步的偏移操作得到新的下落方块位置falling。接着它检查新位置的方块能否与游戏板self.board进行合并通过merged方法以及是否在游戏板的有效范围内通过contained方法。如果这两个条件都满足说明方块可以移动到新位置那么就更新方块在游戏板上的偏移量self.shift完成方块的移动操作并返回。如果传入的参数(x, y)是(0, 1)表示方块是向下移动一格此时会先将当前下落方块与游戏板进行合并通过merged方法获取合并后的游戏板然后检查游戏板上是否有完整的行通过whole_lines方法。如果没有完整的行就调用new_falling方法生成一个新的下落方块继续游戏如果有完整的行就将游戏状态设置为Flashing状态并传入当前时间和需要闪烁的行索引开始处理满行消除的闪烁效果。 rust // on_press 方法用于处理按键按下事件根据按下的按钮类型进行不同的处理 fn on_press(mut self, args: Button) {match args {Button::Keyboard(key) { self.on_key(key); }_ {},} }作用 该方法是游戏处理输入事件的入口点之一用于接收一个Button类型的参数表示按下的按钮信息。它通过匹配按钮类型如果是键盘按钮Button::Keyboard就调用on_key方法进一步处理具体的键盘按键操作如果不是键盘按钮则不进行任何操作直接返回。 rust // on_key 方法用于处理具体的键盘按键操作根据当前游戏状态和按下的键盘按键执行不同的操作 fn on_key(mut self, key: Key) {match mut self.state {State::Flashing {..} {},State::Falling {..} {let movement match key {Key::Right Some((1, 0)),Key::Left Some((-1, 0)),Key::Down Some((0, 1)),_ None,};if let Some(movement) movement {self.move_falling(movement.0, movement.1);return;}match key {Key::Up self.rotate(false),Key::NumPad5 self.rotate(true),_ return,}}State::GameOver { } {match key {Key::Return {self.board.0.clear();self.new_falling();},_ return,}},} }作用 此方法根据当前游戏状态和按下的具体键盘按键来执行相应的游戏操作。当游戏处于Flashing状态时不执行任何操作因为在满行消除闪烁期间通常不希望玩家进行其他操作干扰闪烁效果的处理。当游戏处于Falling状态时首先通过匹配按下的键盘按键来确定方块的移动方向或旋转操作。如果按下的是Key::Right、Key::Left或Key::Down就分别对应方块向右、向左或向下移动一格的操作通过调用move_falling方法并传入相应的移动参数来实现方块的移动。如果按下的是Key::Up或Key::NumPad5则分别对应方块的逆时针或顺时针旋转操作通过调用rotate方法并传入相应的旋转方向参数来实现方块的旋转。当游戏处于GameOver状态时只有当按下Key::Return键时会清除游戏板上的所有方块通过board.0.clear()然后调用new_falling方法生成一个新的下落方块重新开始游戏按下其他键则不执行任何操作直接返回。 rust // rotate 方法用于旋转正在下落的方块 fn rotate(mut self, counter: bool) {match mut self.state {State::Falling(state_falling) {let rotated if counter {state_falling.rotated()} else {state_falling.rotated_counter()}let (x, y) rotated.negative_shift();let falling rotated.shifted((-x, -y));for d in [(0, 0), (-1, 0)] {let mut shift self.shift;shift.0 d.0;shift.1 d.1;if let Some(merged) self.board.merged(falling.shifted(shift)) {if merged.contained(self.metrics.board_x as i8,self.metrics.board_y as i8){// Allow the rotation*state_falling falling;self.shift shift;return}}}}State::GameOver {..} panic!(),State::Flashing {..} panic!(),} }作用 该方法用于处理正在下落的方块的旋转操作。当游戏处于Falling状态时首先根据传入的参数counter确定是顺时针还是逆时针旋转方块。如果counter为true就通过state_falling.rotated()方法对下落方块进行顺时针旋转如果counter为false则通过state_failing.rotated_counter()方法对下落方块进行逆时针旋转。然后获取旋转后方块的最小偏移量(x, y)通过negative_shift方法并将旋转后的方块按照这个偏移量的相反数进行反向偏移得到falling以便将方块放置在合适的位置进行后续的合并操作。接着通过遍历[(0, 0), (-1, 0)]这两个偏移量对旋转后的方块在不同的偏移位置尝试与游戏板进行合并操作通过merged方法并检查合并后的方块是否在游戏板的有效范围内通过contained方法。如果在某个偏移位置满足这两个条件说明方块可以旋转到该位置就更新下落方块的状态*state_falling为falling并更新方块在游戏板上的偏移量self.shift完成方块的旋转操作并返回。如果当前游戏状态不是Falling状态如GameOver或Flashing状态则触发panic!因为该方法假设只有在方块处于下落状态时才会被调用以进行正确的旋转操作其他状态下调用此方法是不符合预期逻辑的所以通过panic!来提示程序出现了错误情况。 7. main函数 rust fn main() {let metrics Metrics {block_pixels: 20,board_x: 8,board_y: 20,};let mut window: PistonWindow WindowSettings::new(Tetris, metrics.resolution()).exit_on_esc(true).build().unwrap();let mut game Game::new(metrics);game.new_falling();while let Some(e) window.next() {game.progress();if let Some(_) e.render_args() {game.render(mut window, e);}if let Some(args) e.press_args() {game.on_press(args);}} }作用 在main函数中首先创建了一个Metrics结构体实例设置了每个方块的像素大小为 20游戏板的行数为 20列数为 8这些参数定义了游戏的基本布局和显示效果。然后使用PistonWindow库创建了一个游戏窗口通过WindowSettings设置窗口的标题为 Tetris并根据metrics.resolution()计算出的窗口分辨率来设置窗口大小同时设置了按下Esc键时退出游戏。接着创建了一个Game结构体实例并调用new_falling方法生成第一个下落方块开始游戏。之后进入一个循环不断从游戏窗口获取事件通过window.next()。对于每个获取到的事件 如果事件有渲染相关的参数通过e.render_args()就调用game.render方法在窗口中绘制游戏的当前状态。如果事件有按键按下相关的参数通过e.press_args()就调用game.on_press方法处理按键按下事件。这样游戏就能够不断地根据玩家的操作和游戏自身的逻辑进行更新和绘制实现俄罗斯方块游戏的基本功能。 综上所述这段代码通过定义一系列结构体、枚举和相关方法完整地实现了一个俄罗斯方块游戏的核心逻辑包括游戏板的操作、方块的生成、移动、旋转、满行消除以及游戏状态的管理和窗口事件的处理等功能。 效果如下
http://www.pierceye.com/news/236216/

相关文章:

  • 深圳网站设计工作室广告公司名字 三个字
  • 长沙门户网站广告网站设计公司
  • 余姚网站建设的公司wordpress 开发文档
  • 怎么建设一个微信网站莱芜金点子最新招工信息
  • 石家庄网站排名优化wordpress修改布局
  • 景安服务器管理助手如何备份网站国外做图标网站
  • 网站轮播怎么做石家庄网站建设规划
  • 免费软件网站下载深圳网站开发哪个公司好
  • 建设项目验收网站公示内网门户网站建设方案
  • 滨海做网站哪家最好宝安附近做网站公司
  • 详情页的五大模块东莞网站优化科技有限公司
  • 南阳建设网站哪家好昆明网站服务
  • 大潮建设集团有限公司 网站网站改版策划方案
  • 网站开发心路历程烟台网站建设薇企汇互联见效付款
  • 企业网站的制作周期wordpress添加数据库表
  • 广告推广营销网站网站买空间的价格
  • 转转假网站怎么做linux建设视频网站
  • 伍佰亿搜索引擎网站系统wordpress 增加备案
  • 韩国做游戏的电影 迅雷下载网站有哪些网络营销方式文献
  • 大学生兼职网站的融资方案龙华网站建设设计制作公司
  • 青之峰网站建设哪家好用什么l软件做网站了
  • 免费建站资源怎么编写app软件
  • 机关网站建设建议云南响应式网站建设
  • 对网站开发语言的统计杭州网站设计公司有哪些
  • 不会代码 怎么做网站兴义网络推广
  • 综合电子商务型企业网站怎么做网站的网盘
  • ucenter使用自己做的网站房地产新闻时事热点
  • 企业网站备案 过户电商运营视频教程
  • 做网站运营这工作怎么样北京网站优化价格
  • 河南专业网站建设网站怎么做高权重