Continue to create, accelerate growth! This is the 12th day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the event details
foreword
This is a series of tutorials produced by Zhang Fengjietlie and published in the Nuggets community. Flutter&Flame
If you see this article on other platforms, you can move to the Nuggets to view it according to the link. Because the article may be updated and revised, the version of the Nuggets article shall prevail. List of articles in this series:
- 【Flutter&Flame Game-One】Open the door to a new world
- 【Flutter&Flame Game - Ⅱ】Joystick and Character Movement
- 【Flutter&Flame Game - 3】Keyboard Events and Gesture Operation
- 【Flutter&Flame game - 4】Sprite image loading method
- 【Flutter&Flame Game - Wu】Canvas Participation | Character's Health Bar
- 【Flutter&Flame Game - Lu】Critical Dash | Use of Text Components
- 【Flutter&Flame Game - 7】People follow the finger | Animation touch and move
- 【Flutter&Flame Game - 摌】Finished reloading | Character weapon launch
- 【Flutter&Flame Game - Nine】Explore Component | What is Component
- [Flutter&Flame Game - Pickup] Explore Component | Component Lifecycle Callback
- 【Flutter&Flame Game - Pick One】Explore Component | Component Usage Details (
本文
)
1. About the component tree
As shown in the scene below, each displayed object is Component
, they form a tree structure. See [11/01] for the code
Various roles are added to the tree through the add
method , and the tree structure at this time is as follows:
Now there's a problem: because the health bar and volume are added to the Adventurer
widget , Adventurer
the transformation behavior of the will also cause the health bar to change. The following characters are mirrored along the Y axis, and you can see that the health bar and text are also mirrored, which is not what we expected.
How to solve it? The idea is very simple, since Adventurer
there is a need for a separate mirror, it cannot be the parent of the health bar. The relationship between the two can be changed from a parent-child relationship to a brother relationship. Here, the blood bar is encapsulated as LifeComponent
build , and Adventurer
exist together with HeroComponent
in :
2. Mirror reversal in character movement
Now I want to achieve the following effect: if the touch point is on the left side of the character, the character will be mirrored to the left, otherwise, the mirror will be reversed to the right. The purpose of this is so that the character can choose the direction of the attack, such as facing the left to attack the monster on the left: see the code [11/02]
Since only the left and right are reversed here HeroComponent
, define a value ofisLeft
in to record the state. bool
If you need to support other directions, such as up, down, top left, bottom right, etc., you can maintain it through enumeration.
---->[HeroComponent]----
bool isLeft = true;
late Adventurer adventurer;
late LifeComponent lifeComponent;
复制代码
When the screen is clicked, the toTarget
method . At the beginning, the method can be _checkFlip
used to maintain the isLeft
property . If it needs to be flip
reversed, the role is reversed:
---->[HeroComponent#toTarget]----
void toTarget(Vector2 target) {
_checkFlip(target);
// 略同...
}
void _checkFlip(Vector2 target){
if (target.x < position.x) {
if (isLeft) {
flip();
isLeft = false;
}
}
if (target.x > position.x) {
if (!isLeft) {
flip();
isLeft = true;
}
}
}
复制代码
Used to only want to reverse the protagonist, so flip
in , execute adventurer.flip
. This will not affect the display of the blood bar:
void flip({
bool x = false,
bool y = true,
}) {
adventurer.flip(x: x, y: y);
}
复制代码
---->[HeroComponent#flip]----
void flip({
bool x = false,
bool y = true,
}) {
adventurer.flip(x: x, y: y);
}
复制代码
In addition, regarding the reversal, you also need to pay attention to the direction in which the bullet is fired. Because the front bullet is always fired to the right, if facing left, it should move left, like this:
It is also relatively simple to deal with, according to whether isLeft
it is really left or right to launch, as followstag1
---->[Bullet]----
@override
void update(double dt) {
super.update(dt);
Vector2 ds = Vector2(isLeft ? 1 : -1, 0) * speed * dt; // tag1
_length += ds.length;
position.add(ds);
if (_length > maxRange) {
_length = 0;
removeFromParent();
}
}
复制代码
3. About the maintenance of properties
In order to facilitate the demonstration, the attributes of the characters are relatively scattered, such as speed and attack power. Since it can be encapsulated here HeroComponent
to maintain the protagonist class. You can define a HeroAttr
class to maintain the properties of the main character, as follows:
class HeroAttr {
double life; // 生命值
double speed; // 速度
double attackSpeed; // 攻击速度
double attackRange; // 射程
double attack; // 攻击力
double crit; // 暴击率
double critDamage; // 暴击伤害
HeroAttr({
required this.life,
required this.speed,
required this.attackSpeed,
required this.attackRange,
required this.attack,
required this.crit,
required this.critDamage,
});
}
复制代码
In this way, HeroComponent
when , pass HeroAttr
in the object to determine the attribute information of the object.
---->[TolyGame#onLoad]----
final HeroAttr heroAttr = HeroAttr(
life: 3000,
speed: 100,
attackSpeed: 200,
attackRange: 200,
attack: 50,
crit: 0.75,
critDamage: 1.5,
);
player = HeroComponent(attr: heroAttr);
add(player);
复制代码
In this way, the loss of life value in the monster can be calculated according to HeroAttr
the attribute of :
---->[Liveable]----
void loss(HeroAttr attr) {
double point = attr.attack;
double crit = attr.crit;
double critDamage = attr.critDamage;
bool isCrit = _random.nextDouble() < crit;
if (isCrit) {
point = point * critDamage;
}
_damageText.addDamage(-point.toInt(), isCrit: isCrit);
}
复制代码
When adding bullets, the attack speed and range can be determined according to HeroAttr
the attribute information of :
In this article, we continue to expand the function of roles, knowing that the transformation of parent components will affect child components, so you need to pay attention to the relationship between components when using components. In addition, the character information is HeroAttr
encapsulated , so that through HeroComponent
, you can add multiple protagonist nodes, and you can fight monsters in double mode.
At this point, you can see TolyGame
that it is very chaotic. In the next chapter, I will introduce how to manage multiple characters and monsters, including the generation of monsters, firing bullets, hitting the protagonist, etc. That's it for this article, see you tomorrow~
@张风捷特烈 2022.06.05 未允禁转
我的 公众号: 编程之王
我的 掘金主页
: Zhang Fengjieteli我的 B站主页
: Zhang Fengjieteli我的 github 主页
: toly1994328
\