diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java index 421e5cb..ff123f2 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/Tetris.java @@ -1,8 +1,8 @@ package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris; import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game.TetrisGame; import eu.mhsl.minenet.minigames.score.FirstWinsScore; -import eu.mhsl.minenet.minigames.util.BatchUtil; import eu.mhsl.minenet.minigames.instance.Dimension; import eu.mhsl.minenet.minigames.world.generator.terrain.CircularPlateTerrainGenerator; import net.kyori.adventure.text.Component; @@ -10,8 +10,6 @@ import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Player; import net.minestom.server.event.player.*; -import net.minestom.server.instance.batch.AbsoluteBlockBatch; -import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import org.jetbrains.annotations.NotNull; @@ -21,9 +19,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; class Tetris extends StatelessGame { - private final boolean isFast; - private final int width = 9; - private final int height = 20; + private TetrisGame tetrisGame; private final Map lastPresses = new HashMap<>(); @@ -37,12 +33,10 @@ class Tetris extends StatelessGame { space } - public Tetris(boolean isFast) { + public Tetris() { super(Dimension.THE_END.key, "Tetris", new FirstWinsScore()); this.setGenerator(new CircularPlateTerrainGenerator(30).setPlateHeight(0)); - this.isFast = isFast; - eventNode() .addListener(PlayerUseItemEvent.class, this::onPlayerInteract) .addListener(PlayerHandAnimationEvent.class, this::onPlayerAttack); @@ -51,6 +45,8 @@ class Tetris extends StatelessGame { @Override protected void onStart() { super.onStart(); + + this.tetrisGame.generate(); } protected void pressedButton(Button button) { @@ -74,25 +70,7 @@ class Tetris extends StatelessGame { @Override protected void onLoad(@NotNull CompletableFuture callback) { - AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); - - for(int y = 45; y <= 45+height; y++) { - for(int x = -(width/2)-1; x <= (width/2)+1; x++) { - batch.setBlock(x, y, 0, Block.STONE); - } - } - - for(int y = 45; y <= 45+height; y++) { - batch.setBlock(-(width/2)-1, y, 1, Block.GRAY_CONCRETE); - batch.setBlock((width/2)+1, y, 1, Block.GRAY_CONCRETE); - } - for(int x = -(width/2)-1; x <= (width/2)+1; x++) { - batch.setBlock(x, 45, 1, Block.GRAY_CONCRETE); - } - - batch.setBlock((int) getSpawn().x(), (int) (getSpawn().y()-1), (int) getSpawn().z(), Block.STONE); - - BatchUtil.loadAndApplyBatch(batch, this, () -> callback.complete(null)); + this.tetrisGame = new TetrisGame(this, getSpawn().sub(6, 8, 15)); } @Override @@ -117,10 +95,10 @@ class Tetris extends StatelessGame { double forwardAmount = movementVector.dot(forward); double leftAmount = movementVector.dot(left); - if (forwardAmount > 0.01) { + if (forwardAmount > 0.018) { pressedButton(Button.W); releasedButton(Button.S); - } else if (forwardAmount < -0.01) { + } else if (forwardAmount < -0.018) { pressedButton(Button.S); releasedButton(Button.W); } else { @@ -128,10 +106,10 @@ class Tetris extends StatelessGame { releasedButton(Button.S); } - if (leftAmount > 0.01) { + if (leftAmount > 0.018) { pressedButton(Button.D); releasedButton(Button.A); - } else if (leftAmount < -0.01) { + } else if (leftAmount < -0.018) { pressedButton(Button.A); releasedButton(Button.D); } else { @@ -155,6 +133,7 @@ class Tetris extends StatelessGame { @Override protected boolean onPlayerJoin(Player p) { p.getInventory().setItemStack(0, ItemStack.builder(Material.BIRCH_BUTTON).customName(Component.text("Controller")).build()); + p.setSprinting(false); return super.onPlayerJoin(p); } diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/TetrisFactory.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/TetrisFactory.java index 02d6f3c..3b5b628 100644 --- a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/TetrisFactory.java +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/TetrisFactory.java @@ -28,7 +28,7 @@ public class TetrisFactory implements GameFactory { @Override public Game manufacture(Room parent, Map> configuration) { - return new Tetris(false).setParent(parent); + return new Tetris().setParent(parent); } @Override diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/Playfield.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/Playfield.java new file mode 100644 index 0000000..2710d85 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/Playfield.java @@ -0,0 +1,37 @@ +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.util.BatchUtil; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.instance.batch.AbsoluteBlockBatch; +import net.minestom.server.instance.block.Block; + +public class Playfield { + private final Pos lowerLeftCorner; + + public Playfield(Pos lowerLeftCorner) { + this.lowerLeftCorner = lowerLeftCorner; + } + + public Pos getPlayerSpawnPosition() { + return lowerLeftCorner.add(6, 8, 15); + } + + public void generate(StatelessGame instance) { + AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); + + for(int x=0; x<12; x++) { + for(int y=0; y<21; y++) { + batch.setBlock(lowerLeftCorner.add(x, y, 0), Block.STONE); + + if(x==0 || x==11 || y==0) { + batch.setBlock(lowerLeftCorner.add(x, y, 1), Block.GRAY_CONCRETE); + } + } + } + + batch.setBlock(getPlayerSpawnPosition().sub(0, 1, 0), Block.STONE); + + BatchUtil.loadAndApplyBatch(batch, instance, () -> {}); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java new file mode 100644 index 0000000..9e6401b --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/TetrisGame.java @@ -0,0 +1,28 @@ +package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game; + +import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame; +import net.minestom.server.coordinate.Pos; + +public class TetrisGame { + private final StatelessGame instance; + private final Playfield playfield; + private int speed = 1; + private int lines = 0; + private Tetromino currentTetromino; + private Tetromino nextTetromino; + + public TetrisGame(StatelessGame instance, Pos lowerLeftCorner) { + this(instance, lowerLeftCorner, new Tetromino(Tetromino.Shape.J), new Tetromino(Tetromino.Shape.T)); + } + + public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, Tetromino startTetromino, Tetromino nextTetromino) { + this.playfield = new Playfield(lowerLeftCorner); + this.currentTetromino = startTetromino; + this.nextTetromino = nextTetromino; + this.instance = instance; + } + + public void generate() { + this.playfield.generate(this.instance); + } +} diff --git a/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/Tetromino.java b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/Tetromino.java new file mode 100644 index 0000000..71bad89 --- /dev/null +++ b/src/main/java/eu/mhsl/minenet/minigames/instance/game/stateless/types/tetris/game/Tetromino.java @@ -0,0 +1,69 @@ +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.util.BatchUtil; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.instance.batch.AbsoluteBlockBatch; +import net.minestom.server.instance.block.Block; + +public class Tetromino { + private final Shape shape; + + private int[][] shapeArray; + + public enum Shape { + I, + J, + L, + O, + S, + T, + Z + } + + public Tetromino(Shape shape) { + this.shape = shape; + + switch (this.shape) { + case I -> shapeArray = new int[][]{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}; + case J -> shapeArray = new int[][]{{1,0,0}, {1,1,1}, {0,0,0}}; + case L -> shapeArray = new int[][]{{0,0,1}, {1,1,1}, {0,0,0}}; + case O -> shapeArray = new int[][]{{1,1}, {1,1}}; + case S -> shapeArray = new int[][]{{0,1,1}, {1,1,0}, {0,0,0}}; + case T -> shapeArray = new int[][]{{0,1,0}, {1,1,1}, {0,0,0}}; + case Z -> shapeArray = new int[][]{{1,1,0}, {0,1,1}, {0,0,0}}; + } + } + + private int[][] getTurnedShapeArray(boolean clockwise) { + int iterations = 1; + if(!clockwise) iterations = 3; + + int arrayLength = this.shapeArray.length; + int[][] returnArray = new int[arrayLength][arrayLength]; + + for(int k=0; k {}); + } +}