如何为带方向速度的抛射体添加重力效果?
Alright, let's break down what's going wrong here and fix your bullet's gravity behavior properly. Your core issue is that your initial update logic doesn't correctly separate the bullet's velocity into world-space components—you’re forcing the bullet to always move along its initial launch angle, which cancels out the effect gravity should have on its trajectory.
Why Your Previous Attempts Failed
Let’s unpack the problems with your two tries:
- First Attempt: You added gravity to
vel.y, but then immediately calculated y-displacement usingMath.sin(this.angle * Math.PI/4) * this.vel.y. This means the gravity-induced change tovel.ynever actually affects the bullet’s movement—you’re still tying y-motion strictly to the initial angle, hence the weird curved path. - Second Attempt: Multiplying gravity by
Math.sin(this.angle * Math.PI/4)makes gravity act along the bullet’s launch direction instead of straight down. Whenthis.angleis 0, that sine value becomes 0, so gravity does nothing—this is why you saw anomalies at that angle. Gravity should always pull along the world’s y-axis, not the bullet’s initial angle.
The Standard Solution for Projectile Motion
The correct way to handle this follows real-world physics principles:
- Decompose initial velocity into x/y components once when the bullet spawns.
- Update the y-velocity each frame by adding gravity (since gravity acts vertically).
- Update position directly using current velocity—no need to re-use the initial angle every frame.
Step 1: Initialize Bullet Velocity Correctly
When creating the bullet, calculate its initial vel.x and vel.y from the launch angle and speed:
// When spawning the bullet: const initialSpeed = this.vel; // Assume this was your original speed magnitude this.vel.x = Math.cos(this.angle * Math.PI/4) * initialSpeed; this.vel.y = Math.sin(this.angle * Math.PI/4) * initialSpeed;
(Note: Adjust the Math.PI/4 scaling if your angle uses a different unit conversion.)
Step 2: Update Position and Velocity Each Frame
In your bullet’s update function, use the current velocity components directly, then apply gravity to the y-axis:
// In the bullet's update loop: this.pos.x += this.vel.x; this.pos.y += this.vel.y; this.vel.y += GRAVITY; // Tip: Use a negative GRAVITY value if your y-axis increases downward (common in game engines), positive if y increases upward
This will give you a natural parabolic trajectory: the x-velocity stays constant (no air resistance), while the y-velocity is continuously pulled by gravity, making the bullet arc downward as expected.
Optional: Extending the Behavior
If you want to add extra physics touches, you can build on this foundation:
- Air Resistance: Multiply
vel.xandvel.yby a drag factor each frame (e.g.,this.vel.x *= 0.99; this.vel.y *= 0.99;) to slow the bullet over time. - Terminal Velocity: Cap the magnitude of
vel.yto a maximum value so the bullet doesn’t accelerate indefinitely.
内容的提问来源于stack exchange,提问作者Kake

