Added gravity and refactored player controls
- Added gravity (still testing) - Two modes: realistic (9.8 m/s^2) and Minecraft (32 m/s^2) - Switch with G - Changing (0; 0; 0) rebound to H - Added walking controls - Minecraft-style - WIP - LayerTestGUI now displays dev options - Added Units
This commit is contained in:
parent
9c894215f8
commit
154cc0a3b8
@ -3,10 +3,10 @@ package ru.windcorp.progressia.client;
|
||||
import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel;
|
||||
import ru.windcorp.progressia.client.graphics.GUI;
|
||||
import ru.windcorp.progressia.client.graphics.flat.LayerTestUI;
|
||||
import ru.windcorp.progressia.client.graphics.gui.LayerTestGUI;
|
||||
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
|
||||
import ru.windcorp.progressia.common.world.WorldData;
|
||||
import ru.windcorp.progressia.server.ServerState;
|
||||
import ru.windcorp.progressia.test.LayerTestGUI;
|
||||
|
||||
public class ClientState {
|
||||
|
||||
|
@ -1,125 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.progressia.client.graphics.gui;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import glm.vec._2.i.Vec2i;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import ru.windcorp.progressia.client.graphics.Colors;
|
||||
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
|
||||
import ru.windcorp.progressia.client.graphics.font.Font;
|
||||
import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.localization.Localizer;
|
||||
import ru.windcorp.progressia.client.localization.MutableString;
|
||||
import ru.windcorp.progressia.client.localization.MutableStringLocalized;
|
||||
|
||||
public class LayerTestGUI extends GUILayer {
|
||||
|
||||
private static class DebugComponent extends Component {
|
||||
private final int color;
|
||||
|
||||
public DebugComponent(String name, Vec2i size, int color) {
|
||||
super(name);
|
||||
this.color = color;
|
||||
|
||||
setPreferredSize(size);
|
||||
|
||||
addListener(new Object() {
|
||||
@Subscribe
|
||||
public void onHoverChanged(HoverEvent e) {
|
||||
requestReassembly();
|
||||
}
|
||||
});
|
||||
|
||||
addListener(KeyEvent.class, this::onClicked);
|
||||
}
|
||||
|
||||
private boolean onClicked(KeyEvent event) {
|
||||
if (!event.isMouse()) {
|
||||
return false;
|
||||
} else if (event.isPress() && event.isLeftMouseButton()) {
|
||||
System.out.println("You pressed a Component!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assembleSelf(RenderTarget target) {
|
||||
target.fill(getX(), getY(), getWidth(), getHeight(), Colors.BLACK);
|
||||
|
||||
target.fill(
|
||||
getX() + 2, getY() + 2,
|
||||
getWidth() - 4, getHeight() - 4,
|
||||
isHovered() ? Colors.DEBUG_YELLOW : color
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public LayerTestGUI() {
|
||||
super("LayerTestGui", new LayoutAlign(1, 0.75, 5));
|
||||
|
||||
Panel panel = new Panel("Alex", new LayoutVertical(5));
|
||||
|
||||
panel.addChild(new DebugComponent("Bravo", new Vec2i(200, 100), 0x44FF44));
|
||||
|
||||
Component charlie = new DebugComponent("Charlie", null, 0x222222);
|
||||
charlie.setLayout(new LayoutVertical(5));
|
||||
|
||||
//Debug
|
||||
Localizer.getInstance().setLanguage("ru-RU");
|
||||
MutableString epsilon = new MutableStringLocalized("Epsilon")
|
||||
.addListener(() -> ((Label)charlie.getChild(0)).update()).format(34, "thirty-four");
|
||||
// These two are swapped in code due to a bug in layouts, fixing ATM
|
||||
charlie.addChild(
|
||||
new Label(
|
||||
"Delta",
|
||||
new Font().withColor(0xCCBB44).deriveShadow().deriveBold(),
|
||||
"Пре-альфа!"
|
||||
)
|
||||
);
|
||||
charlie.addChild(
|
||||
new Label(
|
||||
"Epsilon",
|
||||
new Font().withColor(0x4444BB).deriveItalic(),
|
||||
() -> epsilon.get().concat("\u269b")
|
||||
)
|
||||
);
|
||||
panel.addChild(charlie);
|
||||
|
||||
|
||||
charlie.addListener(KeyEvent.class, e -> {
|
||||
if(e.isPress() && e.getKey() == GLFW.GLFW_KEY_L) {
|
||||
Localizer localizer = Localizer.getInstance();
|
||||
if (localizer.getLanguage().equals("ru-RU")) {
|
||||
localizer.setLanguage("en-US");
|
||||
} else {
|
||||
localizer.setLanguage("ru-RU");
|
||||
}
|
||||
return true;
|
||||
} return false;
|
||||
});
|
||||
charlie.setFocusable(true);
|
||||
charlie.takeFocus();
|
||||
|
||||
getRoot().addChild(panel);
|
||||
}
|
||||
|
||||
}
|
@ -271,6 +271,10 @@ public class Camera {
|
||||
currentModeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentModeIndex() {
|
||||
return currentModeIndex;
|
||||
}
|
||||
|
||||
public float getLastAnchorYaw() {
|
||||
return lastAnchorYaw;
|
||||
|
@ -20,41 +20,27 @@ package ru.windcorp.progressia.client.graphics.world;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import glm.Glm;
|
||||
import glm.mat._3.Mat3;
|
||||
import glm.vec._2.Vec2;
|
||||
import glm.vec._3.Vec3;
|
||||
import ru.windcorp.progressia.client.Client;
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
import ru.windcorp.progressia.client.comms.controls.InputBasedControls;
|
||||
import ru.windcorp.progressia.client.graphics.Layer;
|
||||
import ru.windcorp.progressia.client.graphics.backend.FaceCulling;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
import ru.windcorp.progressia.common.Units;
|
||||
import ru.windcorp.progressia.common.collision.Collideable;
|
||||
import ru.windcorp.progressia.common.collision.colliders.Collider;
|
||||
import ru.windcorp.progressia.common.util.FloatMathUtils;
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||
import ru.windcorp.progressia.test.CollisionModelRenderer;
|
||||
import ru.windcorp.progressia.test.TestPlayerControls;
|
||||
|
||||
public class LayerWorld extends Layer {
|
||||
|
||||
private final Mat3 angMat = new Mat3();
|
||||
|
||||
private int movementForward = 0;
|
||||
private int movementRight = 0;
|
||||
private int movementUp = 0;
|
||||
|
||||
private final WorldRenderHelper helper = new WorldRenderHelper();
|
||||
|
||||
private final Client client;
|
||||
private final InputBasedControls inputBasedControls;
|
||||
private final TestPlayerControls tmp_testControls = TestPlayerControls.getInstance();
|
||||
|
||||
public LayerWorld(Client client) {
|
||||
super("World");
|
||||
@ -75,40 +61,12 @@ public class LayerWorld extends Layer {
|
||||
|
||||
@Override
|
||||
protected void doRender() {
|
||||
if (client.getLocalPlayer() != null) {
|
||||
tmp_handleControls();
|
||||
}
|
||||
|
||||
Camera camera = client.getCamera();
|
||||
if (camera.hasAnchor()) {
|
||||
renderWorld();
|
||||
}
|
||||
}
|
||||
|
||||
private void tmp_handleControls() {
|
||||
EntityData player = client.getLocalPlayer();
|
||||
|
||||
angMat.identity().rotateZ(player.getYaw());
|
||||
|
||||
Vec3 movement = Vectors.grab3();
|
||||
|
||||
// Horizontal and vertical max control speed
|
||||
final float movementSpeed = 0.1f * 60.0f;
|
||||
// (0; 1], 1 is instant change, 0 is no control authority
|
||||
final float controlAuthority = 0.1f;
|
||||
|
||||
movement.set(movementForward, -movementRight, 0);
|
||||
if (movementForward != 0 && movementRight != 0) movement.normalize();
|
||||
angMat.mul_(movement); // bug in jglm, .mul() and mul_() are swapped
|
||||
movement.z = movementUp;
|
||||
movement.mul(movementSpeed);
|
||||
movement.sub(player.getVelocity());
|
||||
movement.mul(controlAuthority);
|
||||
player.getVelocity().add(movement);
|
||||
|
||||
Vectors.release(movement);
|
||||
}
|
||||
|
||||
private void renderWorld() {
|
||||
client.getCamera().apply(helper);
|
||||
FaceCulling.push(true);
|
||||
@ -127,11 +85,16 @@ public class LayerWorld extends Layer {
|
||||
private static final boolean RENDER_COLLISION_MODELS = false;
|
||||
|
||||
private void tmp_doEveryFrame() {
|
||||
float tickLength = (float) GraphicsInterface.getFrameLength();
|
||||
|
||||
try {
|
||||
tmp_performCollisions();
|
||||
tmp_performCollisions(tickLength);
|
||||
|
||||
tmp_testControls.applyPlayerControls();
|
||||
|
||||
for (EntityData data : this.client.getWorld().getData().getEntities()) {
|
||||
tmp_applyFriction(data);
|
||||
tmp_applyGravity(data, tickLength);
|
||||
tmp_renderCollisionModel(data);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
@ -147,121 +110,47 @@ public class LayerWorld extends Layer {
|
||||
}
|
||||
}
|
||||
|
||||
private void tmp_performCollisions() {
|
||||
private void tmp_performCollisions(float tickLength) {
|
||||
tmp_collideableList.clear();
|
||||
tmp_collideableList.addAll(this.client.getWorld().getData().getEntities());
|
||||
|
||||
Collider.performCollisions(
|
||||
tmp_collideableList,
|
||||
this.client.getWorld().getData(),
|
||||
(float) GraphicsInterface.getFrameLength(),
|
||||
tickLength,
|
||||
tmp_colliderWorkspace
|
||||
);
|
||||
}
|
||||
|
||||
private void tmp_applyFriction(EntityData entity) {
|
||||
final float frictionCoeff = 1 - 1e-2f;
|
||||
final float frictionCoeff = 1 - 1e-5f;
|
||||
entity.getVelocity().mul(frictionCoeff);
|
||||
}
|
||||
|
||||
private void tmp_applyGravity(EntityData entity, float tickLength) {
|
||||
if (ClientState.getInstance().getLocalPlayer() == entity && tmp_testControls.isFlying()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final float gravitationalAcceleration;
|
||||
|
||||
if (tmp_testControls.useMinecraftGravity()) {
|
||||
gravitationalAcceleration = 32f * Units.METERS_PER_SECOND_SQUARED; // plz dont sue me M$
|
||||
} else {
|
||||
gravitationalAcceleration = 9.81f * Units.METERS_PER_SECOND_SQUARED;
|
||||
}
|
||||
entity.getVelocity().add(0, 0, -gravitationalAcceleration * tickLength);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleInput(Input input) {
|
||||
if (input.isConsumed()) return;
|
||||
|
||||
InputEvent event = input.getEvent();
|
||||
|
||||
if (event instanceof KeyEvent) {
|
||||
if (onKeyEvent((KeyEvent) event)) {
|
||||
input.consume();
|
||||
}
|
||||
} else if (event instanceof CursorMoveEvent) {
|
||||
onMouseMoved((CursorMoveEvent) event);
|
||||
input.consume();
|
||||
}
|
||||
tmp_testControls.handleInput(input);
|
||||
|
||||
if (!input.isConsumed()) {
|
||||
inputBasedControls.handleInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean flag = true;
|
||||
|
||||
private boolean onKeyEvent(KeyEvent event) {
|
||||
if (event.isRepeat()) return false;
|
||||
|
||||
int multiplier = event.isPress() ? 1 : -1;
|
||||
|
||||
switch (event.getKey()) {
|
||||
case GLFW.GLFW_KEY_W:
|
||||
movementForward += +1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
movementForward += -1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_A:
|
||||
movementRight += -1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_D:
|
||||
movementRight += +1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_SPACE:
|
||||
movementUp += +1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_LEFT_SHIFT:
|
||||
movementUp += -1 * multiplier;
|
||||
break;
|
||||
|
||||
case GLFW.GLFW_KEY_ESCAPE:
|
||||
if (!event.isPress()) return false;
|
||||
|
||||
if (flag) {
|
||||
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
|
||||
} else {
|
||||
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
|
||||
}
|
||||
|
||||
flag = !flag;
|
||||
break;
|
||||
|
||||
case GLFW.GLFW_KEY_F5:
|
||||
if (!event.isPress()) return false;
|
||||
|
||||
if (client.getCamera().hasAnchor()) {
|
||||
client.getCamera().selectNextMode();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onMouseMoved(CursorMoveEvent event) {
|
||||
if (!flag) return;
|
||||
|
||||
final float yawScale = -0.002f;
|
||||
final float pitchScale = yawScale;
|
||||
|
||||
EntityData player = client.getLocalPlayer();
|
||||
|
||||
if (player != null) {
|
||||
normalizeAngles(player.getDirection().add(
|
||||
(float) (event.getChangeX() * yawScale),
|
||||
(float) (event.getChangeY() * pitchScale)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizeAngles(Vec2 dir) {
|
||||
// Normalize yaw
|
||||
dir.x = FloatMathUtils.normalizeAngle(dir.x);
|
||||
|
||||
// Clamp pitch
|
||||
dir.y = Glm.clamp(
|
||||
dir.y, -FloatMathUtils.PI_F/2, +FloatMathUtils.PI_F/2
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
56
src/main/java/ru/windcorp/progressia/common/Units.java
Normal file
56
src/main/java/ru/windcorp/progressia/common/Units.java
Normal file
@ -0,0 +1,56 @@
|
||||
package ru.windcorp.progressia.common;
|
||||
|
||||
public class Units {
|
||||
|
||||
// Base units
|
||||
// We're SI.
|
||||
public static final float METERS = 1;
|
||||
public static final float KILOGRAMS = 1;
|
||||
public static final float SECONDS = 1;
|
||||
|
||||
// Length
|
||||
public static final float CENTIMETERS = METERS / 100;
|
||||
public static final float MILLIMETERS = METERS / 1000;
|
||||
public static final float KILOMETERS = METERS * 1000;
|
||||
|
||||
// Surface
|
||||
public static final float SQUARE_CENTIMETERS = CENTIMETERS * CENTIMETERS;
|
||||
public static final float SQUARE_METERS = METERS * METERS;
|
||||
public static final float SQUARE_MILLIMETERS = MILLIMETERS * MILLIMETERS;
|
||||
public static final float SQUARE_KILOMETERS = KILOMETERS * KILOMETERS;
|
||||
|
||||
// Volume
|
||||
public static final float CUBIC_CENTIMETERS = CENTIMETERS * CENTIMETERS * CENTIMETERS;
|
||||
public static final float CUBIC_METERS = METERS * METERS * METERS;
|
||||
public static final float CUBIC_MILLIMETERS = MILLIMETERS * MILLIMETERS * MILLIMETERS;
|
||||
public static final float CUBIC_KILOMETERS = KILOMETERS * KILOMETERS * KILOMETERS;
|
||||
|
||||
// Mass
|
||||
public static final float GRAMS = KILOGRAMS / 1000;
|
||||
public static final float TONNES = KILOGRAMS * 1000;
|
||||
|
||||
// Density
|
||||
public static final float KILOGRAMS_PER_CUBIC_METER = KILOGRAMS / CUBIC_METERS;
|
||||
public static final float GRAMS_PER_CUBIC_CENTIMETER = GRAMS / CUBIC_CENTIMETERS;
|
||||
|
||||
// Time
|
||||
public static final float MILLISECONDS = SECONDS / 1000;
|
||||
public static final float MINUTES = SECONDS * 60;
|
||||
public static final float HOURS = MINUTES * 60;
|
||||
public static final float DAYS = HOURS * 24;
|
||||
|
||||
// Frequency
|
||||
public static final float HERTZ = 1 / SECONDS;
|
||||
public static final float KILOHERTZ = HERTZ * 1000;
|
||||
|
||||
// Velocity
|
||||
public static final float METERS_PER_SECOND = METERS / SECONDS;
|
||||
public static final float KILOMETERS_PER_HOUR = KILOMETERS / HOURS;
|
||||
|
||||
// Acceleration
|
||||
public static final float METERS_PER_SECOND_SQUARED = METERS_PER_SECOND / SECONDS;
|
||||
|
||||
// Force
|
||||
public static final float NEWTONS = METERS_PER_SECOND_SQUARED * KILOGRAMS;
|
||||
|
||||
}
|
155
src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java
Executable file
155
src/main/java/ru/windcorp/progressia/test/LayerTestGUI.java
Executable file
@ -0,0 +1,155 @@
|
||||
/*******************************************************************************
|
||||
* Progressia
|
||||
* Copyright (C) 2020 Wind Corporation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*******************************************************************************/
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
import ru.windcorp.progressia.client.graphics.font.Font;
|
||||
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;
|
||||
|
||||
public class LayerTestGUI extends GUILayer {
|
||||
|
||||
public LayerTestGUI() {
|
||||
super("LayerTestGui", new LayoutAlign(0, 1, 5));
|
||||
|
||||
Panel panel = new Panel("ControlDisplays", new LayoutVertical(5));
|
||||
|
||||
Collection<Label> labels = new ArrayList<>();
|
||||
|
||||
panel.addChild(new Label(
|
||||
"IsFlyingDisplay", new Font().withColor(0x37A3E6).deriveShadow(),
|
||||
() -> String.format("Flying: %5s (Space bar x2)", TestPlayerControls.getInstance().isFlying())
|
||||
));
|
||||
|
||||
panel.addChild(new Label(
|
||||
"IsMouseCapturedDisplay", new Font().withColor(0x37A3E6).deriveShadow(),
|
||||
() -> String.format("Mouse captured: %5s (esc)", TestPlayerControls.getInstance().isMouseCaptured())
|
||||
));
|
||||
|
||||
panel.addChild(new Label(
|
||||
"CameraModeDisplay", new Font().withColor(0x37A3E6).deriveShadow(),
|
||||
() -> String.format("Camera mode: %5d (F5)", ClientState.getInstance().getCamera().getCurrentModeIndex())
|
||||
));
|
||||
|
||||
panel.addChild(new Label(
|
||||
"GravityModeDisplay", new Font().withColor(0x37A3E6).deriveShadow(),
|
||||
() -> String.format("Gravity: %9s (G)", TestPlayerControls.getInstance().useMinecraftGravity() ? "Minecraft" : "Realistic")
|
||||
));
|
||||
|
||||
panel.getChildren().forEach(c -> labels.add((Label) c));
|
||||
TestPlayerControls.getInstance().setUpdateCallback(() -> labels.forEach(Label::update));
|
||||
|
||||
getRoot().addChild(panel);
|
||||
}
|
||||
|
||||
// private static class DebugComponent extends Component {
|
||||
// private final int color;
|
||||
//
|
||||
// public DebugComponent(String name, Vec2i size, int color) {
|
||||
// super(name);
|
||||
// this.color = color;
|
||||
//
|
||||
// setPreferredSize(size);
|
||||
//
|
||||
// addListener(new Object() {
|
||||
// @Subscribe
|
||||
// public void onHoverChanged(HoverEvent e) {
|
||||
// requestReassembly();
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// addListener(KeyEvent.class, this::onClicked);
|
||||
// }
|
||||
//
|
||||
// private boolean onClicked(KeyEvent event) {
|
||||
// if (!event.isMouse()) {
|
||||
// return false;
|
||||
// } else if (event.isPress() && event.isLeftMouseButton()) {
|
||||
// System.out.println("You pressed a Component!");
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// protected void assembleSelf(RenderTarget target) {
|
||||
// target.fill(getX(), getY(), getWidth(), getHeight(), Colors.BLACK);
|
||||
//
|
||||
// target.fill(
|
||||
// getX() + 2, getY() + 2,
|
||||
// getWidth() - 4, getHeight() - 4,
|
||||
// isHovered() ? Colors.DEBUG_YELLOW : color
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public LayerTestGUI() {
|
||||
// super("LayerTestGui", new LayoutAlign(1, 0.75, 5));
|
||||
//
|
||||
// Panel panel = new Panel("Alex", new LayoutVertical(5));
|
||||
//
|
||||
// panel.addChild(new DebugComponent("Bravo", new Vec2i(200, 100), 0x44FF44));
|
||||
//
|
||||
// Component charlie = new DebugComponent("Charlie", null, 0x222222);
|
||||
// charlie.setLayout(new LayoutVertical(5));
|
||||
//
|
||||
// //Debug
|
||||
// Localizer.getInstance().setLanguage("ru-RU");
|
||||
// MutableString epsilon = new MutableStringLocalized("Epsilon")
|
||||
// .addListener(() -> ((Label)charlie.getChild(0)).update()).format(34, "thirty-four");
|
||||
// // These two are swapped in code due to a bug in layouts, fixing ATM
|
||||
// charlie.addChild(
|
||||
// new Label(
|
||||
// "Delta",
|
||||
// new Font().withColor(0xCCBB44).deriveShadow().deriveBold(),
|
||||
// "Пре-альфа!"
|
||||
// )
|
||||
// );
|
||||
// charlie.addChild(
|
||||
// new Label(
|
||||
// "Epsilon",
|
||||
// new Font().withColor(0x4444BB).deriveItalic(),
|
||||
// () -> epsilon.get().concat("\u269b")
|
||||
// )
|
||||
// );
|
||||
// panel.addChild(charlie);
|
||||
//
|
||||
//
|
||||
// charlie.addListener(KeyEvent.class, e -> {
|
||||
// if(e.isPress() && e.getKey() == GLFW.GLFW_KEY_L) {
|
||||
// Localizer localizer = Localizer.getInstance();
|
||||
// if (localizer.getLanguage().equals("ru-RU")) {
|
||||
// localizer.setLanguage("en-US");
|
||||
// } else {
|
||||
// localizer.setLanguage("ru-RU");
|
||||
// }
|
||||
// return true;
|
||||
// } return false;
|
||||
// });
|
||||
// charlie.setFocusable(true);
|
||||
// charlie.takeFocus();
|
||||
//
|
||||
// getRoot().addChild(panel);
|
||||
// }
|
||||
|
||||
}
|
@ -98,7 +98,7 @@ public class TestContent {
|
||||
|
||||
private static void regsiterControls() {
|
||||
ControlDataRegistry.getInstance().register(new ControlData("Test", "Switch000"));
|
||||
ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test", "Switch000", new KeyMatcher(GLFW.GLFW_KEY_G, new int[0], 0)::matches));
|
||||
ControlTriggerRegistry.getInstance().register(new ControlTriggerOnKeyPress("Test", "Switch000", new KeyMatcher(GLFW.GLFW_KEY_H, new int[0], 0)::matches));
|
||||
ControlLogicRegistry.getInstance().register(new ControlLogic("Test", "Switch000") {
|
||||
@Override
|
||||
public void apply(Server server, PacketControl packet, Client client) {
|
||||
|
@ -0,0 +1,270 @@
|
||||
package ru.windcorp.progressia.test;
|
||||
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import glm.Glm;
|
||||
import glm.mat._3.Mat3;
|
||||
import glm.vec._2.Vec2;
|
||||
import glm.vec._3.Vec3;
|
||||
import ru.windcorp.progressia.client.ClientState;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsBackend;
|
||||
import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface;
|
||||
import ru.windcorp.progressia.client.graphics.input.CursorMoveEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.InputEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.graphics.input.bus.Input;
|
||||
import ru.windcorp.progressia.common.Units;
|
||||
import ru.windcorp.progressia.common.util.FloatMathUtils;
|
||||
import ru.windcorp.progressia.common.util.Matrices;
|
||||
import ru.windcorp.progressia.common.util.Vectors;
|
||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||
|
||||
public class TestPlayerControls {
|
||||
|
||||
private static final TestPlayerControls INSTANCE = new TestPlayerControls();
|
||||
|
||||
public static TestPlayerControls getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private TestPlayerControls() {}
|
||||
|
||||
private static final double MODE_SWITCH_MAX_DELAY = 100 * Units.MILLISECONDS;
|
||||
private static final double MIN_JUMP_DELAY = 200 * Units.MILLISECONDS;
|
||||
|
||||
// Horizontal and vertical max control speed when flying
|
||||
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;
|
||||
|
||||
// Horizontal and vertical max control speed when walking
|
||||
private static final float WALKING_SPEED = 5.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;
|
||||
|
||||
// Vertical velocity instantly add to player when they jump
|
||||
private static final float JUMP_VELOCITY = 5f * Units.METERS_PER_SECOND;
|
||||
|
||||
private boolean isFlying = true;
|
||||
|
||||
private int movementForward = 0;
|
||||
private int movementRight = 0;
|
||||
private int movementUp = 0;
|
||||
|
||||
private double lastSpacePress = Double.NEGATIVE_INFINITY;
|
||||
|
||||
private boolean captureMouse = true;
|
||||
private boolean useMinecraftGravity = false;
|
||||
|
||||
private Runnable updateCallback = null;
|
||||
|
||||
public void applyPlayerControls() {
|
||||
if (ClientState.getInstance() == null || ClientState.getInstance().getLocalPlayer() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityData player = getPlayer();
|
||||
Mat3 angMat = Matrices.grab3();
|
||||
|
||||
angMat.identity().rotateZ(player.getYaw());
|
||||
|
||||
Vec3 movement = Vectors.grab3();
|
||||
|
||||
movement.set(movementForward, -movementRight, 0);
|
||||
|
||||
if (movementForward != 0 && movementRight != 0) {
|
||||
movement.normalize();
|
||||
}
|
||||
|
||||
angMat.mul_(movement); // bug in jglm, .mul() and mul_() are swapped
|
||||
|
||||
if (isFlying) {
|
||||
movement.z = movementUp;
|
||||
movement.mul(FLYING_SPEED);
|
||||
movement.sub(player.getVelocity());
|
||||
movement.mul(FLYING_CONTROL_AUTHORITY);
|
||||
} else {
|
||||
movement.mul(WALKING_SPEED);
|
||||
movement.sub(player.getVelocity());
|
||||
movement.mul(WALKING_CONTROL_AUTHORITY);
|
||||
movement.z = 0;
|
||||
}
|
||||
|
||||
player.getVelocity().add(movement);
|
||||
|
||||
Matrices.release(angMat);
|
||||
Vectors.release(movement);
|
||||
}
|
||||
|
||||
public void handleInput(Input input) {
|
||||
if (ClientState.getInstance() == null || ClientState.getInstance().getLocalPlayer() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
InputEvent event = input.getEvent();
|
||||
|
||||
if (event instanceof KeyEvent) {
|
||||
if (onKeyEvent((KeyEvent) event)) {
|
||||
input.consume();
|
||||
}
|
||||
} else if (event instanceof CursorMoveEvent) {
|
||||
onMouseMoved((CursorMoveEvent) event);
|
||||
input.consume();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean onKeyEvent(KeyEvent event) {
|
||||
if (event.isRepeat()) return false;
|
||||
|
||||
int multiplier = event.isPress() ? 1 : -1;
|
||||
|
||||
switch (event.getKey()) {
|
||||
case GLFW.GLFW_KEY_W:
|
||||
movementForward += +1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
movementForward += -1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_A:
|
||||
movementRight += -1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_D:
|
||||
movementRight += +1 * multiplier;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_SPACE:
|
||||
handleSpace(multiplier);
|
||||
break;
|
||||
case GLFW.GLFW_KEY_LEFT_SHIFT:
|
||||
handleShift(multiplier);
|
||||
break;
|
||||
|
||||
case GLFW.GLFW_KEY_ESCAPE:
|
||||
if (!event.isPress()) return false;
|
||||
handleEscape();
|
||||
break;
|
||||
|
||||
case GLFW.GLFW_KEY_F5:
|
||||
if (!event.isPress()) return false;
|
||||
handleCameraMode();
|
||||
break;
|
||||
|
||||
case GLFW.GLFW_KEY_G:
|
||||
if (!event.isPress()) return false;
|
||||
handleGravitySwitch();
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleSpace(int multiplier) {
|
||||
boolean isPressed = multiplier > 0;
|
||||
|
||||
double timeSinceLastSpacePress = GraphicsInterface.getTime() - lastSpacePress;
|
||||
|
||||
if (isPressed && timeSinceLastSpacePress < MODE_SWITCH_MAX_DELAY) {
|
||||
isFlying = !isFlying;
|
||||
updateGUI();
|
||||
movementUp = +1;
|
||||
} else {
|
||||
if (isFlying) {
|
||||
movementUp += +1 * multiplier;
|
||||
} else {
|
||||
if (isPressed && timeSinceLastSpacePress > MIN_JUMP_DELAY) {
|
||||
jump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastSpacePress = GraphicsInterface.getTime();
|
||||
}
|
||||
|
||||
private void jump() {
|
||||
getPlayer().getVelocity().add(0, 0, JUMP_VELOCITY * (useMinecraftGravity ? 2 : 1));
|
||||
}
|
||||
|
||||
private void handleShift(int multiplier) {
|
||||
if (isFlying) {
|
||||
movementUp += -1 * multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleEscape() {
|
||||
if (captureMouse) {
|
||||
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
|
||||
} else {
|
||||
GLFW.glfwSetInputMode(GraphicsBackend.getWindowHandle(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
|
||||
}
|
||||
|
||||
captureMouse = !captureMouse;
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
private void handleCameraMode() {
|
||||
if (ClientState.getInstance().getCamera().hasAnchor()) {
|
||||
ClientState.getInstance().getCamera().selectNextMode();
|
||||
updateGUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGravitySwitch() {
|
||||
useMinecraftGravity = !useMinecraftGravity;
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
private void onMouseMoved(CursorMoveEvent event) {
|
||||
if (!captureMouse) return;
|
||||
|
||||
final float yawScale = -0.002f;
|
||||
final float pitchScale = yawScale;
|
||||
|
||||
EntityData player = getPlayer();
|
||||
|
||||
normalizeAngles(player.getDirection().add(
|
||||
(float) (event.getChangeX() * yawScale),
|
||||
(float) (event.getChangeY() * pitchScale)
|
||||
));
|
||||
}
|
||||
|
||||
private void normalizeAngles(Vec2 dir) {
|
||||
// Normalize yaw
|
||||
dir.x = FloatMathUtils.normalizeAngle(dir.x);
|
||||
|
||||
// Clamp pitch
|
||||
dir.y = Glm.clamp(
|
||||
dir.y, -FloatMathUtils.PI_F/2, +FloatMathUtils.PI_F/2
|
||||
);
|
||||
}
|
||||
|
||||
private EntityData getPlayer() {
|
||||
return ClientState.getInstance().getLocalPlayer();
|
||||
}
|
||||
|
||||
public void setUpdateCallback(Runnable updateCallback) {
|
||||
this.updateCallback = updateCallback;
|
||||
}
|
||||
|
||||
private void updateGUI() {
|
||||
if (this.updateCallback != null) {
|
||||
this.updateCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFlying() {
|
||||
return isFlying;
|
||||
}
|
||||
|
||||
public boolean isMouseCaptured() {
|
||||
return captureMouse;
|
||||
}
|
||||
|
||||
public boolean useMinecraftGravity() {
|
||||
return useMinecraftGravity;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user