Added different gun characteristics.

This commit is contained in:
Andrew Lalis 2021-06-20 00:46:47 +02:00
parent 876bd32bdc
commit 49bb724f65
11 changed files with 238 additions and 20 deletions

View File

@ -130,11 +130,14 @@ public class Client {
}
public void sendChat() {
String message = this.chatBuffer.toString().trim();
if (!message.isBlank()) {
try {
this.messageTransceiver.send(new PlayerChatMessage(this.playerId, this.chatBuffer.toString()));
this.messageTransceiver.send(new PlayerChatMessage(this.playerId, message));
} catch (IOException e) {
e.printStackTrace();
}
}
this.setChatting(false);
}

View File

@ -14,9 +14,11 @@ public class PlayerKeyListener extends KeyAdapter {
@Override
public void keyTyped(KeyEvent e) {
if (!this.client.isChatting() && (e.getKeyChar() == 't' || e.getKeyChar() == '/')) {
if (!this.client.isChatting()) {
if ((e.getKeyChar() == 't' || e.getKeyChar() == '/')) {
this.client.setChatting(true);
if (e.getKeyChar() == '/') this.client.appendToChat('/');
}
} else if (this.client.isChatting()) {
char c = e.getKeyChar();
if (c >= ' ' && c <= '~') {
@ -43,6 +45,8 @@ public class PlayerKeyListener extends KeyAdapter {
state.setMovingLeft(true);
} else if (e.getKeyCode() == KeyEvent.VK_D) {
state.setMovingRight(true);
} else if (e.getKeyCode() == KeyEvent.VK_R) {
state.setReloading(true);
}
this.client.sendPlayerState();
}
@ -59,6 +63,8 @@ public class PlayerKeyListener extends KeyAdapter {
state.setMovingLeft(false);
} else if (e.getKeyCode() == KeyEvent.VK_D) {
state.setMovingRight(false);
} else if (e.getKeyCode() == KeyEvent.VK_R) {
state.setReloading(false);
}
this.client.sendPlayerState();
}

View File

@ -2,6 +2,7 @@ package nl.andrewlalis.aos_client.view;
import nl.andrewlalis.aos_client.Client;
import nl.andrewlalis.aos_core.model.*;
import nl.andrewlalis.aos_core.model.tools.Gun;
import nl.andrewlalis.aos_core.net.chat.ChatMessage;
import nl.andrewlalis.aos_core.net.chat.PlayerChatMessage;
import nl.andrewlalis.aos_core.net.chat.SystemChatMessage;
@ -48,6 +49,7 @@ public class GamePanel extends JPanel {
World world = client.getWorld();
if (world != null) drawWorld(g2, world);
drawChat(g2, world);
drawStatus(g2, world);
}
private void drawWorld(Graphics2D g2, World world) {
@ -177,4 +179,17 @@ public class GamePanel extends JPanel {
g2.drawString("> " + this.client.getCurrentChatBuffer(), 5, height * 11);
}
}
private void drawStatus(Graphics2D g2, World world) {
Player myPlayer = world.getPlayers().get(this.client.getPlayerId());
if (myPlayer == null) return;
g2.setColor(Color.WHITE);
if (myPlayer.isReloading()) {
g2.drawString("Reloading...", 5, this.getHeight() - 10);
}
Gun gun = myPlayer.getGun();
g2.drawString("Clips: " + gun.getClipCount() + " / " + gun.getMaxClipCount(), 5, this.getHeight() - 20);
g2.drawString("Bullets: " + gun.getCurrentClipBulletCount() + " / " + gun.getClipSize(), 5, this.getHeight() - 30);
}
}

View File

@ -4,4 +4,5 @@ module aos_core {
exports nl.andrewlalis.aos_core.model to aos_server, aos_client;
exports nl.andrewlalis.aos_core.geom to aos_server, aos_client;
exports nl.andrewlalis.aos_core.net.chat to aos_client, aos_server;
exports nl.andrewlalis.aos_core.model.tools to aos_client, aos_server;
}

View File

@ -1,13 +1,23 @@
package nl.andrewlalis.aos_core.model;
public class Bullet extends PhysicsObject {
public static final double SPEED = 100.0; // Meters per second.
import nl.andrewlalis.aos_core.geom.Vec2;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
public class Bullet extends PhysicsObject {
private final int playerId;
public Bullet(Player player) {
super(player.getPosition().add(player.getOrientation().mul(1.5)), player.getOrientation(), player.getOrientation().mul(SPEED));
super(
player.getPosition().add(player.getOrientation().mul(1.5)),
player.getOrientation(),
null
);
this.playerId = player.getId();
Random r = ThreadLocalRandom.current();
Vec2 perturbation = new Vec2((r.nextDouble() - 0.5) * 2, (r.nextDouble() - 0.5) * 2).mul(player.getGun().getAccuracy());
this.setVelocity(player.getOrientation().add(perturbation).mul(player.getGun().getBulletSpeed()));
}
public int getPlayerId() {

View File

@ -1,5 +0,0 @@
package nl.andrewlalis.aos_core.model;
public class Gun {
}

View File

@ -1,9 +1,10 @@
package nl.andrewlalis.aos_core.model;
import nl.andrewlalis.aos_core.model.tools.Gun;
import java.util.Objects;
public class Player extends PhysicsObject {
public static final double SHOT_COOLDOWN = 0.1; // Time between shots, in seconds.
public static final double MOVEMENT_SPEED = 10; // Movement speed, in m/s
public static final double RADIUS = 0.5; // Collision radius, in meters.
@ -11,8 +12,11 @@ public class Player extends PhysicsObject {
private final String name;
private Team team;
private PlayerControlState state;
private Gun gun;
private transient long lastShot;
private transient long reloadingStartedAt;
private boolean reloading;
public Player(int id, String name, Team team) {
this.id = id;
@ -20,7 +24,8 @@ public class Player extends PhysicsObject {
this.team = team;
this.state = new PlayerControlState();
this.state.setPlayerId(this.id);
this.updateLastShot();
this.gun = Gun.m1Garand();
this.useWeapon();
}
public int getId() {
@ -47,12 +52,51 @@ public class Player extends PhysicsObject {
this.team = team;
}
public Gun getGun() {
return gun;
}
public void setGun(Gun gun) {
this.gun = gun;
}
public long getLastShot() {
return lastShot;
}
public void updateLastShot() {
public boolean canUseWeapon() {
return this.state.isShooting() &&
!this.state.isReloading() &&
!this.reloading &&
this.gun.getCurrentClipBulletCount() > 0 &&
this.lastShot + this.gun.getShotCooldownTime() * 1000 < System.currentTimeMillis();
}
public void useWeapon() {
this.lastShot = System.currentTimeMillis();
this.gun.decrementBulletCount();
}
public void startReloading() {
this.reloading = true;
this.reloadingStartedAt = System.currentTimeMillis();
}
public void finishReloading() {
this.gun.reload();
this.reloading = false;
}
public boolean isReloadingComplete() {
long msSinceStart = System.currentTimeMillis() - this.reloadingStartedAt;
if (msSinceStart > this.gun.getReloadTime() * 1000) {
return true;
}
return false;
}
public boolean isReloading() {
return reloading;
}
@Override

View File

@ -13,6 +13,7 @@ public class PlayerControlState implements Serializable {
boolean movingBackward;
boolean shooting;
boolean reloading;
Vec2 mouseLocation;
@ -64,6 +65,14 @@ public class PlayerControlState implements Serializable {
this.shooting = shooting;
}
public boolean isReloading() {
return reloading;
}
public void setReloading(boolean reloading) {
this.reloading = reloading;
}
public Vec2 getMouseLocation() {
return mouseLocation;
}

View File

@ -0,0 +1,122 @@
package nl.andrewlalis.aos_core.model.tools;
import java.io.Serializable;
public class Gun implements Serializable {
private final GunType type;
/**
* Maximum number of clips a player can carry when using this gun.
*/
private final int maxClipCount;
/**
* Number of bullets in each clip.
*/
private final int clipSize;
/**
* How accurate shots from this gun are.
*/
private final double accuracy;
/**
* How long (in seconds) to wait after each shot, before another is shot.
*/
private final double shotCooldownTime;
/**
* How long (in seconds) for reloading a new clip.
*/
private final double reloadTime;
/**
* How fast the bullet travels (in m/s).
*/
private final double bulletSpeed;
/**
* Number of bullets left in the current clip.
*/
private int currentClipBulletCount;
/**
* Number of clips remaining.
*/
private int clipCount;
private Gun(GunType type, int maxClipCount, int clipSize, double accuracy, double shotCooldownTime, double reloadTime, double bulletSpeed) {
this.type = type;
this.maxClipCount = maxClipCount;
this.clipSize = clipSize;
this.accuracy = accuracy;
this.shotCooldownTime = shotCooldownTime;
this.reloadTime = reloadTime;
this.bulletSpeed = bulletSpeed;
this.currentClipBulletCount = 0;
this.clipCount = maxClipCount;
}
public GunType getType() {
return type;
}
public int getMaxClipCount() {
return maxClipCount;
}
public int getClipSize() {
return clipSize;
}
public double getAccuracy() {
return accuracy;
}
public double getShotCooldownTime() {
return shotCooldownTime;
}
public double getReloadTime() {
return reloadTime;
}
public double getBulletSpeed() {
return bulletSpeed;
}
public int getCurrentClipBulletCount() {
return currentClipBulletCount;
}
public int getClipCount() {
return clipCount;
}
public void decrementBulletCount() {
this.currentClipBulletCount = Math.max(this.currentClipBulletCount - 1, 0);
}
public boolean canReload() {
return this.clipCount > 0;
}
public void reload() {
if (this.clipCount > 0) {
this.clipCount--;
this.currentClipBulletCount = this.clipSize;
}
}
public static Gun ak47() {
return new Gun(GunType.SMG, 4, 30, 0.10, 0.05, 1.2, 90);
}
public static Gun m1Garand() {
return new Gun(GunType.RIFLE, 6, 8, 0.02, 0.75, 1.5, 150);
}
public static Gun winchester() {
return new Gun(GunType.SHOTGUN, 8, 4, 0.15, 0.5, 2.0, 75);
}
}

View File

@ -0,0 +1,7 @@
package nl.andrewlalis.aos_core.model.tools;
public enum GunType {
SHOTGUN,
SMG,
RIFLE
}

View File

@ -116,10 +116,16 @@ public class WorldUpdater extends Thread {
}
private void updatePlayerShooting(Player p) {
if (p.getState().isShooting() && p.getLastShot() + Player.SHOT_COOLDOWN * 1000 < System.currentTimeMillis()) {
if (p.canUseWeapon()) {
this.world.getBullets().add(new Bullet(p));
this.world.getSoundsToPlay().add("ak47shot1.wav");
p.updateLastShot();
p.useWeapon();
}
if (p.getState().isReloading() && !p.isReloading() && p.getGun().canReload()) {
p.startReloading();
}
if (p.isReloading() && p.isReloadingComplete()) {
p.finishReloading();
}
}