Как рисовать в расте
Перейти к содержимому

Как рисовать в расте

  • автор:

Модификация от сообщества

This community-made mod requires that you have Rust installed prior to running this game. Нажмите здесь, чтобы узнать больше о модификациях в Steam.

Внимание: Because this is a mod dependent on another game, it is possible that the mod will lose functionality when the base game is updated

Установить Rustangelo

Контент для этой игры Просмотреть все (3)

Открыть центр сообщества

Об этой игре

is an automatic sign painter for

With Rustangelo you can choose your image and have it painted to a sign automatically! Works on any RUST server and has been approved by the game developers.

The PRO version includes more features and unlimited painting time.

FEATURES:

  • Automatically paints signs using images loaded from disk or URL
  • Support for all common image formats (png, jpeg, gif, svg, etc.)
  • Support for all canvas sizes in-game (wooden signs, neon signs, pumpkins, picture frames, metal sign posts)
  • Able to crop, rotate, and adjust your image before painting
  • Unlimited painting time; limited to one hour for non-PRO users
  • Paints using 320 possible colors by utilizing different brush opacities (PRO feature)
  • Automatically draws straight lines to speed up the painting process (PRO feature)
  • Auto-update the sign while painting for display to other players (PRO feature)
  • Works on any server type (vanilla, community, modded)
  • Load your image from disk or URL
  • Click the Paint button and capture the canvas area (where to paint)
  • Press the Control hotkey to capture the painting controls area
  • Rustangelo will process and dither the image to match the colors available in the palette
  • Every pixel in the image is scanned and placed in the matching palette color bucket
  • Now Press the Control hotkey again to begin the painting process
  • When the painting process begins the app automatically cycles through all the colors, painting each pixel for every color
  • It is recommended not to move your mouse while Rustangelo is painting as it will disrupt the process

Rustangelo is currently only compatible with a Windows OS.
Rustangelo is not affiliated with Facepunch Studios (FP) or any of their developers.

ATTENTION:

Rustangelo requires that you set your Mode to Borderless or Windowed in Screen options in RUST.

OTHER APPS FROM THE SAME DEVELOPER:

Rustissimo :: RUST Instruments Concert Creator on Steam: https://store.steampowered.com/app/1222580/Rustissimo/

Rustrician :: RUST Electricity Simulator: https://www.rustrician.io/

RustPlusBot :: Rust+ Team Chat Discord Bot: https://bot.rustplus.io/

SPECIAL RUST SERVER HOSTING OFFER:

Interested in running your own Rust server? Get your first month of Rust server hosting discounted 25% off when you sign up for HostEZ using promo code: RUSTPLUSBOT.

Большая деревянная табличка

Декоративная деревянная табличка размером 3 на 1,5 метра, предназначенная для рисования и декорирования.
Требуется 300 единиц дерева для создания этой стенной украшения. Может быть размещена на стенах.

Как рисовать на табличках

Для рисования на табличке необходимо подойти к ней и нажать на кнопку взаимодействия (по умолчанию — Е). На экране появится окно настроек кисти и цвета, где вы можете выбрать нужные параметры.

Далее, для рисования зажмите левую кнопку мыши и ведите мышкой по холсту. Правой кнопкой мыши можно повернуть табличку, а колесиком мыши — приблизить или отдалить изображение.

По окончании работы можно нажать кнопку «Обновить», чтобы обновить рисунок и выйти из таблички. Сохранить рисунок можно, нажав на иконку дискеты.

Чтобы предотвратить изменения рисунка другими игроками, можно зажать клавишу взаимодействия и в меню выбрать «Запретить изменения».

Кроме того, при нажатии на иконку корзины будут удалены все рисунки с таблички, а при выборе «Отмена» — несохраненные фрагменты рисунка.

Рисование на табличке при помощи программы

Если вы хотите быстро и легко создать красивый рисунок на табличке в Rust, то вам стоит попробовать программу «Rustangelo». Это бесплатное программное обеспечение позволяет загружать изображения из файлов или URL-ссылок и нарисовать их на табличке в Rust.

