diff --git a/source/core/assets/configs/tower.json b/source/core/assets/configs/tower.json index a15ab4d27..004dda33c 100644 --- a/source/core/assets/configs/tower.json +++ b/source/core/assets/configs/tower.json @@ -8,5 +8,10 @@ "health": 20, "baseAttack": 0, "cost": 5 + }, + "income": { + "health": 20, + "baseAttack": 0, + "cost": 1 } } \ No newline at end of file diff --git a/source/core/assets/images/mine_tower.png b/source/core/assets/images/mine_tower.png new file mode 100644 index 000000000..aa2d5940c Binary files /dev/null and b/source/core/assets/images/mine_tower.png differ diff --git a/source/core/assets/images/scrap.png b/source/core/assets/images/scrap.png new file mode 100644 index 000000000..91d0763b2 Binary files /dev/null and b/source/core/assets/images/scrap.png differ diff --git a/source/core/assets/images/scrapsUI.png b/source/core/assets/images/scrapsUI.png new file mode 100644 index 000000000..35e24df68 Binary files /dev/null and b/source/core/assets/images/scrapsUI.png differ diff --git a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java index 5431962bb..34c8ed564 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.math.GridPoint2; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.input.DropInputComponent; import com.csse3200.game.areas.terrain.TerrainFactory; import com.csse3200.game.areas.terrain.TerrainFactory.TerrainType; import com.csse3200.game.entities.Entity; @@ -80,7 +81,9 @@ public class ForestGameArea extends GameArea { "images/rangeBossRight.png", "images/wallTower.png", "images/building2.png", - "images/iso_grass_3.png" + "images/iso_grass_3.png", + "images/scrap.png", + "images/mine_tower.png" }; private static final String[] forestTextureAtlases = { "images/terrain_iso_grass.atlas", @@ -132,6 +135,8 @@ public void create() { spawnGhosts(); spawnWeaponTower(); + spawnIncome(); + spawnScrap(); bossKing1 = spawnBossKing1(); bossKing2 = spawnBossKing2(); @@ -146,6 +151,7 @@ public void create() { private void displayUI() { Entity ui = new Entity(); ui.addComponent(new GameAreaDisplay("Box Forest")); + ui.addComponent(ServiceLocator.getCurrencyService().getDisplay()); spawnEntity(ui); } @@ -178,7 +184,7 @@ private void spawnTerrain() { spawnEntityAt( ObstacleFactory.createWall(worldBounds.x, WALL_WIDTH), GridPoint2Utils.ZERO, false, false); } -private void spawnBuilding1() { + private void spawnBuilding1() { GridPoint2 minPos = new GridPoint2(0, 0); GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); @@ -231,7 +237,7 @@ private void spawnGhosts() { spawnEntityAt(ghost, randomPos, true, true); } } - + private Entity spawnBossKing1() { GridPoint2 minPos = new GridPoint2(0, 0); GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); @@ -246,7 +252,7 @@ private Entity spawnBossKing1() { true, false); } - return bossKing1; + return bossKing1; } private Entity spawnBossKing2() { @@ -264,7 +270,7 @@ private Entity spawnBossKing2() { false); } return bossKing2; -} + } /** * Spawns a projectile currently just in the center of the game @@ -340,4 +346,27 @@ public void dispose() { this.unloadAssets(); } + private void spawnScrap() { + GridPoint2 minPos = new GridPoint2(0, 0); + GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); + + for (int i = 0; i < 50; i++) { + GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); + Entity scrap = DropFactory.createScrapDrop(); + spawnEntityAt(scrap, randomPos, true, false); + } + } + + private void spawnIncome() { + GridPoint2 minPos = new GridPoint2(0, 0); + GridPoint2 maxPos = terrain.getMapBounds(0).sub(2, 2); + + for (int i = 0; i < 5; i++) { + GridPoint2 randomPos = RandomUtils.random(minPos, maxPos); + Entity towerfactory = TowerFactory.createIncomeTower(); + spawnEntityAt(towerfactory, randomPos, true, true); + } + } + + } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java new file mode 100644 index 000000000..c6d3c8a47 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java @@ -0,0 +1,84 @@ +package com.csse3200.game.components.gamearea; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; +import com.csse3200.game.services.ServiceLocator; +import com.csse3200.game.ui.UIComponent; + +/** + * A UI component for displaying the currency owned + */ +public class CurrencyDisplay extends UIComponent { + Table table; + private TextButton scrapsTb; + + /** + * Adds actors to stage + */ + @Override + public void create() { + super.create(); + addActors(); + entity.getEvents().addListener("updateCurrency", this::updateScrapsStats); + } + + /** + * Initialises the currency label + * Positions it on the stage using a table + */ + private void addActors() { + table = new Table(); + table.top().left(); + table.setFillParent(true); + table.padTop(50f).padLeft(20f); + + // create text button style + Drawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/scrapsUI.png"))); + TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle( + drawable, drawable, drawable, new BitmapFont()); + + // create scraps button + int value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + String text = String.format("%d", value); + scrapsTb = new TextButton(text, textButtonStyle); + scrapsTb.setDisabled(true); + scrapsTb.getLabel().setAlignment(Align.right); + scrapsTb.getLabel().setFontScale(2, 2); // font size + scrapsTb.pad(0, 0, 0, 70); + scrapsTb.setTransform(true); + scrapsTb.setScale(0.5f); // button size + + table.add(scrapsTb); + stage.addActor(table); + } + + @Override + public void draw(SpriteBatch batch) { + // handled by stage + } + + /** + * Updates the currency (Scraps) value on the UI component + */ + public void updateScrapsStats() { + int value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + CharSequence text = String.format("%d", value); + scrapsTb.getLabel().setText(text); + } + + @Override + public void dispose() { + super.dispose(); + scrapsTb.remove(); + } +} diff --git a/source/core/src/main/com/csse3200/game/components/npc/DropComponent.java b/source/core/src/main/com/csse3200/game/components/npc/DropComponent.java new file mode 100644 index 000000000..39a5dcb2d --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/npc/DropComponent.java @@ -0,0 +1,24 @@ +package com.csse3200.game.components.npc; +import com.csse3200.game.components.Component; +import com.csse3200.game.currency.Currency; +public class DropComponent extends Component { + private int value = 0; + protected Currency currency; + + public DropComponent(Currency currency) { + this.value = currency.getAmount(); + this.currency = currency; + } + + public int getValue() { + return this.value; + } + + public Currency getCurrency() { + return this.currency; + } + @Override + public void dispose() { + this.currency.setAmount(currency.getAmount() + this.value); + } +} diff --git a/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java new file mode 100644 index 000000000..f38d02f51 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tasks/CurrencyTask.java @@ -0,0 +1,87 @@ +package com.csse3200.game.components.tasks; + +import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.currency.Scrap; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The CurrencyTask updates the in-game currency based on time intervals. + */ +public class CurrencyTask extends DefaultTask implements PriorityTask { + private static final Logger logger = LoggerFactory.getLogger(CurrencyTask.class); + private final int priority; // The active priority this task will have + private final int INTERVAL = 10; // time interval to update currency in seconds + private final GameTime timeSource; + private long endTime; + private int interval; + private final Scrap scrap = new Scrap(); // currency to update + private final int currencyAmount = scrap.getAmount(); // amount of currency to update + + /** + * @param priority Task priority for currency updates. Must be a positive integer. + */ + public CurrencyTask(int priority, int interval) { + this.priority = priority; + this.interval = interval; + this.timeSource = ServiceLocator.getTimeSource(); + } + + + /** + * Starts the Task running and initializes currency-related variables. + */ + @Override + public void start() { + super.start(); + endTime = timeSource.getTime() + (INTERVAL * 1000); + } + + /** + * The update method is what is run every time the TaskRunner in the AiTaskComponent calls update(). + * Updates the currency based on time intervals. + */ + + @Override + public void update() { + if (timeSource.getTime() >= endTime) { + updateCurrency(); // update currency + endTime = timeSource.getTime() + (interval * 1000L); // reset end time + } + } + + + /** + * Updates the currency based on time intervals. + */ + public void updateCurrency() { + //logger.info("Updating currency"); + ServiceLocator.getCurrencyService().getScrap().modify(currencyAmount/2); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); // update currency display + + } + + /** + * For stopping the running task + */ + @Override + public void stop() { + super.stop(); + } + + /** + * Returns the current priority of the task. + * @return active priority value + */ + @Override + public int getPriority() { + return priority; + } + + public void setInterval(int interval) { + this.interval = interval; + } +} diff --git a/source/core/src/main/com/csse3200/game/currency/Currency.java b/source/core/src/main/com/csse3200/game/currency/Currency.java new file mode 100644 index 000000000..e1d5b3438 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/currency/Currency.java @@ -0,0 +1,75 @@ +package com.csse3200.game.currency; + +import com.csse3200.game.entities.Entity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class Currency { + + private static final Logger logger = LoggerFactory.getLogger(Currency.class); + + // The logo of the currency + private final String logoFilePath; + + // Stores the amount of currency there is + private int amount; + + private final String name; + + /** + * Constructor for the currency object. + * @param logoFilePath the file path of the logo + */ + public Currency(String logoFilePath, String name) { + this.logoFilePath = logoFilePath; + this.name = name; + } + + public String getName() { + return this.name; + } + + public int getAmount() { + return this.amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + /** + * Getter for the logo of the currency. + * + * @return the logo of the currency in a Texture format. + */ + public String getTexture() { + return this.logoFilePath; + } + + /** + * This method increments the currency amount by a given amount. + * Added amount is assumed to be larger than negative the currency's amount. + * + * @requires addedAmount >= -this.amount + * @param addedAmount The amount the currency will be incremented by. + */ + public void modify(int addedAmount) { + logger.debug("Modifying " + this.getClass().getSimpleName() + "by " + addedAmount); + this.amount += addedAmount; + } + + /** + * Checks if you can buy some item with a given cost. + * + * @param cost the cost of the item. + * @return boolean representing if you can buy that object or not. + */ + public boolean canBuy(int cost) { + return this.getAmount() >= cost; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + ": " + this.getAmount(); + } +} diff --git a/source/core/src/main/com/csse3200/game/currency/Scrap.java b/source/core/src/main/com/csse3200/game/currency/Scrap.java new file mode 100644 index 000000000..958babaa5 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/currency/Scrap.java @@ -0,0 +1,17 @@ +package com.csse3200.game.currency; + +public class Scrap extends Currency { + + private static final int STARTING_CURRENCY = 100; + + private static final String LOGO_FILE_PATH = "images/scrap.png"; // The file path of the logo + + /** + * Constructor for the scrap currency object. + * Sets the amount of scrap to the starting amount. + */ + public Scrap() { + super(LOGO_FILE_PATH, "Scrap"); + this.setAmount(STARTING_CURRENCY); + } +} diff --git a/source/core/src/main/com/csse3200/game/entities/EntityService.java b/source/core/src/main/com/csse3200/game/entities/EntityService.java index 55ab46422..7cc482cb6 100644 --- a/source/core/src/main/com/csse3200/game/entities/EntityService.java +++ b/source/core/src/main/com/csse3200/game/entities/EntityService.java @@ -1,9 +1,17 @@ package com.csse3200.game.entities; +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; +import com.csse3200.game.components.npc.DropComponent; +import com.csse3200.game.input.DropInputComponent; +import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.services.ServiceLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.security.Provider; + /** * Provides a global access point for entities to register themselves. This allows for iterating * over entities to perform updates each loop. All game entities should be registered here. @@ -14,9 +22,12 @@ public class EntityService { private static final Logger logger = LoggerFactory.getLogger(EntityService.class); private static final int INITIAL_CAPACITY = 16; - private final Array entities = new Array<>(false, INITIAL_CAPACITY); + public static void removeEntity(Entity clickedEntity) { + clickedEntity.dispose(); + } + /** * Register a new entity with the entity service. The entity will be created and start updating. * @param entity new entity. @@ -54,4 +65,22 @@ public void dispose() { entity.dispose(); } } + + public Entity getEntityAtPosition(float x, float y) { + for (Entity entity : entities) { + if (entityContainsPosition(entity, x, y)) { + return entity; + } + } + return null; + } + + private boolean entityContainsPosition(Entity entity, float x, float y) { + float entityX = entity.getPosition().x; + float entityY = entity.getPosition().y; + float entityWidth = entity.getScale().x; + float entityHeight = entity.getScale().y; + return (x >= entityX && x <= entityX + entityWidth && y >= entityY && y <= entityY + entityHeight); + } + } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java new file mode 100644 index 000000000..65dee1def --- /dev/null +++ b/source/core/src/main/com/csse3200/game/entities/configs/IncomeTowerConfig.java @@ -0,0 +1,10 @@ +package com.csse3200.game.entities.configs; + +/** + * Defines a basic set of properties stored in entities config files to be loaded by Entity Factories. + */ +public class IncomeTowerConfig { + public int health = 1; + public int baseAttack = 0; + public int cost = 1; +} diff --git a/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java b/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java index c641a053c..13c6fe19b 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/baseTowerConfigs.java @@ -6,4 +6,5 @@ public class baseTowerConfigs { public WeaponTowerConfig weapon = new WeaponTowerConfig(); public WallTowerConfig wall = new WallTowerConfig(); + public IncomeTowerConfig income = new IncomeTowerConfig(); } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/entities/factories/DropFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/DropFactory.java new file mode 100644 index 000000000..d35c4a834 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/entities/factories/DropFactory.java @@ -0,0 +1,28 @@ +package com.csse3200.game.entities.factories; + +import com.csse3200.game.components.npc.DropComponent; +import com.csse3200.game.currency.Currency; +import com.csse3200.game.currency.Scrap; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.input.DropInputComponent; +import com.csse3200.game.rendering.TextureRenderComponent; + +public class DropFactory { + + /** + * Creates a drop entity. This entity will have a texture and a drop component. + * @return entity + */ + + // We can make different drops for different currencies + public static Entity createScrapDrop() { + Scrap scrap = new Scrap(); + Entity drop = new Entity() + .addComponent(new TextureRenderComponent(scrap.getTexture())) + .addComponent(new DropComponent(scrap)); + drop.getComponent(TextureRenderComponent.class).scaleEntity(); + drop.scaleHeight(0.5f); + drop.scaleWidth(0.5f); + return drop; + } +} diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index 528eacace..9b7fd6c67 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -1,6 +1,7 @@ package com.csse3200.game.entities.factories; - +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Animation; import com.badlogic.gdx.graphics.g2d.TextureAtlas; @@ -12,6 +13,7 @@ import com.csse3200.game.components.tasks.TowerCombatTask; import com.csse3200.game.components.tasks.TowerIdleTask; import com.csse3200.game.components.tower.TowerAnimationController; +import com.csse3200.game.components.tasks.CurrencyTask; import com.csse3200.game.entities.Entity; import com.csse3200.game.entities.configs.WallTowerConfig; import com.csse3200.game.physics.PhysicsLayer; @@ -19,6 +21,7 @@ import com.csse3200.game.physics.components.HitboxComponent; import com.csse3200.game.physics.components.PhysicsComponent; import com.csse3200.game.entities.configs.WeaponTowerConfig; +import com.csse3200.game.entities.configs.IncomeTowerConfig; import com.csse3200.game.entities.configs.baseTowerConfigs; import com.csse3200.game.files.FileLoader; import com.csse3200.game.rendering.AnimationRenderComponent; @@ -35,10 +38,36 @@ public class TowerFactory { private static final int WEAPON_SCAN_INTERVAL = 1; private static final int COMBAT_TASK_PRIORITY = 2; + private static final int INCOME_INTERVAL = 300; + private static final int INCOME_TASK_PRIORITY = 1; public static final int WEAPON_TOWER_MAX_RANGE = 40; + private static final baseTowerConfigs configs = FileLoader.readClass(baseTowerConfigs.class, "configs/tower.json"); + /** + * Creates an income tower that generates scrap + * @return income + */ + public static Entity createIncomeTower() { + Entity income = createBaseTower(); + IncomeTowerConfig config = configs.income; + // Create the CurrencyIncomeTask and add it to the AITaskComponent + CurrencyTask currencyTask = new CurrencyTask(INCOME_TASK_PRIORITY, 3); + + int updatedInterval = 1; + currencyTask.setInterval(updatedInterval); + AITaskComponent aiTaskComponent = new AITaskComponent().addTask(currencyTask); + + income + .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new CostComponent(config.cost)) + .addComponent(new TextureRenderComponent("images/mine_tower.png")) + .addComponent(aiTaskComponent); + + + return income; + } public static Entity createWallTower() { @@ -50,9 +79,11 @@ public static Entity createWallTower() { .addComponent(new CostComponent(config.cost)) .addComponent(new TextureRenderComponent("images/wallTower.png")); + return wall; } + /** * Creates a weaponry tower that shoots at mobs - This will most likely need to be extended * once other types of weapon towers are developed diff --git a/source/core/src/main/com/csse3200/game/input/DropInputComponent.java b/source/core/src/main/com/csse3200/game/input/DropInputComponent.java new file mode 100644 index 000000000..10c7313bd --- /dev/null +++ b/source/core/src/main/com/csse3200/game/input/DropInputComponent.java @@ -0,0 +1,79 @@ +package com.csse3200.game.input; + + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Camera; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.areas.terrain.TerrainComponent; +import com.csse3200.game.components.CameraComponent; +import com.csse3200.game.components.npc.DropComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.csse3200.game.entities.factories.DropFactory; +import com.csse3200.game.entities.factories.RenderFactory; +import com.csse3200.game.rendering.Renderer; +import com.csse3200.game.services.ServiceLocator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.Provider; + +public class DropInputComponent extends InputComponent { + private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); + private final EntityService entityService; + private final Camera camera; + int value; + + /** + * Constructor for the DropInputComponent + * @param camera the camera to be used, this is the camera that the game is rendered with + */ + public DropInputComponent(Camera camera) { + this.value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + this.entityService = ServiceLocator.getEntityService(); + this.camera = camera; + } + + /** + * Getter for the camera + * @return the camera + */ + public Camera getCamera() { + return camera; + } + + /** + * When the mouse is clicked, this method is called. + * It checks if the mouse is clicked on a drop entity and if it is, + * it adds the value of the drop to the scrap + * + * @param screenX The x coordinate, origin is in the upper left corner + * @param screenY The y coordinate, origin is in the upper left corner + * @param pointer the pointer for the event. + * @param button the button + * @return + */ + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + Vector3 worldCoordinates = new Vector3((float) screenX , (float) screenY, 0); + getCamera().unproject(worldCoordinates); // translate from screen to world coordinates + Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); + Entity clickedEntity = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); + //logger.info("Clicked entity: " + clickedEntity); + if (clickedEntity != null && clickedEntity.getComponent(DropComponent.class) != null) { + ServiceLocator.getCurrencyService().getScrap() + .modify(clickedEntity.getComponent(DropComponent.class).getValue()); + // add the value of the drop to the scrap + EntityService.removeEntity(clickedEntity); // remove the entity from the game + //logger.info("Scrap amount: " + ServiceLocator.getCurrencyService().getScrap().getAmount()); + ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); // update the display + return true; + } + return false; + } + + +} diff --git a/source/core/src/main/com/csse3200/game/rendering/Renderer.java b/source/core/src/main/com/csse3200/game/rendering/Renderer.java index 5026bd274..1f877d45f 100644 --- a/source/core/src/main/com/csse3200/game/rendering/Renderer.java +++ b/source/core/src/main/com/csse3200/game/rendering/Renderer.java @@ -93,6 +93,7 @@ public CameraComponent getCamera() { /** Render everything to the render service. */ public void render() { Matrix4 projMatrix = camera.getProjectionMatrix(); + camera.update(); batch.setProjectionMatrix(projMatrix); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); diff --git a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java index 81fe9c359..f3ad9f461 100644 --- a/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/MainGameScreen.java @@ -23,6 +23,7 @@ import com.csse3200.game.entities.EntityService; import com.csse3200.game.entities.factories.PlayerFactory; import com.csse3200.game.entities.factories.RenderFactory; +import com.csse3200.game.input.DropInputComponent; import com.csse3200.game.input.InputComponent; import com.csse3200.game.input.InputDecorator; import com.csse3200.game.input.InputService; @@ -30,6 +31,7 @@ import com.csse3200.game.physics.PhysicsService; import com.csse3200.game.rendering.RenderService; import com.csse3200.game.rendering.Renderer; +import com.csse3200.game.services.CurrencyService; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ResourceService; import com.csse3200.game.services.ServiceLocator; @@ -105,12 +107,16 @@ public MainGameScreen(GdxGame game) { ServiceLocator.registerInputService(new InputService()); ServiceLocator.registerResourceService(new ResourceService()); + ServiceLocator.registerCurrencyService(new CurrencyService()); + ServiceLocator.registerEntityService(new EntityService()); ServiceLocator.registerRenderService(new RenderService()); renderer = RenderFactory.createRenderer(); renderer.getCamera().getEntity().setPosition(CAMERA_POSITION); renderer.getDebug().renderPhysicsWorld(physicsEngine.getWorld()); + InputComponent inputHandler = new DropInputComponent(renderer.getCamera().getCamera()); + ServiceLocator.getInputService().register(inputHandler); loadAssets(); createUI(); diff --git a/source/core/src/main/com/csse3200/game/services/CurrencyService.java b/source/core/src/main/com/csse3200/game/services/CurrencyService.java new file mode 100644 index 000000000..3e33876b9 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/services/CurrencyService.java @@ -0,0 +1,38 @@ +package com.csse3200.game.services; + +import com.csse3200.game.components.gamearea.CurrencyDisplay; +import com.csse3200.game.currency.Scrap; + +import java.util.ArrayList; +import com.csse3200.game.currency.Currency; + +public class CurrencyService { + + private ArrayList currencies; + private CurrencyDisplay display; + + /** + * Constructor for the CurrencyService class + */ + public CurrencyService() { + this.currencies = new ArrayList<>(); // Creates an array list of currencies + this.currencies.add(new Scrap()); // Adds a scrap currency to the array list + this.display = new CurrencyDisplay(); // Creates a new currency display + } + + public ArrayList getCurrencies() { + return this.currencies; + } + + /** + * Returns the scrap currency + * @return Scrap object + */ + public Scrap getScrap() { + return (Scrap) this.currencies.get(0); // Returns the scrap currency + } + + public CurrencyDisplay getDisplay() { + return display; + } +} diff --git a/source/core/src/main/com/csse3200/game/services/ServiceLocator.java b/source/core/src/main/com/csse3200/game/services/ServiceLocator.java index 63e5786f0..5bbe956cc 100644 --- a/source/core/src/main/com/csse3200/game/services/ServiceLocator.java +++ b/source/core/src/main/com/csse3200/game/services/ServiceLocator.java @@ -17,6 +17,7 @@ */ public class ServiceLocator { private static final Logger logger = LoggerFactory.getLogger(ServiceLocator.class); + private static CurrencyService currencyService; private static EntityService entityService; private static RenderService renderService; private static PhysicsService physicsService; @@ -24,6 +25,9 @@ public class ServiceLocator { private static InputService inputService; private static ResourceService resourceService; + public static CurrencyService getCurrencyService() { + return currencyService; + } public static EntityService getEntityService() { return entityService; @@ -49,6 +53,11 @@ public static ResourceService getResourceService() { return resourceService; } + public static void registerCurrencyService(CurrencyService service) { + logger.debug("Registering currency service {}", service); + currencyService = service; + } + public static void registerEntityService(EntityService service) { logger.debug("Registering entity service {}", service); entityService = service; diff --git a/source/core/src/test/com/csse3200/game/currency/CurrencyTest.java b/source/core/src/test/com/csse3200/game/currency/CurrencyTest.java new file mode 100644 index 000000000..8fa375e4e --- /dev/null +++ b/source/core/src/test/com/csse3200/game/currency/CurrencyTest.java @@ -0,0 +1,96 @@ +package com.csse3200.game.currency; + +import com.csse3200.game.components.npc.DropComponent; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; +import com.csse3200.game.extensions.GameExtension; +import com.csse3200.game.physics.PhysicsService; +import com.csse3200.game.rendering.DebugRenderer; +import com.csse3200.game.rendering.RenderService; +import com.csse3200.game.services.GameTime; +import com.csse3200.game.services.ResourceService; +import com.csse3200.game.services.ServiceLocator; +import org.junit.Before; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(GameExtension.class) +class CurrencyTest { + private Entity scrap; + private String[] texture = {"images/scrap.png"}; + + @BeforeEach + public void setUp() { + GameTime gameTime = mock(GameTime.class); + when(gameTime.getDeltaTime()).thenReturn(0.02f); + ServiceLocator.registerTimeSource(gameTime); + ServiceLocator.registerPhysicsService(new PhysicsService()); + RenderService render = new RenderService(); + render.setDebug(mock(DebugRenderer.class)); + ServiceLocator.registerRenderService(render); + ResourceService resourceService = new ResourceService(); + ServiceLocator.registerResourceService(resourceService); + resourceService.loadTextures(texture); + resourceService.loadAll(); + scrap = DropFactory.createScrapDrop(); + } + + @Test + void shouldCreateCurrency() { + Currency currency = mock(Currency.class, CALLS_REAL_METHODS); + assertEquals(0, currency.getAmount(), + "The currency should be set to 0"); + } + + @Test + void shouldCreateCurrencyWithAmount() { + Currency currency = mock(Currency.class, CALLS_REAL_METHODS); + currency = new Scrap(); + assertEquals(100, currency.getAmount(), + "The currency should be set to 100"); + } + + @Test + void scrapIsNotNull() { + assertNotNull(scrap, "Scrap should not be null"); + } + @Test + void testCreateScrapComponentNotNull() { + assertNotNull(scrap.getComponent(DropComponent.class), + "Scrap component should not be null"); + } + + @Test + void shouldSetAndGetAmount() { + Currency currency = mock(Currency.class, CALLS_REAL_METHODS); + int value = 100; + currency.setAmount(value); + assertEquals(value, currency.getAmount()); + } + + @Test + void shouldModifyAmount() { + Currency currency = mock(Currency.class, CALLS_REAL_METHODS); + int value = 100; + currency.setAmount(value); + currency.modify(value); + assertEquals(200, currency.getAmount()); + + currency.modify(-100); + assertEquals(100, currency.getAmount()); + } + + @Test + void testCanBuy() { + Currency currency = mock(Currency.class, CALLS_REAL_METHODS); + currency.setAmount(100); + + assertFalse(currency.canBuy(200)); + assertTrue(currency.canBuy(60)); + } + +} diff --git a/source/core/src/test/com/csse3200/game/services/CurrencyServiceTest.java b/source/core/src/test/com/csse3200/game/services/CurrencyServiceTest.java new file mode 100644 index 000000000..2d51fa6f7 --- /dev/null +++ b/source/core/src/test/com/csse3200/game/services/CurrencyServiceTest.java @@ -0,0 +1,24 @@ +package com.csse3200.game.services; + +import com.csse3200.game.components.gamearea.CurrencyDisplay; +import com.csse3200.game.currency.Scrap; +import com.csse3200.game.extensions.GameExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(GameExtension.class) +class CurrencyServiceTest { + @Test + void shouldReturnScrap() { + CurrencyService currencyService = new CurrencyService(); + assertEquals(Scrap.class, currencyService.getScrap().getClass()); + } + + @Test + void shouldReturnDisplay() { + CurrencyService currencyService = new CurrencyService(); + assertEquals(CurrencyDisplay.class, currencyService.getDisplay().getClass()); + } +}