Solved Collision Detection?

Discussion in 'Plugin Development' started by derfabifabi, Jan 28, 2016.

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

    derfabifabi

    I ran into a bug i cant fix.

    Im giving an item(in my case snowball) a velocity so it flys in the players direction.
    So this is working just fine, but as the snowball reaches a block, it just bounces off.

    How can i detect this Collision, so that I can remove the SnowBall after hitting a block?

    Thank you,

    Fabi
     
  2. Offline

    teej107

  3. Offline

    derfabifabi

  4. Offline

    I Al Istannen

    @derfabifabi You could check the block position + the velocity of the item every tick if that is a block it is going to hit probably. That isn't the most efficient way though.
     
  5. Offline

    derfabifabi

    Checking the block position doesnt work because it is going to bounce really before the x or the z is "increased".

    How do i check the velocity of the item if its going to hit?
    I tried AABB, but i guess I didnt do it correctly xD
     
  6. Offline

    I Al Istannen

    @derfabifabi I used this code in one of my projects, but I have a constant speed factor so that might not work.
    Code:
    // will hit in the next tick
    Block block = entity.getLocation().add(entity.getVelocity().normalize().multiply(speed)).getBlock();
    if(block.getType() != Material.AIR) {
      arena.getGoals().reactToQuaffleCollision(block.getLocation(), lastOwner, this);
    }
    You would need to cross out the .normalize().multiply(speed) at least.

    And i have encountered some settings in which it just refused to work, also I can't tell you why. So you could try that, but i encourage you to keep searching for a better solution!
     
  7. Offline

    derfabifabi


    It actually seems to work sometimes, sometimes it really gets removed. Sadly i guess that isnt the ultimate solutin for my problem :/

    But Thank you anyways ;)
     
  8. Offline

    I Al Istannen

    @derfabifabi Yea, like I said :) It worked good enough for what I did, so I didn't bother searching further. I am away now however and will look into it again tomorrow if I don't forget it.

    Good luck to you though!
     
  9. Offline

    teej107

    A Snowball Object extends from Projectile.
     
  10. Offline

    I Al Istannen

    @teej107 But an Item extends Entity. And that is what he means, I think.
     
  11. Offline

    teej107

    @derfabifabi Are you throwing a Snowball or just dropping it?
     
  12. Offline

    derfabifabi

    I am dropping a Snowball and it justs gets a velocity.
    Code:
    Item item=p.getWorld().dropItem(p.getEyeLocation(), new ItemStack(Material.SNOW_BALL));
     
  13. Offline

    teej107

  14. Offline

    derfabifabi

    But then i cant do this, can I?
    @teej107
    Code:
    package Weapon;
    
    import org.bukkit.ChatColor;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Item;
    import org.bukkit.entity.Player;
    import org.bukkit.entity.Zombie;
    import org.bukkit.inventory.meta.ItemMeta;
    
    public class Shot implements Runnable {
        private Thread thread;
        private Player player;
    
        private double radius;
        private boolean running;
        private Item item;
        private ItemMeta waffe;
        public Shot(Player p, double radius, Item item,ItemMeta waffe){
            this.player=p;
            this.radius=radius;
            this.item=item;
            this.waffe=waffe;
            this.thread= new Thread(this);
        }
        public Weapons getWeaponbyName(String name){
            for(Weapons w: Weapons.values()){
               if(w.name().equalsIgnoreCase(name)){
                   return w;
               }
            }
            return null;
        }
        @Override
        public void run() {
            while(running){
                for(Entity entity: item.getNearbyEntities(radius, radius, radius)){
                    if(entity instanceof Zombie){
                        Zombie target= (Zombie) entity;
                        if(target!=player){
                            String b =waffe.getDisplayName();
                            if(b.startsWith(ChatColor.RED+"")){
                                b=b.substring(2);
                            }
                            target.damage(getWeaponbyName(b).schaden);
                            this.item.remove();
                            this.stop();
                        }
                    }
                }
            if(item.isOnGround()){
                this.item.remove();
                this.stop();
            }
            int xc=item.getLocation().getBlockX();
            int yc=item.getLocation().getBlockY();
            int zc= item.getLocation().getBlockZ();
            if(player.getWorld().getBlockAt(new Location(player.getWorld(),xc,yc,(zc-1))).getType() != Material.AIR){
                if(item.getVelocity().isInAABB(player.getWorld().getBlockAt(new Location(player.getWorld(),xc,yc,(zc-1))).getLocation().toVector(), player.getWorld().getBlockAt(new Location(player.getWorld(),xc,yc,(zc-1))).getLocation().toVector())){
                    item.remove();
                    player.sendMessage("Whatever");
                    this.stop();
                }
            }
            try{
            Thread.sleep(1);
            }catch(Exception e){
              
            }
            }
          
        }
        public void start(){
            this.running=true;
            this.thread.start();
        }
        @SuppressWarnings("deprecation")
        public void stop(){
            this.running=false;
            this.thread.stop();
        }
      
    }
    
    
    Code:
    Shot shot=new Shot(p,0.6,item,e.getHoe().getItemMeta());
     
    Last edited: Jan 29, 2016
  15. Offline

    I Al Istannen

    @derfabifabi I would switch to a "BukkitRunnable" (or here). That way it will run on the same thread as the Server itself and will have the exact same timing. I did some testing and was relativly happy with this:
    Code:
    Block b = item.getLocation().add(item.getVelocity().add(item.getVelocity().normalize())).getBlock();
    It will use the block the item would be in the next tick and adds some portion of the velocity to it.This way the code will be a bit ahead of the item and register the hit (mostly). If it hits a wall or a corner it might be bad to add something as it won't even register it, because the velocity added to the location would be the block behind it. Another Problem is, that it will fire a bit too early. In median with a normally dropped item it was about 1.8 blocks too early. I don't really know what you will use this for though. As we have 50 milliseconds (if the server runs at 20 TPS) between each measure, the item can have moved far enough to bounce off and get a different, non colliding velocity. The code will then run shortly after, check if it will hit and return false. Logically, because it already hit. The only real way I know would be to reduce the time between (what isn't possible I think) or plan a bit ahead. However we didn't even had vectors in school and I can't help you with that.

    A combination of this with the onGround() and isValid() (if it was despawned or picked up) works quite well though.

    There must be a better way I don't know though.
     
  16. Offline

    derfabifabi

    @I Al Istannen I will give it a try later ;)

    We hadnt had vectors yet too in school, so im a total noob working with them xD
     
  17. Offline

    teej107

    What is that class supposed to do? Btw you are violating thread safety by calling Bukkit methods outside the main thread. Bukkit API is not thread safe.
     
  18. Offline

    I Al Istannen

    @derfabifabi If you want it to be maximum Ressource intensive you could check for the next few Blocks in line oft Sicht in really small differences.
     
    derfabifabi likes this.
  19. Offline

    derfabifabi

    I have no other idea how i should code this^^

    So the class is just a Runnable, that Checks the Item with the Velocity(Snowball) every x ms,(should use BukkitRunnable ik)if there are nearby Players.
    If there are nearby players they get damage based on the weapon the "shooter"is holding.
    This is working just fine with the damage based because i have the enum Weapons and the function getWeaponbyname
    So i dont have to worry about that.

    But yeah the item is b0uncing if it hits a block, so you could shoot around corners. I dont want that xD

    You mean check every 26Blocks around the Airblock the Snowball is in? xD
    26Because
    Cube of 3^3-1
     
    Last edited by a moderator: Jan 29, 2016
  20. Offline

    teej107

    @derfabifabi If you want to throw a Snowball, use the launchProjectile method.
     
  21. Offline

    derfabifabi

    But then again, im not having an object to follow.
    You have to now that the player can change between weapons. So an iteminHand wont be useful. And you cant say
    Projectile p= new Projectile(bla);

    This is the Problem...
     
  22. Offline

    teej107

    @derfabifabi the launchProjectile method returns the projectile so you can have reference to it.
     
    derfabifabi likes this.
  23. Offline

    derfabifabi

    OMG xD
    Biggest facepalm ever.

    That solves it.

    Thank you very much Sir for taking your time explaining to an idiot xD
     
Thread Status:
Not open for further replies.

Share This Page