Keep jumps at natural sprint distance, grow new blocks out of the top of the previous one and show one more preview block
This commit is contained in:
1 parent
452f2f3ef7
commit
b1950dd664
2 files changed
+31
-18
No files matched your search
@@ -10,27 +10,35 @@ import net.minestom.server.instance.block.Block;
|
|||||||
import net.minestom.server.timer.TaskSchedule;
|
import net.minestom.server.timer.TaskSchedule;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lässt einen neuen Block als Block-Display aus dem vorherigen Block „herauswachsen“ und
|
* Lässt einen neuen Block als Block-Display klein oben aus dem vorherigen Block herauswachsen
|
||||||
* zu seiner Zielposition gleiten. Erst bei Ankunft wird der echte Block gesetzt.
|
* und zu seiner Zielposition gleiten. Erst bei Ankunft wird der echte Block gesetzt.
|
||||||
*/
|
*/
|
||||||
public class BlockTransition {
|
public class BlockTransition {
|
||||||
private static final int DURATION_TICKS = 8;
|
public static final int DURATION_TICKS = 8;
|
||||||
|
/** Zeit vom Start bis der echte Block steht (Spawn-Vorlauf + Animation + Puffer). */
|
||||||
|
public static final int TOTAL_TICKS = DURATION_TICKS + 3;
|
||||||
private static final double START_SCALE = 0.3;
|
private static final double START_SCALE = 0.3;
|
||||||
|
|
||||||
public static void animate(Instance world, Pos from, Pos to, Block block, Runnable onArrival) {
|
public static void animate(Instance world, Pos from, Pos to, Block block, int delayTicks, Runnable onArrival) {
|
||||||
|
world.scheduler().buildTask(() -> spawn(world, from, to, block, onArrival))
|
||||||
|
.delay(TaskSchedule.tick(Math.max(1, delayTicks)))
|
||||||
|
.schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void spawn(Instance world, Pos from, Pos to, Block block, Runnable onArrival) {
|
||||||
Entity display = new Entity(EntityType.BLOCK_DISPLAY);
|
Entity display = new Entity(EntityType.BLOCK_DISPLAY);
|
||||||
display.setNoGravity(true);
|
display.setNoGravity(true);
|
||||||
display.editEntityMeta(BlockDisplayMeta.class, meta -> {
|
display.editEntityMeta(BlockDisplayMeta.class, meta -> {
|
||||||
meta.setBlockState(block);
|
meta.setBlockState(block);
|
||||||
meta.setPosRotInterpolationDuration(DURATION_TICKS);
|
meta.setPosRotInterpolationDuration(DURATION_TICKS);
|
||||||
meta.setTransformationInterpolationDuration(DURATION_TICKS);
|
meta.setTransformationInterpolationDuration(DURATION_TICKS);
|
||||||
// klein und mittig im Ursprungsblock starten
|
// klein und mittig auf der Oberseite des vorherigen Blocks starten
|
||||||
meta.setScale(new Vec(START_SCALE));
|
meta.setScale(new Vec(START_SCALE));
|
||||||
meta.setTranslation(new Vec((1 - START_SCALE) / 2));
|
meta.setTranslation(new Vec((1 - START_SCALE) / 2, 1, (1 - START_SCALE) / 2));
|
||||||
});
|
});
|
||||||
|
|
||||||
display.setInstance(world, from).thenRun(() -> {
|
display.setInstance(world, from).thenRun(() -> {
|
||||||
// einen Moment warten, damit der Client das Display kennt, bevor die Interpolation startet
|
// kurz warten, damit der Client das Display kennt, bevor die Interpolation startet
|
||||||
display.scheduler().buildTask(() -> {
|
display.scheduler().buildTask(() -> {
|
||||||
display.editEntityMeta(BlockDisplayMeta.class, meta -> {
|
display.editEntityMeta(BlockDisplayMeta.class, meta -> {
|
||||||
meta.setTransformationInterpolationStartDelta(0);
|
meta.setTransformationInterpolationStartDelta(0);
|
||||||
@@ -43,7 +51,7 @@ public class BlockTransition {
|
|||||||
display.scheduler().buildTask(() -> {
|
display.scheduler().buildTask(() -> {
|
||||||
onArrival.run();
|
onArrival.run();
|
||||||
display.remove();
|
display.remove();
|
||||||
}).delay(TaskSchedule.tick(DURATION_TICKS + 3)).schedule();
|
}).delay(TaskSchedule.tick(TOTAL_TICKS)).schedule();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,7 @@ public class JumpGenerator {
|
|||||||
|
|
||||||
private int combo = 0;
|
private int combo = 0;
|
||||||
|
|
||||||
private final int preview = 2;
|
private final int preview = 3;
|
||||||
|
|
||||||
private static final int FULL_DIFFICULTY_AT = 1000;
|
private static final int FULL_DIFFICULTY_AT = 1000;
|
||||||
|
|
||||||
@@ -37,6 +37,10 @@ public class JumpGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateNext() {
|
public void generateNext() {
|
||||||
|
this.generateNext(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateNext(int animationDelayTicks) {
|
||||||
boolean isTenth = this.blocks.size() % 10 == 0;
|
boolean isTenth = this.blocks.size() % 10 == 0;
|
||||||
boolean standingTenth = (this.blocks.size()-this.preview-1) % 10 == 0;
|
boolean standingTenth = (this.blocks.size()-this.preview-1) % 10 == 0;
|
||||||
boolean isHundredth = this.blocks.size() % 100 == 0;
|
boolean isHundredth = this.blocks.size() % 100 == 0;
|
||||||
@@ -51,7 +55,7 @@ public class JumpGenerator {
|
|||||||
Pos previous = blocks.get(blocks.size()-1);
|
Pos previous = blocks.get(blocks.size()-1);
|
||||||
Pos target = previous.add(this.nextOffset(index, r));
|
Pos target = previous.add(this.nextOffset(index, r));
|
||||||
Block block = isHundredth ? Block.DIAMOND_BLOCK : isTenth ? Block.GOLD_BLOCK : BlockPalette.getRandom(index, r);
|
Block block = isHundredth ? Block.DIAMOND_BLOCK : isTenth ? Block.GOLD_BLOCK : BlockPalette.getRandom(index, r);
|
||||||
BlockTransition.animate(this.world, previous, target, block, () -> {
|
BlockTransition.animate(this.world, previous, target, block, animationDelayTicks, () -> {
|
||||||
this.world.setBlock(target, block);
|
this.world.setBlock(target, block);
|
||||||
this.world.setBlock(target.add(0, 1, 0), Block.LIGHT);
|
this.world.setBlock(target.add(0, 1, 0), Block.LIGHT);
|
||||||
this.player.sendPacket(new ParticlePacket(Particle.CRIT, target, target.add(0.5), 1, 10));
|
this.player.sendPacket(new ParticlePacket(Particle.CRIT, target, target.add(0.5), 1, 10));
|
||||||
@@ -76,16 +80,15 @@ public class JumpGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstand zum nächsten Block. Die Schwierigkeit steigt über die ersten {@link #FULL_DIFFICULTY_AT}
|
* Abstand zum nächsten Block. Sprünge sind immer mindestens 3 weit (natürliche Sprint-Weite,
|
||||||
* Sprünge von leicht (2–3 weit, kaum seitlich/aufwärts) bis zum bisherigen Niveau (3–4 weit,
|
* kürzere werden überjumpt). Über die ersten {@link #FULL_DIFFICULTY_AT} Sprünge steigen der
|
||||||
* oft seitlich und aufwärts) und bleibt danach dort.
|
* Anteil an 4er-Sprüngen, seitlichen Versätzen und Sprüngen nach oben bis zum bisherigen
|
||||||
|
* Niveau und bleiben danach dort.
|
||||||
*/
|
*/
|
||||||
private Pos nextOffset(int index, Random r) {
|
private Pos nextOffset(int index, Random r) {
|
||||||
double difficulty = Math.min(1.0, (double) index / FULL_DIFFICULTY_AT);
|
double difficulty = Math.min(1.0, (double) index / FULL_DIFFICULTY_AT);
|
||||||
|
|
||||||
int dz = 2;
|
int dz = r.nextDouble() < 0.1 + 0.4 * difficulty ? 4 : 3;
|
||||||
if(r.nextDouble() < 0.5 + 0.5 * difficulty) dz++;
|
|
||||||
if(r.nextDouble() < 0.5 * difficulty) dz++;
|
|
||||||
|
|
||||||
int dx = r.nextDouble() < 0.1 + 0.57 * difficulty ? (r.nextBoolean() ? 1 : -1) : 0;
|
int dx = r.nextDouble() < 0.1 + 0.57 * difficulty ? (r.nextBoolean() ? 1 : -1) : 0;
|
||||||
|
|
||||||
@@ -95,7 +98,8 @@ public class JumpGenerator {
|
|||||||
if(roll < 0.05 + 0.28 * difficulty && y <= 120) dy = 1;
|
if(roll < 0.05 + 0.28 * difficulty && y <= 120) dy = 1;
|
||||||
else if(roll > 1 - (0.2 + 0.13 * difficulty) && y >= 80) dy = -1;
|
else if(roll > 1 - (0.2 + 0.13 * difficulty) && y >= 80) dy = -1;
|
||||||
|
|
||||||
// weite Diagonalsprünge nach oben erst gegen Ende
|
// weite Sprünge nach oben erst ab mittlerer, diagonal erst ab hoher Schwierigkeit
|
||||||
|
if(dy == 1 && dz == 4 && difficulty < 0.4) dz = 3;
|
||||||
if(dy == 1 && dz == 4 && dx != 0 && difficulty < 0.7) dx = 0;
|
if(dy == 1 && dz == 4 && dx != 0 && difficulty < 0.7) dx = 0;
|
||||||
|
|
||||||
return new Pos(dx, dy, dz);
|
return new Pos(dx, dy, dz);
|
||||||
@@ -111,7 +115,8 @@ public class JumpGenerator {
|
|||||||
this.checkpoint = start;
|
this.checkpoint = start;
|
||||||
this.blocks.add(this.starting);
|
this.blocks.add(this.starting);
|
||||||
this.world.setBlock(this.starting, Block.DIAMOND_BLOCK);
|
this.world.setBlock(this.starting, Block.DIAMOND_BLOCK);
|
||||||
for(int i = 0; i <= preview; i++) generateNext();
|
// nacheinander animieren, damit jeder Block aus seinem bereits stehenden Vorgänger wächst
|
||||||
|
for(int i = 0; i <= preview; i++) generateNext(i * BlockTransition.TOTAL_TICKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
|
|||||||
Reference in new issue
Block a user