Added scope mechanism to the game!

This commit is contained in:
Andrew Lalis 2022-07-29 11:34:30 +02:00
parent 4f172ccb98
commit dbdfcc554b
8 changed files with 72 additions and 29 deletions

View File

@ -4,13 +4,12 @@ import nl.andrewl.aos2_client.Client;
import nl.andrewl.aos2_client.CommunicationHandler; import nl.andrewl.aos2_client.CommunicationHandler;
import nl.andrewl.aos2_client.model.ClientPlayer; import nl.andrewl.aos2_client.model.ClientPlayer;
import nl.andrewl.aos_core.model.item.BlockItemStack; import nl.andrewl.aos_core.model.item.BlockItemStack;
import nl.andrewl.aos_core.model.item.GunItemStack;
import nl.andrewl.aos_core.model.world.Hit; import nl.andrewl.aos_core.model.world.Hit;
import nl.andrewl.aos_core.net.client.BlockColorMessage; import nl.andrewl.aos_core.net.client.BlockColorMessage;
import nl.andrewl.aos_core.net.client.ChatWrittenMessage; import nl.andrewl.aos_core.net.client.ChatWrittenMessage;
import nl.andrewl.aos_core.net.client.ClientInputState; import nl.andrewl.aos_core.net.client.ClientInputState;
import static org.lwjgl.glfw.GLFW.*;
/** /**
* Class which manages the player's input, and sending it to the server. * Class which manages the player's input, and sending it to the server.
*/ */
@ -234,6 +233,11 @@ public class InputHandler {
} }
} }
public boolean isScopeEnabled() {
return interacting &&
client.getMyPlayer().getInventory().getSelectedItemStack() instanceof GunItemStack;
}
public void pickBlock() { public void pickBlock() {
var player = client.getMyPlayer(); var player = client.getMyPlayer();
if (player.getInventory().getSelectedItemStack() instanceof BlockItemStack stack) { if (player.getInventory().getSelectedItemStack() instanceof BlockItemStack stack) {

View File

@ -48,9 +48,11 @@ public class PlayerViewCursorCallback implements GLFWCursorPosCallbackI {
float dy = y - lastMouseCursorY; float dy = y - lastMouseCursorY;
lastMouseCursorX = x; lastMouseCursorX = x;
lastMouseCursorY = y; lastMouseCursorY = y;
float trueSensitivity = config.mouseSensitivity;
if (client.getInputHandler().isScopeEnabled()) trueSensitivity *= 0.1f;
client.getMyPlayer().setOrientation( client.getMyPlayer().setOrientation(
client.getMyPlayer().getOrientation().x - dx * config.mouseSensitivity, client.getMyPlayer().getOrientation().x - dx * trueSensitivity,
client.getMyPlayer().getOrientation().y - dy * config.mouseSensitivity client.getMyPlayer().getOrientation().y - dy * trueSensitivity
); );
camera.setOrientationToPlayer(client.getMyPlayer()); camera.setOrientationToPlayer(client.getMyPlayer());
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();

View File

@ -1,6 +1,7 @@
package nl.andrewl.aos2_client.model; package nl.andrewl.aos2_client.model;
import nl.andrewl.aos2_client.Camera; import nl.andrewl.aos2_client.Camera;
import nl.andrewl.aos2_client.control.InputHandler;
import nl.andrewl.aos_core.model.Player; import nl.andrewl.aos_core.model.Player;
import nl.andrewl.aos_core.model.item.Inventory; import nl.andrewl.aos_core.model.item.Inventory;
import org.joml.Matrix3f; import org.joml.Matrix3f;
@ -42,12 +43,16 @@ public class ClientPlayer extends Player {
this.health = health; this.health = health;
} }
public void updateHeldItemTransform(Camera cam) { public void updateHeldItemTransform(Camera cam, InputHandler inputHandler) {
heldItemTransform.identity() heldItemTransform.identity()
.translate(cam.getPosition()) .translate(cam.getPosition())
.rotate((float) (cam.getOrientation().x + Math.PI), Camera.UP) .rotate((float) (cam.getOrientation().x + Math.PI), Camera.UP)
.rotate(-cam.getOrientation().y + (float) Math.PI / 2, Camera.RIGHT) .rotate(-cam.getOrientation().y + (float) Math.PI / 2, Camera.RIGHT);
.translate(-0.35f, -0.4f, 0.5f); if (inputHandler.isScopeEnabled()) {
heldItemTransform.translate(0, -0.12f, 0);
} else {
heldItemTransform.translate(-0.35f, -0.4f, 0.5f);
}
heldItemTransform.get(heldItemTransformData); heldItemTransform.get(heldItemTransformData);
heldItemTransform.normal(heldItemNormalTransform); heldItemTransform.normal(heldItemNormalTransform);

View File

@ -56,6 +56,7 @@ public class GameRenderer {
private final int screenHeight; private final int screenHeight;
private final Matrix4f perspectiveTransform; private final Matrix4f perspectiveTransform;
private final float[] perspectiveTransformData = new float[16];
public GameRenderer(Client client, InputHandler inputHandler) { public GameRenderer(Client client, InputHandler inputHandler) {
this.config = client.getConfig().display; this.config = client.getConfig().display;
@ -155,10 +156,9 @@ public class GameRenderer {
fovRad = 0.01f; fovRad = 0.01f;
} }
perspectiveTransform.setPerspective(fovRad, getAspectRatio(), Z_NEAR, Z_FAR); perspectiveTransform.setPerspective(fovRad, getAspectRatio(), Z_NEAR, Z_FAR);
float[] data = new float[16]; perspectiveTransform.get(perspectiveTransformData);
perspectiveTransform.get(data); if (chunkRenderer != null) chunkRenderer.setPerspective(perspectiveTransformData);
if (chunkRenderer != null) chunkRenderer.setPerspective(data); if (modelRenderer != null) modelRenderer.setPerspective(perspectiveTransformData);
if (modelRenderer != null) modelRenderer.setPerspective(data);
} }
public boolean windowShouldClose() { public boolean windowShouldClose() {
@ -175,13 +175,19 @@ public class GameRenderer {
public void draw() { public void draw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
chunkRenderer.draw(camera, client.getWorld().getChunkMeshesToDraw());
ClientPlayer myPlayer = client.getMyPlayer(); ClientPlayer myPlayer = client.getMyPlayer();
if (client.getInputHandler().isScopeEnabled()) {
updatePerspective(15);
} else {
updatePerspective(config.fov);
}
myPlayer.updateHeldItemTransform(camera, client.getInputHandler());
chunkRenderer.draw(camera, client.getWorld().getChunkMeshesToDraw());
// Draw models. Use one texture at a time for efficiency. // Draw models. Use one texture at a time for efficiency.
modelRenderer.start(camera.getViewTransformData()); modelRenderer.start(camera.getViewTransformData());
myPlayer.updateHeldItemTransform(camera);
playerModel.bind(); playerModel.bind();
for (var player : client.getPlayers().values()) { for (var player : client.getPlayers().values()) {

View File

@ -0,0 +1,6 @@
package nl.andrewl.aos2_client.render;
public record TransformData(
float[] tx,
float[] norm
) {}

View File

@ -222,10 +222,12 @@ public class GuiRenderer {
nvgBeginFrame(vgId, width, height, width / height); nvgBeginFrame(vgId, width, height, width / height);
nvgSave(vgId); nvgSave(vgId);
drawCrosshair(width, height); drawCrosshair(width, height, client.getInputHandler().isScopeEnabled());
if (!client.getInputHandler().isScopeEnabled()) {
drawChat(width, height, client); drawChat(width, height, client);
drawHealthBar(width, height, client.getMyPlayer()); drawHealthBar(width, height, client.getMyPlayer());
drawHeldItemStackInfo(width, height, client.getMyPlayer()); drawHeldItemStackInfo(width, height, client.getMyPlayer());
}
if (client.getInputHandler().isDebugEnabled()) { if (client.getInputHandler().isDebugEnabled()) {
drawDebugInfo(width, height, client); drawDebugInfo(width, height, client);
} }
@ -253,16 +255,18 @@ public class GuiRenderer {
shaderProgram.free(); shaderProgram.free();
} }
private void drawCrosshair(float w, float h) { private void drawCrosshair(float w, float h, boolean scopeEnabled) {
float cx = w / 2f; float cx = w / 2f;
float cy = h / 2f; float cy = h / 2f;
float size = 20f;
if (scopeEnabled) size = 3f;
nvgStrokeColor(vgId, GuiUtils.rgba(1, 1, 1, 0.25f, colorA)); nvgStrokeColor(vgId, GuiUtils.rgba(1, 1, 1, 0.25f, colorA));
nvgBeginPath(vgId); nvgBeginPath(vgId);
nvgMoveTo(vgId, cx - 10, cy); nvgMoveTo(vgId, cx - size / 2, cy);
nvgLineTo(vgId, cx + 10, cy); nvgLineTo(vgId, cx + size / 2, cy);
nvgMoveTo(vgId, cx, cy - 10); nvgMoveTo(vgId, cx, cy - size / 2);
nvgLineTo(vgId, cx, cy + 10); nvgLineTo(vgId, cx, cy + size / 2);
nvgStroke(vgId); nvgStroke(vgId);
} }

View File

@ -54,14 +54,22 @@ public class ProjectileManager {
if (nextProjectileId == Integer.MAX_VALUE) nextProjectileId = 1; if (nextProjectileId == Integer.MAX_VALUE) nextProjectileId = 1;
pos.set(0); pos.set(0);
direction.set(player.getViewVector()).normalize();
float accuracy = gun.getAccuracy();
if (player.getActionManager().isScopeEnabled()) {
bulletTransform.identity()
.translate(player.getEyePosition())
.rotate(player.getOrientation().x + (float) Math.PI, Directions.UPf);
accuracy += (1f - accuracy) / 2f;
} else {
bulletTransform.identity() bulletTransform.identity()
.translate(player.getEyePosition()) .translate(player.getEyePosition())
.rotate(player.getOrientation().x + (float) Math.PI, Directions.UPf) .rotate(player.getOrientation().x + (float) Math.PI, Directions.UPf)
.translate(-0.35f, -0.4f, 0.35f); .translate(-0.35f, -0.4f, 0.35f);
bulletTransform.transformPosition(pos); }
direction.set(player.getViewVector()).normalize(); bulletTransform.transformPosition(pos);
float accuracy = gun.getAccuracy();
accuracy -= server.getConfig().actions.movementAccuracyDecreaseFactor * player.getVelocity().length(); accuracy -= server.getConfig().actions.movementAccuracyDecreaseFactor * player.getVelocity().length();
float perturbationFactor = (1 - accuracy) / 8; float perturbationFactor = (1 - accuracy) / 8;
direction.x += rand.nextGaussian(0, perturbationFactor); direction.x += rand.nextGaussian(0, perturbationFactor);

View File

@ -56,6 +56,11 @@ public class PlayerActionManager {
return input.setLastInputState(lastInputState); return input.setLastInputState(lastInputState);
} }
public boolean isScopeEnabled() {
return input.interacting() &&
player.getInventory().getSelectedItemStack() instanceof GunItemStack;
}
public boolean isUpdated() { public boolean isUpdated() {
return updated; return updated;
} }
@ -113,6 +118,7 @@ public class PlayerActionManager {
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ItemStackMessage(player.getInventory())); server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ItemStackMessage(player.getInventory()));
// Apply recoil! // Apply recoil!
float recoilFactor = 10f; // Maximum number of degrees to recoil. float recoilFactor = 10f; // Maximum number of degrees to recoil.
if (isScopeEnabled()) recoilFactor *= 0.1f;
float recoil = recoilFactor * gun.getRecoil() + (float) ThreadLocalRandom.current().nextGaussian(0, 0.01); float recoil = recoilFactor * gun.getRecoil() + (float) ThreadLocalRandom.current().nextGaussian(0, 0.01);
server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ClientRecoilMessage(0, Math.toRadians(recoil))); server.getPlayerManager().getHandler(player.getId()).sendDatagramPacket(new ClientRecoilMessage(0, Math.toRadians(recoil)));
// Play sound! // Play sound!
@ -249,7 +255,7 @@ public class PlayerActionManager {
acceleration.rotateAxis(orientation.x, 0, 1, 0); acceleration.rotateAxis(orientation.x, 0, 1, 0);
acceleration.mul(config.movementAcceleration); acceleration.mul(config.movementAcceleration);
horizontalVelocity.add(acceleration); horizontalVelocity.add(acceleration);
final float maxSpeed; float maxSpeed;
if (input.crouching()) { if (input.crouching()) {
maxSpeed = config.crouchingSpeed; maxSpeed = config.crouchingSpeed;
} else if (input.sprinting()) { } else if (input.sprinting()) {
@ -257,6 +263,8 @@ public class PlayerActionManager {
} else { } else {
maxSpeed = config.walkingSpeed; maxSpeed = config.walkingSpeed;
} }
// If scoping, then force limit to crouching speed.
if (isScopeEnabled()) maxSpeed = config.crouchingSpeed;
if (horizontalVelocity.length() > maxSpeed) { if (horizontalVelocity.length() > maxSpeed) {
horizontalVelocity.normalize(maxSpeed); horizontalVelocity.normalize(maxSpeed);
} }