我认为,这个游戏存在一个很大的问题,就是它如何处理形状的锚点,例如玩家。
我们可以通过在锚点位置上绘制一个小红色矩形来突出显示锚点:
g.setColor(Color.RED);
g.drawRect((int)player.getX() -5, (int)player.getY() -5, 10, 10);
这段代码出现在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);
然后我们会发现锚点不在图像的中心:
![带有锚点的图片](https://istack.dev59.com/Ik1Xa.webp)
如您所见,锚点(旋转前的原始(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);
你正在使用 +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());
![带有居中锚点的图像](https://istack.dev59.com/KtDQ7.webp)
如果你现在开枪,你会发现子弹总是从玩家的某个位置“开始”。问题在于你使用了错误的偏移量。正确的值为:
float gunOffsetX = 35, gunOffsetY = 29
(我通过试错得到了它们,所以如果需要,您可以进一步调整它们)
现在它看起来像这样:
![shot fired, still misplaced](https://istack.dev59.com/ph9OG.webp)
正如您所看到的,子弹还是有点偏离目标,但这是由于子弹旋转不正确造成的(就像您对玩家形状所做的那样):
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);
它应该看起来像这样(没有任何X或Y的调整):
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());
最终结果是:
![正确射击](https://istack.dev59.com/45xNX.webp)
现在玩家的准心正确对准了,子弹会落在枪口前面。
如果你想直接通过准心中心开火,你只需要微调一下玩家位置和子弹偏移量。
玩家(在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);
(请注意在 (int)player.getY() - (player.getHeight() / 2) - 30
中的 -30
)
子弹:
float gunOffsetX = 35, gunOffsetY = 0
现在子弹穿过了准心(请注意红色矩形正好在武器上方):
![shot fired, bullet through crosshair](https://istack.dev59.com/I4GBa.webp)
(我不太会制作合适的GIF文件,所以只能提供图片)
现在你有必要的偏移值来得到想要的结果,但你应该尝试理解为什么这些值现在是这样。之后你需要用动态值替换它们,因为不同的武器需要不同的子弹偏移量,由于玩家图像不同。拥有一些包含每种武器类型实例的类将非常有帮助,其中包含图像和武器枪管位于图像中的坐标。然后你可以使用这些坐标来正确地设置子弹图像的偏移量。
106
和96
设为常量吗? - wake-00.5 * w
?)2)你是否意味着在这里将gunOffsetX添加到Math.sin()中(y + (gunOffsetX * Math.sin(angle)
? - Ashwin Gupta