From 043f4688ef9fe34360316a6fad7a031ce7d83159 Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 18 Mar 2019 23:09:03 -0400 Subject: [PATCH] snakes --- .../anuke/mindustry/entities/type/Player.java | 37 ++--- .../anuke/mindustry/input/DesktopInput.java | 156 ++++++++++++++---- .../maps/generators/MapGenerator.java | 4 + core/src/io/anuke/mindustry/world/Tile.java | 8 + 4 files changed, 154 insertions(+), 51 deletions(-) diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java index a592a0ce85..f7713bb7f6 100644 --- a/core/src/io/anuke/mindustry/entities/type/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -9,9 +9,13 @@ import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; +import io.anuke.arc.math.geom.Point2; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.*; +import io.anuke.arc.util.Align; +import io.anuke.arc.util.Interval; +import io.anuke.arc.util.Pack; +import io.anuke.arc.util.Time; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.Mechs; @@ -426,32 +430,23 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ Lines.square( request.x * tilesize + block.offset(), - request.y * tilesize + block.offset(), - rad); + request.y * tilesize + block.offset(), rad); }else{ - float rad = Mathf.absin(Time.time(), 7f, 1f) - 1.5f + request.block.size * tilesize / 2f; - - //draw place request - Lines.stroke(1f, Pal.accentBack); - - Lines.square( - request.x * tilesize + request.block.offset(), - request.y * tilesize + request.block.offset() - 1, - rad); - Draw.color(); - Draw.rect(request.block.icon(Icon.full), - request.x * tilesize + request.block.offset(), - request.y * tilesize + request.block.offset(), rad*2, rad*2, request.block.rotate ? request.rotation * 90 : 0); + TextureRegion region = request.block.icon(Icon.full); + Draw.rect(region, request.x * tilesize + request.block.offset(), request.y * tilesize + request.block.offset(), + region.getWidth() * 1f * Draw.scl, + region.getHeight() * 1f * Draw.scl, request.block.rotate ? request.rotation * 90 : 0); Draw.color(Pal.accent); - - Lines.square( - request.x * tilesize + request.block.offset(), - request.y * tilesize + request.block.offset(), - rad); + for(int i = 0; i < 4; i++){ + Point2 p = Geometry.d8edge[i]; + float offset = -Math.max(request.block.size-1, 0)/2f * tilesize; + Draw.rect("block-select", request.x * tilesize + request.block.offset() + offset * p.x, request.y * tilesize + request.block.offset() + offset * p.y, i * 90); + } + Draw.color(); } } diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 4c22050f54..f6fe08c2a1 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -3,12 +3,17 @@ package io.anuke.mindustry.input; import io.anuke.arc.Core; import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; +import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Bresenham2; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; +import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.pooling.Pool; +import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.type.Player; @@ -33,6 +38,12 @@ public class DesktopInput extends InputHandler{ private PlaceMode mode; /**Animation scale for line.*/ private float selectScale; + /**All requests for the line mode placing.*/ + private Array requests = new Array<>(); + + private Bresenham2 bres = new Bresenham2(); + private Array points = new Array<>(); + private Array outPoints = new Array<>(); public DesktopInput(Player player){ super(player); @@ -77,32 +88,29 @@ public class DesktopInput extends InputHandler{ //draw selection(s) if(mode == placing && block != null){ - NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, true, maxLength); + int i = 0; + for(PlaceRequest request : requests){ + int x = request.x, y = request.y; - for(int i = 0; i <= result.getLength(); i += block.size){ - int x = selectX + i * Mathf.sign(cursorX - selectX) * Mathf.num(result.isX()); - int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.num(!result.isX()); - - if(i + block.size > result.getLength() && block.rotate){ - Draw.color(!validPlace(x, y, block, result.rotation) ? Pal.removeBack : Pal.accentBack); + if(++i >= requests.size && block.rotate){ + Draw.color(!validPlace(x, y, block, request.rotation) ? Pal.removeBack : Pal.accentBack); Draw.rect(Core.atlas.find("place-arrow"), - x * tilesize + block.offset(), - y * tilesize + block.offset() - 1, - Core.atlas.find("place-arrow").getWidth() * Draw.scl, - Core.atlas.find("place-arrow").getHeight() * Draw.scl, result.rotation * 90 - 90); + x * tilesize + block.offset(), + y * tilesize + block.offset() - 1, + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, request.rotation * 90 - 90); - Draw.color(!validPlace(x, y, block, result.rotation) ? Pal.remove : Pal.accent); + Draw.color(!validPlace(x, y, block, request.rotation) ? Pal.remove : Pal.accent); Draw.rect(Core.atlas.find("place-arrow"), - x * tilesize + block.offset(), - y * tilesize + block.offset(), - Core.atlas.find("place-arrow").getWidth() * Draw.scl, - Core.atlas.find("place-arrow").getHeight() * Draw.scl, result.rotation * 90 - 90); + x * tilesize + block.offset(), + y * tilesize + block.offset(), + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, request.rotation * 90 - 90); } - drawPlace(x, y, block, result.rotation); + drawPlace(request.x, request.y, block, request.rotation); } - Draw.reset(); }else if(mode == breaking){ NormalizeDrawResult result = PlaceUtils.normalizeDrawArea(Blocks.air, selectX, selectY, cursorX, cursorY, false, maxLength, 1f); NormalizeResult dresult = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, false, maxLength); @@ -166,13 +174,17 @@ public class DesktopInput extends InputHandler{ //renderer.minimap.zoomBy(-Core.input.axisTap(Binding.zoom_minimap)); - if(player.isDead()) return; + if(player.isDead()){ + cursorType = SystemCursor.arrow; + return; + } pollInput(); //deselect if not placing if(!isPlacing() && mode == placing){ mode = none; + requests.clear(); } if(player.isShooting && !canShoot()){ @@ -190,9 +202,7 @@ public class DesktopInput extends InputHandler{ Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY()); - if(player.isDead()){ - cursorType = SystemCursor.arrow; - }else if(cursor != null){ + if(cursor != null){ cursor = cursor.target(); cursorType = cursor.block().getCursor(cursor); @@ -231,6 +241,7 @@ public class DesktopInput extends InputHandler{ selectX = cursorX; selectY = cursorY; mode = placing; + requests.add(new PlaceRequest(selectX, selectY, rotation)); }else if(selected != null){ //only begin shooting if there's no cursor event if (!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && @@ -255,20 +266,51 @@ public class DesktopInput extends InputHandler{ selectY = tileY(Core.input.mouseY()); } + if(isPlacing() && mode == placing){ + if((cursorX != selectX || cursorY != selectY)){ + points.clear(); + outPoints.clear(); + Pool pool = Pools.get(Point2.class, Point2::new); + Array out = bres.line(selectX, selectY, cursorX, cursorY, pool, outPoints); + + for(int i = 0; i < out.size; i++){ + points.add(out.get(i)); + + if(i != out.size - 1){ + Point2 curr = out.get(i); + Point2 next = out.get(i + 1); + //diagonal + if(next.x != curr.x && next.y != curr.y){ + points.add(new Point2(next.x, curr.y)); + } + } + } + + for(Point2 point : points){ + if(checkUnused(point.x, point.y)){ + addRequest(point); + selectX = point.x; + selectY = point.y; + } + + } + + pool.freeAll(outPoints); + + } + } if(Core.input.keyRelease(Binding.break_block) || Core.input.keyRelease(Binding.select)){ if(mode == placing && block != null){ //touch up while placing, place everything in selection - NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, true, maxLength); + int rot = rotation; - for(int i = 0; i <= result.getLength(); i += block.size){ - int x = selectX + i * Mathf.sign(cursorX - selectX) * Mathf.num(result.isX()); - int y = selectY + i * Mathf.sign(cursorY - selectY) * Mathf.num(!result.isX()); - - rotation = result.rotation; - - tryPlaceBlock(x, y); + for(PlaceRequest req : requests){ + rotation = req.rotation; + tryPlaceBlock(req.x, req.y); } + + rotation = rot; }else if(mode == breaking){ //touch up while breaking, break everything in selection NormalizeResult result = PlaceUtils.normalizeArea(selectX, selectY, cursorX, cursorY, rotation, false, maxLength); for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){ @@ -285,11 +327,46 @@ public class DesktopInput extends InputHandler{ tryDropItems(selected.target(), Core.input.mouseWorld().x, Core.input.mouseWorld().y); } + requests.clear(); mode = none; } } + boolean checkUnused(int x, int y){ + Tmp.r2.setSize(block.size * tilesize); + Tmp.r2.setCenter(x * tilesize + block.offset(), y * tilesize + block.offset()); + + for(PlaceRequest req : requests){ + Tmp.r1.setSize(block.size * tilesize); + Tmp.r1.setCenter(req.x*tilesize + block.offset(), req.y*tilesize + block.offset()); + + if(Tmp.r2.overlaps(Tmp.r1)){ + return false; + } + } + return true; + } + + void addRequest(Point2 point){ + if(!checkUnused(point.x, point.y)) return; + + PlaceRequest last = requests.peek(); + + if(last.x == point.x && last.y == point.y){ + return; + } + + int rel = Tile.relativeTo(last.x, last.y, point.x, point.y); + + if(rel != -1){ + last.rotation = rel; + rotation = rel; + } + + requests.add(new PlaceRequest(point.x, point.y, rotation)); + } + @Override public boolean selectedBlock(){ return isPlacing() && mode != breaking; @@ -313,4 +390,23 @@ public class DesktopInput extends InputHandler{ } } + class PlaceRequest{ + int x, y, rotation; + + public PlaceRequest(int x, int y, int rotation){ + this.x = x; + this.y = y; + this.rotation = rotation; + } + + @Override + public String toString(){ + return "PlaceRequest{" + + "x=" + x + + ", y=" + y + + ", rotation=" + rotation + + '}'; + } + } + } diff --git a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java index c2756b4753..96a904fc8c 100644 --- a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java @@ -99,6 +99,10 @@ public class MapGenerator extends Generator{ enemies.add(new Point2(x, y)); tiles[x][y].setBlock(Blocks.air); } + + if(tiles[x][y].block() == Blocks.part){ + tiles[x][y].setBlock(Blocks.air); + } } } diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index bb3d9dacfa..e1481dcfab 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -87,6 +87,14 @@ public class Tile implements Position, TargetTrait{ return -1; } + public static byte relativeTo(int x, int y, int cx, int cy){ + if(x == cx && y == cy - 1) return 1; + if(x == cx && y == cy + 1) return 3; + if(x == cx - 1 && y == cy) return 0; + if(x == cx + 1 && y == cy) return 2; + return -1; + } + public byte absoluteRelativeTo(int cx, int cy){ if(x == cx && y <= cy - 1) return 1; if(x == cx && y >= cy + 1) return 3;