🇺🇦 Українська (Ukrainian - Ukraine)
🇺🇦 Українська (Ukrainian - Ukraine)
Зовнішній вигляд
🇺🇦 Українська (Ukrainian - Ukraine)
🇺🇦 Українська (Ukrainian - Ukraine)
Зовнішній вигляд
Ця сторінка написана для версії:
1.21
Ця сторінка написана для версії:
1.21
Іноді використання формату моделі Minecraft недостатньо. Якщо вам потрібно додати до нього динамічне промальовування, вам потрібно буде використовувати BlockEntityRenderer
.
Наприклад, нумо зробимо так, щоб блок лічильника зі статті про блокові-сутностей показував кількість натискань у зверху.
Для початку, нам треба створити BlockEntityRenderer
для CounterBlockEntity
.
Створюючи BlockEntityRenderer
для CounterBlockEntity
, важливо помістити клас у відповідний вихідний набір, наприклад src/client/
, якщо ваш проєкт використовує розділені вихідні набори для клієнта та сервера. Доступ до пов'язаних із промальовуванням класів безпосередньо у вихідному наборі src/main/
небезпечний, оскільки ці класи можуть бути завантажені на сервер.
public class CounterBlockEntityRenderer implements BlockEntityRenderer<CounterBlockEntity> {
public CounterBlockEntityRenderer(BlockEntityRendererFactory.Context context) {
}
@Override
public void render(CounterBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) {
}
}
Новий клас має конструктор із BlockEntityRendererFactory.Context
як параметр. У Context
є кілька корисних штук промальовування, наприклад ItemRenderer
або TextRenderer
. Крім того, включивши такий конструктор, стає можливим використовувати конструктор як сам функціональний інтерфейс BlockEntityRendererFactory
:
public class FabricDocsBlockEntityRenderer implements ClientModInitializer {
@Override
public void onInitializeClient() {
BlockEntityRendererFactories.register(ModBlockEntities.COUNTER_BLOCK_ENTITY, CounterBlockEntityRenderer::new);
}
}
Додайте точку входу до файлу fabric.mod.json
, щоб зареєструвати промальовування.
BlockEntityRendererFactory
— це реєстр, який зіставляє кожен BlockEntityType
зі спеціальним кодом відтворення на відповідний BlockEntityRenderer
.
Тепер, коли у нас є промальовування, ми можемо малювати. Метод render
викликається кожним кадром, і саме в ньому відбувається магія промальовування.
По-перше, нам потрібно змістити та повернути текст так, щоб він знаходився вище блоку.
INFO
Як випливає з назви, MatrixStack
є стосом, що означає, що ви можете надсилати та витягувати перетворення. Гарне емпіричне правило полягає в тому, щоб додати новий блок на початку методу render
і відкрити його в кінці, щоб промальовування одного блоку не впливав на інші.
Більше інформації про MatrixStack
можна знайти в статті про базові концепції промальовування.
Щоб полегшити розуміння необхідних перекладів і поворотів, візуалізуємо їх. На цьому зображенні зелений блок – це місце, де буде намальовано текст, за замовчуванням у найдальшій нижній лівій точці блоку:
Отже, спочатку нам потрібно перемістити текст наполовину блоку по осях X і Z, а потім перемістити його вгору до верхньої частини блоку по осі Y:
Це робиться за допомогою одного виклику translate
:
matrices.translate(0.5, 1, 0.5);
Ось і переклад зроблено, обертання і масштаб залишаються
За замовчуванням текст малюється на площині X-Y, тому нам потрібно повернути його на 90 градусів навколо осі X, щоб він був спрямований вгору на площині X-Z:
![Зелений блок у верхній центральній точці, спрямований догори] (/assets/develop/blocks/block_entity_renderer_3.png)
MatrixStack
не має функції rotate
, натомість нам потрібно використовувати multiply
і RotationAxis.POSITIVE_X
:
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
Тепер текст у правильному положенні, але він завеликий. BlockEntityRenderer
промальовує весь блок на куб [-0.5, 0.5]
, тоді як TextRenderer
використовує координати Y [0, 9]
. Таким чином, нам потрібно зменшити його в 18 разів:
matrices.scale(1/18f, 1/18f, 1/18f);
Тепер усе перетворення виглядає так:
matrices.push();
matrices.translate(0.5, 1, 0.5);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
matrices.scale(1/18f, 1/18f, 1/18f);
Як згадувалося раніше, Context
, переданий у конструктор нашого промальовування, має TextRenderer
, який ми можемо використовувати для малювання тексту. Для цього прикладу ми збережемо його в полі.
TextRenderer
має методи для вимірювання тексту (getWidth
), що корисно для центрування, і для його малювання (draw
).
String text = entity.getClicks() + "";
float width = textRenderer.getWidth(text);
// draw the text. params:
// text, x, y, color, shadow, matrix, vertexConsumers, layerType, backgroundColor, light
textRenderer.draw(
text,
-width/2, -4f,
0xffffff,
false,
matrices.peek().getPositionMatrix(),
vertexConsumers,
TextRenderer.TextLayerType.SEE_THROUGH,
0,
light
);
Метод draw
приймає багато параметрів, але найважливіші з них:
Text
(або String
) для малювання;x
і y
;Matrix4f
, що описує, як його слід трансформувати (щоб отримати один із MatrixStack
, ми можемо використати .peek().getPositionMatrix()
, щоб отримати Matrix4f
для самого верхнього запису).І після всієї цієї роботи ось результат: