Added weapon upgrades, bugfixes

This commit is contained in:
Anuken
2017-05-05 15:19:19 -04:00
parent be0276bb2a
commit c9019dd2eb
25 changed files with 470 additions and 133 deletions

View File

@ -15,6 +15,12 @@ import io.anuke.ucore.util.Timers;
public class GameState{
public static void reset(){
for(Weapon weapon : Weapon.values()){
weapons.put(weapon, weapon.unlocked);
}
currentWeapon = Weapon.blaster;
wave = 1;
wavetime = waveSpacing();
Entities.clear();
@ -25,6 +31,7 @@ public class GameState{
spawnpoints.clear();
ui.updateItems();
ui.updateWeapons();
}
public static void play(){

View File

@ -5,6 +5,7 @@ import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Input.Buttons;
import io.anuke.mindustry.ai.Pathfind;
import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
@ -18,9 +19,32 @@ import io.anuke.ucore.util.Mathf;
public class Input{
public static void doInput(){
//player is dead
if(player.health <= 0) return;
if(Inputs.scrolled()){
Weapon[] val = Weapon.values();
int index = 0;
for(int i = 0; i < val.length; i ++)
if(val[i] == currentWeapon){
index = i;
break;
}
for(int i = 0; i < val.length; i ++){
index += Inputs.scroll();
if(index >= 0 && index < val.length){
if(weapons.get(val[index])){
currentWeapon = (val[index]);
break;
}
}else{
break;
}
}
ui.updateWeapons();
}
if(Inputs.keyUp("rotate"))
rotation++;

View File

@ -39,4 +39,10 @@ public class Inventory{
items.put(req.item, items.get(req.item, 0)-req.amount);
ui.updateItems();
}
public static void removeItems(ItemStack... reqs){
for(ItemStack req : reqs)
items.put(req.item, items.get(req.item, 0)-req.amount);
ui.updateItems();
}
}

View File

@ -158,6 +158,7 @@ public class Renderer{
float offset = 7;
float fraction = Mathf.clamp((float) health / maxhealth);
float w = (len * 2 * fraction);
Draw.thickness(3f);
Draw.color(Color.GRAY);
@ -166,7 +167,8 @@ public class Renderer{
Draw.color(Color.BLACK);
Draw.line(x - len + 1, y - offset, x + len, y - offset);
Draw.color(Color.RED);
Draw.line(x - len + 1, y - offset, x - len + (int)(len * 2 * fraction), y - offset);
if(w >= 1)
Draw.line(x - len + 1, y - offset, x - len + w, y - offset);
Draw.clear();
}
}

View File

@ -7,10 +7,11 @@ import java.util.function.BooleanSupplier;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.resource.*;
import io.anuke.mindustry.ui.*;
import io.anuke.ucore.core.Draw;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.graphics.Hue;
@ -25,12 +26,10 @@ import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Timers;
public class UI extends SceneModule{
Table itemtable;
Table itemtable, weapontable;
SettingsDialog prefs;
KeybindDialog keys;
Dialog about, menu, restart, tutorial, levels;
//Texture conveyor = new Texture("sprites/conveyor.png"), conveyort = new Texture("sprites/conveyort.png");
int selectedMap = 0;
Dialog about, menu, restart, tutorial, levels, upgrades;
BooleanSupplier play = () -> {
return playing;
@ -100,35 +99,16 @@ public class UI extends SceneModule{
@Override
public void init(){
ButtonGroup<ImageButton> mapgroup = new ButtonGroup<>();
//TODO oh my god just move these dialogs to different files
levels = new Dialog("Level Select");
levels.addCloseButton();
levels.getButtonTable().addButton("Play", ()->{
levels.hide();
World.loadMap(selectedMap);
GameState.play();
});
upgrades = new UpgradeDialog();
for(int i = 0; i < maps.length; i ++){
levels.content().add(maps[i]);
}
levels.content().row();
for(int i = 0; i < maps.length; i ++){
int index = i;
ImageButton image = new ImageButton(new TextureRegion(mapTextures[i]), "togglemap");
mapgroup.add(image);
image.clicked(()->{
selectedMap = index;
});
image.getImageCell().size(150, 150);
levels.content().add(image).size(180);
}
levels = new LevelDialog();
prefs = new SettingsDialog();
menu = new MenuDialog();
prefs.sliderPref("difficulty", "Difficulty", 1, 0, 2, i -> {
return i == 0 ? "Easy" : i == 1 ? "Normal" : "Hard";
});
@ -143,25 +123,7 @@ public class UI extends SceneModule{
about = new TextDialog("About", aboutText);
tutorial = new TextDialog("Tutorial", tutorialText)
.setDialog();
tutorial.hidden(()->{
playing = true;
paused = false;
});
tutorial.getButtonTable().addButton("OK", ()->{
tutorial.hide();
});
tutorial.content().pad(8);
tutorial.content().row();
tutorial.content().addCheck("Don't show again", b->{
Settings.putBool("tutorial", !b);
Settings.save();
}).padTop(4);
tutorial = new TutorialDialog();
restart = new Dialog("The core was destroyed.", "dialog"){
public Dialog show(Scene scene){
@ -179,41 +141,9 @@ public class UI extends SceneModule{
GameState.reset();
});
menu = new Dialog("Paused", "dialog");
menu.content().addButton("Back", ()->{
menu.hide();
paused = false;
}).width(200);
menu.content().row();
menu.content().addButton("Settings", ()->{
prefs.show();
}).width(200);
menu.content().row();
menu.content().addButton("Controls", ()->{
keys.show();
}).width(200);
menu.content().row();
menu.content().addButton("Back to menu", ()->{
new Dialog("Confirm", "dialog"){
{
text("Are you sure you want to quit?");
button("Ok", true);
button("Cancel", false);
}
protected void result(Object object){
if(object == Boolean.TRUE){
menu.hide();
paused = false;
playing = false;
}
}
}.show(scene);
}).width(200);
weapontable = fill();
weapontable.bottom();
weapontable.setVisible(play);
build.begin(scene);
@ -319,12 +249,6 @@ public class UI extends SceneModule{
table.add().size(size);
}
if(sec == Section.distribution){
table.row();
table.add().size(size);
}
table.setVisible(()->{
return button.isChecked();
});
@ -337,7 +261,14 @@ public class UI extends SceneModule{
add(stack).colspan(3);
get().pad(10f);
}}.right().bottom();
end();
}}.right().bottom().uniformX();
row();
new button("Upgrades", ()->{
upgrades.show();
}).uniformX().fillX();
get().setVisible(play);
@ -446,6 +377,46 @@ public class UI extends SceneModule{
build.end();
}
public void updateWeapons(){
weapontable.clearChildren();
for(Weapon weapon : Weapon.values()){
if(weapons.get(weapon) == Boolean.TRUE){
ImageButton button = new ImageButton(Draw.region("weapon-"+weapon.name()), "static");
button.getImageCell().size(40);
button.setDisabled(true);
if(weapon != currentWeapon)
button.setColor(Color.GRAY);
weapontable.add(button).size(48, 52);
Table tiptable = new Table();
String description = weapon.description;
tiptable.background("button");
tiptable.add("[PURPLE]" + weapon.name(), 0.75f).left().padBottom(2f);
tiptable.row();
tiptable.row();
tiptable.add("[ORANGE]" + description).left();
tiptable.pad(10f);
Tooltip tip = new Tooltip(tiptable);
tip.setInstant(true);
button.addListener(tip);
}
}
}
public void showPrefs(){
prefs.show();
}
public void showControls(){
keys.show();
}
public void showMenu(){
menu.show();
}

View File

@ -7,6 +7,7 @@ import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.world.Tile;
@ -17,8 +18,8 @@ public class Vars{
public static final float respawntime = 60*4;
public static final float wavespace = 20*60;
public static final float enemyspawnspace = 65;
public static final float breakduration = 40;
public static boolean debug = false;
public static final float breakduration = 30;
public static boolean debug = true;
public static final Vector2 vector = new Vector2();
@ -28,6 +29,8 @@ public class Vars{
public static UI ui;
public static final ObjectMap<Item, Integer> items = new ObjectMap<>();
public static final ObjectMap<Weapon, Boolean> weapons = new ObjectMap<Weapon, Boolean>();
public static Weapon currentWeapon;
public static Player player;
@ -39,6 +42,7 @@ public class Vars{
public static int worldsize = 128;
public static int pixsize = worldsize*tilesize;
public static Tile[][] tiles = new Tile[worldsize][worldsize];
public static Recipe recipe;
public static int rotation;

View File

@ -16,7 +16,6 @@ public class Player extends DestructibleEntity{
float speed = 1f;
float rotation;
float reload;
Weapon weapon = Weapon.blaster;
public Player(){
hitsize = 5;
@ -74,14 +73,14 @@ public class Player extends DestructibleEntity{
boolean shooting = Inputs.buttonDown(Buttons.LEFT) && recipe == null && !ui.hasMouse();
if(shooting && reload <= 0){
weapon.shoot(this);
currentWeapon.shoot(this);
Sounds.play("shoot");
reload = weapon.reload;
reload = currentWeapon.reload;
}
vector.limit(speed);
move(vector.x*delta, vector.y*delta);
move(vector.x*delta, vector.y*delta, 4);
if(!shooting){
direction.add(vector.scl(delta));

View File

@ -1,28 +1,54 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.util.Angles;
public enum Weapon{
blaster(15, BulletType.shot){
blaster(15, BulletType.shot, "Shoots a slow, weak bullet."){
{
unlocked = true;
}
},
trishot(15, BulletType.shot, "Shoots 3 bullets in a spread.", stack(Item.iron, 40)){
@Override
public void shoot(Player p){
float ang = mouseAngle(p);
float space = 12;
bullet(p, p.x, p.y, ang);
bullet(p, p.x, p.y, ang+space);
bullet(p, p.x, p.y, ang-space);
}
};
public float reload;
public BulletType type;
public boolean unlocked;
public ItemStack[] requirements;
public String description = "no desc for you";
private Weapon(float reload, BulletType type){
private Weapon(float reload, BulletType type, String desc, ItemStack... requirements){
this.reload = reload;
this.type = type;
this.requirements = requirements;
this.description = desc;
}
public void shoot(Player p){
bullet(p, p.x, p.y);
bullet(p, p.x, p.y, mouseAngle(p));
}
void bullet(Entity owner, float x, float y){
new Bullet(type, owner, x, y, Angles.mouseAngle(owner.x, owner.y)).add();
float mouseAngle(Entity owner){
return Angles.mouseAngle(owner.x, owner.y);
}
void bullet(Entity owner, float x, float y, float angle){
new Bullet(type, owner, x, y, angle).add();
}
private static ItemStack stack(Item item, int amount){
return new ItemStack(item, amount);
}
}

View File

@ -16,6 +16,7 @@ public enum Recipe{
conveyor(distribution, ProductionBlocks.conveyor, stack(Item.stone, 1)),
fastconveyor(distribution, ProductionBlocks.steelconveyor, stack(Item.steel, 1)),
router(distribution, ProductionBlocks.router, stack(Item.stone, 3)),
junction(distribution, ProductionBlocks.junction, stack(Item.iron, 5)),
turret(defense, WeaponBlocks.turret, stack(Item.stone, 6)),
dturret(defense, WeaponBlocks.doubleturret, stack(Item.stone, 12)),

View File

@ -0,0 +1,48 @@
package io.anuke.mindustry.ui;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import io.anuke.mindustry.GameState;
import io.anuke.mindustry.World;
import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.Dialog;
import io.anuke.ucore.scene.ui.ImageButton;
public class LevelDialog extends Dialog{
private int selectedMap;
public LevelDialog(){
super("Level Select");
setup();
}
void setup(){
ButtonGroup<ImageButton> mapgroup = new ButtonGroup<>();
addCloseButton();
getButtonTable().addButton("Play", ()->{
hide();
World.loadMap(selectedMap);
GameState.play();
});
for(int i = 0; i < maps.length; i ++){
content().add(maps[i]);
}
content().row();
for(int i = 0; i < maps.length; i ++){
int index = i;
ImageButton image = new ImageButton(new TextureRegion(mapTextures[i]), "togglemap");
mapgroup.add(image);
image.clicked(()->{
selectedMap = index;
});
image.getImageCell().size(150, 150);
content().add(image).size(180);
}
}
}

View File

@ -0,0 +1,40 @@
package io.anuke.mindustry.ui;
import static io.anuke.mindustry.Vars.*;
import io.anuke.ucore.scene.ui.ConfirmDialog;
import io.anuke.ucore.scene.ui.Dialog;
public class MenuDialog extends Dialog{
public MenuDialog(){
super("Paused", "dialog");
setup();
}
void setup(){
content().addButton("Back", ()->{
hide();
paused = false;
}).width(200);
content().row();
content().addButton("Settings", ()->{
ui.showPrefs();
}).width(200);
content().row();
content().addButton("Controls", ()->{
ui.showControls();
}).width(200);
content().row();
content().addButton("Back to menu", ()->{
new ConfirmDialog("Confirm", "Are you sure you want to quit?", ()->{
hide();
paused = false;
playing = false;
});
}).width(200);
}
}

View File

@ -0,0 +1,35 @@
package io.anuke.mindustry.ui;
import static io.anuke.mindustry.Vars.*;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.scene.ui.TextDialog;
public class TutorialDialog extends TextDialog{
public TutorialDialog(){
super("Tutorial", tutorialText);
setup();
}
void setup(){
setDialog();
hidden(()->{
playing = true;
paused = false;
});
getButtonTable().addButton("OK", ()->{
hide();
});
content().pad(8);
content().row();
content().addCheck("Don't show again", b->{
Settings.putBool("tutorial", !b);
Settings.save();
}).padTop(4);
}
}

View File

@ -0,0 +1,119 @@
package io.anuke.mindustry.ui;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.graphics.Color;
import io.anuke.mindustry.Inventory;
import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.ucore.core.Draw;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Table;
public class UpgradeDialog extends Dialog{
public UpgradeDialog() {
super("Upgrades");
setup();
}
void setup(){
addCloseButton();
hidden(()->{
paused = false;
});
shown(()->{
paused = true;
});
getButtonTable().addButton("Ok", ()->{
hide();
});
Table weptab = new Table();
weptab.background("button");
weptab.pad(20);
for(Weapon weapon : Weapon.values()){
TextButton button = new TextButton(weapon.name());
Image img = new Image(Draw.region("weapon-"+weapon.name()));
button.add(img).size(8*5);
button.getCells().reverse();
button.row();
button.pack();
button.update(()->{
if(weapons.get(weapon) == Boolean.TRUE){
button.setDisabled(true);
button.setColor(Color.GRAY);
button.setTouchable(Touchable.disabled);
}else{
button.setColor(Color.WHITE);
button.setDisabled(false);
}
button.setDisabled(!Inventory.hasItems(weapon.requirements));
});
weptab.add(button).width(160);
Table tiptable = new Table();
Runnable run = ()->{
tiptable.clearChildren();
String description = weapon.description;
tiptable.background("button");
tiptable.add("[PURPLE]" + weapon.name(), 0.75f).left().padBottom(2f);
if(weapons.get(weapon) != Boolean.TRUE){
ItemStack[] req = weapon.requirements;
for(ItemStack s : req){
tiptable.row();
int amount = Math.min(items.get(s.item, 0), s.amount);
tiptable.add(
(amount >= s.amount ? "[YELLOW]" : "[RED]")
+s.item + ": " + amount + " / " +s.amount, 0.5f).left();
}
}
tiptable.row();
tiptable.add().size(10);
tiptable.row();
tiptable.add("[ORANGE]" + description).left();
tiptable.row();
if(weapons.get(weapon) == Boolean.TRUE)
tiptable.add("[LIME]Purchased!").left();
tiptable.pad(10f);
};
run.run();
Tooltip tip = new Tooltip(tiptable, run);
tip.setInstant(true);
button.addListener(tip);
button.clicked(()->{
Inventory.removeItems(weapon.requirements);
weapons.put(weapon, true);
ui.updateWeapons();
run.run();
});
}
content().add("Weapons");
content().row();
content().add(weptab);
content().row();
}
}

View File

@ -36,11 +36,11 @@ public class Block{
return null;
}
protected void handleItem(Tile tile, Item item, Tile source){
public void handleItem(Tile tile, Item item, Tile source){
tile.entity.addItem(item, 1);
}
public boolean accept(Item item){
public boolean accept(Item item, Tile dest, Tile source){
return false;
}
@ -62,7 +62,7 @@ public class Block{
for(int j = 0; j < 4; j ++){
Tile other = tiles[i];
if(other != null && other.block().accept(item)
if(other != null && other.block().accept(item, other, tile)
//don't output to things facing this thing
&& !(other.block().rotate && (other.rotation + 2) % 4 == i)){
@ -98,7 +98,7 @@ public class Block{
if(todump != null && item != todump) continue;
if(tile.entity.hasItem(item) && other != null && other.block().accept(item) &&
if(tile.entity.hasItem(item) && other != null && other.block().accept(item, other, tile) &&
//don't output to things facing this thing
!(other.block().rotate && (other.rotation + 2) % 4 == i)){
other.block().handleItem(other, item, tile);
@ -119,7 +119,7 @@ public class Block{
*/
protected boolean offloadDir(Tile tile, Item item){
Tile other = tile.getNearby()[tile.rotation];
if(other != null && other.block().accept(item)){
if(other != null && other.block().accept(item, other, tile)){
other.block().handleItem(other, item, tile);
//other.entity.addCovey(item, ch == 1 ? 0.5f : ch ==2 ? 1f : 0f);
return true;

View File

@ -64,7 +64,7 @@ public class Conveyor extends Block{
}
@Override
public boolean accept(Item item){
public boolean accept(Item item, Tile dest, Tile source){
return true;
}
@ -74,7 +74,7 @@ public class Conveyor extends Block{
}
@Override
protected void handleItem(Tile tile, Item item, Tile source){
public void handleItem(Tile tile, Item item, Tile source){
int ch = Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation);
int ang = ((source.relativeTo(tile.x, tile.y) - tile.rotation));

View File

@ -40,7 +40,7 @@ public class Crafter extends Block{
}
@Override
public boolean accept(Item item){
public boolean accept(Item item, Tile dest, Tile source){
return item == Item.iron || item == Item.coal;
}
}

View File

@ -17,12 +17,12 @@ public class ProductionBlocks{
}
@Override
protected void handleItem(Tile tile, Item item, Tile source){
public void handleItem(Tile tile, Item item, Tile source){
Inventory.addItem(item, 1);
}
@Override
public boolean accept(Item item){
public boolean accept(Item item, Tile dest, Tile source){
return true;
}
},
@ -44,14 +44,14 @@ public class ProductionBlocks{
@Override
public void update(Tile tile){
if(Timers.get(tile, 10) && tile.entity.totalItems() > 0){
if(Timers.get(tile, 2) && tile.entity.totalItems() > 0){
tryDump(tile, tile.rotation++, null);
tile.rotation %= 4;
}
}
@Override
public boolean accept(Item item){
public boolean accept(Item item, Tile dest, Tile source){
return true;
}
@ -61,6 +61,37 @@ public class ProductionBlocks{
}
},
junction = new Block("junction"){
{
update = true;
solid = true;
}
@Override
public void handleItem(Tile tile, Item item, Tile source){
int dir = source.relativeTo(tile.x, tile.y);
dir = (dir+4)%4;
Tile to = tile.getNearby()[dir];
Timers.run(15, ()->{
to.block().handleItem(to, item, tile);
});
}
@Override
public boolean accept(Item item, Tile dest, Tile source){
int dir = source.relativeTo(dest.x, dest.y);
dir = (dir+4)%4;
Tile to = dest.getNearby()[dir];
return to != null && to.block() != junction && to.block().accept(item, dest, to);
}
@Override
public String description(){
return "Serves as a conveyor junction.";
}
},
smelter = new Crafter("smelter"){{
health = 70;
requirements = new Item[]{Item.coal, Item.iron};

View File

@ -64,7 +64,7 @@ public class Turret extends Block{
}
@Override
public boolean accept(Item item){
public boolean accept(Item item, Tile dest, Tile source){
return item == ammo;
}