Чтобы начать использовать программу, загрузите ее с официального сайта и откройте ее. Затем откройте меню рисования в игре и программу поверх игры. Загрузите изображение в программу, затем выделите область на табличке, где вы хотите нарисовать изображение.

Как только вы выделите область, нажмите на нее дважды левой кнопкой мыши, после чего нажмите «F10», чтобы начать рисование. Не трогайте мышку и не сворачивайте программу во время рисования, чтобы избежать искажений изображения.

Бесплатная версия программы «Rustangelo» доступна на официальном сайте, а также есть возможность приобрести платную версию. Она является отличным вариантом для тех, кто не знает, как вставить картинку в расте в табличку, но при этом хочет перенести какой-то логотип или изображение на сервер.

Как нарисовать раста искусства

Шаг 1. Начните с круга для головы, а затем эскиз в лицевых руководящих принципов вместе с нижней челюстью гида.

Шаг 2. Используя направляющие, которые вы сделали в первом шаге, начинаем набрасывать структуру кости на щеках. Когда это будет сделано, вы можете нарисовать вытянутую челюсть/подбородок что тоже очень квадратный. Добавить деталь вокруг которой рот будет так же хорошо.

Шаг 3. Далее начните набрасывать формы раста стиль черепа глазами, вот так. Они должны быть длинными, а с плоской верхней крышки, чтобы создать выражение. Ничья в носовой полости и затем добавить некоторые подробности костной ткани вокруг щек и верхней челюсти.

Шаг 4. Отделка рта, рисуя зубов для верхней и нижней части рта. Заметили, как суть отдельных зубов на нижней толстые или тучные формы. Это создание размерных и стиль.

Шаг 5. Вместо того, чтобы рисовать череп, мы заполним это пространство со шляпой. Эти шляпы называются «Rastacaps’ и они приходят в много различных размеров, стилей и форм.

Шаг 6. Добавить свой вязать подробно на Rastacap нравится так, которая лишь несколько вертикальных линий или полос. Когда это будет сделано, вы можете переходить к шагу семь.

Шаг 7. Сейчас такое время, что мы закончим рисовать и делать, что вам нужно будет нарисовать в дреды. Эти пряди волос должны быть толстыми, как куски веревки. Стереть ошибки и рекомендации.

Шаг 8. Вот и все, что к нему. Теперь вы можете покрасить в свой раста-искусство выглядеть удивительный рисунок.

Как Rust меняет мышление разработчика

Я страшно ненавижу C++. Обычно я люблю программирование, но каждый проект, с которым я имел дело на C++, ощущался как монотонная рутина. В январе 2023 года я пошёл по пути изучения Rust, поэтому теперь могу сказать, что знаю язык системного программирования, который действительно люблю использовать.

Первый стабильный релиз Rust появился в 2015 году, и каждый год, начиная с 2016, он признаётся в Stack Overflow’s Annual Developer Survey самым любимым языком (в 2023 году эта категория называется «обожаемый»). Почему же разработчики, ощутившие вкус Rust, не могут отказаться от его использования? Похоже, в мире прогремевших наследников C/C++ репутация растёт только у Rust. Как же этот язык, появившийся на сцене меньше десятка лет назад, стал настолько популярным?

Ржавый красный краб Феррис по версии Midjourney

Кривая обучения оказалась крутой. Я нашёл многое, что мне нравится в Rust, но постоянно попадал в его ловушки. Однако в конечном счёте именно препятствия и проблемы, с которыми столкнулся, я научился любить больше всего.

Я начну историю с разговора о том, что легко полюбить — со среды Rust, управления пакетами и документации. Затем я расскажу о системе типов и типажах (trait). Далее я поведаю о тех возможностях тестирования и test driven development, которые становятся возможными благодаря Rust. Наконец, мы обсудим самую запутанную и сбивающую с толку часть — одержимость Rust тем, кто какой переменной владеет.

▍ Экосистема Rust

В большинстве регулярно используемых мной языков есть управление пакетами и версиями. В наши дни очень полезны системы наподобие npm, pip и NuGet, но они не всегда были такими, и всё ещё далеки от идеала. В большинстве языков само управление установленной версией языка становится мучением.

