Tree-based zone layout

This commit is contained in:
Anuken
2019-01-25 21:48:03 -05:00
parent 89e29bce62
commit ead0547d59
4 changed files with 161 additions and 159 deletions

View File

@@ -237,7 +237,5 @@ public class Zones implements ContentList{
waveSpacing = 60 * 80;
}};
}};
frozenForest.zoneRequirements = new Zone[]{frozenForest};
}
}

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.game;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.Vars;
/**Base interface for an unlockable content type.*/
public abstract class UnlockableContent extends MappableContent{
@@ -26,4 +27,12 @@ public abstract class UnlockableContent extends MappableContent{
public boolean alwaysUnlocked(){
return false;
}
public final boolean unlocked(){
return Vars.data.isUnlocked(this);
}
public final boolean locked(){
return !unlocked();
}
}

View File

@@ -5,14 +5,8 @@ import io.anuke.arc.collection.Array;
import io.anuke.arc.collection.ObjectIntMap;
import io.anuke.arc.collection.ObjectSet;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.graphics.g2d.Lines;
import io.anuke.arc.scene.Group;
import io.anuke.arc.scene.event.InputEvent;
import io.anuke.arc.scene.event.InputListener;
import io.anuke.arc.scene.event.Touchable;
import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.arc.scene.ui.ImageButton;
import io.anuke.arc.scene.ui.ScrollPane;
import io.anuke.arc.scene.ui.TextButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Align;
@@ -20,6 +14,7 @@ import io.anuke.arc.util.Structs;
import io.anuke.mindustry.content.Zones;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.Saves.SaveSlot;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.io.SaveIO.SaveException;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack;
@@ -27,7 +22,6 @@ import io.anuke.mindustry.type.ItemType;
import io.anuke.mindustry.type.Zone;
import io.anuke.mindustry.ui.TreeLayout;
import io.anuke.mindustry.ui.TreeLayout.TreeNode;
import io.anuke.mindustry.ui.dialogs.TechTreeDialog.TechTreeNode;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Block.Icon;
@@ -51,7 +45,10 @@ public class DeployDialog extends FloatingDialog{
cont.setFillParent(true);
cont.add(new View()).grow();
shown(this::setup);
addCloseButton();
buttons.addImageTextButton("$techtree", "icon-tree", 16 * 2, () -> ui.tech.show()).size(230f, 64f);
//shown(this::setup);
}
public void setup(){
@@ -74,153 +71,48 @@ public class DeployDialog extends FloatingDialog{
}
}
}}, new ScrollPane(new Table(){{
}}, new Table(){{
SaveSlot slot = control.saves.getZoneSlot();
if(control.saves.getZoneSlot() == null){
TextButton[] b = {null};
int i = 0;
for(Zone zone : content.zones()){
table(t -> {
TextButton button = t.addButton("", () -> {
if(!data.isUnlocked(zone)){
data.removeItems(zone.itemRequirements);
data.unlockContent(zone);
setup();
}else{
data.removeItems(zone.deployCost);
hide();
world.playZone(zone);
}
}).size(250f).disabled(b -> !canUnlock(zone)).get();
TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> {
if(b[0].childrenPressed()) return;
button.clearChildren();
if(data.isUnlocked(zone)){
button.table(title -> {
title.addImage("icon-zone").padRight(3);
title.add(zone.localizedName());
});
button.row();
if(data.getWaveScore(zone) > 0){
button.add(Core.bundle.format("bestwave", data.getWaveScore(zone)));
}
button.row();
button.add("$launch").color(Color.LIGHT_GRAY).pad(4);
button.row();
button.table(req -> {
for(ItemStack stack : zone.deployCost){
req.addImage(stack.item.region).size(8 * 3);
req.add(stack.amount + "").left();
}
}).pad(3).growX();
}else{
button.addImage("icon-zone-locked");
button.row();
button.add("$locked").padBottom(6);
if(!hidden(zone)){
button.row();
button.table(req -> {
req.defaults().left();
if(zone.zoneRequirements.length > 0){
req.table(r -> {
r.add("$complete").colspan(2).left();
r.row();
for(Zone other : zone.zoneRequirements){
r.addImage("icon-zone").padRight(4);
r.add(other.localizedName()).color(Color.LIGHT_GRAY);
r.addImage(data.isCompleted(other) ? "icon-check-2" : "icon-cancel-2")
.color(data.isCompleted(other) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
});
}
req.row();
if(zone.itemRequirements.length > 0){
req.table(r -> {
for(ItemStack stack : zone.itemRequirements){
r.addImage(stack.item.region).size(8 * 3).padRight(4);
r.add(Math.min(data.getItem(stack.item), stack.amount) + "/" + stack.amount)
.color(stack.amount > data.getItem(stack.item) ? Color.SCARLET : Color.LIGHT_GRAY).left();
r.row();
}
}).padTop(10);
}
req.row();
if(zone.blockRequirements.length > 0){
req.table(r -> {
r.add("$research.list").colspan(2).left();
r.row();
for(Block block : zone.blockRequirements){
r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4);
r.add(block.formalName).color(Color.LIGHT_GRAY);
r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2")
.color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
}).padTop(10);
}
}).growX();
}
}
}).pad(4);
if(++i % 2 == 0){
row();
hide();
ui.loadAnd(() -> {
try{
control.saves.getZoneSlot().load();
state.set(State.playing);
}catch(SaveException e){ //make sure to handle any save load errors!
e.printStackTrace();
if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete();
ui.showInfo("$save.corrupted");
show();
}
}
}else{
SaveSlot slot = control.saves.getZoneSlot();
});
}).size(200f).get();
b[0] = button;
TextButton b[] = {null};
String color = "[lightgray]";
TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> {
if(b[0].childrenPressed()) return;
button.defaults().colspan(2);
button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row();
button.add().grow();
button.row();
hide();
ui.loadAnd(() -> {
try{
control.saves.getZoneSlot().load();
state.set(State.playing);
}catch(SaveException e){ //make sure to handle any save load errors!
e.printStackTrace();
if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete();
ui.showInfo("$save.corrupted");
show();
}
});
}).size(200f).get();
b[0] = button;
button.addButton("$abandon", () -> {
ui.showConfirm("$warning", "$abandon.text", () -> {
slot.delete();
setup();
});
}).growX().height(50f).pad(-12).padTop(10);
String color = "[lightgray]";
button.defaults().colspan(2);
button.row();
button.add(Core.bundle.format("save.wave", color + slot.getWave()));
button.row();
button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime()));
button.row();
button.add().grow();
button.row();
button.addButton("$abandon", () -> {
ui.showConfirm("$warning", "$abandon.text", () -> {
slot.delete();
setup();
});
}).growX().height(50f).pad(-12).padTop(10);
}
}})).grow();
}}).grow();
}
boolean hidden(Zone zone){
@@ -257,24 +149,112 @@ public class DeployDialog extends FloatingDialog{
return data.hasItems(zone.itemRequirements);
}
static Array<Zone> arr = new Array<>();
void buildButton(Zone zone, TextButton button){
button.setDisabled(() -> !canUnlock(zone));
button.clicked(() -> {
if(!data.isUnlocked(zone)){
data.removeItems(zone.itemRequirements);
data.unlockContent(zone);
setup();
}else{
data.removeItems(zone.deployCost);
hide();
world.playZone(zone);
}
});
if(zone.unlocked()){
button.table(title -> {
title.addImage("icon-zone").padRight(3);
title.add(zone.localizedName());
});
button.row();
if(data.getWaveScore(zone) > 0){
button.add(Core.bundle.format("bestwave", data.getWaveScore(zone)));
}
button.row();
button.add("$launch").color(Color.LIGHT_GRAY).pad(4);
button.row();
button.table(req -> {
for(ItemStack stack : zone.deployCost){
req.addImage(stack.item.region).size(8 * 3);
req.add(stack.amount + "").left();
}
}).pad(3).growX();
}else{
button.addImage("icon-zone-locked");
button.row();
button.add("$locked").padBottom(6);
if(!hidden(zone)){
button.row();
button.table(req -> {
req.defaults().left();
if(zone.zoneRequirements.length > 0){
req.table(r -> {
r.add("$complete").colspan(2).left();
r.row();
for(Zone other : zone.zoneRequirements){
r.addImage("icon-zone").padRight(4);
r.add(other.localizedName()).color(Color.LIGHT_GRAY);
r.addImage(data.isCompleted(other) ? "icon-check-2" : "icon-cancel-2")
.color(data.isCompleted(other) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
});
}
req.row();
if(zone.itemRequirements.length > 0){
req.table(r -> {
for(ItemStack stack : zone.itemRequirements){
r.addImage(stack.item.region).size(8 * 3).padRight(4);
r.add(Math.min(data.getItem(stack.item), stack.amount) + "/" + stack.amount)
.color(stack.amount > data.getItem(stack.item) ? Color.SCARLET : Color.LIGHT_GRAY).left();
r.row();
}
}).padTop(10);
}
req.row();
if(zone.blockRequirements.length > 0){
req.table(r -> {
r.add("$research.list").colspan(2).left();
r.row();
for(Block block : zone.blockRequirements){
r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4);
r.add(block.formalName).color(Color.LIGHT_GRAY);
r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2")
.color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3);
r.row();
}
}).padTop(10);
}
}).growX();
}
}
}
class View extends Group{
float panX = 0, panY = -200;
{
for(ZoneNode node : nodes){
ImageButton button = new ImageButton("", "node");
TextButton button = new TextButton("", "node");
button.setSize(nodeSize, nodeSize);
button.update(() -> {
button.setPosition(node.x + panX + width/2f, node.y + panY + height/2f, Align.center);
button.getStyle().up = Core.scene.skin.getDrawable(!locked(node.node) ? "content-background" : "content-background-locked");
((TextureRegionDrawable)button.getStyle().imageUp)
.setRegion(node.visible ? node.node.block.icon(Icon.medium) : Core.atlas.find("icon-tree-locked"));
button.getImage().setColor(!locked(node.node) ? Color.WHITE : Color.GRAY);
});
button.clearChildren();
buildButton(node.zone, button);
addChild(button);
}
@@ -283,9 +263,24 @@ public class DeployDialog extends FloatingDialog{
panY += y;
});
}
@Override
public void draw(){
float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y;
for(ZoneNode node : nodes){
for(ZoneNode child : node.children){
Lines.stroke(3f, node.zone.locked() || child.zone.locked() ? Palette.locked : Palette.accent);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
}
super.draw();
}
}
class ZoneNode extends TreeNode<ZoneNode>{
final Array<Zone> arr = new Array<>();
final Zone zone;
ZoneNode(Zone zone, ZoneNode parent){