2015-11-04 3 views
2

Я пытаюсь масштабировать игру в холсте динамически на основе экранов. Я понимаю, как изменить размер холста на основе экранов, но я хочу также изменить размер содержимого. В принципе, я хочу, чтобы игра выглядела одинаково на каждом устройстве. проблема у меня в настоящее время заключается в том, что когда люди с 4k экраном играют в игру, они могут легко увидеть всю карту. И когда у кого-то действительно маленький экран, они почти ничего не видят. Есть ли простой и эффективный способ сделать это? Я попытался сделать следующее:Правильное масштабирование игры на холсте Javascript

var maxWidth = 1920; 
var maxHeight = 1080; 

... 

function resize() { 
    c.width = screenWidth = window.innerWidth; 
    c.height = screenHeight = window.innerHeight; 
    widthToHeight = screenWidth/screenHeight; // ASPECT RATIO 

    var scalerAmnt = (maxWidth + maxHeight) 
      /(screenWidth + screenHeight); 
    context.scale(scalerAmnt, scalerAmnt); 
} 

Если я масштабировать холст, как это, он нежелателен результаты. Он выходит из центра и слишком велик. Как вы можете видеть, я установил максимальную ширину и высоту. В основном я стараюсь, чтобы игра выглядела одинаково на каждом устройстве, как на машине с этим разрешением.

ЖИВОЙ DEMO: www.vertix.io

UPDATE: Вот изображение того, что она в настоящее время выглядит следующим образом: enter image description here

+0

Вы можете добавить скриншот? –

+0

Я добавил ссылку на демонстрационную версию. Таким образом, вы можете видеть, когда вы перемасштабируете. Или вам нужен скриншот другой попытки? – TastyLemons

ответ

5

Вы будете сталкиваться с некоторыми проблемами.

Диски с высоким разрешением покажут размытие, если вы не установили ctx.imageSmoothingEnabled = false, а дисплеи с низким разрешением покажут эффекты сглаживания, если вы не установили ctx.imageSmoothingEnabled = true.

Лучше всего не допускать максимального разрешения. Это произвольно, и мой вариант - использовать разрешение экрана, которое большинство людей использует. Пример Screen stats Есть много сайтов, которые предоставляют эту информацию. Выберите тот, который ближе всего сообщает вашу демографическую цель.

Для дисплеев большего размера, не увеличивающих разрешение, просто увеличьте размер элемента DOM.

canvas.width и canvas.height установить размер холста. canvas.style.width и canvas.style.height установить разрешение.

Для дисплеев с более низким разрешением уменьшите разрешение холста, чтобы соответствовать разрешению экрана. Нет смысла указывать дополнительные пиксели устройства, которые не будут отображаться. Я лично переопределяю все графики, чтобы исправить res для более низких отображений res при загрузке изображений. Опять же, это означает, что устройство не может отображать больше пикселей, чем необходимо (мобильным устройствам не удается справиться много), а также, поскольку метод сглаживания оставляет желать лучшего (а именно, это совершенно неправильно). Посмотрите это видео, чтобы объяснить, почему Computer colour is broken

Будьте осторожны с уменьшением разрешения. если у вас есть изображение 100by100 пикселей и вам нужно уменьшить его до 93by93, он не будет выглядеть хорошо. Внимательно выбирайте размеры графических элементов для каждого элемента рендеринга, чтобы обеспечить наилучшее возможное сокращение до наиболее распространенного набора разрешений, которые вы будете отображать.

Также разрешите некоторое пространство для маневра в размере поля игры, они не все должны быть точно такого же размера.

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

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

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

var nativeWidth = 1024; // the resolution the games is designed to look best in 
var nativeHeight = 768; 

// the resolution of the device that is being used to play 
var deviceWidth = window.innerWidth; // please check for browser compatibility 
var deviceHeight = window.innerHeight; 

У вас есть два варианта масштабирования. Масштаб по размеру или масштаб для заполнения.

// A: This will ensure that the scale fills the device but will crop 
// some of the top and bottom, or left and right of the play field. 
// use the max scale. 
var scaleFillNative = Math.max(deviceWidth/nativeWidth, deviceHeight/nativeHeight); 

// B: this will ensure that all screens will see all of the native playscreen size 
// but some displays will have extra playfield on the sides or top and bottom. 
// use the min scale 
var scaleFitNative = Math.min(deviceWidth/nativeWidth, deviceHeight/nativeHeight); 

Установите разрешение и размер холста до

canvas.style.width = deviceWidth + "px"; 
canvas.style.height = deviceHeight + "px"; 
canvas.width = deviceWidth; 
canvas.height = deviceHeight; 

