简体   繁体   English

C#中的小行星游戏运动

[英]Asteroids Game Movement In C#

I am trying to make the game Asteroids. 我正在尝试制作游戏小行星。 My issue I have right now, is if you press the UP Arrow key, it will move the "ship" 10 pixels up. 我现在的问题是,如果按下向上箭头键,它会将“船”向上移动10个像素。 And if you hit the LEFT Arrow key, it will turn the "ship" 5 degrees to the left, the issue I have comes into play when you turn left, or right. 如果你按下LEFT箭头键,它会将“船”向左转5度,当你向左转或向右转时我就会发挥作用。 And then try to move up. 然后尝试向上移动。 It won't move into the turned direction. 它不会进入转向的方向。 It will just move the turned "ship" 10 degrees in the Y direction. 它只会将转向的“船”向Y方向移动10度。

What I am thinking of doing is having a variable called direction, think of this variable as a circle with 360 degrees. 我想要做的是使用一个名为direction的变量,将此变量视为360度的圆。 What I am trying to do is everytime I hit the Left Arrow, it will subtract 5 from direction, which started at 0 and goes backwards from 360 and thus set it to 355. I would then divide 355 by 10 and get 35.5. 我想要做的是每当我点击左箭头时,它将从方向减去5,从0开始并从360向后减去因此将其设置为355.然后我将355除以10得到35.5。 Then I would divide 10 by 35.5 and get .355. 然后我将10除以35.5得到.355。 I would then subtract .355 from 10 (moving up in the Y). 然后我会从10减去.355(在Y中向上移动)。 And subtract it from 0 (moving left in the X). 并从0减去它(在X中向左移动)。 So I would be moving 9.645 up in the Y and moving 0.355 left in the X. 因此,我将在Y中移动9.645并在X中移动0.355。

The issue I'm having is the "ship" in Asteroids I have is a Graphics.FillPie, which needs Ints to use as the Start Angle and Sweep angle, However as you can see I would have to be working with doubles or floats. 我遇到的问题是我所拥有的Asteroids中的“船”是一个Graphics.FillPie,需要使用Int作为起始角度和扫描角度,但是你可以看到我必须使用双打或浮点数。 I'm pretty sure I'm overcomplicating this and am pretty sure there is something 100 times simpler, I'm thinking something along the lines of Bresenham's Line Algorithm. 我很确定我过于复杂,我很确定有一些简单的东西,我正在思考Bresenham的线算法。 If anyone could help by suggesting something easier or a fix to my problem, it would be much appreciated. 如果有人可以通过建议更容易或修复我的问题来提供帮助,那将非常感激。 Thanks in advance. 提前致谢。

It sounds like you need to calculate heading vectors for the ship based on the its current orientation in radians. 听起来您需要根据其当前的弧度方向计算船舶的航向矢量。 For example: 例如:

double xVector = Math.Sin(orientationInRadians);
double yVector = Math.Cos(orientationInRadians);

Then use the left and right arrows to control the ship's current orientation. 然后使用左右箭头控制船舶的当前方向。 Once you have the vector you can calculate the location of the ship that is 10 units away from its current position along the heading vector. 获得矢量后,您可以计算船舶的位置,该位置与航向矢量的当前位置相距10个单位。 First you need to scale the vector to a unit (length of 1) vector. 首先,您需要将矢量缩放到单位(长度为1)的矢量。

double magnitude = sqrt(xVector*xVector + yVector*yVector);
double unitVectorX = xVector/magnitude;
double unitVectorY = yVector/magnitude;

Now you have a vector that is 1 unit long but still points in the ship's current orientation. 现在你有一个长度为1个单位但仍指向船舶当前方向的矢量。 Next move the ship with positionX and positionY as current its coordinates. 接下来将船舶的positionX和positionY作为其当前坐标。

double distanceToTravel = 10;
double newPositionX = positionX + unitVectorX*distanceToTravel;
double newPositionY = positionY + unitVectorY*distanceToTravel;

You'll want to track the ship's position and orientation with doubles or floats even if you end up rendering with a system that only allows ints. 即使您最终使用仅允许整数的系统进行渲染,您也希望使用双精度或浮点数来跟踪船舶的位置和方向。 You shouldn't store the current position and orientation using the rendering engine's precision or you will start to see strange jumps and pauses as you move and rotate. 您不应使用渲染引擎的精度存储当前位置和方向,否则您将在移动和旋转时开始看到奇怪的跳跃和暂停。 Also, using the above you can make distanceToTravel non-constant (imagine accelerating while the key is pressed instead of moving a fixed distance from a key press). 此外,使用上述方法可以使distanceToTravel非常量(假设在按下按键时加速,而不是从按键移动固定距离)。

