Implemented local multiplayer fully

This commit is contained in:
Anuken
2018-05-13 20:48:44 -07:00
parent d1a3752b2d
commit ca24e64c42
14 changed files with 161 additions and 49 deletions

View File

@ -23,6 +23,7 @@ text.level.mode=Gamemode:
text.savegame=Save Game text.savegame=Save Game
text.loadgame=Load Game text.loadgame=Load Game
text.joingame=Join Game text.joingame=Join Game
text.addplayers=Add/Remove Players
text.newgame=New Game text.newgame=New Game
text.quit=Quit text.quit=Quit
text.about.button=About text.about.button=About

View File

@ -166,9 +166,11 @@ public class Control extends Module{
InputHandler[] oldi = inputs; InputHandler[] oldi = inputs;
inputs = new InputHandler[index + 1]; inputs = new InputHandler[index + 1];
System.arraycopy(old, 0, inputs, 0, oldi.length); System.arraycopy(oldi, 0, inputs, 0, oldi.length);
} }
Player setTo = (index == 0 ? null : players[0]);
Player player = new Player(); Player player = new Player();
player.name = Settings.getString("name"); player.name = Settings.getString("name");
player.mech = mobile ? Mechs.standardShip : Mechs.standard; player.mech = mobile ? Mechs.standardShip : Mechs.standard;
@ -177,6 +179,14 @@ public class Control extends Module{
player.playerIndex = index; player.playerIndex = index;
players[index] = player; players[index] = player;
if(setTo != null){
player.set(setTo.x, setTo.y);
}
if(!state.is(State.menu)){
player.add();
}
InputHandler input; InputHandler input;
if(mobile){ if(mobile){
@ -189,6 +199,19 @@ public class Control extends Module{
Inputs.addProcessor(input); Inputs.addProcessor(input);
} }
public void removePlayer(){
players[players.length-1].remove();
inputs[inputs.length-1].remove();
Player[] old = players;
players = new Player[players.length - 1];
System.arraycopy(old, 0, players, 0, players.length);
InputHandler[] oldi = inputs;
inputs = new InputHandler[inputs.length - 1];
System.arraycopy(oldi, 0, inputs, 0, inputs.length);
}
public Input gdxInput(){ public Input gdxInput(){
return gdxInput; return gdxInput;
} }

View File

@ -11,7 +11,6 @@ import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.gen.CallEvent;
import io.anuke.mindustry.io.Platform; import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.io.Version; import io.anuke.mindustry.io.Version;
import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.*;

View File

@ -52,6 +52,7 @@ public class UI extends SceneModule{
public AdminsDialog admins; public AdminsDialog admins;
public TraceDialog traces; public TraceDialog traces;
public ChangelogDialog changelog; public ChangelogDialog changelog;
public LocalPlayerDialog localplayers;
public final MenuFragment menufrag = new MenuFragment(); public final MenuFragment menufrag = new MenuFragment();
public final HudFragment hudfrag = new HudFragment(); public final HudFragment hudfrag = new HudFragment();
@ -171,6 +172,7 @@ public class UI extends SceneModule{
bans = new BansDialog(); bans = new BansDialog();
admins = new AdminsDialog(); admins = new AdminsDialog();
traces = new TraceDialog(); traces = new TraceDialog();
localplayers = new LocalPlayerDialog();
build.begin(scene); build.begin(scene);

View File

@ -279,8 +279,10 @@ public class Player extends Unit{
movement.set(0, 0); movement.set(0, 0);
float xa = Inputs.getAxis("move_x"); String section = "player_"+(playerIndex + 1);
float ya = Inputs.getAxis("move_y");
float xa = Inputs.getAxis(section, "move_x");
float ya = Inputs.getAxis(section, "move_y");
if(Math.abs(xa) < 0.3) xa = 0; if(Math.abs(xa) < 0.3) xa = 0;
if(Math.abs(ya) < 0.3) ya = 0; if(Math.abs(ya) < 0.3) ya = 0;
@ -310,7 +312,7 @@ public class Player extends Unit{
rotation = Mathf.slerpDelta(rotation, movement.angle(), 0.13f); rotation = Mathf.slerpDelta(rotation, movement.angle(), 0.13f);
} }
}else{ }else{
float angle = Angles.mouseAngle(x, y); float angle = control.input(playerIndex).mouseAngle(x, y);
this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f); this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f);
} }
} }

View File

