Solved The math to make a effect line

Discussion in 'Plugin Development' started by sprockbot, Jun 1, 2013.

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

    sprockbot

    I need to know how do you make a line of effect (firework,flame etc) from players view to block their looking at
     
  2. Offline

    sprockbot

  3. Offline

    LucasEmanuel

    To get every block between the player and the block they are looking, you can do something like this:
    Code:
    Location pl = player.getEyeLocation();
     
    double px = pl.getX();
    double py = pl.getY();
    double pz = pl.getZ();
     
    double yaw  = Math.toRadians(pl.getYaw() + 90);
    double pitch = Math.toRadians(pl.getPitch() + 90);
     
    double x = Math.sin(pitch) * Math.cos(yaw);
    double y = Math.sin(pitch) * Math.sin(yaw);
    double z = Math.cos(pitch);
     
    for(int i = 1 ; i <= 70 ; i++) {
        Location loc = new Location(player.getWorld(), px + i*x, py + i*z, pz + i*y);
        if(loc.getBlock().getType() == Material.AIR)
            player.getWorld().createExplosion(loc, 1f);
        else break;
    }
    There are probably better ways to do this, but this was what first came to mind, and holy eff this was awesome to play around with :)
     
    chasechocolate and tills13 like this.
  4. Offline

    InflamedSebi

    Code:java
    1. List<Material> passThrough = Arrays.asList(Material.AIR, Material.WATER, Material.STATIONARY_WATER, Material.VINE, Material.TORCH); // Materials to pass through
    2. Location center = player.getLocation(); // start of the line
    3. Vector direction = center.getDirection().normalize(); // direction vector of the line (normalized means length = 1)
    4. double range = 100; // range of the line (100 blocks for example)
    5. int amount = 10; // amount of effects on the line (10 effects on 100 blocks means 1 effect per 10 blocks)
    6. World w = center.getWorld();
    7.  
    8. // create the effect
    9. int effectsDone = 0;
    10. for (double distance = 0; distance < Math.pow(range, 2);) {
    11. center.add(direction); // get the new location
    12. distance += direction.lengthSquared();
    13. if (!passThrough.contains(center.getBlock().getType()))
    14. distance = range;
    15. if (distance / (range / amount) > effectsDone) {
    16. w.createExplosion(center, 1.0f); // create effect
    17. effectsDone++;
    18. }
    19. }
    20.  
     
  5. InflamedSebi your code will end in an infinite loop as done will never be bigger or equals amount.
     
  6. Offline

    LucasEmanuel

    InflamedSebi
    Yes, using vectors would be the better alternative, but that code is incomplete. You need to multiply the vector for each iteration to generate a new location along the line and you also need to check for solids to make sure you hit the block and not continue through it.
     
  7. Offline

    InflamedSebi

    kumpelblase2ups
    oops :D missed that.
    btw are u german? (because of your name :p)
    LucasEmanuel
    "You need to multiply the vector for each iteration to generate a new location along the line"​
    Nope, ->​
    center.add(direction);
    This will add the x,y,z values of direction to center each time you call it ... due to it is inside the loop, it will move the center in the direction along the line every time the loop runs.

    "also need to check for solids to make sure you hit the block and not continue through it."​
    I didn't add it before, because a solid-check wasn't neccesary for me, due to the explotion will destroy the blocks around them anyway (didnt thought about obsidian and bedrock), so the loop should continue until max range anyway.

    However, i added it now :)

    btw, if you wonder why i used .lenghtSquared instead of .lenght, this is because of performance reasons. Every function, which uses a squareroot will slow down performance and should not be used in a loop.
     
Thread Status:
Not open for further replies.

Share This Page