仅用角度(非弧度整数运算)实现Minecraft对象绕轨需求
Got it, let's work through this orbital motion problem for Minecraft—those constraints are tricky but totally solvable with some fixed-point math and angle wrapping! Here's how I'd approach it, tailored exactly to your limitations:
Since we can't use floats/doubles and all values get rounded to integers, we'll use fixed-point scaling (multiplying all decimals by a large factor like 1000 to store them as integers) and keep our angles clamped to the -180° to 180° range required by your sin/cos functions.
Step 1: Define Your Orbital Parameters (As Scaled Integers)
First, set up all your orbital values as scaled integers (I'll use a scale factor of 1000 here, matching your 0.017 → 17 example):
#radius_scaled: Your desired orbit radius multiplied by 1000 (e.g., 5.2 blocks → 5200)#angle: Current orbit angle (starts at 0, updates each tick)#angle_step: How much to increment the angle each tick (e.g., 1 for 1° per tick, or 2 for 2° if you want a faster orbit)#full_circle: Pre-set to 360 (for angle wrapping)#scale_factor: Pre-set to 1000 (to reverse our scaling later)
You can set these up using Minecraft's scoreboard system:
# Initialize parameters scoreboard objectives add orbital_vars dummy scoreboard players set #radius_scaled orbital_vars 5200 scoreboard players set #angle orbital_vars 0 scoreboard players set #angle_step orbital_vars 1 scoreboard players set #full_circle orbital_vars 360 scoreboard players set #scale_factor orbital_vars 1000
Step 2: Wrap Angles to Stay Within -180° to 180°
Every time you update your angle, you need to make sure it never goes outside the valid range for your sin/cos functions. Here's how to clamp it:
# Update the angle each tick scoreboard players add #angle orbital_vars #angle_step # Wrap angles over 180° down to negative values execute if score #angle orbital_vars matches 181.. run scoreboard players operation #angle orbital_vars -= #full_circle orbital_vars # Wrap angles under -180° up to positive values execute if score #angle orbital_vars matches ..-181 run scoreboard players operation #angle orbital_vars += #full_circle orbital_vars
Step 3: Calculate Orbital Offsets (Fixed-Point Math)
Now use sin/cos to calculate your X/Z/Y offsets. Since your sin/cos returns scaled integers (e.g., sin(90°) = 1 → 1000), multiply by your scaled radius, then divide by the scale factor to get the final integer offset:
# Get scaled sin/cos values for the current angle execute store result score #sin_val orbital_vars run math sin(#angle) execute store result score #cos_val orbital_vars run math cos(#angle) # Calculate X and Z offsets (for a Y-axis orbit—adjust axes for other planes) scoreboard players operation #dx orbital_vars = #sin_val orbital_vars * #radius_scaled orbital_vars scoreboard players operation #dx orbital_vars /= #scale_factor orbital_vars scoreboard players operation #dz orbital_vars = #cos_val orbital_vars * #radius_scaled orbital_vars scoreboard players operation #dz orbital_vars /= #scale_factor orbital_vars
Step 4: Apply the Offset to Your Orbiting Object
Finally, grab the center object's coordinates (scaled to integers), add your offsets, and set the orbiting object's position:
# Get center object's scaled coordinates (multiply by 1000 to keep precision) execute as @e[type=armor_stand,tag=center] store result score #center_x orbital_vars run data get entity @s Pos[0] 1000 execute as @e[type=armor_stand,tag=center] store result score #center_y orbital_vars run data get entity @s Pos[1] 1000 execute as @e[type=armor_stand,tag=center] store result score #center_z orbital_vars run data get entity @s Pos[2] 1000 # Calculate target coordinates for the orbiter scoreboard players operation #target_x orbital_vars = #center_x orbital_vars + #dx orbital_vars scoreboard players operation #target_y orbital_vars = #center_y orbital_vars # Keep Y same, or add a scaled offset here scoreboard players operation #target_z orbital_vars = #center_z orbital_vars + #dz orbital_vars # Set the orbiter's position (divide by 1000 to convert back to Minecraft's coordinate system) execute as @e[type=armor_stand,tag=orbiter] store result entity @s Pos[0] double 0.001 run scoreboard players get #target_x orbital_vars execute as @e[type=armor_stand,tag=orbiter] store result entity @s Pos[1] double 0.001 run scoreboard players get #target_y orbital_vars execute as @e[type=armor_stand,tag=orbiter] store result entity @s Pos[2] double 0.001 run scoreboard players get #target_z orbital_vars
Quick Optimizations & Adjustments
- Slower/Faster Orbits: If you want a slower orbit (e.g., 0.5° per tick), scale your angle by 2—store
#angleas actual angle * 2, increment by 1 each tick, then divide by 2 before passing to sin/cos. - Different Orbital Planes: To orbit around X or Z instead of Y, swap which axis uses sin/cos (e.g., for X-axis orbits, use sin for Y offset and cos for Z offset).
- Higher Precision: If 1000x scaling isn't enough, use 10000x—just make sure your scoreboard values don't overflow (Minecraft supports integers up to ~2 billion, so 10000x is safe for most orbit sizes).
内容的提问来源于stack exchange,提问作者James