Установить Rust можно при помощи rustup — инструмента, который позже позволяет управлять версией Rust и связанными с ним инструментами.

Cargo сочетает в себе функциональность управления пакетами и инструментов сборки; он воплощает все лучшие характеристики управления пакетами. Он прост и никогда не мешает работе.

Ещё один важнейший аспект экосистемы Rust — это документация. Я изучал язык исключительно по официальной документации и у меня никогда не было потребности искать туториалы в других местах. В «книге» и в Rust By Example было раскрыто всё необходимое мне. На самом деле, когда бы я ни приходил на Stack Overflow с вопросом, самые полезные ответы обычно заключались в указании на подходящий раздел или в официальной документации, или в одном из этих двух источников.

Я могу долго рассуждать о сообщениях компилятора, которые ощущаются как менторство со стороны более опытного программиста (это я оставлю на потом), или о Rust Playground — прекрасном способе проверить, работает ли код. Но вместо этого я перейду к действительно выделяющимся особенностям языка. Настало время углубиться в тонкости системы типов Rust, и в особенности в концепцию типажей (Trait).

▍ Кря-кря! Утиная типизация с типажами

В самом начале у Rust были классы, но они продержались меньше полугода. Их заменила гораздо более простая структура данных — struct . Типы определяются объявлением struct , которая является чем-то большим, чем набор связанных полей для хранения данных. Rust позволяет добавлять реализации для типов, которые являются множествами функций, способных выполнять операции, связанные с этими типами, или над ними.

Удобная концепция, которую я полюбил при работе с языками с динамической типизацией — это утиная типизация. Это принцип, по которому функция может принимать объект любого типа, если он имеет подходящие свойства и методы, нужные функции. «Если это выглядит как утка, плавает как утка и крякает как утка, то это утка». Если вызываемой нами функции нужен ввод, способный плавать, то нас не должно волновать, утка ли это. Нам важно только, умеет ли это плавать.

Слон, притворяющийся уткой (Midjourney)

Несмотря на то, что Rust — язык со статической типизацией, он всё равно справляется с этим изящно. Благодаря типажам вы можете перестать думать, какие типы должны принимать ваши функции, и вместо этого начать думать о том, какие входные данные функции должны уметь обрабатывать.

Давайте взглянем на пример. Вот типаж для плавания. Любой тип, реализующий типаж Swim , умеет плавать.

trait Swim

Функция, имеющая аргумент, который должен уметь плавать, не обязана указывать тип. Ей достаточно указать, что он должен реализовать типаж Swim . Нас не должно волновать, какие типы появятся в будущем. Компилятор будет смотреть, какие типы мы вызываем с функцией, выполнять соответствующие проверки и генерировать соответствующий машинный код для их обработки.

fn cross_the_pond(animal: impl Swim)

Давайте создадим несколько типов, которые можно передавать функции cross_the_pond . Мы можем создать тип Duck , определив struct и реализовав для неё типаж Swim .

struct Duck < name: String, >impl Swim for Duck < fn swim(&self) < println!("<>paddles furiously. ", self.name); > >

Но утка — не единственное, что может плавать. Давайте определим struct Elephant и тоже реализуем для неё типаж Swim .

struct Elephant < name: String, >impl Swim for Elephant < fn swim(&self) < println!("<>is actually just walking on the bottom. ", self.name); > >

Наша функция main способна создавать экземпляры уток и слонов, соединяя всё это вместе.

fn main() < let duck = Duck < name: String::from("Sir Quacks-a-lot") >; let ellie = Elephant < name: String::from("Ellie BigEndian") >; println!("Crossing the pond. "); cross_the_pond(duck); cross_the_pond(ellie); >

При этом получается следующий вывод:

Crossing the pond. Sir Quacks-a-lot paddles furiously. Ellie BigEndian is actually just walking on the bottom. 

Можете поэкспериментировать с этим кодом в Rust Playground здесь.

