尝试添加弹道计算

This commit is contained in:
17146 2024-11-11 16:32:48 +08:00
parent af597faa24
commit 0392af6b03
3 changed files with 171 additions and 1 deletions

View file

@ -1,7 +1,16 @@
package net.mcreator.superbwarfare.client.gui; package net.mcreator.superbwarfare.client.gui;
import net.minecraft.core.BlockPos;
public class RangeHelper { public class RangeHelper {
// 发射角度以度为单位需要根据实际情况修改
public static final int MAX_RANGE = 512;
/**
* 计算迫击炮理论水平射程
*
* @param thetaDegrees 发射角度以度为单位需要根据实际情况修改
*/
public static double getRange(double thetaDegrees) { public static double getRange(double thetaDegrees) {
double initialVelocity = 8.0; // 初始速度 8 m/s double initialVelocity = 8.0; // 初始速度 8 m/s
double thetaRadians = Math.toRadians(thetaDegrees); // 将角度转换为弧度 double thetaRadians = Math.toRadians(thetaDegrees); // 将角度转换为弧度
@ -38,4 +47,103 @@ public class RangeHelper {
// 返回最终水平距离 // 返回最终水平距离
return x; 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;
}
} }

View file

@ -110,6 +110,8 @@ public class ModItems {
*/ */
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ModUtils.MODID); public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ModUtils.MODID);
public static final RegistryObject<Item> TEST_ITEM = ITEMS.register("test_item", TestItem::new);
public static final RegistryObject<Item> SENPAI_SPAWN_EGG = ITEMS.register("senpai_spawn_egg", () -> new ForgeSpawnEggItem(ModEntities.SENPAI, -11584987, -14014413, new Item.Properties())); public static final RegistryObject<Item> SENPAI_SPAWN_EGG = ITEMS.register("senpai_spawn_egg", () -> new ForgeSpawnEggItem(ModEntities.SENPAI, -11584987, -14014413, new Item.Properties()));
public static final RegistryObject<Item> ANCIENT_CPU = ITEMS.register("ancient_cpu", () -> new Item(new Item.Properties().rarity(Rarity.RARE))); public static final RegistryObject<Item> ANCIENT_CPU = ITEMS.register("ancient_cpu", () -> new Item(new Item.Properties().rarity(Rarity.RARE)));
public static final RegistryObject<Item> PROPELLER = ITEMS.register("propeller", () -> new Item(new Item.Properties())); public static final RegistryObject<Item> PROPELLER = ITEMS.register("propeller", () -> new Item(new Item.Properties()));

View file

@ -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<Component> 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]));
}
}