From 0392af6b0379432acd5d0ecbe2d610d23b9552dd Mon Sep 17 00:00:00 2001 From: 17146 <1714673995@qq.com> Date: Mon, 11 Nov 2024 16:32:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E6=B7=BB=E5=8A=A0=E5=BC=B9?= =?UTF-8?q?=E9=81=93=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../superbwarfare/client/gui/RangeHelper.java | 110 +++++++++++++++++- .../mcreator/superbwarfare/init/ModItems.java | 2 + .../mcreator/superbwarfare/item/TestItem.java | 60 ++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/mcreator/superbwarfare/item/TestItem.java diff --git a/src/main/java/net/mcreator/superbwarfare/client/gui/RangeHelper.java b/src/main/java/net/mcreator/superbwarfare/client/gui/RangeHelper.java index 619cbc474..36d167c26 100644 --- a/src/main/java/net/mcreator/superbwarfare/client/gui/RangeHelper.java +++ b/src/main/java/net/mcreator/superbwarfare/client/gui/RangeHelper.java @@ -1,7 +1,16 @@ package net.mcreator.superbwarfare.client.gui; +import net.minecraft.core.BlockPos; + public class RangeHelper { - // 发射角度(以度为单位),需要根据实际情况修改 + + public static final int MAX_RANGE = 512; + + /** + * 计算迫击炮理论水平射程 + * + * @param thetaDegrees 发射角度(以度为单位),需要根据实际情况修改 + */ public static double getRange(double thetaDegrees) { double initialVelocity = 8.0; // 初始速度 8 m/s double thetaRadians = Math.toRadians(thetaDegrees); // 将角度转换为弧度 @@ -38,4 +47,103 @@ public class RangeHelper { // 返回最终水平距离 return x; } + + public static double calculateRangeWithDeltaY(double initialVelocity, double theta, double gravity, double velocityDecay, double deltaY) { + double vx = initialVelocity * Math.cos(theta); // 水平速度 + double vy = initialVelocity * Math.sin(theta); // 垂直速度 + + double range = 0.0; // 水平距离 + double y = 1.0; // 垂直位置 + + double commonRange = calculateRange(initialVelocity, theta, gravity, velocityDecay); + + // 当炮弹还未触地时,继续计算飞行轨迹 + while (range < commonRange / 2 || (range >= commonRange / 2 && y >= deltaY)) { + // 更新位置 + range += vx; + y += vy; + + // 更新速度 + vx *= velocityDecay; + vy = vy * velocityDecay - gravity; + + if (range >= commonRange / 2 && y < deltaY) { + break; + } + } + + // 返回最终水平距离 + return range; + } + + public static boolean canReachTarget(double initialVelocity, double gravity, double velocityDecay, BlockPos startPos, BlockPos targetPos, double[] angles) { + if (startPos.equals(targetPos)) { + return false; + } + + int startX = startPos.getX(); + int startY = startPos.getY(); + int startZ = startPos.getZ(); + + int targetX = targetPos.getX(); + int targetY = targetPos.getY(); + int targetZ = targetPos.getZ(); + + double distanceXZ = Math.sqrt(Math.pow(targetX - startX, 2) + Math.pow(targetZ - startZ, 2)); + if (distanceXZ > MAX_RANGE) { + return false; + } + + double theta = calculateLaunchAngle(initialVelocity, gravity, velocityDecay, distanceXZ, targetY - startY); + + if (theta < 20 || theta > 90) { + return false; + } + + angles[0] = Math.atan2(targetZ, targetX); // 水平角度 + angles[1] = theta; // 炮口抬升角度 + return true; + } + + public static double calculateLaunchAngle(double initialVelocity, double gravity, double velocityDecay, double distanceXZ, double targetY) { + double left = 20; // 最小角度 + double right = 30; // 最大角度 + double tolerance = 0.5; // 允许的误差范围 + + // 在 20 到 30 之间搜索 + while (right - left > tolerance) { + double mid = (left + right) / 2; + double radian = Math.toRadians(mid); + double range = calculateRangeWithDeltaY(initialVelocity, radian, gravity, velocityDecay, targetY); + + if (Math.abs(range - distanceXZ) < tolerance * 4) { + return mid; + } else if (range < distanceXZ) { + left = mid; + } else { + right = mid; + } + } + + // 如果在 20 到 30 之间没有找到合适的角度,则在 30 到 90 之间搜索 + left = 30; + right = 90; + + while (right - left > tolerance) { + double mid = (left + right) / 2; + double radian = Math.toRadians(mid); + double range = calculateRangeWithDeltaY(initialVelocity, radian, gravity, velocityDecay, targetY); + + if (Math.abs(range - distanceXZ) < tolerance * 4) { + return mid; + } else if (range < distanceXZ) { + right = mid; + } else { + left = mid; + } + } + + // 如果仍然没有找到合适的角度,则返回 -1 + return -1; + } } diff --git a/src/main/java/net/mcreator/superbwarfare/init/ModItems.java b/src/main/java/net/mcreator/superbwarfare/init/ModItems.java index 066df3fc8..3e4cb8434 100644 --- a/src/main/java/net/mcreator/superbwarfare/init/ModItems.java +++ b/src/main/java/net/mcreator/superbwarfare/init/ModItems.java @@ -110,6 +110,8 @@ public class ModItems { */ public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ModUtils.MODID); + public static final RegistryObject TEST_ITEM = ITEMS.register("test_item", TestItem::new); + public static final RegistryObject SENPAI_SPAWN_EGG = ITEMS.register("senpai_spawn_egg", () -> new ForgeSpawnEggItem(ModEntities.SENPAI, -11584987, -14014413, new Item.Properties())); public static final RegistryObject ANCIENT_CPU = ITEMS.register("ancient_cpu", () -> new Item(new Item.Properties().rarity(Rarity.RARE))); public static final RegistryObject PROPELLER = ITEMS.register("propeller", () -> new Item(new Item.Properties())); diff --git a/src/main/java/net/mcreator/superbwarfare/item/TestItem.java b/src/main/java/net/mcreator/superbwarfare/item/TestItem.java new file mode 100644 index 000000000..f555e136e --- /dev/null +++ b/src/main/java/net/mcreator/superbwarfare/item/TestItem.java @@ -0,0 +1,60 @@ +package net.mcreator.superbwarfare.item; + +import net.mcreator.superbwarfare.client.gui.RangeHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class TestItem extends Item { + + public TestItem() { + super(new Properties().stacksTo(1)); + } + + @Override + public InteractionResult useOn(UseOnContext pContext) { + ItemStack stack = pContext.getItemInHand(); + BlockPos pos = pContext.getClickedPos(); + pos = pos.relative(pContext.getClickedFace()); + Player player = pContext.getPlayer(); + if (player == null) return InteractionResult.PASS; + + if (player.isShiftKeyDown()) { + stack.getOrCreateTag().putInt("StartX", pos.getX()); + stack.getOrCreateTag().putInt("StartY", pos.getY()); + stack.getOrCreateTag().putInt("StartZ", pos.getZ()); + return InteractionResult.SUCCESS; + } else { + stack.getOrCreateTag().putInt("TargetX", pos.getX()); + stack.getOrCreateTag().putInt("TargetY", pos.getY()); + stack.getOrCreateTag().putInt("TargetZ", pos.getZ()); + } + + return InteractionResult.SUCCESS; + } + + @Override + public void appendHoverText(ItemStack pStack, @Nullable Level pLevel, List pTooltipComponents, TooltipFlag pIsAdvanced) { + pTooltipComponents.add(Component.literal("Start Pos: [" + pStack.getOrCreateTag().getInt("StartX") + "," + + pStack.getOrCreateTag().getInt("StartY") + "," + pStack.getOrCreateTag().getInt("StartZ") + "]")); + pTooltipComponents.add(Component.literal("Target Pos: [" + pStack.getOrCreateTag().getInt("TargetX") + "," + + pStack.getOrCreateTag().getInt("TargetY") + "," + pStack.getOrCreateTag().getInt("TargetZ") + "]")); + + double[] angles = new double[2]; + boolean flag = RangeHelper.canReachTarget(8.0, 0.05, 0.99, + new BlockPos(pStack.getOrCreateTag().getInt("StartX"), pStack.getOrCreateTag().getInt("StartY"), pStack.getOrCreateTag().getInt("StartZ")), + new BlockPos(pStack.getOrCreateTag().getInt("TargetX"), pStack.getOrCreateTag().getInt("TargetY"), pStack.getOrCreateTag().getInt("TargetZ")), + angles); + + pTooltipComponents.add(Component.literal(flag + " Angles: " + angles[0] + "," + angles[1])); + } +}