Кроме того, в стандартной библиотеке Rust есть очень полезные типы наподобие Option и Result , позволяющие обрабатывать случаи, в которых значение может существовать, а может и не существовать. Благодаря сопоставлению с образцом (pattern matching) Rust при помощи этих типов можно писать сжатый и читаемый код обработки ошибок. В этой статье мы не будем рассматривать их или оператор match , но если вы только осваиваете Rust, с ними стоит ознакомиться. Вместо этого давайте поговорим о подходе Rust к тестированию.

▍ Тестирование кода в коде

У разработчиков обычно есть устоявшиеся мнения о структуре папок и формате именования файлов. Все согласятся, что мы стремимся поддерживать максимальную чистоту в папках, но люди обычно расходятся в том, что же это на самом деле значит. Важная причина споров заключается в том, куда помещать тесты. Нужно ли создавать для них отдельную папку? Должна ли структура папки с тестами копировать структуру папки с исходниками? Добавлять ли к файлам тестов префикс «test_», чтобы они были сгруппированы вместе, или добавлять суффикс «_test», чтобы тесты были рядом с тем, что они тестируют?

Запутанная структура усложняет поиск. Но какой должна быть аккуратная структура? (Midjourney)

Ещё одна проблема — это тестирование приватных функций. В большинстве языков у вас есть выбор: или остановиться на тестировании только публичных интерфейсов, или сделать приватные функции публичными (это отвратительно, пожалуйста, не делайте так), или положиться на трюки с рефлексией, из-за которых тесты становятся неуклюжими и сложными в чтении и поддержке. Как с этими трудностями справляется Rust?

В Rust рекомендуется помещать тесты в тот же файл, что и код, который они тестируют. Преимущества этого огромны. Отсутствует хаос в файловой системе, споры о способах именования, а сами тесты при необходимости могут иметь доступ к приватным функциям без необходимости компрометации или раскрытия подробностей реализации.

Давайте рассмотрим пример. Показанный ниже модуль обеспечивает одну глупую функцию, складывающую два числа и возвращающую удвоенную сумму. Она использует приватную вспомогательную функцию и несколько тестов.

// Публичная функция, получающая два integer и возвращающая их удвоенную сумму pub fn add_and_double(x: i32, y: i32) -> i32 < 2 * _add(x, y) >// Приватная вспомогательная функция, складывающая два integer fn _add(x: i32, y: i32) -> i32 < x + y >#[cfg(test)] mod tests < use super::*; #[test] fn test_add_and_double() < assert_eq!(add_and_double(2, 3), 10); assert_eq!(add_and_double(0, 0), 0); >#[test] fn test_add() < assert_eq!(_add(2, 3), 5); assert_eq!(_add(0, 0), 0); >>

Атрибут #[cfg(test)] приказывает компилятору компилировать тестовый модуль только при выполнении тестов, а из сборки продакшена тесты вырезаются.

В Rust также имеются очень удобные функции наподобие тестов документации (примеры в документации выполняются в качестве тестов, чтобы документация никогда не теряла актуальности) и конкурентное исполнение тестов, делающее выполнение тестов крайне быстрым.

Типизация и тестирование были теми двумя особенностями, которые сразу же восхитили меня, но давайте рассмотрим и особенность, которую полюбить сложнее всего.

▍ Позаимствовал и теперь не отдаёт

Для меня самой сложной частью изучения Rust стало понимание концепции владения (ownership), времени жизни (lifetime), заимствования (borrowing), перемещения (moving) и копирования (copying).

Rust — это язык, проектируемый как безопасный с точки зрения доступа к памяти по своей сути. Источником вдохновения для создания Rust стал сбой в операционной системе лифта в жилом здании. Сбои часто вызывают ошибки в памяти, в том числе нулевые указатели, висячие указатели и утечки памяти, которых можно избегать, создавая более качественные программы. Система владения Rust гарантирует отсутствие подобных ошибок.

Значение в памяти имеет лишь одного владельца. Владелец — это только переменная, содержащая значение, и компилятор может во время компиляции понять, когда владелец вышел за границы блока (scope), и точно знает, когда можно освободить память. Весь другой блок, которому нужно использовать значение, должен заимствовать его, и за один раз значение заимствовать может только один блок. Это гарантирует, что одновременно не может быть больше одной ссылки на значение. Также в языке есть строгая система управления временем жизни, поэтому ссылка на значение не может жить дольше, чем переменная, владеющая значением. Эти концепции являются фундаментом безопасности доступа к памяти Rust.

