[JAVA] Non-physique similaire utilisé pour exprimer le baseball sur Minecraft et mise en œuvre dans Spigot (édition reliée)

introduction

Pendant environ un an, Snowball Game, un plug-in qui fonctionne sur le logiciel serveur multijoueur de Minecraft Spigot Je fais un jeu de boules de neige. En plus des fonctions de base de frapper, lancer et attraper, je pense que je suis capable de faire quelque chose qui est raisonnablement satisfaisant, comme le jugement automatique de changement de balle et de zone de frappe, et une fonction de frappe avec un certain degré de précision.

Mais,

C'est presque comme le premier code Java que j'ai écrit de ma vie, et je suis toujours à un niveau où je peux difficilement dire que je suis un débutant. De plus, le code de ce plug-in est extrêmement sale car je l'ai développé en ajoutant de plus en plus de fonctions après avoir fait la partie de base avec une construction assez simple.

Pour le moment, le code source publié sur Github sous la licence de Spigot n'est pas quelque chose qui peut être montré aux gens, et il est difficile de lire presque toute l'histoire. Il est composé de pièces et de points de plongée. De plus, il n'y a pas de commentaires sur la ligne. (Parce que je me demandais si je devais écrire en anglais ou pas)

Jusqu'à présent, j'ai pu saisir le contenu car les fonctions que je souhaite ajouter régulièrement me viennent à l'esprit, mais je suis sûr que je ne saurai jamais ce qu'elles sont. Alors, je voudrais la refactoriser dans la mesure où elle prendra forme pour le moment.

Pour ce travail, j'ai écrit cet article avec l'intention de résumer des choses telles que «ce que j'ai pensé et écrit» en japonais au lieu de code. Par conséquent, bien que cet article ait été principalement écrit pour moi, j'espère qu'il sera utile si quelqu'un veut développer d'autres plug-ins sportifs.

lié

Tout d'abord, la mise en place de la partie liée du ballon qui semble être absolument nécessaire dans tout jeu de ballon. Puisqu'il n'y a pas de faces diagonales dans Minecraft, le mouvement de rebond est remplacé par "l'inversion d'une seule des coordonnées X, Y ou Z du vecteur de mouvement de l'objet en fonction de la face qu'il frappe." Dans Spigot, si la balle utilisée est Projectile, ProjectileHitEvent bloquera la balle. / Peut détecter une "collision avec une entité". Quant à savoir de quel côté vous frappez, Spigot a un type appelé BlockFace, vous pouvez donc faire ```event.getHitBlock (). GetFace (event.getEntity (). GetLocation (). GetBlock ()) ``. Si vous le faites, vous pouvez l'obtenir. Après cela, si la Face de Bloc acquise est HAUT ou BAS, le Y de la Vitesse de la balle peut être inversé, s'il est EST ou OUEST, X peut être inversé, et s'il est SUD ou NORD, Z peut être inversé.

Au moment où ProjectileHitEvent est appelé, la balle d'origine a déjà disparu du jeu, donc `` World.spawnEntity (Location, EntityType) '' appelle une nouvelle balle et l'inverse. Il est nécessaire de définir.

problème

Cependant, il y a un problème avec cette méthode. Block.getFace (Block) ne renvoie BlockFace (devient null) que si le bloc d'origine et le bloc d'arguments sont adjacents. C'est un gros problème car la position de la balle et la position du bloc au moment de l'événement peuvent être séparées d'un bloc ou plus lorsque la vitesse de la balle est plus rapide qu'un certain niveau. En outre, BlockFace renvoie des valeurs à des positions diagonales telles que sud-ouest et nord-nord-est, en plus des six nord, sud, est et ouest. Ce problème semble être résolu en écrivant "ToString de BlockFace et inverser X si EAST ou WEST est inclus, et Z si SOUTH ou NORTH est inclus". Si vous essayez, vous pouvez voir que la plage de "jugement diagonal" est assez large et que le mouvement est un peu contre-intuitif.

Solution

Par conséquent, si le BlockFace renvoyé est nul ou contient \ _ comme SOUTH_EAST, il est nécessaire de le corriger en haut, en bas, à l'est, à l'ouest, au nord ou au sud. La partie qui s'y trouve est [BlockIterator](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/util/BlockIterator.html#BlockIterator-org.bukkit.World-org.bukkit.util.Vector-org. Je l'ai écrit comme ça en utilisant 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);
    }

En bref, obtenez le bloc dans la direction du vecteur de mouvement de la balle à partir des coordonnées de la balle lorsqu'elle frappe, cochez "Est-ce un bloc qui peut rebondir" dans l'ordre, et si c'est OK, quittez la boucle Le mécanisme est tel que le bloc dans cette direction renvoie la surface adjacente au bloc d'origine en tant que "surface de collision". Il y a beaucoup de choses à creuser ici aussi, mais fondamentalement, cela fonctionne.

