Implemented Android support

This commit is contained in:
Anuken
2017-06-29 00:54:10 -04:00
parent 9658059b24
commit 547c2b9025
273 changed files with 792 additions and 50 deletions

View File

@@ -2,26 +2,41 @@ package io.anuke.mindustry;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.input.GestureDetector;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.input.AndroidInput;
import io.anuke.mindustry.input.GestureHandler;
import io.anuke.mindustry.input.Input;
import io.anuke.mindustry.world.Generator;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.graphics.Atlas;
import io.anuke.ucore.modules.RendererModule;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timers;
public class Control extends RendererModule{
public int rangex = 10, rangey = 10;
public float targetzoom = 1f;
private float targetx, targety;
//GifRecorder recoder = new GifRecorder(batch);
public Control(){
cameraScale = 4;
pixelate();
Gdx.input.setCatchBackKey(true);
if(android){
Inputs.addProcessor(new GestureDetector(20, 0.5f, 2, 0.15f, new GestureHandler()));
Inputs.addProcessor(new AndroidInput());
}
Draw.addSurface("shadow", cameraScale);
atlas = new Atlas("mindustry.atlas");
@@ -39,7 +54,7 @@ public class Control extends RendererModule{
"down", Keys.S,
"right", Keys.D,
"rotate", Keys.R,
"menu", Keys.ESCAPE
"menu", Gdx.app.getType() == ApplicationType.Android ? Keys.BACK : Keys.ESCAPE
);
Settings.loadAll("io.anuke.moment");
@@ -65,12 +80,19 @@ public class Control extends RendererModule{
EffectLoader.create();
}
public void clampZoom(){
targetzoom = Mathf.clamp(targetzoom, 0.5f, 2f);
camera.zoom = Mathf.clamp(camera.zoom, 0.5f, 2f);
}
@Override
public void update(){
if(Inputs.keyUp(Keys.ESCAPE) && debug)
Gdx.app.exit();
//camera.zoom = MathUtils.lerp(camera.zoom, targetzoom, 0.5f*delta());
if(Inputs.keyUp(Keys.SPACE) && debug)
Effects.sound("shoot", core.worldx(), core.worldy());
@@ -110,17 +132,26 @@ public class Control extends RendererModule{
}
Entities.update();
Input.doInput();
if(!android){
Input.doInput();
}else{
AndroidInput.doInput();
}
}
if(core.block() == ProductionBlocks.core)
camera.position.set(player.x, player.y, 0f);
else
camera.position.set(core.worldx(), core.worldy(), 0f);
if(core.block() == ProductionBlocks.core){
smoothCamera(player.x, player.y, 0.3f);
}else{
smoothCamera(core.worldx(), core.worldy(), 0.4f);
}
updateShake();
clampCamera(-tilesize / 2f, -tilesize / 2f, pixsize - tilesize / 2f, pixsize - tilesize / 2f);
float lastx = camera.position.x, lasty = camera.position.y;
camera.position.set((int)camera.position.x, (int)camera.position.y, 0);
drawDefault();
@@ -129,6 +160,8 @@ public class Control extends RendererModule{
Renderer.renderOverlay();
batch.end();
camera.position.set(lastx, lasty, 0);
//recoder.update();
}
@@ -151,5 +184,8 @@ public class Control extends RendererModule{
rangex = (int) (width / tilesize / cameraScale/2)+2;
rangey = (int) (height / tilesize / cameraScale/2)+2;
AndroidInput.mousex = Gdx.graphics.getWidth()/2;
AndroidInput.mousey = Gdx.graphics.getHeight()/2;
}
}

View File

@@ -25,7 +25,10 @@ public class GameState{
wavetime = waveSpacing();
Entities.clear();
enemies = 0;
player.add();
if(!android)
player.add();
player.heal();
Inventory.clearItems();
spawnpoints.clear();
@@ -40,6 +43,8 @@ public class GameState{
player.x = core.worldx();
player.y = core.worldy()-8;
control.camera.position.set(player.x, player.y, 0);
wavetime = waveSpacing();
if(showedTutorial || !Settings.getBool("tutorial")){

View File

@@ -6,8 +6,10 @@ import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.input.AndroidInput;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
@@ -104,11 +106,27 @@ public class Renderer{
public static void renderPixelOverlay(){
if(recipe != null && !ui.hasMouse()){
float x = Mathf.round2(Graphics.mouseWorld().x, tilesize);
float y = Mathf.round2(Graphics.mouseWorld().y, tilesize);
if(recipe != null && (!ui.hasMouse() || android)){
float x = 0;
float y = 0;
int tilex = 0;
int tiley = 0;
if(android){
Vector2 vec = Graphics.world(AndroidInput.mousex, AndroidInput.mousey);
x = Mathf.round2(vec.x, tilesize);
y = Mathf.round2(vec.y, tilesize);
tilex = Mathf.scl2(vec.x, tilesize);
tiley = Mathf.scl2(vec.y, tilesize);
}else{
x = Mathf.round2(Graphics.mouseWorld().x, tilesize);
y = Mathf.round2(Graphics.mouseWorld().y, tilesize);
tilex = World.tilex();
tiley = World.tiley();
}
boolean valid = World.validPlace(World.tilex(), World.tiley(), recipe.result);
boolean valid = World.validPlace(tilex, tiley, recipe.result);
Draw.color(valid ? Color.PURPLE : Color.SCARLET);
Draw.thickness(2f);
@@ -143,6 +161,16 @@ public class Renderer{
Draw.reset();
}
}
if(android && breaktime > 0){
Tile tile = AndroidInput.selected();
if(tile.breakable() && tile.block() != ProductionBlocks.core){
float fract = breaktime / tile.block().breaktime;
Draw.color(Color.YELLOW, Color.SCARLET, fract);
Draw.circle(tile.worldx(), tile.worldy(), 4 + (1f-fract)*26);
Draw.reset();
}
}
if(recipe == null && !ui.hasMouse()){
Tile tile = World.cursorTile();

View File

@@ -12,10 +12,12 @@ import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.input.AndroidInput;
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.function.Listenable;
import io.anuke.ucore.function.VisibilityProvider;
import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.graphics.Textures;
@@ -30,7 +32,7 @@ import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Timers;
public class UI extends SceneModule{
Table itemtable, weapontable;
Table itemtable, weapontable, tools;
SettingsDialog prefs;
KeybindDialog keys;
Dialog about, menu, restart, tutorial, levels, upgrades;
@@ -164,6 +166,10 @@ public class UI extends SceneModule{
weapontable.bottom();
weapontable.setVisible(play);
if(android){
weapontable.remove();
}
build.begin(scene);
new table(){{
@@ -229,7 +235,7 @@ public class UI extends SceneModule{
Table tiptable = new Table();
Runnable run = ()->{
Listenable run = ()->{
tiptable.clearChildren();
String description = r.result.description();
@@ -253,7 +259,7 @@ public class UI extends SceneModule{
tiptable.pad(10f);
};
run.run();
run.listen();
Tooltip tip = new Tooltip(tiptable, run);
@@ -288,10 +294,11 @@ public class UI extends SceneModule{
row();
new button("Upgrades", ()->{
upgrades.show();
}).uniformX().fillX();
if(!android){
new button("Upgrades", ()->{
upgrades.show();
}).uniformX().fillX();
}
get().setVisible(play);
}}.end();
@@ -344,7 +351,8 @@ public class UI extends SceneModule{
}}.end();
//+- table
//if(Gdx.app.getType() != ApplicationType.Android){
//+- table
new table(){{
aleft();
abottom();
@@ -368,6 +376,7 @@ public class UI extends SceneModule{
get().setVisible(play);
}}.end();
//}
//menu table
new table(){{
@@ -385,12 +394,14 @@ public class UI extends SceneModule{
}).width(w);
row();
new button("Controls", () -> {
keys.show(scene);
}).width(w);
row();
if(!android){
new button("Controls", () -> {
keys.show(scene);
}).width(w);
row();
}
new button("About", () -> {
about.show(scene);
@@ -427,6 +438,30 @@ public class UI extends SceneModule{
});
}};
}}.end();
tools = new Table();
tools.addIButton("icon-cancel", 42, ()->{
recipe = null;
});
tools.addIButton("icon-rotate", 42, ()->{
rotation++;
rotation %= 4;
});
tools.addIButton("icon-check", 42, ()->{
AndroidInput.place();
});
scene.add(tools);
tools.setVisible(()->{
return playing && android && recipe != null;
});
tools.update(()->{
tools.setPosition(AndroidInput.mousex, Gdx.graphics.getHeight()-AndroidInput.mousey-60, Align.top);
});
updateItems();

View File

@@ -1,5 +1,7 @@
package io.anuke.mindustry;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
@@ -14,9 +16,11 @@ import io.anuke.mindustry.world.Tile;
/**ick, global state*/
public class Vars{
public static final boolean android = (Gdx.app.getType() == ApplicationType.Android);
public static final float placerange = 66;
public static final float respawnduration = 60*4;
public static final float wavespace = 20*60;
public static final float wavespace = 20*60*(android ? 2 : 1);
public static final float enemyspawnspace = 65;
public static boolean debug = false;
@@ -77,7 +81,23 @@ public class Vars{
"[YELLOW][[L-MOUSE][] to shoot.",
"[yellow][[scrollwheel] to switch weapons.",
"",
"[GOLD]Every 20 seconds, a new wave will appear.",
"[GOLD]Every "+wavespace/60+" seconds, a new wave will appear.",
"Build turrets to defend the core.",
"If the core is destroyed, you lose the game.",
"",
"[LIME]To collect building resources, move them into the core with conveyors.",
"[LIME]Place [ORANGE]drills[] on the right material,they will automatically mine material",
"and dump it to nearby conveyors or turrets.",
"",
"[SCARLET]To produce steel, feed coal and iron into a smelter."
};
public static String[] androidTutorialText = {
"[GREEN]Default Controls:",
"[WHITE]Use [YELLOW]one finger[] to pan the camera, or two while placing blocks.",
"[YELLOW]Hold and tap[] to destroy blocks.",
"",
"[GOLD]Every "+wavespace/60+" seconds, a new wave will appear.",
"Build turrets to defend the core.",
"If the core is destroyed, you lose the game.",
"",

View File

@@ -105,7 +105,7 @@ public class World{
public static boolean validPlace(int x, int y, Block type){
if(!cursorNear())
if(!cursorNear() && !android)
return false;
for(Tile spawn : spawnpoints){

View File

@@ -42,6 +42,7 @@ public class Player extends DestructibleEntity{
@Override
public void update(){
float speed = this.speed;
if(Vars.debug)

View File

@@ -0,0 +1,121 @@
package io.anuke.mindustry.input;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.Inventory;
import io.anuke.mindustry.World;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Sounds;
import io.anuke.ucore.scene.utils.Cursors;
import io.anuke.ucore.util.Mathf;
public class AndroidInput extends InputAdapter{
public static float mousex, mousey;
private static float lmousex, lmousey;
private static float warmup;
private static float warmupDelay = 20;
@Override
public boolean keyDown (int keycode) {
if(keycode == Keys.E){
place();
}
return false;
}
@Override
public boolean touchDown (int screenX, int screenY, int pointer, int button) {
if(pointer == 0){
lmousex = screenX;
lmousey = screenY;
}
warmup = 0;
return false;
}
public static Tile selected(){
Vector2 vec = Graphics.world(mousex, mousey);
return World.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize));
}
public static void breakBlock(){
Tile tile = selected();
breaktime += Mathf.delta();
if(breaktime >= tile.block().breaktime){
Effects.effect("break", tile.worldx(), tile.worldy());
Effects.shake(3f, 1f);
tile.setBlock(Blocks.air);
breaktime = 0f;
Sounds.play("break");
}
}
public static void place(){
Vector2 vec = Graphics.world(mousex, mousey);
int tilex = Mathf.scl2(vec.x, tilesize);
int tiley = Mathf.scl2(vec.y, tilesize);
if(recipe != null &&
World.validPlace(tilex, tiley, recipe.result)){
Tile tile = World.tile(tilex, tiley);
if(tile == null)
return; //just in case
tile.setBlock(recipe.result);
tile.rotation = rotation;
Effects.effect("place", tilex*tilesize, tiley*tilesize);
Effects.shake(2f, 2f);
Sounds.play("place");
for(ItemStack stack : recipe.requirements){
Inventory.removeItem(stack);
}
if(!Inventory.hasItems(recipe.requirements)){
recipe = null;
Cursors.restoreCursor();
}
}
}
public static void doInput(){
if(Gdx.input.isTouched(0)
&& Mathf.near2d(lmousex, lmousey, Gdx.input.getX(0), Gdx.input.getY(0), 50)
&& !ui.hasMouse() && recipe == null){
warmup += Mathf.delta();
mousex = Gdx.input.getX(0);
mousey = Gdx.input.getY(0);
Tile sel = selected();
if(warmup > warmupDelay && sel.block() != ProductionBlocks.core && sel.breakable()){
breaktime += Mathf.delta();
if(breaktime > selected().block().breaktime){
breakBlock();
breaktime = 0;
}
}
}else{
warmup = 0;
lmousex = Gdx.input.getX(0);
lmousey = Gdx.input.getY(0);
breaktime = 0;
}
}
}

View File

@@ -0,0 +1,99 @@
package io.anuke.mindustry.input;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.input.GestureDetector.GestureAdapter;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.World;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Sounds;
import io.anuke.ucore.util.Mathf;
public class GestureHandler extends GestureAdapter{
Vector2 pinch1 = new Vector2(-1, -1), pinch2 = pinch1.cpy();
Vector2 vector = new Vector2();
float initzoom = -1;
@Override
public boolean longPress(float x, float y){
Tile tile = World.cursorTile();
breaktime += Mathf.delta();
if(breaktime >= tile.block().breaktime){
Effects.effect("break", tile.worldx(), tile.worldy());
Effects.shake(3f, 1f);
tile.setBlock(Blocks.air);
breaktime = 0f;
Sounds.play("break");
}
return false;
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY){
if(recipe == null){
player.x -= deltaX*control.camera.zoom/control.cameraScale;
player.y += deltaY*control.camera.zoom/control.cameraScale;
}else{
AndroidInput.mousex += deltaX;
AndroidInput.mousey += deltaY;
}
return false;
}
@Override
public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
if(recipe == null)
return false;
if(pinch1.x < 0){
pinch1.set(initialPointer1);
pinch2.set(initialPointer2);
}
Vector2 vec = (vector.set(pointer1).add(pointer2).scl(0.5f)).sub(pinch1.add(pinch2).scl(0.5f));
player.x -= vec.x*control.camera.zoom/control.cameraScale;
player.y += vec.y*control.camera.zoom/control.cameraScale;
pinch1.set(pointer1);
pinch2.set(pointer2);
return false;
}
@Override
public boolean zoom(float initialDistance, float distance){
if(initzoom <= 0)
initzoom = initialDistance;
control.targetzoom /= (distance/initzoom);
control.clampZoom();
control.camera.update();
initzoom = distance;
return false;
}
@Override
public void pinchStop () {
initzoom = -1;
pinch2.set(pinch1.set(-1, -1));
}
int touches(){
int sum = 0;
for(int i = 0; i < 10; i ++){
if(Gdx.input.isTouched(i)) sum++;
}
return sum;
}
}

View File

@@ -1,10 +1,12 @@
package io.anuke.mindustry;
package io.anuke.mindustry.input;
import static io.anuke.mindustry.Vars.*;
import com.badlogic.gdx.Input.Buttons;
import com.badlogic.gdx.Input.Keys;
import io.anuke.mindustry.Inventory;
import io.anuke.mindustry.World;
import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.world.Tile;

View File

@@ -8,7 +8,7 @@ import io.anuke.ucore.scene.ui.TextDialog;
public class TutorialDialog extends TextDialog{
public TutorialDialog(){
super("Tutorial", tutorialText);
super("Tutorial", android ? androidTutorialText : tutorialText);
setup();
}

View File

@@ -9,6 +9,7 @@ import io.anuke.mindustry.entities.Weapon;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.ucore.core.Draw;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.function.Listenable;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Table;
@@ -71,7 +72,7 @@ public class UpgradeDialog extends Dialog{
Table tiptable = new Table();
Runnable run = ()->{
Listenable run = ()->{
tiptable.clearChildren();
String description = weapon.description;
@@ -100,7 +101,7 @@ public class UpgradeDialog extends Dialog{
tiptable.pad(10f);
};
run.run();
run.listen();
Tooltip tip = new Tooltip(tiptable, run);
@@ -114,7 +115,7 @@ public class UpgradeDialog extends Dialog{
Inventory.removeItems(weapon.requirements);
weapons.put(weapon, true);
ui.updateWeapons();
run.run();
run.listen();
Effects.sound("purchase");
});
}

View File

@@ -160,10 +160,8 @@ public class Block{
if(floor.id <= this.id) continue;
TextureRegion region = Draw.region(floor.name() + "edge");
if(region == null)
region = Draw.region(floor.edge + "edge");
TextureRegion region = Draw.hasRegion(floor.name() + "edge") ? Draw.region(floor.name() + "edge") :
Draw.region(floor.edge + "edge");
int sx = -dx*8+2, sy = -dy*8+2;
int x = Mathf.clamp(sx, 0, 12);

View File

@@ -0,0 +1,7 @@
package io.anuke.ucore.function;
import io.anuke.ucore.scene.Action;
public interface ActionProvider{
public Action get();
}

View File

@@ -0,0 +1,7 @@
package io.anuke.ucore.function;
import io.anuke.ucore.scene.ui.TextButton;
public interface ButtonTweaker{
public void tweak(TextButton button);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface Callable{
public void run();
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface CheckListenable{
public void listen(boolean checked);
}

View File

@@ -0,0 +1,7 @@
package io.anuke.ucore.function;
import com.badlogic.gdx.graphics.Color;
public interface ColorListenable{
public void changed(Color color);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface Consumer<T>{
public void accept(T t);
}

View File

@@ -0,0 +1,7 @@
package io.anuke.ucore.function;
import io.anuke.ucore.entities.Effect;
public interface EffectRenderer{
public void render(Effect effect);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface FieldListenable{
public void listen(String text);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface KeyListenable{
public void pressed(int key);
}

View File

@@ -0,0 +1,6 @@
package io.anuke.ucore.function;
/**Listener lambda class.*/
public interface Listenable{
public void listen();
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface PositionConsumer{
public void accept(float x, float y);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface Predicate<T>{
public boolean test(T t);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface StringProcessor{
public String get(int i);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface StringSupplier{
public String get();
}

View File

@@ -0,0 +1,6 @@
package io.anuke.ucore.function;
public interface TileCollider{
public boolean solid(int x, int y);
}

View File

@@ -0,0 +1,7 @@
package io.anuke.ucore.function;
import com.badlogic.gdx.math.Rectangle;
public interface TileHitboxProvider{
public void getHitbox(int x, int y, Rectangle out);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface TypingListenable{
public void typed(char c);
}

View File

@@ -0,0 +1,5 @@
package io.anuke.ucore.function;
public interface VisibilityProvider{
public boolean visible();
}