Added dynamic text, fixed issues related to low FPS
- Hacked dynamic (quickly changing) text support into Typeface - No formatting for now - Requires a proper rewrite later - Added DynamicLabel to display dynamic text - Movement friction and player controls no longer depend on framerate - Added FPS and TPS display
This commit is contained in:
parent
bfdb22f357
commit
7cc4fcbffc
@ -85,10 +85,6 @@ public class OpenGLObjectTracker {
|
||||
this.GLDeleter = GLDeleter;
|
||||
}
|
||||
|
||||
public int getHandle() {
|
||||
return referentGLhandle;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
GLDeleter.accept(referentGLhandle);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package ru.windcorp.progressia.client.graphics.font;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
import ru.windcorp.progressia.client.graphics.Colors;
|
||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||
@ -48,6 +50,12 @@ public class Font {
|
||||
) {
|
||||
return typeface.assemble(chars, style, align, maxWidth, color);
|
||||
}
|
||||
|
||||
public Renderable assembleDynamic(
|
||||
Supplier<CharSequence> supplier
|
||||
) {
|
||||
return typeface.assembleDynamic(supplier, color);
|
||||
}
|
||||
|
||||
public int getWidth(CharSequence chars, int maxWidth) {
|
||||
return typeface.getWidth(chars, style, align, maxWidth);
|
||||
|
@ -4,22 +4,29 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import glm.vec._3.Vec3;
|
||||
import gnu.trove.map.TCharObjectMap;
|
||||
import gnu.trove.map.hash.TCharObjectHashMap;
|
||||
import ru.windcorp.progressia.client.graphics.backend.Usage;
|
||||
import ru.windcorp.progressia.client.graphics.model.Face;
|
||||
import ru.windcorp.progressia.client.graphics.model.Faces;
|
||||
import ru.windcorp.progressia.client.graphics.model.Shape;
|
||||
import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper;
|
||||
import ru.windcorp.progressia.client.graphics.model.ShapeRenderProgram;
|
||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||
import ru.windcorp.progressia.client.graphics.texture.Texture;
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
|
||||
public abstract class SpriteTypeface extends Typeface {
|
||||
|
||||
|
||||
private final int height;
|
||||
private final int thickness;
|
||||
private final Vec3 shadowOffset;
|
||||
|
||||
private final TCharObjectMap<Shape> charShapes = new TCharObjectHashMap<>();
|
||||
|
||||
public SpriteTypeface(String name, int height, int thinkness) {
|
||||
super(name);
|
||||
this.height = height;
|
||||
@ -37,6 +44,11 @@ public abstract class SpriteTypeface extends Typeface {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineHeight() {
|
||||
return getHeight();
|
||||
}
|
||||
|
||||
public int getThickness() {
|
||||
return thickness;
|
||||
}
|
||||
@ -275,6 +287,11 @@ public abstract class SpriteTypeface extends Typeface {
|
||||
faces.add(copy);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Renderable assembleDynamic(Supplier<CharSequence> supplier, int color) {
|
||||
return new DynamicText(supplier, createVectorFromRGBInt(color));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getSize(
|
||||
@ -303,6 +320,21 @@ public abstract class SpriteTypeface extends Typeface {
|
||||
|
||||
return pack(resultWidth, height);
|
||||
}
|
||||
|
||||
private Shape createCharShape(char c, Vec3 color) {
|
||||
return new Shape(
|
||||
Usage.STATIC, getProgram(),
|
||||
Faces.createRectangle(
|
||||
getProgram(),
|
||||
getTexture(c),
|
||||
color,
|
||||
Vectors.ZERO_3,
|
||||
new Vec3(getWidth(c), 0, 0),
|
||||
new Vec3(0, height, 0),
|
||||
false
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO remove
|
||||
private static Vec3 createVectorFromRGBInt(int rgb) {
|
||||
@ -312,5 +344,43 @@ public abstract class SpriteTypeface extends Typeface {
|
||||
|
||||
return new Vec3(r / 256f, g / 256f, b / 256f);
|
||||
}
|
||||
|
||||
private class DynamicText implements Renderable {
|
||||
|
||||
private final Supplier<CharSequence> supplier;
|
||||
private final Vec3 color;
|
||||
|
||||
public DynamicText(Supplier<CharSequence> supplier, Vec3 color) {
|
||||
this.supplier = supplier;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(ShapeRenderHelper renderer) {
|
||||
CharSequence text = supplier.get();
|
||||
|
||||
int x = 0;
|
||||
for (int i = 0; i < text.length(); ++i) {
|
||||
char c = text.charAt(i);
|
||||
|
||||
renderer.pushTransform().translate(x, -getInterlineBuffer(), 0);
|
||||
Shape charShape = getShape(c);
|
||||
charShape.render(renderer);
|
||||
renderer.popTransform();
|
||||
|
||||
x += getWidth(c);
|
||||
}
|
||||
}
|
||||
|
||||
private Shape getShape(char c) {
|
||||
Shape shape = charShapes.get(c);
|
||||
if (shape == null) {
|
||||
shape = createCharShape(c, this.color);
|
||||
charShapes.put(c, shape);
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package ru.windcorp.progressia.client.graphics.font;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import glm.vec._2.i.Vec2i;
|
||||
import ru.windcorp.progressia.client.graphics.model.Renderable;
|
||||
import ru.windcorp.progressia.common.util.CoordinatePacker;
|
||||
@ -51,6 +53,9 @@ public abstract class Typeface extends Named {
|
||||
float align, int maxWidth,
|
||||
int color
|
||||
);
|
||||
|
||||
// TODO implement styling
|
||||
public abstract Renderable assembleDynamic(Supplier<CharSequence> supplier, int color);
|
||||
|
||||
public int getWidth(
|
||||
CharSequence chars, int style,
|
||||
@ -66,6 +71,8 @@ public abstract class Typeface extends Named {
|
||||
return getHeight(getSize(chars, style, align, maxWidth));
|
||||
}
|
||||
|
||||
public abstract int getLineHeight();
|
||||
|
||||
public Vec2i getSize(
|
||||
CharSequence chars, int style,
|
||||
float align, int maxWidth,
|
||||
|
@ -0,0 +1,36 @@
|
||||
package ru.windcorp.progressia.client.graphics.gui;
|
||||
|
||||
import glm.mat._4.Mat4;
|
||||
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
|
||||
import ru.windcorp.progressia.client.graphics.font.Font;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DynamicLabel extends Component {
|
||||
|
||||
private Font font;
|
||||
private Supplier<CharSequence> contents;
|
||||
|
||||
public DynamicLabel(String name, Font font, Supplier<CharSequence> contents, int width) {
|
||||
super(name);
|
||||
this.font = font;
|
||||
this.contents = contents;
|
||||
setPreferredSize(width, font.getHeight("", Integer.MAX_VALUE) * 2);
|
||||
}
|
||||
|
||||
public Font getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public Supplier<CharSequence> getContentSupplier() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assembleSelf(RenderTarget target) {
|
||||
target.pushTransform(new Mat4().identity().translate(getX(), getY(), -1000).scale(2));
|
||||
target.addCustomRenderer(font.assembleDynamic(getContentSupplier()));
|
||||
target.popTransform();
|
||||
}
|
||||
|
||||
}
|
@ -51,7 +51,7 @@ public class Label extends Component {
|
||||
@Override
|
||||
protected void assembleSelf(RenderTarget target) {
|
||||
target.pushTransform(
|
||||
new Mat4().identity().translate(getX(), getY(), -1000)
|
||||
new Mat4().identity().translate(getX(), getY(), -1000) // TODO wtf is this magic <---
|
||||
.scale(2)
|
||||
);
|
||||
|
||||
|
@ -176,10 +176,11 @@ public class LayerWorld extends Layer {
|
||||
|
||||
return new StaticModel(b);
|
||||
}
|
||||
|
||||
private static final float FRICTION_COEFF = Units.get("1e-5f kg/s");
|
||||
|
||||
private void tmp_applyFriction(EntityData entity, float tickLength) {
|
||||
final float frictionCoeff = Units.get(1e-5f, "kg/s");
|
||||
entity.getVelocity().mul((float) Math.exp(-frictionCoeff / entity.getCollisionMass() * tickLength));
|
||||
entity.getVelocity().mul((float) Math.exp(-FRICTION_COEFF / entity.getCollisionMass() * tickLength));
|
||||
}
|
||||
|
||||
private static final float MC_g = Units.get("32 m/s^2");
|
||||
|
@ -55,7 +55,7 @@ public class WorldData {
|
||||
}
|
||||
|
||||
public void tmp_generate() {
|
||||
final int size = 3;
|
||||
final int size = 2;
|
||||
Vec3i cursor = new Vec3i(0, 0, 0);
|
||||
|
||||
for (cursor.x = -(size / 2); cursor.x <= (size / 2); ++cursor.x) {
|
||||
|
@ -126,6 +126,10 @@ public class Server {
|
||||
return this.serverThread.getTicker().getTickLength();
|
||||
}
|
||||
|
||||
public double getTPS() {
|
||||
return this.serverThread.getTicker().getTPS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link WorldAccessor} object for this server. Use the provided accessor to
|
||||
* request common {@link Evaluation}s and {@link Change}s.
|
||||
|
@ -49,6 +49,10 @@ public class TickerCoordinator {
|
||||
|
||||
private final AtomicInteger workingTickers = new AtomicInteger();
|
||||
|
||||
private boolean isTickStartSet = false;
|
||||
private long tickStart = -1;
|
||||
private double tickLength = 1.0 / 20; // Do something about it
|
||||
|
||||
private final Logger logger = LogManager.getLogger("Ticker Coordinator");
|
||||
|
||||
public TickerCoordinator(Server server, int tickers) {
|
||||
@ -97,8 +101,23 @@ public class TickerCoordinator {
|
||||
}
|
||||
|
||||
public double getTickLength() {
|
||||
// TODO implement
|
||||
return Units.SECONDS / 20;
|
||||
return tickLength;
|
||||
}
|
||||
|
||||
public double getTPS() {
|
||||
return 1 / tickLength;
|
||||
}
|
||||
|
||||
private void onTickStart() {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (isTickStartSet) {
|
||||
tickLength = (now - tickStart) * Units.MILLISECONDS;
|
||||
} else {
|
||||
isTickStartSet = true;
|
||||
}
|
||||
|
||||
tickStart = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -107,6 +126,7 @@ public class TickerCoordinator {
|
||||
|
||||
public void runOneTick() {
|
||||
try {
|
||||
onTickStart();
|
||||
|
||||
int passes = 0;
|
||||
|
||||
|
@ -19,14 +19,18 @@ package ru.windcorp.progressia.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.font.Font;
|
||||
import ru.windcorp.progressia.client.graphics.gui.DynamicLabel;
|
||||
import ru.windcorp.progressia.client.graphics.gui.GUILayer;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Label;
|
||||
import ru.windcorp.progressia.client.graphics.gui.Panel;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
|
||||
public class LayerTestGUI extends GUILayer {
|
||||
|
||||
@ -57,7 +61,23 @@ public class LayerTestGUI extends GUILayer {
|
||||
() -> String.format("Gravity: %9s (G)", TestPlayerControls.getInstance().useMinecraftGravity() ? "Minecraft" : "Realistic")
|
||||
));
|
||||
|
||||
panel.getChildren().forEach(c -> labels.add((Label) c));
|
||||
panel.addChild(new DynamicLabel(
|
||||
"FPSDisplay", new Font().withColor(0x37A3E6).deriveShadow(),
|
||||
() -> String.format(Locale.US, "FPS: %5.1f", GraphicsInterface.getFPS()),
|
||||
128
|
||||
));
|
||||
|
||||
panel.addChild(new DynamicLabel(
|
||||
"TPSDisplay", new Font().withColor(0x37A3E6).deriveShadow(),
|
||||
() -> ServerState.getInstance() == null ? "TPS: n/a" : String.format(Locale.US, "TPS: %5.1f", ServerState.getInstance().getTPS()),
|
||||
128
|
||||
));
|
||||
|
||||
panel.getChildren().forEach(c -> {
|
||||
if (c instanceof Label) {
|
||||
labels.add((Label) c);
|
||||
}
|
||||
});
|
||||
TestPlayerControls.getInstance().setUpdateCallback(() -> labels.forEach(Label::update));
|
||||
|
||||
getRoot().addChild(panel);
|
||||
|
@ -35,13 +35,13 @@ public class TestPlayerControls {
|
||||
private static final float FLYING_SPEED = 6.0f * Units.METERS_PER_SECOND;
|
||||
|
||||
// (0; 1], 1 is instant change, 0 is no control authority
|
||||
private static final float FLYING_CONTROL_AUTHORITY = 0.05f;
|
||||
private static final float FLYING_CONTROL_AUTHORITY = Units.get("2 1/s");
|
||||
|
||||
// Horizontal and vertical max control speed when walking
|
||||
private static final float WALKING_SPEED = 4.0f * Units.METERS_PER_SECOND;
|
||||
|
||||
// (0; 1], 1 is instant change, 0 is no control authority
|
||||
private static final float WALKING_CONTROL_AUTHORITY = 0.1f;
|
||||
private static final float WALKING_CONTROL_AUTHORITY = Units.get("15 1/s");
|
||||
|
||||
// Vertical velocity instantly add to player when they jump
|
||||
private static final float JUMP_VELOCITY = 5f * Units.METERS_PER_SECOND;
|
||||
@ -66,28 +66,36 @@ public class TestPlayerControls {
|
||||
|
||||
EntityData player = getEntity();
|
||||
|
||||
Mat3 angMat = new Mat3().identity().rotateZ(player.getYaw());
|
||||
Vec3 movement = new Vec3(movementForward, -movementRight, 0);
|
||||
|
||||
if (movementForward != 0 && movementRight != 0) {
|
||||
movement.normalize();
|
||||
}
|
||||
|
||||
angMat.mul_(movement); // bug in jglm, .mul() and mul_() are swapped
|
||||
final float speed, authority;
|
||||
|
||||
if (isFlying) {
|
||||
movement.z = movementUp;
|
||||
movement.mul(FLYING_SPEED);
|
||||
movement.sub(player.getVelocity());
|
||||
movement.mul(FLYING_CONTROL_AUTHORITY);
|
||||
speed = FLYING_SPEED;
|
||||
authority = FLYING_CONTROL_AUTHORITY;
|
||||
} else {
|
||||
movement.mul(WALKING_SPEED);
|
||||
movement.sub(player.getVelocity());
|
||||
movement.mul(WALKING_CONTROL_AUTHORITY);
|
||||
movement.z = 0;
|
||||
speed = WALKING_SPEED;
|
||||
authority = WALKING_CONTROL_AUTHORITY;
|
||||
}
|
||||
|
||||
player.getVelocity().add(movement);
|
||||
Mat3 angMat = new Mat3().identity().rotateZ(player.getYaw());
|
||||
Vec3 desiredVelocity = new Vec3(movementForward, -movementRight, 0);
|
||||
|
||||
if (movementForward != 0 && movementRight != 0) desiredVelocity.normalize();
|
||||
angMat.mul_(desiredVelocity); // bug in jglm, .mul() and mul_() are swapped
|
||||
desiredVelocity.z = movementUp;
|
||||
desiredVelocity.mul(speed);
|
||||
|
||||
Vec3 change = new Vec3()
|
||||
.set(desiredVelocity)
|
||||
.sub(player.getVelocity())
|
||||
.mul((float) Math.exp(-authority * GraphicsInterface.getFrameLength()))
|
||||
.negate()
|
||||
.add(desiredVelocity);
|
||||
|
||||
if (!isFlying) {
|
||||
change.z = player.getVelocity().z;
|
||||
}
|
||||
|
||||
player.getVelocity().set(change);
|
||||
}
|
||||
|
||||
public void handleInput(Input input) {
|
||||
@ -233,11 +241,11 @@ public class TestPlayerControls {
|
||||
);
|
||||
}
|
||||
|
||||
private EntityData getEntity() {
|
||||
public EntityData getEntity() {
|
||||
return getPlayer().getEntity();
|
||||
}
|
||||
|
||||
private LocalPlayer getPlayer() {
|
||||
public LocalPlayer getPlayer() {
|
||||
return ClientState.getInstance().getLocalPlayer();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user