added tetromino controlls
This commit is contained in:
parent
5acfe8f6af
commit
1332a42bf6
@ -46,7 +46,7 @@ class Tetris extends StatelessGame {
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
this.tetrisGame.generate();
|
||||
this.tetrisGame.start();
|
||||
}
|
||||
|
||||
protected void pressedButton(Button button) {
|
||||
@ -54,9 +54,18 @@ class Tetris extends StatelessGame {
|
||||
lastPresses.put(button, System.currentTimeMillis());
|
||||
|
||||
switch (button) {
|
||||
case A -> System.out.println("A");
|
||||
case S -> System.out.println("S");
|
||||
case D -> System.out.println("D");
|
||||
case A -> {
|
||||
System.out.println("A");
|
||||
System.out.println(this.tetrisGame.currentTetromino.moveLeft());
|
||||
}
|
||||
case S -> {
|
||||
System.out.println("S");
|
||||
System.out.println(this.tetrisGame.currentTetromino.moveDown());
|
||||
}
|
||||
case D -> {
|
||||
System.out.println("D");
|
||||
System.out.println(this.tetrisGame.currentTetromino.moveRight());
|
||||
}
|
||||
case W -> System.out.println("W");
|
||||
case mouseLeft -> System.out.println("mouse left");
|
||||
case mouseRight -> System.out.println("mouse right");
|
||||
@ -71,6 +80,7 @@ class Tetris extends StatelessGame {
|
||||
@Override
|
||||
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
||||
this.tetrisGame = new TetrisGame(this, getSpawn().sub(6, 8, 15));
|
||||
this.tetrisGame.generate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -17,6 +17,10 @@ public class Playfield {
|
||||
return lowerLeftCorner.add(6, 8, 15);
|
||||
}
|
||||
|
||||
public Pos getTetrominoSpawnPosition() {
|
||||
return this.lowerLeftCorner.add(5, 21, 1);
|
||||
}
|
||||
|
||||
public void generate(StatelessGame instance) {
|
||||
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||
|
||||
|
@ -1,18 +1,26 @@
|
||||
package eu.mhsl.minenet.minigames.instance.game.stateless.types.tetris.game;
|
||||
|
||||
import eu.mhsl.minenet.minigames.instance.game.stateless.StatelessGame;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.coordinate.Pos;
|
||||
import net.minestom.server.timer.Scheduler;
|
||||
import net.minestom.server.timer.TaskSchedule;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class TetrisGame {
|
||||
private final StatelessGame instance;
|
||||
private final Playfield playfield;
|
||||
private int speed = 1;
|
||||
private int lines = 0;
|
||||
private Tetromino currentTetromino;
|
||||
public Tetromino currentTetromino;
|
||||
private Tetromino nextTetromino;
|
||||
private final Random random = new Random();
|
||||
|
||||
private final Pos tetrominoSpawnPosition;
|
||||
|
||||
public TetrisGame(StatelessGame instance, Pos lowerLeftCorner) {
|
||||
this(instance, lowerLeftCorner, new Tetromino(Tetromino.Shape.J), new Tetromino(Tetromino.Shape.T));
|
||||
this(instance, lowerLeftCorner, new Tetromino(instance, Tetromino.Shape.J), new Tetromino(instance, Tetromino.Shape.T));
|
||||
}
|
||||
|
||||
public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, Tetromino startTetromino, Tetromino nextTetromino) {
|
||||
@ -20,9 +28,49 @@ public class TetrisGame {
|
||||
this.currentTetromino = startTetromino;
|
||||
this.nextTetromino = nextTetromino;
|
||||
this.instance = instance;
|
||||
|
||||
this.tetrominoSpawnPosition = this.playfield.getTetrominoSpawnPosition();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Scheduler scheduler = MinecraftServer.getSchedulerManager();
|
||||
scheduler.submitTask(() -> {
|
||||
this.tick();
|
||||
return TaskSchedule.tick(40/this.speed);
|
||||
});
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
this.playfield.generate(this.instance);
|
||||
|
||||
this.currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
||||
this.currentTetromino.draw();
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if(!currentTetromino.moveDown()) {
|
||||
currentTetromino = nextTetromino;
|
||||
currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
||||
currentTetromino.draw();
|
||||
nextTetromino = getNextTetromino();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Tetromino getNextTetromino() {
|
||||
int randomNumber = random.nextInt(1, 7);
|
||||
Tetromino.Shape nextShape;
|
||||
|
||||
switch (randomNumber) {
|
||||
case 2 -> nextShape = Tetromino.Shape.J;
|
||||
case 3 -> nextShape = Tetromino.Shape.L;
|
||||
case 4 -> nextShape = Tetromino.Shape.O;
|
||||
case 5 -> nextShape = Tetromino.Shape.S;
|
||||
case 6 -> nextShape = Tetromino.Shape.T;
|
||||
case 7 -> nextShape = Tetromino.Shape.Z;
|
||||
default -> nextShape = Tetromino.Shape.I;
|
||||
}
|
||||
|
||||
return new Tetromino(this.instance, nextShape);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Tetromino {
|
||||
private final Shape shape;
|
||||
|
||||
private final StatelessGame instance;
|
||||
private Pos position;
|
||||
private int[][] shapeArray;
|
||||
|
||||
public enum Shape {
|
||||
@ -21,7 +23,8 @@ public class Tetromino {
|
||||
Z
|
||||
}
|
||||
|
||||
public Tetromino(Shape shape) {
|
||||
public Tetromino(StatelessGame instance, Shape shape) {
|
||||
this.instance = instance;
|
||||
this.shape = shape;
|
||||
|
||||
switch (this.shape) {
|
||||
@ -35,6 +38,58 @@ public class Tetromino {
|
||||
}
|
||||
}
|
||||
|
||||
public Pos getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
public void setPosition(Pos newPosition) {
|
||||
this.position = newPosition;
|
||||
}
|
||||
|
||||
public boolean rotate(boolean clockwise) {
|
||||
int[][] newShapeArray = this.getTurnedShapeArray(clockwise);
|
||||
return checkCollisionAndMove(this.position, newShapeArray);
|
||||
}
|
||||
|
||||
public boolean moveDown() {
|
||||
Pos newPosition = this.position.sub(0, 1, 0);
|
||||
return checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
}
|
||||
|
||||
public boolean moveLeft() {
|
||||
Pos newPosition = this.position.sub(1, 0, 0);
|
||||
return checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
}
|
||||
|
||||
public boolean moveRight() {
|
||||
Pos newPosition = this.position.add(1, 0, 0);
|
||||
return checkCollisionAndMove(newPosition, this.shapeArray);
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
getBlockPositions().forEach(pos -> this.instance.setBlock(pos, this.getColoredBlock()));
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
this.getBlockPositions().forEach(pos -> this.instance.setBlock(pos, Block.AIR));
|
||||
}
|
||||
|
||||
|
||||
private Block getColoredBlock() {
|
||||
Block returnBlock;
|
||||
switch (this.shape) {
|
||||
case I -> returnBlock = Block.LIGHT_BLUE_CONCRETE;
|
||||
case J -> returnBlock = Block.BLUE_CONCRETE;
|
||||
case L -> returnBlock = Block.ORANGE_CONCRETE;
|
||||
case O -> returnBlock = Block.YELLOW_CONCRETE;
|
||||
case S -> returnBlock = Block.GREEN_CONCRETE;
|
||||
case T -> returnBlock = Block.PURPLE_CONCRETE;
|
||||
case Z -> returnBlock = Block.RED_CONCRETE;
|
||||
default -> returnBlock = Block.WHITE_CONCRETE;
|
||||
}
|
||||
return returnBlock;
|
||||
}
|
||||
|
||||
private int[][] getTurnedShapeArray(boolean clockwise) {
|
||||
int iterations = 1;
|
||||
if(!clockwise) iterations = 3;
|
||||
@ -53,17 +108,57 @@ public class Tetromino {
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public void draw(StatelessGame instance, Pos spawnPosition) {
|
||||
private boolean isPartOfTetromino(Pos position) {
|
||||
for(Pos blockPosition : getBlockPositions()) {
|
||||
if(position.sameBlock(blockPosition)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
System.out.println("Not part of Tetromino!!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Pos> getBlockPositions() {
|
||||
List<Pos> returnList = new ArrayList<>();
|
||||
if(this.position == null) return returnList;
|
||||
|
||||
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);
|
||||
for(int x=0; x<arrayLength; x++) {
|
||||
for(int y=0; y<arrayLength; y++) {
|
||||
if(this.shapeArray[arrayLength-1-y][x] == 1) {
|
||||
returnList.add(this.position.add(x-1, y-1, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BatchUtil.loadAndApplyBatch(batch, instance, () -> {});
|
||||
return returnList;
|
||||
}
|
||||
|
||||
private boolean checkCollision(Pos newPosition, int[][] newShapeArray) {
|
||||
int arrayLength = newShapeArray.length;
|
||||
|
||||
for(int x=0; x<arrayLength; x++) {
|
||||
for(int y=0; y<arrayLength; y++) {
|
||||
Pos checkPosition = newPosition.add(x-1, y-1, 0);
|
||||
if(isPartOfTetromino(checkPosition)) continue;
|
||||
if(this.instance.getBlock(checkPosition) != Block.AIR) return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: collision check to -y not working
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkCollisionAndMove(Pos newPosition, int[][] newShapeArray) {
|
||||
if(!checkCollision(newPosition, newShapeArray)) {
|
||||
this.remove();
|
||||
this.shapeArray = newShapeArray;
|
||||
this.setPosition(newPosition);
|
||||
this.draw();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user