mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-13 00:05:23 +07:00
Beam node link previews, closes Anuken/Mindustry-Suggestions/issues/5140
This commit is contained in:
parent
1f900b52f8
commit
7671766469
@ -441,6 +441,14 @@ public class Block extends UnlockableContent implements Senseable{
|
|||||||
|
|
||||||
Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 2f, Pal.place);
|
Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 2f, Pal.place);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
BeamNode.getNodeLinks(tile, this, player.team(), other -> {
|
||||||
|
BeamNode node = (BeamNode)other.block;
|
||||||
|
Draw.color(node.laserColor1, Renderer.laserOpacity * 0.5f);
|
||||||
|
node.drawLaser(other.x, other.y, x * tilesize + offset, y * tilesize + offset, size, other.block.size);
|
||||||
|
|
||||||
|
Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 2f, Pal.place);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package mindustry.world.blocks.power;
|
package mindustry.world.blocks.power;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
@ -20,6 +23,9 @@ import java.util.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class BeamNode extends PowerBlock{
|
public class BeamNode extends PowerBlock{
|
||||||
|
//maximum expected range of any beam node; used for previews
|
||||||
|
private static final int maxRange = 30;
|
||||||
|
|
||||||
public int range = 5;
|
public int range = 5;
|
||||||
|
|
||||||
public @Load(value = "@-beam", fallback = "power-beam") TextureRegion laser;
|
public @Load(value = "@-beam", fallback = "power-beam") TextureRegion laser;
|
||||||
@ -105,12 +111,99 @@ public class BeamNode extends PowerBlock{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Iterates through linked nodes of a block at a tile. All returned buildings are beam nodes. */
|
||||||
|
public static void getNodeLinks(Tile tile, Block block, Team team, Cons<Building> others){
|
||||||
|
var tree = team.data().buildingTree;
|
||||||
|
|
||||||
|
if(tree == null) return;
|
||||||
|
|
||||||
|
float cx = tile.worldx() + block.offset, cy = tile.worldy() + block.offset, s = block.size * tilesize/2f, r = maxRange * tilesize;
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
int dx = Geometry.d4[i].x, dy = Geometry.d4[i].y;
|
||||||
|
for(int length = 1; length < maxRange; length++){
|
||||||
|
Tile other = tile.nearby(dx * i, dy * i);
|
||||||
|
if(other == null || other.build == null || other.build.isInsulated()) break;
|
||||||
|
|
||||||
|
Building build = other.build;
|
||||||
|
|
||||||
|
if(build.team == team && build.block.hasPower && build.block.connectedPower){
|
||||||
|
if(build instanceof BeamNodeBuild){
|
||||||
|
if(build.tileX() == tile.x || build.tileY() == tile.y){
|
||||||
|
others.get(build);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else{ //it's a power structure that is blocking the way to any potential beam node.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(i){
|
||||||
|
case 0 -> Tmp.r1.set(cx - s, cy - s, r, s * 2f);
|
||||||
|
case 1 -> Tmp.r1.set(cx - s, cy - s, s * 2f, r);
|
||||||
|
case 2 -> Tmp.r1.set(cx + s, cy - s, -r, s * 2f).normalize();
|
||||||
|
case 3 -> Tmp.r1.set(cx - s, cy + s, s * 2f, -r).normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
tempBuilds.clear();
|
||||||
|
tree.intersect(Tmp.r1, tempBuilds);
|
||||||
|
int fi = i;
|
||||||
|
Building closest = tempBuilds.min(b -> b instanceof BeamNodeBuild node && node.couldConnect((fi + 2) % 4, block, tile.x, tile.y), b -> b.dst2(cx, cy));
|
||||||
|
if(closest != null){
|
||||||
|
others.get(closest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Note that x1 and y1 are expected to be coordinates of the node to draw the beam from. */
|
||||||
|
public void drawLaser(float x1, float y1, float x2, float y2, int size1, int size2){
|
||||||
|
float w = laserWidth;
|
||||||
|
float dst = Math.max(Math.abs(x1 - x2), Math.abs(y2 - y1)) / tilesize;
|
||||||
|
float sizeOff = dst * tilesize - (size1 + size2) * tilesize/2f;
|
||||||
|
|
||||||
|
//don't draw lasers for adjacent blocks
|
||||||
|
if(dst > 1 + size/2){
|
||||||
|
var point = Geometry.d4(Tile.relativeTo(x1, y1, x2, y2));
|
||||||
|
float poff = tilesize/2f;
|
||||||
|
Drawf.laser(laser, laserEnd, x1 + poff*size*point.x, y1 + poff*size*point.y, x1 + (poff*size + sizeOff) * point.x, y1 + (poff*size + sizeOff) * point.y, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class BeamNodeBuild extends Building{
|
public class BeamNodeBuild extends Building{
|
||||||
//current links in cardinal directions
|
//current links in cardinal directions
|
||||||
public Building[] links = new Building[4];
|
public Building[] links = new Building[4];
|
||||||
public Tile[] dests = new Tile[4];
|
public Tile[] dests = new Tile[4];
|
||||||
public int lastChange = -2;
|
public int lastChange = -2;
|
||||||
|
|
||||||
|
/** @return whether a beam could theoretically connect with the specified block at a position */
|
||||||
|
public boolean couldConnect(int direction, Block target, int targetX, int targetY){
|
||||||
|
int offset = -(target.size - 1) / 2;
|
||||||
|
int minX = targetX + offset, minY = targetY + offset, maxX = targetX + offset + target.size - 1, maxY = targetY + offset + target.size - 1;
|
||||||
|
var dir = Geometry.d4[direction];
|
||||||
|
|
||||||
|
int rangeOffset = size/2;
|
||||||
|
|
||||||
|
//find first block with power in range
|
||||||
|
for(int j = 1 + rangeOffset; j <= range + rangeOffset; j++){
|
||||||
|
var other = world.tile(tile.x + j * dir.x, tile.y + j * dir.y);
|
||||||
|
|
||||||
|
if(other == null) return false;
|
||||||
|
|
||||||
|
//hit insulated wall
|
||||||
|
if((other.build != null && other.build.isInsulated()) || (other.block().hasPower && other.block().connectedPower && other.team() == team)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//within target rectangle
|
||||||
|
if(other.x >= minX && other.y >= minY && other.x <= maxX && other.y <= maxY){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
//TODO this block technically does not need to update every frame, perhaps put it in a special list.
|
//TODO this block technically does not need to update every frame, perhaps put it in a special list.
|
||||||
|
@ -26,4 +26,4 @@ org.gradle.caching=true
|
|||||||
org.gradle.internal.http.socketTimeout=100000
|
org.gradle.internal.http.socketTimeout=100000
|
||||||
org.gradle.internal.http.connectionTimeout=100000
|
org.gradle.internal.http.connectionTimeout=100000
|
||||||
android.enableR8.fullMode=false
|
android.enableR8.fullMode=false
|
||||||
archash=1fdfcdc213
|
archash=6676d38433
|
||||||
|
Loading…
Reference in New Issue
Block a user