[JAVA] Similar non-physics used to express baseball on Minecraft and implementation in Spigot (bound)

Introduction

For about a year, Snowball Game, a plug-in that works on Minecraft's multiplayer server software Spigot I am making snowball game.35339 /). In addition to the basic functions of hitting, throwing, and catching, I think that I am able to make something that is reasonably satisfying, such as automatic judgment of changing balls and strike zones, and a knock function with a certain degree of accuracy.

But,

This is almost like the first Java code I wrote in my life, and I'm still at a level where I can hardly say that I'm a beginner. In addition, the code of this plugin is extremely dirty because I developed it by adding functions one after another after making the basic part with a fairly simple construction.

For the time being, the source code published on Github under the license of Spigot is not something that can be shown to people, and it is almost difficult to read the whole story. It is composed of parts and plunge points. In addition, there are no comments on the line. (Because I was wondering if I should write in English or not)

Up to this point, I've been able to grasp the contents because the functions I want to add on a regular basis have come to my mind, but I'm sure I'll never know what they are. So, I'd like to refactor it to the extent that it takes shape for the time being.

For that work, I wrote this article with the intention of summarizing things such as "what I thought about and wrote" in Japanese instead of code. Therefore, although it is an article I wrote mainly for myself, if anyone wants to develop other sports plugins, I hope you find it useful.

bound

First of all, the implementation of the bound part of the ball that seems to be absolutely necessary in any ball game. Since there is no diagonal plane in Minecraft, the motion of bouncing is replaced by "reversing only one of the X, Y, Z coordinates of the object's movement vector depending on the plane it hits." In Spigot, if the ball used is Projectile, ProjectileHitEvent will block the ball. / Can detect "collision with entity". As for which side you hit, Spigot has a type called BlockFace, so you can do ```event.getHitBlock (). GetFace (event.getEntity (). GetLocation (). GetBlock ())` `` If you do it, you can get it. After that, if the acquired Block Face is UP or DOWN, the Y of the ball's velocity can be inverted, if it is EAST or WEST, X can be inverted, and if it is SOUTH or NORTH, Z can be inverted.

By the time ProjectileHitEvent is called, the entity of the original ball has already disappeared from the game, so `World.spawnEntity (Location, EntityType)` calls the new ball and flips it to velocity. It is necessary to set.

problem

However, there is a problem with this method. Block.getFace (Block) returns BlockFace (becomes null) only if the original block and the argument block are adjacent. This is a big problem because the position of the ball and the position of the block at the time of the event may be separated by one block or more when the speed of the ball is faster than a certain level. In addition, BlockFace returns values for diagonal positions such as southwest and northeast, in addition to the six north, south, east, and west. This problem seems to be solved by writing "ToString of BlockFace and invert X if EAST or WEST is included, and Z if SOUTH or NORTH is included". If you try it, you can see that the range of "diagonal judgment" is quite wide, and the movement is a little counterintuitive.

solution

Therefore, if the returned BlockFace is null or contains \ _ like SOUTH_EAST, it is necessary to correct it to either the top, bottom, east, west, north, or south. The part there is [Block Iterator](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/util/BlockIterator.html#BlockIterator-org.bukkit.World-org.bukkit.util.Vector-org. I wrote it like this using bukkit.util.Vector-double-int-).

hitFaceModifier


    if(hitFace == null || hitFace.toString().contains("_")){
        BlockIterator blockIterator = new BlockIterator(hitLoc.getWorld(), hitLoc.toVector(), velocity, 0.0D, 3);
        Block previousBlock = hitLoc.getBlock();
        Block nextBlock = blockIterator.next();
        while (blockIterator.hasNext() && (!Util.doesRepel(nextBlock) ||nextBlock.isLiquid() || nextBlock.equals(hitLoc.getBlock()))) {
            previousBlock = nextBlock;
            nextBlock = blockIterator.next();
        }
        hitFace = nextBlock.getFace(previousBlock);
    }

In short, get the block in the direction of the ball's movement vector direction from the coordinates of the ball when it hits, check "Is it a block that can bounce" in order, and if it is OK, exit the loop The mechanism is such that the block in that direction returns the surface adjacent to the original block as the "collision surface". There's a lot to dig into here as well, but basically it's working.

Remarks

Dealing with discomfort

When implemented by this method, it may bounce off blocks that you do not want to have a collision detection such as a torch, or it may be judged that it has hit the side surface of a carpet or redstone wire depending on the angle at which it hits, resulting in a strange behavior. To prevent that, "If you hit this type of block, overwrite it with UP" "This type of block should be avoided by the ball when it hits (However, Projectile HitEvent is not Cancelable, so you need to rewrite the movement yourself There is) ”, it may be good to prepare a list in advance. I wrote it in that format, but I'm not so confident in the code there, so I'll omit it here.

Give physically incorrect features

If you describe it in this way and attenuate the speed to the extent that it matches the coefficient of restitution of the ball, you can implement the correct bounce for the time being, but if you make it like that, it seems that "If you try to bring the rolling distance of the goro closer to reality Problems such as "the first bounce bounces too much" and "when the bounce of the fly is set to an appropriate level, it rolls like an iron ball" occur. (Is this the cause of the abnormal rolling of the ball in a famous original baseball game that became a hot topic for a while?) Therefore, I write that "the faster the ball speed at the time of bouncing, the greater the deceleration" and "the smaller the angle between the normal vector of the bounced surface and the vector after the bounce of the ball, the greater the deceleration". The faster the ball hits at a right angle, the easier it is for the ball to collapse and the ground to be dug, so the loss force will be greater, but there is no proper data and I am adjusting it with my own feelings. Because of the suitability of this area, I named the title "similar" physics.

In addition, I want to somehow express the difficulty of the one-bound curve bouncing in the opposite direction to the change and the annoyance of escaping to the foul zone when the fly that cuts while slicing bounces, so I want to express the ball when throwing or hitting. The spin of is given to the ball as metadata in the form of a rotation vector, and this value is used at the time of bouncing so that the rotation is reflected to some extent.

However, this is quite troublesome, and in general, the effect of rotation on the movement of the ball when it bounces is "proportional to the outer product of the ground normal vector and the ball rotation vector (vector representation of rotation)." However, this does not meet the above requirements. From the perspective of the right fielder, a ball that slices toward the foul zone is thought to have the same axis of rotation as a right-handed first baseman throwing a shot toward the right side. If you try to satisfy, the direction of change at the time of bouncing will be completely opposite between the former and the latter.

I'm not sure the correct cause of this phenomenon. Therefore, "Maybe if it is a low liner trajectory that does not fly to the outfield, it should bounce to the fair zone side, if it is a fly, it should bounce to the foul zone side", "The rotation vector of the ball It is written so that the bounce is changed in the direction proportional to the outer product of "the vector of the motion of the ball before the bounce is inverted".

However, this does not explain the opposite direction of the tennis slice serve and the pitcher's curve. So it's probably a clear misimplementation of what isn't physically rigorous. However, he gives up because he does not have the ability to find and implement the correct laws of physics. Those who are familiar with physics I would be very happy if you could tell me about this matter. If the number of revolutions is high and the ball slips when bouncing, will it escape to the foul zone? I have thought about it, but I don't know how to describe it.

Continued

The rest was split because it was longer than I expected with only letters. Pitching / Batting Catching / Tips

Recommended Posts

Similar non-physics used to express baseball on Minecraft and implementation in Spigot (bound)
Similar non-physics used to express baseball on Minecraft and implementation in Spigot (catch / Tips)
Similar non-physics used to express baseball on Minecraft and implementation in Spigot (Pitching / Battering)