Compare commits
4 Commits
develop
...
develop-te
| Author | SHA1 | Date | |
|---|---|---|---|
| ffba86ac41 | |||
| f95c670514 | |||
| 0b3c757ce0 | |||
| 76df6643db |
@@ -0,0 +1,28 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
||||
|
||||
public enum Orientation {
|
||||
NONE,
|
||||
RIGHT,
|
||||
LEFT,
|
||||
UPSIDE_DOWN;
|
||||
|
||||
public Orientation rotated(boolean clockwise) {
|
||||
switch(this) {
|
||||
case NONE -> {
|
||||
return clockwise ? Orientation.RIGHT : Orientation.LEFT;
|
||||
}
|
||||
case RIGHT -> {
|
||||
return clockwise ? Orientation.UPSIDE_DOWN : Orientation.NONE;
|
||||
}
|
||||
case UPSIDE_DOWN -> {
|
||||
return clockwise ? Orientation.LEFT : Orientation.RIGHT;
|
||||
}
|
||||
case LEFT -> {
|
||||
return clockwise ? Orientation.NONE : Orientation.UPSIDE_DOWN;
|
||||
}
|
||||
default -> {
|
||||
return Orientation.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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 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<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) {
|
||||
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(orientation);
|
||||
case I -> I_WALL_KICKS.get(orientation);
|
||||
case O -> O_WALL_KICKS.get(orientation);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,14 +8,12 @@ import net.minestom.server.entity.metadata.other.FallingBlockMeta;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.tag.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
public class Tetromino {
|
||||
private final static EntityType ghostEntityType = EntityType.FALLING_BLOCK;
|
||||
private final static Tag<String> uuidTag = Tag.String("uuid");
|
||||
private Orientation orientation = Orientation.NONE;
|
||||
private final Shape shape;
|
||||
private final StatelessGame instance;
|
||||
private final UUID uuid;
|
||||
@@ -28,10 +26,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}};
|
||||
@@ -43,12 +41,22 @@ public class Tetromino {
|
||||
}
|
||||
|
||||
public void setPosition(Pos newPosition) {
|
||||
this.position = newPosition;
|
||||
this.position = new Pos(newPosition.x(), newPosition.y(), newPosition.z());
|
||||
}
|
||||
|
||||
public boolean rotate(boolean clockwise) {
|
||||
public void rotate(boolean clockwise) {
|
||||
int[][] newShapeArray = this.getTurnedShapeArray(clockwise);
|
||||
return this.checkCollisionAndMove(this.position, newShapeArray);
|
||||
Orientation newOrientation = this.orientation.rotated(clockwise);
|
||||
|
||||
int[][] kicksArray = RotationChecker.getKicksArray(this.orientation, newOrientation, this.shape);
|
||||
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)) {
|
||||
this.orientation = newOrientation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean moveDown() {
|
||||
@@ -56,14 +64,14 @@ public class Tetromino {
|
||||
return this.checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
}
|
||||
|
||||
public boolean moveLeft() {
|
||||
public void moveLeft() {
|
||||
Pos newPosition = this.position.sub(1, 0, 0);
|
||||
return this.checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
this.checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
}
|
||||
|
||||
public boolean moveRight() {
|
||||
public void moveRight() {
|
||||
Pos newPosition = this.position.add(1, 0, 0);
|
||||
return this.checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
this.checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
@@ -73,7 +81,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);
|
||||
@@ -182,7 +190,7 @@ public class Tetromino {
|
||||
|
||||
private boolean isPartOfTetromino(Pos position) {
|
||||
return this.getBlockPositions().stream()
|
||||
.anyMatch(pos -> pos.equals(position));
|
||||
.anyMatch(pos -> pos.sameBlock(position));
|
||||
}
|
||||
|
||||
private List<Pos> getBlockPositions() {
|
||||
@@ -198,10 +206,10 @@ public class Tetromino {
|
||||
for(int x = 0; x < arrayLength; x++) {
|
||||
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));
|
||||
if(Objects.requireNonNull(this.shape) == Shape.I) {
|
||||
returnList.add(position.add(x - 2, y - 2, 0));
|
||||
} else {
|
||||
returnList.add(position.add(x - 1, y - 1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,7 +218,7 @@ public class Tetromino {
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private boolean checkCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
private boolean hasCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
List<Pos> newBlockPositions = this.getBlockPositions(newPosition, newShapeArray);
|
||||
|
||||
for(Pos pos : newBlockPositions) {
|
||||
@@ -223,14 +231,12 @@ public class Tetromino {
|
||||
}
|
||||
|
||||
private boolean checkCollisionAndMove(Pos newPosition, int[][] newShapeArray) {
|
||||
if(!this.checkCollision(newPosition, newShapeArray)) {
|
||||
this.remove();
|
||||
this.shapeArray = Arrays.stream(newShapeArray).map(int[]::clone).toArray(int[][]::new);
|
||||
this.setPosition(newPosition);
|
||||
this.draw();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
|
||||
public enum Shape {
|
||||
|
||||
Reference in New Issue
Block a user