You're over thinking it. 你在想它。 ;> Just use matrix transforms to rotate and move the ship. ;>只需使用矩阵变换来旋转和移动船只。 When the ship is pointed "northwest" and the user pushes the UP key, you adjust the ship's translation matrix by 10 units in the ship's Y axis. 当船舶指向“西北”并且用户按下向上键时,您可以在船舶的Y轴上将船舶的平移矩阵调整10个单位。 You apply the rotation and translation matrixes to convert the ship's coordinate system to the screen coordinate system. 您应用旋转和平移矩阵将船舶的坐标系转换为屏幕坐标系。 Order of operations is critical - if you apply translation before rotation, the ship will go swinging around a center point instead of rotating around the ships origin and then translating to its new "forward" direction. 操作顺序至关重要 - 如果您在旋转前应用平移,船舶将围绕中心点摆动而不是围绕船舶原点旋转,然后转换到新的“向前”方向。

Since you can use the same matrix transforms for drawing, you can just draw the ship in the same fixed orientation (nose pointing "up" the positive Y axis) relative to its local coordinate system. 由于您可以使用相同的矩阵变换进行绘制,因此您可以相对于其局部坐标系以相同的固定方向(鼻子指向“正Y轴”)绘制船舶。 The rotation of the image will be taken care of by the matrix transform. 通过矩阵变换来处理图像的旋转。

I don't want to take your fun away, but you can always download someone else's code and look at it to figure out how to do it in your own. 我不想带走你的乐趣,但你总是可以下载其他人的代码并查看它以找出如何在你自己的代码中完成它。 You can get one implementation here: http://www.c-sharpcorner.com/UploadFile/dannaboneheart/Asteroids11292005064500AM/Asteroids.aspx 您可以在此处获得一个实现: http//www.c-sharpcorner.com/UploadFile/dannaboneheart/Asteroids11292005064500AM/Asteroids.aspx

ans here: http://www.codeproject.com/KB/game/hucsharpasteroids.aspx ans这里: http//www.codeproject.com/KB/game/hucsharpasteroids.aspx

There is no problem using floats internally and converting them to ints when you need to use them that way: 在内部使用浮点数并在需要以这种方式使用它们时将它们转换为整数是没有问题的:

double angle = ...;
int angleAsInt = (int)Math.Round(angle);

I suggest you look into using trigonometric functions like sin and cos for determining the X and Y components of velocities and accelerations. 我建议你研究使用像sincos这样的三角函数来确定速度和加速度的X和Y分量。

One thing you haven't yet mentioned is that in the Asteroids(R) brand arcade machine and video games derived therefrom, the player's ship has inertia. 你还没有提到的一件事是,在Asteroids(R)品牌街机和由此衍生的视频游戏中,玩家的船具有惯性。 Consequently, you need to keep track of the ship's velocity. 因此,您需要跟踪船舶的速度。 Each frame you should do something like: 你应该做的每一帧都是这样的:

if (thrusting)
{
  XVelocity += (XVelocity - Math.Cos(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT);
  YVelocity += (YVelocity - Math.Sin(Heading)*MAX_SPEED) * (1/INERTIA_CONSTANT);
}
else
{
  XVelocity -= XVelocity * (1/FRICTION_CONSTANT);
  YVelocity -= YVelocity * (1/FRICTION_CONSTANT);
}

XPosition += XVelocity; // Do twice--once before and once after speed adjust
YPosition += YVelocity;

Note that some games simply add to the velocity some constant times the cosine/sine. 请注意,有些游戏只是将速度添加到余弦值/正弦值的常数。 Doing that will have the unfortunate consequence that if a player points his ship in some direction and starts thrusting continuously, the distance traversed by the ship each frame may grow to absurd limits. 这样做将产生令人遗憾的结果,即如果玩家将他的船指向某个方向并开始连续推进,则每架船所经过的距离可能会增长到荒谬的极限。 The code as shown will cause the acceleration to diminish as the ship's velocity asymptotically approaches the maximum. 当船舶的速度渐近接近最大值时,所示的代码将导致加速度减小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM