Implemented basic minimap

This commit is contained in:
Anuken
2018-04-19 21:57:55 -04:00
parent 7df232c65d
commit ccd25c7e76
11 changed files with 172 additions and 71 deletions

View File

@ -1,5 +1,5 @@
#Autogenerated file. Do not modify.
#Thu Apr 19 19:06:19 EDT 2018
#Thu Apr 19 21:55:56 EDT 2018
version=release
androidBuildCode=1073
name=Mindustry

View File

@ -6,12 +6,15 @@ import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.ai.Pathfind;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.game.EventType.TileChangeEvent;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.io.MapIO;
import io.anuke.mindustry.io.Maps;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.WorldGenerator;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Mathf;
@ -28,6 +31,7 @@ public class World extends Module{
private Maps maps = new Maps();
private Array<Tile> tempTiles = new Array<>();
private boolean generating;
public World(){
maps.load();
@ -157,6 +161,7 @@ public class World extends Module{
}
public void loadMap(Map map, int seed){
generating = true;
this.currentMap = map;
this.seed = seed;
@ -167,12 +172,21 @@ public class World extends Module{
Entities.resizeTree(0, 0, width * tilesize, height * tilesize);
WorldGenerator.generate(tiles, MapIO.readTileData(map, true));
generating = false;
Events.fire(WorldLoadEvent.class);
}
public int getSeed(){
return seed;
}
public void notifyChanged(Tile tile){
if(!generating){
Gdx.app.postRunnable(() -> Events.fire(TileChangeEvent.class, tile));
}
}
public void removeBlock(Tile tile){
if(!tile.block().isMultiblock() && !tile.isLinked()){
tile.setBlock(Blocks.air);

View File

@ -6,6 +6,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.Pool.Poolable;
import com.badlogic.gdx.utils.Pools;
import io.anuke.mindustry.content.Liquids;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.content.fx.BlockFx;
import io.anuke.mindustry.content.fx.EnvironmentFx;
@ -60,8 +61,9 @@ public class Puddle extends Entity implements SerializableEntity, Poolable{
}
private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){
if(tile.floor().liquid){
reactPuddle(tile.floor().liquidDrop, liquid, amount, tile, tile.worldx(), tile.worldy());
if(tile.floor().liquid && !canStayOn(liquid, tile.floor().liquidDrop)){
reactPuddle(tile.floor().liquidDrop, liquid, amount, tile,
(tile.worldx() + source.worldx())/2f, (tile.worldy() + source.worldy())/2f);
if(generation == 0 && Timers.get(tile, "ripple", 50)){
Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color,
@ -90,19 +92,26 @@ public class Puddle extends Entity implements SerializableEntity, Poolable{
}
}
private static float reactPuddle(Liquid pliquid, Liquid liquid, float amount, Tile tile, float x, float y){
if((pliquid.flammability > 0.3f && liquid.temperature > 0.7f) ||
(liquid.flammability > 0.3f && pliquid.temperature > 0.7f)){ //flammable liquid + hot liquid
/**Returns whether the first liquid can 'stay' on the second one.
* Currently, the only place where this can happen is oil on water.*/
private static boolean canStayOn(Liquid liquid, Liquid other){
return liquid == Liquids.oil && other == Liquids.water;
}
/**Reacts two liquids together at a location.*/
private static float reactPuddle(Liquid dest, Liquid liquid, float amount, Tile tile, float x, float y){
if((dest.flammability > 0.3f && liquid.temperature > 0.7f) ||
(liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid
Fire.create(tile);
if(Mathf.chance(0.006 * amount)){
new Fireball(x, y, pliquid.flameColor, Mathf.random(360f)).add();
new Fireball(x, y, dest.flameColor, Mathf.random(360f)).add();
}
}else if(pliquid.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle
}else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot puddle
if(Mathf.chance(0.5f * amount)){
Effects.effect(EnvironmentFx.steam, x, y);
}
return - 0.1f * amount;
}else if(liquid.temperature > 0.7f && pliquid.temperature < 0.55f){ //hot liquid poured onto cold puddle
}else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold puddle
if(Mathf.chance(0.8f * amount)){
Effects.effect(EnvironmentFx.steam, x, y);
}

View File

@ -1,13 +1,7 @@
package io.anuke.mindustry.game;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.function.Event;
public class EventType {
@ -28,63 +22,15 @@ public class EventType {
void handle();
}
public interface StateChangeEvent extends Event{
void handle(State from, State to);
}
public interface FriendlyFireChange extends Event{
void handle(boolean on);
}
public interface BulletEvent extends Event{
void handle(BulletType type, Entity owner, float x, float y, float angle, short damage);
}
public interface EnemyDeathEvent extends Event{
void handle(BaseUnit enemy);
}
public interface BlockDestroyEvent extends Event{
void handle(TileEntity entity);
}
public interface BlockDamageEvent extends Event{
void handle(TileEntity entity);
}
public interface PlayerDeathEvent extends Event{
public interface WorldLoadEvent extends Event{
void handle();
}
public interface BlockConfigEvent extends Event{
void handle(Tile tile, byte data);
}
public interface BlockTapEvent extends Event{
public interface TileChangeEvent extends Event{
void handle(Tile tile);
}
public interface WeaponSwitchEvent extends Event{
void handle();
}
public interface UpgradeEvent extends Event{
void handle(Weapon weapon);
}
public interface MessageSendEvent extends Event{
void handle(String message);
}
public interface ShootEvent extends Event{
void handle(Weapon weapon, float x, float y, float angle);
}
public interface PlaceEvent extends Event{
void handle(int x, int y, Block block, int rotation);
}
public interface BreakEvent extends Event{
void handle(int x, int y);
public interface StateChangeEvent extends Event{
void handle(State from, State to);
}
}

View File

@ -9,8 +9,10 @@ public enum Team {
green(Color.valueOf("1dc645"));
public final Color color;
public final int intColor;
Team(Color color){
this.color = color;
intColor = Color.rgba8888(color);
}
}

View File

@ -1,29 +1,119 @@
package io.anuke.mindustry.graphics;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.sun.media.jfxmediaimpl.MediaDisposer.Disposable;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.game.EventType.TileChangeEvent;
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
public class MinimapRenderer implements Disposable{
private static final int baseSize = 16;
private Pixmap pixmap;
private Texture texture;
private TextureRegion region;
private Rectangle rect = new Rectangle();
private int zoom = 4;
public MinimapRenderer(){
Events.on(WorldLoadEvent.class, () -> {
reset();
updateAll();
});
Events.on(TileChangeEvent.class, this::update);
}
public Texture getTexture(){
return texture;
}
public void reset(){
public void zoomBy(int amount){
zoom += amount;
zoom = Mathf.clamp(zoom, 1, Math.min(world.width(), world.height())/baseSize/2);
}
public void updated(Tile tile){
public void reset(){
if(pixmap != null){
pixmap.dispose();
texture.dispose();
}
pixmap = new Pixmap(world.width(), world.height(), Format.RGBA8888);
texture = new Texture(pixmap);
region = new TextureRegion(texture);
}
public void drawEntities(float x, float y, float w, float h){
int sz = baseSize * zoom;
float dx = (Core.camera.position.x / tilesize);
float dy = (Core.camera.position.y / tilesize);
dx = Mathf.clamp(dx, sz, world.width()-sz);
dy = Mathf.clamp(dy, sz, world.height()-sz);
rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize);
Units.getNearby(rect, unit -> {
if(!rect.contains(unit.x, unit.y)) return;
float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y)/ rect.width * h;
Draw.color(unit.team.color);
Draw.rect("white", x + rx, y + ry, w/(sz*2), h/(sz*2));
});
Draw.color();
}
public TextureRegion getRegion() {
int sz = Mathf.clamp(baseSize * zoom, baseSize, Math.min(world.width(), world.height()));
float dx = (Core.camera.position.x / tilesize);
float dy = (Core.camera.position.y / tilesize);
dx = Mathf.clamp(dx, sz, world.width()-sz);
dy = Mathf.clamp(dy, sz, world.height()-sz);
float invTexWidth = 1f / texture.getWidth();
float invTexHeight = 1f / texture.getHeight();
float x = dx - sz, y = world.height()-dy - sz, width = sz*2, height = sz*2;
region.setRegion(x * invTexWidth, y * invTexHeight, (x + width) * invTexWidth, (y + height) * invTexHeight);
return region;
}
public void updateAll(){
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(world.tile(x, y)));
}
}
texture.draw(pixmap, 0, 0);
}
public void update(Tile tile){
int color = colorFor(world.tile(tile.x, tile.y));
pixmap.drawPixel(tile.x, pixmap.getHeight() - 1 - tile.y, color);
texture.bind();
Pixmaps.drawPixel(texture, tile.x, pixmap.getHeight() - 1 - tile.y, color);
}
private int colorFor(Tile tile){
int color = tile.breakable() ? tile.target().getTeam().intColor : ColorMapper.getColor(tile.block());
if(color == 0) color = ColorMapper.getColor(tile.floor());
return color;
}
@Override
public void dispose() {
pixmap.dispose();
texture.dispose();
texture = null;
pixmap = null;
}
}

View File

@ -18,6 +18,7 @@ public class DefaultKeybinds {
"shoot", Input.MOUSE_LEFT,
"zoom_hold", Input.CONTROL_LEFT,
"zoom", new Axis(Input.SCROLL),
"zoom_minimap", new Axis(Input.MINUS, Input.PLUS),
"menu", Gdx.app.getType() == ApplicationType.Android ? Input.BACK : Input.ESCAPE,
"pause", Input.SPACE,
"dash", Input.SHIFT_LEFT,

View File

@ -81,6 +81,8 @@ public class DesktopInput extends InputHandler{
zoomed = false;
}
renderer.minimap().zoomBy(-(int)Inputs.getAxisTapped("zoom_minimap"));
if(!rotated) {
rotation += Inputs.getAxis("rotate_alt");
rotated = true;

View File

@ -44,7 +44,7 @@ public class DebugFragment implements Fragment {
new table(){{
visible(() -> debug);
atop().aright();
abottom().aleft();
new table("pane"){{
defaults().fillX();

View File

@ -2,16 +2,21 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Interpolation;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.net.Net;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.actions.Actions;
import io.anuke.ucore.scene.builders.imagebutton;
import io.anuke.ucore.scene.builders.label;
import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.style.TextureRegionDrawable;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.Label;
import io.anuke.ucore.scene.ui.layout.Table;
@ -131,6 +136,36 @@ public class HudFragment implements Fragment{
visible(() -> control.tutorial().active());
}}.end();
new table(){{
visible(() -> state.is(State.playing));
atop();
aright();
new table("button"){{
margin(5);
marginBottom(10);
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion());
Image image = new Image(){
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
if(renderer.minimap().getTexture() != null){
renderer.minimap().drawEntities(x, y, width, height);
}
}
};
image.setDrawable(draw);
image.update(() -> {
if (renderer.minimap().getTexture() == null) {
draw.getRegion().setRegion(Draw.region("white"));
} else {
draw.getRegion().setRegion(renderer.minimap().getRegion());
}
});
add(image).size(140f, 140f);
}}.end();
}}.end();
//paused table
new table(){{
visible(() -> state.is(State.paused) && !Net.active());

View File

@ -325,6 +325,8 @@ public class Tile{
updateOcclusion();
}
world.notifyChanged(this);
}
@Override