How can I make the canvas be the same for all screen sizes

Question: I have a game, but the way it resizes things is wrong. It stretches them and compresses them to fit in the screen. I want the screen to look something like this:

Screenshot 2023-10-27 8.24.52 AM

Repl link: https://replit.com/@ColoredHue/BulletPartyio#client/script.js

This is what I use to resize the canvas:

canvas.width = document.documentElement.clientWidth;
canvas.height = 9 * canvas.width / 16;
var playersize = canvas.width / 50
var playerspeed = canvas.width / 250

This is what I use to change each player’s position:

x = player.x / player.width * canvas.width
y = player.y / player.height * canvas.height

You need to modify the way you calculate the canvas dimensions and the player positions.

For example:

function resizeCanvas() {
    const aspectRatio = 16 / 9;
    let newWidth = document.documentElement.clientWidth;
    let newHeight = document.documentElement.clientHeight;

    // Check if the current width fits a 16:9 ratio within the current height
    if (newWidth / aspectRatio > newHeight) {
        // If not, adjust the width to fit the height
        newWidth = newHeight * aspectRatio;
    } else {
        // Or, adjust the height to fit the width
        newHeight = newWidth / aspectRatio;
    }

    canvas.width = newWidth;
    canvas.height = newHeight;
    playersize = canvas.width / 50;
    playerspeed = canvas.width / 250;
}

// Call this function to initially set the canvas size and whenever the window is resized
resizeCanvas();
window.addEventListener('resize', resizeCanvas);

And adjust the player position

x = player.x / player.width * canvas.width;
y = player.y / player.height * canvas.height;

Don’t forget to test in different screen sizes

2 Likes

There’s a slight problem with this…

Screenshot 2023-10-28 7.10.52 PM

It squishes/stretches all the objects on the canvas.
Instead of squishing the objects I want them all to be the same size.

Hmmm might be better to implement a viewport system.

At the top of your script.js , define the dimensions of your virtual game world like

const gameWorldWidth = 1600; // This is an example width you can change to what you like
const gameWorldHeight = gameWorldWidth / (16 / 9); // Maintain 16:9 ratio since that''s what you want
var scaleFactor;

Than you update the resize function to calculate the scalefactor:

function resizeCanvas() {
    let newWidth = document.documentElement.clientWidth;
    let newHeight = document.documentElement.clientHeight;

    if (newWidth / gameWorldWidth > newHeight / gameWorldHeight) {
        newWidth = newHeight * (gameWorldWidth / gameWorldHeight);
    } else {
        newHeight = newWidth / (gameWorldWidth / gameWorldHeight);
    }

    canvas.width = newWidth;
    canvas.height = newHeight;
    scaleFactor = newWidth / gameWorldWidth;
}

And modify the drawPlayer function too since we will use scaleFactor

function drawPlayer(player, playerId) {
    // right after your code to set color

    var scaledX = player.x * scaleFactor;
    var scaledY = player.y * scaleFactor;
    var scaledSize = playersize * scaleFactor;

    ctx.fillRect(scaledX, scaledY, scaledSize, scaledSize);
}

And define playersize and playerspeed based on the game world size too

var playersize = gameWorldWidth / 50;
var playerspeed = gameWorldWidth / 250;
1 Like