Skip to content

Commit 0089f42

Browse files
committed
feat: completed DoE implementation
1 parent 4d1c218 commit 0089f42

File tree

5 files changed

+124
-22
lines changed

5 files changed

+124
-22
lines changed

CHANGELOG.md

+14-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
## v1.1
22

3-
- Fix a bug with inconsistent projectile speed
4-
- Fix broken spicy pepper test
5-
- Remove executable jar from tracked files (it can be accessed via the releases page)
3+
### New features
4+
- Added a new boss: Duke of Eyes!
5+
6+
### Tweaks and changes
7+
- Increased invincibility duration after being hit by an attack to .5 seconds
8+
9+
### Bugfixes
10+
- Fixed a bug with inconsistent projectile speed
11+
12+
### Dev notes
13+
- Added a new `Attack` class that features different attack patterns that can be used by any generic entity.
14+
- Removed executable jar from tracked files (it can be accessed via the releases page)
15+
- Fixed broken spicy pepper test
16+
- Refactored enemy projectile spawn in the decorators to use the generic methods provided by the `Attack` class

src/main/java/tbooop/model/boss/attacks/Attack.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ public static void vomit(Entity source, Point2d target,
2626
double scatterAngle = r.nextDouble(-maxScatterAngle, maxScatterAngle);
2727
Vector2d vec = new Vector2dImpl(target
2828
.subtract(source.getPosition()).toV2d()).normalize();
29-
double speed = r.nextDouble(maxprojSpeed - (projSpeedVariation * maxprojSpeed), maxprojSpeed);
29+
double speed = r.nextDouble(maxprojSpeed - (projSpeedVariation / 100 * maxprojSpeed), maxprojSpeed);
3030
EnemyProjectile proj = new EnemyProjectile(vec.rotate(scatterAngle), source.getPosition(), speed);
3131
source.addProjectile(proj);
3232
}
3333

