Finish up MineKart

This commit is contained in:
Sam 2018-09-12 17:35:33 +01:00 committed by Alexander Meech
parent e716c9b2ea
commit 4b09c66cdc
4 changed files with 300 additions and 57 deletions

View File

@ -97,6 +97,7 @@ public class GameCompassComponent extends GameComponent<Game>
double dist = UtilMath.offset(player, closest); double dist = UtilMath.offset(player, closest);
player.setCompassTarget(closest.getLocation());
UtilTextBottom.display(C.cWhiteB + "Target: " + closestTeam.getChatColour() + closest.getName() + C.cWhiteB + " Distance: " + closestTeam.getChatColour() + _distanceFormat.format(dist), player); UtilTextBottom.display(C.cWhiteB + "Target: " + closestTeam.getChatColour() + closest.getName() + C.cWhiteB + " Distance: " + closestTeam.getChatColour() + _distanceFormat.format(dist), player);
} }
} }

View File

@ -1,7 +1,7 @@
package mineplex.game.nano.game.games.minekart; package mineplex.game.nano.game.games.minekart;
import org.bukkit.DyeColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Sheep; import org.bukkit.entity.Sheep;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@ -14,7 +14,7 @@ public class Kart
{ {
private final Player _driver; private final Player _driver;
private final LivingEntity _vehicle; private final Sheep _vehicle;
private int _lap, _lapCheckpoint, _lapKeyCheckpoint; private int _lap, _lapCheckpoint, _lapKeyCheckpoint;
@ -28,6 +28,8 @@ public class Kart
private boolean _crashed; private boolean _crashed;
private long _crashedAt; private long _crashedAt;
private long _completedAt;
Kart(Player driver) Kart(Player driver)
{ {
_driver = driver; _driver = driver;
@ -39,6 +41,8 @@ public class Kart
UtilEnt.ghost(_vehicle, true, false); UtilEnt.ghost(_vehicle, true, false);
UtilEnt.setFakeHead(_vehicle, true); UtilEnt.setFakeHead(_vehicle, true);
_vehicle.setColor(DyeColor.RED);
_vehicle.setPassenger(driver); _vehicle.setPassenger(driver);
_lap = 1; _lap = 1;
@ -57,11 +61,17 @@ public class Kart
return _driver; return _driver;
} }
public LivingEntity getVehicle() public Sheep getVehicle()
{ {
return _vehicle; return _vehicle;
} }
public Location getParticleLocation()
{
Location location = _vehicle.getLocation().add(0, 0.3, 0);
return location.subtract(location.getDirection().multiply(0.4));
}
public void setLap(int lap) public void setLap(int lap)
{ {
_lap = lap; _lap = lap;
@ -154,15 +164,21 @@ public class Kart
_driftPower = 0; _driftPower = 0;
} }
public boolean canBoost()
{
return UtilTime.elapsed(_driftLast, 500);
}
public boolean isBoosting() public boolean isBoosting()
{ {
return !UtilTime.elapsed(_driftLast, 1000); return !UtilTime.elapsed(_driftLast, 1200);
} }
public void setCrashed(boolean crashed) public void setCrashed(boolean crashed)
{ {
_crashed = crashed; _crashed = crashed;
_driftDirection = null; _driftDirection = null;
_driftPower = 0;
_driftLast = 0; _driftLast = 0;
if (crashed) if (crashed)
@ -180,4 +196,14 @@ public class Kart
{ {
return _crashedAt; return _crashedAt;
} }
public void complete()
{
_completedAt = System.currentTimeMillis();
}
public long getCompletedAt()
{
return _completedAt;
}
} }

View File

@ -2,9 +2,14 @@ package mineplex.game.nano.game.games.minekart;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilParticle;
import mineplex.core.common.util.UtilParticle.ParticleType;
import mineplex.core.common.util.UtilParticle.ViewDist;
public class KartController public class KartController
{ {
@ -14,73 +19,152 @@ public class KartController
LEFT, RIGHT LEFT, RIGHT
} }
void applyAirDrag(Kart kart) void applyAirResistance(Kart kart)
{ {
if (kart.getFrontWaysInput() != 0) Vector velocity = kart.getVelocity();
{
return;
}
Vector velocity = kart.getVelocity().multiply(0.95); if (kart.getFrontWaysInput() == 0 && velocity.length() < 0.1)
if (velocity.length() < 0.05)
{ {
velocity.multiply(0); velocity.multiply(0);
} }
else
{
velocity.multiply(1 - (Math.log(velocity.length() + 1) / 50));
}
} }
void collideBlock(Kart kart) void collideBlock(Kart kart)
{
Location location = kart.getVehicle().getLocation().add(0, 0.5, 0);
kart.getDriver().sendMessage("y=" + kart.getVehicle().getLocation().getY() % 1);
if (location.getBlock().getType() != Material.AIR)
{
kart.getVelocity().multiply(-1);
kart.getVelocity().setY(0.5);
kart.setCrashed(true);
}
}
void accelerate(Kart kart)
{ {
if (kart.isCrashed()) if (kart.isCrashed())
{ {
return; return;
} }
Vector velocity = kart.getVelocity(); Location location = kart.getVehicle().getLocation();
Vector facing = UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(0.03 * kart.getFrontWaysInput()); Block next = location.getBlock();
velocity.add(facing);
if (next.getType() != Material.AIR)
{
Vector velocity = kart.getVelocity();
double length = velocity.length();
if (next.getRelative(BlockFace.UP).getType() != Material.AIR)
{
if (length > 0.4)
{
velocity.multiply(-0.6);
}
else
{
velocity.normalize().multiply(-0.4);
}
velocity.setY(0.4);
kart.setCrashed(true);
}
else if (next.getType() == Material.SOUL_SAND)
{
if (velocity.length() > 0.3)
{
velocity.multiply(0.95);
}
}
else
{
double blockY = location.getY() % 1;
double y = 0.42 - (blockY / 3);
velocity.add(new Vector(0, y, 0));
}
}
} }
void turn(Kart kart) void accelerate(Kart kart)
{ {
double velocityLength = kart.getVelocity().length(); if (kart.isCrashed() || kart.getFrontWaysInput() <= 0)
if (velocityLength < 0.1)
{ {
return; return;
} }
float velocityInverse = (float) (2 - velocityLength); Vector velocity = kart.getVelocity();
float rotation = 3 * kart.getSidewaysInput() * velocityInverse;
kart.setYaw(kart.getYaw() - rotation); if (velocity.lengthSquared() == 0)
{
kart.setVelocity(UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(0.001 * kart.getFrontWaysInput()));
}
Vector acceleration = new Vector(velocity.getX(), 0, velocity.getZ());
if (acceleration.lengthSquared() > 0)
{
acceleration.normalize();
}
velocity.add(acceleration.multiply(0.01));
}
void brake(Kart kart)
{
if (kart.getFrontWaysInput() >= 0)
{
return;
}
kart.getVelocity().multiply(0.95);
}
void turn(Kart kart)
{
Vector velocity = kart.getVelocity();
double speed = velocity.length();
if (speed < 0.05)
{
return;
}
float velocityInverse = (float) (2 - speed);
float newYaw = kart.getYaw() - (3 * kart.getSidewaysInput() * velocityInverse);
kart.setYaw(newYaw);
Vector turn = UtilAlg.getTrajectory(newYaw, 0);
turn.subtract(new Vector(velocity.getX(), 0, velocity.getZ()).normalize()).multiply(0.033);
velocity.add(turn);
speed = (speed + (velocity.length() * 3)) / 4;
velocity.normalize().multiply(speed);
} }
void drift(Kart kart) void drift(Kart kart)
{ {
if (kart.getDriftDirection() != null && kart.getVelocity().lengthSquared() > 0) if (kart.isBoosting())
{ {
float power = 0.05F * (kart.getDriftDirection() == DriftDirection.LEFT ? kart.getSidewaysInput() : -kart.getSidewaysInput()); UtilParticle.PlayParticleToAll(ParticleType.FLAME, kart.getParticleLocation(), null, 0.1F, 2, ViewDist.NORMAL);
kart.setDriftPower(kart.getDriftPower() + power);
} }
else if (kart.getDriftPower() > 0.2)
if (!kart.canBoost())
{ {
Vector facing = UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(kart.getVelocity().length() + (kart.getDriftPower() / 2)); return;
}
if (kart.getDriftDirection() != null && kart.getVelocity().length() > 0.1)
{
float power = kart.getDriftPower() + (0.05F * (kart.getDriftDirection() == DriftDirection.LEFT ? kart.getSidewaysInput() : -kart.getSidewaysInput()));
if (power > 0.3)
{
UtilParticle.PlayParticleToAll(ParticleType.FIREWORKS_SPARK, kart.getParticleLocation(), null, 0.1F, power > 0.6 ? 2 : 1, ViewDist.NORMAL);
}
kart.setDriftPower(power);
}
else if (kart.getDriftPower() > 0.3)
{
Vector facing = UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(0.5 + (kart.getDriftPower() * 0.6));
kart.setVelocity(facing); kart.setVelocity(facing);
kart.setDriftLast(); kart.setDriftLast();
} }
@ -90,7 +174,7 @@ public class KartController
} }
} }
void applyTopSpeed(Kart kart) void applyTopSpeed(Kart kart, int position)
{ {
if (kart.isCrashed()) if (kart.isCrashed())
{ {
@ -99,14 +183,11 @@ public class KartController
Vector velocity = kart.getVelocity(); Vector velocity = kart.getVelocity();
double length = velocity.length(); double length = velocity.length();
double max = kart.isBoosting() ? 1.5 : 0.7; double max = kart.isBoosting() ? 1.5 : 0.7 + (position / 100F);
if (length > max) if (length > max)
{ {
kart.setVelocity(velocity.clone() velocity.multiply(0.98);
.setY(0)
.normalize()
.multiply(max));
} }
} }
} }

