skip to Main Content

am trying to achieve something like this

desired result

but i always endup tiles are not rendering when reaching to boundries , it should be drawing 200×200 map how ever it only show 17×17

the game am building is similer in idea to travian kingdoms but whole different story and design

here is the code

const canvas = document.getElementById('mapCanvas');
const ctx = canvas.getContext('2d');

const tileWidth = 128; // Tile width
const tileHeight = 64; // Tile height
const gridSize = 1000; // Large grid size for 1,000,000 tiles (1000x1000)
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let offsetX = canvas.width / 2; // Start with center offset
let offsetY = canvas.height / 2; // Start with center offset
let isDragging = false;
let startX, startY;

// Test data for tiles using colors
const testData = [
  '#76b041', // Grass
  '#557a29', // Forest
  '#c2b280', // Plain
  '#a4a4a4', // Mountain
];

function drawTile(x, y, screenX, screenY, color) {
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.moveTo(screenX, screenY);
  ctx.lineTo(screenX + tileWidth / 2, screenY + tileHeight / 2);
  ctx.lineTo(screenX, screenY + tileHeight);
  ctx.lineTo(screenX - tileWidth / 2, screenY + tileHeight / 2);
  ctx.closePath();
  ctx.fill();
  ctx.strokeStyle = '#000'; // Optional: add border to each tile
  ctx.stroke();

  // Draw the coordinates on the tile
  ctx.fillStyle = '#000';
  ctx.font = '14px Arial';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(`(${x}, ${y})`, screenX, screenY + tileHeight / 2);
}

function loadMap() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas

  // Calculate how many tiles we need to draw to cover the screen
  const tilesX = Math.ceil(canvas.width / tileWidth) + 2;
  const tilesY = Math.ceil(canvas.height / tileHeight) + 2;

  for (let x = -tilesX; x <= tilesX; x++) {
    for (let y = -tilesY; y <= tilesY; y++) {
      // Convert grid coordinates to screen coordinates
      const screenX = (x - y) * (tileWidth / 2) + offsetX;
      const screenY = (x + y) * (tileHeight / 2) + offsetY;

      // Draw the tile
      const tileColor = testData[(x + y + gridSize) % testData.length];
      drawTile(x, y, screenX, screenY, tileColor);
    }
  }
}

canvas.addEventListener('mousedown', onMouseDown);
canvas.addEventListener('mousemove', onMouseMove);
canvas.addEventListener('mouseup', onMouseUp);

function onMouseDown(e) {
  isDragging = true;
  startX = e.clientX;
  startY = e.clientY;
}

function onMouseMove(e) {
  if (!isDragging) return;

  const dx = e.clientX - startX;
  const dy = e.clientY - startY;

  offsetX += dx;
  offsetY += dy;

  startX = e.clientX;
  startY = e.clientY;

  loadMap(); // Redraw the map based on the new position
}

function onMouseUp() {
  isDragging = false;
}

// Initial load
loadMap();

// Handle window resizing
window.addEventListener('resize', () => {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  loadMap();
});
body {
  margin: 0;
  overflow: hidden;
}

canvas {
  display: block;
  background-color: #e0e0e0;
}
<canvas id="mapCanvas"></canvas>

current result

your help is appreciated thank you in advance

i tried every possible solution with no hope

2

