Files
Mindustry/core/src/mindustry/graphics/MenuRenderer.java
hortiSquash 1d971231ca Support of mods with textures in different resolution (HD or low-res) (#7602)
* HDustry - scl() & private map

Co-Authored-By: citrusMarmelade <20476281+citrusMarmelade@users.noreply.github.com>

* MEEP stop doing stuff when i work

<3 <3

* Replaced Draw.scl

Co-authored-by: citrusMarmelade <20476281+citrusMarmelade@users.noreply.github.com>
Co-authored-by: Anuken <arnukren@gmail.com>
2022-09-23 16:21:53 -04:00

295 lines
9.9 KiB
Java

package mindustry.graphics;
import arc.*;
import arc.func.*;
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.gl.*;
import arc.math.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import arc.util.noise.*;
import mindustry.content.*;
import mindustry.type.*;
import mindustry.world.*;
import static mindustry.Vars.*;
public class MenuRenderer implements Disposable{
private static final float darkness = 0.3f;
private final int width = !mobile ? 100 : 60, height = !mobile ? 50 : 40;
private int cacheFloor, cacheWall;
private Camera camera = new Camera();
private Mat mat = new Mat();
private FrameBuffer shadows;
private CacheBatch batch;
private float time = 0f;
private float flyerRot = 45f;
private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15);
//no longer random or "dynamic", mod units in the menu look jarring, and it's not worth the configuration effort
private UnitType flyerType = Seq.with(UnitTypes.flare, UnitTypes.horizon, UnitTypes.zenith, UnitTypes.mono, UnitTypes.poly, UnitTypes.mega, UnitTypes.alpha, UnitTypes.beta, UnitTypes.gamma).random();
public MenuRenderer(){
Time.mark();
generate();
cache();
Log.debug("Time to generate menu: @", Time.elapsed());
}
private void generate(){
//suppress tile change events.
world.setGenerating(true);
Tiles tiles = world.resize(width, height);
//only uses base game ores now, mod ones usually contrast too much with the floor
Seq<Block> ores = Seq.with(Blocks.oreCopper, Blocks.oreLead, Blocks.oreScrap, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium);
shadows = new FrameBuffer(width, height);
int offset = Mathf.random(100000);
int s1 = offset, s2 = offset + 1, s3 = offset + 2;
Block[] selected = Structs.random(
new Block[]{Blocks.sand, Blocks.sandWall},
new Block[]{Blocks.shale, Blocks.shaleWall},
new Block[]{Blocks.ice, Blocks.iceWall},
new Block[]{Blocks.sand, Blocks.sandWall},
new Block[]{Blocks.shale, Blocks.shaleWall},
new Block[]{Blocks.ice, Blocks.iceWall},
new Block[]{Blocks.moss, Blocks.sporePine},
new Block[]{Blocks.dirt, Blocks.dirtWall},
new Block[]{Blocks.dacite, Blocks.daciteWall}
);
Block[] selected2 = Structs.random(
new Block[]{Blocks.basalt, Blocks.duneWall},
new Block[]{Blocks.basalt, Blocks.duneWall},
new Block[]{Blocks.stone, Blocks.stoneWall},
new Block[]{Blocks.stone, Blocks.stoneWall},
new Block[]{Blocks.moss, Blocks.sporeWall},
new Block[]{Blocks.salt, Blocks.saltWall}
);
Block ore1 = ores.random();
ores.remove(ore1);
Block ore2 = ores.random();
double tr1 = Mathf.random(0.65f, 0.85f);
double tr2 = Mathf.random(0.65f, 0.85f);
boolean doheat = Mathf.chance(0.25);
boolean tendrils = Mathf.chance(0.25);
boolean tech = Mathf.chance(0.25);
int secSize = 10;
Block floord = selected[0], walld = selected[1];
Block floord2 = selected2[0], walld2 = selected2[1];
for(int x = 0; x < width; x++){
for(int y = 0; y < height; y++){
Block floor = floord;
Block ore = Blocks.air;
Block wall = Blocks.air;
if(Simplex.noise2d(s1, 3, 0.5, 1/20.0, x, y) > 0.5){
wall = walld;
}
if(Simplex.noise2d(s3, 3, 0.5, 1/20.0, x, y) > 0.5){
floor = floord2;
if(wall != Blocks.air){
wall = walld2;
}
}
if(Simplex.noise2d(s2, 3, 0.3, 1/30.0, x, y) > tr1){
ore = ore1;
}
if(Simplex.noise2d(s2, 2, 0.2, 1/15.0, x, y+99999) > tr2){
ore = ore2;
}
if(doheat){
double heat = Simplex.noise2d(s3, 4, 0.6, 1 / 50.0, x, y + 9999);
double base = 0.65;
if(heat > base){
ore = Blocks.air;
wall = Blocks.air;
floor = Blocks.basalt;
if(heat > base + 0.1){
floor = Blocks.hotrock;
if(heat > base + 0.15){
floor = Blocks.magmarock;
}
}
}
}
if(tech){
int mx = x % secSize, my = y % secSize;
int sclx = x / secSize, scly = y / secSize;
if(Simplex.noise2d(s1, 2, 1f / 10f, 0.5f, sclx, scly) > 0.4f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){
floor = Blocks.darkPanel3;
if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 1){
floor = Blocks.darkPanel4;
}
if(wall != Blocks.air && Mathf.chance(0.7)){
wall = Blocks.darkMetal;
}
}
}
if(tendrils){
if(Ridged.noise2d(1 + offset, x, y, 1f / 17f) > 0f){
floor = Mathf.chance(0.2) ? Blocks.sporeMoss : Blocks.moss;
if(wall != Blocks.air){
wall = Blocks.sporeWall;
}
}
}
Tile tile;
tiles.set(x, y, (tile = new CachedTile()));
tile.x = (short)x;
tile.y = (short)y;
tile.setFloor(floor.asFloor());
tile.setBlock(wall);
tile.setOverlay(ore);
}
}
//don't fire a world load event, it just causes lag and confusion
world.setGenerating(false);
}
private void cache(){
//draw shadows
Draw.proj().setOrtho(0, 0, shadows.getWidth(), shadows.getHeight());
shadows.begin(Color.clear);
Draw.color(Color.black);
for(Tile tile : world.tiles){
if(tile.block() != Blocks.air){
Fill.rect(tile.x + 0.5f, tile.y + 0.5f, 1, 1);
}
}
Draw.color();
shadows.end();
Batch prev = Core.batch;
Core.batch = batch = new CacheBatch(new SpriteCache(width * height * 6, false));
batch.beginCache();
for(Tile tile : world.tiles){
tile.floor().drawBase(tile);
}
for(Tile tile : world.tiles){
tile.overlay().drawBase(tile);
}
cacheFloor = batch.endCache();
batch.beginCache();
for(Tile tile : world.tiles){
tile.block().drawBase(tile);
}
cacheWall = batch.endCache();
Core.batch = prev;
}
public void render(){
time += Time.delta;
float scaling = Math.max(Scl.scl(4f), Math.max(Core.graphics.getWidth() / ((width - 1f) * tilesize), Core.graphics.getHeight() / ((height - 1f) * tilesize)));
camera.position.set(width * tilesize / 2f, height * tilesize / 2f);
camera.resize(Core.graphics.getWidth() / scaling,
Core.graphics.getHeight() / scaling);
mat.set(Draw.proj());
Draw.flush();
Draw.proj(camera);
batch.setProjection(camera.mat);
batch.beginDraw();
batch.drawCache(cacheFloor);
batch.endDraw();
Draw.color();
Draw.rect(Draw.wrap(shadows.getTexture()),
width * tilesize / 2f - 4f, height * tilesize / 2f - 4f,
width * tilesize, -height * tilesize);
Draw.flush();
batch.beginDraw();
batch.drawCache(cacheWall);
batch.endDraw();
drawFlyers();
Draw.proj(mat);
Draw.color(0f, 0f, 0f, darkness);
Fill.crect(0, 0, Core.graphics.getWidth(), Core.graphics.getHeight());
Draw.color();
}
private void drawFlyers(){
Draw.color(0f, 0f, 0f, 0.4f);
TextureRegion icon = flyerType.fullIcon;
flyers((x, y) -> {
Draw.rect(icon, x - 12f, y - 13f, flyerRot - 90);
});
float size = Math.max(icon.width, icon.height) * icon.scl() * 1.6f;
flyers((x, y) -> {
Draw.rect("circle-shadow", x, y, size, size);
});
Draw.color();
flyers((x, y) -> {
float engineOffset = flyerType.engineOffset, engineSize = flyerType.engineSize, rotation = flyerRot;
Draw.color(Pal.engine);
Fill.circle(x + Angles.trnsx(rotation + 180, engineOffset), y + Angles.trnsy(rotation + 180, engineOffset),
engineSize + Mathf.absin(Time.time, 2f, engineSize / 4f));
Draw.color(Color.white);
Fill.circle(x + Angles.trnsx(rotation + 180, engineOffset - 1f), y + Angles.trnsy(rotation + 180, engineOffset - 1f),
(engineSize + Mathf.absin(Time.time, 2f, engineSize / 4f)) / 2f);
Draw.color();
Draw.rect(icon, x, y, flyerRot - 90);
});
}
private void flyers(Floatc2 cons){
float tw = width * tilesize * 1f + tilesize;
float th = height * tilesize * 1f + tilesize;
float range = 500f;
float offset = -100f;
for(int i = 0; i < flyers; i++){
Tmp.v1.trns(flyerRot, time * (flyerType.speed));
cons.get(
(Mathf.randomSeedRange(i, range) + Tmp.v1.x + Mathf.absin(time + Mathf.randomSeedRange(i + 2, 500), 10f, 3.4f) + offset) % (tw + Mathf.randomSeed(i + 5, 0, 500)),
(Mathf.randomSeedRange(i + 1, range) + Tmp.v1.y + Mathf.absin(time + Mathf.randomSeedRange(i + 3, 500), 10f, 3.4f) + offset) % th
);
}
}
@Override
public void dispose(){
batch.dispose();
shadows.dispose();
}
}