Remarques

Gérer l'inconfort

Lorsqu'il est mis en œuvre de cette manière, il peut rebondir sur des blocs que vous ne voulez pas avoir un jugement de frappe comme un ananas, ou il peut être jugé avoir heurté la surface latérale d'un tapis ou d'un fil de redstone en fonction de l'angle auquel il frappe, ce qui entraîne un comportement étrange. Pour éviter cela, "Si vous frappez ce type de bloc, écrasez-le avec UP" "Ce type de bloc doit être évité par la balle quand elle frappe (Cependant, Projectile HitEvent n'est pas annulable, vous devez donc réécrire le mouvement vous-même Il y a) », il peut être bon de préparer une liste à l'avance. Je l'ai écrit dans ce format, mais je ne suis pas très sûr du code là-bas, donc je l'omettrai ici.

Donner des fonctionnalités physiquement incorrectes

Si vous le décrivez de cette manière et réduisez la vitesse pour correspondre au coefficient de répulsion de la balle, vous pouvez mettre en œuvre le rebond correct pour le moment, mais si vous le faites comme ça, il semble que "Si vous essayez de rapprocher la distance de roulement du goro de la réalité Des problèmes tels que "le premier rebond rebondit trop" et "lorsque le rebond de la mouche est réglé à un niveau approprié, elle roule comme une boule de fer" se produisent. (Est-ce la cause du roulement anormal de la balle dans un célèbre match de baseball original qui est devenu un sujet brûlant pendant un moment?) Par conséquent, j'écris que "plus la vitesse de la balle au moment du rebond est rapide, plus la décélération est grande" et "plus l'angle entre le vecteur normal de la surface rebondie et le vecteur après le rebond de la balle est petit, plus la décélération est grande". Plus la balle frappe rapidement à angle droit, plus il est facile pour la balle de s'effondrer et de creuser le sol, donc la force de perte sera plus grande, mais il n'y a pas de données appropriées et je les ajuste avec mes propres sentiments. En raison de la pertinence de ce domaine, j'ai nommé le titre physique «similaire».

De plus, je veux exprimer en quelque sorte la difficulté de la courbe à une seule limite qui rebondit dans la direction opposée du changement et l'irritation de s'échapper vers la zone de faute lorsque la mouche qui coupe en tranchant rebondit, donc je veux exprimer la balle lors du lancer ou de la frappe. La rotation de est donnée à la balle sous forme de métadonnées sous la forme d'un vecteur de rotation, et cette valeur est utilisée au moment du rebond afin que la rotation soit reflétée dans une certaine mesure.

Cependant, cela est assez gênant, et en général, l'effet de la rotation sur le mouvement lorsque la balle rebondit est "proportionnel au produit extérieur du vecteur normal au sol et du vecteur de rotation de la balle (représentation vectorielle de la rotation)". Cependant, cela ne répond pas aux exigences ci-dessus. Du point de vue de l'ailier droit, on pense qu'une balle frappée qui tranche vers la zone de faute a le même axe de rotation qu'un joueur de premier but tirant à droite qui lance un tir vers le côté léger. Si vous essayez de satisfaire, la direction du changement au moment du rebond sera complètement opposée entre le premier et le second.

Je ne suis pas sûr de la cause correcte de ce phénomène. Par conséquent, "Peut-être que s'il s'agit d'une trajectoire de ligne basse qui ne vole pas vers le champ extérieur, elle devrait rebondir du côté de la zone de la foire, si c'est une mouche, elle devrait rebondir du côté de la zone de faute" et "Le vecteur de rotation de la balle" Il est écrit de façon à ce que le rebond soit changé dans une direction proportionnelle au produit extérieur du "vecteur du mouvement de la balle avant que le rebond ne soit inversé".

Cependant, cela n'explique pas la direction opposée du service de la tranche de tennis et de la courbe de lancer du lanceur. C'est donc probablement une mauvaise mise en œuvre de ce qui n'est pas physiquement rigoureux. Cependant, il abandonne car il n'a pas la capacité de trouver et de mettre en œuvre les bonnes lois de la physique. Ceux qui connaissent la physique, je serais très heureux si vous pouviez me parler de cette question. S'échappera-t-il vers la zone des fautes si le nombre de tours est élevé et que la balle glisse en rebondissant? J'y ai réfléchi, mais je ne sais pas comment le décrire.

A continué

Le reste a été divisé car il était plus long que prévu avec seulement des lettres. Lancer et frapper Catching / Tips

Recommended Posts

Non-physique similaire utilisé pour exprimer le baseball sur Minecraft et mise en œuvre dans Spigot (édition reliée)
Non-physique similaire utilisé pour exprimer le baseball sur Minecraft et mise en œuvre dans Spigot (capture de balle / Conseils)
Non-physique similaire utilisé pour exprimer le baseball sur Minecraft et mise en œuvre dans Spigot (lancer / frapper)