fixed srs rotations
This commit is contained in:
@@ -1,38 +1,52 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class RotationChecker {
|
||||
private record RotationKey(Orientation from, Orientation to) {}
|
||||
|
||||
private static final Map<RotationKey, int[][]> STANDARD_WALL_KICKS = Map.of(
|
||||
new RotationKey(Orientation.NONE, Orientation.RIGHT), new int[][] {{0,0}, {-1,0}, {-1,1}, {0,-2}, {-1,-2}},
|
||||
new RotationKey(Orientation.RIGHT, Orientation.NONE), new int[][] {{0,0}, {1,0}, {1,-1}, {0,2}, {1,2}},
|
||||
new RotationKey(Orientation.RIGHT, Orientation.UPSIDE_DOWN), new int[][] {{0,0}, {1,0}, {1,-1}, {0,2}, {1,2}},
|
||||
new RotationKey(Orientation.UPSIDE_DOWN, Orientation.RIGHT), new int[][] {{0,0}, {-1,0}, {-1,1}, {0,-2}, {-1,-2}},
|
||||
new RotationKey(Orientation.UPSIDE_DOWN, Orientation.LEFT), new int[][] {{0,0}, {1,0}, {1,1}, {0,-2}, {1,-2}},
|
||||
new RotationKey(Orientation.LEFT, Orientation.UPSIDE_DOWN), new int[][] {{0,0}, {-1,0}, {-1,-1}, {0,2}, {-1,2}},
|
||||
new RotationKey(Orientation.LEFT, Orientation.NONE), new int[][] {{0,0}, {-1,0}, {-1,-1}, {0,2}, {-1,2}},
|
||||
new RotationKey(Orientation.NONE, Orientation.LEFT), new int[][] {{0,0}, {1,0}, {1,1}, {0,-2}, {1,-2}}
|
||||
public final class RotationChecker {private static final Map<Orientation, int[][]> STANDARD_WALL_KICKS = Map.of(
|
||||
Orientation.NONE, new int[][] {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}},
|
||||
Orientation.RIGHT, new int[][] {{0,0}, {1,0}, {1,-1}, {0,2}, {1,2}},
|
||||
Orientation.UPSIDE_DOWN, new int[][] {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}},
|
||||
Orientation.LEFT, new int[][] {{0,0}, {-1,0}, {-1,-1}, {0,2}, {-1,2}}
|
||||
);
|
||||
|
||||
private static final Map<RotationKey, int[][]> I_WALL_KICKS = Map.of(
|
||||
new RotationKey(Orientation.NONE, Orientation.RIGHT), new int[][] {{0,0}, {-2,0}, {1,0}, {-2,-1}, {1,2}},
|
||||
new RotationKey(Orientation.RIGHT, Orientation.NONE), new int[][] {{0,0}, {2,0}, {-1,0}, {2,1}, {-1,-2}},
|
||||
new RotationKey(Orientation.RIGHT, Orientation.UPSIDE_DOWN), new int[][] {{0,0}, {-1,0}, {2,0}, {-1,2}, {2,-1}},
|
||||
new RotationKey(Orientation.UPSIDE_DOWN, Orientation.RIGHT), new int[][] {{0,0}, {1,0}, {-2,0}, {1,-2}, {-2,1}},
|
||||
new RotationKey(Orientation.UPSIDE_DOWN, Orientation.LEFT), new int[][] {{0,0}, {2,0}, {-1,0}, {2,1}, {-1,-2}},
|
||||
new RotationKey(Orientation.LEFT, Orientation.UPSIDE_DOWN), new int[][] {{0,0}, {-2,0}, {1,0}, {-2,-1}, {1,2}},
|
||||
new RotationKey(Orientation.LEFT, Orientation.NONE), new int[][] {{0,0}, {1,0}, {-2,0}, {1,-2}, {-2,1}},
|
||||
new RotationKey(Orientation.NONE, Orientation.LEFT), new int[][] {{0,0}, {-1,0}, {2,0}, {-1,2}, {2,-1}}
|
||||
private static final Map<Orientation, int[][]> I_WALL_KICKS = Map.of(
|
||||
Orientation.NONE, new int[][] {{0,0}, {-1,0}, {2,0}, {-1,0}, {2,0}},
|
||||
Orientation.RIGHT, new int[][] {{-1,0}, {0,0}, {0,0}, {0,1}, {0,-2}},
|
||||
Orientation.UPSIDE_DOWN, new int[][] {{-1,1}, {1,1}, {-2,1}, {1,0}, {-2,0}},
|
||||
Orientation.LEFT, new int[][] {{0,1}, {0,1}, {0,1}, {0,-1}, {0,2}}
|
||||
);
|
||||
|
||||
private static final Map<Orientation, int[][]> O_WALL_KICKS = Map.of(
|
||||
Orientation.NONE, new int[][] {{0,0}},
|
||||
Orientation.RIGHT, new int[][] {{0,-1}},
|
||||
Orientation.UPSIDE_DOWN, new int[][] {{-1,-1}},
|
||||
Orientation.LEFT, new int[][] {{-1,0}}
|
||||
);
|
||||
|
||||
public static int[][] getKicksArray(Orientation from, Orientation to, Tetromino.Shape shape) {
|
||||
RotationKey rotationKey = new RotationKey(from, to);
|
||||
int[][] firstOffsets = getOffsetData(from, shape);
|
||||
int[][] secondOffsets = getOffsetData(to, shape);
|
||||
int[][] result = new int[firstOffsets.length][2];
|
||||
|
||||
for(int i = 0; i < firstOffsets.length; i++) {
|
||||
result[i] = subtractInt(firstOffsets[i], secondOffsets[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int[] subtractInt(int[] first, int[] second) {
|
||||
return IntStream.range(0, first.length)
|
||||
.map(i -> first[i] - second[i])
|
||||
.toArray();
|
||||
}
|
||||
|
||||
private static int[][] getOffsetData(Orientation orientation, Tetromino.Shape shape) {
|
||||
return switch(shape) {
|
||||
case J, L, S, T, Z -> STANDARD_WALL_KICKS.get(rotationKey);
|
||||
case I -> I_WALL_KICKS.get(rotationKey);
|
||||
default -> new int[][]{{0, 0}};
|
||||
case J, L, S, T, Z -> STANDARD_WALL_KICKS.get(orientation);
|
||||
case I -> I_WALL_KICKS.get(orientation);
|
||||
case O -> O_WALL_KICKS.get(orientation);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ public class Tetromino {
|
||||
this.uuid = UUID.randomUUID();
|
||||
|
||||
switch(this.shape) {
|
||||
case I -> this.shapeArray = new int[][]{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}};
|
||||
case I -> this.shapeArray = new int[][]{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 1, 1, 1}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}};
|
||||
case J -> this.shapeArray = new int[][]{{1, 0, 0}, {1, 1, 1}, {0, 0, 0}};
|
||||
case L -> this.shapeArray = new int[][]{{0, 0, 1}, {1, 1, 1}, {0, 0, 0}};
|
||||
case O -> this.shapeArray = new int[][]{{1, 1}, {1, 1}};
|
||||
case O -> this.shapeArray = new int[][]{{0, 1, 1}, {0, 1, 1}, {0, 0, 0}};
|
||||
case S -> this.shapeArray = new int[][]{{0, 1, 1}, {1, 1, 0}, {0, 0, 0}};
|
||||
case T -> this.shapeArray = new int[][]{{0, 1, 0}, {1, 1, 1}, {0, 0, 0}};
|
||||
case Z -> this.shapeArray = new int[][]{{1, 1, 0}, {0, 1, 1}, {0, 0, 0}};
|
||||
@@ -53,9 +53,12 @@ public class Tetromino {
|
||||
|
||||
// TODO: doesn't work for I-Tetromino
|
||||
int[][] kicksArray = RotationChecker.getKicksArray(this.orientation, newOrientation, this.shape);
|
||||
System.out.println(this.shape.toString() + ": " + Arrays.deepToString(kicksArray));
|
||||
for(int[] k : kicksArray) {
|
||||
Pos candidate = new Pos(this.position.x() + k[0], this.position.y() + k[1], this.position.z());
|
||||
if(this.checkCollisionAndMove(candidate, newShapeArray)) {
|
||||
boolean moved = this.checkCollisionAndMove(candidate, newShapeArray);
|
||||
System.out.println("Candidate: " + Arrays.toString(k) + " " + moved);
|
||||
if(moved) {
|
||||
this.orientation = newOrientation;
|
||||
return true;
|
||||
}
|
||||
@@ -86,7 +89,7 @@ public class Tetromino {
|
||||
public void draw(boolean withGhost) {
|
||||
if(withGhost) {
|
||||
Pos ghostPos = this.position;
|
||||
while(!this.checkCollision(ghostPos.sub(0, 1, 0), this.shapeArray)) {
|
||||
while(!this.hasCollision(ghostPos.sub(0, 1, 0), this.shapeArray)) {
|
||||
ghostPos = ghostPos.sub(0, 1, 0);
|
||||
}
|
||||
Pos positionChange = this.position.sub(ghostPos);
|
||||
@@ -212,9 +215,8 @@ public class Tetromino {
|
||||
for(int y = 0; y < arrayLength; y++) {
|
||||
if(shapeArray[arrayLength - 1 - y][x] == 1) {
|
||||
switch(this.shape) {
|
||||
case I -> returnList.add(position.add(x - 1, y - 2, 0));
|
||||
case O -> returnList.add(position.add(x, y, 0));
|
||||
default -> returnList.add(position.add(x - 1, y - 1, 0));
|
||||
case I -> returnList.add(new Pos(position).add(x - 2, y - 2, 0));
|
||||
default -> returnList.add(new Pos(position).add(x - 1, y - 1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,7 +225,22 @@ public class Tetromino {
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private boolean checkCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
// private List<Pos> getBlockPositions(Pos position, int[][] shapeArray) {
|
||||
// List<Pos> returnList = new ArrayList<>();
|
||||
// if(position == null) return returnList;
|
||||
//
|
||||
// for(int x = 0; x < shapeArray.length; x++) {
|
||||
// for(int y = 0; y < shapeArray.length; y++) {
|
||||
// if(shapeArray[x][y] == 1) {
|
||||
// returnList.add(new Pos(position).sub(1, 1, 0).add(x, y, 0));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return returnList;
|
||||
// }
|
||||
|
||||
private boolean hasCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
List<Pos> newBlockPositions = this.getBlockPositions(newPosition, newShapeArray);
|
||||
|
||||
for(Pos pos : newBlockPositions) {
|
||||
@@ -236,15 +253,13 @@ public class Tetromino {
|
||||
}
|
||||
|
||||
private boolean checkCollisionAndMove(Pos newPosition, int[][] newShapeArray) {
|
||||
if(!this.checkCollision(newPosition, newShapeArray)) {
|
||||
if(this.hasCollision(newPosition, newShapeArray)) return false;
|
||||
this.remove();
|
||||
this.shapeArray = Arrays.stream(newShapeArray).map(int[]::clone).toArray(int[][]::new);
|
||||
this.setPosition(newPosition);
|
||||
this.draw();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public enum Shape {
|
||||
I,
|
||||
|
||||
Reference in New Issue
Block a user