skip to Main Content

I simulate an interactive view for a player. As long as a component of the game is within the view width, it should be possible to interact with it. With my code, it is not a problem to play the different directions, but only in 180°. Can I limit the view further so that it is a variable number, as you can see here in my sketch?

Blue is the player’s collision area.
Red is the current view width.
Gray is the desired view width.

https://i.imgur.com/cyNYpv3.png

Interact with the canvas in focusing the window and change direction with WASD or arrow keys.

const canvas = document.querySelector('canvas')
const context = canvas.getContext('2d');

canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

const keymap = [];

const player = { 
  x: window.innerWidth / 2 - 50, 
  y: window.innerHeight / 2 - 50,
  size: 100,
  range: 200,
  view: {
    start: 0,
    end: Math.PI
  }
};

const draw = () => {
  context.clearRect(0, 0, canvas.width, canvas.height);
  
  context.fillStyle = 'rgba(0, 0, 255, .6)';
  context.fillRect(
    player.x,
    player.y,
    player.size, 
    player.size, 
  );
  
  context.fillStyle = 'rgba(0, 0, 0, .6)';
  context.beginPath();
  context.arc(
    player.x + player.size / 2, 
    player.y + player.size / 2, 
    player.range, 
    player.view.start, 
    player.view.end, 
    false
  );
  context.fill();
};

const change = () => {
  let tempChange = { x: 0, y: 0 };
  
  keymap.forEach(direction => {
    if (direction === 'KeyS' || direction === 'ArrowDown') {
      tempChange.y = 1;
    }

    if (direction === 'KeyA' || direction === 'ArrowLeft') {
      tempChange.x = -1;
    }

    if (direction === 'KeyW' || direction === 'ArrowUp') {
      tempChange.y = -1;
    }

    if (direction === 'KeyD' || direction === 'ArrowRight') {
      tempChange.x = 1;
    }
  });
  
  const actions = {
    '1_1': () => {
      // Down Right
      player.view.start = 1.75 * Math.PI;
      player.view.end = 0.75 * Math.PI;
    },
    '1_-1': () => {
      // Up Right
      player.view.start = 1.25 * Math.PI;
      player.view.end = 0.25 * Math.PI;
    },
    '1_0': () => {
      // Right
      player.view.start = 1.5 * Math.PI;
      player.view.end = 0.5 * Math.PI;
    },
    '-1_1': () => {
      // Down Left
      player.view.start = 0.25 * Math.PI;
      player.view.end = 1.25 * Math.PI;
    },
    '-1_-1': () => {
      // Up Left
      player.view.start = 0.75 * Math.PI;
      player.view.end = 1.75 * Math.PI;
    },
    '-1_0': () => {
      // Left
      player.view.start = 0.5 * Math.PI;
      player.view.end = 1.5 * Math.PI;
    },
    '0_1': () => {
      // Down
      player.view.start = 0;
      player.view.end = Math.PI;
    },
    '0_-1': () => {
      // Up
      player.view.start = Math.PI;
      player.view.end = 0;
    },
    '0_0': () => {},
  };

  const dir = tempChange.x + '_' + tempChange.y;
  const func = actions[dir];
  func();
};

const loop = () => {
  change();
  draw();
  
  requestAnimationFrame(loop);
};

const setup = () => {
  window.addEventListener('keydown', event => {
    const key = event.code;
    const index = keymap.indexOf(key);

    if (index > -1)
      keymap.splice(index, 1);

    keymap.push(key);
  });

  window.addEventListener('keyup', event => {
    const key = event.code;
    const index = keymap.indexOf(key);

    if (index > -1)
      keymap.splice(index, 1);
  });
};

setup();
requestAnimationFrame(loop);
<canvas></canvas>

2