Если вы пишете код логичным и удобным образом, ваши функции должны быть короткими, а переменные не должны жить слишком долго. Но у любой полезной программы есть необходимость хранить данные намного дольше, чем один вызов функции. На сцене появляется перемещение (moving).

При возврате значения из функции или при присвоении его новой переменной другая переменная должна получить владение этим значением. Это называется перемещением; после перемещения исходной переменной больше не разрешается использовать значение. Это значит, что показанный ниже простой код, который не был бы проблемой в большинстве других высокоуровневых языков, в Rust не скомпилируется.

fn main() < let original_owner = String::from("Something"); let new_owner = original_owner; println!("<>", original_owner); >

Меня это очень сбивало с толку. Давайте взглянем на сообщение об ошибке:

error[E0382]: borrow of moved value: `original_owner` --> src/main.rs:6:20 | 3 | let original_owner = String::from("Something"); | -------------- move occurs because `original_owner` has type `String`, which does not implement the `Copy` trait 4 | let new_owner = original_owner; | -------------- value moved here 5 | 6 | println!("<>", original_owner); | ^^^^^^^^^^^^^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | 4 | let new_owner = original_owner.clone(); | ++++++++ For more information about this error, try `rustc --explain E0382`.

Это типичная структура сообщений об ошибках от компилятора Rust. Она не орёт на вас, не давая понять, в чём же вы ошиблись, а спокойно указывает, почему значение необходимо переместить, показывает, где произошло перемещение, подсказывает, как это можно исправить и даёт полезное уведомление о снижении производительности при обходном решении.

Задумайтесь об этом. Когда я в первый раз встретился с умеренно сложной ошибкой компиляции, вызванной перемещённым значением, мне казалось, что я бьюсь головой в стену. Нечто столь простое, что я всю свою карьеру программиста считал само собой разумеющимся, было в новом языке невозможно. Почему же так много разработчиков любят этот язык, делающий простые вещи столь раздражающими?

Но потом я понял. Rust позволяет мне делать то, что я хочу, но сначала просит подумать, действительно ли я хочу именно этого, и заставляет задуматься о последствиях моего решения. Теперь когда я пишу код на других языках, то думаю о том, какие объекты хранят ссылки на какое значение, где на значения ссылаются или где их копируют, а также о влиянии этого на производительность и надёжность. Rust делает меня более совершенным программистом, даже когда я пишу код на других языках.

▍ В заключение

В 2019 году я выступил с докладом «Не только синтаксис» о своём опыте изучения Racket — языка из семейства Lisp. Хотя я никогда не пользовался и не буду пользоваться языком Lisp профессионально, этот опыт привёл к глубокому прозрению относительно функционального программирования на уровне, которого я не ощущал ранее. Завершил доклад я следующими цитатами:

«Язык, который не влияет на то, как вы думаете о программировании, не стоит освоения», — Алан Перлис

«Скрипка формирует не только скрипача, всех нас тоже формируют используемые нами инструменты, и в этом языки программирования имеют косвенное влияние: они формируют наши мыслительные привычки», — Эдсгер Дейкстра

Откровения, снизошедшие на меня при изучении Rust в течение последних нескольких месяцев, трансформировали меня схожим образом. Кривая обучения была крутой. Rust — не нежный и не прощающий язык. Он строгий и чёткий, но это лишь мешает вам писать код, о котором вы пожалеете спустя пару лет.

Я обнаружил то, что видят в Rust почти 85% использовавших его разработчиков, и когда на мою электронную почту пришла форма с опросом Stack Overflow на 2024 год, в которой был вопрос, буду ли я пользоваться Rust в следующем году, ответом было твёрдое «да».

  • ruvds_перевод
  • rust
  • безопасность доступа к памяти
  • memory safety
  • утиная типизация
  • traits

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *