子弹没有从枪中射出

L3n*_*L3n 13 java math game-physics

我正在制作一个只是为了好玩的小游戏而且我被困住使子弹从枪中出来.在下面的代码中,玩家的方向是一个称为角度的角度rot.

代码:

float gunOffsetX = 106, gunOffsetY = 96;
double angle = Math.toRadians(rot); // convert direction of player from degrees to radians for sin and cos
x = getX(); // player X
y = getY(); // player Y

float bulletX = (float) (x + (gunOffsetX * Math.cos(angle) - gunOffsetY * Math.sin(angle)));
float bulletY = (float) (y + (gunOffsetX * Math.sin(angle) + gunOffsetY * Math.cos(angle)));

Instances.fire.add(new Fire(bulletX, bulletY, rot, weapon));
Run Code Online (Sandbox Code Playgroud)

还尝试过:

bulletX = (float) (x + Math.cos(angle + Math.atan2(106, 96)) * Point2D.distance(0, 0, 106, 96));
Run Code Online (Sandbox Code Playgroud)

但结果相同

据说子弹应该在枪的末端产生,但事实并非如此,你可以在下面的gif中看到.

在此输入图像描述

任何帮助赞赏

Tom*_*Tom 12

一个大问题(至少在我看来)是这个游戏如何处理形状的锚点,如玩家.

我们可以通过在其位置绘制一个小红色矩形来突出显示锚点:

g.setColor(Color.RED);
g.drawRect((int)player.getX() -5, (int)player.getY() -5, 10, 10);
Run Code Online (Sandbox Code Playgroud)

这进入了Draw#renderGame(Graphics2D)方法,所以它看起来像:

private void renderGame(Graphics2D g) {
    g.rotate(Math.toRadians(player.rot), player.getX()+64, player.getY()+64);
    g.drawImage(player.getCurrentFrame(), (int)player.getX(), (int)player.getY(), player.getWidth(), player.getHeight(), null);
    g.setColor(Color.RED);
    g.drawRect((int)player.getX() -5, (int)player.getY() -5, 10, 10);
    g.rotate(-Math.toRadians(player.rot), player.getX()+64, player.getY()+64);
    //...
Run Code Online (Sandbox Code Playgroud)

然后我们会看到锚点不在图像的中心:

带锚点的图像

如您所见,锚点(旋转前的原始(0,0)点)不在图像的中心,十字准线与其相关,而不是与播放器的视图相关.

这是因为玩家轮换时的移动操作:

g.rotate(Math.toRadians(player.rot), player.getX()+64, player.getY()+64);
//...
g.rotate(-Math.toRadians(player.rot), player.getX()+64, player.getY()+64);
Run Code Online (Sandbox Code Playgroud)

你正在改变这个位置+64.我建议删除它并将转移添加到g.drawImage调用中,因此锚点正确位于中心(请注意我避免使用固定值64):

g.rotate(Math.toRadians(player.rot), player.getX(), player.getY());
g.drawImage(player.getCurrentFrame(), (int)player.getX() - (player.getWidth() / 2), (int)player.getY() - (player.getHeight() / 2), player.getWidth(), player.getHeight(), null);
g.rotate(-Math.toRadians(player.rot), player.getX(), player.getY());
Run Code Online (Sandbox Code Playgroud)

中心锚的图像

然后你现在开枪,你会发现子弹总是从玩家的某个位置"开始".这里的问题是您使用的偏移量不正确.适当的值是:

float gunOffsetX = 35, gunOffsetY = 29;
Run Code Online (Sandbox Code Playgroud)

(我通过反复试验得到它们,所以你可以调整一下,如果你愿意的话)

现在它看起来像这样:

枪击,仍然放错了地方

正如你所看到的,镜头仍然有点放错位置,但这是由于子弹旋转不正确(就像你为玩家形状做的那样):

g.rotate(Math.toRadians(f.rot), f.getX()+f.getWidth()/2, f.getY()+f.getHeight()/2);
g.drawImage(f.img, (int)f.getX(), (int)f.getY(), f.getWidth(), f.getHeight(), null);
g.rotate(-Math.toRadians(f.rot), f.getX()+f.getWidth()/2, f.getY()+f.getHeight()/2);
Run Code Online (Sandbox Code Playgroud)

它看起来应该是这样的(没有任何XY调整):

g.rotate(Math.toRadians(f.rot), f.getX(), f.getY());
g.drawImage(f.img, (int)f.getX(), (int)f.getY(), f.getWidth(), f.getHeight(), null);
g.rotate(-Math.toRadians(f.rot), f.getX(), f.getY());
Run Code Online (Sandbox Code Playgroud)

最终结果是:

射击射击,正确放置

现在,玩家正确地看着十字准线,并将镜头放在枪口前面.


如果你想直接穿过十字准线的中心,你只需要调整玩家位置和子弹偏移量.

球员(上Draw#renderGame(Graphics2D)):

g.drawImage(player.getCurrentFrame(), (int)player.getX() - (player.getWidth() / 2), (int)player.getY() - (player.getHeight() / 2) - 30, player.getWidth(), player.getHeight(), null);
Run Code Online (Sandbox Code Playgroud)

(介意-30(int)player.getY() - (player.getHeight() / 2) - 30)

子弹:

float gunOffsetX = 35, gunOffsetY = 0;
Run Code Online (Sandbox Code Playgroud)

现在子弹穿过十字准线(注意红色矩形正好在武器上):

射击射击,子弹穿过十字准线

(我创建合适的GIF文件有点太愚蠢,所以我只能提供图片)


现在你有了必要的偏移值来获得你想要的结果,但是你一定要试着理解为什么它们就像现在这样.您需要稍后用动态值替换它们,因为不同的武器需要不同的子弹偏移,因为玩家图像不同.为每种武器类型设置一些具有实例的类应该是有帮助的,其中包含图像和武器桶在图像中的坐标.然后,您可以使用这些坐标正确设置项目符号图像的偏移量.