Answers


  1. It looks like you have the view field declared in radians from 0 to pi (180°) changing that to your desired radians could fix it

    Login or Signup to reply.
  2. Two things:

    • The .arc command will only draw the part of the FOV that follows a circle. When you fill that, it will "connect" the start and end of that path. To make sure your FOV looks like a slice of pie, you have to ensure there’s a point added to the path that goes to the center of the player. See context.lineTo after context.arc
    • It’s easier to manage variable field-of-view if you store just the orientation of the player + the FOV angle. I updated your key-handler to write player.orientation. 0 means pointing right, and then it spans 2PI clockwise. In draw, I subtract/add half the FOV from the orientation to get to the arc’s start and end angle.
    const canvas = document.querySelector('canvas')
    const context = canvas.getContext('2d');
    
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
    
    const keymap = [];
    
    const player = { 
      x: window.innerWidth / 2 - 50, 
      y: window.innerHeight / 2 - 50,
      size: 100,
      range: 200,
      orientation: 0,
      fov: 140 * (Math.PI / 180)
    };
    
    const draw = () => {
      context.clearRect(0, 0, canvas.width, canvas.height);
      
      context.fillStyle = 'rgba(0, 0, 255, .6)';
      context.fillRect(
        player.x,
        player.y,
        player.size, 
        player.size, 
      );
      
      const viewStart = player.orientation - player.fov / 2;
      const viewEnd = player.orientation + player.fov / 2;
      const ax = player.x + player.size / 2;
      const ay = player.y + player.size / 2;
      context.fillStyle = 'rgba(0, 0, 0, .6)';
      context.beginPath();
      context.arc(
        ax, 
        ay, 
        player.range, 
        viewStart, 
        viewEnd,
        false
      );
      
      context.lineTo(ax, ay)
      
      context.fill();
    };
    
    const change = () => {
    
      const tempChange = { x: 0, y: 0 }
      
      keymap.forEach(direction => {
        if (direction === 'KeyS' || direction === 'ArrowDown') {
          tempChange.y = 1;
        }
    
        if (direction === 'KeyA' || direction === 'ArrowLeft') {
          tempChange.x = -1;
        }
    
        if (direction === 'KeyW' || direction === 'ArrowUp') {
          tempChange.y = -1;
        }
    
        if (direction === 'KeyD' || direction === 'ArrowRight') {
          tempChange.x = 1;
        }
      });
      
      // Set orientation
      const { x, y } = tempChange;
      player.turn = (
        x ===  0 && y === -1 ? 0.00 * Math.PI * 2 : // North
        x ===  1 && y === -1 ? 0.25 * Math.PI * 2 : // North-East
        x ===  1 && y ===  0 ? 0.50 * Math.PI * 2 : // East
        x ===  1 && y ===  1 ? 0.75 * Math.PI * 2 : // South-East
        x ===  0 && y ===  1 ? 1.00 * Math.PI * 2 : // South
        x === -1 && y ===  1 ? 1.25 * Math.PI * 2 : // South-West
        x === -1 && y ===  0 ? 1.50 * Math.PI * 2 : // West
        x === -1 && y === -1 ? 1.75 * Math.PI * 2 : // North West
        player.orientation
      );
      
     const actions = {
       '1_0': () => {
          // Right
          player.orientation = 0;
        },
        '1_1': () => {
          // Down Right
          player.orientation = 0.25 * Math.PI;
        },
        '0_1': () => {
          // Down
          player.orientation = 0.5 * Math.PI;
        },
        '-1_1': () => {
          // Down Left
          player.orientation = 0.75 * Math.PI;
        },
        '-1_0': () => {
          // Left
          player.orientation = 1 * Math.PI;
        },
        '-1_-1': () => {
          // Up Left
          player.orientation = 1.25 * Math.PI;
        },
        '0_-1': () => {
          // Up
          player.orientation = 1.5 * Math.PI;
        },
    
        '1_-1': () => {
          // Up Right
          player.orientation = 1.75 * Math.PI;
        },
    
        '0_0': () => {},
      };
    
      const dir = tempChange.x + '_' + tempChange.y;
      const func = actions[dir];
      func();
    };
    
    const loop = () => {
      change();
      draw();
      
      requestAnimationFrame(loop);
    };
    
    const setup = () => {
      window.addEventListener('keydown', event => {
        const key = event.code;
        const index = keymap.indexOf(key);
    
        if (index > -1)
          keymap.splice(index, 1);
    
        keymap.push(key);
        
        event.preventDefault();
      });
    
      window.addEventListener('keyup', event => {
        const key = event.code;
        const index = keymap.indexOf(key);
    
        if (index > -1)
          keymap.splice(index, 1);
      });
    };
    
    setup();
    requestAnimationFrame(loop);
    <canvas></canvas>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search