improved speed mechanic and bomb spawning, added countdown for last player

This commit is contained in:
2025-10-05 18:24:46 +02:00
parent dece9c13b7
commit 84de61388e
2 changed files with 39 additions and 16 deletions

View File

@@ -125,18 +125,26 @@ class TurtleGame extends StatelessGame {
} }
protected void explode(Player p, Entity bomb) { protected void explode(Player p, Entity bomb) {
Turtle turtle = this.turtlePlayerMap.get(p); this.letPlayerLoose(p);
p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.MASTER, 2f, 1f), bomb.getPosition()); p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.MASTER, 2f, 1f), bomb.getPosition());
p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.MASTER, 2f, 1f), bomb.getPosition()); p.playSound(Sound.sound(SoundEvent.ENTITY_GENERIC_EXPLODE, Sound.Source.MASTER, 2f, 1f), bomb.getPosition());
p.sendPacket(new ParticlePacket(Particle.EXPLOSION, p.getPosition(), new Pos(0.5, 0.5, 0.5), 0, 8)); p.sendPacket(new ParticlePacket(Particle.EXPLOSION, p.getPosition(), new Pos(0.5, 0.5, 0.5), 0, 8));
p.setGameMode(GameMode.SPECTATOR); if(this.getLeftPlayers().size() == 1) this.setTimeLimit(10);
p.setFlying(true);
turtle.destroy();
this.getScore().insertResult(p, this.turtlePlayerMap.get(p).getScore());
this.bombs.remove(bomb); this.bombs.remove(bomb);
bomb.remove(); bomb.remove();
} }
protected void letPlayerLoose(Player p) {
p.setGameMode(GameMode.SPECTATOR);
p.setFlying(true);
this.turtlePlayerMap.get(p).destroy();
this.getScore().insertResult(p, this.turtlePlayerMap.get(p).getScore());
}
protected List<Player> getLeftPlayers() {
return this.turtlePlayerMap.keySet().stream().filter(player -> !player.isFlying()).toList();
}
@Override @Override
protected boolean onPlayerJoin(Player p) { protected boolean onPlayerJoin(Player p) {
this.turtlePlayerMap.putIfAbsent(p, new Turtle(p, this.startSpeed)); this.turtlePlayerMap.putIfAbsent(p, new Turtle(p, this.startSpeed));
@@ -200,7 +208,7 @@ class TurtleGame extends StatelessGame {
meta.setCustomName(Component.text("Bomb").color(NamedTextColor.RED).decorate(TextDecoration.BOLD)); meta.setCustomName(Component.text("Bomb").color(NamedTextColor.RED).decorate(TextDecoration.BOLD));
meta.setCustomNameVisible(true); meta.setCustomNameVisible(true);
bomb.setInstance(this); bomb.setInstance(this);
Pos spawnPosition = this.newSpawnPosition(bomb, 2); Pos spawnPosition = this.newSpawnPosition(bomb, false);
if(spawnPosition == null) { if(spawnPosition == null) {
bomb.remove(); bomb.remove();
return; return;
@@ -211,11 +219,11 @@ class TurtleGame extends StatelessGame {
@Nullable @Nullable
private Pos newSpawnPosition(Entity entity) { private Pos newSpawnPosition(Entity entity) {
return this.newSpawnPosition(entity, 0); return this.newSpawnPosition(entity, true);
} }
@Nullable @Nullable
private Pos newSpawnPosition(Entity entity, double border) { private Pos newSpawnPosition(Entity entity, boolean nearPlayers) {
Pos spawnPosition; Pos spawnPosition;
int counter = 0; int counter = 0;
boolean isInRadius, collides; boolean isInRadius, collides;
@@ -227,10 +235,15 @@ class TurtleGame extends StatelessGame {
int z = this.rnd.nextInt(-this.radius+2, this.radius-2); int z = this.rnd.nextInt(-this.radius+2, this.radius-2);
spawnPosition = new Pos(x, 1, z).add(0.5, 0, 0.5); spawnPosition = new Pos(x, 1, z).add(0.5, 0, 0.5);
Pos checkPosition = spawnPosition; Pos checkPosition = spawnPosition;
isInRadius = checkPosition.distance(0, 1, 0) < this.radius-3; isInRadius = checkPosition.distance(0, 1, 0) < this.radius-2;
collides = this.getEntities().stream() collides = this.getEntities().stream()
.filter(e -> !e.equals(entity)) .filter(e -> !e.equals(entity))
.anyMatch(e -> entity.getBoundingBox().growSymmetrically(border, border, border).intersectBox(e.getPosition().sub(checkPosition), e.getBoundingBox())); .anyMatch(e -> entity.getBoundingBox().intersectBox(e.getPosition().sub(checkPosition), e.getBoundingBox()));
if(!collides && !nearPlayers) collides = this.turtlePlayerMap.values().stream()
.filter(turtle -> !turtle.equals(entity))
.anyMatch(turtle -> entity.getBoundingBox()
.growSymmetrically(turtle.getBombBorder(), 1, turtle.getBombBorder())
.intersectBox(turtle.getPosition().sub(checkPosition), turtle.getBoundingBox()));
counter++; counter++;
} while (!isInRadius || collides); } while (!isInRadius || collides);
return spawnPosition; return spawnPosition;
@@ -242,4 +255,9 @@ class TurtleGame extends StatelessGame {
this.generateNewBomb((int) Math.ceil(this.snacks.size() * 0.5)); this.generateNewBomb((int) Math.ceil(this.snacks.size() * 0.5));
this.turtlePlayerMap.values().forEach(Turtle::startBoostRefill); this.turtlePlayerMap.values().forEach(Turtle::startBoostRefill);
} }
@Override
protected void onStop() {
this.getLeftPlayers().forEach(this::letPlayerLoose);
}
} }

View File

@@ -14,7 +14,7 @@ public class Turtle extends EntityCreature {
private final Player player; private final Player player;
private int score = 0; private int score = 0;
private double speed; private double speed;
private final double boostSpeedAmount = 4; private double boostSpeedMultiplier = 1;
private float boostChargeLevel = 0f; private float boostChargeLevel = 0f;
private Task boostTask; private Task boostTask;
private Task boostRefillTask; private Task boostRefillTask;
@@ -47,8 +47,8 @@ public class Turtle extends EntityCreature {
this.removePassenger(this.player); this.removePassenger(this.player);
this.remove(); this.remove();
this.kill(); this.kill();
this.boostRefillTask.cancel(); if(this.boostRefillTask.isAlive()) this.boostRefillTask.cancel();
this.boostTask.cancel(); if(this.boostTask.isAlive()) this.boostTask.cancel();
} }
public void adaptView() { public void adaptView() {
@@ -60,7 +60,7 @@ public class Turtle extends EntityCreature {
public void move() { public void move() {
this.adaptView(); this.adaptView();
Vec direction = this.player.getPosition().direction(); Vec direction = this.player.getPosition().direction();
Vec movementVector = direction.withY(0).normalize().mul(this.speed); Vec movementVector = direction.withY(0).normalize().mul(this.speed * this.boostSpeedMultiplier);
this.setVelocity(movementVector); this.setVelocity(movementVector);
} }
@@ -70,7 +70,7 @@ public class Turtle extends EntityCreature {
public void boostSpeed() { public void boostSpeed() {
if(this.boostChargeLevel <= 0f) return; if(this.boostChargeLevel <= 0f) return;
this.speed += this.boostSpeedAmount; this.boostSpeedMultiplier = 3.5;
this.boostTask = MinecraftServer.getSchedulerManager().scheduleTask(() -> { this.boostTask = MinecraftServer.getSchedulerManager().scheduleTask(() -> {
if(this.boostChargeLevel <= 0f) { if(this.boostChargeLevel <= 0f) {
this.cancelBoost(); this.cancelBoost();
@@ -85,7 +85,7 @@ public class Turtle extends EntityCreature {
public void cancelBoost() { public void cancelBoost() {
if(!this.boostTask.isAlive()) return; if(!this.boostTask.isAlive()) return;
this.boostTask.cancel(); this.boostTask.cancel();
this.speed -= this.boostSpeedAmount; this.boostSpeedMultiplier = 1;
} }
public void addSpeed(double amount) { public void addSpeed(double amount) {
@@ -96,6 +96,11 @@ public class Turtle extends EntityCreature {
return this.score; return this.score;
} }
public double getBombBorder() {
// 1 bei speed 2; 2 bei speed 4; 4 bei speed 8
return Math.clamp((this.speed * this.boostSpeedMultiplier) / 2, 1.5, 4);
}
public void increaseScore() { public void increaseScore() {
this.score += 1; this.score += 1;
this.player.setLevel(this.score); this.player.setLevel(this.score);