mirror of
https://github.com/flame-engine/flame.git
synced 2025-10-31 00:48:47 +08:00
This PR introduces the notions of structured text, and text styles, to support rendering of rich text bodies. Specifically, we recognize that sometimes in games one needs to render pieces of text that are larger than a single word or even a single paragraph. These pieces may include: books, quest descriptions, mission objectives, tutorials, in-game help system, dialogues, etc. Rendering such a piece of text is non-trivial, however. In order to tackle this problem, I break into the following parts: Text structure, represented as a tree of Nodes. The nodes describe the logical structure of the text, for example the document may contain a header, and then several paragraphs, and a list, where the list contains some list items, some of which having possibly several paragraphs, etc. This structure is similar to how in HTML the text is marked up with HTML tags. Text styles are struct-like classes that contain properties describing how the text is to be styled: font size, font renderer, borders, backgrounds, margins, padding, etc. This representation is also tree-like, so that for example text inside paragraphs can have different style than text within headers, and paragraphs within lists can have different margins. A text style is similar to a stylesheet in HTML. Text elements are the result of applying the document style to a document node: they are the "prepared" and laid out pieces, ready to be rendered. Elements are a bit like mini-components, or perhaps text "particles" in a particle system.
73 lines
2.4 KiB
Dart
73 lines
2.4 KiB
Dart
import 'package:flame/components.dart';
|
|
import 'package:flame/game.dart';
|
|
import 'package:flame/text.dart';
|
|
import 'package:flutter/painting.dart';
|
|
|
|
class RichTextExample extends FlameGame {
|
|
static String description = '';
|
|
|
|
@override
|
|
Color backgroundColor() => const Color(0xFF888888);
|
|
|
|
@override
|
|
Future<void> onLoad() async {
|
|
add(MyTextComponent()..position = Vector2.all(100));
|
|
}
|
|
}
|
|
|
|
class MyTextComponent extends PositionComponent {
|
|
late final Element element;
|
|
|
|
@override
|
|
Future<void> onLoad() async {
|
|
final style = DocumentStyle(
|
|
width: 400,
|
|
height: 200,
|
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14),
|
|
background: BackgroundStyle(
|
|
color: const Color(0xFFFFFFEE),
|
|
borderColor: const Color(0xFF000000),
|
|
borderWidth: 2.0,
|
|
),
|
|
paragraphStyle: BlockStyle(
|
|
margin: const EdgeInsets.symmetric(vertical: 6),
|
|
padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 6),
|
|
background: BackgroundStyle(
|
|
color: const Color(0xFFFFF0CB),
|
|
borderColor: const Color(0xFFAAAAAA),
|
|
),
|
|
),
|
|
);
|
|
final document = DocumentNode([
|
|
ParagraphNode.simple(
|
|
'Anything could be true. The so-called laws of nature were nonsense.',
|
|
),
|
|
ParagraphNode.simple(
|
|
'The law of gravity was nonsense. "If I wished," O\'Brien had said, '
|
|
'"I could float off this floor like a soap bubble." Winston worked it '
|
|
'out. "If he thinks he floats off the floor, and I simultaneously '
|
|
'think I can see him do it, then the thing happens."',
|
|
),
|
|
ParagraphNode.simple(
|
|
'Suddenly, like a lump of submerged wreckage breaking the surface of '
|
|
'water, the thought burst into his mind: "It doesn\'t really happen. '
|
|
'We imagine it. It is hallucination."',
|
|
),
|
|
ParagraphNode.simple(
|
|
'He pushed the thought under instantly. The fallacy was obvious. It '
|
|
'presupposed that somewhere or other, outside oneself, there was a '
|
|
'"real" world where "real" things happened. But how could there be '
|
|
'such a world? What knowledge have we of anything, save through our '
|
|
'own minds? All happenings are in the mind. Whatever happens in all '
|
|
'minds, truly happens.',
|
|
),
|
|
]);
|
|
element = document.format(style);
|
|
}
|
|
|
|
@override
|
|
void render(Canvas canvas) {
|
|
element.render(canvas);
|
|
}
|
|
}
|