Generating a (flat) circle of blocks..

Discussion in 'Plugin Development' started by Eballer48, Aug 13, 2012.

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

    Eballer48

    How would I go about doing so..?
     
    Limeth likes this.
  2. Offline

    Jnorr44

    simple

    Code:
            for (int x = -radius; x <= radius; x++) {
                for (int z = -radius; z <= radius; z++) {
                    world.getBlockAt(x, y, z).setType(Material.DESIREDMATERIAL);
                }
            }
     
  3. Offline

    Eballer48

    I'm sure this is correct so I apologize for misunderstanding however this code only creates one center netherrack block.

    Code:
    int radius = 7;
    World w = Bukkit.getServer().getWorld("world");
    Location loc = Bukkit.getServer().getWorld("world").getSpawnLocation();
     
    for (int x = -radius; x <= radius; x++) {
               for (int z = -radius; z <= radius; z++) {
                   w.getBlockAt(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()).setType(Material.NETHERRACK);
               }
           }
    
     
  4. Offline

    Jnorr44

    ohhh I see, your trying to create a circle around the spawn point...

    So...

    PROBLEM: Your just getting the X, Y and Z of the loc (spawn point) and setting that to Netherrack.

    SOLUTION: do:
    w.getBlockAt(loc.getX() + x, loc.getY() + 0, loc.getZ() + z).setType(Material.NETHERRACK);

    That should work... try that!
     
  5. Offline

    Eballer48

    Right except it need to be a hollow circle (sorry for being picky) and that code you just gave me returns this error in eclipse;
    Code:
    The method getBlockAt(int, int, int) in the type World is not applicable for the arguments (double, double, double)
    
     
  6. Offline

    hovercatz

    w.getBlockAt((int) loc.getX() + x, (int) loc.getY() + 0, (int) loc.getZ() + z).setType(Material.NETHERRACK);
     
  7. Offline

    Jnorr44

    oh ok... try the getBlockX,Y,Z (like you did before) that may get an integer for you.

    Also, to make a hollow circle is a bit harder.

    Not sure if this will work though, but you should try it...
    Code:
            int y = 0;
            int x = x2 - radius - 1;
            for (int z = z2 - radius - 1; z <= z2 + radius + 1; z++) {
                world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
            }
            x = x2 + radius + 1;
            for (int z = z2 - radius - 1; z <= z2 + radius + 1; z++) {
                world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
            }
            int z = z2 - radius - 1;
            for (x = x2 - radius - 1; x <= x2 + radius + 1; x++) {
                world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
            }
            z = z2 + radius + 1;
            for (x = x2 - radius - 1; x <= x2 + radius + 1; x++) {
                world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
            }
    EDIT: yeah, hovercatz is probably right, just cast the loc.getX,Y,Z to an int
     
  8. Jnorr44
    Umm, you know, that actually only creates a rectangle, not a circle ;)

    Theory of creating a circle:
    - Iterate through the rectangle around the circle (the way Jnorr44 did it)
    - If the distance of your current block to the center is bigger than the radius, don't do anything
    - Otherwise set your block

    Code:
    int radius = ...;
    int radiusSquared = radius * radius;
     
    for(int x = -radius; x <= radius; x++) {
        for(int z = -radius; z <= radius; z++) {
            if( (x*x) + (z*z) <= radiusSquared) {
                // do your thing
            }
        }
    }
    
    Note how I compare against the squared radius to improve performance. Normally, you would have to use Math.sqrt(x*x + z*z), which is a pretty slow method.

    edit: didn't see the hollow thing ...
     
    dylanisawesome1 likes this.
  9. Offline

    Jnorr44

    Bone008, yeah, forgot about that XD
     
  10. Offline

    Eballer48

    Just gave me a solid 15x15 square of netherrack.

    So will these create a hollow circle? And what exactly am I suppose to add in //do your thing?

    Code:
    [I][SIZE=12px]w.getBlockAt((int) loc.getX() + x, [/SIZE][/I][I][SIZE=12px](int)[/SIZE][/I][I][SIZE=12px] [/SIZE][/I][I][SIZE=12px]loc.getY() + 0, [/SIZE][/I][I][SIZE=12px](int)[/SIZE][/I][I][SIZE=12px] [/SIZE][/I][I][SIZE=12px]loc.getZ() + z).setType(Material.NETHERRACK);[/SIZE][/I]
    
    ...? Again I apologize for my noobiness.

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

    Jnorr44

    Use the code I just gave you, but add in Bone008's third line:

    if ((x*x) + (z*z) <= radiusSquard){
    //do your thing - he means set the block to netherrack
    }
     
  12. I don't support spoon-feeding, try to do a little bit of thinking. "x" and "z" go from "negative radius" to "positive radius" in these loops. So you add that value to your center block, and you got your new coordinates to set your block.

    I did the math part for you, but please try and think about the code you get, then you'll understand how to continue.

    And no, that doesn't create a hollow one, as you should see by yourself if you actually understand it. I don't know how to do that either.
     
  13. Offline

    Eballer48

    Okay so I've got this..

    Code:java
    1.  
    2. int radius = 7;
    3. World world = Bukkit.getServer().getWorld("world");
    4. Location loc = Bukkit.getServer().getWorld("world").getSpawnLocation();
    5.  
    6. loc.setY(loc.getY() - 1);
    7.  
    8. int y = 0;
    9. int x = x2 - radius - 1;
    10. for (int z = z2 - radius - 1; z <= z2 + radius + 1; z++) {
    11. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    12. }
    13. x = x2 + radius + 1;
    14. for (int z = z2 - radius - 1; z <= z2 + radius + 1; z++) {
    15. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    16. }
    17. int z = z2 - radius - 1;
    18. for (x = x2 - radius - 1; x <= x2 + radius + 1; x++) {
    19. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    20. }
    21. z = z2 + radius + 1;
    22. for (x = x2 - radius - 1; x <= x2 + radius + 1; x++) {
    23. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    24. }
    25.  


    What do I put for like x2 and z2.. and again between my noobiness, plus it being late and I'm tired I'm extremely slow atm.. ha. So where should I add bone's code?
     
  14. Offline

    Jnorr44

    ahh sorry, that not your fault thats mine... this was taken from a bit of code i used earlier...

    add in Bone008's code after each of the 4 'for' loops, and x2 and z2 are actually loc.getBlockX() and loc.getBlockY() - sorry about that.
     
  15. Offline

    Eballer48

    Okay, well here is what I came up with:

    Code:java
    1.  
    2. World world = Bukkit.getServer().getWorld("world");
    3. Location loc = Bukkit.getServer().getWorld("world").getSpawnLocation();
    4.  
    5. loc.setY(loc.getY() - 1);
    6.  
    7. int radius = 7;
    8. int radiusSquard = 7;
    9. int x2 = loc.getBlockX();
    10. int z2 = loc.getBlockZ();
    11. int y = 0;
    12. int x = x2 - radius - 1;
    13.  
    14. for (int z = z2 - radius - 1; z <= z2 + radius + 1; z++) {
    15. if ((x * x) + (z * z) <= radiusSquard) {
    16. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    17. }
    18. }
    19. x = x2 + radius + 1;
    20. for (int z = z2 - radius - 1; z <= z2 + radius + 1; z++) {
    21. if ((x * x) + (z * z) <= radiusSquard) {
    22. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    23. }
    24. }
    25. int z = z2 - radius - 1;
    26. for (x = x2 - radius - 1; x <= x2 + radius + 1; x++) {
    27. if ((x * x) + (z * z) <= radiusSquard) {
    28. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    29. }
    30. }
    31. z = z2 + radius + 1;
    32. for (x = x2 - radius - 1; x <= x2 + radius + 1; x++) {
    33. if ((x * x) + (z * z) <= radiusSquard) {
    34. world.getBlockAt(loc.getBlockX() + x, loc.getBlockY() + y, loc.getBlockZ() + z).setType(Material.NETHERRACK);
    35. }
    36. }
    37.  


    and it literally does nothing.. :p Wasn't sure what to put fr radiusSquared so I just made it 7.
     
  16. Offline

    Jnorr44

    lol, don't you know how to square a number? 7*7 = 49 (your radiusSquared)
     
    Icyene and ZeusAllMighty11 like this.
  17. Offline

    Eballer48

    Dude.. I've had a long day haha.. I didn't think it LITERALLY meant squared.. anyways so:

    Code:
    int radiusSquard = radius * radius;
    
    but still.. no circle.
     
  18. Offline

    Icyene

    And THAT is why it doesn't work. radiusSquared = radius. Squared. radiusSquared = Math.pow(radius, 2);

    Beat me to it. Still, Math.pow is more efficient. :D

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 27, 2016
  19. Jnorr44 Seriously, how the heck are your 4 loops supposed to be used to create a hollow circle? They create a hollow rectangle, but drawing 4 lines can't really be used to draw a circle ...

    This is what WorldEdit uses to generate a hollow cylinder (in MC, a circle is a cylinder with height 1). It has some extra features like doing it elliptical (different radius for X and Z), so it looks a lot more complicated, though:
    https://github.com/sk89q/worldedit/...va/com/sk89q/worldedit/EditSession.java#L2067

    I think the key part is that one needs to get the "next" x/z distance/whatever in the loop and stuff and check distances on that as well or something.

    edit:
    What? Math.pow is in no terms more efficient than a raw integer multiplication. It is designed for higher/variable powers, and thus probably uses a loop. How is that supposed to be more efficient?
     
  20. Offline

    Eballer48

    Okay well we're clearly getting no where because I without a doubt do NOT understand this. I'm getting the hint you're suggesting I use
    Code:
    public int makeCylinder
    The only problem with that is that I don't know how to.
     
  21. Offline

    Jnorr44

    umm... lol - an integer will NOT make a cylinder XD
     
  22. Offline

    Eballer48

    For once... would you mind cramming a spoon down my throat?
     
  23. Offline

    Jnorr44

    Haha, I would just use WorldEdits code as a guide...
     
  24. Offline

    Eballer48

    I'm not good T looking into others code because I don't know what is what.. would you helping me find it?
     
  25. Offline

    Jnorr44

    TheGreenGamerHD likes this.
  26. Offline

    Squish000

    The simplest way would just be to use worldedits code, it quite east to understand.

    Or a method i could think of (its very inefficient) would be to create a filled circle and for each block check if it has air next to it on the x and z axis and if does,it keeps the block but if the block is surrounded by other blocks it gets deleted.
     
  27. Offline

    Eballer48

    What class is it in,
     
  28. Offline

    Squish000

  29. Offline

    Eballer48

    So is this my answer?

    Code:java
    1.  
    2. public int makeCylinder(Vector pos, Pattern block, double radiusX, double radiusZ, int height, boolean filled) throws MaxChangedBlocksException {
    3. int affected = 0;
    4. radiusX += 0.5;
    5. radiusZ += 0.5;
    6. if (height == 0) {
    7. return 0;
    8. } else if (height < 0) {
    9. height = -height;
    10. pos = pos.subtract(0, height, 0);
    11. }
    12. if (pos.getBlockY() < 0) {
    13. pos = pos.setY(0);
    14. } else if (pos.getBlockY() + height - 1 > world.getMaxY()) {
    15. height = world.getMaxY() - pos.getBlockY() + 1;
    16. }
    17. final double invRadiusX = 1 / radiusX;
    18. final double invRadiusZ = 1 / radiusZ;
    19. final int ceilRadiusX = (int) Math.ceil(radiusX);
    20. final int ceilRadiusZ = (int) Math.ceil(radiusZ);
    21. double nextXn = 0;
    22. forX: for (int x = 0; x <= ceilRadiusX; ++x) {
    23. final double xn = nextXn;
    24. nextXn = (x + 1) * invRadiusX;
    25. double nextZn = 0;
    26. forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
    27. final double zn = nextZn;
    28. nextZn = (z + 1) * invRadiusZ;
    29. double distanceSq = lengthSq(xn, zn);
    30. if (distanceSq > 1) {
    31. if (z == 0) {
    32. break forX;
    33. }
    34. break forZ;
    35. }
    36. if (!filled) {
    37. if (lengthSq(nextXn, zn) <= 1 && lengthSq(xn, nextZn) <= 1) {
    38. continue;
    39. }
    40. }
    41. for (int y = 0; y < height; ++y) {
    42. if (setBlock(pos.add(x, y, z), block)) {
    43. ++affected;
    44. }
    45. if (setBlock(pos.add(-x, y, z), block)) {
    46. ++affected;
    47. }
    48. if (setBlock(pos.add(x, y, -z), block)) {
    49. ++affected;
    50. }
    51. if (setBlock(pos.add(-x, y, -z), block)) {
    52. ++affected;
    53. }
    54. }
    55. }
    56. }
    57. return affected;
    58. }
    59.  
     
  30. Offline

    Squish000

    Yes, but you will obviously have to re write it to not use 'Pattern' and set every block as the block you want.
     
Thread Status:
Not open for further replies.

Share This Page