尝试添加弹道计算
This commit is contained in:
parent
af597faa24
commit
0392af6b03
3 changed files with 171 additions and 1 deletions
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
60
src/main/java/net/mcreator/superbwarfare/item/TestItem.java
Normal file
60
src/main/java/net/mcreator/superbwarfare/item/TestItem.java
Normal 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]));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue