Skip to content

Commit 1e43ef6

Browse files
authored
Merge pull request #206 from powerpuff-luv/main
[Feature]: Added level progress bar
2 parents 729c6ec + 66b93d3 commit 1e43ef6

File tree

7 files changed

+122
-6
lines changed

7 files changed

+122
-6
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.dinosaur.dinosaurexploder.components;
2+
3+
import com.almasb.fxgl.animation.Interpolators;
4+
import com.almasb.fxgl.dsl.FXGL;
5+
import com.almasb.fxgl.entity.component.Component;
6+
import com.dinosaur.dinosaurexploder.utils.LevelManager;
7+
import javafx.scene.shape.Rectangle;
8+
import javafx.util.Duration;
9+
10+
/**
11+
* Summary:
12+
* This class extends Component and handles filling the level progress bar
13+
*/
14+
public class LevelProgressBarComponent extends Component {
15+
private static final double MAX_WIDTH = 148;
16+
private static final Duration UPDATE_DURATION = Duration.seconds(0.3);
17+
private static final Duration RESET_DURATION = Duration.seconds(0.5);
18+
19+
private final Rectangle fill;
20+
private final LevelManager levelManager;
21+
private boolean isLocked = false;
22+
23+
public LevelProgressBarComponent(Rectangle fill, LevelManager levelManager) {
24+
this.fill = fill;
25+
this.levelManager = levelManager;
26+
}
27+
28+
public void updateProgress() {
29+
if (isLocked) return;
30+
31+
float progress = Math.min(levelManager.getLevelProgress(), 1);
32+
updateWidth(MAX_WIDTH * progress, UPDATE_DURATION);
33+
34+
if (progress >= 1) isLocked = true;
35+
}
36+
37+
public void resetProgress() {
38+
isLocked = false;
39+
40+
float progress = Math.min(levelManager.getLevelProgress(), 1);
41+
updateWidth(MAX_WIDTH * progress, RESET_DURATION);
42+
}
43+
44+
private void updateWidth(double targetWidth, Duration duration) {
45+
FXGL.animationBuilder()
46+
.duration(duration)
47+
.interpolator(Interpolators.EXPONENTIAL.EASE_OUT())
48+
.animate(fill.widthProperty())
49+
.from(fill.getWidth())
50+
.to(targetWidth)
51+
.buildAndPlay();
52+
}
53+
}

src/main/java/com/dinosaur/dinosaurexploder/constants/EntityType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
* This handles with all the entities in the game like lives, player projectile etc.
55
*/
66
public enum EntityType {
7-
PLAYER, GREEN_DINO,RED_DINO, PROJECTILE, ENEMY_PROJECTILE, SCORE, LIFE, BOMB, COIN, HEART, LEVEL, HEALTHBAR
7+
PLAYER, GREEN_DINO,RED_DINO, PROJECTILE, ENEMY_PROJECTILE, SCORE, LIFE, BOMB, COIN, HEART, LEVEL, HEALTHBAR, LEVEL_PROGRESS_BAR
88
}

src/main/java/com/dinosaur/dinosaurexploder/controller/DinosaurController.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.almasb.fxgl.dsl.FXGL;
44
import com.almasb.fxgl.entity.Entity;
5+
import com.almasb.fxgl.entity.SpawnData;
56
import com.almasb.fxgl.time.TimerAction;
67
import com.dinosaur.dinosaurexploder.components.*;
78
import com.dinosaur.dinosaurexploder.constants.EntityType;
@@ -34,6 +35,7 @@ public class DinosaurController {
3435
private CollectedCoinsComponent collectedCoinsComponent;
3536
private Entity levelDisplay;
3637
private Entity life;
38+
private Entity levelProgressBar;
3739
private LevelManager levelManager;
3840
private TimerAction enemySpawnTimer;
3941
private boolean isSpawningPaused = false;
@@ -87,8 +89,8 @@ public void initInput() {
8789
}
8890

8991
public void initGame() {
90-
initGameEntities();
9192
levelManager = new LevelManager();
93+
initGameEntities();
9294
collisionHandler = new CollisionHandler(levelManager);
9395
bossSpawner = new BossSpawner(settings, levelManager);
9496
CoinSpawner coinSpawner = new CoinSpawner(10, 1.0);
@@ -114,6 +116,7 @@ private void initGameEntities() {
114116
Entity coin = spawn("Coins", getAppCenter().getX() - 260, getAppCenter().getY() - 235);
115117
collectedCoinsComponent = coin.getComponent(CollectedCoinsComponent.class);
116118
bomb.addComponent(new BombComponent());
119+
levelProgressBar = spawn("levelProgressBar", new SpawnData(getAppCenter().getX() - 170, getAppCenter().getY() + 340).put("levelManager", levelManager));
117120
}
118121

119122
/**
@@ -169,6 +172,11 @@ private void resumeEnemySpawning() {
169172
* and shows a message when the level is changed
170173
*/
171174
private void showLevelMessage() {
175+
// Hide the progress bar for boss levels
176+
if (levelManager.getCurrentLevel() % 5 == 0) {
177+
levelProgressBar.setVisible(false);
178+
}
179+
172180
//Pause game elements during level transition
173181
FXGL.getGameWorld().getEntitiesByType(EntityType.GREEN_DINO).forEach(e -> {
174182
if (e.hasComponent(GreenDinoComponent.class)) {
@@ -192,9 +200,17 @@ private void showLevelMessage() {
192200

193201
// Resume gameplay after a delay
194202
runOnce(() -> {
203+
if (levelManager.getCurrentLevel() % 5 != 0) {
204+
levelProgressBar.setVisible(true);
205+
}
206+
195207
getGameScene().removeUINode(levelText);
196208
updateLevelDisplay();
197209

210+
if (levelProgressBar.hasComponent(LevelProgressBarComponent.class)) {
211+
levelProgressBar.getComponent(LevelProgressBarComponent.class).resetProgress();
212+
}
213+
198214
FXGL.getGameWorld().getEntitiesByType(EntityType.GREEN_DINO).forEach(e -> {
199215
if (e.hasComponent(GreenDinoComponent.class)) {
200216
e.getComponent(GreenDinoComponent.class).setPaused(false);
@@ -250,7 +266,9 @@ public void initPhysics() {
250266
}
251267
projectile.removeFromWorld();
252268
greenDino.removeFromWorld();
253-
if (collisionHandler.isLevelUpAfterHitDino(score.getComponent(ScoreComponent.class))) {
269+
if (collisionHandler.isLevelUpAfterHitDino(
270+
score.getComponent(ScoreComponent.class),
271+
levelProgressBar.getComponent(LevelProgressBarComponent.class))) {
254272
showLevelMessage();
255273
System.out.println("Level up!");
256274
}

src/main/java/com/dinosaur/dinosaurexploder/model/CollisionHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.dinosaur.dinosaurexploder.components.BombComponent;
44
import com.dinosaur.dinosaurexploder.components.CollectedCoinsComponent;
5+
import com.dinosaur.dinosaurexploder.components.LevelProgressBarComponent;
56
import com.dinosaur.dinosaurexploder.components.LifeComponent;
67
import com.dinosaur.dinosaurexploder.components.RedDinoComponent;
78
import com.dinosaur.dinosaurexploder.components.ScoreComponent;
@@ -15,9 +16,10 @@ public CollisionHandler(LevelManager levelManager) {
1516
this.levelManager = levelManager;
1617
}
1718

18-
public boolean isLevelUpAfterHitDino(ScoreComponent scoreComponent) {
19+
public boolean isLevelUpAfterHitDino(ScoreComponent scoreComponent, LevelProgressBarComponent levelProgressBarComponent) {
1920
scoreComponent.incrementScore(1);
2021
levelManager.incrementDefeatedEnemies();
22+
levelProgressBarComponent.updateProgress();
2123

2224
return adjustLevel();
2325
}

src/main/java/com/dinosaur/dinosaurexploder/model/GameEntityFactory.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import com.dinosaur.dinosaurexploder.constants.EntityType;
2020
import com.dinosaur.dinosaurexploder.constants.GameConstants;
2121
import com.dinosaur.dinosaurexploder.utils.FXGLGameTimer;
22+
import com.dinosaur.dinosaurexploder.utils.LevelManager;
2223
import javafx.geometry.Orientation;
2324
import javafx.geometry.Point2D;
25+
import javafx.scene.Group;
2426
import javafx.scene.image.Image;
2527
import javafx.scene.image.ImageView;
2628
import javafx.scene.paint.Color;
@@ -280,6 +282,30 @@ public Entity newLevel(SpawnData data) {
280282
.build();
281283
}
282284

285+
/**
286+
* Summary :
287+
* Creates level progress bar
288+
*/
289+
@Spawns("levelProgressBar")
290+
public Entity newLevelProgressBar(SpawnData data) {
291+
LevelManager levelManager = data.get("levelManager");
292+
293+
Rectangle background = new Rectangle(150, 10, Color.DARKGRAY);
294+
background.setStroke(Color.GRAY);
295+
background.setStrokeWidth(1);
296+
297+
Rectangle filled = new Rectangle(0, 8, Color.LIMEGREEN);
298+
filled.setLayoutX(1);
299+
filled.setLayoutY(1);
300+
301+
Group progressBar = new Group(background, filled);
302+
303+
return entityBuilderBase(data, EntityType.LEVEL_PROGRESS_BAR)
304+
.view(progressBar)
305+
.with(new LevelProgressBarComponent(filled, levelManager))
306+
.build();
307+
}
308+
283309
/**
284310
* Summary :
285311
* Reusable part of every entity

src/main/java/com/dinosaur/dinosaurexploder/utils/LevelManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ public double getEnemySpeed() {
2424
return enemySpeed;
2525
}
2626

27+
public float getLevelProgress() {
28+
return (float) defeatedEnemies / enemiesToDefeat;
29+
}
30+
2731
public void incrementDefeatedEnemies() {
2832
defeatedEnemies++;
2933
}

src/test/java/com/dinosaur/dinosaurexploder/model/CollisionHandlerTest.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import com.almasb.fxgl.entity.Entity;
44
import com.dinosaur.dinosaurexploder.components.BombComponent;
55
import com.dinosaur.dinosaurexploder.components.CollectedCoinsComponent;
6+
import com.dinosaur.dinosaurexploder.components.LevelProgressBarComponent;
67
import com.dinosaur.dinosaurexploder.components.LifeComponent;
78
import com.dinosaur.dinosaurexploder.components.RedDinoComponent;
89
import com.dinosaur.dinosaurexploder.components.ScoreComponent;
910
import com.dinosaur.dinosaurexploder.utils.LevelManager;
1011
import com.dinosaur.dinosaurexploder.utils.MockGameTimer;
12+
import javafx.scene.paint.Color;
13+
import javafx.scene.shape.Rectangle;
1114
import org.junit.jupiter.api.BeforeEach;
1215
import org.junit.jupiter.api.Test;
1316
import org.mockito.Mockito;
@@ -34,17 +37,27 @@ void setUp() {
3437
@Test
3538
void projectileHitDino_thenLevelUp() {
3639
ScoreComponent scoreComponent = new ScoreComponent();
40+
Rectangle rect = new Rectangle(0, 8, Color.LIMEGREEN);
41+
LevelProgressBarComponent levelProgressBarComponent = new LevelProgressBarComponent(rect, levelManager) {
42+
@Override
43+
public void updateProgress() {}
44+
};
3745

38-
for (int i = 0; i < LEVEL_UP_COUNT; i++) collisionHandler.isLevelUpAfterHitDino(scoreComponent);
46+
for (int i = 0; i < LEVEL_UP_COUNT; i++) collisionHandler.isLevelUpAfterHitDino(scoreComponent, levelProgressBarComponent);
3947

4048
assertEquals(2, levelManager.getCurrentLevel());
4149
}
4250

4351
@Test
4452
void projectileHitDino_thenScoreIncrease() {
4553
ScoreComponent scoreComponent = new ScoreComponent();
54+
Rectangle rect = new Rectangle(0, 8, Color.LIMEGREEN);
55+
LevelProgressBarComponent levelProgressBarComponent = new LevelProgressBarComponent(rect, levelManager) {
56+
@Override
57+
public void updateProgress() {}
58+
};
4659

47-
collisionHandler.isLevelUpAfterHitDino(scoreComponent);
60+
collisionHandler.isLevelUpAfterHitDino(scoreComponent, levelProgressBarComponent);
4861

4962
assertEquals(1, scoreComponent.getScore());
5063
}

0 commit comments

Comments
 (0)