diff --git a/source/core/assets/images/ingamebg.png b/source/core/assets/images/desert_bg.png similarity index 100% rename from source/core/assets/images/ingamebg.png rename to source/core/assets/images/desert_bg.png diff --git a/source/core/assets/images/ice_bg.png b/source/core/assets/images/ice_bg.png new file mode 100644 index 000000000..2fae5a19e Binary files /dev/null and b/source/core/assets/images/ice_bg.png differ diff --git a/source/core/assets/images/lava_bg.png b/source/core/assets/images/lava_bg.png new file mode 100644 index 000000000..cca706805 Binary files /dev/null and b/source/core/assets/images/lava_bg.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 8409382ba..b66f7af95 100644 --- a/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java +++ b/source/core/src/main/com/csse3200/game/areas/ForestGameArea.java @@ -45,7 +45,10 @@ public class ForestGameArea extends GameArea { // Required to load assets before using them private static final String[] forestTextures = { - "images/ingamebg.png", + + "images/desert_bg.png", + "images/ice_bg.png", + "images/lava_bg.png", "images/box_boy_leaf.png", "images/background/building1.png", "images/ghost_1.png", diff --git a/source/core/src/main/com/csse3200/game/areas/terrain/TerrainFactory.java b/source/core/src/main/com/csse3200/game/areas/terrain/TerrainFactory.java index 794878666..c65b69caa 100644 --- a/source/core/src/main/com/csse3200/game/areas/terrain/TerrainFactory.java +++ b/source/core/src/main/com/csse3200/game/areas/terrain/TerrainFactory.java @@ -20,9 +20,9 @@ import com.badlogic.gdx.utils.viewport.Viewport; import com.csse3200.game.areas.terrain.TerrainComponent.TerrainOrientation; import com.csse3200.game.components.CameraComponent; +import com.csse3200.game.screens.GameLevelData; import com.csse3200.game.services.ResourceService; import com.csse3200.game.services.ServiceLocator; - import static com.csse3200.game.screens.MainGameScreen.viewportHeight; import static com.csse3200.game.screens.MainGameScreen.viewportWidth; @@ -33,8 +33,10 @@ public class TerrainFactory { private static OrthographicCamera camera; private final TerrainOrientation orientation; private static Stage stage; + int selectedLevel = GameLevelData.getSelectedLevel(); private Texture whiteTexture; + /** * Create a terrain factory with Orthogonal orientation * @@ -46,7 +48,6 @@ public TerrainFactory(CameraComponent cameraComponent) { Viewport viewport = new ScreenViewport(camera); viewport.update(viewportWidth, viewportHeight, true); stage = new Stage(viewport, new SpriteBatch()); - camera.update(); Pixmap pixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888); @@ -106,25 +107,78 @@ private TiledMapRenderer createRenderer(TiledMap tiledMap, float tileScale) { private TiledMap createForestDemoTiles(GridPoint2 tileSize, TextureRegion grass) { TiledMap tiledMap = new TiledMap(); + /** + * Creates a background layer for a tiled map with the specified dimensions and tile size. + * + * @param width The width of the layer in tiles. + * @param height The height of the layer in tiles. + * @param tileWidth The width of each individual tile in pixels. + * @param tileHeight The height of each individual tile in pixels. + */ - // Create a background layer TiledMapTileLayer backgroundLayer = new TiledMapTileLayer(20, 8, tileSize.x, tileSize.y); - TextureRegion backgroundTextureRegion = new TextureRegion(ServiceLocator.getResourceService().getAsset("images/ingamebg.png", Texture.class)); + /** + * Define a TextureRegion to be used as the background texture. + */ + TextureRegion backgroundTextureRegion ; + + switch (selectedLevel) { + case 0: // Desert + backgroundTextureRegion = new TextureRegion(ServiceLocator.getResourceService().getAsset("images/desert_bg.png", Texture.class)); + break; + case 1: // Ice + backgroundTextureRegion = new TextureRegion(ServiceLocator.getResourceService().getAsset("images/ice_bg.png", Texture.class)); + break; + case 2: // Lava + backgroundTextureRegion = new TextureRegion(ServiceLocator.getResourceService().getAsset("images/lava_bg.png", Texture.class)); + break; + default: + // Use a default background for other levels or planets + backgroundTextureRegion = new TextureRegion(ServiceLocator.getResourceService().getAsset("images/desert_bg.png", Texture.class)); + break; + } - // Create a single cell for the entire background image + /** + * Creates a single cell with the specified background texture region and adds it to the background layer + * of a tiled map. The background layer represents the entire background image of the map. + * + * @param backgroundTextureRegion The TextureRegion to use as the background texture. + * @param tileSizeX The width of each individual tile in pixels. + * @param tileSizeY The height of each individual tile in pixels. + * @param tiledMap The TiledMap to which the background layer should be added. + */ Cell cell = new Cell(); cell.setTile(new StaticTiledMapTile(backgroundTextureRegion)); backgroundLayer.setCell(0, 0, cell); tiledMap.getLayers().add(backgroundLayer); - // Create a grass layer + /** + * Creates a grass layer for the tiled map with the specified dimensions and tile size, filling it with + * grass tiles using the provided grass terrain tile. + * + * @param tileSizeX The width of each individual tile in pixels. + * @param tileSizeY The height of each individual tile in pixels. + * @param grassTile The TerrainTile representing the grass tile to be used for the layer. + * @param tiledMap The TiledMap to which the grass layer should be added. + */ TerrainTile grassTile = new TerrainTile(grass); TiledMapTileLayer grassLayer = new TiledMapTileLayer(20, 8, tileSize.x, tileSize.y); fillTiles(grassLayer, new GridPoint2(20, 8), grassTile); tiledMap.getLayers().add(grassLayer); - // Create lanes (invisible) + /** + * Creates lanes of invisible tiles in the TiledMap. These lanes are added as separate layers + * and are typically used for gameplay purposes. + * + * @param tiledMap The TiledMap to which the lanes should be added. + * @param tileSize The size of each tile in pixels (width and height). + * @param numberOfLanes The total number of lanes to create. + * @param mapWidth The width of the TiledMap in tiles. + * @param mapHeight The height of the TiledMap in tiles. + * @return The modified TiledMap with the added invisible lanes. + */ + int numberOfLanes = 8; int laneHeight = 1; // Height of each lane in tiles int mapWidth = 20; @@ -140,6 +194,14 @@ private TiledMap createForestDemoTiles(GridPoint2 tileSize, TextureRegion grass) return tiledMap; } + /** + * Fills a TiledMapTileLayer with invisible tiles, creating a layer of transparent tiles. + * + * @param layer The TiledMapTileLayer to fill with invisible tiles. + * @param mapSize The size of the layer in tiles (width and height). + */ + + private void fillInvisibleTiles(TiledMapTileLayer layer, GridPoint2 mapSize) { for (int x = 0; x < mapSize.x; x++) { for (int y = 0; y < mapSize.y; y++) { @@ -152,7 +214,7 @@ private void fillInvisibleTiles(TiledMapTileLayer layer, GridPoint2 mapSize) { } } -//tile class + //tile class public static class Tile { private int row; private int col; @@ -177,85 +239,81 @@ public String getLogCoordinates() { } } -// grid class -public static class Grid { - private Tile[][] tiles; + // grid class + public static class Grid { + private Tile[][] tiles; - public Grid(int numRows, int numCols) { - tiles = new Tile[numRows][numCols]; + public Grid(int numRows, int numCols) { + tiles = new Tile[numRows][numCols]; - for (int row = 0; row < numRows; row++) { - for (int col = 0; col < numCols; col++) { - tiles[row][col] = new Tile(row,col); + for (int row = 0; row < numRows; row++) { + for (int col = 0; col < numCols; col++) { + tiles[row][col] = new Tile(row,col); + } } } - } - public void placeObject(int row, int col, Object object) { - if (isValidCoordinate(row, col)) { - tiles[row][col].setObject(object); - } else { - System.out.println("Invalid coordinates."); + public void placeObject(int row, int col, Object object) { + if (isValidCoordinate(row, col)) { + tiles[row][col].setObject(object); + } else { + System.out.println("Invalid coordinates."); + } } - } - public Object getObject(int row, int col) { - if (isValidCoordinate(row, col)) { - return tiles[row][col].getObject(); - } else { - System.out.println("Invalid coordinates."); - return null; + public Object getObject(int row, int col) { + if (isValidCoordinate(row, col)) { + return tiles[row][col].getObject(); + } else { + System.out.println("Invalid coordinates."); + return null; + } } - } - public String getLogCoordinates(int row, int col) { - if (isValidCoordinate(row, col)) { - return tiles[row][col].getLogCoordinates(); - } else { - return "Invalid coordinates."; + public String getLogCoordinates(int row, int col) { + if (isValidCoordinate(row, col)) { + return tiles[row][col].getLogCoordinates(); + } else { + return "Invalid coordinates."; + } } - } - private boolean isValidCoordinate(int row, int col) { - return row >= 0 && row < tiles.length && col >= 0 && col < tiles[0].length; - } + private boolean isValidCoordinate(int row, int col) { + return row >= 0 && row < tiles.length && col >= 0 && col < tiles[0].length; + } - public void placeEntity(int row, int col, Object existingEntity) { - } + public void placeEntity(int row, int col, Object existingEntity) { + } - public Object getEntity(int row, int col) { + public Object getEntity(int row, int col) { return null; + } } -} -// Array class 1+2 -public class Array { - public static void main(String[] args) { - int numRows = 8; - int numCols = 20; + // Array class 1+2 + public class Array { + public static void main(String[] args) { + int numRows = 8; + int numCols = 20; - Grid grid = new Grid(numRows, numCols); + Grid grid = new Grid(numRows, numCols); - // Place an existing entity in a specific tile - int row = 3; - int col = 5; - // Replace 'Object' with the type of existing entity you want to place - Object existingEntity = new YourExistingEntity(); + // Place an existing entity in a specific tile + int row = 3; + int col = 5; + // Replace 'Object' with the type of existing entity you want to place + Object existingEntity = new YourExistingEntity(); - grid.placeEntity(row, col, existingEntity); + grid.placeEntity(row, col, existingEntity); - // Get the entity from a tile - Object entity = grid.getEntity(row, col); - System.out.println("Entity at " + grid.getLogCoordinates(row, col) + ": " + entity); - } + // Get the entity from a tile + Object entity = grid.getEntity(row, col); + System.out.println("Entity at " + grid.getLogCoordinates(row, col) + ": " + entity); + } - private static class YourExistingEntity { + private static class YourExistingEntity { + } } -} - - - - private static void fillTiles(TiledMapTileLayer layer, GridPoint2 mapSize, TerrainTile tile) { BitmapFont font = new BitmapFont(); @@ -276,4 +334,4 @@ private static void fillTiles(TiledMapTileLayer layer, GridPoint2 mapSize, Terra public enum TerrainType { FOREST_DEMO } -} +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/tasks/RangeBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/RangeBossTask.java new file mode 100644 index 000000000..a7aa3b5d9 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/components/tasks/RangeBossTask.java @@ -0,0 +1,112 @@ +package com.csse3200.game.components.tasks; + +import com.badlogic.gdx.math.Vector2; +import com.csse3200.game.ai.tasks.DefaultTask; +import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.ai.tasks.Task; +import com.csse3200.game.components.ProjectileEffects; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.ProjectileFactory; +import com.csse3200.game.physics.PhysicsEngine; +import com.csse3200.game.physics.raycast.RaycastHit; +import com.csse3200.game.services.ServiceLocator; +import com.csse3200.game.physics.PhysicsLayer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Wander around by moving a random position within a range of the starting position. Wait a little + * bit between movements. Requires an entity with a PhysicsMovementComponent. + */ +public class RangeBossTask extends DefaultTask implements PriorityTask { +// private static final Logger logger = LoggerFactory.getLogger(RangeBossTask.class); +// +// private final float waitTime; +// private Vector2 currentPos; +// private MovementTask movementTask; +// private WaitTask waitTask; +// private Task currentTask; +// private PhysicsEngine physics; +// private static final short TARGET = PhysicsLayer.TOWER; +// private final RaycastHit hit = new RaycastHit(); +// +// /** +// * @param waitTime How long in seconds to wait between wandering. +// */ +// public RangeBossTask(float waitTime) { +// +// this.waitTime = waitTime; +// physics = ServiceLocator.getPhysicsService().getPhysics(); +// } +// + @Override + public int getPriority() { + return 1; // Low priority task + } +// +// @Override +// public void start() { +// super.start(); +// currentPos = owner.getEntity().getPosition(); +// +// waitTask = new WaitTask(waitTime); +// waitTask.create(owner); +// movementTask = new MovementTask(currentPos.sub(2,0)); +// movementTask.create(owner); +// +// movementTask.start(); +// currentTask = movementTask; +// +// this.owner.getEntity().getEvents().trigger("rangeBossMovementStart"); +// } +// +// @Override +// public void update() { +// if (currentTask.getStatus() != Status.ACTIVE) { +// if (currentTask == movementTask) { +// if (towerAhead() || engineerAhead()) { +// owner.getEntity().getEvents().trigger("chargingStart"); +// Entity newProjectile = ProjectileFactory.createBossBall(PhysicsLayer.TOWER, new Vector2(0,currentPos.y + 0.75f), new Vector2(2f,2f)); +// newProjectile.setPosition((float) (currentPos.x), (float) (currentPos.y)); +// ServiceLocator.getEntityService().register(newProjectile); +// this.owner.getEntity().getEvents().trigger("attack1Start"); +// } +// startWaiting(); +// } else { +// startMoving(); +// +// } +// } +// currentTask.update(); +// } +// +// private void startWaiting() { +// logger.debug("Starting waiting"); +// owner.getEntity().getEvents().trigger("idleStart"); +// swapTask(waitTask); +// } +// +// private void startMoving() { +// logger.debug("Starting moving"); +// owner.getEntity().getEvents().trigger("walkStart"); +// owner.getEntity().getEvents().trigger("attack1Start"); +// movementTask.setTarget(currentPos.sub(2,0)); +// swapTask(movementTask); +// } +// +// private void swapTask(Task newTask) { +// if (currentTask != null) { +// currentTask.stop(); +// } +// currentTask = newTask; +// currentTask.start(); +// } +// +// private boolean towerAhead() { +// return physics.raycast(currentPos, new Vector2(0, currentPos.y), TARGET, hit); +// } +// private boolean engineerAhead() { +// return physics.raycast(currentPos, new Vector2(0, currentPos.y), PhysicsLayer.ENGINEER, hit); +// } + +} diff --git a/source/core/src/main/com/csse3200/game/screens/DesertGameScreen.java b/source/core/src/main/com/csse3200/game/screens/DesertGameScreen.java new file mode 100644 index 000000000..f5d4f768b --- /dev/null +++ b/source/core/src/main/com/csse3200/game/screens/DesertGameScreen.java @@ -0,0 +1,190 @@ +package com.csse3200.game.screens; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.ScreenAdapter; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.utils.viewport.ScreenViewport; +import com.badlogic.gdx.utils.viewport.Viewport; +import com.csse3200.game.GdxGame; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.areas.terrain.TerrainFactory; +import com.csse3200.game.components.gamearea.PerformanceDisplay; +import com.csse3200.game.components.maingame.MainGameActions; +import com.csse3200.game.components.maingame.MainGameExitDisplay; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +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; +import com.csse3200.game.physics.PhysicsEngine; +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; +import com.csse3200.game.ui.terminal.Terminal; +import com.csse3200.game.ui.terminal.TerminalDisplay; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DesertGameScreen extends ScreenAdapter { + private static final Logger logger = LoggerFactory.getLogger(DesertGameScreen.class); + private static final String[] mainGameTextures = {"images/heart.png"}; + private static final Vector2 CAMERA_POSITION = new Vector2(10f, 5.64f); + + private final GdxGame game; + private final Renderer renderer; + private final PhysicsEngine physicsEngine; + + private final Stage stage; + static int screenWidth = Gdx.graphics.getWidth(); + static int screenHeight = Gdx.graphics.getHeight(); + + + + public static int viewportWidth = screenWidth; + public static int viewportHeight= screenHeight; + + + + private OrthographicCamera camera; + private SpriteBatch batch; + + private Texture backgroundTexture; + + public DesertGameScreen(GdxGame game) { + this.game = game; + camera = new OrthographicCamera(); + camera.setToOrtho(false, viewportWidth, viewportHeight); + camera.position.set(viewportWidth / 2, viewportHeight / 2, 0); + + batch = new SpriteBatch(); + + Viewport viewport = new ScreenViewport(camera); + stage = new Stage(viewport, new SpriteBatch()); + + + + logger.debug("Initialising main game screen services"); + ServiceLocator.registerTimeSource(new GameTime()); + + PhysicsService physicsService = new PhysicsService(); + ServiceLocator.registerPhysicsService(physicsService); + physicsEngine = physicsService.getPhysics(); + + 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(); + + logger.debug("Initialising main game screen entities"); + TerrainFactory terrainFactory = new TerrainFactory(renderer.getCamera()); + ForestGameArea forestGameArea = new ForestGameArea(terrainFactory); + forestGameArea.create(); + } + + @Override + public void render(float delta) { + physicsEngine.update(); + ServiceLocator.getEntityService().update(); + + batch.setProjectionMatrix(camera.combined); + batch.begin(); + batch.draw(backgroundTexture, 0, 0, viewportWidth, viewportHeight); + batch.end(); + + + renderer.render(); + stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f)); + stage.draw(); + } + + + + + @Override + public void resize(int width, int height) { + renderer.resize(width, height); + logger.trace("Resized renderer: ({} x {})", width, height); + } + + @Override + public void pause() { + logger.info("Game paused"); + } + + @Override + public void resume() { + logger.info("Game resumed"); + } + + @Override + public void dispose() { + logger.debug("Disposing main game screen"); + + renderer.dispose(); + unloadAssets(); + + ServiceLocator.getEntityService().dispose(); + ServiceLocator.getRenderService().dispose(); + ServiceLocator.getResourceService().dispose(); + + ServiceLocator.clear(); + } + + private void loadAssets() { + logger.debug("Loading assets"); + ResourceService resourceService = ServiceLocator.getResourceService(); + resourceService.loadTextures(mainGameTextures); + backgroundTexture = new Texture("images/Dusty_MoonBG.png"); // Load the background image + ServiceLocator.getResourceService().loadAll(); + } + + private void unloadAssets() { + logger.debug("Unloading assets"); + ResourceService resourceService = ServiceLocator.getResourceService(); + resourceService.unloadAssets(mainGameTextures); + } + + /** + * Creates the main game's ui including components for rendering ui elements to the screen and + * capturing and handling ui input. + */ + private void createUI() { + logger.debug("Creating ui"); + Stage stage = ServiceLocator.getRenderService().getStage(); + InputComponent inputComponent = + ServiceLocator.getInputService().getInputFactory().createForTerminal(); + + Entity ui = new Entity(); + ui.addComponent(new InputDecorator(stage, 10)) + .addComponent(new PerformanceDisplay()) + .addComponent(new MainGameActions(this.game)) + .addComponent(new MainGameExitDisplay()) + .addComponent(new Terminal()) + .addComponent(inputComponent) + .addComponent(new TerminalDisplay()); + + ServiceLocator.getEntityService().register(ui); + } +} diff --git a/source/core/src/main/com/csse3200/game/screens/GameLevelData.java b/source/core/src/main/com/csse3200/game/screens/GameLevelData.java new file mode 100644 index 000000000..471eba7bb --- /dev/null +++ b/source/core/src/main/com/csse3200/game/screens/GameLevelData.java @@ -0,0 +1,24 @@ +package com.csse3200.game.screens; +/** + * The {@code GameLevelData} class is responsible for managing the selected game level. + * It provides methods to get and set the selected game level. + */ +public class GameLevelData { + private static int selectedLevel = -1; + /** + * Get the currently selected game level. + * + * @return The selected game level. + */ + public static int getSelectedLevel() { + return selectedLevel; + } + /** + * Set the selected game level. + * + * @param level The new game level to be selected. + */ + public static void setSelectedLevel(int level) { + selectedLevel = level; + } +} \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/screens/IceGameScreen.java b/source/core/src/main/com/csse3200/game/screens/IceGameScreen.java new file mode 100644 index 000000000..e7e12517b --- /dev/null +++ b/source/core/src/main/com/csse3200/game/screens/IceGameScreen.java @@ -0,0 +1,191 @@ +package com.csse3200.game.screens; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.ScreenAdapter; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.utils.viewport.ScreenViewport; +import com.badlogic.gdx.utils.viewport.Viewport; +import com.csse3200.game.GdxGame; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.areas.terrain.TerrainFactory; +import com.csse3200.game.components.gamearea.PerformanceDisplay; +import com.csse3200.game.components.maingame.MainGameActions; +import com.csse3200.game.components.maingame.MainGameExitDisplay; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +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; +import com.csse3200.game.physics.PhysicsEngine; +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; +import com.csse3200.game.ui.terminal.Terminal; +import com.csse3200.game.ui.terminal.TerminalDisplay; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IceGameScreen extends ScreenAdapter { + private static final Logger logger = LoggerFactory.getLogger(IceGameScreen.class); + private static final String[] mainGameTextures = {"images/heart.png"}; + private static final Vector2 CAMERA_POSITION = new Vector2(10f, 5.64f); + + private final GdxGame game; + private final Renderer renderer; + private final PhysicsEngine physicsEngine; + + private final Stage stage; + static int screenWidth = Gdx.graphics.getWidth(); + static int screenHeight = Gdx.graphics.getHeight(); + + + + public static int viewportWidth = screenWidth; + public static int viewportHeight= screenHeight; + + + + private OrthographicCamera camera; + private SpriteBatch batch; + + private Texture backgroundTexture; + + public IceGameScreen(GdxGame game) { + this.game = game; + camera = new OrthographicCamera(); + camera.setToOrtho(false, viewportWidth, viewportHeight); + camera.position.set(viewportWidth / 2, viewportHeight / 2, 0); + + batch = new SpriteBatch(); + + Viewport viewport = new ScreenViewport(camera); + stage = new Stage(viewport, new SpriteBatch()); + + + + logger.debug("Initialising main game screen services"); + ServiceLocator.registerTimeSource(new GameTime()); + + PhysicsService physicsService = new PhysicsService(); + ServiceLocator.registerPhysicsService(physicsService); + physicsEngine = physicsService.getPhysics(); + + 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(); + + logger.debug("Initialising main game screen entities"); + TerrainFactory terrainFactory = new TerrainFactory(renderer.getCamera()); + ForestGameArea forestGameArea = new ForestGameArea(terrainFactory); + forestGameArea.create(); + } + + @Override + public void render(float delta) { + physicsEngine.update(); + ServiceLocator.getEntityService().update(); + + batch.setProjectionMatrix(camera.combined); + batch.begin(); + batch.draw(backgroundTexture, 0, 0, viewportWidth, viewportHeight); + batch.end(); + + + renderer.render(); + stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f)); + stage.draw(); + } + + + + + @Override + public void resize(int width, int height) { + renderer.resize(width, height); + logger.trace("Resized renderer: ({} x {})", width, height); + } + + @Override + public void pause() { + logger.info("Game paused"); + } + + @Override + public void resume() { + logger.info("Game resumed"); + } + + @Override + public void dispose() { + logger.debug("Disposing main game screen"); + + renderer.dispose(); + unloadAssets(); + + ServiceLocator.getEntityService().dispose(); + ServiceLocator.getRenderService().dispose(); + ServiceLocator.getResourceService().dispose(); + + ServiceLocator.clear(); + } + + private void loadAssets() { + logger.debug("Loading assets"); + ResourceService resourceService = ServiceLocator.getResourceService(); + resourceService.loadTextures(mainGameTextures); + backgroundTexture = new Texture("images/Dusty_MoonBG.png"); // Load the background image + ServiceLocator.getResourceService().loadAll(); + } + + private void unloadAssets() { + logger.debug("Unloading assets"); + ResourceService resourceService = ServiceLocator.getResourceService(); + resourceService.unloadAssets(mainGameTextures); + } + + /** + * Creates the main game's ui including components for rendering ui elements to the screen and + * capturing and handling ui input. + */ + private void createUI() { + logger.debug("Creating ui"); + Stage stage = ServiceLocator.getRenderService().getStage(); + InputComponent inputComponent = + ServiceLocator.getInputService().getInputFactory().createForTerminal(); + + Entity ui = new Entity(); + ui.addComponent(new InputDecorator(stage, 10)) + .addComponent(new PerformanceDisplay()) + .addComponent(new MainGameActions(this.game)) + .addComponent(new MainGameExitDisplay()) + .addComponent(new Terminal()) + .addComponent(inputComponent) + .addComponent(new TerminalDisplay()); + + ServiceLocator.getEntityService().register(ui); + } +} + diff --git a/source/core/src/main/com/csse3200/game/screens/LavaGameScreen.java b/source/core/src/main/com/csse3200/game/screens/LavaGameScreen.java new file mode 100644 index 000000000..51b25c432 --- /dev/null +++ b/source/core/src/main/com/csse3200/game/screens/LavaGameScreen.java @@ -0,0 +1,187 @@ +package com.csse3200.game.screens; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.ScreenAdapter; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.utils.viewport.ScreenViewport; +import com.badlogic.gdx.utils.viewport.Viewport; +import com.csse3200.game.GdxGame; +import com.csse3200.game.areas.ForestGameArea; +import com.csse3200.game.areas.terrain.TerrainFactory; +import com.csse3200.game.components.gamearea.PerformanceDisplay; +import com.csse3200.game.components.maingame.MainGameActions; +import com.csse3200.game.components.maingame.MainGameExitDisplay; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.EntityService; +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; +import com.csse3200.game.physics.PhysicsEngine; +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; +import com.csse3200.game.ui.terminal.Terminal; +import com.csse3200.game.ui.terminal.TerminalDisplay; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LavaGameScreen extends ScreenAdapter { + private static final Logger logger = LoggerFactory.getLogger(LavaGameScreen.class); + private static final String[] mainGameTextures = {"images/heart.png"}; + private static final Vector2 CAMERA_POSITION = new Vector2(10f, 5.64f); + + private final GdxGame game; + private final Renderer renderer; + private final PhysicsEngine physicsEngine; + + private final Stage stage; + static int screenWidth = Gdx.graphics.getWidth(); + static int screenHeight = Gdx.graphics.getHeight(); + + + + public static int viewportWidth = screenWidth; + public static int viewportHeight= screenHeight; + + + + private OrthographicCamera camera; + private SpriteBatch batch; + + private Texture backgroundTexture; + + public LavaGameScreen(GdxGame game) { + this.game = game; + camera = new OrthographicCamera(); + camera.setToOrtho(false, viewportWidth, viewportHeight); + camera.position.set(viewportWidth / 2, viewportHeight / 2, 0); + + batch = new SpriteBatch(); + + Viewport viewport = new ScreenViewport(camera); + stage = new Stage(viewport, new SpriteBatch()); + + + + logger.debug("Initialising main game screen services"); + ServiceLocator.registerTimeSource(new GameTime()); + + PhysicsService physicsService = new PhysicsService(); + ServiceLocator.registerPhysicsService(physicsService); + physicsEngine = physicsService.getPhysics(); + + 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(); + + logger.debug("Initialising main game screen entities"); + TerrainFactory terrainFactory = new TerrainFactory(renderer.getCamera()); + ForestGameArea forestGameArea = new ForestGameArea(terrainFactory); + forestGameArea.create(); + } + + @Override + public void render(float delta) { + physicsEngine.update(); + ServiceLocator.getEntityService().update(); + + batch.setProjectionMatrix(camera.combined); + batch.begin(); + batch.draw(backgroundTexture, 0, 0, viewportWidth, viewportHeight); + batch.end(); + + + renderer.render(); + stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f)); + stage.draw(); + } + + @Override + public void resize(int width, int height) { + renderer.resize(width, height); + logger.trace("Resized renderer: ({} x {})", width, height); + } + + @Override + public void pause() { + logger.info("Game paused"); + } + + @Override + public void resume() { + logger.info("Game resumed"); + } + + @Override + public void dispose() { + logger.debug("Disposing main game screen"); + + renderer.dispose(); + unloadAssets(); + + ServiceLocator.getEntityService().dispose(); + ServiceLocator.getRenderService().dispose(); + ServiceLocator.getResourceService().dispose(); + + ServiceLocator.clear(); + } + + private void loadAssets() { + logger.debug("Loading assets"); + ResourceService resourceService = ServiceLocator.getResourceService(); + resourceService.loadTextures(mainGameTextures); + backgroundTexture = new Texture("images/Dusty_MoonBG.png"); // Load the background image + ServiceLocator.getResourceService().loadAll(); + } + + private void unloadAssets() { + logger.debug("Unloading assets"); + ResourceService resourceService = ServiceLocator.getResourceService(); + resourceService.unloadAssets(mainGameTextures); + } + + /** + * Creates the main game's ui including components for rendering ui elements to the screen and + * capturing and handling ui input. + */ + private void createUI() { + logger.debug("Creating ui"); + Stage stage = ServiceLocator.getRenderService().getStage(); + InputComponent inputComponent = + ServiceLocator.getInputService().getInputFactory().createForTerminal(); + + Entity ui = new Entity(); + ui.addComponent(new InputDecorator(stage, 10)) + .addComponent(new PerformanceDisplay()) + .addComponent(new MainGameActions(this.game)) + .addComponent(new MainGameExitDisplay()) + .addComponent(new Terminal()) + .addComponent(inputComponent) + .addComponent(new TerminalDisplay()); + + ServiceLocator.getEntityService().register(ui); + } +} diff --git a/source/core/src/main/com/csse3200/game/screens/LevelSelectScreen.java b/source/core/src/main/com/csse3200/game/screens/LevelSelectScreen.java index aeddb19b7..7894142aa 100644 --- a/source/core/src/main/com/csse3200/game/screens/LevelSelectScreen.java +++ b/source/core/src/main/com/csse3200/game/screens/LevelSelectScreen.java @@ -14,6 +14,7 @@ import com.csse3200.game.entities.factories.RenderFactory; import com.csse3200.game.rendering.Renderer; import com.csse3200.game.screens.text.AnimatedText; +import com.csse3200.game.screens.Planets; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Text; @@ -25,6 +26,7 @@ public class LevelSelectScreen extends ScreenAdapter { Logger logger = LoggerFactory.getLogger(LevelSelectScreen.class); private final GdxGame game; private SpriteBatch batch; + private int selectedLevel = -1; private static final String INTRO_TEXT = "Select a Planet for Conquest"; @@ -99,15 +101,42 @@ private void spawnPlanetBorders() { if (Gdx.input.justTouched()) { dispose(); logger.info("Loading level {}", planet[4]); - game.setScreen(new MainGameScreen(game)); + GameLevelData.setSelectedLevel(planet[4]); + if (planet[4] == 0) { + handleDesertPlanetClick(); + } else if (planet[4] == 1) { + handleIcePlanetClick(); + } else if (planet[4] == 2) { + handleLavaPlanetClick(); + } + } } else { Sprite planetBorder = new Sprite(new Texture("planets/planetBorder.png")); batch.draw(planetBorder, planet[0] - 2, planet[1] - 2, planet[2] + 3, planet[3] + 3); } } } + + + private void handleDesertPlanetClick() { + // Implement logic for when the desert planet is clicked + logger.info("Desert planet clicked."); + game.setScreen(new DesertGameScreen(game)); // Load the DesertGameScreen + } + + private void handleIcePlanetClick() { + // Implement logic for when the ice planet is clicked + logger.info("Ice planet clicked."); + game.setScreen(new IceGameScreen(game)); // Load the IceGameScreen + } + + private void handleLavaPlanetClick() { + // Implement logic for when the lava planet is clicked + logger.info("Lava planet clicked."); + game.setScreen(new LavaGameScreen(game)); // Load the LavaGameScreen } + // TODO: Make it display information about the planet @Override public void render(float delta) { diff --git a/source/core/src/main/com/csse3200/game/utils/math/GridPoint2Utils.java b/source/core/src/main/com/csse3200/game/utils/math/GridPoint2Utils.java index 332e029af..65a5d1979 100644 --- a/source/core/src/main/com/csse3200/game/utils/math/GridPoint2Utils.java +++ b/source/core/src/main/com/csse3200/game/utils/math/GridPoint2Utils.java @@ -9,6 +9,7 @@ public class GridPoint2Utils { public static final GridPoint2 ZERO = new GridPoint2(0, 0); + private GridPoint2Utils() { throw new IllegalStateException("Instantiating static util class"); } diff --git a/source/core/src/test/GameLevelDataTest.java b/source/core/src/test/GameLevelDataTest.java new file mode 100644 index 000000000..c9f6efcd2 --- /dev/null +++ b/source/core/src/test/GameLevelDataTest.java @@ -0,0 +1,30 @@ +import com.csse3200.game.screens.GameLevelData; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class GameLevelDataTest { + + @Test + void shouldInitializeSelectedLevelToMinusOne() { + assertEquals(-1, GameLevelData.getSelectedLevel()); + } + + @Test + void shouldSetSelectedLevel() { + GameLevelData.setSelectedLevel(2); + assertEquals(2, GameLevelData.getSelectedLevel()); + } + + @Test + void shouldSetSelectedLevelToZero() { + GameLevelData.setSelectedLevel(0); + assertEquals(0, GameLevelData.getSelectedLevel()); + } + + @Test + void shouldSetSelectedLevelToNegativeValue() { + GameLevelData.setSelectedLevel(-5); + assertEquals(-5, GameLevelData.getSelectedLevel()); + } +}