Теперь вам нужно установить масштаб Rendering

// ctx is the canvas 2d context 
ctx.setTransform(
    scaleFitNative,0, // or use scaleFillNative 
    0,scaleFitNative, 
    Math.floor(deviceWidth/2), 
    Math.floor(deviceHeight/2) 
); 

Это установил центр экрана в качестве начала координат.

UPDATE

Существовал ошибка в моем оригинальный ответ.

Чтобы получить смещение к родной Рез левом верхнем углу находится

var offSetToNativeTop = -nativeHeight/2; // incorrect 
var offSetToNativeleft = -nativeWidth/2; // incorrect 

ДОЛЖНА БЫТЬ ...

var offSetToNativeTop = (-nativeHeight/2)*scaleFitNative; // correct 
var offSetToNativeleft = (-nativeWidth/2)*scaleFitNative; // correct 

или

var offSetToNativeTop = (-nativeHeight/2)*scaleFillNative; // correct 
var offSetToNativeleft = (-nativeWidth/2)*scaleFillNative; // correct 

Извините за возможные неудобства вызвало.

Чтобы получить смещение к началу устройства влево

var offsetDeviceTop = -(deviceHeight/scaleFitNative)/2; 
var offsetDeviceLeft = -(deviceWidth/scaleFitNative)/2; 

, чтобы получить устройство Playfield размер дисплея

var deviceDisplayWidth = deviceWidth/scaleFitNative; 
var deviceDisplayHeight = deviceHeight/scaleFitNative; 

Не забывайте сглаживанием.

if(scaleFitNative < 1){ 
    ctx.imageSmoothingEnabled = true; // turn it on for low res screens 
}else{ 
    ctx.imageSmoothingEnabled = false; // turn it off for high res screens. 
} 

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

Это должно дать вам все, что вам нужно сделать графику для всех устройств

+0

Удивительный ответ! Большое спасибо. – TastyLemons

+0

По какой-то причине холст не центрирован. Он находится в левом нижнем углу экрана. Масштабирование работает отлично, но положение холста неверно. – TastyLemons

+1

@TastyLemons Хорошо, я проверю ошибки. Будь то час. – Blindman67

0

После попытки реализовать метод по Blindman67, я нашел более быстрый и короткий путь для достижения этого же результата, используя CSS вместо рисования каждого изображения по-другому с измененной функцией drawImage().

Вот простой способ, пожалуйста, скажите мне, если я упускаю из виду что-то, что касается вышеописанного метода, хотя я считаю, что все проблемы решаются.

-> Учитывая холст, определенный как:

canvas 

что составляет брезентовый элемент на странице HTML.

Нужные родные разрешения для масштабирования (см ответ Blindman67 прояснить ситуацию, если это необходимо) определяется как:

resW, resH 

размеры устройств определяются как:

devW, devH 
//Noting that these values usually correspond to window.innerWidth, window.innerHeight, respectively. 

(1) Для шкалы наполняя экран, обрезание избытка сделайте так:

let f = Math.max(window.innerWidth/resW, window.innerHeight/resH); 
//f is the factor by which we redefine our canvas size as show in the code in the following lines: 
//Change the canvas elements 'direct' width and height properties 
canvas.width = Math.floor(devW/f); 
canvas.height = Math.floor(devH/f); 
//Change the canvas elements 'css' width and height properties to fill 
// the entire page. 
canvas.style.width = '100%'; 
canvas.style.height = '100%'; 

(2) Для установки холста c ontent на экране, это гораздо проще просто:

Set:

//Changing the 'css' canvas width size, making sure the width is always fitting. 
canvas.style.width = '100%'; 

Тогда:

//Making the direct canvas width and height the desired native resolution's size 
canvas.width = resW; 
canvas.height = resH; 

Теперь CSS автоматически заботится о масштабировании вместо того, чтобы полагаться на комплексной функции DrawImage в ,

Хотя для игры (преобладающей функции для холста) масштаб для заполнения может быть более желательным из-за пространства, которое появится на экране, если пользователь изменит размер своего окна. С другой стороны, если вы используете шкалу для заполнения, игрок может получить более захватывающий вид, без пробела или когда нет масштабирования, и проблема, когда возникают другие игроки с более крупными экранами.

Я понимаю, что это было очень поздно, но после того, как вы искали месяцы, чтобы решение было менее сложным, я, наконец, понял это. Поэтому для других, кому это может понадобиться для справки, я хотел бы оставить здесь этот ответ.

спасибо, что прочитал.