let canvas, ctx;
let squares;
const color = {
grey: '#aaa',
black: '#000',
red: '#f00'
};
const squareSize = 10;
const camera = {};
const mode = {
NORMAL: 'NORMAL',
EXCLUDE_OFF_CAMERA: 'EXCLUDE_OFF_CAMERA',
}
let currentMode;
let mainSquare;
let mainSquareSpeed;
const interval = 1000 / 30;
const KEY_LEFT = 37;
const KEY_RIGHT = 39;
const KEY_UP = 38;
const KEY_DOWN = 40;
let keyUpPressede;
let keyDownPressed;
let keyLeftPressed;
let keyRightPressed;
init();
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
camera.width = camera.height = 70;
camera.x = (canvas.width - camera.width) / 2;
camera.y = (canvas.height - camera.height) / 2;
currentMode = mode.EXCLUDE_OFF_CAMERA;
keyUpPressed = false;
keyDownPressed = false;
keyLeftPressed = false;
keyRightPressed = false;
squares = createSquares(canvas, 20);
mainSquare = squares[0];
mainSquare.x = canvas.width / 2;
mainSquare.y = canvas.height / 2;
mainSquare.color = color.red;
mainSquareSpeed = 3;
window.addEventListener("keydown", onKeyDown, false);
window.addEventListener("keyup", onKeyUp, false);
document.getElementById("modeNormal").onclick = function() {
currentMode = mode.NORMAL;
}
document.getElementById("modeExcludeOffCamera").onclick = function() {
currentMode = mode.EXCLUDE_OFF_CAMERA;
}
document.getElementById("cameraSize").addEventListener("change", function(e) {
camera.width = camera.height = parseInt(e.currentTarget.value, 10);
camera.x = (canvas.width - camera.width) / 2;
camera.y = (canvas.height - camera.height) / 2;
}, false);
// requestAnim shim layer by Paul Irish
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback, /* DOMElement */ element){
window.setTimeout(callback, 1000 / 10);
};
})();
step(canvas, ctx, camera, squares, mainSquare, squareSize, mainSquareSpeed);
}
function step(canvas, ctx, camera, squares, mainSquare, squareSize, squareSpeed) {
requestAnimFrame(function() {
step(canvas, ctx, camera, squares, mainSquare, squareSize, squareSpeed);
});
update(canvas, mainSquare, squareSize, squareSpeed);
clear(canvas, ctx);
draw(canvas, ctx, camera, squares, squareSize);
}
function update(canvas, mainSquare, squareSize, squareSpeed) {
if (keyLeftPressed) {
mainSquare.x -= squareSpeed;
} else if (keyRightPressed) {
mainSquare.x += squareSpeed;
}
if (keyUpPressed) {
mainSquare.y -= squareSpeed;
} else if (keyDownPressed) {
mainSquare.y += squareSpeed;
}
if (mainSquare.x < 0) {
mainSquare.x = canvas.width - squareSize;
} else if (mainSquare.x > canvas.width - squareSize) {
mainSquare.x = 0;
}
if (mainSquare.y < 0) {
mainSquare.y = canvas.height - squareSize;
} else if (mainSquare.y > canvas.height - squareSize) {
mainSquare.y = 0;
}
}
function clear(canvas, ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function draw(canvas, ctx, camera, squares, size) {
drawSquares(ctx, squares, size, camera);
drawCamera(canvas, ctx, camera);
}
function drawSquares(ctx, squares, size, camera) {
for (let i = squares.length - 1; i >= 0; i -= 1) {
if (inViewRange(squares[i], camera, size) || currentMode === mode.NORMAL) {
drawSquare(ctx, squares[i], size);
}
}
}
function drawSquare(ctx, square, size) {
ctx.fillStyle = square.color ? square.color : color.grey;
ctx.strokeStyle = color.black;
ctx.fillRect(square.x, square.y, size, size);
ctx.strokeRect(square.x, square.y, size, size);
}
function drawCamera(canvas, ctx, camera) {
ctx.fillStyle = color.black;
ctx.strokeStyle = color.red;
ctx.lineWidth = 3;
ctx.globalAlpha = 0.3;
ctx.fillRect(camera.x, camera.y, camera.width, camera.height);
ctx.globalAlpha = 1;
ctx.strokeRect(camera.x, camera.y, camera.width, camera.height);
}
/**
* Found here: https://stackoverflow.com/questions/1527803/generating-random-whole-numbers-in-javascript-in-a-specific-range
*
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function createSquares(canvas, number) {
const squares = [];
for (let i = 0; i < number; i += 1) {
squares.push({
x: getRandomInt(0, canvas.width),
y: getRandomInt(0, canvas.height)
});
}
return squares;
}
function inViewRange(square, camera, squareSize) {
if (square.x + squareSize > camera.x && camera.x + camera.width > square.x) {
if (square.y + squareSize > camera.y && camera.y + camera.height > square.y) {
return true;
}
}
return false;
}
function onKeyDown(e) {
switch (e.keyCode) {
case KEY_LEFT: keyLeftPressed = true; break;
case KEY_RIGHT: keyRightPressed = true; break;
case KEY_UP: keyUpPressed = true; break;
case KEY_DOWN: keyDownPressed = true; break;l
}
}
function onKeyUp(e) {
switch (e.keyCode) {
case KEY_LEFT: keyLeftPressed = false; break;
case KEY_RIGHT: keyRightPressed = false; break;
case KEY_UP: keyUpPressed = false; break;
case KEY_DOWN: keyDownPressed = false; break;
}
}
canvas {
border: 1px solid black;
margin: 1px;
}
<canvas id="canvas" width=100 height=100></canvas>
<br>
<button id="modeNormal">modeNormal</button>
<button id="modeExcludeOffCamera">modeExcludeOffCamera</button>
Camera size: <input id="cameraSize" type="range" min="10" max="100" value="70">