added main game mechanics

This commit is contained in:
helori_ollivier
2026-03-13 14:46:08 +01:00
parent 06f49b2b23
commit f3118ddf96
8 changed files with 339 additions and 18 deletions

View File

@@ -1,4 +1,10 @@
down: 2
up: 8704
right: 273
left: 1220
0, 0, 0, 1, 1, 2,-1, 2, 1, 0
0, 0, 0, 1,-1, 2, 2,-1, 1, 0
0, 0, 0, 1, 1, 1, 1, 1, 1, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 1, 1, 1, 0, 0, 0, 0, 1, 1
0, 1,-1, 1, 0, 0, 0, 0, 1,-1
0, 1, 1, 1, 1, 2, 2, 1, 1, 1
0, 0, 1, 1, 2,-1,-1, 2, 1, 1
0, 0, 1,-1, 2, 2, 2, 2,-1, 2
0, 0, 1, 1, 1, 0, 0, 1, 2,-1

View File

@@ -3,41 +3,68 @@ package bzh.risotto;
import bzh.risotto.tilemap.Tile;
import bzh.risotto.tilemap.TileMap;
import bzh.risotto.tilemap.TileSet;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyMap;
/**
* class that load, store and update the visual map of the game,
* according to the game actions
*/
public class GameMap {
private final TileSet tileSet;
/** tilemap used by the gamemap */
private final TileMap tileMap;
/** overlay tilemap */
private final TileMap overlayMap;
/** list of tile that are not digged */
private List<Integer> dirtTiles;
private final Logger logger = LogManager.getLogger();
public GameMap() {
/**
* Constructor of the gamemap
*
* @param size size of the map
*/
public GameMap(Vector2 size) {
this.tileSet = new TileSet("tileset.png", new Vector2(16,16), new Vector2(6,10));
List<List<Integer>> map = loadMap();
this.tileMap = new TileMap(this.tileSet, map);
TileSet tileSet = new TileSet("tileset.png", new Vector2(16,16), new Vector2(6,10));
List<List<Integer>> map = loadMap(size);
this.tileMap = new TileMap(tileSet, map);
this.tileMap.setTile(5,0,0);
tileSet = new TileSet("ui.png", new Vector2(16,16), new Vector2(5,3));
this.overlayMap = new TileMap(tileSet, Utils.emptyMap(size));
loadConstArrays();
}
private List<List<Integer>> loadMap() {
/**
* generate the gameMap
*
* @param size size of the map
* @return the generated map
*/
private List<List<Integer>> loadMap(Vector2 size) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> row;
for (int i = 0; i < 10; i++) {
for (int i = 0; i < size.y; i++) {
row = new ArrayList<>();
for (int j = 0; j < 10; j++) {
for (int j = 0; j < size.x; j++) {
int tileId = (i+j)%3;
@@ -49,19 +76,41 @@ public class GameMap {
return res;
}
public void dig(Vector2 worldCoord) {
/**
* Dig the gamemap at the coord
* convert grass tiles to dirt tiles, and make them visualy connect
*
* @param worldCoord the world coordinat to dig
*/
public void dig(Vector2 worldCoord, int nbMines) {
// convert world coord to tilemap coord
Vector2 coord = tileMap.toTileMapCoord(worldCoord);
logger.debug("pos: " + coord);
logger.debug("tileType: " + getTileType((int) coord.x, (int) coord.y));
// prevent diging if spot is marked
int overlayTileId = this.overlayMap.getTileId((int) coord.x, (int) coord.y);
if (overlayTileId == 1) {
return;
}
// dig the tile
tileMap.setTile(13, (int) coord.x, (int) coord.y);
// update the surrounding tiles
for (int i = -1; i < 2; i ++) {
for (int j = -1; j < 2; j ++) {
Tile tile = null;
// prevent out of bound error while checking border tiles
try {
tile = tileMap.getTile((int) coord.x + j, (int) coord.y + i);
} catch (IndexOutOfBoundsException e) {
logger.info("Out of world check", e);
}
// set the right tile to make them visually connect
if ( tile != null && !dirtTiles.contains(tile.getId())) {
int tileType = getTileType((int) coord.x + j, (int) coord.y + i);
int tileId = tileTypeToId(tileType);
@@ -70,12 +119,40 @@ public class GameMap {
}
}
}
this.overlayMap.setTile((nbMines+5), (int) coord.x, (int) coord.y);
}
public void mark(Vector2 worldCoord) {
Vector2 coord = tileMap.toTileMapCoord(worldCoord);
int tileId = this.overlayMap.getTileId((int) coord.x, (int) coord.y);
if (tileId == 0) {
this.overlayMap.setTile((1), (int) coord.x, (int) coord.y);
}
else if (tileId == 1) {
this.overlayMap.setTile((0), (int) coord.x, (int) coord.y);
}
}
/**
* draw the map to the screen
*
* @param spriteBatch the spritebatch to use
*/
public void render(SpriteBatch spriteBatch) {
this.tileMap.render(spriteBatch);
this.overlayMap.render(spriteBatch);
}
/**
* calculate the type of the tile, by checking the surrounding tiles
*
* @param coordX x coordinate of the tile to check
* @param coordY y coordinate of the tile to check
* @return the tile type
*/
private int getTileType(int coordX, int coordY) {
// count tiles around
int p = 0;
@@ -83,12 +160,15 @@ public class GameMap {
for (int i = -1; i < 2; i ++) {
for (int j = -1; j < 2; j ++) {
Tile tile = null;
// prevent out of bound error when checking border tiles
try {
tile = tileMap.getTile(coordX + j, coordY + i);
} catch (IndexOutOfBoundsException e) {
logger.info("Out of world check", e);
}
// compute tile type
if (tile != null && !dirtTiles.contains(tile.getId())) {
tileType += (int) Math.pow(2, p);
}
@@ -102,10 +182,17 @@ public class GameMap {
return tileType;
}
/**
* convert tile type to tile set coordinate
* (could be generalized too fit every tileset)
*coordinate
* @param tileType the tile type we want to convert
* @return the corresponding coordinate in the tileset
*/
private int tileTypeToId(int tileType) {
return switch (tileType) {
case 2, 3, 6, 7, 71, 323, 327, 66, 322, 67, 258, 259, 263, 262, 326, 70 -> 10; // down
case 128, 192, 448, 384, 385, 449, 453, 193, 132, 196, 452, 133, 197, 388, 389 -> 22; // up
case 128, 192, 448, 384, 385, 449, 453, 193, 132, 196, 452, 133, 197, 388, 389, 129 -> 22; // up
case 8, 73, 72, 9, 329, 333, 328, 332, 77, 264, 268, 269, 12, 13, 76 -> 17; // right
case 32, 288, 292, 36, 356, 357, 33, 97, 353, 96, 100, 101, 37, 293, 352, 289 -> 15; // left
case 160, 161, 165, 229, 224, 228, 164, 225 -> 21; // inner bot-left corner
@@ -121,7 +208,7 @@ public class GameMap {
case 38, 102, 358, 359, 294, 295, 39, 103 -> 6; // top-left corner
case 204, 205, 461, 456, 457, 200, 201, 460 -> 20; // bot-left corner
case 416, 417, 481, 485, 420, 484, 421, 480 -> 18; // bot-right corner
case 11, 75, 79, 335, 267, 271, 351, 15 -> 8; // top-right corner
case 11, 75, 79, 335, 267, 271, 351, 15, 331 -> 8; // top-right corner
case 47, 111, 367, 303 -> 7; // up-straight
case 488, 496, 493, 492, 489 -> 19; // bot-straight
case 203, 459, 463, 207 -> 14; // left-straight
@@ -154,6 +241,10 @@ public class GameMap {
};
}
public TileMap getTileMap() {
return this.tileMap;
}
private void loadConstArrays() {
this.dirtTiles = new ArrayList<>();
this.dirtTiles.add(0);

View File

@@ -23,9 +23,13 @@ public class Minesweeper implements ApplicationListener {
private Vector2 zoom;
private GameMap gameMap;
private MinesweeperMap minesweeperMap;
private Timer clickDelay;
private Logger logger = LogManager.getLogger();
@Override
public void create() {
@@ -37,7 +41,11 @@ public class Minesweeper implements ApplicationListener {
zoom = new Vector2(Gdx.graphics.getHeight() / height, Gdx.graphics.getWidth() / width);
gameMap = new GameMap();
gameMap = new GameMap(new Vector2(10, 10));
minesweeperMap = new MinesweeperMap(new Vector2(10, 10), 10);
clickDelay = new Timer(0.25);
}
@Override
@@ -54,9 +62,27 @@ public class Minesweeper implements ApplicationListener {
private void logic() {
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT) && clickDelay.isFinished()) {
Vector2 mousePos = getMouseWorldPos();
gameMap.dig(mousePos);
int cell = minesweeperMap.getCell(this.gameMap.getTileMap().toTileMapCoord(mousePos));
gameMap.dig(mousePos, cell);
if (cell == -1) {
logger.info("Perdu");
}
else {
logger.info(cell);
}
clickDelay.start();
}
if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT) && clickDelay.isFinished()) {
Vector2 mousePos = getMouseWorldPos();
gameMap.mark(mousePos);
clickDelay.start();
}
}

View File

@@ -0,0 +1,121 @@
package bzh.risotto;
import bzh.risotto.tilemap.Tile;
import com.badlogic.gdx.math.Vector2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Class that load, store and update the mines map
*/
public class MinesweeperMap {
private Vector2 size;
private List<List<Integer>> map;
private final Random rand = new Random();
private final Logger logger = LogManager.getLogger();
public MinesweeperMap(Vector2 size, int nbMines) {
this.size = size;
this.map = loadMap(size, nbMines);
}
public int getCell(Vector2 coord) {
return this.map.get((int) coord.y).get((int) coord.x);
}
private List<List<Integer>> loadMap(Vector2 size, int nbMines) {
// generate empty map
List<List<Integer>> res = emptyMap(size);
// set random mines
loadMines(res, nbMines);
// count surrounding mines
countMines(res);
logger.debug(res);
return res;
}
private List<List<Integer>> emptyMap(Vector2 size) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> row;
for (int i = 0; i < size.y; i++) {
row = new ArrayList<>();
for (int j = 0; j < size.x; j++) {
row.add(0);
}
res.add(row);
}
return res;
}
private void loadMines(List<List<Integer>> map, int nbMines) {
while (nbMines > 0) {
int coordX = this.rand.nextInt(map.getFirst().size());
int coordY = this.rand.nextInt(map.size());
if (map.get(coordY).get(coordX) != -1) {
List<Integer> row = map.get(coordY);
row.set(coordX, -1);
map.set(coordY, row);
nbMines --;
}
}
}
private void countMines(List<List<Integer>> map) {
for (int i = 0; i < map.size(); i++) {
for (int j = 0; j < map.getFirst().size(); j++) {
if (map.get(i).get(j) != -1) {
int nbMines = countSurroundingMines(map, j, i);
List<Integer> row = map.get(i);
row.set(j, nbMines);
map.set(i, row);
}
}
}
}
private int countSurroundingMines(List<List<Integer>> map, int coordX, int coordY) {
int res = 0;
for (int i = -1; i < 2; i ++) {
for (int j = -1; j < 2; j++) {
Integer cell = null;
// prevent out of bound error while checking border tiles
try {
cell = map.get(coordY + i).get(coordX + j);
} catch (IndexOutOfBoundsException e) {
logger.info("Out of world check", e);
}
if (cell != null && cell == -1) {
res ++;
}
}
}
return res;
}
}

View File

@@ -0,0 +1,43 @@
package bzh.risotto;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Timer {
private double duration;
private double startTime;
Logger logger = LogManager.getLogger();
public Timer(double duration) {
this.duration = duration;
}
public void start() {
this.startTime = System.currentTimeMillis();
}
public void stop() {
this.startTime = -1;
}
public boolean isFinished() {
return timeLeft() <= 0;
}
public double timeLeft() {
if (this.startTime > 0) {
double res = this.startTime - System.currentTimeMillis() + (duration * 1000);
if (res > 0) {
return res;
}
else {
return 0;
}
}
return -1;
}
}

View File

@@ -0,0 +1,28 @@
package bzh.risotto;
import com.badlogic.gdx.math.Vector2;
import java.util.ArrayList;
import java.util.List;
public class Utils {
public static List<List<Integer>> emptyMap(Vector2 size) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> row;
for (int i = 0; i < size.y; i++) {
row = new ArrayList<>();
for (int j = 0; j < size.x; j++) {
int tileId = 0;
row.add(tileId);
}
res.add(row);
}
return res;
}
}

View File

@@ -114,6 +114,12 @@ public class TileMap {
}
}
/**
* convert world coord to tile map coord
*
* @param worldCoord world coordinate to convert
* @return tilemap coordinate
*/
public Vector2 toTileMapCoord(Vector2 worldCoord) {
Vector2 tileMapCoord = new Vector2();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 631 B