Implemented elevation in editor and mechanically in-game

This commit is contained in:
Anuken
2018-06-11 15:18:25 -04:00
parent cbd83b5e39
commit b609b5909b
25 changed files with 534 additions and 376 deletions

View File

@@ -1,5 +1,6 @@
package io.anuke.mindustry;
import com.badlogic.gdx.utils.async.AsyncExecutor;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.io.BundleLoader;
import io.anuke.ucore.core.Timers;
@@ -9,21 +10,20 @@ import io.anuke.ucore.util.Log;
import static io.anuke.mindustry.Vars.*;
public class Mindustry extends ModuleCore {
private AsyncExecutor exec = new AsyncExecutor(1);
@Override
public void init(){
Timers.mark();
Vars.init();
debug = Platform.instance.isDebug();
Timers.mark();
Log.setUseColors(false);
BundleLoader.load();
ContentLoader.load();
Log.info("Time to load content: {0}", Timers.elapsed());
module(logic = new Logic());
module(world = new World());
module(control = new Control());
@@ -31,6 +31,8 @@ public class Mindustry extends ModuleCore {
module(ui = new UI());
module(netServer = new NetServer());
module(netClient = new NetClient());
Log.info("Time to load [total]: {0}", Timers.elapsed());
}
@Override

View File

@@ -152,7 +152,7 @@ public class Pathfinder {
if (other != null && (path.weights[dx][dy] > cost + 1 || path.searches[dx][dy] < path.search)
&& passable(other, team)){
path.frontier.addFirst(world.tile(dx, dy));
path.weights[dx][dy] = cost + other.cost;
path.weights[dx][dy] = cost + other.cost/2f;
path.searches[dx][dy] = path.search;
}
}

View File

@@ -12,13 +12,18 @@ import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.*;
public class Blocks extends BlockList implements ContentList{
public static Block air, spawn, blockpart, defaultFloor, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, iron, lead, coal, titanium, thorium, dirt, sand, ice, snow, grass, sandblock, snowblock, stoneblock, blackstoneblock, grassblock, mossblock, shrub, rock, icerock, blackrock, dirtblock;
public static Block air, spawn, blockpart, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, iron, lead, coal, titanium, thorium, dirt, sand, ice, snow, grass, sandblock, snowblock, stoneblock, blackstoneblock, grassblock, mossblock, shrub, rock, icerock, blackrock, dirtblock;
@Override
public void load() {
air = new Floor("air") {
{
blend = false;
}
//don't draw
public void draw(Tile tile) {}
public void load() {}
public void init() {}
};
blockpart = new BlockPart();
@@ -28,13 +33,12 @@ public class Blocks extends BlockList implements ContentList{
new BreakBlock("break" + i);
}
defaultFloor = new Floor("defaultfloor");
space = new Floor("space") {{
placeableOn = false;
variants = 0;
cacheLayer = CacheLayer.space;
solid = true;
blend = false;
}};
metalfloor = new Floor("metalfloor") {{

View File

@@ -116,7 +116,6 @@ public class ContentLoader {
/**Initializes all content with the specified function.*/
public static void initialize(Consumer<Content> callable){
for(Array<? extends Content> arr : contentSet){
for(Content content : arr){
callable.accept(content);

View File

@@ -50,6 +50,7 @@ public class Control extends Module{
private Input gdxInput;
public Control(){
saves = new Saves();
db = new ContentDatabase();
@@ -60,9 +61,7 @@ public class Control extends Module{
Effects.setShakeFalloff(10000f);
ContentLoader.initialize(Content::init);
Core.atlas = new Atlas("sprites.atlas");
ContentLoader.initialize(Content::load);
db.load();

View File

@@ -250,21 +250,21 @@ public class UI extends SceneModule{
public void showInfo(String info){
new Dialog("$text.info.title", "dialog"){{
getCell(content()).growX();
content().margin(15).add(info).width(400f).wrap();
content().margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center);
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
}}.show();
}
public void showError(String text){
new Dialog("$text.error.title", "dialog"){{
content().margin(15).add(text).width(400f).wrap();
content().margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
buttons().addButton("$text.ok", this::hide).size(90, 50).pad(4);
}}.show();
}
public void showConfirm(String title, String text, Listenable confirmed){
FloatingDialog dialog = new FloatingDialog(title);
dialog.content().add(text).width(400f).wrap().pad(4f);
dialog.content().add(text).width(400f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
dialog.buttons().defaults().size(200f, 54f).pad(2f);
dialog.buttons().addButton("$text.cancel", dialog::hide);
dialog.buttons().addButton("$text.ok", () -> {

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.io.MapTileData.DataPosition;
import io.anuke.mindustry.io.MapTileData.TileDataMarker;
import io.anuke.mindustry.world.Block;
@@ -32,6 +33,7 @@ public enum EditorTool{
pencil{
{
edit = true;
draggable = true;
}
@Override
@@ -39,6 +41,17 @@ public enum EditorTool{
editor.draw(x, y);
}
},
eraser{
{
edit = true;
draggable = true;
}
@Override
public void touched(MapEditor editor, int x, int y){
editor.draw(x, y, Blocks.air);
}
},
line{
{
@@ -110,7 +123,8 @@ public enum EditorTool{
}
},
zoom;
boolean edit;
boolean edit, draggable;
public void touched(MapEditor editor, int x, int y){

View File

@@ -22,6 +22,7 @@ public class MapEditor{
private MapRenderer renderer = new MapRenderer(this);
private int brushSize = 1;
private byte elevation;
private int rotation;
private Block drawBlock = Blocks.stone;
private Team drawTeam = Team.none;
@@ -47,6 +48,14 @@ public class MapEditor{
renderer.resize(map.width(), map.height());
}
public void setDrawElevation(int elevation){
this.elevation = (byte)elevation;
}
public byte getDrawElevation(){
return elevation;
}
public int getDrawRotation(){
return rotation;
}
@@ -80,6 +89,10 @@ public class MapEditor{
}
public void draw(int x, int y){
draw(x, y, drawBlock);
}
public void draw(int x, int y, Block drawBlock){
if(x < 0 || y < 0 || x >= map.width() || y >= map.height()){
return;
}
@@ -88,7 +101,7 @@ public class MapEditor{
byte partID = (byte)Blocks.blockpart.id;
byte rotationTeam = Bits.packByte(drawBlock.rotate ? (byte)rotation : 0, drawBlock.synthetic() ? (byte)drawTeam.ordinal() : 0);
boolean isfloor = drawBlock instanceof Floor;
boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air;
if(drawBlock.isMultiblock()) {
@@ -155,6 +168,7 @@ public class MapEditor{
if(isfloor){
map.write(wx, wy, DataPosition.floor, writeID);
map.write(wx, wy, DataPosition.elevation, elevation);
}else{
map.write(wx, wy, DataPosition.wall, writeID);
map.write(wx, wy, DataPosition.link, (byte)0);

View File

@@ -24,6 +24,7 @@ import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.function.Listenable;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.input.Input;
@@ -192,11 +193,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
menu.content().row();
menu.content().addImageTextButton("$text.quit", "icon-back", isize, () -> {
if(!saved){
ui.showConfirm("$text.confirm", "$text.editor.unsaved", this::hide);
}else{
hide();
}
tryExit();
menu.hide();
}).padTop(-5).size(swidth*2f + 10, 60f);
@@ -382,8 +379,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
public void build(){
float size = mobile ? (int)(Gdx.graphics.getHeight() / 9.5f / Unit.dp.scl(1f)) : 60;
float amount = 9.5f, baseSize = 60f;
float size = mobile ? (int)(Gdx.graphics.getHeight() / amount / Unit.dp.scl(1f)) :
Math.min(Gdx.graphics.getDisplayMode().height / amount, baseSize);
new table(){{
aleft();
@@ -394,11 +394,22 @@ public class MapEditorDialog extends Dialog implements Disposable{
atop();
ButtonGroup<ImageButton> group = new ButtonGroup<>();
int i = 1;
Consumer<EditorTool> addTool = tool -> {
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
button.clicked(() -> view.setTool(tool));
button.resizeImage(16*2f);
button.update(() -> button.setChecked(view.getTool() == tool));
group.add(button);
if (tool == EditorTool.pencil)
button.setChecked(true);
tools.add(button).padBottom(-5.1f);
};
tools.defaults().size(size, size + 4f).padBottom(-5.1f);
//tools.addImageButton("icon-back", 16*2, () -> hide());
tools.addImageButton("icon-back", 16*2, () -> tryExit());
tools.addImageButton("icon-menu-large", 16*2f, menu::show);
@@ -409,6 +420,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addImageButton("icon-redo", 16*2f, () -> view.redo()).get();
addTool.accept(EditorTool.pick);
tools.row();
undo.setDisabled(() -> !view.getStack().canUndo());
@@ -418,18 +431,14 @@ public class MapEditorDialog extends Dialog implements Disposable{
redo.update(() -> redo.getImage().setColor(redo.isDisabled() ? Color.GRAY : Color.WHITE));
grid.update(() -> grid.setChecked(view.isGrid()));
for(EditorTool tool : EditorTool.values()){
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
button.clicked(() -> view.setTool(tool));
button.resizeImage(16*2f);
button.update(() -> button.setChecked(view.getTool() == tool));
group.add(button);
if (tool == EditorTool.pencil)
button.setChecked(true);
addTool.accept(EditorTool.line);
addTool.accept(EditorTool.pencil);
addTool.accept(EditorTool.eraser);
tools.add(button).padBottom(-5.1f);
if(i++ % 2 == 0) tools.row();
}
tools.row();
addTool.accept(EditorTool.fill);
addTool.accept(EditorTool.zoom);
ImageButton rotate = tools.addImageButton("icon-arrow-16", 16*2f, () -> editor.setDrawRotation((editor.getDrawRotation() + 1)%4)).get();
rotate.getImage().update(() ->{
@@ -441,12 +450,14 @@ public class MapEditorDialog extends Dialog implements Disposable{
tools.table("button", t -> {
t.add("$text.editor.teams");
}).colspan(2).height(40).width(size*2f);
}).colspan(3).height(40).width(size*3f);
tools.row();
ButtonGroup<ImageButton> teamgroup = new ButtonGroup<>();
int i = 0;
for(Team team : Team.values()){
ImageButton button = new ImageButton("white", "toggle");
button.margin(4f, 4f, 10f, 4f);
@@ -457,7 +468,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
teamgroup.add(button);
tools.add(button).padBottom(-5.1f);
if(i++ % 2 == 1) tools.row();
if(i++ % 3 == 2) tools.row();
}
add(tools).top().padBottom(-6);
@@ -469,10 +480,30 @@ public class MapEditorDialog extends Dialog implements Disposable{
Slider slider = new Slider(0, MapEditor.brushSizes.length-1, 1, false);
slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int)(float)f]));
new label("brush");
//new label(() -> Bundles.format("text.editor.brushsize", MapEditor.brushSizes[(int)slider.getValue()])).left();
row();
add(slider).width(size*2f-20).padTop(4f);
}}.padTop(5).growY().top().end();
add(slider).width(size*3f-20).padTop(4f);
}}.padTop(5).growX().growY().top().end();
row();
get().table("button", t -> {
t.add("$text.editor.elevation");
}).colspan(3).height(40).width(size*3f);
row();
get().table("button", t -> {
t.margin(0);
t.addImageButton("icon-arrow-left", 16*2f, () -> {
editor.setDrawElevation(editor.getDrawElevation() - 1);
}).disabled(b -> editor.getDrawElevation() <= 0).size(size);
t.label(() -> editor.getDrawElevation() + "").size(size).get().setAlignment(Align.center, Align.center);
t.addImageButton("icon-arrow-right", 16*2f, () -> {
editor.setDrawElevation(editor.getDrawElevation() + 1);
}).disabled(b -> editor.getDrawElevation() >= 127).size(size);
}).colspan(3).height(size).padTop(-5).width(size*3f);
}}.left().growY().end();
@@ -532,6 +563,14 @@ public class MapEditorDialog extends Dialog implements Disposable{
}
}
private void tryExit(){
if(!saved){
ui.showConfirm("$text.confirm", "$text.editor.unsaved", this::hide);
}else{
hide();
}
}
private void addBlockSelection(Table table){
Table content = new Table();
pane = new ScrollPane(content, "volume");

View File

@@ -36,7 +36,9 @@ public class MapLoadDialog extends FloatingDialog{
public void rebuild(){
content().clear();
selected = world.maps().all().first();
if(world.maps().all().size > 0){
selected = world.maps().all().first();
}
ButtonGroup<TextButton> group = new ButtonGroup<>();

View File

@@ -9,6 +9,7 @@ import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.PixmapPacker;
import com.badlogic.gdx.graphics.g2d.PixmapPacker.Page;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.IntSet;
@@ -23,7 +24,9 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.IndexedRenderer;
import io.anuke.ucore.util.Bits;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.tilesize;
@@ -31,8 +34,10 @@ public class MapRenderer implements Disposable{
private static final int chunksize = 64;
private IndexedRenderer[][] chunks;
private IntSet updates = new IntSet();
private IntSet delayedUpdates = new IntSet();
private MapEditor editor;
private int width, height;
private Color tmpColor = Color.WHITE.cpy();
private ObjectMap<Block, TextureRegion> blockIcons = new ObjectMap<>();
private ObjectMap<String, TextureRegion> regions = new ObjectMap<>();
@@ -65,6 +70,7 @@ public class MapRenderer implements Disposable{
add("clear", packer);
add("block-border", packer);
add("block-elevation", packer);
if(packer.getPages().size > 1){
throw new IllegalArgumentException("Pixmap packer may not have more than 1 page!");
@@ -131,6 +137,9 @@ public class MapRenderer implements Disposable{
}
updates.clear();
updates.addAll(delayedUpdates);
delayedUpdates.clear();
for(int x = 0; x < chunks.length; x ++){
for(int y = 0; y < chunks[0].length; y ++){
IndexedRenderer mesh = chunks[x][y];
@@ -166,6 +175,7 @@ public class MapRenderer implements Disposable{
byte bf = editor.getMap().read(wx, wy, DataPosition.floor);
byte bw = editor.getMap().read(wx, wy, DataPosition.wall);
byte btr = editor.getMap().read(wx, wy, DataPosition.rotationTeam);
byte elev = editor.getMap().read(wx, wy, DataPosition.elevation);
byte rotation = Bits.getLeftByte(btr);
Team team = Team.values()[Bits.getRightByte(btr)];
@@ -198,6 +208,9 @@ public class MapRenderer implements Disposable{
if(wall.update || wall.destructible) {
mesh.setColor(team.color);
region = regions.get("block-border");
}else if(elev > 0 && checkElevation(elev, wx, wy)){
mesh.setColor(tmpColor.fromHsv((360f * elev/127f * 4f) % 360f, 0.5f + (elev / 4f) % 0.5f, 1f));
region = regions.get("block-elevation");
}else{
region = regions.get("clear");
}
@@ -208,6 +221,23 @@ public class MapRenderer implements Disposable{
mesh.setColor(Color.WHITE);
}
private boolean checkElevation(byte elev, int x, int y){
for(GridPoint2 p : Geometry.d4){
int wx = x + p.x, wy = y + p.y;
if(!Mathf.inBounds(wx, wy, editor.getMap().width(), editor.getMap().height())){
return true;
}
byte value = editor.getMap().read(wx, wy, DataPosition.elevation);
if(value < elev){
return true;
}else if(value > elev){
delayedUpdates.add(wx + wy*width);
}
}
return false;
}
@Override
public void dispose() {
if(chunks == null){

View File

@@ -1,5 +1,6 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.input.GestureDetector;
@@ -50,6 +51,7 @@ public class MapView extends Element implements GestureListener{
private int lastx, lasty;
private int startx, starty;
private float mousex, mousey;
private EditorTool lastTool;
public void setTool(EditorTool tool){
this.tool = tool;
@@ -123,6 +125,15 @@ public class MapView extends Element implements GestureListener{
return false;
}
if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){
return true;
}
if(button == Buttons.MIDDLE){
lastTool = tool;
tool = EditorTool.zoom;
}
mousex = x;
mousey = y;
@@ -148,6 +159,10 @@ public class MapView extends Element implements GestureListener{
@Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
if(!mobile && button != Buttons.LEFT && button != Buttons.MIDDLE){
return;
}
drawing = false;
GridPoint2 p = project(x, y);
@@ -168,6 +183,11 @@ public class MapView extends Element implements GestureListener{
op = null;
}
if(lastTool != null){
tool = lastTool;
lastTool = null;
}
}
@Override
@@ -177,11 +197,11 @@ public class MapView extends Element implements GestureListener{
GridPoint2 p = project(x, y);
if(drawing && tool == EditorTool.pencil){
if(drawing && tool.draggable){
ui.editor.resetSaved();
Array<GridPoint2> points = br.line(lastx, lasty, p.x, p.y);
for(GridPoint2 point : points){
editor.draw(point.x, point.y);
tool.touched(editor, point.x, point.y);
}
updated = true;
}
@@ -221,7 +241,7 @@ public class MapView extends Element implements GestureListener{
x = (x - getWidth()/2 + sclwidth/2 - offsetx*zoom) / sclwidth * editor.getMap().width();
y = (y - getHeight()/2 + sclheight/2 - offsety*zoom) / sclheight * editor.getMap().height();
if(editor.getDrawBlock().size % 2 == 0){
if(editor.getDrawBlock().size % 2 == 0 && tool != EditorTool.eraser){
return Tmp.g1.set((int)(x - 0.5f), (int)(y - 0.5f));
}else{
return Tmp.g1.set((int)x, (int)y);
@@ -280,7 +300,7 @@ public class MapView extends Element implements GestureListener{
Draw.color(Palette.accent);
Lines.stroke(Unit.dp.scl(1f * zoom));
if(!editor.getDrawBlock().isMultiblock()) {
if(!editor.getDrawBlock().isMultiblock() || tool == EditorTool.eraser) {
if (tool == EditorTool.line && drawing) {
Vector2 v1 = unproject(startx, starty).add(x, y);
float sx = v1.x, sy = v1.y;

View File

@@ -160,7 +160,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
public Floor getFloorOn(){
Tile tile = world.tileWorld(x, y);
return (Floor)(tile == null || (tile.floor() == null) ? Blocks.defaultFloor : tile.floor());
return tile == null ? (Floor) Blocks.air : tile.floor();
}
/**Updates velocity and status effects.*/

View File

@@ -6,7 +6,9 @@ public enum Team {
none(Color.DARK_GRAY),
blue(Color.ROYAL),
red(Color.valueOf("e84737")),
green(Color.valueOf("1dc645"));
green(Color.valueOf("1dc645")),
purple(Color.valueOf("ba5bd9")),
orange(Color.valueOf("e8c66a"));
public final Color color;
public final int intColor;

View File

@@ -6,12 +6,13 @@ import io.anuke.ucore.util.Bits;
import java.nio.ByteBuffer;
public class MapTileData {
/**Tile size: 3 bytes. <br>
/**Tile size: 4 bytes. <br>
* 0: ground tile <br>
* 1: wall tile <br>
* 2: rotation + team <br>
* 3: link (x/y) <br>*/
private final static int TILE_SIZE = 4;
* 3: link (x/y) <br>
* 4: elevation <br>*/
private final static int TILE_SIZE = 5;
private final ByteBuffer buffer;
private final int width, height;
@@ -91,7 +92,7 @@ public class MapTileData {
}
public enum DataPosition{
floor, wall, link, rotationTeam
floor, wall, link, rotationTeam, elevation
}
public class TileDataMarker {
@@ -99,12 +100,14 @@ public class MapTileData {
public byte link;
public byte rotation;
public byte team;
public byte elevation;
public void read(ByteBuffer buffer){
floor = buffer.get();
wall = buffer.get();
link = buffer.get();
byte rt = buffer.get();
elevation = buffer.get();
rotation = Bits.getLeftByte(rt);
team = Bits.getRightByte(rt);
@@ -120,6 +123,7 @@ public class MapTileData {
buffer.put(wall);
buffer.put(link);
buffer.put(Bits.packByte(rotation, team));
buffer.put(elevation);
}
}
}

View File

@@ -18,7 +18,7 @@ import static io.anuke.mindustry.Vars.*;
public class Maps implements Disposable{
/**List of all built-in maps.*/
private static final String[] defaultMapNames = {"test"};
private static final String[] defaultMapNames = {};
/**Tile format version.*/
private static final int version = 0;

View File

@@ -79,8 +79,6 @@ public class Block extends BaseBlock implements UnlockableContent{
public float baseExplosiveness = 0f;
/**whether to display a different shadow per variant*/
public boolean varyShadow = false;
/**edge fallback, used mainly for ores*/
public String edge = "stone";
/**number of block variants, 0 to disable*/
public int variants = 0;
/**stuff that drops when broken*/

View File

@@ -16,6 +16,7 @@ import io.anuke.mindustry.world.blocks.modules.PowerModule;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Bits;
import io.anuke.ucore.entities.trait.PosTrait;
import io.anuke.ucore.util.Geometry;
import static io.anuke.mindustry.Vars.tilesize;
import static io.anuke.mindustry.Vars.world;
@@ -26,15 +27,21 @@ public class Tile implements PosTrait, TargetTrait {
/**Block ID data.*/
private byte floor, wall;
/**Rotation, 0-3. Also used to store offload location.*/
private byte rotation;
private byte dump;
/**Team ordinal.*/
private byte team;
/**The coordinates of the core tile this is linked to, in the form of two bytes packed into one.
* This is relative to the block it is linked to; negate coords to find the link.*/
public byte link = 0;
public short x, y;
/**Tile traversal cost*/
public float cost = 1f;
/**Tile traversal cost.*/
public byte cost = 1;
/**Elevation of tile.*/
public byte elevation;
/**Position of cliffs around the tile, packed into bits 0-8.*/
public byte cliffs;
/**Tile entity, usually null.*/
public TileEntity entity;
public Tile(int x, int y){
@@ -49,11 +56,12 @@ public class Tile implements PosTrait, TargetTrait {
changed();
}
public Tile(int x, int y, byte floor, byte wall, byte rotation, byte team){
public Tile(int x, int y, byte floor, byte wall, byte rotation, byte team, byte elevation){
this(x, y);
this.floor = floor;
this.wall = wall;
this.rotation = rotation;
this.elevation = elevation;
changed();
this.team = team;
}
@@ -172,7 +180,7 @@ public class Tile implements PosTrait, TargetTrait {
}
public void setDump(byte dump){
this.dump = dump;
this.rotation = dump;
}
public byte getRotation(){
@@ -180,7 +188,7 @@ public class Tile implements PosTrait, TargetTrait {
}
public byte getDump(){
return dump;
return rotation;
}
public boolean passable(){
@@ -198,7 +206,7 @@ public class Tile implements PosTrait, TargetTrait {
public boolean solid(){
Block block = block();
Block floor = floor();
return block.solid || (floor.solid && (block == Blocks.air || block.solidifes)) || block.isSolidFor(this)
return block.solid || cliffs != 0 || (floor.solid && (block == Blocks.air || block.solidifes)) || block.isSolidFor(this)
|| (isLinked() && getLinked().block().isSolidFor(getLinked()));
}
@@ -300,20 +308,23 @@ public class Tile implements PosTrait, TargetTrait {
}
public void updateOcclusion(){
cost = 0.5f;
cost = 1;
cliffs = 0;
boolean occluded = false;
outer:
for(int dx = -1; dx <= 1; dx ++){
for(int dy = -1; dy <= 1; dy ++){
Tile tile = world.tile(x + dx, y + dy);
if(tile != null && tile.solid()){
for(int i = 0; i < 8; i ++){
GridPoint2 point = Geometry.d8[i];
Tile tile = world.tile(x + point.x, y + point.y);
if(tile != null){
if(tile.solid()){
occluded = true;
break outer;
}
if(tile.elevation < elevation){
cliffs |= (0x1 << i);
}
}
}
if(occluded){
cost += 0.5f;
cost += 1;
}
}

View File

@@ -25,20 +25,23 @@ public class WorldGenerator {
for(int y = 0; y < data.height(); y ++){
for(int x = 0; x < data.width(); x ++){
TileDataMarker tile = data.read(marker);
tiles[x][y] = new Tile(x, y, tile.floor, tile.wall == Blocks.blockpart.id ? 0 : tile.wall, tile.rotation, tile.team);
data.read(marker);
Team team = Team.values()[tile.team];
Tile tile = new Tile(x, y, marker.floor, marker.wall == Blocks.blockpart.id ? 0 : marker.wall, marker.rotation, marker.team, marker.elevation);
if(tiles[x][y].block().isMultiblock()){
multiblocks.add(tiles[x][y].packedPosition());
Team team = Team.values()[marker.team];
if(tile.block().isMultiblock()){
multiblocks.add(tile.packedPosition());
}
if(tiles[x][y].block() == StorageBlocks.core &&
if(tile.block() == StorageBlocks.core &&
state.teams.has(team)){
state.teams.get(team).cores.add(tiles[x][y]);
state.teams.get(team).cores.add(tile);
}
tiles[x][y] = tile;
//TODO ores, plants, extra decoration?
}
}

View File

@@ -6,8 +6,8 @@ import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.mindustry.content.fx.BlockFx;
import io.anuke.mindustry.type.StatusEffect;
import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.type.StatusEffect;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects.Effect;
@@ -25,6 +25,8 @@ public class Floor extends Block{
protected Predicate<Block> blends = block -> block != this;
protected boolean blend = true;
/**edge fallback, used mainly for ores*/
public String edge = "stone";
/**Multiplies unit velocity by this when walked on.*/
public float speedMultiplier = 1f;
/**Multiplies unit drag by this when walked on.*/