В начале третьей главы мы вступаем в стадию реального игрового обучения.Знания, которые мы можем получить на протяжении всей третьей главы, в основном включают:
- game loop,
- basic program flow with a state machine,
- add a player,
- simulate gravity,
- and make the player's dragon flap its wings.
- Finally, add obstaches and scorekeeping to the game.
Это также основная игровая структура.
Game Loop
Что касается этого игрового цикла, мы обратимся к блок-схеме, предоставленной автором, а затем объединим наше собственное понимание.
Скриншоты взяты из текста, авторские права защищены
Основной ход игры выглядит следующим образом:
- Настройте приложение, окно и графику, это хорошее понимание, которое является начальным состоянием и интерфейсом игры.
- Опрос ОС для состояния ввода.Я понимаю, что в играх должен быть триггерный механизм для изменения состояния, такого как событие, действие и т. д .;
- Функция Call Tick. Насколько я понимаю, это похоже на игровой движок каждой игры, который помогает нам преобразовывать все события и действия в логику, которую понимает игра, и изменять состояние. В этой статье в основном используется
bracket-lib
двигатель. - Экран обновления.При изменении статуса необходимо обновлять интерфейс в режиме реального времени.
Повторите цикл, и вы сможете запустить игру.
введено в текстbracket-lib
двигатель. Давайте посмотрим, как это использовать.
Использование Bracket-Lib
Плагин импорта:
[dependencies]
bracket-lib="~0.8.1"
Описание номера версии подключаемого модуля см. во введении в Главе 1:
=0.8.1 может использовать только эту версию;
^ 0.8.1 можно использовать выше или равно этой версии, но она может быть ограничена только версией 0.x, например: 1.x нельзя использовать;
~0.8.1 может использовать любую версию выше или равную этой, даже если в какой-то будущей версии будут ошибки.
Конкретный код:
use bracket_lib::prelude::*;
struct State {}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print(1, 1, "Hello, Bracket Terminal!");
}
}
fn main() ->BError {
println!("Hello, world!");
let context = BTermBuilder::simple80x50()
.with_title("Flappy Dragon")
.build()?;
main_loop(context, State{})
}
Сначала посмотрите на эффект бега:
Напечатать текст на экране терминала легко:Hello, Bracket Terminal!
.
Creating Different Game Modes
Я думаю, что это больше похоже на описание состояния игры.В этой демо-версии игры требуются три режима:
- Menu: The player is waiting at the main menu.
- Playing: Game play is in progress.
- End: The game is over.
Очевидно, что эти режимы могут быть представлены перечислением:
enum GameMode {
Menu,
Playing,
End,
}
Это требует, чтобы мы определилиState
плюс:
struct State {
mode: GameMode,
}
// 并 new 时初始化
impl State {
fn new() -> Self {
State {
mode: GameMode::Menu,
}
}
}
// main 函数同时修改
main_loop(context, State::new())
Следующим шагом с описанием состояния является выполнение различных действий в разных состояниях для достижения эффекта игры:
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
// ctx.cls();
// ctx.print(1, 1, "Hello, Bracket Terminal!");
match self.mode {
GameMode::Menu => self.main_menu(ctx),
GameMode::End => self.dead(ctx),
GameMode::Playing => self.play(ctx),
}
}
}
в этотtick
В функции «в режиме реального времени» отслеживаются все изменения состояния и выполняются различные действия, такие как:Playing
состояние, выполнениеself.play(ctx)
функция:
fn play(&mut self, ctx: &mut BTerm) {
// TODO: Fill in this stub later
ctx.cls();
ctx.print_centered(5, "Playing Flappy Dragon");
ctx.print_centered(8, "(E) Play End");
ctx.print_centered(9, "(Q) Quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::E => self.mode = GameMode::End,
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
}
// 直接状态改变
// self.mode = GameMode::End;
}
существуетplay
В функции по мониторингу разных клавиш определяется изменение состояния, что заставляет игру работать.
Эффект от исполнения следующий:
Полный код:
use bracket_lib::prelude::*;
enum GameMode {
Menu,
Playing,
End,
}
struct State {
mode: GameMode,
}
impl State {
fn new() -> Self {
State {
mode: GameMode::Menu,
}
}
fn restart(&mut self) {
self.mode = GameMode::Playing;
}
fn main_menu(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "Welcome to Flappy Dragon");
ctx.print_centered(8, "(P) Play Game");
ctx.print_centered(9, "(Q) Quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
}
}
fn dead(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "You are dead!");
ctx.print_centered(8, "(P) Play Again");
ctx.print_centered(9, "(Q) Quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
}
}
fn play(&mut self, ctx: &mut BTerm) {
// TODO: Fill in this stub later
ctx.cls();
ctx.print_centered(5, "Playing Flappy Dragon");
ctx.print_centered(8, "(E) Play End");
ctx.print_centered(9, "(Q) Quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::E => self.mode = GameMode::End,
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
}
// 直接状态改变
// self.mode = GameMode::End;
}
}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
// ctx.cls();
// ctx.print(1, 1, "Hello, Bracket Terminal!");
match self.mode {
GameMode::Menu => self.main_menu(ctx),
GameMode::End => self.dead(ctx),
GameMode::Playing => self.play(ctx),
}
}
}
fn main() ->BError {
println!("Hello, world!");
let context = BTermBuilder::simple80x50()
.with_title("Flappy Dragon")
.build()?;
main_loop(context, State::new())
}
Временно договоритесь о другой работе сегодня, следуйте процессу в книге, следуйте кодексу, передайтеbracket-lib
Движок отслеживает изменения состояния в режиме реального времени и выполняет различные игровые действия.Хотя он просто использует виртуальные кнопки для реагирования на изменения состояния, чтобы имитировать ход игры, он в основном составляет логику игры.
Продолжите изучение Главы 3 завтра!