Привет, мир, здесь я хочу поделиться с вами своей первой простой программой, написанной на 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. Если при чтении этой статьи возникнут какие-либо трудности, сообщите мне, и я немедленно исправлю это. Спасибо, мир.
Смотрите сайт ГГЕЗ здесь.
Код можно посмотреть на моем гитхабе здесь.