Implemented level-change

This commit is contained in:
Urban Modig
2025-09-01 15:29:25 +02:00
parent 3a4a0a1824
commit be3c4deb3c
6 changed files with 105 additions and 31 deletions

View File

@ -1,12 +1,12 @@
package se.urmo.game.map;
import lombok.extern.slf4j.Slf4j;
import se.urmo.game.graphics.SpriteSheetManager;
import se.urmo.game.util.Direction;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@ -18,15 +18,36 @@ public class GameMap {
public static final int MAP_ROW_SIZE = 30;
public static final int OFFSET_Y = 7 * MAP_TILESIZE; // 160px from top
public static final int OFFSET_X = MAP_TILESIZE; // 16px from left
private final MapTile[][] mapData;
private MapTile[][] mapData;
private final int[][] csvData;
private long numberOfDots;
public GameMap(String mapFilePath) {
this.mapData = loadMap(mapFilePath, MAP_ROW_SIZE, MAP_COL_SIZE);
this.csvData = readCSV(mapFilePath, MAP_ROW_SIZE, MAP_COL_SIZE);
this.mapData = createMap(csvData);
this.numberOfDots = Arrays.stream(mapData)
.flatMap(Arrays::stream)
.filter(tile -> tile != null &&
(tile.getTileType() == TileType.SMALL_PELLET ||
tile.getTileType() == TileType.LARGE_PELLET))
.count();
}
private MapTile[][] loadMap(String path, int mapRowSize, int mapColSize) {
private static MapTile[][] createMap(int[][] data2) {
return Arrays.stream(data2)
.map(a -> Arrays.stream(a)
.mapToObj(i -> MapTile.byType(TileType.fromValue(i)))
.toArray(MapTile[]::new))
.toArray(MapTile[][]::new);
}
private int[][] readCSV(String path, int mapRowSize, int mapColSize) {
MapTile[][] data = new MapTile[mapRowSize][mapColSize];
int[][] data2 = new int[mapRowSize][mapColSize];
try (InputStream is = getClass().getClassLoader().getResourceAsStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(Objects.requireNonNull(is)))) {
@ -42,11 +63,15 @@ public class GameMap {
);
}
for (int col = 0; col < mapColSize; col++) {
int value = Integer.parseInt(tokens[col].trim());
data[row][col] = MapTile.byType(TileType.fromValue(value));
}
row++;
data2[row++] = Arrays.stream(tokens)
.map(String::trim)
.mapToInt(Integer::parseInt)
.toArray();
// for (int col = 0; col < mapColSize; col++) {
// int value = Integer.parseInt(tokens[col].trim());
// data[row][col] = MapTile.byType(TileType.fromValue(value));
// }
}
if (row != mapRowSize) {
@ -57,10 +82,10 @@ public class GameMap {
} catch (NullPointerException e) {
log.error("Failed to open inputstream: {}", e.getMessage(), e);
} catch (IOException e){
} catch (IOException e) {
log.error("Failed to read resource: {}", e.getMessage(), e);
}
return data;
return data2;
}
public void draw(Graphics g) {
@ -77,10 +102,6 @@ public class GameMap {
}
}
public boolean isPassable(List<Point> list){
return list.stream().allMatch(p -> isPassable(p.x, p.y));
}
public boolean isPassable(int screenX, int screenY) {
int row = screenToRow(screenY);
int col = screenToCol(screenX);
@ -90,7 +111,7 @@ public class GameMap {
boolean[][] mask = mapData[row][col].getCollisionMask();
boolean b = mask == null || !mask[tileY][tileX];
log.trace(b?" - passable":" - not passable");
log.trace(b ? " - passable" : " - not passable");
return b;
}
@ -100,8 +121,8 @@ public class GameMap {
public boolean isSolid(int row, int col) {
if (col >= columns() || col < 0 ) return true;
if(row >= rows() || row < 0) return true;
if (col >= columns() || col < 0) return true;
if (row >= rows() || row < 0) return true;
MapTile mapTile = mapData[row][col];
boolean solid = mapTile.isSolid();
log.debug("[{}][{}] {}", row, col, mapTile.getTileType());
@ -143,35 +164,36 @@ public class GameMap {
public int columns() {
return MAP_COL_SIZE;
}
public int rows() {
return MAP_ROW_SIZE;
}
public int colToWorldX(int col){
public int colToWorldX(int col) {
return col * GameMap.MAP_TILESIZE + GameMap.OFFSET_X;
}
public int rowToWorldY(int row){
public int rowToWorldY(int row) {
return row * GameMap.MAP_TILESIZE + GameMap.OFFSET_Y;
}
public int worldXtoCol(int x){
public int worldXtoCol(int x) {
return x / GameMap.MAP_TILESIZE;
}
public int worldYtoRow(int y){
public int worldYtoRow(int y) {
return y / GameMap.MAP_TILESIZE;
}
public Point coordToWorld(int row, int col){
public Point coordToWorld(int row, int col) {
return new Point(colToWorldX(col), rowToWorldY(row));
}
public Point worldToScreen(Point world){
public Point worldToScreen(Point world) {
return new Point(world.x + OFFSET_X, world.y + OFFSET_Y);
}
public Point screenToWorld(Point screen){
public Point screenToWorld(Point screen) {
return new Point(screen.x - OFFSET_X, screen.y - OFFSET_Y);
}
@ -186,6 +208,7 @@ public class GameMap {
public static int colToScreen(int col) {
return col * MAP_TILESIZE + OFFSET_X;
}
public static int rowToScreen(int row) {
return row * MAP_TILESIZE + OFFSET_Y;
}
@ -202,7 +225,8 @@ public class GameMap {
int row = (screenY - GameMap.OFFSET_Y) / GameMap.MAP_TILESIZE;
int col = (screenX - GameMap.OFFSET_X) / GameMap.MAP_TILESIZE;
record DirectionCheck(int rowOffset, int colOffset, Direction direction) {}
record DirectionCheck(int rowOffset, int colOffset, Direction direction) {
}
log.debug("At [{}][{}]", row, col);
return Stream.of(
new DirectionCheck(0, 1, Direction.RIGHT),
@ -226,4 +250,13 @@ public class GameMap {
int col = pos.y % GameMap.MAP_TILESIZE;
return row == GameMap.MAP_TILESIZE / 2 && col == GameMap.MAP_TILESIZE / 2;
}
public long numberOfDots() {
//return this.numberOfDots;
return 10;
}
public void reset() {
mapData = createMap(csvData);
}
}

View File

@ -10,13 +10,12 @@ import java.awt.Graphics;
public class FruitManager {
private final LevelManager levelManager;
private Fruit activeFruit;
private int dotsEaten = 0;
public FruitManager(LevelManager levelManager) {
this.levelManager = levelManager;
}
public void dotEaten() {
public void dotEaten(int dotsEaten) {
dotsEaten++;
if (dotsEaten == 10 || dotsEaten == 170) {
spawnFruit(levelManager.getCurrentLevel().getLevel());
@ -48,4 +47,8 @@ public class FruitManager {
activeFruit.draw(g);
}
}
public void reset() {
activeFruit = null;
}
}

View File

@ -9,7 +9,9 @@ import java.util.Arrays;
@Getter
public enum FruitType {
CHERRY(1, SpriteSheetManager.get(SpriteLocation.ITEM).getSprite(0,0), 100);
CHERRY(1, SpriteSheetManager.get(SpriteLocation.ITEM).getSprite(0,0), 100),
CHERRY2(2, SpriteSheetManager.get(SpriteLocation.ITEM).getSprite(0,0), 100),
CHERRY3(3, SpriteSheetManager.get(SpriteLocation.ITEM).getSprite(0,0), 100);
private final int level;
private final BufferedImage sprite;

View File

@ -92,4 +92,8 @@ public class GhostManager {
public void setFrightMode() {
this.setMode(GhostMode.FRIGHTENED);
}
public void reset() {
ghosts.forEach(Ghost::resetPosition);
}
}

View File

@ -4,9 +4,31 @@ import lombok.Getter;
public class LevelManager {
public void nextLevel() {
currentLevel = Level.forLevel(currentLevel.getLevel() + 1);
}
@Getter
public enum Level {
LEVEL1(1,6000, 0.75, 0.85, FruitType.CHERRY);
LEVEL1(1,6000, 0.75, 0.8, FruitType.CHERRY),
LEVEL2(2,3000, 0.85, 0.85, FruitType.CHERRY),
LEVEL3(3,1000, 0.95, 0.9, FruitType.CHERRY),
LEVEL4(4,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL5(5,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL6(6,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL7(7,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL8(8,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL9(9,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL10(10,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL11(11,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL12(12,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL13(13,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL14(14,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL15(15,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL16(16,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL17(17,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL18(18,6000, 0.75, 0.85, FruitType.CHERRY),
LEVEL19(19,6000, 0.75, 0.85, FruitType.CHERRY);
private final int frightendedDuration;
private final double ghostSpeed;

View File

@ -31,6 +31,7 @@ public class PlayingState implements GameState {
private GameMap map;
private int score;
private int lives = 3;
private int dotsEaten = 0;
public PlayingState(Game game, GameStateManager gameStateManager) {
this.game = game;
@ -63,8 +64,17 @@ public class PlayingState implements GameState {
ghostManager.setFrightMode();
}
if(wasRemoved){
fruitManager.dotEaten();
dotsEaten++;
fruitManager.dotEaten(dotsEaten);
score+=tile.getTileType().getScore();
if(dotsEaten == map.numberOfDots()){
levelManager.nextLevel();
map.reset();
ghostManager.reset();
fruitManager.reset();
pacman.resetPosition();
dotsEaten = 0;
}
}
}