Привет, мир, здесь я хочу поделиться с вами своей первой простой программой, написанной на Rust и библиотеке GGEZ (Good Game eazy).
О ГГЭЗ
Вкратце о GGEZ: это основа для создания 2D-игры с минимальным трением. Эта библиотека содержит базовый и переносимый 2D-рисунок, звук, загрузку ресурсов и обработку событий.
Программа, которую я сделал, представляет собой простую программу, которая реализует некоторые базовые функции этой библиотеки и помогает лучше понять последовательность выполнения кода. Во-первых, приложение, созданное с помощью этой библиотеки, состоит из трех частей: контекста, обработчика событий и цикла. Контекст - это то место, где все состояние, необходимое для взаимодействия с аппаратным обеспечением компьютера. Обработчик событий - это то место, где все события, такие как нажатие кнопки, щелчок мыши и т. Д., Выполняются в нашей программе. Цикл содержит информацию о том, как наша программа запускается и обновляется.
Вот как выглядит программа
Реализации
Далее поговорим о программе. Программы довольно просты, для этого требуется щелчок мышью и положение курсора, каждый щелчок выводит круг с центром в позиции курсора, после этого круг опускается и, когда он почти достигает нижней части окна, исчезает.
Прежде чем мы начали, вот заголовок.
use ggez; use ggez::{graphics, Context, GameResult, timer}; use ggez::event::{self, EventHandler, MouseButton}; use ggez::nalgebra as na;
Во-первых, мы должны создать контекст. Контекст, как упоминалось ранее, содержит все состояние. Итак, нам нужно создать свое государство. Состояние - это структура, которая содержит список объектов в нашей программе, для этой программы - круг.
struct MainState { circles: Vec<CircleObject> }
Наши круги - это вектор объекта CircleObject. Этот тип CircleObject имеет атрибуты pos_x и pos_y и реализует функцию draw (). Эта функция будет вызываться в нашем обработчике событий. Затем мы создаем нашу структуру CircleObject.
struct CircleObject { pos_x: f32, pos_y: f32, } impl CircleObject { fn draw(&self, ctx: &mut Context) -> GameResult<()> { // make our circle instance let circle = graphics::Mesh::new_circle( ctx, graphics::DrawMode::fill(), // Fill the circle na::Point2::new(self.pos_x, self.pos_y), // Center position 50.0, // radius 0.2, // mesh tolerance, higher smoother graphics::WHITE // Colouring )?; // draw our circle instance graphics::draw(ctx, &circle, (na::Point2::new(0.0, 0.0),))?; Ok(()) } }
В методе рисования аргументы являются ссылкой на себя и изменяемой ссылкой на наш контекст. Внутри этого метода мы создаем новый экземпляр круга, используя графику, а затем вызываем метод graphics :: draw для рисования нашего экземпляра круга.
После этого нам нужно реализовать EventHandler для нашего State. Внутри этого EventHandler есть два обязательных метода update () и draw (). EventHandler сначала вызовет update (), здесь наше состояние обновляется. В этой программе мы хотим обновить положение Кругов, чтобы оно опустилось. В этом методе мы также проверяем, попал ли какой-нибудь кружок в нижнюю часть окна, а затем удаляем его из нашего вектора.
impl MainState { // add this method to MainState implementation fn clean_circles(&mut self){ self.circles.retain(|circle| circle.pos_y < 500.0); } } impl EventHandler for MainState { fn update(&mut self, _ctx: &mut Context) -> GameResult { const FPS: u32 = 24; // our desired FPS rate // we set our FPS to 24 while timer::check_update_time(_ctx, FPS) { // update our circle position each frame // the new position equals to velocity * time passed let seconds = 1.0 / (FPS as f32); for b in &mut self.circles { b.pos_y += 100.0 * seconds; } // check for dropped circles self.clean_circles(); } Ok(()) } }
После вызова обновления нам нужно перерисовать все окно. Здесь вызывается метод рисования круга. Внутри этого метода мы собираемся очистить все окна, а затем перерисовать весь экземпляр, который должен быть в окне после обновления.
// put this function inside EventHandler implementation fn draw(&mut self, _ctx: &mut Context) -> GameResult { // Clearing the window graphics::clear(_ctx, [0.1, 0.2, 0.3, 1.0].into()); // Draw all of the Circles for circle in &self.circles { circle.draw(_ctx)?; } // this method needs to be called // to apply all of the changes graphics::present(_ctx)?; Ok(()) }
Помните, что мы хотим считывать данные, введенные мышью, в нашу программу. В EventHandler мы могли бы добавить в реализацию метод mouse_button_down_event. Этот метод считывает нажатия кнопок мыши и текущую позицию курсора.
// add this method inside EventHandler implementation fn mouse_button_down_event( &mut self, _ctx: &mut Context, _button: MouseButton, _x: f32, _y: f32) { match _button { MouseButton::Left => { // creates new Circle and push to vector self.circles.push(CircleObject { pos_x: _x, pos_y: _y }); } _ => { println!("Other button is clicked"); } } }
Наконец, мы могли создать нашу основную функцию
fn main () -> GameResult { // create a context builder let cb = ggez::ContextBuilder::new("mouse_event", "miqdude"); // create context and event_loop instance let (ctx, event_loop) = &mut cb.build()?; // our MainState goes here let state = &mut MainState::new(ctx)?; event::run(ctx, event_loop, state) }
Вывод
Вот и все! Надеюсь, эта статья поможет вам создать вашу первую программу с использованием библиотеки GGEZ в Rust. Если при чтении этой статьи возникнут какие-либо трудности, сообщите мне, и я немедленно исправлю это. Спасибо, мир.
Смотрите сайт ГГЕЗ здесь.
Код можно посмотреть на моем гитхабе здесь.