0
\$\begingroup\$

I'm developing a game using the html5 canvas, but I've never used it before and I'm having difficulty creating a camera. The intention is that it is the same as agar.io, where the player is centered in the middle of screen and only the surrounding field is moved, a 3000x3000 field and the player screen that is rendered is only 25x25. I saw several methods of doing this but I ended up getting very confused with so much information. I prefer the method using Canva's translate, but I'm still having trouble being able to make the render. I'll show you how the code is. It's going to be a multiplayer game.

The logic of the game:

"use strict"

function createGame() {
  const state = {
    players: {},
    fruits: {},
    screen: {
      width: 25,
      height: 25
    }
  }

  function addPlayer({ playerId, playerX, playerY }) {
    state.players[playerId] = {
      x: playerX,
      y: playerY
    };
  }

  function removePlayer({ playerId }) {
    delete state.players[playerId];
  }

  function addFruit({ fruitId, fruitX, fruitY }) {
    state.fruits[fruitId] = {
      x: fruitX,
      y: fruitY
    };
  }

  function removeFruit({ fruitId }) {
    delete state.fruits[fruitId];
  }

  function checkFruitCollision(playerId) {
    const player = state.players[playerId];
    for (const fruitId in state.fruits) {
      const fruit = state.fruits[fruitId];
      if (player.x === fruit.x && player.y === fruit.y) {
        removeFruit({ fruitId });
      }
    }
  }

  function movePlayer(command) {
    const commandsAccepted = {
      ArrowUp: function(player) {
        if (player.y - 1 >= 0) {
          player.y -= 1;
        }
      },
      ArrowDown: function(player) {
        if (player.y + 1 < state.screen.height) {
          player.y += 1;
        }
      },
      ArrowLeft: function(player) {
        if (player.x - 1 >= 0) {
          player.x -= 1;
        }
      },
      ArrowRight: function(player) {
        if (player.x + 1 < state.screen.width) {
          player.x += 1
        }
      }
    }

    const keyPressed = command.key;
    const playerId = command.playerId;
    const player = state.players[playerId];
    const movingPlayer = commandsAccepted[keyPressed]

    if (player && movingPlayer) {
      movingPlayer(player);
      checkFruitCollision(playerId);
    }
  }

  return {
    state,
    movePlayer,
    addPlayer,
    removePlayer,
    addFruit,
    removeFruit
  }
}

export default createGame;

Render logic:

"use strict"

function renderScreen(screen, game, requestAnimationFrame) {
  const ctx = screen.getContext("2d");

  ctx.clearRect(0, 0, screen.width, screen.height);

  for (const playerId in game.state.players) {
    const player = game.state.players[playerId];
    ctx.fillStyle = "#4c7370";
    ctx.fillRect(player.x, player.y, 1, 1);
  }

  for (const fruitId in game.state.fruits) {
    const fruit = game.state.fruits[fruitId];
    ctx.fillStyle = "#90a32a";
    ctx.fillRect(fruit.x, fruit.y, 1, 1);
  }

  requestAnimationFrame(() => renderScreen(screen, game, requestAnimationFrame));
}

export default renderScreen;

```
\$\endgroup\$
6
  • \$\begingroup\$ One thing you could consider doing is keeping the player sprite in the center of the screen, and moving the rest of the map around it. This creates the illusion that the camera and player are moving, when really they remain in place and everything else is moving. \$\endgroup\$ Oct 11, 2023 at 11:15
  • \$\begingroup\$ Sure. But the sprite is only a pixel 1 by 1 and it’s created using x and y of player. I have difficulty creating this illusion cuz my rendering function ends up rendering everything at once, a loop takes all state players and renders at once. \$\endgroup\$
    – Jhon
    Oct 11, 2023 at 12:10
  • 1
    \$\begingroup\$ You wrote that you are "still having trouble being able to make the render". Can you elaborate? What's that trouble? What do you expect to show up on the screen and what shows up instead? Are there any errors in the browsers console that could hint at a runtime error in your code? \$\endgroup\$
    – Philipp
    Oct 11, 2023 at 12:23
  • \$\begingroup\$ The game are working normally. When the game starts, it render the players and the fruits inside this 25x25 canvas. But what I wanted is a functionality similar to that of agar.oi, where there is a field for example 3000x3000 and it renders only that 25x25 area of the player's position. \$\endgroup\$
    – Jhon
    Oct 11, 2023 at 14:59
  • \$\begingroup\$ "I saw several methods of doing this but I ended up getting very confused with so much information" - without more information about what methods you saw or what about them confused you, we're liable to show you more of the same. To help us tailor our answers to something that will be helpful for you, it would help to edit your question to link to a source you're looked at for one method, show the code for how you attempted to apply that method to your game, and call out where you got stuck applying it, or how the behaviour of the code you've written differs from what you want. \$\endgroup\$
    – DMGregory
    Oct 23, 2023 at 15:33

1 Answer 1

0
\$\begingroup\$

screen can be a reference to a canvas of 3000x3000, and a camera a canvas of 25x25.

Player would move around, and be drawn in screen, and camera would copy from screen and be displayed on the page, camera copies the 25x25 region that is around the player. And screen is an offscreencanvas or otherwise not displayed.

\$\endgroup\$
2
  • \$\begingroup\$ I’ve thought about sometimes like it. Did u mean to render everything around player using fillRect by player position + 25 of camera size? \$\endgroup\$
    – Jhon
    Oct 14, 2023 at 21:11
  • \$\begingroup\$ You would render everything first to the 'screen' canvas, a not displayed canvas. And then a displayed 'camera' canvas would copy a 25x25 area of screen, the 25x25 area that is around the player. For example if the player is at 1500x1500 the camera would copy from 1500 - 25/2 by 1500- 25/2. The player walks around in the screen canvas and interactions are done in it, the camera just copies the portion to be displayed. \$\endgroup\$
    – mrall
    Oct 22, 2023 at 21:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .