2D 宇宙飞船的速度上限
就像其他学习编程语言的人一样,我给自己设计了一个太空飞船游戏项目。到目前为止,我已经有了视差星以及我期望从宇宙飞船游戏中获得的所有美好事物。飞船停留在游戏屏幕的中央,可以 360 度旋转,可以推进和滑行,通常表现得像外太空中的物体一样。然而,我在限制船速方面遇到了一个小问题。
飞船有一个 dx 和 dy 值(它通过我的 update() 函数转换为星星,因此它们进行实际的移动),并且它根据它所面对的角度在 x 或 y 轴上施加推力。我给船设定了最大速度(假设为 5)和加速度(每帧 0.1)。当推进时,船会像我预期的那样加速。推进器始终处于 100%,没有油门控制,因为我使用的是数字输入设备(箭头键)。我检查由船舶当前 dx 和 dy 形成的三角形的斜边以确定其当前速度,并跟踪其行进角度(用于以后的 AI;武器开火;当我按下向下箭头时,船舶使用这个值来知道它需要旋转到什么角度才能面对与当前轨迹相反的方向——一种帮助你正确制动的自动驾驶仪)。
船舶具有这些变量,这些变量会在必要时更新(这是一个缩写列表,因为其余内容不直接相关):
x_speed
y_speed
speed
move_angle // Used to track direction of motion
face_angle // Used to determine x_accel and y_accel when thrusting
x_accel
y_accel
accel = 0.1 // Used to determine x_accel and y_accel by multiplying by the dx and dy returned by getDxDy(face_angle)
max_x
max_y
max_speed = 5 // Used to determine max_x and max_y by multiplying by the dx and dy returned by getDxDy(face_angle)
我使用此函数根据face_angle检查我的 dx 和 dy 加速度:
function getDxDy(degree)
{
var dx;
var dy;
var degree = degree;
dx = -Math.sin(degToRad(degree));
dy = Math.cos(degToRad(degree));
var dxdy = {
dx: dx,
dy: dy
};
return dxdy;
}
我更新速度每帧加速都像这样:
x_speed += x_accel
y_speed += y_accel
我尝试过使用多种不同类型的检查来限制速度,并且我尝试过这个:
if (x_speed > max_x)
{
x_speed = max_x
}
并且我尝试过这个:
if (x_speed > max_x)
{
x_speed -= x_accel
}
第一个版本根据需要限制了速度,但是我要么完全无法修改我进一步加速,或者当我尝试通过面向相反方向并推力来反转航向时,我的速度立即跳至相反方向的 max_speed (因为 max_speed 是根据船舶当前的 face_angle 不断计算的)。如果我将该计算更改为 move_angle,那么当船启动且不移动时,我会遇到问题。
如果我碰巧在速度回到阈值以下之前停止推力,第二个版本就会出现问题;我转身并推力,相反,我的推力是负的,这使我在行进的方向上加速得更远,与我面对的方向完全相反。
我理想的情况是能够将任何方向的推力限制在某个值(例如 5),当我改变方向几度时,船在几秒钟后就会朝那个方向行驶。推力,当我掉头推力时,我希望船能像人们预期的那样减速。
如果有人玩过逃逸速度游戏,这就是我正在努力实现的运动和控制系统——如果你愿意的话,可以说是我的“黄金标准”。
在 http://adrian.thomas-prestemon.com/ 查看我当前可以正常工作的代码game/v3/
处理此问题的具体 .js 文件可以在 http://adrian.thomas-prestemon.com/game/v3/js/ships.js。请原谅注释掉的代码和其他东西的混乱。我已经花了一周的时间来解决整个问题的这个特定部分。
我已经检查了在线提供的多个其他解决方案,与我的设计最相似的解决方案使用我上面提供的第一个“if”示例,这对我不起作用。我也查看了以下 StackOverflow 问答:
所有这些解决方案看起来都非常棒,但对于我的目的来说,它们似乎都有点复杂。我不打算实现任何类型的重力系统,如第一个示例中所示,另外两个虽然相关,但似乎没有为我的具体问题提供任何立即使用的东西。
任何人都可以提供的任何基本伪代码和/或其他类型的帮助 - 例如直接向我指出可以回答我的问题的其他内容,我可能错过了 - 将不胜感激。我正在寻找适合我当前设置的解决方案,但我绝对愿意对我的船舶运动代码的功能进行一些更改,如果它能让 max_speed 检查更容易。
感谢您花时间阅读所有这些内容。 :)
更新:
我对我的代码做了一些修改,并且它比以前工作得更好。它并不完美,但需要进行更多的实验、调整和调试。 :)
So like just about everyone else learning some programming language, I've given myself a spaceship game project. So far, I have parallax stars and all the nice things I expect from a spaceship game. The ship stays in the center of the game screen, can rotate 360 degrees, can thrust and coast, and generally behave properly like an object in outer space. I am having a small issue, however, with capping the ship's speed.
The ship has a dx and dy value (which it translates to the stars through my update() function, so they do the actual moving), and it applies thrust on either the x or y axis, based on the angle it is facing. I give the ship a max speed (let's say 5) and an acceleration (0.1 per frame). When thrusting, the ship accelerates as I expect it to. The thrusters are always on 100%, no throttle control, since I'm using a digital input device (arrow key). I check the hypotenuse of the triangle made by the ship's current dx and dy to determine its current velocity, and I track its angle of travel, as well (for use in later AI; weapons fire; and when I press the down arrow, the ship uses this value to know what angle it needs to rotate to in order to face opposite its current trajectory -- a sort of help-you-brake-properly autopilot).
The ship has these variables which are updated whenever necessary (this is an abbreviated list, since the rest of the stuff isn't directly relevant):
x_speed
y_speed
speed
move_angle // Used to track direction of motion
face_angle // Used to determine x_accel and y_accel when thrusting
x_accel
y_accel
accel = 0.1 // Used to determine x_accel and y_accel by multiplying by the dx and dy returned by getDxDy(face_angle)
max_x
max_y
max_speed = 5 // Used to determine max_x and max_y by multiplying by the dx and dy returned by getDxDy(face_angle)
I check my dx and dy for acceleration based on the face_angle using this function:
function getDxDy(degree)
{
var dx;
var dy;
var degree = degree;
dx = -Math.sin(degToRad(degree));
dy = Math.cos(degToRad(degree));
var dxdy = {
dx: dx,
dy: dy
};
return dxdy;
}
I update the speed every frame of acceleration like so:
x_speed += x_accel
y_speed += y_accel
I have tried capping the speed with multiple different types of checks, and I have tried this:
if (x_speed > max_x)
{
x_speed = max_x
}
and I have tried this:
if (x_speed > max_x)
{
x_speed -= x_accel
}
The first version caps the speed as desired, but then I am either completely unable to modify my acceleration further, or when I try to reverse course by facing the opposite direction and thrusting, my speed instantly jumps to the opposite direction's max_speed (since the max_speed is constantly calculated based on the ship's current face_angle). If I change that calculation to the move_angle, then I run into problems when the ship is starting out, and not moving.
The second version has an issue if I happen to stop thrusting before it gets the speed back below the threshold; I about-face and thrust, and instead, my thrust is negative, which causes me to accelerate farther in the direction I'm travelling, exactly opposite to the direction I'm facing.
What I would ideally like is to be able to cap the thrust at some value (5 for example) in any direction, and when I change directions by a few degrees, for the ship to wind up going in that direction after a few seconds of thrust, and when I about-face and thrust, I would like the ship to decelerate as one would expect.
If anyone's ever played the game Escape Velocity, that's the kind of movement and control system I'm working towards -- sort of my "Gold Standard," if you will.
Check out my current somewhat-working code at http://adrian.thomas-prestemon.com/game/v3/
The specific .js file dealing with this can be found at http://adrian.thomas-prestemon.com/game/v3/js/ships.js. Please excuse the mess of commented-out code and stuff. I've been working on this particular bit of the overall problem for a week now.
I have already examined multiple other solutions available online, and the ones most similar to my design use the first "if" example I provided above, which doesn't work for me. I have looked at the following StackOverflow Q&As as well:
2d trajectory planning of a spaceship with physics
Programming a smooth change of thrust from current velocity vector to a target vector
All of these solutions seem quite fantastic, but they all seem a little complicated for my purposes. I do not plan on implementing any kind of gravity system, as in the first example, and the other two, while related, don't seem to provide anything of immediate use to my specific problem.
Any basic pseudocode and/or other kind of help anyone can provide -- such as pointing me directly to something else that answers my question, which I may have missed -- would be greatly appreciated. I'm looking for solutions that work with my current setup, but I am absolutely willing to change a little bit of how my ship's movement code functions if it will make this max_speed checking easier.
Thank you for taking the time to read all of this. :)
UPDATE:
I have made some modifications to my code and I got it working much better than it once did. It's not perfect, but some more experimentation, tweaking, and debugging is all it should take. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
将
dx
、dy
、x_speed
和y_speed
值初始化为 0,并让x_speed< /code> 和
y_speed
值决定移动角度,而不是保持move_angle
分开。或者,如果我误解了您的设置,只需将
speed
设置为 0 开始,并在速度值低于某个截止值时进行不涉及三角学的计算。或者,您可以让大部分速度和加速度计算在极坐标值上进行,并在需要显示到屏幕上时转换为笛卡尔坐标。
抱歉,如果我语无伦次,这对我来说是一天中的低潮期,我宁愿现在小睡也不愿坐在办公桌前。
Initialize your
dx
,dy
,x_speed
, andy_speed
values to 0, and have thex_speed
andy_speed
values determine the move angle rather than keepingmove_angle
separate.Or, if I've misunderstood your setup, just start off with
speed
set to 0, and do calculations that don't involve trigonometry when the speed value is below a certain cutoff.Or you could have most of the velocity and acceleration calculations operate on polar values and just convert to Cartesian coordinates when it's time to display to the screen.
Sorry if I'm semi-incoherent, it's the slump-time of the day for me and I'd rather be taking a nap right now than sitting at a desk.