¡Continúe creando, acelere el crecimiento! Este es el 7º día de mi participación en el "Nuggets Daily New Plan · June Update Challenge", haz clic para ver los detalles del evento
prefacio
Esta es una serie de tutoriales producidos por Zhang Fengjietlie y publicados en la comunidad de Nuggets. Flutter&Flame
Si ve este artículo en otras plataformas, puede pasar a los Nuggets para verlo según el enlace. Debido a que el artículo puede actualizarse y revisarse, prevalecerá la versión del artículo de los Nuggets. Lista de artículos de esta serie:
- 【Flutter&Flame Game-One】Abre la puerta a un nuevo mundo
- 【Flutter&Flame Game - Ⅱ】Joystick y movimiento de personajes
- 【Flutter&Flame Game - 3】Eventos de teclado y operación de gestos
- 【Juego Flutter&Flame - 4】Método de carga de imagen Sprite
- 【Flutter&Flame Game - Wu】Participación en lienzo | Barra de salud del personaje
- 【Juego Flutter&Flame - Lu】Valor de daño | Uso de componentes de texto (
本文
)
1. El valor de las palabras
Ya sea una aplicación o un juego, 文字
ya 图片
es el eterno tema de exhibición. La civilización humana se basa en las palabras como herencia, y el mayor valor de las palabras radica en transmitir información. La siguiente es una captura de pantalla de la batalla de Onmyoji, en la que el daño del personaje, el rendimiento actual, la cantidad de fantasmas, si es crítico y el estado de supervivencia de Shikigami, etc., todo depende del texto para mostrar y retroalimentar información interactiva para el jugador.
Aquí, primero muestre la información del volumen de sangre en la barra de sangre, como se muestra a continuación:
2. Componente de texto - TextComponent
Flame
En , use el TextComponent
widget para mostrar texto. Sabemos Flutter
que el TextPainter
texto se puede dibujar a través de la clase en el dibujo. De hecho, la TextComponent
construcción es esencialmente TextPainter
una capa de encapsulación. Se proporciona una TextPaint
clase para su uso.
El siguiente Liveable
es el procesamiento en , solo cree un TextComponent
objeto y agréguelo usando el add
método . Además, cualquier componente add(RectangleHitbox)
puede de , lo cual es conveniente para ver el área ocupada. Consulte el código: 【06/01】
final TextStyle _defaultTextStyle = const TextStyle(fontSize: 10, color: Colors.white);
late final TextComponent _text;
void initPaint({
required double lifePoint,
Color lifeColor = Colors.red,
Color outlineColor = Colors.white,
}) {
// 略...
// 添加生命值文字
_text = TextComponent(textRenderer: TextPaint(style: _defaultTextStyle));
_updateLifeText();
// 添加外框信息
_text.add(RectangleHitbox()..debugMode = true);
add(_text);
}
void _updateLifeText(){
_text.text = 'Hp ${_currentLife.toInt()}';
}
复制代码
Como se puede ver a continuación, por defecto TextComponent
está alineado con la esquina superior izquierda del área principal. Además, TextComponent
también es una PositionComponent
familia de componentes, y podemos realizar operaciones como traslación, escalado y rotación sobre ella.
Por ejemplo, lo siguiente se tag1
coloca junto al especificado, el_text
lado izquierdo se alinea con la barra de estado y encima de la barra de estado:position
// 添加生命值文字
_text = TextComponent(textRenderer: TextPaint(style: _defaultTextStyle));
_updateLifeText();
double y = -(offsetY+_text.height+2);
double x = (size.x/2)*(1-widthRadio);
_text.position = Vector2(x, y); // tag1
add(_text);
复制代码
Después de eliminar el cuadro de información, se muestra de la siguiente manera, y la vida se reduce cuando se hace clic. Se puede mostrar _updateLifeText
actualizando texto:
3. Mostrar datos de daños
Cuando el monstruo es atacado, los datos de daño generalmente se mostrarán para permitir que el operador tenga una experiencia más intuitiva. Ahora se espera que cuando un monstruo resulte herido, la cantidad de daño se muestre a la izquierda y el daño desaparecerá automáticamente 1s
después de que se mantenga la . Como se muestra a continuación: ver el código [06/02]
伤害数据是在 Liveable
中维护的,虽然可以直接在 Liveable
中添加文字。但这样的话会使得 Liveable
的职能过于复杂,也不利于后续的拓展。我们可以单独定义一个 DamageText
构件,来维护伤害数值的显示逻辑。
如下代码所示,在 Liveable
中添加一个 addDamage
的方法,在 tag1
处添加 damageText
文字。然后使用 Future.delayed
方法,延迟 1s
中,调用 damageText.removeFromParent
方法即可移除。
class DamageText extends PositionComponent{
final TextStyle _damageTextStyle = const TextStyle(
fontSize: 14,
color: Colors.white,
fontFamily: 'Menlo',
shadows: [
Shadow(color: Colors.red, offset: Offset(1, 1), blurRadius: 1),
]);
Future<void> addDamage(int damage) async {
TextComponent damageText =
TextComponent(textRenderer: TextPaint(style: _damageTextStyle));
damageText.text = damage.toString();
damageText.position = Vector2(-30, 0);
add(damageText); // tag1
await Future.delayed(const Duration(seconds: 1));
damageText.removeFromParent();
}
}
复制代码
这样在 Liveable
中就不必处理具体添加伤害文字的逻辑,只需要通过 DamageText
来管理即可。比如在 loss
方法中,当角色受到伤害,通过 _damageText.addDamage
来添加伤害文字,这样处理就非常方便。想要对伤害文字进行显示进行修改或拓展,直接在 DamageText
处理即可,这就是职责的分离。
final DamageText _damageText = DamageText();
void initPaint({
required double lifePoint,
Color lifeColor = Colors.red,
Color outlineColor = Colors.white,
}) {
// 略...
add(_damageText);
}
void loss(double point) {
_damageText.addDamage(-point.toInt());
// 略...
}
复制代码
4. 暴击伤害
这里来模拟一下产生暴击的情况:如下图所示,伤害时有一定概率产生暴击,此时使用另一种文字样式。并给出 暴击
的字样提示:代码见 【06/03】
实现也比较简单,在 addDamage
中,传入 isCrit
的入参,区分是否暴击。如果是暴击,使用 _addCritDamage
进行处理,添加黄色伤害和暴击字样即可。
---->[DamageText]----
void addDamage(int damage,{bool isCrit = false}) {
if(!isCrit){
_addWhiteDamage(damage);
}else{
_addCritDamage(damage);
}
}
Future<void> _addCritDamage(int damage) async {
TextComponent damageText =
TextComponent(textRenderer: TextPaint(style: _critDamageTextStyle));
damageText.text = damage.toString();
damageText.position = Vector2(-30, 0);
TextStyle style = _critDamageTextStyle.copyWith(fontSize: 10);
TextComponent infoText = TextComponent(textRenderer: TextPaint(style:style ));
infoText.text = '暴击';
infoText.position = Vector2(-30+damageText.width-infoText.width/2, -infoText.height/2);
add(infoText);
add(damageText);
await Future.delayed(const Duration(seconds: 1));
infoText.removeFromParent();
damageText.removeFromParent();
}
复制代码
暴击和爆伤,本应是角色的属性,这里暂时不搞这么复杂,在 Liveable
的 loss
方法中,用 75%
暴击和 165%
爆伤进行简单的测试,代码如下:
---->[Liveable]----
final Random _random = Random();
void loss(double point) {
double crit = 0.75;
double critDamage = 1.65;
bool isCrit = _random.nextDouble() < crit;
if (isCrit) {
point = point * critDamage;
}
_damageText.addDamage(-point.toInt(),isCrit: isCrit);
// 略...
}
复制代码
5.多次伤害
1s
El daño desaparece después de .Cuando el daño continuo está dentro de un segundo, o cuando se agregan múltiples daños a un daño, se producirá una oclusión. Por lo tanto, es necesario realizar el procesamiento de compensación en daños múltiples, y el efecto es el siguiente: consulte el código [06/04]
Aquí se explota una característica Component
de , cada uno Component
tiene una children
propiedad que representa una colección de subcomponentes. addDamage
En , solo necesita obtener el último elemento de acuerdo con la colección para determinar el desplazamiento del texto agregado:
void addDamage(int damage,{bool isCrit = false}) {
Vector2 offset = Vector2(-30, 0);
if(children.isNotEmpty){
final PositionComponent last;
if(children.last is PositionComponent){
last = children.last as PositionComponent;
offset = last.position + Vector2(5, last.height);
}
}
if(!isCrit){
_addWhiteDamage(damage,offset);
}else{
_addCritDamage(damage,offset);
}
}
复制代码
El texto en sí es relativamente simple, pero el mantenimiento de datos y el procesamiento lógico relacionado con el texto siguen siendo muy complicados. Este artículo explica brevemente cómo se utiliza el texto mostrando la 生命值
suma de los roles . 伤害值
En los juegos en general, las imágenes se utilizan como texto, como los números de daño de Onmyoji. Recuerde que debe haber herramientas para que las imágenes formen fuentes, como 6000
la cadena de , que corresponderá a las imágenes relevantes en la fuente. Sin embargo, se siente que el flame
marco es demasiado simple y no debería ser apoyado.
Eso es todo por este artículo, nos vemos mañana~
@张风捷特烈 2022.05.31 未允禁转
我的 公众号: 编程之王
我的 掘金主页
: Zhang Fengjieteli我的 B站主页
: Zhang Fengjieteli我的 github 主页
: toly1994328
\