foreword
敌机Component
After the reconstruction, the basic capabilities of aircraft warfare are basically formed. This article will make an upgrade, add bullet props子弹Component
in the game , and deal with collisions with it .战机Component
The author has included this series of articles in the following columns, and interested students are welcome to read:
bullet characteristics
The front is just a simple definition of a class Bullet1
, 子弹Component
according to the existing attributes, a bullet can be defined 父类Bullet
, continue to use the abstract class here.
abstract class Bullet extends SpriteAnimationComponent with CollisionCallbacks {
Bullet({required this.speed, required this.attack})
: super(size: Vector2(5, 11));
double speed;
int attack;
Future<SpriteAnimation> bulletAnimation();
@override
Future<void> onLoad() async {
animation = await bulletAnimation();
add(MoveEffect.to(
Vector2(position.x, -size.y), EffectController(speed: speed),
onComplete: () {
removeFromParent();
}));
add(RectangleHitbox());
}
void loss() {
removeFromParent();
}
}
复制代码
The definition is relatively simple
- Bullets have their own speed
speed
and damageattack
. - fixed
size = 5 * 11
. - Since the textures of different bullets are different , define an abstract method to
bulletAnimation()
be loaded by subclasses. - Use to
MoveEffect
replace the previouss = v * t
control movement, which was mentioned earlier. Here it is moved from the initial position (usually战机Component
the head) to the top of the screen . loss()
method is敌机Component
called when a collision occurs with.
The above list is the common characteristics of current bullets.
upgrade bullet
In the game, you 战机Component
will obtain enhanced bullets for a short time by obtaining props . expressed here类Bullet2
class Bullet2 extends Bullet {
Bullet2({required super.speed, required super.attack});
@override
Future<SpriteAnimation> bulletAnimation() async {
List<Sprite> sprites = [];
sprites.add(await Sprite.load('bullet/bullet2.png'));
final SpriteAnimation spriteAnimation =
SpriteAnimation.spriteList(sprites, stepTime: 0.15);
return spriteAnimation;
}
}
复制代码
Here another texture will be loaded as the bullet's style.
Let's take a look at the final effect
ammo supply
如上面的效果,游戏中会随机生成子弹补给。这里定义一个抽象类Supply
。补给Component
的效果是匀速向下移动并带有小幅度的晃动。
- 匀速向下移动继续采用
MoveEffect
的方式。 - 小幅度的晃动需要使用
RotateEffect
做一个小幅度的旋转。由于需要一个吊起来来回晃动的效果,所以我们还需要将锚点设置为topCenter
,令旋转支点为上方居中的位置。
故最后的逻辑为
abstract class Supply extends SpriteComponent with HasGameRef {
Supply({position, size})
: super(position: position, size: size, anchor: Anchor.topCenter);
@override
Future<void> onLoad() async {
add(MoveEffect.to(
Vector2(position.x, gameRef.size.y), EffectController(speed: 40.0),
onComplete: () {
removeFromParent();
}));
add(RotateEffect.by(15 / 180 * pi,
EffectController(duration: 2, reverseDuration: 2, infinite: true)));
add(RectangleHitbox()..debugMode = true);
}
}
复制代码
- 移动距离是从屏幕最上方向屏幕最下方移动。
- 旋转角度是弧度,这里是
(15 / 180)pi
,需要来回晃动,所以这里设置了正反方向的持续时间且效果是无限循环的。 - 最后需要添加
RectangleHitbox
,作为与战机Component
的碰撞检测。ps:碰撞检测的逻辑在子类实现,这里目前是类BulletSupply
。
子类的逻辑几乎只有碰撞检测,这个在下文会讲到,先来看看这个实现的效果
升级与恢复
在子弹补给Component
中,碰撞检测与战机Component
发生碰撞后
- 会触发其
upgradeBullet()
方法,此时会变更bulletType
,即子弹类型。 - 添加一个
0.15s
的ColorEffect
,作为子弹升级的反馈。 - Turn on one
Timer
, timed5s
, as the bullet returns to normal timing . ps:_bulletUpgradeTimer
setautoStart = false
, do not allow automatic opening . When calledstart()
, the progress will be reset , which can be understood as the timing of continuously obtaining supplies will be reset.
// class BulletSupply
@override
void onCollisionStart(
Set<Vector2> intersectionPoints, PositionComponent other) {
super.onCollisionStart(intersectionPoints, other);
if (other is Player) {
other.upgradeBullet();
removeFromParent();
}
}
// class Player
int bulletType = 1;
_bulletUpgradeTimer = Timer(5, onTick: _downgradeBullet, autoStart: false);
void upgradeBullet() {
bulletType = 2;
add(ColorEffect(Colors.blue.shade900, const Offset(0.3, 0.0),
EffectController(duration: 0.15)));
_bulletUpgradeTimer.start();
}
void _downgradeBullet() {
bulletType = 1;
}
// timer.dart
/// Start the timer from 0.
void start() {
reset();
resume();
}
复制代码
Since 战机Component
it 类Player
has a timer for firing bullets, after the bullet type is bulletType
modified, the logic for the next bullet firing needs to be changed .
// class Player
void _addBullet() {
if (bulletType == 2) {
final Bullet2 bullet2 = Bullet2(speed: 400, attack: 2);
bullet2.priority = 1;
bullet2.position = Vector2(position.x + size.x / 2 - 10, position.y + 10);
final Bullet2 bullet2a = Bullet2(speed: 400, attack: 2);
bullet2a.priority = 1;
bullet2a.position =
Vector2(position.x + size.x / 2 + 10, position.y + 10);
gameRef.add(bullet2);
gameRef.add(bullet2a);
} else {
final Bullet1 bullet1 = Bullet1(speed: 200, attack: 1);
bullet1.priority = 1;
bullet1.position = Vector2(position.x + size.x / 2, position.y);
gameRef.add(bullet1);
}
}
复制代码
Supply generation
Remember that 敌机生成器EnemyCreator
? Here temporarily through its timing to generate supplies
// class EnemyCreator
void _createEnemy() {
final width = gameRef.size.x;
double x = _random.nextDouble() * width;
final double random = _random.nextDouble();
if (random < 0.05) {
final size = Vector2(60, 75);
if (width - x < size.x / 2) {
x = width - size.x / 2;
} else if (x < size.x / 2) {
x = size.x / 2;
}
final enemySupply =
BulletSupply(position: Vector2(x, -size.y), size: size);
add(enemySupply);
return;
}
。。。
复制代码
It should be noted that since 补给Component
the anchor point of ' is modified totopCenter
, position
the position of ' ' has also been moved totopCenter
. The boundary calculation here needs to be adapted according to this situation.
at last
This article records the expansion of bullet types, the effect and generation of bullet supply, and战机Component
the logic of bullet upgrades . So far, the functions of the aircraft war have basically been realized, and the remaining functions such as additional props, scoring system and health value system. In the future, we will consider modifying the structure of the entire project with reference to official bloc
examples.