Added scope mechanism to the game!
This commit is contained in:
		
							parent
							
								
									4f172ccb98
								
							
						
					
					
						commit
						dbdfcc554b
					
				| 
						 | 
					@ -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) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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()) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					package nl.andrewl.aos2_client.render;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public record TransformData(
 | 
				
			||||||
 | 
							float[] tx,
 | 
				
			||||||
 | 
							float[] norm
 | 
				
			||||||
 | 
					) {}
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue