#javascript #canvas #html5-canvas
Вопрос:
У меня есть следующая функция JS для отображения «игрока» в центре окна просмотра.
//state fires every 60ms
socket.on('state', (gameState) => {
//iterates through gameState players
for (let player in gameState.players) {
//draws each player
renderEnemies(gameState.players[player]);
}
});
function renderEnemies(player) {
const ctx = document.getElementById('gameboard').getContext('2d');
const canvas = document.getElementById('gameboard');
//align player with center of viewport (BROKEN)
ctx.translate(canvas.width/2- player.x, canvas.height/2-player.y);
//colour player red
ctx.fillStyle = "#FF0000";
//add the player to the canvas (gameboard)
ctx.fillRect(player.x, player.y, player.width, player.width);
}
Однако часть перевода функции renderEnemies не работает. Я уже экспериментировал с ctx.clear() и restore, но безрезультатно.
Я был бы признателен, если бы кто-нибудь указал мне правильное направление. Спасибо!
ОБНОВЛЕНИЕ: Я исправил ошибку окна просмотра с помощью приведенного ниже кода, но теперь движение игрока нарушено. Функция рисования теперь выглядит следующим образом:
function renderEnemies(player) {
const ctx = document.getElementById('gameboard').getContext('2d');
const canvas = document.getElementById('gameboard');
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(window.innerWidth/2- player.x, window.innerHeight/2-player.y);
ctx.fillStyle = "#FF0000";
ctx.fillRect(player.x, player.y, player.width, player.width);
ctx.restore();
}
Ответ №1:
Это может быть связано с тем, что вы не сохраняете и не восстанавливаете или, по крайней мере, не переводите обратно после рисования. Как вы можете видеть в приведенном ниже фрагменте, если я переведу, не выполнив ни того, ни другого, враг будет переведен неправильно (в этом примере с холста).
Когда вы отмените комментарий, сохраните И восстановите его правильные позиции. Вы также можете просто перевести его обратно, добавив отрицательные значения после рисования. Поэтому в приведенном ниже фрагменте вы можете закомментировать save()
reastore()
и раскомментировать второе translate
, и вы получите те же результаты.
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 300;
canvas.height = 300;
ctx.fillStyle = "lightgrey";
ctx.fillRect(0, 0, canvas.width, canvas.height);
class Enemy {
constructor(x, y) {
this.x = x;
this.y = y;
this.w = 20;
this.h = 20;
this.c = "blue";
}
draw() {
ctx.save();
ctx.translate(canvas.width / 2 - this.w/2, canvas.height / 2 - this.h/2);
//colour player red
ctx.fillStyle = "#FF0000";
//add the player to the canvas (gameboard)
ctx.fillRect(this.x, this.y, this.w, this.h);
ctx.restore();
//ctx.translate(-(canvas.width / 2 - this.w/2), -(canvas.height / 2 - this.h/2)); //or use this
}
}
let enemy1 = new Enemy(0, 0);
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "grey";
ctx.fillRect(0, 0, canvas.width, canvas.height);
enemy1.draw();
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas"></canvas>
Без всего вашего кода я не знаю, что еще это может быть.
Обновить:
Знание основ того, что translate()
вы делаете, поможет вам понять, что происходит, когда вы что-то переводите. Не просто думайте о переводе, когда холст перемещает этот объект, но думайте об этом так, как будто этот объект находится на собственном листе холста, и весь этот лист перемещается. Вот почему, если вы поворачиваете элемент, он поворачивается не от центра, а в (0,0) положении холста. Подумайте об этом таким образом: когда вы вводите значения в translate , вы указываете ему, где вы хотите, чтобы левый верхний угол этого листа холста был для этого конкретного элемента.
На изображении выше сплошной черный цвет-это холст. Если я переведу красный квадрат ctx.translate(canvas.width/2, canvas.height/2)
, то вы увидите, что на самом деле я перевожу лист холста, изображенный серой каймой. Верхний левый угол этого холста центрирован на холсте, но поскольку квадрат нарисован на (0,0), будет казаться, что квадрат не центрирован, но немного вправо и вниз. Кроме того, если бы я дал объекту красного квадрата координату x (холст.ширина/2, 0), вы могли бы увидеть, что произойдет, изображенное квадратом красной границы.
Теперь на следующем изображении, если бы я действительно хотел центрировать красный квадрат, мне нужно было бы учитывать половину ширины и высоты. Я могу сделать это в двух местах. Если я вычитаю его в методе перевода ctx.translate(canvas.width/2 - block.width/2, canvas.height/2 - block.height/2)
, он будет центрироваться, но это также удерживает квадраты (0,0) в соответствии с холстом (0,0). Это нормально до тех пор, пока вы не захотите повернуть красный квадрат из центра.
На рисунке выше я установил вычитание координат красных квадратов вместо (0 - this.width/2, 0 - this.height/2)
этого, это помещает (0,0) холста в центр красного квадрата. Поскольку вращение происходит от (0,0) полотна, этот красный квадрат, если его повернуть, будет вращаться от центра.
Учитывая все сказанное, если вы применяете координаты x и y к своему объекту и пытаетесь перевести одинаковое количество, у вас будут ошибки, такие как первый красный контур изображения. Другими словами, не делайте этого (если вы этого не хотите).
ctx.translate(100, 100)
ctx.fillRect(100, 100, 50, 50)
это переведет его на 100 в каждую сторону, а затем объект будет иметь дополнительные 100 в каждом направлении. Кроме того, вам, вероятно, не нужно использовать clearRect внутри функции сохранения(). Обычно это вызывается при обновлении в начале цикла анимации, чтобы очистить холст перед перерисовкой.
Комментарии:
1. Спасибо! Я вроде как исправил это с помощью window.innerWidth и высоты, но теперь возникли проблемы с движением. Я знаю, что прошу многого, но не могли бы вы взглянуть на мое редактирование вопроса с обновленным кодом и попытаться понять, почему движение не работает? Я бы предположил, что это как-то связано с моими ctx.save() и ctx.restore()
2. Я обновил свой комментарий, чтобы попытаться внести некоторую ясность
translate
. Кроме того, если это нарушило ваше движение, мне интересно, настроено ли у вас обнаружение столкновений на холсте, и, возможно, поскольку переводы неверны, оно все время сталкивается.