Подтвердить что ты не робот

Пули не выстрелили из пистолета

Я делаю маленькую игру просто для удовольствия, и я застрял, выпуская пули из пистолета. В приведенном ниже коде направление игрока - угол градуса, называемый rot.

Целый код: https://github.com/LegendL3n/Mortal-Kombat

Код:

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));

Также попытался:

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

Но те же результаты

Предположительно, пули должны появляться в конце пистолета, но это не так, как вы можете видеть в следующем gif..

введите описание изображения здесь

Любая помощь оценена

4b9b3361

Ответ 1

Одна большая проблема (по крайней мере, на мой взгляд) заключается в том, как эта игра обрабатывает опорные точки фигур, например, игрока.

Мы можем выделить опорную точку, нарисуя на ней небольшой красный прямоугольник:

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);
    //...

то мы увидим, что опорная точка не находится в центре изображения:

образ с якорной точкой

Как вы можете видеть, опорная точка (исходная (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());

изображение с привязкой к центру

Затем вы теперь стреляете из пистолета, вы увидите, что пуля всегда "начинается" с определенной позиции от игрока. Проблема здесь в том, что неправильное смещение вы использовали. Собственные значения:

float gunOffsetX = 35, gunOffsetY = 29;

(я получил их методом проб и ошибок, поэтому вы можете настроить их немного больше, если хотите)

Теперь это выглядит так:

снято, все еще неуместно

Как вы можете видеть, снимок по-прежнему немного неуместен, но это происходит из-за неправильного вращения пули (например, вы сделали это для формы игрока):

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());

Конечный результат:

выстрел, правильно размещен

Теперь игрок правильно смотрит на перекрестье, и выстрелы помещаются перед пистолетом.


Если вам нравится стрелять прямо через центр перекрестия, вам нужно будет только немного отрегулировать положение игрока и смещение пули.

Игрок (в 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);

(ум -30 в (int)player.getY() - (player.getHeight() / 2) - 30)

Пули:

float gunOffsetX = 35, gunOffsetY = 0;

Теперь пуля перемещается прямо через перекрестие (помните, что красный прямоугольник находится прямо на оружии):

выстрел, пуля через перекрестье

(Я слишком глуп, чтобы создавать правильные GIF файлы, поэтому я могу показывать только фотографии)


Теперь у вас есть необходимые значения смещения, чтобы получить желаемый результат, но вы должны определенно попытаться понять, почему значения такие, как сейчас. Вы должны заменить их более поздними динамическими значениями, так как различное оружие нуждается в разных смещениях для пули, потому что изображение игрока отличается. Должно быть полезно иметь какой-то класс с экземплярами для каждого типа оружия, который содержит изображения и координаты, где находится бочонок оружия на изображении. Затем вы можете использовать эти координаты, чтобы правильно установить смещения для изображения пули.