Tutorial Set players velocity to go in a parabolic motion to another location.

Discussion in 'Resources' started by ChipDev, Dec 10, 2014.


Do you use this?

  1. No!

  2. Yes!

  3. Cats.

Thread Status:
Not open for further replies.
  1. Offline


    First off: I want to thank this thread for doing all of this work; Some people requested it to be in the resources section, so I cleaned it up a bit. Thanks to @Hellsing and @Sethbling for writing it in python!
    What this does:

    This allows you to set a vector to an entity, to get it to a certain location with a certain hight on the way!
    Code (Again, thanks to sethbling and Hellsing!):
    public static Vector calculateVelocity(Vector from, Vector to, int heightGain)
            // Gravity of a potion
            double gravity = 0.115;
            // Block locations
            int endGain = to.getBlockY() - from.getBlockY();
            double horizDist = Math.sqrt(distanceSquared(from, to));
            // Height gain
            int gain = heightGain;
            double maxGain = gain > (endGain + gain) ? gain : (endGain + gain);
            // Solve quadratic equation for velocity
            double a = -horizDist * horizDist / (4 * maxGain);
            double b = horizDist;
            double c = -endGain;
            double slope = -b / (2 * a) - Math.sqrt(b * b - 4 * a * c) / (2 * a);
            // Vertical velocity
            double vy = Math.sqrt(maxGain * gravity);
            // Horizontal velocity
            double vh = vy / slope;
            // Calculate horizontal direction
            int dx = to.getBlockX() - from.getBlockX();
            int dz = to.getBlockZ() - from.getBlockZ();
            double mag = Math.sqrt(dx * dx + dz * dz);
            double dirx = dx / mag;
            double dirz = dz / mag;
            // Horizontal velocity components
            double vx = vh * dirx;
            double vz = vh * dirz;
            return new Vector(vx, vy, vz);
    If you scanned the whole code, you may of saw the 'distanceSquared' method. Here it is:
    private static double distanceSquared(Vector from, Vector to)
            double dx = to.getBlockX() - from.getBlockX();
            double dz = to.getBlockZ() - from.getBlockZ();
            return dx * dx + dz * dz;
    And how to use it:
    Bukkit.getPlayer("Kanss").setVelocity(calculateVelocity(Bukkit.getPlayer("Kanss").getLocation().toVector(), new Location(*YOURLOCATION*), *HEIGHT* 6));
    This will shoot me of into the lands!
    Thanks for reading,

    This is ALSO a resource that we may want, this could be a good search tool, helpful, so I'll try and merge gravities into this!

    double gravity = 0.667;
    double gravity = 0.115;
    Make sure to replace gravity with the type you want, or you can use an enum and use it in your code:
    Show Spoiler

    public enum GravityType {
            POTION(0.115), PLAYER(0.667);
            private double g;
            private GravityType(double s) {
                g = s;
            public double getValue() {
                return g;

    Please tell me more, so we can all work on this!
    Last edited: Dec 13, 2014
  2. Offline


    1 Problem, I tried this a few weeks ago, and the gravity of a player is not 0.115, so this will not shoot the player to the requested location.
    First find out the actual gravity of a player.

    With trial and error I found the gravity of a FallingBlock entity is 0.37.
    ChipDev likes this.
  3. Offline


    Aqua likes this.
  4. Offline


    AdamQpzm likes this.
  5. Offline


  6. Offline


  7. Offline


    It seems that it doesn't work that well for players when you use big distances between 'from' and 'to'. If I choose a distance of e.g. 40 blocks and a heightGain of 20 blocks i end up at a distance of 30 blocks and my flight is not parabolic. I would guess that there's a problem with air resistance.
  8. Offline


    Yes, But not for potions.
  9. Offline


    Potions should have air resistence as well: means they as well don't fly in a perfect parabolic curve, like the used formula expects it. This should be noticeable if you try this with higher distances.

    In this thread I have mentioned how I have tried to accomplish this for longer distances (100+ blocks range) in the past. Though the shown code there, while it seems to work quite well, is slightly outdated already: I have applied some improvements to it in the meantime (those mostly affect the table creation and how the gaps between different curves and for fast projectiles are filled) though I wasn't yet able to test those improvements and verify their correctness. But the basic idea is still the same.
Thread Status:
Not open for further replies.

Share This Page