Add hidden (press F12 at main menu) level editor mode

Saves a level.json in the external storage
This commit is contained in:
Matt Low 2018-11-21 15:38:32 +04:00
parent 157a247516
commit bb8d4a41e3
3 changed files with 258 additions and 0 deletions

View File

@ -0,0 +1,23 @@
package com.me.brickbuster.layout;
import com.me.brickbuster.entity.BrickShape;
import com.me.brickbuster.entity.BrickType;
import com.me.brickbuster.entity.powerup.PowerUpType;
import java.util.List;
public class LevelJsonTemplate {
public String backgroundFile;
public String borderFile;
public List<BrickJsonTemplate> bricks;
public static class BrickJsonTemplate {
public int col;
public int row;
public BrickType type;
public BrickShape.Shape shape;
public PowerUpType powerUp;
}
}

View File

@ -0,0 +1,229 @@
package com.me.brickbuster.state;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Json;
import com.me.brickbuster.BrickBuster;
import com.me.brickbuster.entity.Brick;
import com.me.brickbuster.entity.BrickShape;
import com.me.brickbuster.entity.BrickType;
import com.me.brickbuster.entity.powerup.PowerUpType;
import com.me.brickbuster.layout.LevelJsonTemplate;
import com.me.brickbuster.physics.Box2dContactListener;
import java.util.ArrayList;
public class EditorState extends FieldState {
public static final long BLINK_INTERVAL = 250l;
public static final int COLUMNS = 11;
public static final int ROWS = 33;
private Brick placeHolder;
private Brick[][] bricks = new Brick[COLUMNS][ROWS];
private int col = 0;
private int row = 0;
private PowerUpType curPowerUpType;
private BrickShape.Shape curShape;
private BrickType curType;
private Box2DDebugRenderer debugRenderer;
private long lastBlink = System.currentTimeMillis();
private boolean blink = false;
public EditorState(BrickBuster game) {
super(game);
}
@Override
public void setup() {
world = new World(new Vector2(), false);
world.setContactListener(new Box2dContactListener());
curPowerUpType = null;
curShape = BrickShape.Shape.RECTANGLE;
curType = BrickType.STANDARD_10;
updatePlaceHolder();
Gdx.input.setInputProcessor(new InputProcessor());
debugRenderer = new Box2DDebugRenderer();
}
@Override
public void render() {
for (int col = 0; col < bricks.length; col++) {
for (int row = 0; row < bricks[col].length; row++) {
if (col == this.col && row == this.row && !blink) {
continue;
}
Brick brick = bricks[col][row];
if (brick != null) {
brick.render(game.sr);
}
}
}
if (!blink) {
placeHolder.render(game.sr);
}
debugRenderer.render(world, game.cam.combined.cpy().scl(PlayState.PIXEL_PER_METER));
game.sb.begin();
game.font.setColor(Color.GRAY);
game.font.draw(game.sb, String.format("Current powerup: %s", curPowerUpType), 10, 230);
game.font.draw(game.sb, "WASD: Move brick", 10, 170);
game.font.draw(game.sb, "ENTER: Set brick BACKSPACE: Delete brick F12: Save", 10, 110);
game.font.draw(game.sb, "UP/DOWN: type LEFT/RIGHT: shape SPACE: powerup", 10, 55);
game.sb.end();
}
@Override
public void update(float dt) {
long now = System.currentTimeMillis();
if (now - lastBlink > BLINK_INTERVAL) {
blink = !blink;
lastBlink = now;
}
}
private void updatePlaceHolder() {
if (placeHolder != null) {
world.destroyBody(placeHolder.getBody());
}
placeHolder = createBrick();
}
private Brick createBrick() {
return new Brick(this, curType, curShape, curPowerUpType, getBrickX(), getBrickY());
}
private float getBrickX() {
return PlayState.EDGE_PADDING + Brick.BRICK_WIDTH/2 + col * Brick.BRICK_WIDTH;
}
private float getBrickY() {
return PlayState.BOARD_HEIGHT - (PlayState.EDGE_PADDING + Brick.BRICK_HEIGHT/2 + row * Brick.BRICK_HEIGHT);
}
private void saveToFile() {
Json json = new Json();
FileHandle file = Gdx.files.external("level.json");
LevelJsonTemplate level = new LevelJsonTemplate();
level.bricks = new ArrayList<LevelJsonTemplate.BrickJsonTemplate>();
for (int col = 0; col < bricks.length; col++) {
for (int row = 0; row < bricks[col].length; row++) {
Brick brick = bricks[col][row];
if (brick == null) {
continue;
}
LevelJsonTemplate.BrickJsonTemplate brickJson = new LevelJsonTemplate.BrickJsonTemplate();
brickJson.col = col;
brickJson.row = row;
brickJson.type = brick.getType();
brickJson.shape = brick.getShape();
brickJson.powerUp = brick.getPowerUpType();
level.bricks.add(brickJson);
}
}
file.writeString(json.prettyPrint(level), false);
System.out.println("level.json saved to " + file.file().getAbsolutePath());
}
private final class InputProcessor extends InputAdapter {
@Override
public boolean keyDown(int keycode) {
int next = -1;
switch (keycode) {
case Input.Keys.UP:
next = curType.ordinal() == BrickType.values().length-1? 0 : curType.ordinal()+1;
curType = BrickType.values()[next];
updatePlaceHolder();
break;
case Input.Keys.DOWN:
next = curType.ordinal() == 0? BrickType.values().length-1 : curType.ordinal()-1;
curType = BrickType.values()[next];
updatePlaceHolder();
break;
case Input.Keys.LEFT:
next = curShape.ordinal() == 0? BrickShape.Shape.values().length-1 : curShape.ordinal()-1;
curShape = BrickShape.Shape.values()[next];
updatePlaceHolder();
break;
case Input.Keys.RIGHT:
next = curShape.ordinal() == BrickShape.Shape.values().length-1? 0 : curShape.ordinal()+1;
curShape = BrickShape.Shape.values()[next];
updatePlaceHolder();
break;
case Input.Keys.W:
if (row > 0) {
row--;
placeHolder.setY(getBrickY());
}
break;
case Input.Keys.A:
if (col > 0) {
col--;
placeHolder.setX(getBrickX());
}
break;
case Input.Keys.S:
if (row < ROWS-1) {
row++;
placeHolder.setY(getBrickY());
}
break;
case Input.Keys.D:
if (col < COLUMNS-1) {
col++;
placeHolder.setX(getBrickX());
}
break;
case Input.Keys.SPACE:
next = curPowerUpType == null? 0 : curPowerUpType.ordinal()+1;
if (next >= curPowerUpType.values().length) {
curPowerUpType = null;
} else {
curPowerUpType = PowerUpType.values()[next];
}
break;
case Input.Keys.ENTER:
if (bricks[col][row] != null) {
world.destroyBody(bricks[col][row].getBody());
bricks[col][row].dispose();
}
bricks[col][row] = createBrick();
break;
case Input.Keys.BACKSPACE:
if (bricks[col][row] != null) {
world.destroyBody(bricks[col][row].getBody());
bricks[col][row].dispose();
bricks[col][row] = null;
}
break;
case Input.Keys.F12:
saveToFile();
break;
default:
return false;
}
return true;
}
}
}

View File

@ -1,6 +1,7 @@
package com.me.brickbuster.state; package com.me.brickbuster.state;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.Vector3;
import com.me.brickbuster.BrickBuster; import com.me.brickbuster.BrickBuster;
@ -39,6 +40,11 @@ public class MenuState extends State {
dispose(); dispose();
} }
} }
if(Gdx.input.isKeyJustPressed(Input.Keys.F12)) {
game.setScreen(new EditorState(game));
dispose();
}
} }
@Override @Override