3434
/** Returns the next direction */
3535
public static Vector2d spiral(Entity source, double projSpeed, Vector2d direction, double angle) {
36-
Vector2d newDir = direction.rotate(angle);
36+
Vector2d newDir = direction.rotate(angle).normalize();
3737
EnemyProjectile proj = new EnemyProjectile(newDir, source.getPosition(), projSpeed);
3838
source.addProjectile(proj);
3939
return newDir;
@@ -59,7 +59,7 @@ public static void radiusWithGap(Entity source, double projSpeed, int projectile
5959
angles.add(i * angle);
6060
}
6161
removeUpToNElements(angles, gapSize).forEach(a -> source.addProjectile(
62-
new EnemyProjectile(Direction.RIGHT.toP2d().toV2d().rotate(a),
62+
new EnemyProjectile(Direction.RIGHT.toP2d().toV2d().rotate(a).normalize(),
6363
source.getPosition(), projSpeed)));
6464
}
6565

src/main/java/tbooop/model/boss/impl/DukeOfEyes/DoEAngered.java

+83-2
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,107 @@
11
package tbooop.model.boss.impl.DukeOfEyes;
22

3+
import tbooop.commons.api.Vector2d;
4+
import tbooop.commons.api.Vector2dUtils;
5+
import tbooop.model.boss.attacks.Attack;
36
import tbooop.model.boss.impl.DukeOfEyes.DoESM.State;
47
import tbooop.model.boss.stateMachine.api.AbstractState;
58
import tbooop.model.enemy.api.ai.MovementAi;
69
import tbooop.model.enemy.impl.ai.ChasingAi;
710
import tbooop.model.player.api.Player;
11+
import java.util.Random;
812

913
public class DoEAngered extends AbstractState<DoESM.State> {
1014

15+
private static final double VELOCITY_MULTIPLIER = 1.6;
16+
private static final long TIME_BETWEEN_ATTACKS = 3000;
17+
private static final long ATK_DURATION = 1000;
18+
private static final long ATK_FREQUENCY = 20;
19+
private static final double PROJECTILE_SPEED = 0.16;
1120
private DukeOfEyes doe;
21+
private Player p;
1222
private MovementAi ai;
23+
private double velocity;
24+
private long timeSinceLastAttack;
25+
private boolean isAttacking;
26+
private AttackType attackType;
27+
Random rand = new Random();
1328

1429
public DoEAngered(DukeOfEyes doe, Player p) {
1530
super(doe);
1631
this.doe = doe;
32+
this.p = p;
1733
ai = new ChasingAi(p);
34+
velocity = doe.getVelocity() * VELOCITY_MULTIPLIER;
1835
}
1936

37+
@Override
38+
public void onStateEnter() {
39+
timeSinceLastAttack = TIME_BETWEEN_ATTACKS - 1;
40+
}
41+
42+
private long atkWindowTime;
43+
private long atkFreqTime;
44+
2045
@Override
2146
public void updateState(long deltaTime) {
22-
var nextPos = ai.newPosition(doe.getPosition(), deltaTime, doe.getVelocity());
23-
doe.setPosition(nextPos);
47+
if (!(isAttacking && attackType == AttackType.SPIRAL)) {
48+
var nextPos = ai.newPosition(doe.getPosition(), deltaTime, velocity);
49+
doe.setPosition(nextPos);
50+
}
51+
this.timeSinceLastAttack += deltaTime;
52+
if (isAttacking) {
53+
attack(deltaTime);
54+
}
55+
if (this.timeSinceLastAttack >= TIME_BETWEEN_ATTACKS) {
56+
this.timeSinceLastAttack = 0;
57+
setAttackMode(true);
58+
}
59+
}
60+
61+
private void attack(long deltaTime) {
62+
atkWindowTime += deltaTime;
63+
atkFreqTime += deltaTime;
64+
if (atkWindowTime >= ATK_DURATION) {
65+
setAttackMode(false);
66+
return;
67+
}
68+
if (atkFreqTime >= ATK_FREQUENCY) {
69+
atkFreqTime = 0;
70+
performAttack();
71+
}
72+
}
73+
74+
private Vector2d dir = Vector2dUtils.randomNorm();
75+
76+
private void performAttack() {
77+
switch (attackType) {
78+
case SPIRAL:
79+
dir = Attack.spiral(doe, PROJECTILE_SPEED / 2, dir, 35);
80+
break;
81+
case VOMIT:
82+
Attack.vomit(doe, p.getPosition(), 10, PROJECTILE_SPEED, 30);
83+
break;
84+
}
85+
}
86+
87+
private enum AttackType {
88+
VOMIT,
89+
SPIRAL;
90+
}
91+
92+
private void setAttackMode(boolean isAttacking) {
93+
this.isAttacking = isAttacking;
94+
atkWindowTime = 0;
95+
atkFreqTime = 0;
96+
if (isAttacking) {
97+
setRandomAttackType();
98+
}
99+
}
100+
101+
private void setRandomAttackType() {
102+
AttackType[] attackTypes = AttackType.values();
103+
int index = rand.nextInt(attackTypes.length);
104+
attackType = attackTypes[index];
24105
}
25106

26107
@Override

src/main/java/tbooop/model/boss/impl/DukeOfEyes/DoERoam.java

+23-13
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
package tbooop.model.boss.impl.DukeOfEyes;
22

3-
import tbooop.commons.api.Vector2d;
43
import tbooop.commons.api.Vector2dUtils;
54
import tbooop.model.boss.attacks.Attack;
65
import tbooop.model.boss.impl.DukeOfEyes.DoESM.State;
76
import tbooop.model.boss.stateMachine.api.AbstractState;
87
import tbooop.model.enemy.api.ai.MovementAi;
98
import tbooop.model.enemy.impl.ai.BouncingAi;
109
import tbooop.model.player.api.Player;
10+
import java.util.Random;
1111

1212
public class DoERoam extends AbstractState<DoESM.State> {
1313

14-
private MovementAi ai;
14+
private static final long TIME_BETWEEN_ATTACKS = 3000;
15+
private static final double PROJECTILE_SPEED = 0.08;
1516
private DukeOfEyes doe;
1617
private Player p;
17-
private static final long TIME_BETWEEN_ATTACKS = 200;
18-
private static final double PROJECTILE_SPEED = 0.08;
19-
private long timeSinceLastShoot;
18+
private MovementAi ai;
19+
private long timeSinceLastAttack;
20+
Random rand = new Random();
2021

2122
public DoERoam(DukeOfEyes doe, Player p) {
2223
super(doe);
@@ -25,23 +26,32 @@ public DoERoam(DukeOfEyes doe, Player p) {
2526
ai = new BouncingAi(Vector2dUtils.randomNorm().toP2d(), doe.getCollider().getRadius());
2627
}
2728

28-
private Vector2d dir = Vector2dUtils.randomNorm();
29-
3029
@Override
3130
public void updateState(long deltaTime) {
3231
var nextPos = ai.newPosition(doe.getPosition(), deltaTime, doe.getVelocity());
33-
// doe.setPosition(nextPos); TODO uncomment
34-
this.timeSinceLastShoot += deltaTime;
35-
if (this.timeSinceLastShoot >= TIME_BETWEEN_ATTACKS) {
36-
this.timeSinceLastShoot = 0;
37-
dir = Attack.multiSpiral(doe, PROJECTILE_SPEED, dir, 20, 4);
38-
// Attack.snipe(doe, p.getPosition(), PROJECTILE_SPEED);
32+
doe.setPosition(nextPos);
33+
this.timeSinceLastAttack += deltaTime;
34+
if (this.timeSinceLastAttack >= TIME_BETWEEN_ATTACKS) {
35+
this.timeSinceLastAttack = 0;
36+
performRandomAttack();
3937
}
38+
}
4039

40+
private void performRandomAttack() {
41+
switch (rand.nextInt(2)) {
42+
case 0:
43+
Attack.radiusWithGap(doe, PROJECTILE_SPEED, 20, 4);
44+
break;
45+
default:
46+
Attack.snipe(doe, p.getPosition(), PROJECTILE_SPEED * 2);
47+
}
4148
}
4249

4350
@Override
4451
public State getNextStateKey() {
52+
if (doe.getHealth() <= doe.getMaxHealth() / 2) {
53+
return State.ANGERED;
54+
}
4555
return State.ROAMING;
4656
}
4757

src/main/java/tbooop/model/boss/impl/DukeOfEyes/DukeOfEyes.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
public class DukeOfEyes extends AbstractBoss<DoESM.State> {
88

99
public DukeOfEyes(Player p) {
10-
super(new HealthImpl(20), 0.035, 30);
10+
super(new HealthImpl(30), 0.035, 14);
1111
setStateMachine(new DoESM(this, p));
1212
}
1313
}

0 commit comments

Comments
 (0)