Velocity Direction?

Discussion in 'Plugin Development' started by Jayjay110, Jun 4, 2011.

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

    Jayjay110

    If I had block A, and Block B, and I wanted to send an entity with the correct velocity and a variable speed to hit block B, how would I do this? I dont want to do teleport the entity because that kinda ruins the effect :3 Any Ideas?
     
  2. Offline

    DreadKyller

    get the locations of the blocks and make a new Vector out of them:

    Vector vec1 = location1.toVector();
    repeat for #2

    then se the subtract(Vector) method for the second vector. take the target vector and subtract the start vector.

    let's say vec1 is the starting vector, and vec2 is the target:

    Vector pre_velocity = vec2.subtract(vec1);

    then you don't want to go instantly, so like divide it by 10 or something:

    Vector velocity = pre_velocity.multiply(0.1);

    then sert the velocity
     
  3. Offline

    Jayjay110

    WOOT, U are the best :p
     
  4. Offline

    DreadKyller

    @Jayjay110 : actually no where near it. Helping others helps yourself, that's why I like doing it, someone has a problem? that's an opportunity to find it out for yourself as well
     
    Jayjay110 likes this.
  5. Offline

    Jayjay110

    Cant get this to make it move to the point slowly?

    Ok, so if I wanted to fire a projectile in the direction of a point and I have 2 points, A My location, and B the location 5 blocks in front of me, how would I be able to fire the projectile at say 1 block a second, OR how would I be able to get the same effect as a bow and arrow but be able to adjust the power?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 16, 2016
  6. Offline

    nisovin

    That's what the .multiply() is for. Changing the amount you multiply by will change the speed of your projectile.
     
  7. Offline

    DreadKyller

    that's why I put the multipy(0.1) to make it one tenth of the distance, you can change that decimal to make it even slower, the only defect of that method is that it will decelerate as it gets closer to the target

    here is one solution that will give you a constant direction

    PHP:
        public Vector straighten(Vector vecdouble speed){
            
    double x vec.getX();
            
    double y vec.getY();
            
    double z vec.getZ();
            
    double nx x/max(xyz);
            
    double ny y/max(xyz);
            
    double nz z/max(xyz);
            
    nx*=speed;
            
    ny*=speed;
            
    nz*=speed;
            return new 
    Vector(nxnynz);
        }
        public 
    double max(double xdouble ydouble z){
            if((
    x>&& x>z)||((x==y)&&x>z)||((x==z)&&x>y)){
                return 
    x;
            }
            if((
    y>&& y>z)||((y==x)&&y>z)||((y==z)&&y>x)){
                return 
    y;
            }
            if((
    z>&& z>y)||((z==x)&&z>y)||((z==y)&&z>x)){
                return 
    z;
            }
            return 
    0;
        }
    call that with like 1 as speed or 2 to go faster, no value will be more than 1.0 if you use speed=1
     
  8. Offline

    Shamebot

    @DreadKyller What does this method? BTW it will crash for x==y==z.
    If you want to have a direction independent velocity you can use Vector.normalize().
    Edit:
    If your max method is supposed to return the maximum value (I didn't check this, but it should by the name) I think it's a bit complicated implemented.
    Code:
    double max(double... args)
    {
        double max = null;
        for(double d :  args)
        {
            if(max == null || d > max)
                d = max;
        }
        return max;
    }
     
  9. Offline

    DreadKyller

    doesn't normalize basically round it to the closest 90 degreese, and no it does not crash @Shamebot it's not x==y==z it's (x==y)||(y==z)||(z==x) and stuff like that, look at the ands and ors in it. I use that script a lot and it works 100% every time I use it. while normalize seems to just takes the closest 90 degreese and user that.

    (y>x && y>z)||((y==x)&&y>z)||((y==z)&&y>x)

    What this does is:

    first : checks to see if y > x and if y > z, in otherwords x < y > z, only that would not work

    second : if y is equal to x, and y > z

    third : if y is equal to z and more than x

    the reason for these are:

    if both x and y for example are 16 then the x>y will not activate, so to make sure that two coordinates are equal and are both higher than the other number. I did forget one thing, if x y and z are equal it will just return 0, make it return any of the numbers, because that means they are the same, divide by the number will give you correct number anyways.

    the max(x, y, z) basically returns the highest number out of 3 numbers, simmilar to the Math.max, only that one can only have two numbers, of coarse you can replace it with:

    return Math.max(Math.max(x, y), z)

    but the script does work and it does not crash. @Shamebot, did you even test it before posting that it crashes? if so then strange results, it does not crash it only any plugin i've use it on.
     
  10. Offline

    Shamebot

    I'm familiar with boolean maths.
    See?
    Crash...Ok, I have to admit that it's unlikely, but still...
    Also normalize won't round to the next 90°, it will set the length of the vector to 1.
     
  11. Offline

    DreadKyller

    strange, that's what normalize always does to me, If I'm facing 30 degrees in some direction and I set the player velocity to my direction normalized I move diagonal and not straight ahead, because I'm moving along a perfectly aligned line, like the only number changing if the x location for example.

    also, unlikely? how about almost impossible, that max() method will complete in a few milliseconds... expecially if you use the other way I mentioned:

    PHP:
    public double max(double xdouble ydouble z){
        return 
    Math.max(Math.max(xy), z);
    }
    cause to just tell you, I looked at the source of the normalize and you're right it does do what you are saying, but it never seems to do that when I use it, it does something completely strange, I'll have to tape it sometime. but anyways, while looking at the source, its practically the same thing as the code I posted, if finds the max number out of the x y and z and divides everything by it to make the highest number 1.0, if anything it's actually a bit longer than the one I posted but same basic idea.
     
  12. Offline

    Shamebot

    What has the time to calculate it to do with division by zero?
    :eek:
    Code:
    public Vector normalize() {
            double length = length();
    
            x /= length;
            y /= length;
            z /= length;
    
            return this;
        }
     
  13. Offline

    DreadKyller

    ... I said I made a mistake and if you read you'll see I said to replace the return 0 with return any of the x y or z cause the only time it will get to that point is if all the numbers are the same, so therefore it does not matter what you input.

    hey, and if you look at length it returns the highest fkin number of the 3 axises, like I said basically the same thing.
     
  14. Offline

    Shamebot

    Code:
        public double length() {
            return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
        }
     
  15. Offline

    DreadKyller

    yes, exactly, you know math? first off the quare root of all of the axises squared and then added will give you the distance from 0, 0, 0, if you do the math you will find out that's actually what it returns, like the distance between two points it the square root of the x1 - x2 squared plus the y1-y2 squared plus the z1-z2 squared and that gives you the distance between two points, this works very simmilar, but in the distance it's getting the difference on all axises and using that, so if you had a vector that was 5, 5, 5 and one that was 2, 2, 2 and you got sistance, it basically fids the distance from 0 to 3, 3, 3. this will find the distance from 0, 0, 0 to the vector and then divide it by that. for simple math let's go with this example:

    Vector vec = new Vector(0, 5, 0);
    int dist = vect.normalize()//get the distance to 0, 0, 0 in this case 5
    vex.setX(vec.getX()/dist);// 0 / 5 = 0
    vex.setY(vec.getY()/dist);// 5 / 5 = 1
    vex.setZ(vec.getZ()/dist);// 0 / 5 = 0

    and you get the vector forward in one unit, because using the distance from the center and dividing them all by it as you see there works, now let me show you an example of my script:

    double x=2;
    double y = 6;
    double z = 1;
    Vector vec = new Vector(x, y, z);
    double maxn = max(x, y, z);//in this case 6
    x /= maxn;//new x = 0.33333333333
    y /= maxn;//new y = 1
    z /= maxn;//new z = 0.16666666

    and if you do the math on that you'll find out that it keeps the same ratio. they both work a little different but give the same result. Also as I was told before by others, it's always faster to use if statements than to use something that has trigonometry and semi advanced math. in my script it only calls one method, as compared to using normalize it calls sqrt() and pow() 3 times, 4 methods in there, and they take some more elaborate math, etc... all around, even if maybe by only a few millisecs the script I posted is a little faster, while giving save result.

    @Shamebot @ youredit, yes, that is definatly a better choice if there is going to be more than 3 args or not 3 exactly, but I made that specifically for vecorts, in which I actualy am now saying:

    PHP:
    public double max(double xdouble ydouble z){
        return (double)
    Math.max(Math.max(xy), z);
    }
    is the best way to go probably.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 16, 2016
  16. Offline

    Shamebot

    normalize() returns a vector, with the length 1.

    Example your method:
    double x = 10, y = 11, z = 10;
    double max = max(x,y,z);//in this case 11
    double length = ((x/max)^2+(y/max)^2+(z/max)^2)^0.5;//=1.62877026

    I'm not really satisfied with it, will waste some memory for the iterator^^Edit2:not true, arrays don't implement iterable
    Edit: and it's reusable when you're calculating vectors with string theory dimensions^^

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 16, 2016
  17. Offline

    DreadKyller

    @Shamebot : lol, you should be satified, it
    s not too bad, it's a for loop, what's the harm much in it?

    Also, normalize gets a vector with the highest value of 1, not the length of one, the length init will be different depending on the location. if you do not know math well you should look into yourself what getting the square root of a number squared does. the length() returns the distance that vector is from 0, 0, 0, but because of math, say it's different as much as you want, but once you actualy do the math you'll find out that that's exactly what it does. My point I'm trying to make, not any other at this point, so we should stop going into. and also, this:

    double length = ((x/max)^2+(y/max)^2+(z/max)^2)^0.5;//=1.62877026

    ... dude, if you do not believe that my method works, then try it, I've used it for TWO MONTHS and have not had a single problem with it. They Both work, they work differently, but they both work. We are crowding this post with us basically fighting back and forth about this.

    My points :
    *they both work
    *the length() returns the distance to 0, 0, 0
    *using if statements is faster than going through a lot of math and voids

    I will give a demo below in a spoiler with some math in it to show it, but I'll use both methods and show they give very simmilar results.

    Show Spoiler


    My Method:

    ------------------------------------
    vector of 6, 5, 4

    the max value is 6, so that's what will be returned by the max(x, y, z)

    6/6=1
    5/6=0.8333333333
    4/6=0.6666666666

    if this works x/y should be the same as nx/ny and so on with y/z = ny/nz and z/x=nz/nx

    6/5 = 1.2// (x/y)
    1/0.8333 = 1.2// (nx/ny)

    x/y and nx/ny are equal, same ratio

    5/4 = 1.25// (y/z)
    1/0.6666 = 1.25// (ny/nz)

    y/z and ny/nz are equal, same ratio

    4/6 = 0.66666.....// (z/x)
    0.66666...../1 = 0.66666.....// (nz/nx)

    z/x and nz/nx are equal, same ratio

    all three are the same ratio, meaning they are pointing in same direction, only the max length is 1. they both are the same angle.

    ---------------------------------

    normalize

    --------------------------------


    vector of 6, 5, 4 (same as above)

    length of vector = (x^2 + y^2 + z^2)^0.5 = 8.77496438739

    6/8.77496438739 = 0.68376345875799304837502159439063
    5/8.77496438739 = 0.56980288229832754031251799532553
    4/8.77496438739 = 0.45584230583866203225001439626042

    6/5=1.2
    0.68376345875799304837502159439063/0.56980288229832754031251799532553=1.2

    5/4 = 1.25
    0.56980288229832754031251799532553/0.45584230583866203225001439626042=1.25

    4/6 = 0.66666.....
    0.45584230583866203225001439626042/0.68376345875799304837502159439063=0.66666.....

    ----------------------------------------

    As you see, both methods return the exact same diraction, but mine has the max number a perfect 1.0 as compared to the normalize method which gives the same direction, but here is the difference with he two

    normalize = Vector(~0.68376345875, ~0.56980288229, ~0.45584230583)
    straighten = Vector(1, 0.833333....., 0.66666.....)

    if you were a computer which would you rather handle? Which do you think would be quicker to calculate? the calculators and stuff hold a max amount, but the normalize method, in most cases the number would be extremely long if it kept calculating.

    So period, they both work, use which ever one, if you use the normalize method you will move an exact 1 unit even at angles, but my method will create less lag and still be just as accurate in the direction it goes in.
     
  18. Offline

    Shamebot

    Show Spoiler

    I'm not sure what your method is supposed to do, that's why I initially asked.
    If its purpose is to give a vector whose direction is the same but with the length 1, I would have to say that I'm pretty sure it doesn't. If it should return a vector with a constant length, regardless of its inputs, I would have to say so either.
    I suggested to use normalize() to get a direction independent vector, meaning its length is independent from the direction. normalize does that, the returning vector has always a length of 1.
    ((x/((x^2+y^2+z^2)^.5))^2+(y/((x^2+y^2+z^2)^.5))^2+(z/((x^2+y^2+z^2)^.5))^2)^2=((x^2+y^2+z^2)/(x^2+y^2+z^2))^.5=1
    You're right when you say normalize is slower, it's because of Math.sqrt(..) and Math.pow(number,2), Bukkit should use number*number, that's ways faster.
    I would be to lazy to code my own method just to save some nanoseconds a few times, and I'm always trying to save performance and memory, honestly I am/was coding a map api where you can send pictures to the 1.6 map, I've been using bytes and shorts everywhere to save memory, if that's sensible is another question^^.
     
  19. Offline

    Jayjay110

    Im confused, which one is correct?
     
  20. Offline

    DreadKyller

    @Jayjay110 : both would work

    @Shamebot : mine does not return a vector with the length of one, it returns one with the max number being one, there is a difference, however it works for the purpose of having a constant velocity no matter how close you get to the target. @Jayjay110 : I guess use normalize so that this conversation can stop. All I did was make an example of a script that would give you a vector that was a constant speed towards a point independant of the distance, the ONLY difference in the two is the following:

    With Normalize : you will move a perfect 1 unit every time, however, the numbers that computer will be procesing are like 0.877582162681267128956716481246123125571269964986762515231625616192612416245.

    With My Method : you will move exactly 1 unit if facing in a 90 degrees direction, and a little bit faster (~0.4 unit more) when facing in any angle of a 45. Hoewever the numbers that the computer has to process are like 0.75

    So here's the final statement:

    Normalize : more exact
    Mine : Less lag, off on accuracy by ~0.4

    PHP:
    public Vector straighten(Vector vec){
        
    double length Math.pow((x*x)+(y*y)+(z*z), 0.5);

        
    double x vec.getX() /= length;
        
    double y vec.getY() /= length;
        
    double z vec.getZ() /= length;

        
    Vector newvec = new Vector(xyz)

        return 
    newvec;
    there we go, will return same exact thing as normalize only it calls only two methods, a constructor and Math.pow

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 16, 2016
  21. Offline

    Jayjay110

    Thankyou, so this means I get the position of both, subtract it and then put it in this method right?
     
  22. Offline

    DreadKyller

    exactly, take the target vector and do this:

    Vector velocity = straighten(target.subtract(current));

    then set the player velocity

    btw, @Shamebot I do not think using shorts and bytes save any space when the value they are set to isn't high, if you had a double, integer, byte, short, long, and a float that were all of value 5, they would take the same amount of space, just some are needed if the max size is intended to be higher or shorter. but fairly good precaution

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 16, 2016
  23. Shorts and bytes would save space. A float would need more memory as it would need more bytes because it has more decimal points, a byte however would only need 1 byte of memory whereas a float or double will probably need around 5-8 bytes.
     
  24. Offline

    Shamebot

    They allocate different amounts of bits, the problem is that I needed to cast all the time, because when you add something to a byte it is an int and you need to cast it back to byte and I don't know whether casting costs performance.
     
  25. Offline

    DreadKyller

    I don't belive casting looses proforments, but I could be wrong, casting basically tells the program which subclass to use and such, something can only be cast to it's subclass or superclass right? tell me if I'm wrong.
     
  26. Offline

    Shamebot

    Since I'm using primitives, classes don't matter, but we should stop spamming this thread, this is totally unrelated.
     
  27. Offline

    DreadKyller

    I said that exact same thing like 8 posts up...
     
  28. Casting an int would increase memory because an int, typically storing 2/4 bytes to a float which stores 4/8 bytes. Conversely casting float to int would free-up memory.
     
  29. Offline

    DreadKyller

    that makes sense. Thank you, I was actually wondering some of the same things
     
Thread Status:
Not open for further replies.

Share This Page