Implemented item dragging and transferring

This commit is contained in:
Anuken
2018-04-13 23:55:53 -04:00
parent 43c9bc51dc
commit 86b7966027
15 changed files with 331 additions and 68 deletions

View File

@@ -151,6 +151,7 @@ public class Control extends Module{
upgrades.reset();
player.weaponLeft = player.weaponRight = Weapons.blaster;
player.team = Team.blue;
player.inventory.clear();
player.add();
player.heal();

View File

@@ -534,6 +534,23 @@ public class Renderer extends RendererModule{
}
}
if(control.input().isDroppingItem()){
Vector2 v = Graphics.mouseWorld();
float size = 8;
Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size);
Draw.color("accent");
Lines.circle(v.x, v.y, 6 + Mathf.absin(Timers.time(), 5f, 1f));
Draw.reset();
Tile tile = world.tileWorld(v.x, v.y);
if(tile != null) tile = tile.target();
if(tile != null && tile.block().acceptStack(player.inventory.getItem(), tile, player)){
Draw.color("place");
Lines.square(tile.drawx(), tile.drawy(), tile.block().size*tilesize/2f + 1 + Mathf.absin(Timers.time(), 5f, 1f));
Draw.color();
}
}
//TODO draw health bars
/*

View File

@@ -0,0 +1,48 @@
package io.anuke.mindustry.entities;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.resource.Item;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.TimedEntity;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
public class ItemAnimationEffect extends TimedEntity {
private static final float size = 5f;
private final Vector2 vec = new Vector2();
private final Vector2 from = new Vector2();
private final Vector2 to = new Vector2();
private final Item item;
public ItemAnimationEffect(Item item, float x, float y, float tox, float toy) {
this.x = x;
this.y = y;
this.item = item;
from.set(x, y);
to.set(tox, toy);
lifetime = 40f;
}
@Override
public void update() {
super.update();
vec.set(from).interpolate(to, fin(), Interpolation.fade);
x = vec.x;
y = vec.y;
}
@Override
public void draw() {
float s = size * Mathf.curve(fout(), 0.1f);
Draw.rect(item.region, x, y, s, s);
}
@Override
public <T extends Entity> T add() {
return super.add(Vars.effectGroup);
}
}

View File

@@ -9,6 +9,7 @@ import io.anuke.mindustry.content.fx.Fx;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.resource.Mech;
import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon;
@@ -46,6 +47,7 @@ public class Player extends Unit{
public float targetAngle = 0f;
public boolean dashing = false;
public boolean selectingItem;
public int clientid = -1;
public boolean isLocal = false;
@@ -182,6 +184,15 @@ public class Player extends Unit{
Draw.rect(weapon.name + "-equip", x + tr.x, y + tr.y, w, 8, rotation - 90);
}
float backTrns = 4f, itemSize = 5f;
if(inventory.hasItem() && !control.input().isDroppingItem()){
ItemStack stack = inventory.getItem();
Draw.rect(stack.item.region, x + Angles.trnsx(rotation + 180f, backTrns), y + Angles.trnsy(rotation + 180f, backTrns), itemSize, itemSize, rotation);
//Draw.tint(Color.WHITE);
//Lines.circle(x + Angles.trnsx(rotation + 180f, backTrns), y + Angles.trnsy(rotation + 180f, backTrns), 3f + Mathf.absin(Timers.time(), 3f, 0.8f));
//Draw.tint(Color.WHITE);
}
Draw.alpha(1f);
x = px;
@@ -239,8 +250,7 @@ public class Player extends Unit{
movement.y += ya*speed;
movement.x += xa*speed;
boolean shooting = !Inputs.keyDown("dash") && Inputs.keyDown("shoot") && control.input().recipe == null
&& !ui.hasMouse() && !control.input().onConfigurable();
boolean shooting = control.input().canShoot() && control.input().isShooting();
if(shooting){
weaponLeft.update(player, true);

View File

@@ -3,14 +3,51 @@ package io.anuke.mindustry.entities;
import io.anuke.mindustry.resource.*;
public class UnitInventory {
public final AmmoEntry ammo = new AmmoEntry(AmmoType.getByID(0), 0);
public final ItemStack item = new ItemStack(Item.getByID(0), 0);
public final LiquidStack liquid = new LiquidStack(Liquid.getByID(0), 0);
public float power = 0f;
private final AmmoEntry ammo = new AmmoEntry(AmmoType.getByID(0), 0);
private CarryItem item;
public void clear(){
item = null;
}
public boolean hasAnything(){
return item != null;
}
public boolean hasLiquid(){
return item instanceof LiquidStack;
}
public boolean hasItem(){
return item instanceof ItemStack;
}
public void addItem(Item item, int amount){
if(this.item.item != item) this.item.amount = 0;
this.item.item = item;
this.item.amount += amount;
if(hasItem()){
getItem().amount = getItem().item == item ? getItem().amount + amount : amount;
getItem().item = item;
}else{
this.item = new ItemStack(item, amount);
}
}
public void addLiquid(Liquid liquid, float amount){
if(hasItem()){
getLiquid().liquid = liquid;
getLiquid().amount = amount;
}else{
this.item = new LiquidStack(liquid, amount);
}
}
public ItemStack getItem(){
if(!hasItem()) throw new RuntimeException("This inventory has no item! Check hasItem() first.");
return (ItemStack)item;
}
public LiquidStack getLiquid(){
if(!hasItem()) throw new RuntimeException("This inventory has no item! Check hasItem() first.");
return (LiquidStack)item;
}
}

View File

@@ -41,6 +41,20 @@ public class DesktopInput extends InputHandler{
breakMode.released(getBlockX(), getBlockY(), getBlockEndX(), getBlockEndY());
}
if(!Inputs.keyDown("select")){
shooting = false;
}
boolean canBeginShoot = Inputs.keyTap("select") && canShoot();
if(Inputs.keyTap("select") && recipe == null && player.inventory.hasAnything()){
Vector2 vec = Graphics.screen(player.x, player.y);
if(vec.dst(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY()) <= playerSelectRange){
canBeginShoot = false;
droppingItem = true;
}
}
if((Inputs.keyTap("select") && recipe != null) || Inputs.keyTap("break")){
Vector2 vec = Graphics.world(Gdx.input.getX(), Gdx.input.getY());
mousex = vec.x;
@@ -98,9 +112,18 @@ public class DesktopInput extends InputHandler{
Tile target = cursor == null ? null : cursor.target();
boolean showCursor = false;
if(droppingItem && Inputs.keyRelease("select") && player.inventory.hasAnything() && target != null){
dropItem(target, player.inventory.getItem());
}
if(droppingItem && (!Inputs.keyDown("select") || !player.inventory.hasAnything())){
droppingItem = false;
}
if(recipe == null && target != null && !ui.hasMouse() && Inputs.keyDown("block_info") && target.block().isAccessible()){
showCursor = true;
if(Inputs.keyTap("select")){
canBeginShoot = false;
ui.blockinvfrag.showFor(target);
Cursors.restoreCursor();
}
@@ -117,11 +140,15 @@ public class DesktopInput extends InputHandler{
if(target != null && Inputs.keyTap("select") && !ui.hasMouse()){
if(target.block().isConfigurable(target)){
if((!ui.configfrag.isShown()
|| ui.configfrag.getSelectedTile().block().onConfigureTileTapped(ui.configfrag.getSelectedTile(), cursor)))
|| ui.configfrag.getSelectedTile().block().onConfigureTileTapped(ui.configfrag.getSelectedTile(), cursor))) {
ui.configfrag.showConfig(target);
canBeginShoot = false;
}
}else if(!ui.configfrag.hasConfigMouse()){
if(ui.configfrag.isShown() && ui.configfrag.getSelectedTile().block().onConfigureTileTapped(ui.configfrag.getSelectedTile(), cursor))
if(ui.configfrag.isShown() && ui.configfrag.getSelectedTile().block().onConfigureTileTapped(ui.configfrag.getSelectedTile(), cursor)) {
ui.configfrag.hideConfig();
canBeginShoot = false;
}
}
target.block().tapped(target);
@@ -156,6 +183,10 @@ public class DesktopInput extends InputHandler{
showCursor = validPlace(tilex(), tiley(), control.input().recipe.result) && control.input().cursorNear();
}
if(canBeginShoot){
shooting = true;
}
if(!ui.hasMouse()) {
if (showCursor)
Cursors.setHand();

View File

@@ -3,6 +3,8 @@ package io.anuke.mindustry.input;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.entities.ItemAnimationEffect;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.ItemStack;
@@ -10,8 +12,10 @@ import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Placement;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
@@ -24,6 +28,9 @@ public abstract class InputHandler extends InputAdapter{
public PlaceMode breakMode = android ? PlaceMode.none : PlaceMode.holdDelete;
public PlaceMode lastPlaceMode = placeMode;
public PlaceMode lastBreakMode = breakMode;
public boolean droppingItem;
public boolean shooting;
public float playerSelectRange = Unit.dp.scl(60f);
public abstract void update();
public abstract float getCursorX();
@@ -35,12 +42,43 @@ public abstract class InputHandler extends InputAdapter{
public int getBlockEndX(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).x, tilesize, round2()); }
public int getBlockEndY(){ return Mathf.sclb(Graphics.world(getCursorEndX(), getCursorEndY()).y, tilesize, round2()); }
public void resetCursor(){}
public boolean canShoot(){
return recipe == null && !ui.hasMouse() && !onConfigurable() && !isDroppingItem();
}
public boolean isShooting(){
return shooting;
}
public boolean drawPlace(){ return true; }
public boolean onConfigurable(){
Tile tile = world.tile(getBlockX(), getBlockY());
return tile != null && (tile.block().isConfigurable(tile) || (tile.isLinked() && tile.getLinked().block().isConfigurable(tile)));
}
public boolean isDroppingItem(){
return droppingItem;
}
public void dropItem(Tile tile, ItemStack stack){
if(tile.block().acceptStack(stack, tile, player)){
tile.block().handleStack(stack, tile, player);
player.inventory.clear();
float backTrns = 3f;
int sent = Mathf.clamp(stack.amount/3, 1, 8);
for(int i = 0; i < sent; i ++){
Timers.run(i * 3, () -> {
new ItemAnimationEffect(stack.item,
player.x + Angles.trnsx(rotation + 180f, backTrns), player.y + Angles.trnsy(rotation + 180f, backTrns),
tile.drawx(), tile.drawy()).add();
});
}
}
}
public boolean cursorNear(){
return Vector2.dst(player.x, player.y, getBlockX() * tilesize, getBlockY() * tilesize) <= placerange || debug;

View File

@@ -0,0 +1,4 @@
package io.anuke.mindustry.resource;
public interface CarryItem {
}

View File

@@ -1,6 +1,6 @@
package io.anuke.mindustry.resource;
public class ItemStack{
public class ItemStack implements CarryItem{
public Item item;
public int amount;

View File

@@ -1,6 +1,6 @@
package io.anuke.mindustry.resource;
public class LiquidStack {
public class LiquidStack implements CarryItem{
public Liquid liquid;
public float amount;

View File

@@ -0,0 +1,38 @@
package io.anuke.mindustry.ui;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import io.anuke.ucore.function.Supplier;
import io.anuke.ucore.scene.style.TextureRegionDrawable;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table;
public class ItemImage extends Stack {
private Image image;
public ItemImage(TextureRegion region, Supplier<String> text, Color color) {
Table t = new Table();
t.left().bottom();
t.label(text).color(Color.DARK_GRAY);
t.row();
t.label(text).padTop(-22);
image = new Image(region);
image.setColor(color);
add(image);
add(t);
}
public ItemImage updateColor(Supplier<Color> c){
image.update(() -> image.setColor(c.get()));
return this;
}
public ItemImage updateRegion(Supplier<TextureRegion> c){
image.update(() -> image.setDrawable(new TextureRegionDrawable(c.get())));
return this;
}
}

View File

@@ -2,22 +2,26 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Colors;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.content.Liquids;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.ui.ItemImage;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.function.Callable;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.actions.Actions;
import io.anuke.ucore.scene.event.HandCursorListener;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Strings;
import static io.anuke.mindustry.Vars.player;
@@ -72,43 +76,32 @@ public class BlockInventoryFragment implements Fragment {
int cols = 3;
int row = 0;
//table.label(() -> "[accent]"+tile.entity.inventory.totalItems() +"/"+ tile.block().itemCapacity).colspan(cols);
//table.row();
table.margin(3f);
table.defaults().size(16 * 2).space(6f);
if(tile.block().hasPower){
Table t = new Table();
t.left().bottom();
t.label(() -> round(tile.entity.power.amount)).color(Color.DARK_GRAY);
t.row();
t.label(() -> round(tile.entity.power.amount)).padTop(-22);
Image image = new Image("icon-power");
image.setColor(Colors.get("power"));
Stack stack = new Stack();
stack.add(image);
stack.add(t);
table.add(stack).size(16 * 2).space(6f);
table.add(new ItemImage(Draw.region("icon-power"), () -> round(tile.entity.power.amount), Colors.get("power")));
if (row++ % cols == cols - 1) table.row();
}
if(tile.block().hasLiquids){
Table t = new Table();
t.left().bottom();
t.label(() -> round(tile.entity.liquid.amount)).color(Color.DARK_GRAY);
t.row();
t.label(() -> round(tile.entity.liquid.amount)).padTop(-22);
ItemImage image = new ItemImage(Draw.region("icon-liquid"),
() -> round(tile.entity.liquid.amount),
tile.entity.liquid.liquid == Liquids.none ? Color.GRAY : tile.entity.liquid.liquid.color);
Image image = new Image("icon-liquid");
image.setColor(tile.entity.liquid.liquid == Liquids.none ? Color.GRAY : tile.entity.liquid.liquid.color);
image.addListener(new HandCursorListener());
image.tapped(() -> {
if (tile.entity.liquid.amount > 0) {
/*
int amount = Inputs.keyDown("item_withdraw") ? items[f] : 1;
items[f] -= amount;
Stack stack = new Stack();
stack.add(image);
stack.add(t);
table.add(stack).size(16 * 2).space(6f);
move(item.region, image, () -> player.inventory.addItem(item, amount), Color.WHITE);*/
}
});
table.add(image);
if (row++ % cols == cols - 1) table.row();
}
@@ -129,37 +122,17 @@ public class BlockInventoryFragment implements Fragment {
t.row();
t.label(() -> round(items[f])).padTop(-22);
Stack stack = new Stack();
stack.add(new Image(item.region));
stack.add(t);
table.add(stack).size(16 * 2).space(6f);
stack.addListener(new HandCursorListener());
stack.tapped(() -> {
ItemImage image = new ItemImage(item.region, () -> round(items[f]), Color.WHITE);
image.addListener(new HandCursorListener());
image.tapped(() -> {
if (items[f] > 0) {
int amount = Inputs.keyDown("item_withdraw") ? items[f] : 1;
items[f] -= amount;
Vector2 v = stack.localToStageCoordinates(new Vector2(stack.getWidth() / 2f, stack.getHeight() / 2f));
Vector2 tv = Graphics.screen(player.x, player.y);
float tx = tv.x, ty = tv.y;
float dur = 40f / 60f;
Image image = new Image(item.region);
image.setSize(32f, 32f);
image.setOrigin(Align.center);
image.setPosition(v.x, v.y, Align.center);
image.setTouchable(Touchable.disabled);
image.actions(
Actions.parallel(
Actions.moveToAligned(tx, ty, Align.center, dur, Interpolation.fade),
Actions.scaleTo(0.1f, 0.1f, dur, Interpolation.fade)
),
Actions.call(() -> player.inventory.addItem(item, amount)),
Actions.removeActor()
);
Core.scene.add(image);
move(item.region, image, () -> player.inventory.addItem(item, amount), Color.WHITE);
}
});
table.add(image);
if (row++ % cols == cols - 1) table.row();
}
@@ -172,7 +145,32 @@ public class BlockInventoryFragment implements Fragment {
updateTablePosition();
}
String round(float f){
private void move(TextureRegion region, ItemImage image, Callable c, Color color){
Vector2 v = image.localToStageCoordinates(new Vector2(image.getWidth() / 2f, image.getHeight() / 2f));
Vector2 tv = Graphics.screen(player.x + Angles.trnsx(player.rotation + 180f, 5f), player.y + Angles.trnsy(player.rotation + 180f, 5f));
float tx = tv.x, ty = tv.y;
float dur = 40f / 60f;
Image mover = new Image(region);
mover.setColor(color);
mover.setSize(32f, 32f);
mover.setOrigin(Align.center);
mover.setPosition(v.x, v.y, Align.center);
mover.setTouchable(Touchable.disabled);
mover.actions(
Actions.parallel(
Actions.moveToAligned(tx, ty, Align.center, dur, Interpolation.fade),
Actions.scaleTo(0.7f, 0.7f, dur, Interpolation.fade),
Actions.rotateTo(player.rotation, dur, Interpolation.fade)
),
Actions.call(c),
Actions.removeActor()
);
Core.scene.add(mover);
}
private String round(float f){
f = (int)f;
if(f >= 1000){
return Strings.toFixed(f/1000, 1) + "k";

View File

@@ -1,9 +1,39 @@
package io.anuke.mindustry.ui.fragments;
import io.anuke.ucore.util.Strings;
public class PlayerMenuFragment implements Fragment {
@Override
public void build() {
/*
new table(){{
new table("clear"){{
ItemImage item = new ItemImage(player.inventory.item.item.region, () -> round(player.inventory.item.amount), Color.WHITE)
.updateRegion(() -> player.inventory.item.item.region);
ItemImage liquid = new ItemImage(Draw.region("icon-liquid"), () -> round(player.inventory.liquid.amount), Color.WHITE)
.updateColor(() -> player.inventory.liquid.liquid == Liquids.none ? Color.GRAY : player.inventory.liquid.liquid.color);
ItemImage power = new ItemImage(Draw.region("icon-power"), () -> round(player.inventory.power), Colors.get("power"));
defaults().size(16 * 2).space(6f);
add(item);
add(liquid);
add(power);
visible(() -> Inputs.keyDown("player_list"));
padTop(100);
margin(5);
}}.end();
}}.end();*/
}
public String round(float f){
f = (int)f;
if(f >= 1000){
return Strings.toFixed(f/1000, 1) + "k";
}else{
return (int)f+"";
}
}
}

View File

@@ -1,7 +1,9 @@
package io.anuke.mindustry.world;
import com.badlogic.gdx.math.GridPoint2;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.resource.Liquid;
import io.anuke.ucore.util.Mathf;
@@ -15,6 +17,15 @@ public abstract class BaseBlock {
public float liquidFlowFactor = 4.9f;
public float powerCapacity = 10f;
public boolean acceptStack(ItemStack item, Tile tile, Unit source){
return acceptItem(item.item, tile, tile) && hasInventory && source.team == tile.getTeam()
&& tile.entity.inventory.totalItems() + item.amount <= itemCapacity;
}
public void handleStack(ItemStack item, Tile tile, Unit source){
tile.entity.inventory.addItem(item.item, item.amount);
}
public void handleItem(Item item, Tile tile, Tile source){
tile.entity.inventory.addItem(item, 1);
}