17.6. Projectiles
Shoot
Dans cet état le boss tire une série de projectiles en spirale. Afin de représenter cette attaque, nous aurons besoin d'une nouvelle attaque ProjectileAttack
. Pour l'effet de spiral, il est simplement question d'appliquer une rotation de manière incrémentale au vecteur de direction du boss et de s'en servir pour créer le projectile.
Étapes à suivre
- Ajoutez la classe
ProjectileAttack
- Ajoutez la classe
ShootState
/* ProjectileAttack.java */
package com.tutorialquest.entities;
// import ..
public class ProjectileAttack extends PhysicalObject implements IAttack
{
public static float SPEED = 50f;
public static Vector2 SIZE = new Vector2(16, 16);
private static final int NUM_HITS = 3;
private int hits = 0;
private Vector2 direction;
private Sprite sprite;
private List<PhysicalObject> collisionResults = new LinkedList<>();
private float damage;
private float knockback;
private float speed = 1f;
@Override
public float getDamage() {
return damage;
}
@Override
public float getKnockback() {
return knockback;
}
@Override
public Vector2 getDirection() {
return direction;
}
public ProjectileAttack(
Vector2 position,
Vector2 direction,
float damage,
float knockback,
float speed)
{
super(position);
this.sprite = new Sprite("objects/projectile.png", SIZE);
this.collider = new Collider(SIZE, Collider.FLAG_ENEMY);
this.direction = direction;
this.damage = damage;
this.knockback = knockback;
this.speed = speed;
this.locomotionVelocity
.set(direction)
.scl(speed);
}
@Override
public void update(float deltaTime) {
super.update(deltaTime);
updateVelocity(deltaTime);
move();
sprite.update(deltaTime);
collisionResults.clear();
if(collider.getObjectCollisions(
this,
velocity.x,
velocity.y,
Collider.FLAG_AVATAR,
collisionResults))
{
collisionResults.iterator().next().onAttacked(this);
destroy();
return;
}
if(collider.isColliding(this, velocity, Collider.FLAG_NONE))
{
destroy();
}
}
public void destroy()
{
Game.level.remove(this);
}
@Override
public void render(SpriteBatch spriteBatch) {
super.render(spriteBatch);
sprite.render(spriteBatch, position);
}
@Override
public void onAttacked(IAttack attack)
{
sprite.flash();
onPushed(this, attack.getDirection().scl(attack.getKnockback()));
hits++;
if(hits >= NUM_HITS)
{
Game.level.remove(this);
}
}
}
/* ShootState.java */
package com.tutorialquest.entities;
// import ..
public class ShootState extends BossState {
public static final float ROTATION_SPEED = 30f;
@Override
public String getName() {
return "Shoot Spiral";
}
public ShootState(
Boss boss,
StateMachine stateMachine,
int id,
float probability,
float timeLimit,
int timeoutState)
{
super(
boss,
stateMachine,
id,
probability,
timeLimit,
timeoutState);
}
@Override
public boolean update(float deltaTime) {
if (!super.update(deltaTime)) return false;
fireRateTime += deltaTime;
if (fireRateTime >= Boss.FIRE_RATE) {
fireRateTime = 0;
Game.level.add(
new ProjectileAttack(
new Vector2()
.add(boss.direction)
.scl(Boss.PROJECTILE_DISTANCE)
.add(boss.position),
boss.direction.cpy(),
Boss.PROJECTILE_DAMAGE,
Boss.PROJECTILE_KNOCKBACK,
Boss.PROJECTILE_SPEED)
);
boss.direction
.rotate(ROTATION_SPEED)
.nor();
}
return true;
}
@Override
public void enter() {
super.enter();
boss.direction = new Vector2(1, 0);
boss.playAnimation(Boss.SpriteUtils.SHOOT, true, true);
}
}