Как исправить HTML-элемент холста и его координаты на экранах разных размеров? - PullRequest
0 голосов
/ 31 декабря 2018

Я провел последние две недели, делая игру с несколькими друзьями, используя тег HTML canvas и JavaScript.Ни у кого из нас нет опыта работы с проектами такого масштаба, поэтому мы не думали о совместимости браузера с размером экрана.Игра работает и отлично смотрится на наших ноутбуках (у всех одинаковые размеры экрана), но она выглядела плохо, когда мы отправили ссылку другому другу, размер экрана которого сильно отличается от того, что мы имели в виду.

Для обсуждениямакет игры более подробно, он настроен на элемент canvas, действующий как настоящая игра, с рядом элементов div, расположенных под холстом, для представления таких вещей, как диалоговое окно или меню паузы (только один из этих элементов показан навремя, когда остальные скрыты).

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

Изменение свойств высоты и ширины холста в JavaScript успешно зафиксировало соотношение размера холста и гарантировало, что текстуры стены и пола загружаются в нужном месте.,Плеер и другие NPC, однако, появляются в нечетных местах на экране, иногда вообще не показывая загрузки.

Я не совсем уверен, к чему приписать эту проблему, но я думаю, что это как-то связано сСистема координат canvas не очень хорошо сочетается с заведомо плохо выполненной блочной системой, которую мы установили.

//some relevant misc variables
var numSquares = 30;
const blockWidth = 1132 / numSquares * 0.75;
screen.width = 1132;
screen.height = 600;

//some relevant player variables
stats.x = 678;
stats.y = 600;
stats.width = blockWidth * 3 * 0.37;
stats.height = blockWidth * 3;

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

Есть ли способ настроить нашу игру для мониторов разных размеров?кроме реконструкции всей системы координат?Спасибо заранее.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Ваша основная проблема - использовать жестко закодированные значения для ваших переменных.Если stats.x = 678; и ваш экран имеет ширину 480 пикселей (например), stats выпадет из экрана.

Также: screen.width и screen.height - это жестко закодированное число.Вероятно, вам нужно что-то вроде: screen.width = window.innerWidth и screen.height = window.innerHeight

Чего мне не хватает в ваших соответствующих переменных misc : В вашем коде у вас есть это:

var numSquares = 30;
const blockWidth = 1132 / numSquares * 0.75;  

Где 1132 на самом деле screen.width.Это означает, что у вас нет grid, как вы говорите.Это означает, что у вас есть только 1 (один) ряд квадратов.В качестве альтернативы у вас есть 30 квадратов в строке, и в этом случае у вас есть сетка.

Также было бы неплохо увидеть, как вы рисуете свою сетку.Я бы сделал это так:

for (let y = 0; y < ch; y += cw / numSquares) {
  for (let x = 0; x < cw; x += cw / numSquares) {
    let o = { x: x, y: y, w: blockWidth, h: blockWidth };
    drawRect(o);
  }
}

Где drawRect - это пользовательская функция для рисования прямоугольника.Так как ваш blockWidth = screen.width / numSquares * 0.75; я предполагаю, что вы пропустили разрыв между ритами, но это предполагает.

Как я уже говорил, вы не можете дать stats жестко закодированные значения.Вам нужно будет рассчитать эти значения в зависимости от ваших ячеек сетки.Например, ваш stats.x может быть x 5-го столбца вашей сетки, а stats.y может быть y 3-го ряда.Но это опять-таки предполагает, и я могу ошибаться.

Далее идет пример кода.Пожалуйста, посмотрите и дайте мне знать, если это то, что вам нужно.

const screen = document.getElementById("canvas");
const ctx = screen.getContext("2d");
let cw = (screen.width = window.innerWidth);
let ch = (screen.height = window.innerHeight);

let stats = {};

let numSquares = 30;
let blockWidth;

generateGrid();

function Init() {
  // a function to re-generate the grid and re-draw the stats when screen.width and/or screen.height changed
  cw = screen.width = window.innerWidth;
  ch = screen.height = window.innerHeight;
  
  generateGrid();
  drawStats(5, 3);
}

// recalculate everything on resize
setTimeout(function() {
  Init();
  addEventListener("resize", Init, false);
}, 15);


// some useful functions
function drawRect(o) {
  ctx.beginPath();
  ctx.fillStyle = "rgba(0,0,0,.05)";
  ctx.fillRect(o.x, o.y, o.w, o.h);
}

function drawStats(x, y) {
  stats.x = x * cw / numSquares;
  stats.y = y * cw / numSquares;
  stats.width = blockWidth * 3 * 0.37;
  stats.height = blockWidth * 3;

  ctx.fillStyle = "red";
  ctx.beginPath();
  ctx.fillRect(stats.x, stats.y, stats.width, stats.height);
}

function generateGrid() {
  blockWidth = cw / numSquares * 0.75;
  for (let y = 0; y < ch; y += cw / numSquares) {
    for (let x = 0; x < cw; x += cw / numSquares) {
      let o = { x: x, y: y, w: blockWidth, h: blockWidth };
      drawRect(o);
    }
  }
}
*{margin:0;padding:0}
<canvas id="canvas"></canvas>

Если это не то, что вам нужно, пожалуйста, обновите ваш вопрос, добавьте больше объяснений и больше кода.

0 голосов
/ 31 декабря 2018

попробуйте эту мету, которая решит проблему с кроссплатформенным экраном (ноутбук, компьютер, планшет, мобильный телефон):

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...