Major refactoring of building, sound, inventory

This commit is contained in:
Anuken
2018-05-20 17:59:52 -04:00
parent de40df7f7b
commit c1a5482ad2
40 changed files with 348 additions and 991 deletions
@@ -0,0 +1,154 @@
package io.anuke.mindustry.entities;
import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.types.BuildBlock;
import io.anuke.mindustry.world.blocks.types.BuildBlock.BuildEntity;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Translator;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.world;
/**Interface for units that build thing.*/
public interface BlockBuilder {
//temporary static final values
Translator[] tmptr = {new Translator(), new Translator(), new Translator(), new Translator()};
float placeDistance = 80f;
/**Returns the queue for storing build requests.*/
Queue<BuildRequest> getPlaceQueue();
/**Clears the placement queue.*/
default void clearBuilding(){
getPlaceQueue().clear();
}
/**Add another build requests to the tail of the queue.*/
default void addBuildRequest(BuildRequest place){
getPlaceQueue().addLast(place);
}
/**Return the build requests currently active, or the one at the top of the queue.
* May return null.*/
default BuildRequest getCurrentRequest(){
return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
}
/**Update building mechanism for this unit.*/
default void updateBuilding(Unit unit){
BuildRequest current = getCurrentRequest();
if(current == null) return; //nothing to do here
Tile tile = world.tile(current.x, current.y);
if(unit.distanceTo(tile) > placeDistance) { //out of range, skip it.
getPlaceQueue().removeFirst();
}else if(current.remove){
if(Build.validBreak(unit.team, current.x, current.y)){ //if it's valid, break it
current.removeProgress += 1f / tile.getBreakTime();
if(current.removeProgress >= 1f){
Build.breakBlock(unit.team, current.x, current.y, true, true);
}
}else{
//otherwise, skip it
getPlaceQueue().removeFirst();
}
}else{
if (!(tile.block() instanceof BuildBlock)) { //check if haven't started placing
if(Build.validPlace(unit.team, current.x, current.y, current.recipe.result, current.rotation)){
//if it's valid, place it
Build.placeBlock(unit.team, current.x, current.y, current.recipe, current.rotation);
}else{
//otherwise, skip it
getPlaceQueue().removeFirst();
}
}else{
//otherwise, update it.
BuildEntity entity = tile.entity();
entity.progress += 1f / entity.recipe.cost;
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
}
}
}
/**Draw placement effects for an entity.*/
default void drawBuilding(Unit unit){
Tile tile = world.tile(getCurrentRequest().x, getCurrentRequest().y);
Draw.color(unit.distanceTo(tile) > placeDistance ? "placeInvalid" : "accent");
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
float sz = Vars.tilesize*tile.block().size/2f;
float ang = unit.angleTo(tile);
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang),
Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang)));
float x1 = tmptr[0].x, y1 = tmptr[0].y,
x3 = tmptr[1].x, y3 = tmptr[1].y;
Translator close = Geometry.findClosest(unit.x, unit.y, tmptr);
float x2 = close.x, y2 = close.y;
Draw.alpha(0.3f + Mathf.absin(Timers.time(), 0.9f, 0.2f));
Fill.tri(px, py, x2, y2, x1, y1);
Fill.tri(px, py, x2, y2, x3, y3);
Draw.alpha(1f);
Lines.line(px, py, x1, y1);
Lines.line(px, py, x3, y3);
Fill.circle(px, py, 1.5f + Mathf.absin(Timers.time(), 1f, 1.8f));
Draw.color();
}
/**Class for storing build requests. Can be either a place or remove request.*/
class BuildRequest {
public final int x, y, rotation;
public final Recipe recipe;
public final boolean remove;
float removeProgress;
/**This creates a build request.*/
public BuildRequest(int x, int y, int rotation, Recipe recipe) {
this.x = x;
this.y = y;
this.rotation = rotation;
this.recipe = recipe;
this.remove = false;
}
/**This creates a remove request.*/
public BuildRequest(int x, int y) {
this.x = x;
this.y = y;
this.rotation = -1;
this.recipe = null;
this.remove = true;
}
}
}
@@ -1,21 +0,0 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.resource.Recipe;
public interface BlockPlacer {
void addPlaceBlock(PlaceRequest place);
Team getTeam();
class PlaceRequest{
public final int x, y, rotation;
public final Recipe recipe;
public PlaceRequest(int x, int y, int rotation, Recipe recipe) {
this.x = x;
this.y = y;
this.rotation = rotation;
this.recipe = recipe;
}
}
}
@@ -10,6 +10,8 @@ import io.anuke.ucore.function.Callable;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
/**This class should not be used anymore, as the animation does not fit the style well.*/
@Deprecated
public class ItemAnimationEffect extends TimedEntity {
private static final float size = 5f;
+54 -108
View File
@@ -1,10 +1,11 @@
package io.anuke.mindustry.entities;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Pools;
import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.Mechs;
import io.anuke.mindustry.content.Weapons;
import io.anuke.mindustry.content.fx.ExplosionFx;
@@ -14,18 +15,11 @@ import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.*;
import io.anuke.mindustry.world.Placement;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.types.BuildBlock;
import io.anuke.mindustry.world.blocks.types.BuildBlock.BuildEntity;
import io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.*;
@@ -33,17 +27,13 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.*;
public class Player extends Unit implements BlockPlacer{
static final float speed = 1.1f;
static final float dashSpeed = 1.8f;
public static final float placeDistance = 80f;
static final int timerRegen = 3;
static final Translator[] tmptr = {new Translator(), new Translator(), new Translator(), new Translator()};
public class Player extends Unit implements BlockBuilder {
private static final float speed = 1.1f;
private static final float dashSpeed = 1.8f;
private static final Vector2 movement = new Vector2();
public String name = "name";
public String uuid;
@@ -61,12 +51,10 @@ public class Player extends Unit implements BlockPlacer{
public int playerIndex = 0;
public boolean isLocal = false;
public Timer timer = new Timer(4);
public float walktime;
public float respawntime;
private Queue<PlaceRequest> placeQueue = new Queue<>();
private Tile currentPlace;
private Vector2 movement = new Vector2();
private float walktime;
private float respawntime;
private Queue<BuildRequest> placeQueue = new Queue<>();
public Player(){
hitbox.setSize(5);
@@ -110,11 +98,6 @@ public class Player extends Unit implements BlockPlacer{
}
}
@Override
public void addPlaceBlock(PlaceRequest req){
placeQueue.addFirst(req);
}
@Override
public boolean collides(SolidEntity other){
return !isDead() && super.collides(other) && !mech.flying;
@@ -227,45 +210,49 @@ public class Player extends Unit implements BlockPlacer{
@Override
public void drawOver(){
if(!isShooting() && currentPlace != null) {
Draw.color(distanceTo(currentPlace) > placeDistance ? "placeInvalid" : "accent");
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
float px = x + Angles.trnsx(rotation, focusLen);
float py = y + Angles.trnsy(rotation, focusLen);
Tile tile = currentPlace;
float sz = Vars.tilesize*tile.block().size/2f;
float ang = angleTo(tile);
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(x, y, a.x, a.y), ang),
Angles.angleDist(Angles.angle(x, y, b.x, b.y), ang)));
float x1 = tmptr[0].x, y1 = tmptr[0].y,
x3 = tmptr[1].x, y3 = tmptr[1].y;
Translator close = Geometry.findClosest(x, y, tmptr);
float x2 = close.x, y2 = close.y;
Draw.alpha(0.3f + Mathf.absin(Timers.time(), 0.9f, 0.2f));
Fill.tri(px, py, x2, y2, x1, y1);
Fill.tri(px, py, x2, y2, x3, y3);
Draw.alpha(1f);
Lines.line(px, py, x1, y1);
Lines.line(px, py, x3, y3);
Fill.circle(px, py, 1.5f + Mathf.absin(Timers.time(), 1f, 1.8f));
Draw.color();
if(!isShooting() && getCurrentRequest() != null) {
drawBuilding(this);
}
}
public void drawName(){
GlyphLayout layout = Pools.obtain(GlyphLayout.class);
Draw.tscl(0.25f/2);
layout.setText(Core.font, name);
Draw.color(0f, 0f, 0f, 0.3f);
Draw.rect("blank", getDrawPosition().x, getDrawPosition().y + 8 - layout.height/2, layout.width + 2, layout.height + 2);
Draw.color();
Draw.tcolor(color);
Draw.text(name, getDrawPosition().x, getDrawPosition().y + 8);
if(isAdmin){
Draw.color(color);
float s = 3f;
Draw.rect("icon-admin-small", getDrawPosition().x + layout.width/2f + 2 + 1, getDrawPosition().y + 7f, s, s);
}
Draw.reset();
Pools.free(layout);
Draw.tscl(fontscale);
}
public void drawBuildRequests(){
for (BuildRequest request : getPlaceQueue()) {
if(request.remove){
Draw.color("placeInvalid");
Tile tile = world.tile(request.x, request.y);
Lines.poly(tile.drawx(), tile.drawy(),
4, tile.block().size * tilesize /2f + Mathf.absin(Timers.time(), 3f, 1f));
}else{
Draw.color("accent");
Lines.poly(request.x * tilesize + request.recipe.result.getPlaceOffset().x,
request.y * tilesize + request.recipe.result.getPlaceOffset().y,
4, request.recipe.result.size * tilesize /2f + Mathf.absin(Timers.time(), 3f, 1f));
}
}
}
@Override
public void update(){
@@ -300,6 +287,7 @@ public class Player extends Unit implements BlockPlacer{
y = Mathf.clamp(y, 0, world.height() * tilesize);
}
/**Resets all values of the player.*/
public void reset(){
weapon = Weapons.blaster;
team = Team.blue;
@@ -316,12 +304,11 @@ public class Player extends Unit implements BlockPlacer{
return control.input(playerIndex).canShoot() && control.input(playerIndex).isShooting() && inventory.hasAmmo();
}
public Queue<PlaceRequest> getPlaceQueue(){
public Queue<BuildRequest> getPlaceQueue(){
return placeQueue;
}
protected void updateMech(){
Tile tile = world.tileWorld(x, y);
//if player is in solid block
@@ -330,29 +317,7 @@ public class Player extends Unit implements BlockPlacer{
}
if(!isShooting()) {
//update placing queue
if(currentPlace != null) {
Tile check = currentPlace;
if (!(check.block() instanceof BuildBlock)) {
currentPlace = null;
}else if(distanceTo(check) <= placeDistance){
BuildEntity entity = check.entity();
entity.progress += 1f / entity.recipe.cost;
rotation = Mathf.slerpDelta(rotation, angleTo(entity), 0.4f);
}
}else if(placeQueue.size > 0){
PlaceRequest check = placeQueue.last();
if(distanceTo(world.tile(check.x, check.y)) <= placeDistance &&
Placement.validPlace(team, check.x, check.y, check.recipe.result, check.rotation)){
placeQueue.removeLast();
Placement.placeBlock(team, check.x, check.y, check.recipe, check.rotation, true, true);
currentPlace = world.tile(check.x, check.y);
}
}
updateBuilding(this);
}
if(ui.chatfrag.chatOpen()) return;
@@ -365,11 +330,6 @@ public class Player extends Unit implements BlockPlacer{
speed *= ((1f-carrySlowdown) + (inventory.hasItem() ? (float)inventory.getItem().amount/inventory.capacity(): 1f) * carrySlowdown);
if(health < maxhealth && timer.get(timerRegen, 20))
health ++;
health = Mathf.clamp(health, -1, maxhealth);
movement.set(0, 0);
String section = "player_" + (playerIndex + 1);
@@ -524,18 +484,4 @@ public class Player extends Unit implements BlockPlacer{
interpolator.read(this.x, this.y, x, y, rot, baseRot, time);
}
@Override
public void interpolate() {
super.interpolate();
Interpolator i = interpolator;
float tx = x + Angles.trnsx(rotation + 180f, 4f);
float ty = y + Angles.trnsy(rotation + 180f, 4f);
}
public Color getColor(){
return color;
}
}
@@ -3,12 +3,13 @@ package io.anuke.mindustry.entities;
import com.badlogic.gdx.math.Vector2;
import io.anuke.ucore.util.Mathf;
/**Class for predicting shoot angles based on velocities of targets.*/
public class Predict {
private static Vector2 vec = new Vector2();
private static Vector2 vresult = new Vector2();
/**Returns resulting predicted vector.
* Don't call from multiple threads, ever.*/
* Don't call from multiple threads.*/
public static Vector2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v) {
float tx = dstx - srcx,
ty = dsty - srcy,
@@ -37,7 +38,6 @@ public class Predict {
return sol;
}
private static Vector2 quad(float a, float b, float c) {
Vector2 sol = null;
if (Math.abs(a) < 1e-6) {
@@ -3,6 +3,7 @@ package io.anuke.mindustry.entities;
import io.anuke.mindustry.content.StatusEffects;
import io.anuke.ucore.core.Timers;
/**Class for controlling status effects on an entity.*/
public class StatusController {
private static final TransitionResult globalResult = new TransitionResult();