added basic tetris classes

This commit is contained in:
Lars Neuhaus 2024-10-20 18:24:53 +02:00
parent 9d287f7c2f
commit 5acfe8f6af
5 changed files with 146 additions and 33 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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, () -> {});
}
}

View File

@ -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);
}
}

View File

@ -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, () -> {});
}
}