Implemented drone sprite, basic AI
BIN
core/assets-raw/sprites/effects/beam-end.png
Normal file
After Width: | Height: | Size: 307 B |
BIN
core/assets-raw/sprites/effects/beam.png
Normal file
After Width: | Height: | Size: 144 B |
BIN
core/assets-raw/sprites/units/drone.png
Normal file
After Width: | Height: | Size: 319 B |
Before Width: | Height: | Size: 307 B |
Before Width: | Height: | Size: 271 B |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 107 KiB |
@ -1,13 +1,14 @@
|
||||
package io.anuke.mindustry.content;
|
||||
|
||||
import io.anuke.mindustry.entities.units.UnitType;
|
||||
import io.anuke.mindustry.entities.units.types.Vtol;
|
||||
import io.anuke.mindustry.entities.units.types.Drone;
|
||||
import io.anuke.mindustry.entities.units.types.Scout;
|
||||
import io.anuke.mindustry.entities.units.types.Vtol;
|
||||
|
||||
public class UnitTypes {
|
||||
public static final UnitType
|
||||
|
||||
drone = new Vtol(),
|
||||
drone = new Drone(),
|
||||
scout = new Scout(),
|
||||
vtol = new Vtol();
|
||||
}
|
||||
|
@ -59,9 +59,6 @@ public class ProductionBlocks {
|
||||
|
||||
plasmadrill = new Drill("plasmadrill") {{
|
||||
heatColor = Color.valueOf("ff461b");
|
||||
//TODO
|
||||
//inputLiquid = Liquids.plasma;
|
||||
//liquidRequired = true;
|
||||
drillTime = 110;
|
||||
size = 4;
|
||||
powerUse = 0.7f;
|
||||
|
@ -57,8 +57,6 @@ public class ContentLoader {
|
||||
block.init();
|
||||
}
|
||||
|
||||
//TODO 128 blocks!
|
||||
|
||||
Log.info("--- CONTENT INFO ---");
|
||||
Log.info("Blocks loaded: {0}\nItems loaded: {1}\nLiquids loaded: {2}\nUpgrades loaded: {3}\nUnits loaded: {4}\nAmmo types loaded: {5}\nStatus effects loaded: {6}\nTotal content classes: {7}",
|
||||
Block.getAllBlocks().size, Item.getAllItems().size, Liquid.getAllLiquids().size,
|
||||
|
@ -86,9 +86,7 @@ public class Renderer extends RendererModule{
|
||||
if(data instanceof Entity){
|
||||
entity.setParent((Entity)data);
|
||||
}
|
||||
}
|
||||
|
||||
if(effect instanceof GroundEffect){
|
||||
}else{
|
||||
GroundEffectEntity entity = Pools.obtain(GroundEffectEntity.class);
|
||||
entity.effect = effect;
|
||||
entity.color = color;
|
||||
@ -260,6 +258,9 @@ public class Renderer extends RendererModule{
|
||||
Graphics.shader();
|
||||
blocks.drawTeamBlocks(Layer.turret, team);
|
||||
Graphics.endShaders();
|
||||
|
||||
Entities.drawWith(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawOver);
|
||||
Entities.drawWith(playerGroup, p -> p.isFlying() == flying && p.team == team, Unit::drawOver);
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,8 +565,7 @@ public class Renderer extends RendererModule{
|
||||
drawBar(Color.SCARLET, x, y - 8f, unit.health / unit.maxhealth);
|
||||
drawBar(Color.valueOf("32cf6d"), x, y - 9f, unit.inventory.totalAmmo() / (float) unit.inventory.ammoCapacity());
|
||||
}
|
||||
|
||||
//TODO optimize!
|
||||
|
||||
public void drawBar(Color color, float x, float y, float finion){
|
||||
finion = Mathf.clamp(finion);
|
||||
|
||||
|
@ -154,6 +154,7 @@ public abstract class Unit extends SyncEntity implements SerializableEntity {
|
||||
}
|
||||
|
||||
public void drawUnder(){}
|
||||
public void drawOver(){}
|
||||
|
||||
public abstract boolean acceptsAmmo(Item item);
|
||||
public abstract void addAmmo(Item item);
|
||||
|
@ -101,6 +101,10 @@ public class BaseUnit extends Unit{
|
||||
type.drawUnder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOver(){
|
||||
type.drawOver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drawSize(){
|
||||
|
@ -33,7 +33,6 @@ public class FlyingUnitType extends UnitType {
|
||||
super.update(unit);
|
||||
|
||||
unit.rotation = unit.velocity.angle();
|
||||
unit.state.update(unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,4 +13,8 @@ public class StateMachine {
|
||||
this.state = next;
|
||||
if(next != null) next.entered(unit);
|
||||
}
|
||||
|
||||
public boolean is(UnitState state){
|
||||
return this.state == state;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||
import io.anuke.mindustry.entities.Bullet;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetEvents;
|
||||
@ -42,7 +43,7 @@ public abstract class UnitType {
|
||||
protected float drag = 0.1f;
|
||||
protected float maxVelocity = 5f;
|
||||
protected float reload = 40f;
|
||||
protected float retreatPercent = 20f;
|
||||
protected float retreatPercent = 0.2f;
|
||||
protected ObjectMap<Item, AmmoType> ammo = new ObjectMap<>();
|
||||
|
||||
public UnitType(String name){
|
||||
@ -59,12 +60,14 @@ public abstract class UnitType {
|
||||
|
||||
public abstract void draw(BaseUnit unit);
|
||||
|
||||
public void drawUnder(BaseUnit unit){}
|
||||
|
||||
public void drawOver(BaseUnit unit){}
|
||||
|
||||
public UnitState getStartState(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public void drawUnder(BaseUnit unit){}
|
||||
|
||||
public boolean isFlying(){
|
||||
return isFlying;
|
||||
}
|
||||
@ -83,6 +86,7 @@ public abstract class UnitType {
|
||||
|
||||
updateTargeting(unit);
|
||||
|
||||
unit.state.update(unit);
|
||||
unit.updateVelocityStatus(drag, maxVelocity);
|
||||
|
||||
if(unit.target != null) behavior(unit);
|
||||
@ -95,7 +99,8 @@ public abstract class UnitType {
|
||||
public abstract void behavior(BaseUnit unit);
|
||||
|
||||
public void updateTargeting(BaseUnit unit){
|
||||
if(unit.target == null || (unit.target instanceof Unit && (((Unit)unit.target).isDead() || ((Unit)unit.target).team == unit.team))){
|
||||
if(unit.target == null || (unit.target instanceof Unit && (((Unit)unit.target).isDead() || ((Unit)unit.target).team == unit.team))
|
||||
|| (unit.target instanceof TileEntity && ((TileEntity) unit.target).tile.entity == null)){
|
||||
unit.target = null;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,123 @@
|
||||
package io.anuke.mindustry.entities.units.types;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.entities.units.FlyingUnitType;
|
||||
import io.anuke.mindustry.entities.units.UnitState;
|
||||
import io.anuke.mindustry.world.BlockFlag;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Shapes;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class Drone extends FlyingUnitType {
|
||||
protected float healSpeed = 0.1f;
|
||||
protected float discoverRange = 120f;
|
||||
|
||||
public Drone(String name) {
|
||||
super(name);
|
||||
public Drone() {
|
||||
super("drone");
|
||||
speed = 0.2f;
|
||||
maxVelocity = 0.8f;
|
||||
range = 50f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(BaseUnit unit) {
|
||||
float rot = unit.rotation;
|
||||
super.update(unit);
|
||||
unit.rotation = rot;
|
||||
|
||||
if(unit.target != null && unit.state.is(repair)){
|
||||
unit.rotation = Mathf.slerpDelta(rot, unit.angleTo(unit.target), 0.3f);
|
||||
}else{
|
||||
unit.rotation = Mathf.slerpDelta(rot, unit.velocity.angle(), 0.3f);
|
||||
}
|
||||
|
||||
unit.x += Mathf.sin(Timers.time() + unit.id * 999, 25f, 0.07f);
|
||||
unit.y += Mathf.cos(Timers.time() + unit.id * 999, 25f, 0.07f);
|
||||
|
||||
if(unit.velocity.len() <= 0.2f && !(unit.state.is(repair) && unit.target != null)){
|
||||
unit.rotation += Mathf.sin(Timers.time() + unit.id * 99, 10f, 5f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void behavior(BaseUnit unit) {
|
||||
if(unit.health <= health * retreatPercent &&
|
||||
Geometry.findClosest(unit.x, unit.y, world.indexer().getAllied(unit.team, BlockFlag.repair)) != null){
|
||||
unit.setState(retreat);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnitState getStartState() {
|
||||
return repair;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOver(BaseUnit unit) {
|
||||
if(unit.target instanceof TileEntity && unit.state.is(repair)){
|
||||
float len = 5f;
|
||||
Draw.color(Color.BLACK, Color.WHITE, 0.95f + Mathf.absin(Timers.time(), 0.8f, 0.05f));
|
||||
Shapes.laser("beam", "beam-end",
|
||||
unit.x + Angles.trnsx(unit.rotation, len),
|
||||
unit.y + Angles.trnsy(unit.rotation, len),
|
||||
unit.target.x, unit.target.y);
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
public final UnitState
|
||||
|
||||
repair = new UnitState(){
|
||||
public void entered(BaseUnit unit) {
|
||||
unit.target = null;
|
||||
}
|
||||
|
||||
public void update(BaseUnit unit) {
|
||||
if(unit.target != null && (((TileEntity)unit.target).health >= ((TileEntity)unit.target).tile.block().health
|
||||
|| unit.target.distanceTo(unit) > discoverRange)){
|
||||
unit.target = null;
|
||||
}
|
||||
|
||||
if (unit.target == null) {
|
||||
if (unit.timer.get(timerTarget, 20)) {
|
||||
unit.target = Units.findAllyTile(unit.team, unit.x, unit.y, discoverRange,
|
||||
tile -> tile.entity != null && tile.entity.health + 0.0001f < tile.block().health);
|
||||
}
|
||||
}else if(unit.target.distanceTo(unit) > range){
|
||||
circle(unit, range);
|
||||
}else{
|
||||
TileEntity entity = (TileEntity) unit.target;
|
||||
entity.health += healSpeed * Timers.delta();
|
||||
entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health);
|
||||
}
|
||||
}
|
||||
},
|
||||
retreat = new UnitState() {
|
||||
public void entered(BaseUnit unit) {
|
||||
unit.target = null;
|
||||
}
|
||||
|
||||
public void update(BaseUnit unit) {
|
||||
if(unit.health >= health){
|
||||
unit.state.set(unit, attack);
|
||||
}else if(!unit.targetHasFlag(BlockFlag.repair)){
|
||||
if(unit.timer.get(timerTarget, 20)) {
|
||||
Tile target = Geometry.findClosest(unit.x, unit.y, world.indexer().getAllied(unit.team, BlockFlag.repair));
|
||||
if (target != null) unit.target = target.entity;
|
||||
}
|
||||
}else{
|
||||
circle(unit, 40f);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ public class Administration {
|
||||
public String validAdminIP;
|
||||
public Array<String> ips = new Array<>();
|
||||
public Array<String> names = new Array<>();
|
||||
public int timesKicked; //TODO not implemented!
|
||||
public int timesKicked;
|
||||
public int timesJoined;
|
||||
public int totalBlockPlaced;
|
||||
public int totalBlocksBroken;
|
||||
|
@ -1,16 +0,0 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
import io.anuke.ucore.scene.ui.Button;
|
||||
|
||||
public class PressGroup{
|
||||
private Array<Button> buttons = new Array<>();
|
||||
private boolean active = true;
|
||||
|
||||
public void add(Button button){
|
||||
//TODO make only one button in the group be clickable, add implementation
|
||||
buttons.add(button);
|
||||
}
|
||||
|
||||
}
|
@ -3,12 +3,9 @@ package io.anuke.mindustry.ui.dialogs;
|
||||
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.ui.PressGroup;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.builders.build;
|
||||
import io.anuke.ucore.scene.builders.imagebutton;
|
||||
import io.anuke.ucore.scene.ui.ImageButton;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@ -78,8 +75,6 @@ public class PausedDialog extends FloatingDialog{
|
||||
}else{
|
||||
build.begin(content());
|
||||
|
||||
PressGroup group = new PressGroup();
|
||||
|
||||
content().defaults().size(120f).pad(5);
|
||||
float isize = 14f*4;
|
||||
|
||||
@ -114,12 +109,6 @@ public class PausedDialog extends FloatingDialog{
|
||||
});
|
||||
}).text("Quit").padTop(4f);
|
||||
|
||||
for(Element e : content().getChildren()){
|
||||
if(e instanceof ImageButton){
|
||||
group.add((ImageButton)e);
|
||||
}
|
||||
}
|
||||
|
||||
build.end();
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ public class ChatFragment extends Table implements Fragment{
|
||||
|
||||
setVisible(() -> !state.is(State.menu) && Net.active());
|
||||
|
||||
//TODO put it in input?
|
||||
update(() -> {
|
||||
if(!Net.active() && chatOpen){
|
||||
hide();
|
||||
|
@ -67,9 +67,9 @@ public class DebugFragment implements Fragment {
|
||||
row();
|
||||
new button("death", () -> player.damage(99999, false));
|
||||
row();
|
||||
new button("spawn1", () -> new BaseUnit(UnitTypes.vtol, Team.red).set(player.x, player.y).add());
|
||||
new button("spawnf", () -> new BaseUnit(UnitTypes.drone, player.team).set(player.x, player.y).add());
|
||||
row();
|
||||
new button("spawn2", () -> new BaseUnit(UnitTypes.scout, Team.red).set(player.x, player.y).add());
|
||||
new button("spawng", () -> new BaseUnit(UnitTypes.scout, player.team).set(player.x, player.y).add());
|
||||
row();
|
||||
}}.end();
|
||||
|
||||
|
@ -53,8 +53,6 @@ public class Separator extends Block {
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
//TODO draw with effects such as spinning
|
||||
|
||||
@Override
|
||||
public void update(Tile tile) {
|
||||
GenericCrafterEntity entity = tile.entity();
|
||||
|