Answers


  1. An optimized drawing of the whole map:

    function loadMap() {
        ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
    
        for (let x = -200; x <= 200; x++) {
            for (let y = -200; y <= 200; y++) {
                // Convert grid coordinates to screen coordinates
                const screenX = (x - y) * (tileWidth / 2) + offsetX;
                const screenY = (x + y) * (tileHeight / 2) + offsetY;
                if (screenX >= -tileWidth && screenX < canvas.width &&
                    screenY >= -tileHeight && screenY < canvas.height) {
                    // Draw the tile
                    const tileColor = testData[(x + y + gridSize) % testData.length];
                    drawTile(x, y, screenX, screenY, tileColor);
                }
            }
        }
    }
    
    Login or Signup to reply.
  2. The number of tiles to draw should not be computed.

    Also, don’t render the tiles that are not visible. This will improve performance.

    In the code below, I chose a fixed number of tiles to draw i.e. 64×64, but you could change this to 200×200. I chose a smaller number for demonstration.

    const tilesX = 32, tilesY = 32; // Number of tiles to draw
    
    // Check to see if the tile would be visible in the viewport
    function isDrawable(x, y, width, height) {
      return x > -width  &&
             x < ctx.canvas.width + width &&
             y > -height &&
             y < ctx.canvas.height + height
    }
    
    function drawTile(x, y, screenX, screenY, color) {
      // Skip the drawing of the tile, if not visible
      if (!isDrawable(screenX, screenY, tileWidth, tileHeight)) return;
      
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.moveTo(screenX, screenY);
      ctx.lineTo(screenX + tileWidth / 2, screenY + tileHeight / 2);
      ctx.lineTo(screenX, screenY + tileHeight);
      ctx.lineTo(screenX - tileWidth / 2, screenY + tileHeight / 2);
      ctx.closePath();
      ctx.fill();
      ctx.strokeStyle = '#000'; // Optional: add border to each tile
      ctx.stroke();
    
      // Draw the coordinates on the tile
      ctx.fillStyle = '#000';
      ctx.font = '8px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(`(${x}, ${y})`, screenX, screenY + tileHeight / 2);
    }
    

    Demo

    const canvas = document.getElementById('mapCanvas');
    const ctx = canvas.getContext('2d');
    
    const tilesX = 32, tilesY = 32; // Number of tiles to draw
    
    const tileWidth = 64; // Tile width
    const tileHeight = 32; // Tile height
    const gridSize = 1000; // Large grid size for 1,000,000 tiles (1000x1000)
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    
    let offsetX = canvas.width / 2; // Start with center offset
    let offsetY = canvas.height / 2; // Start with center offset
    let isDragging = false;
    let startX, startY;
    
    // Test data for tiles using colors
    const testData = [
      '#76b041', // Grass
      '#557a29', // Forest
      '#c2b280', // Plain
      '#a4a4a4', // Mountain
    ];
    
    // Check to see if the tile would be visible in the viewport
    function isDrawable(x, y, width, height) {
      return x > -width  &&
             x < ctx.canvas.width + width &&
             y > -height &&
             y < ctx.canvas.height + height
    }
    
    function drawTile(x, y, screenX, screenY, color) {
      // Skip the drawing of the tile, if not visible
      if (!isDrawable(screenX, screenY, tileWidth, tileHeight)) return;
      
      ctx.fillStyle = color;
      ctx.beginPath();
      ctx.moveTo(screenX, screenY);
      ctx.lineTo(screenX + tileWidth / 2, screenY + tileHeight / 2);
      ctx.lineTo(screenX, screenY + tileHeight);
      ctx.lineTo(screenX - tileWidth / 2, screenY + tileHeight / 2);
      ctx.closePath();
      ctx.fill();
      ctx.strokeStyle = '#000'; // Optional: add border to each tile
      ctx.stroke();
    
      // Draw the coordinates on the tile
      ctx.fillStyle = '#000';
      ctx.font = '8px Arial';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(`(${x}, ${y})`, screenX, screenY + tileHeight / 2);
    }
    
    function loadMap() {
      ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
    
      for (let x = -tilesX; x <= tilesX; x++) {
        for (let y = -tilesY; y <= tilesY; y++) {
          // Convert grid coordinates to screen coordinates
          const screenX = (x - y) * (tileWidth / 2) + offsetX;
          const screenY = (x + y) * (tileHeight / 2) + offsetY;
          
          // Draw the tile
          const tileColor = testData[(x + y + gridSize) % testData.length];
          drawTile(x, y, screenX, screenY, tileColor);
        }
      }
    }
    
    canvas.addEventListener('mousedown', onMouseDown);
    canvas.addEventListener('mousemove', onMouseMove);
    canvas.addEventListener('mouseup', onMouseUp);
    
    function onMouseDown(e) {
      isDragging = true;
      startX = e.clientX;
      startY = e.clientY;
    }
    
    function onMouseMove(e) {
      if (!isDragging) return;
    
      const dx = e.clientX - startX;
      const dy = e.clientY - startY;
    
      offsetX += dx;
      offsetY += dy;
    
      startX = e.clientX;
      startY = e.clientY;
    
      loadMap(); // Redraw the map based on the new position
    }
    
    function onMouseUp() {
      isDragging = false;
    }
    
    // Initial load
    loadMap();
    
    // Handle window resizing
    window.addEventListener('resize', () => {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      loadMap();
    });
    body {
      margin: 0;
      overflow: hidden;
    }
    
    canvas {
      display: block;
      background-color: #e0e0e0;
    }
    <canvas id="mapCanvas"></canvas>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search