View File

@ -5,6 +5,7 @@ import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle; import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle;
@ -14,15 +15,20 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilEnt; import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilMath;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTextMiddle;
import mineplex.core.common.util.UtilTime; import mineplex.core.common.util.UtilTime;
import mineplex.core.packethandler.IPacketHandler; import mineplex.core.packethandler.IPacketHandler;
import mineplex.core.packethandler.PacketInfo; import mineplex.core.packethandler.PacketInfo;
import mineplex.core.updater.UpdateType; import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent; import mineplex.core.updater.event.UpdateEvent;
import mineplex.game.nano.NanoManager; import mineplex.game.nano.NanoManager;
import mineplex.game.nano.game.GamePlacements;
import mineplex.game.nano.game.GameType; import mineplex.game.nano.game.GameType;
import mineplex.game.nano.game.SoloGame; import mineplex.game.nano.game.SoloGame;
import mineplex.game.nano.game.event.PlayerGameApplyEvent; import mineplex.game.nano.game.event.PlayerGameApplyEvent;
@ -33,14 +39,47 @@ import mineplex.game.nano.game.games.minekart.KartController.DriftDirection;
public class MineKart extends SoloGame implements IPacketHandler public class MineKart extends SoloGame implements IPacketHandler
{ {
private static final int LAPS = 3;
private int _spawnIndex; private int _spawnIndex;
private final List<KartCheckpoint> _checkpoints, _keyCheckpoints; private final List<KartCheckpoint> _checkpoints, _keyCheckpoints;
private Location _faceLocation; private Location _faceLocation;
private final Map<Player, Kart> _karts; private final Map<Player, Kart> _karts;
private final List<Kart> _positions;
private final KartController _controller; private final KartController _controller;
private final Comparator<Kart> _positionSorter = (o1, o2) ->
{
boolean o1Complete = o1.getCompletedAt() != 0, o2Complete = o2.getCompletedAt() != 0;
if (o1Complete && o2Complete)
{
return Long.compare(o1.getCompletedAt(), o2.getCompletedAt());
}
else if (o1Complete)
{
return -1;
}
else if (o2Complete)
{
return 1;
}
if (o1.getLap() != o2.getLap())
{
return Integer.compare(o2.getLap(), o1.getLap());
}
if (o1.getLapKeyCheckpoint() != o2.getLapKeyCheckpoint())
{
return Integer.compare(o2.getLapKeyCheckpoint(), o1.getLapKeyCheckpoint());
}
return Integer.compare(o2.getLapCheckpoint(), o1.getLapCheckpoint());
};
public MineKart(NanoManager manager) public MineKart(NanoManager manager)
{ {
super(manager, GameType.MINEKART, new String[] super(manager, GameType.MINEKART, new String[]
@ -51,13 +90,72 @@ public class MineKart extends SoloGame implements IPacketHandler
_checkpoints = new ArrayList<>(); _checkpoints = new ArrayList<>();
_keyCheckpoints = new ArrayList<>(); _keyCheckpoints = new ArrayList<>();
_karts = new HashMap<>(); _karts = new HashMap<>();
_positions = new ArrayList<>();
_controller = new KartController(); _controller = new KartController();
_teamComponent.setAdjustSpawnYaw(false); _teamComponent.setAdjustSpawnYaw(false);
_damageComponent.setDamage(false); _damageComponent.setDamage(false);
_playerComponent.setHideParticles(true);
manager.getPacketHandler().addPacketHandler(this, PacketPlayInSteerVehicle.class); manager.getPacketHandler().addPacketHandler(this, PacketPlayInSteerVehicle.class);
_scoreboardComponent.setSidebar((player, scoreboard) ->
{
scoreboard.writeNewLine();
scoreboard.write(C.cYellowB + "Racers");
if (getState() == GameState.Prepare || _positions.isEmpty())
{
scoreboard.write(getAllPlayers().size() + " Players");
}
else
{
scoreboard.writeNewLine();
boolean hasShownPlayer = false;
for (int i = 0; i < Math.min(_positions.size(), hasShownPlayer ? 11 : 9); i++)
{
Kart kart = _positions.get(i);
Player other = kart.getDriver();
if (player.equals(other))
{
hasShownPlayer = true;
}
scoreboard.write(kart.getLap() + " " + (player.equals(other) ? C.cGreen : (UtilPlayer.isSpectator(other) ? C.cGray + C.Strike : C.cYellow)) + other.getName());
}
if (!hasShownPlayer)
{
Kart kart = null;
for (Kart other : _positions)
{
if (player.equals(other.getDriver()))
{
kart = other;
break;
}
}
if (kart != null)
{
scoreboard.writeNewLine();
scoreboard.write(kart.getLap() + " " + C.cGreen + player.getName());
}
}
}
scoreboard.writeNewLine();
scoreboard.draw();
});
} }
@Override @Override
@ -99,6 +197,12 @@ public class MineKart extends SoloGame implements IPacketHandler
_keyCheckpoints.sort(Comparator.comparingInt(KartCheckpoint::getIndex)); _keyCheckpoints.sort(Comparator.comparingInt(KartCheckpoint::getIndex));
} }
@Override
public boolean endGame()
{
return getAlivePlayers().isEmpty();
}
@Override @Override
public void disable() public void disable()
{ {
@ -161,6 +265,7 @@ public class MineKart extends SoloGame implements IPacketHandler
Kart kart = new Kart(player); Kart kart = new Kart(player);
_karts.put(player, kart); _karts.put(player, kart);
_positions.add(kart);
_worldComponent.setCreatureAllowOverride(false); _worldComponent.setCreatureAllowOverride(false);
}, 1); }, 1);
@ -178,6 +283,11 @@ public class MineKart extends SoloGame implements IPacketHandler
{ {
LivingEntity vehicle = kart.getVehicle(); LivingEntity vehicle = kart.getVehicle();
if (!vehicle.isValid())
{
return;
}
if (vehicle.getPassenger() == null || !vehicle.getPassenger().equals(player)) if (vehicle.getPassenger() == null || !vehicle.getPassenger().equals(player))
{ {
vehicle.setPassenger(player); vehicle.setPassenger(player);
@ -202,9 +312,25 @@ public class MineKart extends SoloGame implements IPacketHandler
if (checkpoint.getIndex() == 0 && kart.getLapKeyCheckpoint() == _keyCheckpoints.size() - 1) if (checkpoint.getIndex() == 0 && kart.getLapKeyCheckpoint() == _keyCheckpoints.size() - 1)
{ {
kart.setLap(kart.getLap() + 1); int lap = kart.getLap() + 1;
kart.setLapKeyCheckpoint(0); kart.setLapKeyCheckpoint(0);
player.sendMessage("Lap = " + kart.getLap());
if (lap == LAPS + 1)
{
kart.complete();
announce(F.main(getManager().getName(), F.name(player.getName()) + " completed the race in " + F.time(UtilTime.MakeStr(kart.getCompletedAt() - getStateTime())) + "!"), Sound.FIREWORK_BLAST);
addSpectator(player, false, true);
}
else
{
kart.setLap(lap);
boolean finalLap = lap == LAPS;
UtilTextMiddle.display(C.cYellowB + "Lap " + lap, finalLap ? C.cAquaB + "FINAL LAP" : "", 10, 40, 10, player);
player.sendMessage(F.main(getManager().getName(), "Lap " + F.count(lap) + (finalLap ? F.color(" FINAL LAP", C.cAquaB) : "") + "!"));
}
} }
} }
@ -215,28 +341,27 @@ public class MineKart extends SoloGame implements IPacketHandler
if (UtilTime.elapsed(kart.getCrashedAt(), 1000) && UtilEnt.isGrounded(kart.getVehicle())) if (UtilTime.elapsed(kart.getCrashedAt(), 1000) && UtilEnt.isGrounded(kart.getVehicle()))
{ {
kart.setCrashed(false); kart.setCrashed(false);
player.sendMessage("setCrashed(false)");
} }
else else
{ {
player.sendMessage("canControl = false");
canControl = false; canControl = false;
} }
} }
_controller.applyAirDrag(kart); _controller.applyAirResistance(kart);
_controller.collideBlock(kart);
// Accelerate // Accelerate
if (canControl) if (canControl)
{ {
_controller.turn(kart);
_controller.accelerate(kart); _controller.accelerate(kart);
_controller.brake(kart);
_controller.drift(kart); _controller.drift(kart);
_controller.applyTopSpeed(kart); _controller.turn(kart);
_controller.applyTopSpeed(kart, _positions.indexOf(kart));
} }
_controller.collideBlock(kart);
double velocityLength = kart.getVelocity().length(); double velocityLength = kart.getVelocity().length();
location.add(kart.getVelocity()); location.add(kart.getVelocity());
@ -248,6 +373,8 @@ public class MineKart extends SoloGame implements IPacketHandler
player.setLevel((int) (velocityLength * 100)); player.setLevel((int) (velocityLength * 100));
player.setExp(kart.getDriftPower()); player.setExp(kart.getDriftPower());
}); });
_positions.sort(_positionSorter);
} }
@EventHandler @EventHandler
@ -264,6 +391,14 @@ public class MineKart extends SoloGame implements IPacketHandler
} }
} }
@Override
public GamePlacements getGamePlacements()
{
return GamePlacements.fromTeamPlacements(_positions.stream()
.map(Kart::getDriver)
.collect(Collectors.toList()));
}
public KartCheckpoint getCheckpoint(int index) public KartCheckpoint getCheckpoint(int index)
{ {
return _checkpoints.stream() return _checkpoints.stream()