mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-30 09:30:39 +07:00
Improvements to playability at low TPS
This commit is contained in:
parent
0c7f6432d8
commit
2884e4b847
@ -6,10 +6,7 @@ import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.Texture.TextureWrap;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.FloatArray;
|
||||
import com.badlogic.gdx.utils.ObjectIntMap;
|
||||
import com.badlogic.gdx.utils.Pools;
|
||||
import com.badlogic.gdx.utils.*;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
@ -20,8 +17,8 @@ import io.anuke.mindustry.entities.traits.BelowLiquidTrait;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.graphics.*;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
@ -30,7 +27,11 @@ import io.anuke.ucore.entities.EntityDraw;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.entities.impl.BaseEntity;
|
||||
import io.anuke.ucore.entities.impl.EffectEntity;
|
||||
import io.anuke.ucore.entities.trait.DrawTrait;
|
||||
import io.anuke.ucore.entities.trait.SolidTrait;
|
||||
import io.anuke.ucore.function.Callable;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
import io.anuke.ucore.function.Predicate;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
@ -38,6 +39,7 @@ import io.anuke.ucore.graphics.Surface;
|
||||
import io.anuke.ucore.modules.RendererModule;
|
||||
import io.anuke.ucore.scene.utils.Cursors;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.ucore.core.Core.batch;
|
||||
@ -51,7 +53,9 @@ public class Renderer extends RendererModule{
|
||||
private FloatArray shieldHits = new FloatArray();
|
||||
private Array<Callable> shieldDraws = new Array<>();
|
||||
private Rectangle rect = new Rectangle(), rect2 = new Rectangle();
|
||||
private Vector2 avgPosition = new Vector2();
|
||||
private Vector2 avgPosition = new Translator();
|
||||
private Vector2 tmpVector1 = new Translator();
|
||||
private Vector2 tmpVector2 = new Translator();
|
||||
private BlockRenderer blocks = new BlockRenderer();
|
||||
private MinimapRenderer minimap = new MinimapRenderer();
|
||||
private OverlayRenderer overlays = new OverlayRenderer();
|
||||
@ -196,9 +200,9 @@ public class Renderer extends RendererModule{
|
||||
|
||||
blocks.drawFloor();
|
||||
|
||||
EntityDraw.draw(groundEffectGroup, e -> e instanceof BelowLiquidTrait);
|
||||
EntityDraw.draw(puddleGroup);
|
||||
EntityDraw.draw(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait));
|
||||
drawAndInterpolate(groundEffectGroup, e -> e instanceof BelowLiquidTrait);
|
||||
drawAndInterpolate(puddleGroup);
|
||||
drawAndInterpolate(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait));
|
||||
|
||||
blocks.processBlocks();
|
||||
blocks.drawBlocks(Layer.block);
|
||||
@ -213,7 +217,7 @@ public class Renderer extends RendererModule{
|
||||
Shaders.outline.color.set(Team.none.color);
|
||||
|
||||
Graphics.beginShaders(Shaders.outline);
|
||||
EntityDraw.draw(itemGroup);
|
||||
drawAndInterpolate(itemGroup);
|
||||
Graphics.endShaders();
|
||||
}
|
||||
|
||||
@ -224,12 +228,12 @@ public class Renderer extends RendererModule{
|
||||
|
||||
overlays.drawBottom();
|
||||
|
||||
EntityDraw.drawWith(playerGroup, p -> true, Player::drawBuildRequests);
|
||||
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
|
||||
|
||||
drawAllTeams(true);
|
||||
|
||||
EntityDraw.draw(bulletGroup);
|
||||
EntityDraw.draw(effectGroup);
|
||||
drawAndInterpolate(bulletGroup);
|
||||
drawAndInterpolate(effectGroup);
|
||||
|
||||
overlays.drawTop();
|
||||
|
||||
@ -238,7 +242,7 @@ public class Renderer extends RendererModule{
|
||||
|
||||
if(showPaths && debug) drawDebug();
|
||||
|
||||
EntityDraw.drawWith(playerGroup, p -> !p.isLocal && !p.isDead(), Player::drawName);
|
||||
drawAndInterpolate(playerGroup, p -> !p.isLocal && !p.isDead(), Player::drawName);
|
||||
|
||||
batch.end();
|
||||
}
|
||||
@ -250,25 +254,66 @@ public class Renderer extends RendererModule{
|
||||
if(group.count(p -> p.isFlying() == flying) +
|
||||
playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
|
||||
|
||||
EntityDraw.drawWith(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawUnder);
|
||||
EntityDraw.drawWith(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
|
||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawUnder);
|
||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
|
||||
|
||||
Shaders.outline.color.set(team.color);
|
||||
Shaders.mix.color.set(Color.WHITE);
|
||||
|
||||
Graphics.beginShaders(Shaders.outline);
|
||||
Graphics.shader(Shaders.mix, true);
|
||||
EntityDraw.draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying);
|
||||
EntityDraw.draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team);
|
||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying);
|
||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team);
|
||||
Graphics.shader();
|
||||
blocks.drawTeamBlocks(Layer.turret, team);
|
||||
Graphics.endShaders();
|
||||
|
||||
EntityDraw.drawWith(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawOver);
|
||||
EntityDraw.drawWith(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawOver);
|
||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group){
|
||||
drawAndInterpolate(group, t -> true, DrawTrait::draw);
|
||||
}
|
||||
|
||||
private <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group, Predicate<T> toDraw){
|
||||
drawAndInterpolate(group, toDraw, DrawTrait::draw);
|
||||
}
|
||||
|
||||
private <T extends DrawTrait> void drawAndInterpolate(EntityGroup<T> group, Predicate<T> toDraw, Consumer<T> drawer){
|
||||
EntityDraw.drawWith(group, toDraw, t -> {
|
||||
float lastx = t.getX(), lasty = t.getY(), lastrot = 0f;
|
||||
|
||||
if(threads.doInterpolate() && threads.isEnabled() && t instanceof SolidTrait){
|
||||
SolidTrait s = (SolidTrait)t;
|
||||
|
||||
lastrot = s.getRotation();
|
||||
|
||||
if(s.lastUpdated() != 0){
|
||||
float timeSinceUpdate = TimeUtils.timeSinceMillis(s.lastUpdated());
|
||||
float alpha = Math.min(timeSinceUpdate / s.updateSpacing(), 1f);
|
||||
|
||||
tmpVector1.set(s.lastPosition().x, s.lastPosition().y)
|
||||
.lerp(tmpVector2.set(lastx, lasty), alpha);
|
||||
s.setRotation(Mathf.slerp(s.lastPosition().z, lastrot, alpha));
|
||||
|
||||
s.set(tmpVector1.x, tmpVector1.y);
|
||||
}
|
||||
}
|
||||
|
||||
drawer.accept(t);
|
||||
|
||||
if(threads.doInterpolate() && threads.isEnabled()) {
|
||||
t.set(lastx, lasty);
|
||||
|
||||
if (t instanceof SolidTrait) {
|
||||
((SolidTrait) t).setRotation(lastrot);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height){
|
||||
super.resize(width, height);
|
||||
@ -284,10 +329,12 @@ public class Renderer extends RendererModule{
|
||||
}
|
||||
|
||||
public Vector2 averagePosition(){
|
||||
avgPosition.setZero();
|
||||
for(Player player : players){
|
||||
avgPosition.add(player.x, player.y);
|
||||
}
|
||||
avgPosition.setZero();
|
||||
|
||||
drawAndInterpolate(playerGroup, p -> p.isLocal, p -> {
|
||||
avgPosition.add(p.x, p.y);
|
||||
});
|
||||
|
||||
avgPosition.scl(1f / players.length);
|
||||
return avgPosition;
|
||||
}
|
||||
|
@ -111,6 +111,10 @@ public class ThreadHandler {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public boolean doInterpolate(){
|
||||
return enabled && Math.abs(Gdx.graphics.getFramesPerSecond() - getFPS()) > 15;
|
||||
}
|
||||
|
||||
public boolean isOnThread(){
|
||||
return impl.isOnThread();
|
||||
}
|
||||
@ -118,7 +122,7 @@ public class ThreadHandler {
|
||||
private void runLogic(){
|
||||
try {
|
||||
while (true) {
|
||||
long time = TimeUtils.millis();
|
||||
long time = TimeUtils.nanoTime();
|
||||
|
||||
synchronized (toRun) {
|
||||
for(Runnable r : toRun){
|
||||
@ -131,8 +135,8 @@ public class ThreadHandler {
|
||||
logic.update();
|
||||
logic.doUpdate = false;
|
||||
|
||||
long elapsed = TimeUtils.timeSinceMillis(time);
|
||||
long target = (long) (1000 / 60f);
|
||||
long elapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
|
||||
long target = (long) ((1000) / 60f);
|
||||
|
||||
delta = Math.max(elapsed, target) / 1000f * 60f;
|
||||
|
||||
|
@ -41,8 +41,6 @@ import java.io.IOException;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
private static final Vector2 movement = new Vector2();
|
||||
|
||||
public static int typeID = -1;
|
||||
|
||||
public static final int timerShootLeft = 0;
|
||||
@ -73,6 +71,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
private Tile mining;
|
||||
private CarriableTrait carrying;
|
||||
private Trail trail = new Trail(16);
|
||||
private Vector2 movement = new Vector2();
|
||||
private boolean moved;
|
||||
|
||||
public Player(){
|
||||
hitbox.setSize(5);
|
||||
@ -242,13 +242,18 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
|
||||
@Override
|
||||
public float drawSize() {
|
||||
return 40;
|
||||
return isLocal ? Float.MAX_VALUE : 40;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
if((debug && (!showPlayer || !showUI)) || dead) return;
|
||||
|
||||
if(!movement.isZero() && moved){
|
||||
walktime += Timers.delta() * movement.len()/1.6f * getFloorOn().speedMultiplier;
|
||||
baseRotation = Mathf.slerpDelta(baseRotation, movement.angle(), 0.13f);
|
||||
}
|
||||
|
||||
boolean snap = snapCamera && isLocal;
|
||||
|
||||
float px = x, py =y;
|
||||
@ -491,12 +496,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
|
||||
velocity.add(movement);
|
||||
|
||||
float prex = x, prey = y;
|
||||
updateVelocityStatus(mech.drag, debug ? speed : mech.maxSpeed);
|
||||
|
||||
if(!movement.isZero()){
|
||||
walktime += Timers.delta() * velocity.len()*(1f/0.5f)/speed * getFloorOn().speedMultiplier;
|
||||
baseRotation = Mathf.slerpDelta(baseRotation, movement.angle(), 0.13f);
|
||||
}
|
||||
moved = distanceTo(prex, prey) > 0.01f;
|
||||
|
||||
if(!isShooting()){
|
||||
if(!movement.isZero()) {
|
||||
|
@ -51,6 +51,16 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
protected float hitTime;
|
||||
protected float drownTime;
|
||||
|
||||
@Override
|
||||
public float getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotation(float rotation) {
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCarrier(CarryTrait carrier) {
|
||||
this.carrier = carrier;
|
||||
|
@ -2,6 +2,7 @@ package io.anuke.mindustry.entities.bullet;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Pools;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
@ -10,6 +11,7 @@ import io.anuke.mindustry.entities.traits.TeamTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.entities.impl.BulletEntity;
|
||||
import io.anuke.ucore.entities.trait.Entity;
|
||||
@ -59,7 +61,15 @@ public class Bullet extends BulletEntity<BulletType> implements TeamTrait, SyncT
|
||||
|
||||
bullet.team = team;
|
||||
bullet.type = type;
|
||||
bullet.set(x, y);
|
||||
|
||||
//translate bullets backwards, purely for visual reasons
|
||||
float backDelta = Timers.delta();
|
||||
|
||||
bullet.lastPosition().set(x-bullet.velocity.x * backDelta, y-bullet.velocity.y * backDelta, bullet.angle());
|
||||
bullet.setLastUpdated(TimeUtils.millis());
|
||||
bullet.setUpdateSpacing((long)((Timers.delta() / 60f) * 1000));
|
||||
bullet.set(x-bullet.velocity.x * backDelta, y-bullet.velocity.y * backDelta);
|
||||
|
||||
bullet.add();
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
package io.anuke.mindustry.entities.units;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
@ -20,7 +18,10 @@ import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -30,7 +31,6 @@ import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public abstract class BaseUnit extends Unit{
|
||||
private static int timerIndex = 0;
|
||||
private static Vector2 moveVector = new Translator();
|
||||
|
||||
protected static final int timerTarget = timerIndex++;
|
||||
protected static final int timerReload = timerIndex++;
|
||||
@ -113,7 +113,7 @@ public abstract class BaseUnit extends Unit{
|
||||
public void targetClosest(){
|
||||
if(target != null) return;
|
||||
|
||||
target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
|
||||
//target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
|
||||
}
|
||||
|
||||
public UnitState getStartState(){
|
||||
@ -236,11 +236,6 @@ public abstract class BaseUnit extends Unit{
|
||||
CallEntity.onUnitDeath(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collidesOthers() {
|
||||
return !isFlying();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void added(){
|
||||
hitbox.setSize(type.hitsize);
|
||||
|
Loading…
Reference in New Issue
Block a user