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
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
Two things:
.arc
command will only draw the part of the FOV that follows a circle. When youfill
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. Seecontext.lineTo
aftercontext.arc
player.orientation
. 0 means pointing right, and then it spans 2PI clockwise. Indraw
, I subtract/add half the FOV from the orientation to get to the arc’s start and end angle.