Compare commits
6 Commits
develop
...
develop-te
| Author | SHA1 | Date | |
|---|---|---|---|
| 56f56d48b6 | |||
| 991e51bc10 | |||
| ffba86ac41 | |||
| f95c670514 | |||
| 0b3c757ce0 | |||
| 76df6643db |
@@ -82,11 +82,11 @@ class Tetris extends StatelessGame {
|
|||||||
|
|
||||||
private void onPlayerInteract(@NotNull PlayerUseItemEvent event) {
|
private void onPlayerInteract(@NotNull PlayerUseItemEvent event) {
|
||||||
event.setItemUseTime(0);
|
event.setItemUseTime(0);
|
||||||
this.tetrisGames.get(event.getPlayer()).pressedButton(TetrisGame.Button.mouseRight);
|
this.tetrisGames.get(event.getPlayer()).pressedButtonRaw(TetrisGame.Button.mouseRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPlayerAttack(@NotNull PlayerHandAnimationEvent event) {
|
private void onPlayerAttack(@NotNull PlayerHandAnimationEvent event) {
|
||||||
this.tetrisGames.get(event.getPlayer()).pressedButton(TetrisGame.Button.mouseLeft);
|
this.tetrisGames.get(event.getPlayer()).pressedButtonRaw(TetrisGame.Button.mouseLeft);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPlayerTick(PlayerTickEvent event) {
|
private void onPlayerTick(PlayerTickEvent event) {
|
||||||
@@ -100,11 +100,11 @@ class Tetris extends StatelessGame {
|
|||||||
|
|
||||||
if(player.getGameMode() == GameMode.SPECTATOR) return;
|
if(player.getGameMode() == GameMode.SPECTATOR) return;
|
||||||
|
|
||||||
if(player.inputs().forward()) tetrisGame.pressedButton(TetrisGame.Button.W);
|
if(player.inputs().forward()) tetrisGame.pressedButtonRaw(TetrisGame.Button.W);
|
||||||
if(player.inputs().backward()) tetrisGame.pressedButton(TetrisGame.Button.S);
|
if(player.inputs().backward()) tetrisGame.pressedButtonRaw(TetrisGame.Button.S);
|
||||||
if(player.inputs().right()) tetrisGame.pressedButton(TetrisGame.Button.D);
|
if(player.inputs().right()) tetrisGame.pressedButtonRaw(TetrisGame.Button.D);
|
||||||
if(player.inputs().left()) tetrisGame.pressedButton(TetrisGame.Button.A);
|
if(player.inputs().left()) tetrisGame.pressedButtonRaw(TetrisGame.Button.A);
|
||||||
if(player.inputs().jump()) tetrisGame.pressedButton(TetrisGame.Button.space);
|
if(player.inputs().jump()) tetrisGame.pressedButtonRaw(TetrisGame.Button.space);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void letPlayerLoose(Player player) {
|
private void letPlayerLoose(Player player) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,9 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
|||||||
|
|
||||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.minestom.server.MinecraftServer;
|
|
||||||
import net.minestom.server.coordinate.Pos;
|
import net.minestom.server.coordinate.Pos;
|
||||||
import net.minestom.server.scoreboard.Sidebar;
|
import net.minestom.server.scoreboard.Sidebar;
|
||||||
import net.minestom.server.timer.Scheduler;
|
import net.minestom.server.timer.Task;
|
||||||
import net.minestom.server.timer.TaskSchedule;
|
import net.minestom.server.timer.TaskSchedule;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -23,6 +22,8 @@ public class TetrisGame {
|
|||||||
private final Map<Button, Long> lastPresses = new HashMap<>();
|
private final Map<Button, Long> lastPresses = new HashMap<>();
|
||||||
private final List<TetrisGame> otherTetrisGames = new ArrayList<>();
|
private final List<TetrisGame> otherTetrisGames = new ArrayList<>();
|
||||||
private final Random random;
|
private final Random random;
|
||||||
|
private Task tetrominoLockTask;
|
||||||
|
private Task hardTetrominoLockTask;
|
||||||
public boolean lost = false;
|
public boolean lost = false;
|
||||||
public boolean paused = true;
|
public boolean paused = true;
|
||||||
public Tetromino currentTetromino;
|
public Tetromino currentTetromino;
|
||||||
@@ -53,25 +54,28 @@ public class TetrisGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pressedButton(Button button) {
|
public void pressedButtonRaw(Button button) {
|
||||||
final int standardButtonDelay = 100;
|
final int standardButtonDelay = 95;
|
||||||
final int buttonDebounce = 70;
|
final int wsButtonDebounce = 70;
|
||||||
|
|
||||||
if(this.lastPresses.getOrDefault(button, 0L) >= System.currentTimeMillis() - standardButtonDelay) return;
|
if(this.lastPresses.getOrDefault(button, 0L) >= System.currentTimeMillis() - standardButtonDelay) return;
|
||||||
|
|
||||||
this.lastPresses.put(button, System.currentTimeMillis());
|
switch(button) {
|
||||||
if(button == Button.W) this.lastPresses.put(button, System.currentTimeMillis() + buttonDebounce);
|
case W -> this.lastPresses.put(button, System.currentTimeMillis() + wsButtonDebounce);
|
||||||
if(button == Button.S) this.lastPresses.put(button, System.currentTimeMillis() - buttonDebounce);
|
case S -> this.lastPresses.put(button, System.currentTimeMillis() - wsButtonDebounce);
|
||||||
|
case mouseLeft, mouseRight -> this.lastPresses.put(button, 0L);
|
||||||
|
default -> this.lastPresses.put(button, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
if(this.lost || this.paused) return;
|
if(this.lost || this.paused) return;
|
||||||
|
|
||||||
switch(button) {
|
switch(button) {
|
||||||
case A -> this.currentTetromino.moveLeft();
|
case A -> this.moveLeft();
|
||||||
case S -> this.moveDown();
|
case S -> this.moveDown();
|
||||||
case D -> this.currentTetromino.moveRight();
|
case D -> this.moveRight();
|
||||||
case W -> this.hardDrop();
|
case W -> this.hardDrop();
|
||||||
case mouseLeft -> this.currentTetromino.rotate(false);
|
case mouseLeft -> this.rotate(false);
|
||||||
case mouseRight -> this.currentTetromino.rotate(true);
|
case mouseRight -> this.rotate(true);
|
||||||
case space -> this.switchHold();
|
case space -> this.switchHold();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,8 +86,7 @@ public class TetrisGame {
|
|||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
Scheduler scheduler = MinecraftServer.getSchedulerManager();
|
this.instance.scheduler().submitTask(() -> {
|
||||||
scheduler.submitTask(() -> {
|
|
||||||
if(this.lost) return TaskSchedule.stop();
|
if(this.lost) return TaskSchedule.stop();
|
||||||
int standardTickDelay = 40;
|
int standardTickDelay = 40;
|
||||||
if(this.isFast) standardTickDelay = 20;
|
if(this.isFast) standardTickDelay = 20;
|
||||||
@@ -111,8 +114,9 @@ public class TetrisGame {
|
|||||||
|
|
||||||
public void tick() {
|
public void tick() {
|
||||||
if(this.lost || this.paused) return;
|
if(this.lost || this.paused) return;
|
||||||
|
if(!this.currentTetromino.isGrounded()) this.stopTetrominoLockTask(true);
|
||||||
if(!this.currentTetromino.moveDown()) {
|
if(!this.currentTetromino.moveDown()) {
|
||||||
this.setActiveTetrominoDown();
|
this.scheduleTetrominoLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,33 +143,42 @@ public class TetrisGame {
|
|||||||
this.lost = true;
|
this.lost = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean moveDown() {
|
private void moveDown() {
|
||||||
if(!this.currentTetromino.moveDown()) {
|
if(!this.currentTetromino.moveDown()) {
|
||||||
this.setActiveTetrominoDown();
|
this.scheduleTetrominoLock();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
this.score += 1;
|
this.score += 1;
|
||||||
this.updateInfo();
|
this.updateInfo();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hardDrop() {
|
private void moveLeft() {
|
||||||
|
if(this.currentTetromino.moveLeft()) this.stopTetrominoLockTask(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveRight() {
|
||||||
|
if(this.currentTetromino.moveRight()) this.stopTetrominoLockTask(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rotate(boolean clockwise) {
|
||||||
|
if(this.currentTetromino.rotate(clockwise)) this.stopTetrominoLockTask(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hardDrop() {
|
||||||
if(!this.currentTetromino.moveDown()) {
|
if(!this.currentTetromino.moveDown()) {
|
||||||
this.setActiveTetrominoDown();
|
this.lockActiveTetromino();
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
do {
|
||||||
this.score += 2;
|
this.score += 2;
|
||||||
|
} while(this.currentTetromino.moveDown());
|
||||||
this.updateInfo();
|
this.updateInfo();
|
||||||
while(this.currentTetromino.moveDown()) {
|
this.lockActiveTetromino();
|
||||||
this.score += 2;
|
|
||||||
this.updateInfo();
|
|
||||||
}
|
|
||||||
this.setActiveTetrominoDown();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean switchHold() {
|
private void switchHold() {
|
||||||
if(!this.holdPossible) return false;
|
if(!this.holdPossible) return;
|
||||||
|
this.stopTetrominoLockTask(true);
|
||||||
|
|
||||||
Tetromino newCurrentTetromino;
|
Tetromino newCurrentTetromino;
|
||||||
if(this.holdTetromino == null) {
|
if(this.holdTetromino == null) {
|
||||||
@@ -189,7 +202,6 @@ public class TetrisGame {
|
|||||||
this.holdTetromino.setPosition(this.holdPosition.add(xChange, 0, 0));
|
this.holdTetromino.setPosition(this.holdPosition.add(xChange, 0, 0));
|
||||||
this.holdTetromino.drawAsEntities();
|
this.holdTetromino.drawAsEntities();
|
||||||
this.holdPossible = false;
|
this.holdPossible = false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateNextTetrominoes() {
|
private void updateNextTetrominoes() {
|
||||||
@@ -235,7 +247,40 @@ public class TetrisGame {
|
|||||||
this.sidebar.updateLineScore("2", this.level);
|
this.sidebar.updateLineScore("2", this.level);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setActiveTetrominoDown() {
|
private void scheduleTetrominoLock() {
|
||||||
|
if(this.tetrominoLockTask == null || !this.tetrominoLockTask.isAlive())
|
||||||
|
this.tetrominoLockTask = this.instance.scheduler().scheduleTask(() -> {
|
||||||
|
if(this.currentTetromino.isGrounded()) {
|
||||||
|
this.lockActiveTetromino();
|
||||||
|
} else {
|
||||||
|
this.stopTetrominoLockTask(true);
|
||||||
|
}
|
||||||
|
return TaskSchedule.stop();
|
||||||
|
}, TaskSchedule.millis(500));
|
||||||
|
if(this.hardTetrominoLockTask == null || !this.hardTetrominoLockTask.isAlive())
|
||||||
|
this.hardTetrominoLockTask = this.instance.scheduler().scheduleTask(() -> {
|
||||||
|
if(this.currentTetromino.isGrounded()) {
|
||||||
|
this.lockActiveTetromino();
|
||||||
|
} else {
|
||||||
|
this.stopTetrominoLockTask(true);
|
||||||
|
}
|
||||||
|
return TaskSchedule.stop();
|
||||||
|
}, TaskSchedule.millis(6000));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopTetrominoLockTask(boolean resetHard) {
|
||||||
|
if(this.tetrominoLockTask != null) {
|
||||||
|
this.tetrominoLockTask.cancel();
|
||||||
|
this.tetrominoLockTask = null;
|
||||||
|
}
|
||||||
|
if(resetHard && this.hardTetrominoLockTask != null) {
|
||||||
|
this.hardTetrominoLockTask.cancel();
|
||||||
|
this.hardTetrominoLockTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lockActiveTetromino() {
|
||||||
|
this.stopTetrominoLockTask(true);
|
||||||
this.currentTetromino.removeOwnEntities();
|
this.currentTetromino.removeOwnEntities();
|
||||||
this.currentTetromino = this.nextTetrominoes.removeFirst();
|
this.currentTetromino = this.nextTetrominoes.removeFirst();
|
||||||
this.currentTetromino.remove();
|
this.currentTetromino.remove();
|
||||||
|
|||||||
@@ -8,14 +8,12 @@ import net.minestom.server.entity.metadata.other.FallingBlockMeta;
|
|||||||
import net.minestom.server.instance.block.Block;
|
import net.minestom.server.instance.block.Block;
|
||||||
import net.minestom.server.tag.Tag;
|
import net.minestom.server.tag.Tag;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class Tetromino {
|
public class Tetromino {
|
||||||
private final static EntityType ghostEntityType = EntityType.FALLING_BLOCK;
|
private final static EntityType ghostEntityType = EntityType.FALLING_BLOCK;
|
||||||
private final static Tag<String> uuidTag = Tag.String("uuid");
|
private final static Tag<String> uuidTag = Tag.String("uuid");
|
||||||
|
private Orientation orientation = Orientation.NONE;
|
||||||
private final Shape shape;
|
private final Shape shape;
|
||||||
private final StatelessGame instance;
|
private final StatelessGame instance;
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
@@ -28,10 +26,10 @@ public class Tetromino {
|
|||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
|
|
||||||
switch(this.shape) {
|
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 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 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 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 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}};
|
case Z -> this.shapeArray = new int[][]{{1, 1, 0}, {0, 1, 1}, {0, 0, 0}};
|
||||||
@@ -43,12 +41,23 @@ public class Tetromino {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(Pos newPosition) {
|
public void setPosition(Pos newPosition) {
|
||||||
this.position = newPosition;
|
this.position = new Pos(newPosition.x(), newPosition.y(), newPosition.z());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean rotate(boolean clockwise) {
|
public boolean rotate(boolean clockwise) {
|
||||||
int[][] newShapeArray = this.getTurnedShapeArray(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 true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean moveDown() {
|
public boolean moveDown() {
|
||||||
@@ -73,7 +82,7 @@ public class Tetromino {
|
|||||||
public void draw(boolean withGhost) {
|
public void draw(boolean withGhost) {
|
||||||
if(withGhost) {
|
if(withGhost) {
|
||||||
Pos ghostPos = this.position;
|
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);
|
ghostPos = ghostPos.sub(0, 1, 0);
|
||||||
}
|
}
|
||||||
Pos positionChange = this.position.sub(ghostPos);
|
Pos positionChange = this.position.sub(ghostPos);
|
||||||
@@ -182,7 +191,7 @@ public class Tetromino {
|
|||||||
|
|
||||||
private boolean isPartOfTetromino(Pos position) {
|
private boolean isPartOfTetromino(Pos position) {
|
||||||
return this.getBlockPositions().stream()
|
return this.getBlockPositions().stream()
|
||||||
.anyMatch(pos -> pos.equals(position));
|
.anyMatch(pos -> pos.sameBlock(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Pos> getBlockPositions() {
|
private List<Pos> getBlockPositions() {
|
||||||
@@ -198,10 +207,10 @@ public class Tetromino {
|
|||||||
for(int x = 0; x < arrayLength; x++) {
|
for(int x = 0; x < arrayLength; x++) {
|
||||||
for(int y = 0; y < arrayLength; y++) {
|
for(int y = 0; y < arrayLength; y++) {
|
||||||
if(shapeArray[arrayLength - 1 - y][x] == 1) {
|
if(shapeArray[arrayLength - 1 - y][x] == 1) {
|
||||||
switch(this.shape) {
|
if(Objects.requireNonNull(this.shape) == Shape.I) {
|
||||||
case I -> returnList.add(position.add(x - 1, y - 2, 0));
|
returnList.add(position.add(x - 2, y - 2, 0));
|
||||||
case O -> returnList.add(position.add(x, y, 0));
|
} else {
|
||||||
default -> returnList.add(position.add(x - 1, y - 1, 0));
|
returnList.add(position.add(x - 1, y - 1, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +219,7 @@ public class Tetromino {
|
|||||||
return returnList;
|
return returnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkCollision(Pos newPosition, int[][] newShapeArray) {
|
private boolean hasCollision(Pos newPosition, int[][] newShapeArray) {
|
||||||
List<Pos> newBlockPositions = this.getBlockPositions(newPosition, newShapeArray);
|
List<Pos> newBlockPositions = this.getBlockPositions(newPosition, newShapeArray);
|
||||||
|
|
||||||
for(Pos pos : newBlockPositions) {
|
for(Pos pos : newBlockPositions) {
|
||||||
@@ -222,16 +231,18 @@ public class Tetromino {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGrounded() {
|
||||||
|
return this.hasCollision(this.position.sub(0, 1, 0), this.shapeArray);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean checkCollisionAndMove(Pos newPosition, int[][] newShapeArray) {
|
private boolean checkCollisionAndMove(Pos newPosition, int[][] newShapeArray) {
|
||||||
if(!this.checkCollision(newPosition, newShapeArray)) {
|
if(this.hasCollision(newPosition, newShapeArray)) return false;
|
||||||
this.remove();
|
this.remove();
|
||||||
this.shapeArray = Arrays.stream(newShapeArray).map(int[]::clone).toArray(int[][]::new);
|
this.shapeArray = Arrays.stream(newShapeArray).map(int[]::clone).toArray(int[][]::new);
|
||||||
this.setPosition(newPosition);
|
this.setPosition(newPosition);
|
||||||
this.draw();
|
this.draw();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Shape {
|
public enum Shape {
|
||||||
I,
|
I,
|
||||||
|
|||||||
Reference in New Issue
Block a user