Added different gun characteristics.
This commit is contained in:
parent
876bd32bdc
commit
49bb724f65
|
@ -130,11 +130,14 @@ public class Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendChat() {
|
public void sendChat() {
|
||||||
|
String message = this.chatBuffer.toString().trim();
|
||||||
|
if (!message.isBlank()) {
|
||||||
try {
|
try {
|
||||||
this.messageTransceiver.send(new PlayerChatMessage(this.playerId, this.chatBuffer.toString()));
|
this.messageTransceiver.send(new PlayerChatMessage(this.playerId, message));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
this.setChatting(false);
|
this.setChatting(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,11 @@ public class PlayerKeyListener extends KeyAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyTyped(KeyEvent e) {
|
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);
|
this.client.setChatting(true);
|
||||||
if (e.getKeyChar() == '/') this.client.appendToChat('/');
|
if (e.getKeyChar() == '/') this.client.appendToChat('/');
|
||||||
|
}
|
||||||
} else if (this.client.isChatting()) {
|
} else if (this.client.isChatting()) {
|
||||||
char c = e.getKeyChar();
|
char c = e.getKeyChar();
|
||||||
if (c >= ' ' && c <= '~') {
|
if (c >= ' ' && c <= '~') {
|
||||||
|
@ -43,6 +45,8 @@ public class PlayerKeyListener extends KeyAdapter {
|
||||||
state.setMovingLeft(true);
|
state.setMovingLeft(true);
|
||||||
} else if (e.getKeyCode() == KeyEvent.VK_D) {
|
} else if (e.getKeyCode() == KeyEvent.VK_D) {
|
||||||
state.setMovingRight(true);
|
state.setMovingRight(true);
|
||||||
|
} else if (e.getKeyCode() == KeyEvent.VK_R) {
|
||||||
|
state.setReloading(true);
|
||||||
}
|
}
|
||||||
this.client.sendPlayerState();
|
this.client.sendPlayerState();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +63,8 @@ public class PlayerKeyListener extends KeyAdapter {
|
||||||
state.setMovingLeft(false);
|
state.setMovingLeft(false);
|
||||||
} else if (e.getKeyCode() == KeyEvent.VK_D) {
|
} else if (e.getKeyCode() == KeyEvent.VK_D) {
|
||||||
state.setMovingRight(false);
|
state.setMovingRight(false);
|
||||||
|
} else if (e.getKeyCode() == KeyEvent.VK_R) {
|
||||||
|
state.setReloading(false);
|
||||||
}
|
}
|
||||||
this.client.sendPlayerState();
|
this.client.sendPlayerState();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package nl.andrewlalis.aos_client.view;
|
||||||
|
|
||||||
import nl.andrewlalis.aos_client.Client;
|
import nl.andrewlalis.aos_client.Client;
|
||||||
import nl.andrewlalis.aos_core.model.*;
|
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.ChatMessage;
|
||||||
import nl.andrewlalis.aos_core.net.chat.PlayerChatMessage;
|
import nl.andrewlalis.aos_core.net.chat.PlayerChatMessage;
|
||||||
import nl.andrewlalis.aos_core.net.chat.SystemChatMessage;
|
import nl.andrewlalis.aos_core.net.chat.SystemChatMessage;
|
||||||
|
@ -48,6 +49,7 @@ public class GamePanel extends JPanel {
|
||||||
World world = client.getWorld();
|
World world = client.getWorld();
|
||||||
if (world != null) drawWorld(g2, world);
|
if (world != null) drawWorld(g2, world);
|
||||||
drawChat(g2, world);
|
drawChat(g2, world);
|
||||||
|
drawStatus(g2, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawWorld(Graphics2D g2, World 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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,5 @@ module aos_core {
|
||||||
exports nl.andrewlalis.aos_core.model to aos_server, aos_client;
|
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.geom to aos_server, aos_client;
|
||||||
exports nl.andrewlalis.aos_core.net.chat to aos_client, aos_server;
|
exports nl.andrewlalis.aos_core.net.chat to aos_client, aos_server;
|
||||||
|
exports nl.andrewlalis.aos_core.model.tools to aos_client, aos_server;
|
||||||
}
|
}
|
|
@ -1,13 +1,23 @@
|
||||||
package nl.andrewlalis.aos_core.model;
|
package nl.andrewlalis.aos_core.model;
|
||||||
|
|
||||||
public class Bullet extends PhysicsObject {
|
import nl.andrewlalis.aos_core.geom.Vec2;
|
||||||
public static final double SPEED = 100.0; // Meters per second.
|
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
public class Bullet extends PhysicsObject {
|
||||||
private final int playerId;
|
private final int playerId;
|
||||||
|
|
||||||
public Bullet(Player player) {
|
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();
|
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() {
|
public int getPlayerId() {
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package nl.andrewlalis.aos_core.model;
|
|
||||||
|
|
||||||
public class Gun {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,9 +1,10 @@
|
||||||
package nl.andrewlalis.aos_core.model;
|
package nl.andrewlalis.aos_core.model;
|
||||||
|
|
||||||
|
import nl.andrewlalis.aos_core.model.tools.Gun;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Player extends PhysicsObject {
|
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 MOVEMENT_SPEED = 10; // Movement speed, in m/s
|
||||||
public static final double RADIUS = 0.5; // Collision radius, in meters.
|
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 final String name;
|
||||||
private Team team;
|
private Team team;
|
||||||
private PlayerControlState state;
|
private PlayerControlState state;
|
||||||
|
private Gun gun;
|
||||||
|
|
||||||
private transient long lastShot;
|
private transient long lastShot;
|
||||||
|
private transient long reloadingStartedAt;
|
||||||
|
private boolean reloading;
|
||||||
|
|
||||||
public Player(int id, String name, Team team) {
|
public Player(int id, String name, Team team) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
@ -20,7 +24,8 @@ public class Player extends PhysicsObject {
|
||||||
this.team = team;
|
this.team = team;
|
||||||
this.state = new PlayerControlState();
|
this.state = new PlayerControlState();
|
||||||
this.state.setPlayerId(this.id);
|
this.state.setPlayerId(this.id);
|
||||||
this.updateLastShot();
|
this.gun = Gun.m1Garand();
|
||||||
|
this.useWeapon();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
|
@ -47,12 +52,51 @@ public class Player extends PhysicsObject {
|
||||||
this.team = team;
|
this.team = team;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Gun getGun() {
|
||||||
|
return gun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGun(Gun gun) {
|
||||||
|
this.gun = gun;
|
||||||
|
}
|
||||||
|
|
||||||
public long getLastShot() {
|
public long getLastShot() {
|
||||||
return lastShot;
|
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.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
|
@Override
|
||||||
|
|
|
@ -13,6 +13,7 @@ public class PlayerControlState implements Serializable {
|
||||||
boolean movingBackward;
|
boolean movingBackward;
|
||||||
|
|
||||||
boolean shooting;
|
boolean shooting;
|
||||||
|
boolean reloading;
|
||||||
|
|
||||||
Vec2 mouseLocation;
|
Vec2 mouseLocation;
|
||||||
|
|
||||||
|
@ -64,6 +65,14 @@ public class PlayerControlState implements Serializable {
|
||||||
this.shooting = shooting;
|
this.shooting = shooting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isReloading() {
|
||||||
|
return reloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReloading(boolean reloading) {
|
||||||
|
this.reloading = reloading;
|
||||||
|
}
|
||||||
|
|
||||||
public Vec2 getMouseLocation() {
|
public Vec2 getMouseLocation() {
|
||||||
return mouseLocation;
|
return mouseLocation;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package nl.andrewlalis.aos_core.model.tools;
|
||||||
|
|
||||||
|
public enum GunType {
|
||||||
|
SHOTGUN,
|
||||||
|
SMG,
|
||||||
|
RIFLE
|
||||||
|
}
|
|
@ -116,10 +116,16 @@ public class WorldUpdater extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePlayerShooting(Player p) {
|
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.getBullets().add(new Bullet(p));
|
||||||
this.world.getSoundsToPlay().add("ak47shot1.wav");
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue