mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-08 23:07:33 +07:00
Implemented local multiplayer fully
This commit is contained in:
@ -23,6 +23,7 @@ text.level.mode=Gamemode:
|
||||
text.savegame=Save Game
|
||||
text.loadgame=Load Game
|
||||
text.joingame=Join Game
|
||||
text.addplayers=Add/Remove Players
|
||||
text.newgame=New Game
|
||||
text.quit=Quit
|
||||
text.about.button=About
|
||||
|
@ -166,9 +166,11 @@ public class Control extends Module{
|
||||
|
||||
InputHandler[] oldi = inputs;
|
||||
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.name = Settings.getString("name");
|
||||
player.mech = mobile ? Mechs.standardShip : Mechs.standard;
|
||||
@ -177,6 +179,14 @@ public class Control extends Module{
|
||||
player.playerIndex = index;
|
||||
players[index] = player;
|
||||
|
||||
if(setTo != null){
|
||||
player.set(setTo.x, setTo.y);
|
||||
}
|
||||
|
||||
if(!state.is(State.menu)){
|
||||
player.add();
|
||||
}
|
||||
|
||||
InputHandler input;
|
||||
|
||||
if(mobile){
|
||||
@ -189,6 +199,19 @@ public class Control extends Module{
|
||||
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(){
|
||||
return gdxInput;
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.BulletType;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.SyncEntity;
|
||||
import io.anuke.mindustry.gen.CallEvent;
|
||||
import io.anuke.mindustry.io.Platform;
|
||||
import io.anuke.mindustry.io.Version;
|
||||
import io.anuke.mindustry.net.*;
|
||||
|
@ -52,6 +52,7 @@ public class UI extends SceneModule{
|
||||
public AdminsDialog admins;
|
||||
public TraceDialog traces;
|
||||
public ChangelogDialog changelog;
|
||||
public LocalPlayerDialog localplayers;
|
||||
|
||||
public final MenuFragment menufrag = new MenuFragment();
|
||||
public final HudFragment hudfrag = new HudFragment();
|
||||
@ -171,6 +172,7 @@ public class UI extends SceneModule{
|
||||
bans = new BansDialog();
|
||||
admins = new AdminsDialog();
|
||||
traces = new TraceDialog();
|
||||
localplayers = new LocalPlayerDialog();
|
||||
|
||||
build.begin(scene);
|
||||
|
||||
|
@ -279,8 +279,10 @@ public class Player extends Unit{
|
||||
|
||||
movement.set(0, 0);
|
||||
|
||||
float xa = Inputs.getAxis("move_x");
|
||||
float ya = Inputs.getAxis("move_y");
|
||||
String section = "player_"+(playerIndex + 1);
|
||||
|
||||
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(ya) < 0.3) ya = 0;
|
||||
|
||||
@ -310,7 +312,7 @@ public class Player extends Unit{
|
||||
rotation = Mathf.slerpDelta(rotation, movement.angle(), 0.13f);
|
||||
}
|
||||
}else{
|
||||
float angle = Angles.mouseAngle(x, y);
|
||||
float angle = control.input(playerIndex).mouseAngle(x, y);
|
||||
this.rotation = Mathf.slerpDelta(this.rotation, angle, 0.1f);
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,8 @@ public class OverlayRenderer {
|
||||
|
||||
//draw selected block bars and info
|
||||
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) {
|
||||
Tile target = tile;
|
||||
@ -134,7 +135,7 @@ public class OverlayRenderer {
|
||||
}
|
||||
|
||||
if (input.isDroppingItem()) {
|
||||
Vector2 v = Graphics.mouseWorld();
|
||||
Vector2 v = Graphics.world(input.getMouseX(), input.getMouseY());
|
||||
float size = 8;
|
||||
Draw.rect(player.inventory.getItem().item.region, v.x, v.y, size, size);
|
||||
Draw.color("accent");
|
||||
|
@ -16,7 +16,7 @@ public class DefaultKeybinds {
|
||||
for(String section : sections) {
|
||||
|
||||
KeyBinds.defaultSection(section, DeviceType.keyboard,
|
||||
new Category("General"),
|
||||
new Category("General"),
|
||||
"move_x", new Axis(Input.A, Input.D),
|
||||
"move_y", new Axis(Input.S, Input.W),
|
||||
"select", Input.MOUSE_LEFT,
|
||||
@ -44,6 +44,7 @@ public class DefaultKeybinds {
|
||||
);
|
||||
|
||||
KeyBinds.defaultSection(section, DeviceType.controller,
|
||||
new Category("General"),
|
||||
"move_x", new Axis(Input.CONTROLLER_L_STICK_HORIZONTAL_AXIS),
|
||||
"move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS),
|
||||
"cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS),
|
||||
@ -51,13 +52,15 @@ public class DefaultKeybinds {
|
||||
"select", Input.CONTROLLER_R_BUMPER,
|
||||
"break", Input.CONTROLLER_L_BUMPER,
|
||||
"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", new Axis(Input.CONTROLLER_DPAD_DOWN, Input.CONTROLLER_DPAD_UP),
|
||||
"menu", Input.CONTROLLER_X,
|
||||
"pause", Input.CONTROLLER_L_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("Multiplayer"),
|
||||
"player_list", Input.CONTROLLER_START
|
||||
);
|
||||
|
||||
|
@ -62,25 +62,26 @@ public class DesktopInput extends InputHandler{
|
||||
|
||||
if(Inputs.keyTap(section, "select") && recipe == null && player.inventory.hasItem()){
|
||||
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;
|
||||
droppingItem = true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
mousey = vec.y;
|
||||
}
|
||||
|
||||
if(!Inputs.keyDown(section, "select") && !Inputs.keyDown(section, "break")){
|
||||
mousex = Graphics.mouseWorld().x;
|
||||
mousey = Graphics.mouseWorld().y;
|
||||
Vector2 vec = Graphics.world(getMouseX(), getMouseY());
|
||||
mousex = vec.x;
|
||||
mousey = vec.y;
|
||||
}
|
||||
|
||||
endx = Gdx.input.getX();
|
||||
endy = Gdx.input.getY();
|
||||
endx = getMouseX();
|
||||
endy = getMouseY();
|
||||
|
||||
boolean controller = KeyBinds.getSection(section).device.type == DeviceType.controller;
|
||||
|
||||
@ -229,11 +230,11 @@ public class DesktopInput extends InputHandler{
|
||||
}
|
||||
|
||||
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")){
|
||||
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");
|
||||
@ -245,9 +246,11 @@ public class DesktopInput extends InputHandler{
|
||||
controly -= ya*baseControllerSpeed*scl;
|
||||
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());
|
||||
@ -266,17 +269,12 @@ public class DesktopInput extends InputHandler{
|
||||
public int tilex(){
|
||||
return (recipe != null && recipe.result.isMultiblock() &&
|
||||
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(){
|
||||
return (recipe != null && recipe.result.isMultiblock() &&
|
||||
recipe.result.size % 2 == 0) ?
|
||||
Mathf.scl(Graphics.mouseWorld().y, tilesize) : Mathf.scl2(Graphics.mouseWorld().y, tilesize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyDown(int keycode) {
|
||||
return super.keyDown(keycode);
|
||||
Mathf.scl(Graphics.world(getMouseX(), getMouseY()).y, tilesize) : Mathf.scl2(Graphics.world(getMouseX(), getMouseY()).y, tilesize);
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,10 @@ public abstract class InputHandler extends InputAdapter{
|
||||
public void resetCursor(){}
|
||||
public boolean isCursorVisible(){ return false; }
|
||||
|
||||
public float mouseAngle(float x, float y){
|
||||
return Graphics.world(getMouseX(), getMouseY()).sub(x, y).angle();
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
Inputs.removeProcessor(this);
|
||||
frag.remove();
|
||||
|
@ -52,7 +52,8 @@ public class Weapon extends Upgrade{
|
||||
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);
|
||||
|
||||
float cx = tr.x + p.x, cy = tr.y + p.y;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -54,6 +54,11 @@ public class PausedDialog extends FloatingDialog{
|
||||
load.show();
|
||||
}).disabled(b -> Net.active());
|
||||
|
||||
content().row();
|
||||
content().addButton("$text.addplayers", () -> {
|
||||
ui.localplayers.show();
|
||||
}).disabled(b -> Net.active());
|
||||
|
||||
content().row();
|
||||
|
||||
if(!gwt) {
|
||||
|
@ -14,12 +14,11 @@ import io.anuke.ucore.scene.actions.Actions;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
public class BlockConfigFragment implements Fragment {
|
||||
private Table table;
|
||||
private Table table = new Table();
|
||||
private Tile configTile;
|
||||
|
||||
@Override
|
||||
public void build(Group parent) {
|
||||
table = new Table();
|
||||
parent.addChild(table);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
import io.anuke.mindustry.content.Recipes;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.input.InputHandler;
|
||||
import io.anuke.mindustry.resource.Item;
|
||||
import io.anuke.mindustry.resource.ItemStack;
|
||||
@ -161,30 +162,44 @@ public class BlocksFragment implements Fragment{
|
||||
}
|
||||
});
|
||||
|
||||
image.clicked(() -> {
|
||||
// note: input.recipe only gets set here during a click.
|
||||
// during a hover only the visual description will be updated.
|
||||
boolean nothingSelectedYet = input.recipe == null;
|
||||
boolean selectedSomethingElse = !nothingSelectedYet && input.recipe != r;
|
||||
boolean shouldMakeSelection = nothingSelectedYet || selectedSomethingElse;
|
||||
if (shouldMakeSelection) {
|
||||
input.recipe = r;
|
||||
hoveredDescriptionRecipe = r;
|
||||
updateRecipe(r);
|
||||
} else {
|
||||
input.recipe = null;
|
||||
hoveredDescriptionRecipe = null;
|
||||
updateRecipe(null);
|
||||
}
|
||||
});
|
||||
image.addListener(new ClickListener(){
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y){
|
||||
// note: input.recipe only gets set here during a click.
|
||||
// during a hover only the visual description will be updated.
|
||||
InputHandler handler = mobile ? input : control.input(event.getPointer());
|
||||
|
||||
boolean nothingSelectedYet = handler.recipe == null;
|
||||
boolean selectedSomethingElse = !nothingSelectedYet && handler.recipe != r;
|
||||
boolean shouldMakeSelection = nothingSelectedYet || selectedSomethingElse;
|
||||
if (shouldMakeSelection) {
|
||||
handler.recipe = r;
|
||||
hoveredDescriptionRecipe = r;
|
||||
updateRecipe(r);
|
||||
} else {
|
||||
handler.recipe = null;
|
||||
hoveredDescriptionRecipe = null;
|
||||
updateRecipe(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
table.add(image).size(size + 8);
|
||||
|
||||
image.update(() -> {
|
||||
boolean has = (state.inventory.hasItems(r.requirements));
|
||||
image.setChecked(input.recipe == r);
|
||||
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)
|
||||
|
Reference in New Issue
Block a user