added ghost tetromino
This commit is contained in:
parent
f56023004a
commit
710838645f
@ -93,21 +93,20 @@ class Tetris extends StatelessGame {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
protected void onLoad(@NotNull CompletableFuture<Void> callback) {
|
||||||
this.tetrisGame = new TetrisGame(this, getSpawn().sub(6, 8, 15));
|
|
||||||
this.tetrisGame.generate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPlayerMove(@NotNull PlayerMoveEvent event) {
|
protected void onPlayerMove(@NotNull PlayerMoveEvent event) {
|
||||||
// if(!getSpawn().withView(event.getNewPosition()).equals(event.getNewPosition())) {
|
|
||||||
// event.setCancelled(true);
|
|
||||||
// event.getPlayer().setSprinting(false);
|
|
||||||
// }
|
|
||||||
|
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
Pos previousPosition = event.getPlayer().getPosition();
|
Pos previousPosition = event.getPlayer().getPosition();
|
||||||
Pos currentPosition = event.getNewPosition();
|
Pos currentPosition = event.getNewPosition();
|
||||||
|
|
||||||
|
if(this.tetrisGame == null) return;
|
||||||
|
|
||||||
|
event.setNewPosition(this.tetrisGame.getPlayerSpawnPosition().withView(event.getNewPosition()));
|
||||||
|
player.setSprinting(false);
|
||||||
|
|
||||||
Vec movementVector = currentPosition.asVec().sub(previousPosition.asVec());
|
Vec movementVector = currentPosition.asVec().sub(previousPosition.asVec());
|
||||||
|
|
||||||
float yaw = player.getPosition().yaw();
|
float yaw = player.getPosition().yaw();
|
||||||
@ -145,8 +144,6 @@ class Tetris extends StatelessGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(previousPosition.y() < currentPosition.y()) pressedButton(Button.space);
|
if(previousPosition.y() < currentPosition.y()) pressedButton(Button.space);
|
||||||
|
|
||||||
// event.setNewPosition(getSpawn().withView(event.getNewPosition()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onPlayerInteract(@NotNull PlayerUseItemEvent event) {
|
protected void onPlayerInteract(@NotNull PlayerUseItemEvent event) {
|
||||||
@ -162,11 +159,9 @@ class Tetris extends StatelessGame {
|
|||||||
p.getInventory().setItemStack(0, ItemStack.builder(Material.BIRCH_BUTTON).customName(Component.text("Controller")).build());
|
p.getInventory().setItemStack(0, ItemStack.builder(Material.BIRCH_BUTTON).customName(Component.text("Controller")).build());
|
||||||
p.setSprinting(false);
|
p.setSprinting(false);
|
||||||
|
|
||||||
// p.setGameMode(GameMode.SPECTATOR);
|
this.tetrisGame = new TetrisGame(this, getSpawn().sub(6, 8, 15));
|
||||||
// Entity anvil = new Entity(EntityType.FALLING_BLOCK);
|
this.tetrisGame.generate();
|
||||||
// ((FallingBlockMeta) anvil.getEntityMeta()).setBlock(Block.ANVIL);
|
p.teleport(this.tetrisGame.getPlayerSpawnPosition());
|
||||||
// anvil.setInstance(this, getSpawn());
|
|
||||||
// anvil.addPassenger(p);
|
|
||||||
|
|
||||||
this.tetrisGame.sidebar.addViewer(p);
|
this.tetrisGame.sidebar.addViewer(p);
|
||||||
return super.onPlayerJoin(p);
|
return super.onPlayerJoin(p);
|
||||||
|
@ -9,6 +9,7 @@ import net.minestom.server.instance.block.Block;
|
|||||||
public class Playfield {
|
public class Playfield {
|
||||||
private final Pos lowerLeftCorner;
|
private final Pos lowerLeftCorner;
|
||||||
private final StatelessGame instance;
|
private final StatelessGame instance;
|
||||||
|
private final int height = 22;
|
||||||
|
|
||||||
public Playfield(Pos lowerLeftCorner, StatelessGame instance) {
|
public Playfield(Pos lowerLeftCorner, StatelessGame instance) {
|
||||||
this.lowerLeftCorner = lowerLeftCorner;
|
this.lowerLeftCorner = lowerLeftCorner;
|
||||||
@ -16,7 +17,7 @@ public class Playfield {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Pos getPlayerSpawnPosition() {
|
public Pos getPlayerSpawnPosition() {
|
||||||
return this.lowerLeftCorner.add(6, 8, 15);
|
return this.lowerLeftCorner.add(6, 8, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pos getTetrominoSpawnPosition() {
|
public Pos getTetrominoSpawnPosition() {
|
||||||
@ -27,28 +28,36 @@ public class Playfield {
|
|||||||
return this.lowerLeftCorner.add(-4, 19, 0);
|
return this.lowerLeftCorner.add(-4, 19, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Pos getNextPosition() {
|
||||||
|
return this.lowerLeftCorner.add(14, 19, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public void generate() {
|
public void generate() {
|
||||||
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
AbsoluteBlockBatch batch = new AbsoluteBlockBatch();
|
||||||
|
|
||||||
for(int x=0; x<12; x++) {
|
for(int x=0; x<12; x++) {
|
||||||
for(int y=0; y<22; y++) {
|
for(int y=0; y<this.height; y++) {
|
||||||
batch.setBlock(this.lowerLeftCorner.add(x, y, 0), Block.GLASS);
|
batch.setBlock(this.lowerLeftCorner.add(x, y, 0), Block.GLASS);
|
||||||
batch.setBlock(this.lowerLeftCorner.add(x, y, -1), Block.BLACK_CONCRETE);
|
batch.setBlock(this.lowerLeftCorner.add(x, y, -1), Block.BLACK_CONCRETE);
|
||||||
|
|
||||||
if(x==0 || x==11 || y==0) {
|
if(x==0 || x==11 || y==0) {
|
||||||
batch.setBlock(this.lowerLeftCorner.add(x, y, 1), Block.GRAY_CONCRETE);
|
batch.setBlock(this.lowerLeftCorner.add(x, y, 1), Block.GRAY_CONCRETE);
|
||||||
|
batch.setBlock(this.lowerLeftCorner.add(x, y, 0), Block.GRAY_CONCRETE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.setBlock(getPlayerSpawnPosition().sub(0, 1, 0), Block.STONE);
|
batch.setBlock(getPlayerSpawnPosition().sub(0, 1, 0), Block.STONE);
|
||||||
|
batch.setBlock(getPlayerSpawnPosition().sub(0, 1, 1), Block.STONE);
|
||||||
|
batch.setBlock(getPlayerSpawnPosition().sub(1, 1, 1), Block.STONE);
|
||||||
|
batch.setBlock(getPlayerSpawnPosition().sub(1, 1, 0), Block.STONE);
|
||||||
|
|
||||||
BatchUtil.loadAndApplyBatch(batch, this.instance, () -> {});
|
BatchUtil.loadAndApplyBatch(batch, this.instance, () -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public int removeFullLines() {
|
public int removeFullLines() {
|
||||||
int removedLinesCounter = 0;
|
int removedLinesCounter = 0;
|
||||||
for(int y=1; y<22; y++) {
|
for(int y=1; y<this.height; y++) {
|
||||||
boolean isFullLine = true;
|
boolean isFullLine = true;
|
||||||
for(int x=1; x<11; x++) {
|
for(int x=1; x<11; x++) {
|
||||||
if(this.instance.getBlock(this.lowerLeftCorner.add(x, y, 1)) == Block.AIR) isFullLine = false;
|
if(this.instance.getBlock(this.lowerLeftCorner.add(x, y, 1)) == Block.AIR) isFullLine = false;
|
||||||
@ -62,8 +71,19 @@ public class Playfield {
|
|||||||
return removedLinesCounter;
|
return removedLinesCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeBlock(Block block) {
|
||||||
|
for(int x=0; x<12; x++) {
|
||||||
|
for(int y=0; y<this.height; y++) {
|
||||||
|
if(this.instance.getBlock(this.lowerLeftCorner.add(x, y, 1)).equals(block)) {
|
||||||
|
this.instance.setBlock(this.lowerLeftCorner.add(x, y, 1), Block.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeFullLine(int positionY) {
|
private void removeFullLine(int positionY) {
|
||||||
for(int y=positionY; y<22; y++) {
|
for(int y=positionY; y<this.height; y++) {
|
||||||
for(int x=1; x<11; x++) {
|
for(int x=1; x<11; x++) {
|
||||||
Block blockAbove = this.instance.getBlock(this.lowerLeftCorner.add(x, y+1, 1));
|
Block blockAbove = this.instance.getBlock(this.lowerLeftCorner.add(x, y+1, 1));
|
||||||
this.instance.setBlock(this.lowerLeftCorner.add(x, y, 1), blockAbove);
|
this.instance.setBlock(this.lowerLeftCorner.add(x, y, 1), blockAbove);
|
||||||
|
@ -25,23 +25,30 @@ public class TetrisGame {
|
|||||||
private Tetromino holdTetromino;
|
private Tetromino holdTetromino;
|
||||||
private final List<Tetromino> tetrominoBag = new ArrayList<>();
|
private final List<Tetromino> tetrominoBag = new ArrayList<>();
|
||||||
private boolean holdPossible = true;
|
private boolean holdPossible = true;
|
||||||
|
private final Pos nextPosition;
|
||||||
private final Pos holdPosition;
|
private final Pos holdPosition;
|
||||||
private final Pos tetrominoSpawnPosition;
|
private final Pos tetrominoSpawnPosition;
|
||||||
public Sidebar sidebar = new Sidebar(Component.text("Info:"));
|
public Sidebar sidebar = new Sidebar(Component.text("Info:"));
|
||||||
|
|
||||||
public TetrisGame(StatelessGame instance, Pos lowerLeftCorner) {
|
public TetrisGame(StatelessGame instance, Pos lowerLeftCorner) {
|
||||||
this(instance, lowerLeftCorner, new Tetromino(instance, Tetromino.Shape.J), new Tetromino(instance, Tetromino.Shape.T));
|
this(instance, lowerLeftCorner, Tetromino.Shape.J);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, Tetromino startTetromino, Tetromino nextTetromino) {
|
public TetrisGame(StatelessGame instance, Pos lowerLeftCorner, Tetromino.Shape startTetrominoShape) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.playfield = new Playfield(lowerLeftCorner, this.instance);
|
this.playfield = new Playfield(lowerLeftCorner, this.instance);
|
||||||
this.currentTetromino = startTetromino;
|
|
||||||
this.nextTetromino = nextTetromino;
|
|
||||||
|
|
||||||
this.holdPosition = this.playfield.getHoldPosition();
|
this.holdPosition = this.playfield.getHoldPosition();
|
||||||
|
this.nextPosition = this.playfield.getNextPosition();
|
||||||
this.tetrominoSpawnPosition = this.playfield.getTetrominoSpawnPosition();
|
this.tetrominoSpawnPosition = this.playfield.getTetrominoSpawnPosition();
|
||||||
this.buildSidebar();
|
this.buildSidebar();
|
||||||
|
|
||||||
|
this.currentTetromino = new Tetromino(this.instance, startTetrominoShape, this.playfield);
|
||||||
|
this.nextTetromino = this.getNextTetromino();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pos getPlayerSpawnPosition() {
|
||||||
|
return this.playfield.getPlayerSpawnPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
@ -115,7 +122,7 @@ public class TetrisGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.currentTetromino.remove();
|
this.currentTetromino.remove();
|
||||||
this.holdTetromino = this.currentTetromino;
|
this.holdTetromino = new Tetromino(this.instance, this.currentTetromino.shape, this.playfield);
|
||||||
this.currentTetromino = newCurrentTetromino;
|
this.currentTetromino = newCurrentTetromino;
|
||||||
|
|
||||||
this.currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
this.currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
||||||
@ -123,7 +130,7 @@ public class TetrisGame {
|
|||||||
if(!this.currentTetromino.moveDown()) loose();
|
if(!this.currentTetromino.moveDown()) loose();
|
||||||
|
|
||||||
this.holdTetromino.setPosition(this.holdPosition);
|
this.holdTetromino.setPosition(this.holdPosition);
|
||||||
this.holdTetromino.draw();
|
this.holdTetromino.draw(false);
|
||||||
this.holdPossible = false;
|
this.holdPossible = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -132,12 +139,17 @@ public class TetrisGame {
|
|||||||
private Tetromino getNextTetromino() {
|
private Tetromino getNextTetromino() {
|
||||||
if(this.tetrominoBag.isEmpty()) {
|
if(this.tetrominoBag.isEmpty()) {
|
||||||
for(Tetromino.Shape shape : Tetromino.Shape.values()) {
|
for(Tetromino.Shape shape : Tetromino.Shape.values()) {
|
||||||
this.tetrominoBag.add(new Tetromino(this.instance, shape));
|
this.tetrominoBag.add(new Tetromino(this.instance, shape, this.playfield));
|
||||||
}
|
}
|
||||||
Collections.shuffle(this.tetrominoBag);
|
Collections.shuffle(this.tetrominoBag);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.tetrominoBag.removeFirst();
|
if(this.nextTetromino != null) this.nextTetromino.remove();
|
||||||
|
Tetromino tetromino = this.tetrominoBag.removeFirst();
|
||||||
|
tetromino.setPosition(this.nextPosition);
|
||||||
|
tetromino.draw(false);
|
||||||
|
|
||||||
|
return tetromino;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loose() {
|
private void loose() {
|
||||||
@ -169,8 +181,8 @@ public class TetrisGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setActiveTetrominoDown() {
|
private void setActiveTetrominoDown() {
|
||||||
currentTetromino = nextTetromino;
|
this.currentTetromino = this.nextTetromino;
|
||||||
nextTetromino = getNextTetromino();
|
this.nextTetromino = getNextTetromino();
|
||||||
|
|
||||||
int removedLines = this.playfield.removeFullLines();
|
int removedLines = this.playfield.removeFullLines();
|
||||||
switch (removedLines) {
|
switch (removedLines) {
|
||||||
@ -197,9 +209,9 @@ public class TetrisGame {
|
|||||||
|
|
||||||
this.updateSidebar();
|
this.updateSidebar();
|
||||||
|
|
||||||
currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
this.currentTetromino.setPosition(this.tetrominoSpawnPosition);
|
||||||
currentTetromino.draw();
|
this.currentTetromino.draw();
|
||||||
if(!currentTetromino.moveDown()) {
|
if(!this.currentTetromino.moveDown()) {
|
||||||
loose();
|
loose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Tetromino {
|
public class Tetromino {
|
||||||
private final Shape shape;
|
public final Shape shape;
|
||||||
private final StatelessGame instance;
|
private final StatelessGame instance;
|
||||||
|
private final Playfield playfield;
|
||||||
private Pos position;
|
private Pos position;
|
||||||
private int[][] shapeArray;
|
private int[][] shapeArray;
|
||||||
|
private final Block ghostBlock = Block.ICE;
|
||||||
|
|
||||||
public enum Shape {
|
public enum Shape {
|
||||||
I,
|
I,
|
||||||
@ -24,9 +26,10 @@ public class Tetromino {
|
|||||||
Z
|
Z
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tetromino(StatelessGame instance, Shape shape) {
|
public Tetromino(StatelessGame instance, Shape shape, Playfield playfield) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.shape = shape;
|
this.shape = shape;
|
||||||
|
this.playfield = playfield;
|
||||||
|
|
||||||
switch (this.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 I -> shapeArray = new int[][]{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}};
|
||||||
@ -39,10 +42,6 @@ public class Tetromino {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pos getPosition() {
|
|
||||||
return this.position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPosition(Pos newPosition) {
|
public void setPosition(Pos newPosition) {
|
||||||
this.position = newPosition;
|
this.position = newPosition;
|
||||||
}
|
}
|
||||||
@ -68,6 +67,20 @@ public class Tetromino {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void draw() {
|
public void draw() {
|
||||||
|
this.draw(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw(boolean withGhost) {
|
||||||
|
if(withGhost) {
|
||||||
|
this.playfield.removeBlock(this.ghostBlock);
|
||||||
|
Pos ghostPos = this.position;
|
||||||
|
while (!checkCollision(ghostPos.sub(0, 1, 0), this.shapeArray)) {
|
||||||
|
ghostPos = ghostPos.sub(0, 1, 0);
|
||||||
|
}
|
||||||
|
Pos positionChange = this.position.sub(ghostPos);
|
||||||
|
getBlockPositions().forEach(pos -> this.instance.setBlock(pos.sub(positionChange), this.ghostBlock));
|
||||||
|
}
|
||||||
|
|
||||||
getBlockPositions().forEach(pos -> this.instance.setBlock(pos, this.getColoredBlock()));
|
getBlockPositions().forEach(pos -> this.instance.setBlock(pos, this.getColoredBlock()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +163,7 @@ public class Tetromino {
|
|||||||
|
|
||||||
for(Pos pos : newBlockPositions) {
|
for(Pos pos : newBlockPositions) {
|
||||||
if(isPartOfTetromino(pos)) continue;
|
if(isPartOfTetromino(pos)) continue;
|
||||||
|
if(this.instance.getBlock(pos) == this.ghostBlock) continue;
|
||||||
if(this.instance.getBlock(pos) != Block.AIR) return true;
|
if(this.instance.getBlock(pos) != Block.AIR) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user