@ -74,7 +74,8 @@ public class OverlayRenderer {
//draw selected block bars and info //draw selected block bars and info
if (input.recipe == null && !ui.hasMouse() && !input.frag.config.isShown()) { if (input.recipe == null && !ui.hasMouse() && !input.frag.config.isShown()) {
Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y); Vector2 vec = Graphics.world(input.getMouseX(), input.getMouseY());
Tile tile = world.tileWorld(vec.x, vec.y);
if (tile != null && tile.block() != Blocks.air) { if (tile != null && tile.block() != Blocks.air) {
Tile target = tile; Tile target = tile;
@ -134,7 +135,7 @@ public class OverlayRenderer {
} }
if (input.isDroppingItem()) { if (input.isDroppingItem()) {
Vector2 v = Graphics.mouseWorld(); Vector2 v = Graphics.world(input.getMouseX(), input.getMouseY());
float size = 8; float size = 8;
Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size); Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size);
Draw.color("accent"); Draw.color("accent");

View File

@ -16,7 +16,7 @@ public class DefaultKeybinds {
for(String section : sections) { for(String section : sections) {
KeyBinds.defaultSection(section, DeviceType.keyboard, KeyBinds.defaultSection(section, DeviceType.keyboard,
new Category("General"), new Category("General"),
"move_x", new Axis(Input.A, Input.D), "move_x", new Axis(Input.A, Input.D),
"move_y", new Axis(Input.S, Input.W), "move_y", new Axis(Input.S, Input.W),
"select", Input.MOUSE_LEFT, "select", Input.MOUSE_LEFT,
@ -44,6 +44,7 @@ public class DefaultKeybinds {
); );
KeyBinds.defaultSection(section, DeviceType.controller, KeyBinds.defaultSection(section, DeviceType.controller,
new Category("General"),
"move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS), "move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS),
"move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS), "move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS),
"cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS), "cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS),
@ -51,13 +52,15 @@ public class DefaultKeybinds {
"select", Input.CONTROLLER_R_BUMPER, "select", Input.CONTROLLER_R_BUMPER,
"break", Input.CONTROLLER_L_BUMPER, "break", Input.CONTROLLER_L_BUMPER,
"shoot", Input.CONTROLLER_R_TRIGGER, "shoot", Input.CONTROLLER_R_TRIGGER,
"dash", Input.CONTROLLER_Y,
"rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT),
"rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B),
new Category("View"),
"zoom_hold", Input.ANY_KEY, "zoom_hold", Input.ANY_KEY,
"zoom", new Axis(Input.CONTROLLER_DPAD_DOWN, Input.CONTROLLER_DPAD_UP), "zoom", new Axis(Input.CONTROLLER_DPAD_DOWN, Input.CONTROLLER_DPAD_UP),
"menu", Input.CONTROLLER_X, "menu", Input.CONTROLLER_X,
"pause", Input.CONTROLLER_L_TRIGGER, "pause", Input.CONTROLLER_L_TRIGGER,
"dash", Input.CONTROLLER_Y, new Category("Multiplayer"),
"rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT),
"rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B),
"player_list", Input.CONTROLLER_START "player_list", Input.CONTROLLER_START
); );

View File

@ -62,25 +62,26 @@ public class DesktopInput extends InputHandler{
if(Inputs.keyTap(section, "select") && recipe == null && player.inventory.hasItem()){ if(Inputs.keyTap(section, "select") && recipe == null && player.inventory.hasItem()){
Vector2 vec = Graphics.screen(player.x, player.y); Vector2 vec = Graphics.screen(player.x, player.y);
if(vec.dst(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY()) <= playerSelectRange){ if(vec.dst(getMouseX(), Gdx.graphics.getHeight() - getMouseY()) <= playerSelectRange){
canBeginShoot = false; canBeginShoot = false;
droppingItem = true; droppingItem = true;
} }
} }
if((Inputs.keyTap(section, "select") && recipe != null) || Inputs.keyTap(section, "break")){ if((Inputs.keyTap(section, "select") && recipe != null) || Inputs.keyTap(section, "break")){
Vector2 vec = Graphics.world(Gdx.input.getX(), Gdx.input.getY()); Vector2 vec = Graphics.world(getMouseX(), getMouseY());
mousex = vec.x; mousex = vec.x;
mousey = vec.y; mousey = vec.y;
} }
if(!Inputs.keyDown(section, "select") && !Inputs.keyDown(section, "break")){ if(!Inputs.keyDown(section, "select") && !Inputs.keyDown(section, "break")){
mousex = Graphics.mouseWorld().x; Vector2 vec = Graphics.world(getMouseX(), getMouseY());
mousey = Graphics.mouseWorld().y; mousex = vec.x;
mousey = vec.y;
} }
endx = Gdx.input.getX(); endx = getMouseX();
endy = Gdx.input.getY(); endy = getMouseY();
boolean controller = KeyBinds.getSection(section).device.type == DeviceType.controller; boolean controller = KeyBinds.getSection(section).device.type == DeviceType.controller;
@ -229,11 +230,11 @@ public class DesktopInput extends InputHandler{
} }
if(Inputs.keyTap(section,"select")){ if(Inputs.keyTap(section,"select")){
Inputs.getProcessor().touchDown(Gdx.input.getX(), Gdx.input.getY(), player.playerIndex, Buttons.LEFT); Inputs.getProcessor().touchDown((int)getMouseX(), (int)getMouseY(), player.playerIndex, Buttons.LEFT);
} }
if(Inputs.keyRelease(section,"select")){ if(Inputs.keyRelease(section,"select")){
Inputs.getProcessor().touchUp(Gdx.input.getX(), Gdx.input.getY(), player.playerIndex, Buttons.LEFT); Inputs.getProcessor().touchUp((int)getMouseX(), (int)getMouseY(), player.playerIndex, Buttons.LEFT);
} }
float xa = Inputs.getAxis(section, "cursor_x"); float xa = Inputs.getAxis(section, "cursor_x");
@ -245,9 +246,11 @@ public class DesktopInput extends InputHandler{
controly -= ya*baseControllerSpeed*scl; controly -= ya*baseControllerSpeed*scl;
controlling = true; controlling = true;
Gdx.input.setCursorCatched(true); if(index == 0){
Gdx.input.setCursorCatched(true);
}
Inputs.getProcessor().touchDragged(Gdx.input.getX(), Gdx.input.getY(), player.playerIndex); Inputs.getProcessor().touchDragged((int)getMouseX(), (int)getMouseY(), player.playerIndex);
} }
controlx = Mathf.clamp(controlx, 0, Gdx.graphics.getWidth()); controlx = Mathf.clamp(controlx, 0, Gdx.graphics.getWidth());
@ -266,17 +269,12 @@ public class DesktopInput extends InputHandler{
public int tilex(){ public int tilex(){
return (recipe != null && recipe.result.isMultiblock() && return (recipe != null && recipe.result.isMultiblock() &&
recipe.result.size % 2 == 0) ? recipe.result.size % 2 == 0) ?
Mathf.scl(Graphics.mouseWorld().x, tilesize) : Mathf.scl2(Graphics.mouseWorld().x, tilesize); Mathf.scl(Graphics.world(getMouseX(), getMouseY()).x, tilesize) : Mathf.scl2(Graphics.world(getMouseX(), getMouseY()).x, tilesize);
} }
public int tiley(){ public int tiley(){
return (recipe != null && recipe.result.isMultiblock() && return (recipe != null && recipe.result.isMultiblock() &&
recipe.result.size % 2 == 0) ? recipe.result.size % 2 == 0) ?
Mathf.scl(Graphics.mouseWorld().y, tilesize) : Mathf.scl2(Graphics.mouseWorld().y, tilesize); Mathf.scl(Graphics.world(getMouseX(), getMouseY()).y, tilesize) : Mathf.scl2(Graphics.world(getMouseX(), getMouseY()).y, tilesize);
}
@Override
public boolean keyDown(int keycode) {
return super.keyDown(keycode);
} }
} }

View File

@ -60,6 +60,10 @@ public abstract class InputHandler extends InputAdapter{
public void resetCursor(){} public void resetCursor(){}
public boolean isCursorVisible(){ return false; } public boolean isCursorVisible(){ return false; }
public float mouseAngle(float x, float y){
return Graphics.world(getMouseX(), getMouseY()).sub(x, y).angle();
}
public void remove(){ public void remove(){
Inputs.removeProcessor(this); Inputs.removeProcessor(this);
frag.remove(); frag.remove();

View File

@ -52,7 +52,8 @@ public class Weapon extends Upgrade{
p.timer.reset(t2, reload/2f); p.timer.reset(t2, reload/2f);
} }
tr.set(Graphics.mouseWorld()).sub(p.x, p.y); tr.set(Graphics.world(Vars.control.input(p.playerIndex).getMouseX(),
Vars.control.input(p.playerIndex).getMouseY())).sub(p.x, p.y);
if(tr.len() < minPlayerDist) tr.setLength(minPlayerDist); if(tr.len() < minPlayerDist) tr.setLength(minPlayerDist);
float cx = tr.x + p.x, cy = tr.y + p.y; float cx = tr.x + p.x, cy = tr.y + p.y;

View File

@ -0,0 +1,59 @@
package io.anuke.mindustry.ui.dialogs;
import com.badlogic.gdx.utils.Scaling;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.entities.Player;
import io.anuke.ucore.graphics.Draw;
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 LocalPlayerDialog extends FloatingDialog{
public LocalPlayerDialog() {
super("$text.addplayers");
addCloseButton();
shown(this::rebuild);
}
private void rebuild(){
float size = 140f;
content().clear();
if(players.length > 1) {
content().addImageButton("icon-cancel", 14 * 2, () -> {
control.removePlayer();
rebuild();
}).size(50f, size).pad(5).bottom();
}else{
content().add().size(50f, size);
}
for(Player player : players){
Table table = new Table();
Stack stack = new Stack();
stack.add(new Image("button"));
Image img = new Image(Draw.region("icon-chat"));
img.setScaling(Scaling.fill);
stack.add(img);
table.add("Player " + (player.playerIndex + 1)).update(label -> label.setColor(player.color));
table.row();
table.add(stack).size(size);
content().add(table).pad(5);
}
if(players.length < 4) {
content().addImageButton("icon-add", 14 * 2, () -> {
control.addPlayer(players.length);
rebuild();
}).size(50f, size).pad(5).bottom();
}
}
}

View File

@ -54,6 +54,11 @@ public class PausedDialog extends FloatingDialog{
load.show(); load.show();
}).disabled(b -> Net.active()); }).disabled(b -> Net.active());
content().row();
content().addButton("$text.addplayers", () -> {
ui.localplayers.show();
}).disabled(b -> Net.active());
content().row(); content().row();
if(!gwt) { if(!gwt) {

View File

@ -14,12 +14,11 @@ import io.anuke.ucore.scene.actions.Actions;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
public class BlockConfigFragment implements Fragment { public class BlockConfigFragment implements Fragment {
private Table table; private Table table = new Table();
private Tile configTile; private Tile configTile;
@Override @Override
public void build(Group parent) { public void build(Group parent) {
table = new Table();
parent.addChild(table); parent.addChild(table);
} }

View File

@ -8,6 +8,7 @@ import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.content.Recipes; import io.anuke.mindustry.content.Recipes;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.resource.Item; import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.ItemStack;
@ -161,30 +162,44 @@ public class BlocksFragment implements Fragment{
} }
}); });
image.clicked(() -> { image.addListener(new ClickListener(){
// note: input.recipe only gets set here during a click. @Override
// during a hover only the visual description will be updated. public void clicked(InputEvent event, float x, float y){
boolean nothingSelectedYet = input.recipe == null; // note: input.recipe only gets set here during a click.
boolean selectedSomethingElse = !nothingSelectedYet && input.recipe != r; // during a hover only the visual description will be updated.
boolean shouldMakeSelection = nothingSelectedYet || selectedSomethingElse; InputHandler handler = mobile ? input : control.input(event.getPointer());
if (shouldMakeSelection) {
input.recipe = r; boolean nothingSelectedYet = handler.recipe == null;
hoveredDescriptionRecipe = r; boolean selectedSomethingElse = !nothingSelectedYet && handler.recipe != r;
updateRecipe(r); boolean shouldMakeSelection = nothingSelectedYet || selectedSomethingElse;
} else { if (shouldMakeSelection) {
input.recipe = null; handler.recipe = r;
hoveredDescriptionRecipe = null; hoveredDescriptionRecipe = r;
updateRecipe(null); updateRecipe(r);
} } else {
}); handler.recipe = null;
hoveredDescriptionRecipe = null;
updateRecipe(null);
}
}
});
table.add(image).size(size + 8); table.add(image).size(size + 8);
image.update(() -> { image.update(() -> {
boolean has = (state.inventory.hasItems(r.requirements)); boolean has = (state.inventory.hasItems(r.requirements));
image.setChecked(input.recipe == r);
image.setTouchable(Touchable.enabled); image.setTouchable(Touchable.enabled);
for(Element e : istack.getChildren()) e.setColor(has ? Color.WHITE : Hue.lightness(0.33f)); for(Element e : istack.getChildren()){
e.setColor(has ? Color.WHITE : Hue.lightness(0.33f));
}
for(Player player : players){
if(control.input(player.playerIndex).recipe == r){
image.setChecked(true);
return;
}
}
image.setChecked(false);
}); });
if (i % rows == rows - 1) if (i % rows == rows - 1)