added basic tetris classes
This commit is contained in:
		| @@ -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<Button, Long> 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<Void> 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); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -28,7 +28,7 @@ public class TetrisFactory implements GameFactory { | ||||
|  | ||||
|     @Override | ||||
|     public Game manufacture(Room parent, Map<String, Option<?>> configuration) { | ||||
|         return new Tetris(false).setParent(parent); | ||||
|         return new Tetris().setParent(parent); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -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, () -> {}); | ||||
|     } | ||||
| } | ||||
| @@ -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); | ||||
|     } | ||||
| } | ||||
| @@ -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<iterations; k++) { | ||||
|             for(int i=0; i<arrayLength; i++) { | ||||
|                 for(int j=0; j<arrayLength; j++) { | ||||
|                     returnArray[i][arrayLength-1-j] = this.shapeArray[j][i]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return returnArray; | ||||
|     } | ||||
|  | ||||
|     public void draw(StatelessGame instance, Pos spawnPosition) { | ||||
|         int arrayLength = this.shapeArray.length; | ||||
|  | ||||
|         AbsoluteBlockBatch batch = new AbsoluteBlockBatch(); | ||||
|  | ||||
|         for(int x=-1; x<arrayLength-1; x++) { | ||||
|             for(int y=-1; y<arrayLength-1; y++) { | ||||
|                 batch.setBlock(spawnPosition.add(x, y, 0), Block.WHITE_CONCRETE); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         BatchUtil.loadAndApplyBatch(batch, instance, () -> {}); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user